From 050835b535d5307f218c996aadd387e9c67bd50a Mon Sep 17 00:00:00 2001 From: sfb Date: Tue, 16 Oct 2012 12:05:23 -0500 Subject: [PATCH] merging gsoc2012-achievements --HG-- branch : gsoc2012-achievements --- .../georges_plugin_sound/PageBgFades.cpp | 460 +- .../georges_plugin_sound/PageBgFades.h | 138 +- .../georges_plugin_sound/PageBgFlags.cpp | 868 +- .../georges_plugin_sound/PageBgFlags.h | 170 +- .../georges_plugin_sound/PageComplex.cpp | 338 +- .../georges_plugin_sound/PageComplex.h | 148 +- .../georges_plugin_sound/PageComtext.cpp | 210 +- .../georges_plugin_sound/PageComtext.h | 146 +- .../georges_plugin_sound/PagePosition.cpp | 268 +- .../georges_plugin_sound/PagePosition.h | 154 +- .../georges_plugin_sound/PageSimple.cpp | 270 +- .../georges_plugin_sound/PageSimple.h | 150 +- .../georges_plugin_sound.cpp | 126 +- .../georges_plugin_sound.h | 50 +- .../georges_plugin_sound/listener_view.cpp | 630 +- .../georges_plugin_sound/listener_view.h | 226 +- .../georges_plugin_sound/loading_dialog.cpp | 108 +- .../georges_plugin_sound/loading_dialog.h | 124 +- .../georges_plugin_sound/resource.h | 590 +- .../georges_plugin_sound/sound_dialog.cpp | 1148 +- .../georges_plugin_sound/sound_dialog.h | 288 +- .../sound_document_plugin.cpp | 378 +- .../sound_document_plugin.h | 122 +- .../georges_plugin_sound/sound_plugin.cpp | 1320 +-- .../georges_plugin_sound/sound_plugin.h | 312 +- .../georges_plugin_sound/std_sound_plugin.h | 58 +- .../georges_plugin_test/Resource.h | 78 +- .../georges_plugin_test/StdAfx.cpp | 48 +- .../leveldesign/georges_plugin_test/StdAfx.h | 116 +- .../georges_plugin_test.cpp | 506 +- .../georges_plugin_test/georges_plugin_test.h | 192 +- .../test_global_dialog.cpp | 116 +- .../georges_plugin_test/test_global_dialog.h | 126 +- .../georges_plugin_test/test_local_dialog.cpp | 168 +- .../georges_plugin_test/test_local_dialog.h | 130 +- .../leveldesign/icon_search/icon_search.cpp | 784 +- .../tools/leveldesign/install/history.txt | 514 +- .../install/world_editor_script.xml | 38 +- .../tools/leveldesign/master/ChooseDir.cpp | 236 +- .../tools/leveldesign/master/ChooseDir.h | 146 +- .../tools/leveldesign/master/ChooseTag.cpp | 280 +- .../tools/leveldesign/master/ChooseTag.h | 142 +- .../tools/leveldesign/master/ContinentCfg.cpp | 144 +- .../tools/leveldesign/master/ContinentCfg.h | 96 +- .../master/ContinentPropertiesDlg.cpp | 730 +- .../master/ContinentPropertiesDlg.h | 136 +- .../tools/leveldesign/master/ExportCBDlg.cpp | 366 +- .../tools/leveldesign/master/ExportCBDlg.h | 212 +- .../tools/leveldesign/master/ExportDlg.cpp | 522 +- .../tools/leveldesign/master/ExportDlg.h | 178 +- .../tools/leveldesign/master/MainFrm.cpp | 3870 +++---- code/ryzom/tools/leveldesign/master/MainFrm.h | 572 +- .../tools/leveldesign/master/MasterTree.cpp | 1996 ++-- .../tools/leveldesign/master/MasterTree.h | 364 +- .../tools/leveldesign/master/NameEditDlg.cpp | 158 +- .../tools/leveldesign/master/NameEditDlg.h | 124 +- .../ryzom/tools/leveldesign/master/ReadMe.txt | 194 +- .../ryzom/tools/leveldesign/master/StdAfx.cpp | 48 +- code/ryzom/tools/leveldesign/master/StdAfx.h | 98 +- .../tools/leveldesign/master/easy_cfg.cpp | 316 +- .../ryzom/tools/leveldesign/master/easy_cfg.h | 114 +- .../ryzom/tools/leveldesign/master/master.cpp | 338 +- code/ryzom/tools/leveldesign/master/master.h | 132 +- .../ryzom/tools/leveldesign/master/resource.h | 216 +- .../mission_compiler_fe/AddPathDlg.cpp | 106 +- .../mission_compiler_fe/AddPathDlg.h | 124 +- .../mission_compiler_fe/CompilDialog.cpp | 118 +- .../mission_compiler_fe/CompilDialog.h | 128 +- .../mission_compiler_fe/Resource.h | 138 +- .../mission_compiler_fe/StdAfx.cpp | 48 +- .../leveldesign/mission_compiler_fe/StdAfx.h | 108 +- .../mission_compiler_fe/dialog_mode.cpp | 138 +- .../mission_compiler_fe/dialog_mode.h | 132 +- .../mission_compiler_fe.cpp | 336 +- .../mission_compiler_fe/mission_compiler_fe.h | 130 +- .../mission_compiler_feDlg.cpp | 2056 ++-- .../mission_compiler_feDlg.h | 336 +- .../leveldesign/mission_compiler_lib/main.cpp | 540 +- .../mission_compiler_lib/mission_compiler.cpp | 4540 ++++---- .../mission_compiler_lib/mission_compiler.h | 1094 +- .../leveldesign/mission_compiler_lib/step.h | 534 +- .../mission_compiler_lib/step_content.cpp | 6932 ++++++------ .../mission_compiler_lib/steps.cpp | 2804 ++--- .../mission_compiler_lib/variables.cpp | 1414 +-- .../tools/leveldesign/mp_generator/main.cpp | 3162 +++--- .../leveldesign/mp_generator/moulinette.h | 306 +- .../tools/leveldesign/mp_generator/utils.h | 658 +- .../named_items_2_csv/named_items_2_csv.cpp | 1124 +- .../tools/leveldesign/prim_export/main.cpp | 2312 ++-- .../primitive_id_assignator.cpp | 314 +- .../tools/leveldesign/uni_conv/uni_conv.cpp | 266 +- .../leveldesign/variable_parser/ReadMe.txt | 176 +- .../leveldesign/variable_parser/StdAfx.cpp | 48 +- .../leveldesign/variable_parser/StdAfx.h | 88 +- .../variable_parser/lua_helper.cpp | 1452 +-- .../leveldesign/variable_parser/lua_helper.h | 748 +- .../variable_parser/lua_helper_inline.h | 844 +- .../leveldesign/variable_parser/resource.h | 98 +- .../variable_parser/variable_parser.cpp | 184 +- .../variable_parser/variable_parser.h | 130 +- .../variable_parser/variable_parserDlg.cpp | 1000 +- .../variable_parser/variable_parserDlg.h | 202 +- .../world_editor/land_export/main.cpp | 612 +- .../world_editor/land_export_lib/export.cpp | 5798 +++++----- .../world_editor/land_export_lib/export.h | 444 +- .../leveldesign/world_editor/ligoscape.txt | 84 +- .../world_editor/world_editor/action.cpp | 5802 +++++----- .../world_editor/world_editor/action.h | 1464 +-- .../world_editor/builder_logic.cpp | 3042 ++--- .../world_editor/world_editor/builder_logic.h | 274 +- .../world_editor/builder_zone.cpp | 3500 +++--- .../world_editor/world_editor/builder_zone.h | 450 +- .../world_editor/builder_zone_region.cpp | 4186 +++---- .../world_editor/builder_zone_region.h | 206 +- .../world_editor/color_button.cpp | 136 +- .../world_editor/world_editor/color_button.h | 184 +- .../world_editor/custom_snapshot.cpp | 230 +- .../world_editor/custom_snapshot.h | 150 +- .../world_editor/dialog_properties.cpp | 7424 ++++++------- .../world_editor/dialog_properties.h | 700 +- .../world_editor/world_editor/display.cpp | 7826 ++++++------- .../world_editor/world_editor/display.h | 778 +- .../world_editor/editor_primitive.cpp | 2358 ++-- .../world_editor/editor_primitive.h | 960 +- .../world_editor/export_cb_dlg.cpp | 346 +- .../world_editor/world_editor/export_cb_dlg.h | 218 +- .../world_editor/world_editor/export_dlg.cpp | 616 +- .../world_editor/world_editor/export_dlg.h | 202 +- .../world_editor/external_editor.cpp | 192 +- .../world_editor/external_editor.h | 58 +- .../world_editor/file_dialog_ex.cpp | 352 +- .../world_editor/file_dialog_ex.h | 126 +- .../world_editor/find_primitive_dlg.cpp | 706 +- .../world_editor/find_primitive_dlg.h | 162 +- .../world_editor/generate_dlg.cpp | 196 +- .../world_editor/world_editor/generate_dlg.h | 146 +- .../world_editor/generate_primitive.cpp | 2240 ++-- .../world_editor/generate_primitive.h | 218 +- .../world_editor/world_editor/goto_dialog.cpp | 168 +- .../world_editor/world_editor/goto_dialog.h | 132 +- .../world_editor/imagelist_ex.cpp | 284 +- .../world_editor/world_editor/imagelist_ex.h | 104 +- .../world_editor/world_editor/main_frm.cpp | 8772 +++++++-------- .../world_editor/world_editor/main_frm.h | 1066 +- .../world_editor/world_editor/move_dlg.cpp | 112 +- .../world_editor/world_editor/move_dlg.h | 126 +- .../world_editor/world_editor/my_list_box.cpp | 464 +- .../world_editor/world_editor/my_list_box.h | 170 +- .../world_editor/world_editor/name_dlg.cpp | 814 +- .../world_editor/world_editor/name_dlg.h | 192 +- .../world_editor/world_editor/pacs.cpp | 318 +- .../world_editor/world_editor/pacs.h | 116 +- .../world_editor/plugin_interface.h | 442 +- .../primitive_configuration_dlg.cpp | 540 +- .../primitive_configuration_dlg.h | 180 +- .../world_editor/primitive_view.cpp | 240 +- .../world_editor/primitive_view.h | 142 +- .../world_editor/project_settings.cpp | 294 +- .../world_editor/project_settings.h | 130 +- .../world_editor/world_editor/resource.h | 698 +- .../world_editor/select_by_location.cpp | 160 +- .../world_editor/select_by_location.h | 136 +- .../world_editor/splash_screen.cpp | 158 +- .../world_editor/world_editor/splash_screen.h | 130 +- .../world_editor/world_editor/stdafx.cpp | 42 +- .../world_editor/world_editor/stdafx.h | 234 +- .../world_editor/world_editor/tools_logic.cpp | 4392 ++++---- .../world_editor/world_editor/tools_logic.h | 502 +- .../world_editor/world_editor/tools_zone.cpp | 1388 +-- .../world_editor/world_editor/tools_zone.h | 274 +- .../world_editor/world_editor/type_dlg.cpp | 174 +- .../world_editor/world_editor/type_dlg.h | 138 +- .../world_editor/type_manager_dlg.cpp | 292 +- .../world_editor/type_manager_dlg.h | 142 +- .../world_editor/type_sel_dlg.cpp | 160 +- .../world_editor/world_editor/type_sel_dlg.h | 142 +- .../world_editor/world_editor.cpp | 2102 ++-- .../world_editor/world_editor/world_editor.h | 370 +- .../world_editor/world_editor_doc.cpp | 5252 ++++----- .../world_editor/world_editor_doc.h | 948 +- .../world_editor/world_editor_view.cpp | 228 +- .../world_editor/world_editor_view.h | 166 +- .../DialogFlags.cpp | 244 +- .../DialogFlags.h | 164 +- .../ReadMe.txt | 132 +- .../Resource.h | 74 +- .../StdAfx.cpp | 48 +- .../world_editor_fauna_graph_plugin/StdAfx.h | 124 +- .../plugin.cpp | 784 +- .../world_editor_fauna_graph_plugin/plugin.h | 172 +- .../world_editor_fauna_graph_plugin.cpp | 144 +- .../world_editor_fauna_graph_plugin.h | 122 +- .../world_editor_graph_plugin/StdAfx.cpp | 48 +- .../world_editor_graph_plugin/StdAfx.h | 100 +- .../graph_plugin.cpp | 1890 ++-- .../world_editor_graph_plugin/graph_plugin.h | 202 +- .../world_editor_graph_plugin/resource.h | 92 +- .../world_editor_graph_plugin.cpp | 184 +- .../world_editor_graph_plugin.h | 134 +- .../world_editor_graph_plugin_dlg.cpp | 1534 +-- .../world_editor_graph_plugin_dlg.h | 220 +- .../world_editor_plugin/CMakeLists.txt | 52 +- .../world_editor_plugin/DialogFlags.cpp | 154 +- .../world_editor_plugin/DialogFlags.h | 150 +- .../world_editor_plugin/LoadDialog.cpp | 106 +- .../world_editor_plugin/LoadDialog.h | 124 +- .../world_editor_plugin/StdAfx.cpp | 48 +- .../world_editor/world_editor_plugin/StdAfx.h | 100 +- .../world_editor_plugin/plugin.cpp | 690 +- .../world_editor/world_editor_plugin/plugin.h | 172 +- .../world_editor_plugin/resource.h | 160 +- .../world_editor_scriptPLAYER.xml | 20 +- .../CMakeLists.txt | 42 +- .../primitive_plugin.cpp | 714 +- .../primitive_plugin.h | 212 +- .../DialogFlags.cpp | 996 +- .../DialogFlags.h | 250 +- .../DialogLogin.cpp | 110 +- .../DialogLogin.h | 130 +- .../StdAfx.cpp | 48 +- .../StdAfx.h | 114 +- .../entity_display_info.h | 128 +- .../list_box_color.cpp | 682 +- .../list_box_color.h | 234 +- .../memory_combo_box.cpp | 1552 +-- .../memory_combo_box.h | 306 +- .../plugin.cpp | 2602 ++--- .../plugin.h | 526 +- .../resource.h | 250 +- .../world_editor_shard_monitor_plugin.xml | 26 +- .../world_editor_sound_plugin/DialogFlags.cpp | 658 +- .../world_editor_sound_plugin/DialogFlags.h | 196 +- .../world_editor_sound_plugin/LoadDialog.cpp | 106 +- .../world_editor_sound_plugin/LoadDialog.h | 124 +- .../world_editor_sound_plugin/StdAfx.cpp | 48 +- .../world_editor_sound_plugin/StdAfx.h | 106 +- .../world_editor_sound_plugin/resource.h | 162 +- .../sound_plugin.cpp | 810 +- .../world_editor_sound_plugin/sound_plugin.h | 222 +- .../tools/make_alias_file/make_alias_file.cpp | 498 +- code/ryzom/tools/make_anim_by_race/main.cpp | 650 +- .../tools/make_anim_melee_impact/anim.txt | 1832 +-- .../tools/make_anim_melee_impact/main.cpp | 954 +- code/ryzom/tools/occ2huff/occ2huff.cpp | 540 +- .../tools/patch_gen/patch_gen_common.cpp | 1232 +-- code/ryzom/tools/patch_gen/patch_gen_main.cpp | 116 +- code/ryzom/tools/patch_gen/patch_gen_main.h | 40 +- .../tools/patch_gen/patch_gen_service.cpp | 134 +- .../ryzom/tools/patch_gen/patch_gen_service.h | 88 +- code/ryzom/tools/pd_parser/cpp_output.h | 1862 ++-- code/ryzom/tools/pd_parser/main.cpp | 268 +- code/ryzom/tools/pd_parser/parse_node.h | 2970 ++--- code/ryzom/tools/pd_parser/parser.cpp | 9818 ++++++++--------- code/ryzom/tools/pd_parser/parser.h | 64 +- code/ryzom/tools/pd_parser/parser_rules.cpp | 1132 +- code/ryzom/tools/pd_parser/parser_rules.h | 832 +- code/ryzom/tools/pd_parser/templatizer.cpp | 1112 +- code/ryzom/tools/pd_parser/templatizer.h | 2714 ++--- code/ryzom/tools/pd_parser/tokenizer.h | 1566 +-- code/ryzom/tools/pdr_util/pdr_util.cpp | 598 +- code/ryzom/tools/phrase_generator/StdAfx.cpp | 48 +- code/ryzom/tools/phrase_generator/StdAfx.h | 70 +- .../phrase_generator/phrase_generator.cpp | 5512 ++++----- .../tools/phrase_generator/skill_tree.cpp | 260 +- .../ryzom/tools/phrase_generator/skill_tree.h | 214 +- code/ryzom/tools/phrase_generator/sstring.h | 1076 +- .../ryzom/tools/reynolds/reynolds_manager.cpp | 922 +- code/ryzom/tools/reynolds/reynolds_manager.h | 702 +- code/ryzom/tools/reynolds/stdpch.cpp | 34 +- code/ryzom/tools/reynolds/stdpch.h | 92 +- code/ryzom/tools/reynolds/track.cpp | 1090 +- code/ryzom/tools/reynolds/track.h | 1006 +- .../server/admin/docs/shard_restart/Hd36.xml | 1638 +-- .../ai_build_wmap/build_proximity_maps.cpp | 1448 +-- .../ryzom/tools/server/ai_build_wmap/main.cpp | 220 +- .../brick_param_extractor.cpp | 1508 +-- .../build_spell_sheet/build_spell_sheet.cpp | 1104 +- .../build_world_packed_col.cpp | 870 +- .../build_world_packed_col/builder_config.cpp | 216 +- .../build_world_packed_col/builder_config.h | 90 +- .../packed_world_builder.cpp | 1344 +-- .../packed_world_builder.h | 98 +- .../build_world_packed_col/std_header.cpp | 32 +- .../build_world_packed_col/std_header.h | 48 +- .../build_world_packed_col/test_col_world.cpp | 2200 ++-- .../server/build_world_packed_col/village.cpp | 608 +- .../server/build_world_packed_col/village.h | 174 +- .../build_world_packed_col/zone_util.cpp | 140 +- .../server/build_world_packed_col/zone_util.h | 66 +- .../tools/sheet_random_generator/StdAfx.cpp | 48 +- .../tools/sheet_random_generator/StdAfx.h | 70 +- .../sheet_random_generator.cpp | 7814 ++++++------- .../sheet_random_generator/srg_utilities.cpp | 38 +- .../sheet_random_generator/srg_utilities.h | 5928 +++++----- .../tools/sheets_packer/sheets_packer.cpp | 224 +- .../tools/sheets_packer/sheets_packer_cfg.cpp | 504 +- .../tools/sheets_packer/sheets_packer_cfg.h | 158 +- .../sheets_packer/sheets_packer_init.cpp | 252 +- .../tools/sheets_packer/sheets_packer_init.h | 70 +- code/ryzom/tools/sheets_packer/stdpch.cpp | 4 +- code/ryzom/tools/sheets_packer/stdpch.h | 80 +- .../tools/skill_extractor/skill_extractor.cpp | 1496 +-- code/ryzom/tools/stats_scan/char_commands.cpp | 604 +- .../tools/stats_scan/char_filter_factory.cpp | 208 +- .../tools/stats_scan/char_filter_factory.h | 268 +- .../char_info_extractor_factory.cpp | 208 +- .../stats_scan/char_info_extractor_factory.h | 276 +- .../tools/stats_scan/char_scan_script.cpp | 644 +- .../ryzom/tools/stats_scan/char_scan_script.h | 346 +- code/ryzom/tools/stats_scan/character.cpp | 1012 +- code/ryzom/tools/stats_scan/character.h | 1394 +-- .../tools/stats_scan/character_scan_job.cpp | 566 +- .../tools/stats_scan/character_scan_job.h | 188 +- code/ryzom/tools/stats_scan/job_manager.cpp | 358 +- code/ryzom/tools/stats_scan/job_manager.h | 198 +- code/ryzom/tools/stats_scan/service_main.cpp | 188 +- .../tools/stats_scan/user_char_filters.cpp | 106 +- .../stats_scan/user_char_info_extractors.cpp | 156 +- .../translation_tools/extract_bot_names.cpp | 1510 +-- .../extract_new_sheet_names.cpp | 834 +- code/ryzom/tools/translation_tools/main.cpp | 6610 +++++------ code/ryzom/tools/xml_packer/xml_packer.cpp | 732 +- code/snowballs2/CMakeLists.txt | 62 +- code/snowballs2/client/CMakeLists.txt | 24 +- code/snowballs2/client/src/CMakeLists.txt | 40 +- code/snowballs2/client/src/animation.cpp | 572 +- code/snowballs2/client/src/animation.h | 112 +- code/snowballs2/client/src/camera.cpp | 338 +- code/snowballs2/client/src/camera.h | 138 +- code/snowballs2/client/src/commands.cpp | 750 +- code/snowballs2/client/src/commands.h | 102 +- code/snowballs2/client/src/compass.cpp | 360 +- code/snowballs2/client/src/compass.h | 68 +- code/snowballs2/client/src/configuration.cpp | 356 +- code/snowballs2/client/src/configuration.h | 128 +- code/snowballs2/client/src/entities.cpp | 2068 ++-- code/snowballs2/client/src/entities.h | 426 +- code/snowballs2/client/src/game_time.cpp | 230 +- code/snowballs2/client/src/game_time.h | 106 +- code/snowballs2/client/src/graph.cpp | 338 +- code/snowballs2/client/src/graph.h | 170 +- code/snowballs2/client/src/interface.cpp | 548 +- code/snowballs2/client/src/interface.h | 110 +- .../client/src/internationalization.cpp | 236 +- .../client/src/internationalization.h | 100 +- code/snowballs2/client/src/landscape.cpp | 984 +- code/snowballs2/client/src/landscape.h | 156 +- code/snowballs2/client/src/lens_flare.cpp | 654 +- code/snowballs2/client/src/lens_flare.h | 68 +- code/snowballs2/client/src/mouse_listener.cpp | 938 +- code/snowballs2/client/src/mouse_listener.h | 616 +- code/snowballs2/client/src/network.cpp | 840 +- code/snowballs2/client/src/network.h | 160 +- code/snowballs2/client/src/pacs.cpp | 368 +- code/snowballs2/client/src/pacs.h | 118 +- code/snowballs2/client/src/physics.cpp | 120 +- code/snowballs2/client/src/physics.h | 138 +- code/snowballs2/client/src/radar.cpp | 1502 +-- code/snowballs2/client/src/radar.h | 82 +- .../client/src/snowballs_client.cpp | 2688 ++--- code/snowballs2/client/src/snowballs_client.h | 198 +- code/snowballs2/client/src/snowballs_config.h | 156 +- code/snowballs2/client/src/sound.cpp | 490 +- code/snowballs2/client/src/sound.h | 138 +- code/snowballs2/server/CMakeLists.txt | 12 +- code/snowballs2/server/chat/CMakeLists.txt | 6 +- .../snowballs2/server/chat/src/CMakeLists.txt | 34 +- code/snowballs2/server/chat/src/main.cpp | 198 +- .../server/collision/CMakeLists.txt | 6 +- .../server/collision/src/CMakeLists.txt | 38 +- .../collision/src/collision_service.cpp | 818 +- .../server/collision/src/collision_service.h | 192 +- .../server/empty/src/empty_service.cpp | 418 +- .../server/empty/src/empty_service.h | 106 +- .../snowballs2/server/frontend/CMakeLists.txt | 6 +- .../server/frontend/src/CMakeLists.txt | 34 +- code/snowballs2/server/frontend/src/main.cpp | 1418 +-- .../snowballs2/server/position/CMakeLists.txt | 6 +- .../server/position/src/CMakeLists.txt | 24 +- code/snowballs2/server/position/src/main.cpp | 1230 +-- .../server/position/src/physics.cpp | 92 +- code/snowballs2/server/position/src/physics.h | 126 +- code/tool/bin2c/bin2c.cpp | 190 +- code/tool/crash/crash.cpp | 54 +- .../increment_version/increment_version.cpp | 270 +- code/tool/mkdir_date/mkdir_date.cpp | 100 +- code/tool/open_file/open_file.cpp | 200 +- .../path_content_diff/path_content_diff.cpp | 440 +- code/tool/ren_date/ren_date.cpp | 158 +- code/tool/resswap/ResSwap.cpp | 100 +- .../nevrax_macros_howto.txt | 298 +- 391 files changed, 136243 insertions(+), 136243 deletions(-) diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFades.cpp b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFades.cpp index 059b4a0ed..e0285a3fb 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFades.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFades.cpp @@ -1,230 +1,230 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// PageBgFades.cpp : implementation file -// - -#include "std_sound_plugin.h" -#include "georges_plugin_sound.h" -#include "nel/misc/types_nl.h" -#include "sound_dialog.h" -#include "sound_plugin.h" -#include "nel/sound/u_audio_mixer.h" - -#include "PageBgFades.h" - -using namespace std; - -uint FILTER_NAMES[] = -{ - IDC_FILTER_NAME_00, - IDC_FILTER_NAME_01, - IDC_FILTER_NAME_02, - IDC_FILTER_NAME_03, - IDC_FILTER_NAME_04, - IDC_FILTER_NAME_05, - IDC_FILTER_NAME_06, - IDC_FILTER_NAME_07, - IDC_FILTER_NAME_08, - IDC_FILTER_NAME_09, - IDC_FILTER_NAME_10, - IDC_FILTER_NAME_11, - IDC_FILTER_NAME_12, - IDC_FILTER_NAME_13, - IDC_FILTER_NAME_14, - IDC_FILTER_NAME_15, - IDC_FILTER_NAME_16, - IDC_FILTER_NAME_17, - IDC_FILTER_NAME_18, - IDC_FILTER_NAME_19, - IDC_FILTER_NAME_20, - IDC_FILTER_NAME_21, - IDC_FILTER_NAME_22, - IDC_FILTER_NAME_23, - IDC_FILTER_NAME_24, - IDC_FILTER_NAME_25, - IDC_FILTER_NAME_26, - IDC_FILTER_NAME_27, - IDC_FILTER_NAME_28, - IDC_FILTER_NAME_29, - IDC_FILTER_NAME_30, - IDC_FILTER_NAME_31 -}; - -uint FILTER_FADE_IN[] = -{ - IDC_FADE_IN_00, - IDC_FADE_IN_01, - IDC_FADE_IN_02, - IDC_FADE_IN_03, - IDC_FADE_IN_04, - IDC_FADE_IN_05, - IDC_FADE_IN_06, - IDC_FADE_IN_07, - IDC_FADE_IN_08, - IDC_FADE_IN_09, - IDC_FADE_IN_10, - IDC_FADE_IN_11, - IDC_FADE_IN_12, - IDC_FADE_IN_13, - IDC_FADE_IN_14, - IDC_FADE_IN_15, - IDC_FADE_IN_16, - IDC_FADE_IN_17, - IDC_FADE_IN_18, - IDC_FADE_IN_19, - IDC_FADE_IN_20, - IDC_FADE_IN_21, - IDC_FADE_IN_22, - IDC_FADE_IN_23, - IDC_FADE_IN_24, - IDC_FADE_IN_25, - IDC_FADE_IN_26, - IDC_FADE_IN_27, - IDC_FADE_IN_28, - IDC_FADE_IN_29, - IDC_FADE_IN_30, - IDC_FADE_IN_31 -}; - -uint FILTER_FADE_OUT[] = -{ - IDC_FADE_OUT_00, - IDC_FADE_OUT_01, - IDC_FADE_OUT_02, - IDC_FADE_OUT_03, - IDC_FADE_OUT_04, - IDC_FADE_OUT_05, - IDC_FADE_OUT_06, - IDC_FADE_OUT_07, - IDC_FADE_OUT_08, - IDC_FADE_OUT_09, - IDC_FADE_OUT_10, - IDC_FADE_OUT_11, - IDC_FADE_OUT_12, - IDC_FADE_OUT_13, - IDC_FADE_OUT_14, - IDC_FADE_OUT_15, - IDC_FADE_OUT_16, - IDC_FADE_OUT_17, - IDC_FADE_OUT_18, - IDC_FADE_OUT_19, - IDC_FADE_OUT_20, - IDC_FADE_OUT_21, - IDC_FADE_OUT_22, - IDC_FADE_OUT_23, - IDC_FADE_OUT_24, - IDC_FADE_OUT_25, - IDC_FADE_OUT_26, - IDC_FADE_OUT_27, - IDC_FADE_OUT_28, - IDC_FADE_OUT_29, - IDC_FADE_OUT_30, - IDC_FADE_OUT_31, -}; - -map FILTER_FADE_IN_IDX; -map FILTER_FADE_OUT_IDX; - -///////////////////////////////////////////////////////////////////////////// -// CPageBgFades property page - -#undef new -IMPLEMENT_DYNCREATE(CPageBgFades, CPageBase) -#define new NL_NEW - -CPageBgFades::CPageBgFades(NLGEORGES::CSoundDialog *soundDialog) - : CPageBase(soundDialog, CPageBgFades::IDD) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - //{{AFX_DATA_INIT(CPageBgFades) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT - - for (uint i=0; i<32; ++i) - { - FILTER_FADE_IN_IDX.insert(make_pair(FILTER_FADE_IN[i], i)); - FILTER_FADE_OUT_IDX.insert(make_pair(FILTER_FADE_OUT[i], i)); - } -} - -CPageBgFades::~CPageBgFades() -{ -} - -void CPageBgFades::DoDataExchange(CDataExchange* pDX) -{ - CPropertyPage::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CPageBgFades) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CPageBgFades, CPropertyPage) - //{{AFX_MSG_MAP(CPageBgFades) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CPageBgFades message handlers - -BOOL CPageBgFades::OnInitDialog() -{ - CPropertyPage::OnInitDialog(); - - // initialize the filter names and fade value - for (uint i =0; i<32; ++i) - { - char tmp[128]; - GetDlgItem(FILTER_NAMES[i])->SetWindowText(SoundDialog->EnvNames[i].Name.c_str()); - sprintf(tmp, "%u", SoundDialog->FilterFades.FadeIns[i]); - GetDlgItem(FILTER_FADE_IN[i])->SetWindowText(tmp); - sprintf(tmp, "%u", SoundDialog->FilterFades.FadeOuts[i]); - GetDlgItem(FILTER_FADE_OUT[i])->SetWindowText(tmp); - } - - SoundDialog->getSoundPlugin()->getMixer()->setBackgroundFilterFades(SoundDialog->FilterFades); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -BOOL CPageBgFades::OnCommand(WPARAM wParam, LPARAM lParam) -{ - if (lParam != 0 && HIWORD(wParam) == EN_CHANGE) - { - int id = ::GetDlgCtrlID(HWND(lParam)); - char tmp[1024]; - - if (FILTER_FADE_IN_IDX.find(id) != FILTER_FADE_IN_IDX.end()) - { - // this is a fade in value modified ! - GetDlgItem(id)->GetWindowText(tmp, 1024); - SoundDialog->FilterFades.FadeIns[FILTER_FADE_IN_IDX[id]] = atoi(tmp); - SoundDialog->getSoundPlugin()->getMixer()->setBackgroundFilterFades(SoundDialog->FilterFades); - } - else if (FILTER_FADE_OUT_IDX.find(id) != FILTER_FADE_OUT_IDX.end()) - { - // this is a fade in value modified ! - GetDlgItem(id)->GetWindowText(tmp, 1024); - SoundDialog->FilterFades.FadeOuts[FILTER_FADE_OUT_IDX[id]] = atoi(tmp); - SoundDialog->getSoundPlugin()->getMixer()->setBackgroundFilterFades(SoundDialog->FilterFades); - } - } - - return CPropertyPage::OnCommand(wParam, lParam); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// PageBgFades.cpp : implementation file +// + +#include "std_sound_plugin.h" +#include "georges_plugin_sound.h" +#include "nel/misc/types_nl.h" +#include "sound_dialog.h" +#include "sound_plugin.h" +#include "nel/sound/u_audio_mixer.h" + +#include "PageBgFades.h" + +using namespace std; + +uint FILTER_NAMES[] = +{ + IDC_FILTER_NAME_00, + IDC_FILTER_NAME_01, + IDC_FILTER_NAME_02, + IDC_FILTER_NAME_03, + IDC_FILTER_NAME_04, + IDC_FILTER_NAME_05, + IDC_FILTER_NAME_06, + IDC_FILTER_NAME_07, + IDC_FILTER_NAME_08, + IDC_FILTER_NAME_09, + IDC_FILTER_NAME_10, + IDC_FILTER_NAME_11, + IDC_FILTER_NAME_12, + IDC_FILTER_NAME_13, + IDC_FILTER_NAME_14, + IDC_FILTER_NAME_15, + IDC_FILTER_NAME_16, + IDC_FILTER_NAME_17, + IDC_FILTER_NAME_18, + IDC_FILTER_NAME_19, + IDC_FILTER_NAME_20, + IDC_FILTER_NAME_21, + IDC_FILTER_NAME_22, + IDC_FILTER_NAME_23, + IDC_FILTER_NAME_24, + IDC_FILTER_NAME_25, + IDC_FILTER_NAME_26, + IDC_FILTER_NAME_27, + IDC_FILTER_NAME_28, + IDC_FILTER_NAME_29, + IDC_FILTER_NAME_30, + IDC_FILTER_NAME_31 +}; + +uint FILTER_FADE_IN[] = +{ + IDC_FADE_IN_00, + IDC_FADE_IN_01, + IDC_FADE_IN_02, + IDC_FADE_IN_03, + IDC_FADE_IN_04, + IDC_FADE_IN_05, + IDC_FADE_IN_06, + IDC_FADE_IN_07, + IDC_FADE_IN_08, + IDC_FADE_IN_09, + IDC_FADE_IN_10, + IDC_FADE_IN_11, + IDC_FADE_IN_12, + IDC_FADE_IN_13, + IDC_FADE_IN_14, + IDC_FADE_IN_15, + IDC_FADE_IN_16, + IDC_FADE_IN_17, + IDC_FADE_IN_18, + IDC_FADE_IN_19, + IDC_FADE_IN_20, + IDC_FADE_IN_21, + IDC_FADE_IN_22, + IDC_FADE_IN_23, + IDC_FADE_IN_24, + IDC_FADE_IN_25, + IDC_FADE_IN_26, + IDC_FADE_IN_27, + IDC_FADE_IN_28, + IDC_FADE_IN_29, + IDC_FADE_IN_30, + IDC_FADE_IN_31 +}; + +uint FILTER_FADE_OUT[] = +{ + IDC_FADE_OUT_00, + IDC_FADE_OUT_01, + IDC_FADE_OUT_02, + IDC_FADE_OUT_03, + IDC_FADE_OUT_04, + IDC_FADE_OUT_05, + IDC_FADE_OUT_06, + IDC_FADE_OUT_07, + IDC_FADE_OUT_08, + IDC_FADE_OUT_09, + IDC_FADE_OUT_10, + IDC_FADE_OUT_11, + IDC_FADE_OUT_12, + IDC_FADE_OUT_13, + IDC_FADE_OUT_14, + IDC_FADE_OUT_15, + IDC_FADE_OUT_16, + IDC_FADE_OUT_17, + IDC_FADE_OUT_18, + IDC_FADE_OUT_19, + IDC_FADE_OUT_20, + IDC_FADE_OUT_21, + IDC_FADE_OUT_22, + IDC_FADE_OUT_23, + IDC_FADE_OUT_24, + IDC_FADE_OUT_25, + IDC_FADE_OUT_26, + IDC_FADE_OUT_27, + IDC_FADE_OUT_28, + IDC_FADE_OUT_29, + IDC_FADE_OUT_30, + IDC_FADE_OUT_31, +}; + +map FILTER_FADE_IN_IDX; +map FILTER_FADE_OUT_IDX; + +///////////////////////////////////////////////////////////////////////////// +// CPageBgFades property page + +#undef new +IMPLEMENT_DYNCREATE(CPageBgFades, CPageBase) +#define new NL_NEW + +CPageBgFades::CPageBgFades(NLGEORGES::CSoundDialog *soundDialog) + : CPageBase(soundDialog, CPageBgFades::IDD) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + //{{AFX_DATA_INIT(CPageBgFades) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + for (uint i=0; i<32; ++i) + { + FILTER_FADE_IN_IDX.insert(make_pair(FILTER_FADE_IN[i], i)); + FILTER_FADE_OUT_IDX.insert(make_pair(FILTER_FADE_OUT[i], i)); + } +} + +CPageBgFades::~CPageBgFades() +{ +} + +void CPageBgFades::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPageBgFades) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CPageBgFades, CPropertyPage) + //{{AFX_MSG_MAP(CPageBgFades) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPageBgFades message handlers + +BOOL CPageBgFades::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // initialize the filter names and fade value + for (uint i =0; i<32; ++i) + { + char tmp[128]; + GetDlgItem(FILTER_NAMES[i])->SetWindowText(SoundDialog->EnvNames[i].Name.c_str()); + sprintf(tmp, "%u", SoundDialog->FilterFades.FadeIns[i]); + GetDlgItem(FILTER_FADE_IN[i])->SetWindowText(tmp); + sprintf(tmp, "%u", SoundDialog->FilterFades.FadeOuts[i]); + GetDlgItem(FILTER_FADE_OUT[i])->SetWindowText(tmp); + } + + SoundDialog->getSoundPlugin()->getMixer()->setBackgroundFilterFades(SoundDialog->FilterFades); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +BOOL CPageBgFades::OnCommand(WPARAM wParam, LPARAM lParam) +{ + if (lParam != 0 && HIWORD(wParam) == EN_CHANGE) + { + int id = ::GetDlgCtrlID(HWND(lParam)); + char tmp[1024]; + + if (FILTER_FADE_IN_IDX.find(id) != FILTER_FADE_IN_IDX.end()) + { + // this is a fade in value modified ! + GetDlgItem(id)->GetWindowText(tmp, 1024); + SoundDialog->FilterFades.FadeIns[FILTER_FADE_IN_IDX[id]] = atoi(tmp); + SoundDialog->getSoundPlugin()->getMixer()->setBackgroundFilterFades(SoundDialog->FilterFades); + } + else if (FILTER_FADE_OUT_IDX.find(id) != FILTER_FADE_OUT_IDX.end()) + { + // this is a fade in value modified ! + GetDlgItem(id)->GetWindowText(tmp, 1024); + SoundDialog->FilterFades.FadeOuts[FILTER_FADE_OUT_IDX[id]] = atoi(tmp); + SoundDialog->getSoundPlugin()->getMixer()->setBackgroundFilterFades(SoundDialog->FilterFades); + } + } + + return CPropertyPage::OnCommand(wParam, lParam); +} diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFades.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFades.h index 43a339225..8aaa4adb6 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFades.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFades.h @@ -1,69 +1,69 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_PAGEBGFADES_H__AED887E2_E8D1_4BDB_B180_B6ADF8C44D58__INCLUDED_) -#define AFX_PAGEBGFADES_H__AED887E2_E8D1_4BDB_B180_B6ADF8C44D58__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// PageBgFades.h : header file -// -#include "PageBase.h" - -///////////////////////////////////////////////////////////////////////////// -// CPageBgFades dialog - -class CPageBgFades : public CPageBase -{ - DECLARE_DYNCREATE(CPageBgFades) - -// Construction -public: - CPageBgFades() {} - CPageBgFades(NLGEORGES::CSoundDialog *soundDialog); - ~CPageBgFades(); - -// Dialog Data - //{{AFX_DATA(CPageBgFades) - enum { IDD = IDD_PAGE_BG_FADES }; - // NOTE - ClassWizard will add data members here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_DATA - - -// Overrides - // ClassWizard generate virtual function overrides - //{{AFX_VIRTUAL(CPageBgFades) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - //}}AFX_VIRTUAL - -// Implementation -protected: - // Generated message map functions - //{{AFX_MSG(CPageBgFades) - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_PAGEBGFADES_H__AED887E2_E8D1_4BDB_B180_B6ADF8C44D58__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_PAGEBGFADES_H__AED887E2_E8D1_4BDB_B180_B6ADF8C44D58__INCLUDED_) +#define AFX_PAGEBGFADES_H__AED887E2_E8D1_4BDB_B180_B6ADF8C44D58__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PageBgFades.h : header file +// +#include "PageBase.h" + +///////////////////////////////////////////////////////////////////////////// +// CPageBgFades dialog + +class CPageBgFades : public CPageBase +{ + DECLARE_DYNCREATE(CPageBgFades) + +// Construction +public: + CPageBgFades() {} + CPageBgFades(NLGEORGES::CSoundDialog *soundDialog); + ~CPageBgFades(); + +// Dialog Data + //{{AFX_DATA(CPageBgFades) + enum { IDD = IDD_PAGE_BG_FADES }; + // NOTE - ClassWizard will add data members here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CPageBgFades) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CPageBgFades) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PAGEBGFADES_H__AED887E2_E8D1_4BDB_B180_B6ADF8C44D58__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFlags.cpp b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFlags.cpp index 20a2ddb05..bc0d108f4 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFlags.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFlags.cpp @@ -1,434 +1,434 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// PageBgFlags.cpp : implementation file -// - -#include "std_sound_plugin.h" -#include "nel/misc/types_nl.h" -#include "georges_plugin_sound.h" -#include "nel/georges/u_form_elm.h" -#include "sound_document_plugin.h" -#include "nel/sound/u_audio_mixer.h" - -#include "PageBgFlags.h" - -using namespace std; - -// controls id arrays -uint FILTER_EDIT[] = -{ - IDC_FILTER_00, - IDC_FILTER_01, - IDC_FILTER_02, - IDC_FILTER_03, - IDC_FILTER_04, - IDC_FILTER_05, - IDC_FILTER_06, - IDC_FILTER_07, - IDC_FILTER_08, - IDC_FILTER_09, - IDC_FILTER_10, - IDC_FILTER_11, - IDC_FILTER_12, - IDC_FILTER_13, - IDC_FILTER_14, - IDC_FILTER_15, - IDC_FILTER_16, - IDC_FILTER_17, - IDC_FILTER_18, - IDC_FILTER_19, - IDC_FILTER_20, - IDC_FILTER_21, - IDC_FILTER_22, - IDC_FILTER_23, - IDC_FILTER_24, - IDC_FILTER_25, - IDC_FILTER_26, - IDC_FILTER_27, - IDC_FILTER_28, - IDC_FILTER_29, - IDC_FILTER_30, - IDC_FILTER_31 -}; - -uint FILTER_EDIT_NAME[] = -{ - IDC_FILTER_NAME_00, - IDC_FILTER_NAME_01, - IDC_FILTER_NAME_02, - IDC_FILTER_NAME_03, - IDC_FILTER_NAME_04, - IDC_FILTER_NAME_05, - IDC_FILTER_NAME_06, - IDC_FILTER_NAME_07, - IDC_FILTER_NAME_08, - IDC_FILTER_NAME_09, - IDC_FILTER_NAME_10, - IDC_FILTER_NAME_11, - IDC_FILTER_NAME_12, - IDC_FILTER_NAME_13, - IDC_FILTER_NAME_14, - IDC_FILTER_NAME_15, - IDC_FILTER_NAME_16, - IDC_FILTER_NAME_17, - IDC_FILTER_NAME_18, - IDC_FILTER_NAME_19, - IDC_FILTER_NAME_20, - IDC_FILTER_NAME_21, - IDC_FILTER_NAME_22, - IDC_FILTER_NAME_23, - IDC_FILTER_NAME_24, - IDC_FILTER_NAME_25, - IDC_FILTER_NAME_26, - IDC_FILTER_NAME_27, - IDC_FILTER_NAME_28, - IDC_FILTER_NAME_29, - IDC_FILTER_NAME_30, - IDC_FILTER_NAME_31 -}; - -uint FILTER_SIM[] = -{ - IDC_ENV_FLAG_00, - IDC_ENV_FLAG_01, - IDC_ENV_FLAG_02, - IDC_ENV_FLAG_03, - IDC_ENV_FLAG_04, - IDC_ENV_FLAG_05, - IDC_ENV_FLAG_06, - IDC_ENV_FLAG_07, - IDC_ENV_FLAG_08, - IDC_ENV_FLAG_09, - IDC_ENV_FLAG_10, - IDC_ENV_FLAG_11, - IDC_ENV_FLAG_12, - IDC_ENV_FLAG_13, - IDC_ENV_FLAG_14, - IDC_ENV_FLAG_15, - IDC_ENV_FLAG_16, - IDC_ENV_FLAG_17, - IDC_ENV_FLAG_18, - IDC_ENV_FLAG_19, - IDC_ENV_FLAG_20, - IDC_ENV_FLAG_21, - IDC_ENV_FLAG_22, - IDC_ENV_FLAG_23, - IDC_ENV_FLAG_24, - IDC_ENV_FLAG_25, - IDC_ENV_FLAG_26, - IDC_ENV_FLAG_27, - IDC_ENV_FLAG_28, - IDC_ENV_FLAG_29, - IDC_ENV_FLAG_30, - IDC_ENV_FLAG_31, -}; - -uint FILTER_SIM_NAME[] = -{ - IDC_ENV_NAME_00, - IDC_ENV_NAME_01, - IDC_ENV_NAME_02, - IDC_ENV_NAME_03, - IDC_ENV_NAME_04, - IDC_ENV_NAME_05, - IDC_ENV_NAME_06, - IDC_ENV_NAME_07, - IDC_ENV_NAME_08, - IDC_ENV_NAME_09, - IDC_ENV_NAME_10, - IDC_ENV_NAME_11, - IDC_ENV_NAME_12, - IDC_ENV_NAME_13, - IDC_ENV_NAME_14, - IDC_ENV_NAME_15, - IDC_ENV_NAME_16, - IDC_ENV_NAME_17, - IDC_ENV_NAME_18, - IDC_ENV_NAME_19, - IDC_ENV_NAME_20, - IDC_ENV_NAME_21, - IDC_ENV_NAME_22, - IDC_ENV_NAME_23, - IDC_ENV_NAME_24, - IDC_ENV_NAME_25, - IDC_ENV_NAME_26, - IDC_ENV_NAME_27, - IDC_ENV_NAME_28, - IDC_ENV_NAME_29, - IDC_ENV_NAME_30, - IDC_ENV_NAME_31, -}; - -std::map FILTER_SIM_IDX; -std::map FILTER_EDIT_IDX; -///////////////////////////////////////////////////////////////////////////// -// CPageBgFlags property page - -#undef new -IMPLEMENT_DYNCREATE(CPageBgFlags, CPageBase) -#define new NL_NEW - -CPageBgFlags::CPageBgFlags(NLGEORGES::CSoundDialog *soundDialog) -: CPageBase(soundDialog, CPageBgFlags::IDD), - _recurse(false) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - //{{AFX_DATA_INIT(CPageBgFlags) - _SubSoundName = _T(""); - //}}AFX_DATA_INIT - - for (uint i=0; i<32; ++i) - { - FILTER_EDIT_IDX.insert(make_pair(FILTER_EDIT[i], i)); - FILTER_SIM_IDX.insert(make_pair(FILTER_SIM[i], i)); - } -} - -CPageBgFlags::~CPageBgFlags() -{ -} - -void CPageBgFlags::DoDataExchange(CDataExchange* pDX) -{ - CPropertyPage::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CPageBgFlags) - DDX_Text(pDX, IDC_SUB_SOUND_NAME, _SubSoundName); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CPageBgFlags, CPropertyPage) - //{{AFX_MSG_MAP(CPageBgFlags) - ON_BN_CLICKED(IDC_BTN_EDIT_ALL_ON, OnBtnEditAllOn) - ON_BN_CLICKED(IDC_BTN_EDIT_ALL_OFF, OnBtnEditAllOff) - ON_BN_CLICKED(IDC_BTN_ENV_ALL_OFF, OnBtnEnvAllOff) - ON_BN_CLICKED(IDC_BTN_ENV_ALL_ON, OnBtnEnvAllOn) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CPageBgFlags message handlers - - -BOOL CPageBgFlags::OnCommand(WPARAM wParam, LPARAM lParam) -{ - _recurse = true; - if (lParam != 0) - { - int id = ::GetDlgCtrlID(HWND(lParam)); - // command come from a control - - if (FILTER_EDIT_IDX.find(id) != FILTER_EDIT_IDX.end()) - { - bool state = static_cast(GetDlgItem(id))->GetCheck() == 1; - nldebug("Setting filter %u of sound %u to %s", FILTER_EDIT_IDX[id], _Index, state ? "true" : "false"); - // here, we don't use the updateData method coz it's too slow for only one value - char path[1024]; - sprintf(path, ".SoundType.Sounds[%u].Filter%02u", _Index, FILTER_EDIT_IDX[id]); - SoundDialog->getSoundPlugin()->getActiveDocument()->setValue(state ? "true" : "false", path); - SoundDialog->getSoundPlugin()->getActiveDocument()->refreshView(); - } - else if (FILTER_SIM_IDX.find(id) != FILTER_SIM_IDX.end()) - { -// bool state = (static_cast(GetDlgItem(id))->GetState() & 0x0003) != 0; -// nldebug("Setting simul filter %u to %s", FILTER_SIM_IDX[id] , state ? "true" : "false"); - updateData(false); - } - } - - _recurse = false; - - return CPropertyPage::OnCommand(wParam, lParam); -} - -void CPageBgFlags::OnBtnEditAllOn() -{ - for (uint i=0; i<32; ++i) - { - static_cast(GetDlgItem(FILTER_EDIT[i]))->SetCheck(TRUE); - } - updateData(true); -} - -void CPageBgFlags::OnBtnEditAllOff() -{ - for (uint i=0; i<32; ++i) - { - static_cast(GetDlgItem(FILTER_EDIT[i]))->SetCheck(FALSE); - } - updateData(true); -} - -void CPageBgFlags::OnBtnEnvAllOn() -{ - for (uint i=0; i<32; ++i) - { - static_cast(GetDlgItem(FILTER_SIM[i]))->SetCheck(TRUE); - } - updateData(false); -} - -void CPageBgFlags::OnBtnEnvAllOff() -{ - for (uint i=0; i<32; ++i) - { - static_cast(GetDlgItem(FILTER_SIM[i]))->SetCheck(FALSE); - } - updateData(false); -} - -void CPageBgFlags::onDocChanged() -{ - // the document have been modified, update the dialog - NLGEORGES::IEditDocument *pdoc = SoundDialog->getSoundPlugin()->getActiveDocument(); - - bool valid = false; - - if (_recurse) - return; - - if (pdoc != NULL) - { - string type, dfnName; - NLGEORGES::UFormElm *psoundType; - - pdoc->getForm()->getRootNode().getNodeByName(&psoundType, ".SoundType"); - - if (psoundType != NULL) - { - psoundType->getDfnName(dfnName); - if (dfnName == "background_sound.dfn") - { - // set the filter flags according to active node - bool val; - string activeNode; - pdoc->getActiveNode(activeNode); - if (activeNode.find(".SoundType.Sounds") != string::npos) - { - // extract the root path on the sheet. - string::size_type p = activeNode.find(".SoundType.Sounds"); - while (p < activeNode.size() && activeNode[p] != '[') - p++; - if (p < activeNode.size()) - { - // skip the open [ - p++; - string index; - - while (isdigit(activeNode[p])) - index += char(activeNode[p++]); - - // extract the index value - _Index = atoi(index.c_str()); - - // skip the closing ] - p++; - - string sheetRoot = activeNode.substr(0, p); - string soundName; - -// pdoc->getForm()->getRootNode().getValueByName(soundName, (sheetRoot+".Sound").c_str()); -// _SoundFilterPane.SetWindowText((string("Edit Sound Filters ")+soundName).c_str()); - - for (uint i=0; i<32; ++i) - { - char tmp[128]; - sprintf(tmp, "%02u", i); - - pdoc->getForm()->getRootNode().getValueByName(val, (sheetRoot+".Filter"+tmp).c_str()); - GetDlgItem(FILTER_EDIT[i])->EnableWindow(TRUE); - static_cast(GetDlgItem(FILTER_EDIT[i]))->SetCheck(val ? 1 : 0); - } - - // set the name of the sub sound - string s; - pdoc->getForm()->getRootNode().getValueByName(s, (sheetRoot+".Sound").c_str()); - - _SubSoundName = s.c_str(); - UpdateData(FALSE); - GetDlgItem(IDC_SUB_SOUND_NAME)->EnableWindow(TRUE); - - valid = true; - } - } - } - } - } - - if (!valid) - { - for (uint i=0; i<32; ++i) - { - GetDlgItem(FILTER_EDIT[i])->EnableWindow(FALSE); - } - GetDlgItem(IDC_SUB_SOUND_NAME)->EnableWindow(FALSE); - - _Index = -1; - } -} - -void CPageBgFlags::updateData(bool updateEditFilter) -{ - _recurse = true; - // update the filter flags and simulation status - if (_Index != -1 && updateEditFilter) - { - // filter edition is valid, update them - for (uint i=0; i<32; ++i) - { - bool state = static_cast(GetDlgItem(FILTER_EDIT[i]))->GetCheck() == 1; - - char path[1024]; - sprintf(path, ".SoundType.Sounds[%u].Filter%02u", _Index, i); - SoundDialog->getSoundPlugin()->getActiveDocument()->setValue(state ? "true" : "false", path); - } - SoundDialog->getSoundPlugin()->getActiveDocument()->refreshView(); - } - - // simulation filters - NLSOUND::UAudioMixer::TBackgroundFlags flags; - for (uint i=0; i<32; ++i) - { - flags.Flags[i] = static_cast(GetDlgItem(FILTER_SIM[i]))->GetCheck() == 1; - } - SoundDialog->getSoundPlugin()->getMixer()->setBackgroundFlags(flags); - - _recurse = false; -} - - - -BOOL CPageBgFlags::OnInitDialog() -{ - CPropertyPage::OnInitDialog(); - - // update filter labels and state - const NLSOUND::UAudioMixer::TBackgroundFlags &flag = SoundDialog->getSoundPlugin()->getMixer()->getBackgroundFlags(); - for (uint i=0; i<32; ++i) - { - GetDlgItem(FILTER_EDIT_NAME[i])->SetWindowText(SoundDialog->EnvNames[i].Name.c_str()); - GetDlgItem(FILTER_SIM_NAME[i])->SetWindowText(SoundDialog->EnvNames[i].ShortName.c_str()); - - static_cast(GetDlgItem(FILTER_SIM[i]))->SetCheck(flag.Flags[i] ? 1 : 0); - } - - // force an update of the dialog state - onDocChanged(); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// PageBgFlags.cpp : implementation file +// + +#include "std_sound_plugin.h" +#include "nel/misc/types_nl.h" +#include "georges_plugin_sound.h" +#include "nel/georges/u_form_elm.h" +#include "sound_document_plugin.h" +#include "nel/sound/u_audio_mixer.h" + +#include "PageBgFlags.h" + +using namespace std; + +// controls id arrays +uint FILTER_EDIT[] = +{ + IDC_FILTER_00, + IDC_FILTER_01, + IDC_FILTER_02, + IDC_FILTER_03, + IDC_FILTER_04, + IDC_FILTER_05, + IDC_FILTER_06, + IDC_FILTER_07, + IDC_FILTER_08, + IDC_FILTER_09, + IDC_FILTER_10, + IDC_FILTER_11, + IDC_FILTER_12, + IDC_FILTER_13, + IDC_FILTER_14, + IDC_FILTER_15, + IDC_FILTER_16, + IDC_FILTER_17, + IDC_FILTER_18, + IDC_FILTER_19, + IDC_FILTER_20, + IDC_FILTER_21, + IDC_FILTER_22, + IDC_FILTER_23, + IDC_FILTER_24, + IDC_FILTER_25, + IDC_FILTER_26, + IDC_FILTER_27, + IDC_FILTER_28, + IDC_FILTER_29, + IDC_FILTER_30, + IDC_FILTER_31 +}; + +uint FILTER_EDIT_NAME[] = +{ + IDC_FILTER_NAME_00, + IDC_FILTER_NAME_01, + IDC_FILTER_NAME_02, + IDC_FILTER_NAME_03, + IDC_FILTER_NAME_04, + IDC_FILTER_NAME_05, + IDC_FILTER_NAME_06, + IDC_FILTER_NAME_07, + IDC_FILTER_NAME_08, + IDC_FILTER_NAME_09, + IDC_FILTER_NAME_10, + IDC_FILTER_NAME_11, + IDC_FILTER_NAME_12, + IDC_FILTER_NAME_13, + IDC_FILTER_NAME_14, + IDC_FILTER_NAME_15, + IDC_FILTER_NAME_16, + IDC_FILTER_NAME_17, + IDC_FILTER_NAME_18, + IDC_FILTER_NAME_19, + IDC_FILTER_NAME_20, + IDC_FILTER_NAME_21, + IDC_FILTER_NAME_22, + IDC_FILTER_NAME_23, + IDC_FILTER_NAME_24, + IDC_FILTER_NAME_25, + IDC_FILTER_NAME_26, + IDC_FILTER_NAME_27, + IDC_FILTER_NAME_28, + IDC_FILTER_NAME_29, + IDC_FILTER_NAME_30, + IDC_FILTER_NAME_31 +}; + +uint FILTER_SIM[] = +{ + IDC_ENV_FLAG_00, + IDC_ENV_FLAG_01, + IDC_ENV_FLAG_02, + IDC_ENV_FLAG_03, + IDC_ENV_FLAG_04, + IDC_ENV_FLAG_05, + IDC_ENV_FLAG_06, + IDC_ENV_FLAG_07, + IDC_ENV_FLAG_08, + IDC_ENV_FLAG_09, + IDC_ENV_FLAG_10, + IDC_ENV_FLAG_11, + IDC_ENV_FLAG_12, + IDC_ENV_FLAG_13, + IDC_ENV_FLAG_14, + IDC_ENV_FLAG_15, + IDC_ENV_FLAG_16, + IDC_ENV_FLAG_17, + IDC_ENV_FLAG_18, + IDC_ENV_FLAG_19, + IDC_ENV_FLAG_20, + IDC_ENV_FLAG_21, + IDC_ENV_FLAG_22, + IDC_ENV_FLAG_23, + IDC_ENV_FLAG_24, + IDC_ENV_FLAG_25, + IDC_ENV_FLAG_26, + IDC_ENV_FLAG_27, + IDC_ENV_FLAG_28, + IDC_ENV_FLAG_29, + IDC_ENV_FLAG_30, + IDC_ENV_FLAG_31, +}; + +uint FILTER_SIM_NAME[] = +{ + IDC_ENV_NAME_00, + IDC_ENV_NAME_01, + IDC_ENV_NAME_02, + IDC_ENV_NAME_03, + IDC_ENV_NAME_04, + IDC_ENV_NAME_05, + IDC_ENV_NAME_06, + IDC_ENV_NAME_07, + IDC_ENV_NAME_08, + IDC_ENV_NAME_09, + IDC_ENV_NAME_10, + IDC_ENV_NAME_11, + IDC_ENV_NAME_12, + IDC_ENV_NAME_13, + IDC_ENV_NAME_14, + IDC_ENV_NAME_15, + IDC_ENV_NAME_16, + IDC_ENV_NAME_17, + IDC_ENV_NAME_18, + IDC_ENV_NAME_19, + IDC_ENV_NAME_20, + IDC_ENV_NAME_21, + IDC_ENV_NAME_22, + IDC_ENV_NAME_23, + IDC_ENV_NAME_24, + IDC_ENV_NAME_25, + IDC_ENV_NAME_26, + IDC_ENV_NAME_27, + IDC_ENV_NAME_28, + IDC_ENV_NAME_29, + IDC_ENV_NAME_30, + IDC_ENV_NAME_31, +}; + +std::map FILTER_SIM_IDX; +std::map FILTER_EDIT_IDX; +///////////////////////////////////////////////////////////////////////////// +// CPageBgFlags property page + +#undef new +IMPLEMENT_DYNCREATE(CPageBgFlags, CPageBase) +#define new NL_NEW + +CPageBgFlags::CPageBgFlags(NLGEORGES::CSoundDialog *soundDialog) +: CPageBase(soundDialog, CPageBgFlags::IDD), + _recurse(false) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + //{{AFX_DATA_INIT(CPageBgFlags) + _SubSoundName = _T(""); + //}}AFX_DATA_INIT + + for (uint i=0; i<32; ++i) + { + FILTER_EDIT_IDX.insert(make_pair(FILTER_EDIT[i], i)); + FILTER_SIM_IDX.insert(make_pair(FILTER_SIM[i], i)); + } +} + +CPageBgFlags::~CPageBgFlags() +{ +} + +void CPageBgFlags::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPageBgFlags) + DDX_Text(pDX, IDC_SUB_SOUND_NAME, _SubSoundName); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CPageBgFlags, CPropertyPage) + //{{AFX_MSG_MAP(CPageBgFlags) + ON_BN_CLICKED(IDC_BTN_EDIT_ALL_ON, OnBtnEditAllOn) + ON_BN_CLICKED(IDC_BTN_EDIT_ALL_OFF, OnBtnEditAllOff) + ON_BN_CLICKED(IDC_BTN_ENV_ALL_OFF, OnBtnEnvAllOff) + ON_BN_CLICKED(IDC_BTN_ENV_ALL_ON, OnBtnEnvAllOn) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPageBgFlags message handlers + + +BOOL CPageBgFlags::OnCommand(WPARAM wParam, LPARAM lParam) +{ + _recurse = true; + if (lParam != 0) + { + int id = ::GetDlgCtrlID(HWND(lParam)); + // command come from a control + + if (FILTER_EDIT_IDX.find(id) != FILTER_EDIT_IDX.end()) + { + bool state = static_cast(GetDlgItem(id))->GetCheck() == 1; + nldebug("Setting filter %u of sound %u to %s", FILTER_EDIT_IDX[id], _Index, state ? "true" : "false"); + // here, we don't use the updateData method coz it's too slow for only one value + char path[1024]; + sprintf(path, ".SoundType.Sounds[%u].Filter%02u", _Index, FILTER_EDIT_IDX[id]); + SoundDialog->getSoundPlugin()->getActiveDocument()->setValue(state ? "true" : "false", path); + SoundDialog->getSoundPlugin()->getActiveDocument()->refreshView(); + } + else if (FILTER_SIM_IDX.find(id) != FILTER_SIM_IDX.end()) + { +// bool state = (static_cast(GetDlgItem(id))->GetState() & 0x0003) != 0; +// nldebug("Setting simul filter %u to %s", FILTER_SIM_IDX[id] , state ? "true" : "false"); + updateData(false); + } + } + + _recurse = false; + + return CPropertyPage::OnCommand(wParam, lParam); +} + +void CPageBgFlags::OnBtnEditAllOn() +{ + for (uint i=0; i<32; ++i) + { + static_cast(GetDlgItem(FILTER_EDIT[i]))->SetCheck(TRUE); + } + updateData(true); +} + +void CPageBgFlags::OnBtnEditAllOff() +{ + for (uint i=0; i<32; ++i) + { + static_cast(GetDlgItem(FILTER_EDIT[i]))->SetCheck(FALSE); + } + updateData(true); +} + +void CPageBgFlags::OnBtnEnvAllOn() +{ + for (uint i=0; i<32; ++i) + { + static_cast(GetDlgItem(FILTER_SIM[i]))->SetCheck(TRUE); + } + updateData(false); +} + +void CPageBgFlags::OnBtnEnvAllOff() +{ + for (uint i=0; i<32; ++i) + { + static_cast(GetDlgItem(FILTER_SIM[i]))->SetCheck(FALSE); + } + updateData(false); +} + +void CPageBgFlags::onDocChanged() +{ + // the document have been modified, update the dialog + NLGEORGES::IEditDocument *pdoc = SoundDialog->getSoundPlugin()->getActiveDocument(); + + bool valid = false; + + if (_recurse) + return; + + if (pdoc != NULL) + { + string type, dfnName; + NLGEORGES::UFormElm *psoundType; + + pdoc->getForm()->getRootNode().getNodeByName(&psoundType, ".SoundType"); + + if (psoundType != NULL) + { + psoundType->getDfnName(dfnName); + if (dfnName == "background_sound.dfn") + { + // set the filter flags according to active node + bool val; + string activeNode; + pdoc->getActiveNode(activeNode); + if (activeNode.find(".SoundType.Sounds") != string::npos) + { + // extract the root path on the sheet. + string::size_type p = activeNode.find(".SoundType.Sounds"); + while (p < activeNode.size() && activeNode[p] != '[') + p++; + if (p < activeNode.size()) + { + // skip the open [ + p++; + string index; + + while (isdigit(activeNode[p])) + index += char(activeNode[p++]); + + // extract the index value + _Index = atoi(index.c_str()); + + // skip the closing ] + p++; + + string sheetRoot = activeNode.substr(0, p); + string soundName; + +// pdoc->getForm()->getRootNode().getValueByName(soundName, (sheetRoot+".Sound").c_str()); +// _SoundFilterPane.SetWindowText((string("Edit Sound Filters ")+soundName).c_str()); + + for (uint i=0; i<32; ++i) + { + char tmp[128]; + sprintf(tmp, "%02u", i); + + pdoc->getForm()->getRootNode().getValueByName(val, (sheetRoot+".Filter"+tmp).c_str()); + GetDlgItem(FILTER_EDIT[i])->EnableWindow(TRUE); + static_cast(GetDlgItem(FILTER_EDIT[i]))->SetCheck(val ? 1 : 0); + } + + // set the name of the sub sound + string s; + pdoc->getForm()->getRootNode().getValueByName(s, (sheetRoot+".Sound").c_str()); + + _SubSoundName = s.c_str(); + UpdateData(FALSE); + GetDlgItem(IDC_SUB_SOUND_NAME)->EnableWindow(TRUE); + + valid = true; + } + } + } + } + } + + if (!valid) + { + for (uint i=0; i<32; ++i) + { + GetDlgItem(FILTER_EDIT[i])->EnableWindow(FALSE); + } + GetDlgItem(IDC_SUB_SOUND_NAME)->EnableWindow(FALSE); + + _Index = -1; + } +} + +void CPageBgFlags::updateData(bool updateEditFilter) +{ + _recurse = true; + // update the filter flags and simulation status + if (_Index != -1 && updateEditFilter) + { + // filter edition is valid, update them + for (uint i=0; i<32; ++i) + { + bool state = static_cast(GetDlgItem(FILTER_EDIT[i]))->GetCheck() == 1; + + char path[1024]; + sprintf(path, ".SoundType.Sounds[%u].Filter%02u", _Index, i); + SoundDialog->getSoundPlugin()->getActiveDocument()->setValue(state ? "true" : "false", path); + } + SoundDialog->getSoundPlugin()->getActiveDocument()->refreshView(); + } + + // simulation filters + NLSOUND::UAudioMixer::TBackgroundFlags flags; + for (uint i=0; i<32; ++i) + { + flags.Flags[i] = static_cast(GetDlgItem(FILTER_SIM[i]))->GetCheck() == 1; + } + SoundDialog->getSoundPlugin()->getMixer()->setBackgroundFlags(flags); + + _recurse = false; +} + + + +BOOL CPageBgFlags::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // update filter labels and state + const NLSOUND::UAudioMixer::TBackgroundFlags &flag = SoundDialog->getSoundPlugin()->getMixer()->getBackgroundFlags(); + for (uint i=0; i<32; ++i) + { + GetDlgItem(FILTER_EDIT_NAME[i])->SetWindowText(SoundDialog->EnvNames[i].Name.c_str()); + GetDlgItem(FILTER_SIM_NAME[i])->SetWindowText(SoundDialog->EnvNames[i].ShortName.c_str()); + + static_cast(GetDlgItem(FILTER_SIM[i]))->SetCheck(flag.Flags[i] ? 1 : 0); + } + + // force an update of the dialog state + onDocChanged(); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFlags.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFlags.h index 6e5c2488c..147eb06c3 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFlags.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageBgFlags.h @@ -1,85 +1,85 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_PAGEBGFLAGS_H__302480C3_66F1_460C_BC59_B468ACBD55B2__INCLUDED_) -#define AFX_PAGEBGFLAGS_H__302480C3_66F1_460C_BC59_B468ACBD55B2__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// PageBgFlags.h : header file -// -#include "nel/misc/types_nl.h" -#include "PageBase.h" - -///////////////////////////////////////////////////////////////////////////// -// CPageBgFlags dialog - -class CPageBgFlags : public CPageBase -{ - DECLARE_DYNCREATE(CPageBgFlags) - - // called by the master dialog when doc change - void onDocChanged(); - - // called by this dialog when data must be updated - void updateData(bool updateEditFilter); - - - /// Index of the current edited sound the the background - sint _Index; - /// Flag to block updating will modifying - bool _recurse; - -// Construction -public: - CPageBgFlags() {} - CPageBgFlags(NLGEORGES::CSoundDialog *soundDialog); - ~CPageBgFlags(); - -// Dialog Data - //{{AFX_DATA(CPageBgFlags) - enum { IDD = IDD_PAGE_BG_FLAGS }; - CString _SubSoundName; - //}}AFX_DATA - - -// Overrides - // ClassWizard generate virtual function overrides - //{{AFX_VIRTUAL(CPageBgFlags) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - //}}AFX_VIRTUAL - -// Implementation -protected: - // Generated message map functions - //{{AFX_MSG(CPageBgFlags) - afx_msg void OnBtnEditAllOn(); - afx_msg void OnBtnEditAllOff(); - afx_msg void OnBtnEnvAllOff(); - afx_msg void OnBtnEnvAllOn(); - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_PAGEBGFLAGS_H__302480C3_66F1_460C_BC59_B468ACBD55B2__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_PAGEBGFLAGS_H__302480C3_66F1_460C_BC59_B468ACBD55B2__INCLUDED_) +#define AFX_PAGEBGFLAGS_H__302480C3_66F1_460C_BC59_B468ACBD55B2__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PageBgFlags.h : header file +// +#include "nel/misc/types_nl.h" +#include "PageBase.h" + +///////////////////////////////////////////////////////////////////////////// +// CPageBgFlags dialog + +class CPageBgFlags : public CPageBase +{ + DECLARE_DYNCREATE(CPageBgFlags) + + // called by the master dialog when doc change + void onDocChanged(); + + // called by this dialog when data must be updated + void updateData(bool updateEditFilter); + + + /// Index of the current edited sound the the background + sint _Index; + /// Flag to block updating will modifying + bool _recurse; + +// Construction +public: + CPageBgFlags() {} + CPageBgFlags(NLGEORGES::CSoundDialog *soundDialog); + ~CPageBgFlags(); + +// Dialog Data + //{{AFX_DATA(CPageBgFlags) + enum { IDD = IDD_PAGE_BG_FLAGS }; + CString _SubSoundName; + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CPageBgFlags) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CPageBgFlags) + afx_msg void OnBtnEditAllOn(); + afx_msg void OnBtnEditAllOff(); + afx_msg void OnBtnEnvAllOff(); + afx_msg void OnBtnEnvAllOn(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PAGEBGFLAGS_H__302480C3_66F1_460C_BC59_B468ACBD55B2__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComplex.cpp b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComplex.cpp index 07c5c1bac..b69ea8614 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComplex.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComplex.cpp @@ -1,170 +1,170 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// PageComplex.cpp : implementation file -// - -#include "std_sound_plugin.h" -#include "sound_document_plugin.h" -#include - -#include "PageComplex.h" - -using namespace std; - -///////////////////////////////////////////////////////////////////////////// -// CPageComplex property page - -#undef new -IMPLEMENT_DYNCREATE(CPageComplex, CPageBase) -#define new NL_NEW - -CPageComplex::CPageComplex(NLGEORGES::CSoundDialog *soundDialog) : CPageBase(soundDialog, CPageComplex::IDD) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - //{{AFX_DATA_INIT(CPageComplex) - _SequenceSize = 0; - _MaxDelay = 0; - _MinDelay = 0; - //}}AFX_DATA_INIT -} - -CPageComplex::~CPageComplex() -{ -} - -void CPageComplex::DoDataExchange(CDataExchange* pDX) -{ - CPropertyPage::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CPageComplex) - DDX_Control(pDX, IDC_BTN_RANDOM_SOUND, _BtnRandomSound); - DDX_Control(pDX, IDC_BTN_RANDOM_DELAY, _BtnRandomDelay); - DDX_Text(pDX, IDC_EDIT_SEQ_SIZE, _SequenceSize); - DDX_Text(pDX, IDC_EDIT_MAX_DELAY, _MaxDelay); - DDX_Text(pDX, IDC_EDIT_MIN_DELAY, _MinDelay); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CPageComplex, CPropertyPage) - //{{AFX_MSG_MAP(CPageComplex) - ON_BN_CLICKED(IDC_BTN_RANDOM_DELAY, OnBtnRandomDelay) - ON_BN_CLICKED(IDC_BTN_RANDOM_SOUND, OnBtnRandomSound) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CPageComplex message handlers - -void CPageComplex::OnBtnRandomDelay() -{ - UpdateData(TRUE); - nldebug("Random sound : size = %u, min = %u, max = %u", _SequenceSize, _MinDelay, _MaxDelay); - - if (_MinDelay < 0) - { - _MinDelay = 0; - UpdateData(FALSE); - } - - if (_MaxDelay < _MinDelay) - { - _MaxDelay = _MinDelay+1; - UpdateData(FALSE); - } - - NLGEORGES::IEditDocument *pdoc = SoundDialog->getSoundPlugin()->getActiveDocument(); - - if (pdoc != NULL) - { - // create a delay list. - string seq; - - for (sint i=0; i<_SequenceSize; ++i) - { - char tmp[200]; - sprintf(tmp, "%u", _MinDelay + rand()%((_MaxDelay+1)-_MinDelay)); - seq += string(tmp)+";"; - } - pdoc->setValue(seq.c_str(), ".SoundType.DelaySeq"); - pdoc->refreshView(); - } -} - -void CPageComplex::OnBtnRandomSound() -{ - UpdateData(TRUE); - nldebug("Random sound : size = %u, min = %u, max = %u", _SequenceSize, _MinDelay, _MaxDelay); - - NLGEORGES::IEditDocument *pdoc = SoundDialog->getSoundPlugin()->getActiveDocument(); - - if (pdoc != NULL) - { - // create a sound list. - NLGEORGES::UFormElm *psoundsArray; - pdoc->getForm()->getRootNode().getNodeByName(&psoundsArray, ".SoundType.SoundList"); - - if (psoundsArray != NULL) - { - uint size; - psoundsArray->getArraySize(size); - - string seq; - - for (sint i=0; i<_SequenceSize; ++i) - { - char tmp[200]; - sprintf(tmp, "%u", rand()%size); - seq += string(tmp)+";"; - } - pdoc->setValue(seq.c_str(), ".SoundType.SoundSeq"); - pdoc->refreshView(); - } - } -} - -void CPageComplex::onDocChanged() -{ - // the document have been modified, update the dialog - NLGEORGES::IEditDocument *pdoc = SoundDialog->getSoundPlugin()->getActiveDocument(); - - bool valid = false; - - if (pdoc != NULL) - { - string type, dfnName; - NLGEORGES::UFormElm *psoundType; - - pdoc->getForm()->getRootNode().getNodeByName(&psoundType, ".SoundType"); - - if (psoundType != NULL) - { - psoundType->getDfnName(dfnName); - if (dfnName == "complex_sound.dfn") - { - _BtnRandomDelay.EnableWindow(TRUE); - _BtnRandomSound.EnableWindow(TRUE); - valid = true; - } - } - } - - if (!valid) - { - _BtnRandomDelay.EnableWindow(FALSE); - _BtnRandomSound.EnableWindow(FALSE); - } +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// PageComplex.cpp : implementation file +// + +#include "std_sound_plugin.h" +#include "sound_document_plugin.h" +#include + +#include "PageComplex.h" + +using namespace std; + +///////////////////////////////////////////////////////////////////////////// +// CPageComplex property page + +#undef new +IMPLEMENT_DYNCREATE(CPageComplex, CPageBase) +#define new NL_NEW + +CPageComplex::CPageComplex(NLGEORGES::CSoundDialog *soundDialog) : CPageBase(soundDialog, CPageComplex::IDD) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + //{{AFX_DATA_INIT(CPageComplex) + _SequenceSize = 0; + _MaxDelay = 0; + _MinDelay = 0; + //}}AFX_DATA_INIT +} + +CPageComplex::~CPageComplex() +{ +} + +void CPageComplex::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPageComplex) + DDX_Control(pDX, IDC_BTN_RANDOM_SOUND, _BtnRandomSound); + DDX_Control(pDX, IDC_BTN_RANDOM_DELAY, _BtnRandomDelay); + DDX_Text(pDX, IDC_EDIT_SEQ_SIZE, _SequenceSize); + DDX_Text(pDX, IDC_EDIT_MAX_DELAY, _MaxDelay); + DDX_Text(pDX, IDC_EDIT_MIN_DELAY, _MinDelay); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CPageComplex, CPropertyPage) + //{{AFX_MSG_MAP(CPageComplex) + ON_BN_CLICKED(IDC_BTN_RANDOM_DELAY, OnBtnRandomDelay) + ON_BN_CLICKED(IDC_BTN_RANDOM_SOUND, OnBtnRandomSound) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPageComplex message handlers + +void CPageComplex::OnBtnRandomDelay() +{ + UpdateData(TRUE); + nldebug("Random sound : size = %u, min = %u, max = %u", _SequenceSize, _MinDelay, _MaxDelay); + + if (_MinDelay < 0) + { + _MinDelay = 0; + UpdateData(FALSE); + } + + if (_MaxDelay < _MinDelay) + { + _MaxDelay = _MinDelay+1; + UpdateData(FALSE); + } + + NLGEORGES::IEditDocument *pdoc = SoundDialog->getSoundPlugin()->getActiveDocument(); + + if (pdoc != NULL) + { + // create a delay list. + string seq; + + for (sint i=0; i<_SequenceSize; ++i) + { + char tmp[200]; + sprintf(tmp, "%u", _MinDelay + rand()%((_MaxDelay+1)-_MinDelay)); + seq += string(tmp)+";"; + } + pdoc->setValue(seq.c_str(), ".SoundType.DelaySeq"); + pdoc->refreshView(); + } +} + +void CPageComplex::OnBtnRandomSound() +{ + UpdateData(TRUE); + nldebug("Random sound : size = %u, min = %u, max = %u", _SequenceSize, _MinDelay, _MaxDelay); + + NLGEORGES::IEditDocument *pdoc = SoundDialog->getSoundPlugin()->getActiveDocument(); + + if (pdoc != NULL) + { + // create a sound list. + NLGEORGES::UFormElm *psoundsArray; + pdoc->getForm()->getRootNode().getNodeByName(&psoundsArray, ".SoundType.SoundList"); + + if (psoundsArray != NULL) + { + uint size; + psoundsArray->getArraySize(size); + + string seq; + + for (sint i=0; i<_SequenceSize; ++i) + { + char tmp[200]; + sprintf(tmp, "%u", rand()%size); + seq += string(tmp)+";"; + } + pdoc->setValue(seq.c_str(), ".SoundType.SoundSeq"); + pdoc->refreshView(); + } + } +} + +void CPageComplex::onDocChanged() +{ + // the document have been modified, update the dialog + NLGEORGES::IEditDocument *pdoc = SoundDialog->getSoundPlugin()->getActiveDocument(); + + bool valid = false; + + if (pdoc != NULL) + { + string type, dfnName; + NLGEORGES::UFormElm *psoundType; + + pdoc->getForm()->getRootNode().getNodeByName(&psoundType, ".SoundType"); + + if (psoundType != NULL) + { + psoundType->getDfnName(dfnName); + if (dfnName == "complex_sound.dfn") + { + _BtnRandomDelay.EnableWindow(TRUE); + _BtnRandomSound.EnableWindow(TRUE); + valid = true; + } + } + } + + if (!valid) + { + _BtnRandomDelay.EnableWindow(FALSE); + _BtnRandomSound.EnableWindow(FALSE); + } } \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComplex.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComplex.h index 26ee864de..eaa28a365 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComplex.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComplex.h @@ -1,74 +1,74 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_PAGECOMPLEX_H__6EB5AE57_5E13_4028_9985_04EF86FB7AE6__INCLUDED_) -#define AFX_PAGECOMPLEX_H__6EB5AE57_5E13_4028_9985_04EF86FB7AE6__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// PageComplex.h : header file -// -#include "PageBase.h" - -///////////////////////////////////////////////////////////////////////////// -// CPageComplex dialog - -class CPageComplex : public CPageBase -{ - DECLARE_DYNCREATE(CPageComplex) - - void onDocChanged(); - -// Construction -public: - CPageComplex(){} - CPageComplex(NLGEORGES::CSoundDialog *soundDialog); - ~CPageComplex(); - -// Dialog Data - //{{AFX_DATA(CPageComplex) - enum { IDD = IDD_PAGE_COMPLEX }; - CButton _BtnRandomSound; - CButton _BtnRandomDelay; - int _SequenceSize; - int _MaxDelay; - int _MinDelay; - //}}AFX_DATA - - -// Overrides - // ClassWizard generate virtual function overrides - //{{AFX_VIRTUAL(CPageComplex) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - // Generated message map functions - //{{AFX_MSG(CPageComplex) - afx_msg void OnBtnRandomDelay(); - afx_msg void OnBtnRandomSound(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_PAGECOMPLEX_H__6EB5AE57_5E13_4028_9985_04EF86FB7AE6__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_PAGECOMPLEX_H__6EB5AE57_5E13_4028_9985_04EF86FB7AE6__INCLUDED_) +#define AFX_PAGECOMPLEX_H__6EB5AE57_5E13_4028_9985_04EF86FB7AE6__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PageComplex.h : header file +// +#include "PageBase.h" + +///////////////////////////////////////////////////////////////////////////// +// CPageComplex dialog + +class CPageComplex : public CPageBase +{ + DECLARE_DYNCREATE(CPageComplex) + + void onDocChanged(); + +// Construction +public: + CPageComplex(){} + CPageComplex(NLGEORGES::CSoundDialog *soundDialog); + ~CPageComplex(); + +// Dialog Data + //{{AFX_DATA(CPageComplex) + enum { IDD = IDD_PAGE_COMPLEX }; + CButton _BtnRandomSound; + CButton _BtnRandomDelay; + int _SequenceSize; + int _MaxDelay; + int _MinDelay; + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CPageComplex) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CPageComplex) + afx_msg void OnBtnRandomDelay(); + afx_msg void OnBtnRandomSound(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PAGECOMPLEX_H__6EB5AE57_5E13_4028_9985_04EF86FB7AE6__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComtext.cpp b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComtext.cpp index 3cf64c4f1..46856b955 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComtext.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComtext.cpp @@ -1,105 +1,105 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// PageComtext.cpp : implementation file -// - -#include "std_sound_plugin.h" -#include "georges_plugin_sound.h" -#include -#include "PageComtext.h" - -using namespace std; - -uint EDIT_ARG_ID [] = -{ - IDC_EDIT_ARG_0, - IDC_EDIT_ARG_1, - IDC_EDIT_ARG_2, - IDC_EDIT_ARG_3, - IDC_EDIT_ARG_4, - IDC_EDIT_ARG_5, - IDC_EDIT_ARG_6, - IDC_EDIT_ARG_7, - IDC_EDIT_ARG_8, - IDC_EDIT_ARG_9 -}; - -map EDIT_ARG_IDX; - -///////////////////////////////////////////////////////////////////////////// -// CPageComtext property page - -#undef new -IMPLEMENT_DYNCREATE(CPageComtext, CPageBase) -#define new NL_NEW - -CPageComtext::CPageComtext(NLGEORGES::CSoundDialog *soundDialog) : CPageBase(soundDialog, CPageComtext::IDD) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - //{{AFX_DATA_INIT(CPageComtext) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT - - for (uint i =0; i<10; ++i) - { - EDIT_ARG_IDX.insert(make_pair(EDIT_ARG_ID[i], i)); - - // init the context sound vars - SoundContext.Args[i] = 0; - } -} - -CPageComtext::~CPageComtext() -{ -} - -void CPageComtext::DoDataExchange(CDataExchange* pDX) -{ - CPropertyPage::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CPageComtext) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CPageComtext, CPropertyPage) - //{{AFX_MSG_MAP(CPageComtext) - // NOTE: the ClassWizard will add message map macros here - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CPageComtext message handlers - -BOOL CPageComtext::OnCommand(WPARAM wParam, LPARAM lParam) -{ - if (lParam != 0 && HIWORD(wParam) == EN_CHANGE) - { - int id = ::GetDlgCtrlID(HWND(lParam)); - // command come from a control - if (EDIT_ARG_IDX.find(id) != EDIT_ARG_IDX.end()) - { - // need to update the var. - char tmp[1024]; - GetDlgItem(id)->GetWindowText(tmp, 1024); - SoundContext.Args[EDIT_ARG_IDX[id]] = atoi(tmp); - } - } - - return CPropertyPage::OnCommand(wParam, lParam); -} - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// PageComtext.cpp : implementation file +// + +#include "std_sound_plugin.h" +#include "georges_plugin_sound.h" +#include +#include "PageComtext.h" + +using namespace std; + +uint EDIT_ARG_ID [] = +{ + IDC_EDIT_ARG_0, + IDC_EDIT_ARG_1, + IDC_EDIT_ARG_2, + IDC_EDIT_ARG_3, + IDC_EDIT_ARG_4, + IDC_EDIT_ARG_5, + IDC_EDIT_ARG_6, + IDC_EDIT_ARG_7, + IDC_EDIT_ARG_8, + IDC_EDIT_ARG_9 +}; + +map EDIT_ARG_IDX; + +///////////////////////////////////////////////////////////////////////////// +// CPageComtext property page + +#undef new +IMPLEMENT_DYNCREATE(CPageComtext, CPageBase) +#define new NL_NEW + +CPageComtext::CPageComtext(NLGEORGES::CSoundDialog *soundDialog) : CPageBase(soundDialog, CPageComtext::IDD) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + //{{AFX_DATA_INIT(CPageComtext) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + for (uint i =0; i<10; ++i) + { + EDIT_ARG_IDX.insert(make_pair(EDIT_ARG_ID[i], i)); + + // init the context sound vars + SoundContext.Args[i] = 0; + } +} + +CPageComtext::~CPageComtext() +{ +} + +void CPageComtext::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPageComtext) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CPageComtext, CPropertyPage) + //{{AFX_MSG_MAP(CPageComtext) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPageComtext message handlers + +BOOL CPageComtext::OnCommand(WPARAM wParam, LPARAM lParam) +{ + if (lParam != 0 && HIWORD(wParam) == EN_CHANGE) + { + int id = ::GetDlgCtrlID(HWND(lParam)); + // command come from a control + if (EDIT_ARG_IDX.find(id) != EDIT_ARG_IDX.end()) + { + // need to update the var. + char tmp[1024]; + GetDlgItem(id)->GetWindowText(tmp, 1024); + SoundContext.Args[EDIT_ARG_IDX[id]] = atoi(tmp); + } + } + + return CPropertyPage::OnCommand(wParam, lParam); +} + diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComtext.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComtext.h index 3c99f9089..ce8599f32 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComtext.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageComtext.h @@ -1,73 +1,73 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_PAGECOMTEXT_H__C904D249_575F_460D_9E6B_F3D814B65873__INCLUDED_) -#define AFX_PAGECOMTEXT_H__C904D249_575F_460D_9E6B_F3D814B65873__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// PageComtext.h : header file -// -#include "nel/sound/u_audio_mixer.h" -#include "PageBase.h" - -///////////////////////////////////////////////////////////////////////////// -// CPageComtext dialog - -class CPageComtext : public CPageBase -{ - DECLARE_DYNCREATE(CPageComtext) - -// Construction -public: - CPageComtext(){} - CPageComtext(NLGEORGES::CSoundDialog *soundDialog); - ~CPageComtext(); - - /// The current sound context. - NLSOUND::CSoundContext SoundContext; - -// Dialog Data - //{{AFX_DATA(CPageComtext) - enum { IDD = IDD_PAGE_CONTEXT }; - // NOTE - ClassWizard will add data members here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_DATA - - -// Overrides - // ClassWizard generate virtual function overrides - //{{AFX_VIRTUAL(CPageComtext) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - //}}AFX_VIRTUAL - -// Implementation -protected: - // Generated message map functions - //{{AFX_MSG(CPageComtext) - // NOTE: the ClassWizard will add member functions here - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_PAGECOMTEXT_H__C904D249_575F_460D_9E6B_F3D814B65873__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_PAGECOMTEXT_H__C904D249_575F_460D_9E6B_F3D814B65873__INCLUDED_) +#define AFX_PAGECOMTEXT_H__C904D249_575F_460D_9E6B_F3D814B65873__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PageComtext.h : header file +// +#include "nel/sound/u_audio_mixer.h" +#include "PageBase.h" + +///////////////////////////////////////////////////////////////////////////// +// CPageComtext dialog + +class CPageComtext : public CPageBase +{ + DECLARE_DYNCREATE(CPageComtext) + +// Construction +public: + CPageComtext(){} + CPageComtext(NLGEORGES::CSoundDialog *soundDialog); + ~CPageComtext(); + + /// The current sound context. + NLSOUND::CSoundContext SoundContext; + +// Dialog Data + //{{AFX_DATA(CPageComtext) + enum { IDD = IDD_PAGE_CONTEXT }; + // NOTE - ClassWizard will add data members here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CPageComtext) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CPageComtext) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PAGECOMTEXT_H__C904D249_575F_460D_9E6B_F3D814B65873__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/PagePosition.cpp b/code/ryzom/tools/leveldesign/georges_plugin_sound/PagePosition.cpp index 40e5ca1a4..e3cb73c1f 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/PagePosition.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/PagePosition.cpp @@ -1,134 +1,134 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// PagePosition.cpp : implementation file -// - -#include "std_sound_plugin.h" -#include "georges_plugin_sound.h" -#include "listener_view.h" -#include "sound_dialog.h" -#include "nel/georges/u_form_elm.h" -#include "sound_document_plugin.h" -#include "nel/sound/u_audio_mixer.h" -#include "nel/sound/sound.h" -#include "nel/sound/simple_sound.h" - -#include "PagePosition.h" - -using namespace std; - -///////////////////////////////////////////////////////////////////////////// -// CPagePosition property page - -#undef new -IMPLEMENT_DYNCREATE(CPagePosition, CPageBase) -#define new NL_NEW - -CPagePosition::CPagePosition(NLGEORGES::CSoundDialog *soundDialog) : CPageBase(soundDialog, CPagePosition::IDD) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - //{{AFX_DATA_INIT(CPagePosition) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -CPagePosition::~CPagePosition() -{ -} - -void CPagePosition::DoDataExchange(CDataExchange* pDX) -{ - CPropertyPage::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CPagePosition) - DDX_Control(pDX, IDC_PSEUDO_PICTURE, _Picture); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CPagePosition, CPropertyPage) - //{{AFX_MSG_MAP(CPagePosition) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CPagePosition message handlers - -BOOL CPagePosition::OnInitDialog() -{ - CPropertyPage::OnInitDialog(); - - // TODO: Add extra initialization here - // insert the listener position view inside the pseudo picture control. - WINDOWPLACEMENT place; - _Picture.GetWindowPlacement(&place); - - -#undef new - _ListenerView = new NLGEORGES::CListenerView(); -#define new NL_NEW - _ListenerView->init(SoundDialog->getSoundPlugin(), CRect(place.rcNormalPosition), this); - - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - - -void CPagePosition::onDocChanged() -{ -/* // the document have been modified, update the dialog - NLGEORGES::IEditDocument *pdoc = SoundDialog->getSoundPlugin()->getActiveDocument(); -*/ - bool valid = false; -/* - if (pdoc != NULL) - { - string type, dfnName; - - pdoc->getForm()->getRootNode().getDfnName(dfnName); - if (dfnName == "sound.dfn") - { -*/ NLSOUND::CSound *sound = SoundDialog->getSoundPlugin()->getSound(); - - if (sound != 0) - { - // the sound is available ! - float minDist = 1.0f; - _ListenerView->setAngles(uint32(180 * sound->getConeInnerAngle() / NLMISC::Pi), uint32(180 * sound->getConeOuterAngle() / NLMISC::Pi)); - if (sound->getSoundType() == NLSOUND::CSound::SOUND_SIMPLE) - { - _ListenerView->setAlpha(static_cast(sound)->getAlpha()); - _ListenerView->setShowAlpha(true); - minDist = static_cast(sound)->getMinDistance(); - } - else - _ListenerView->setShowAlpha(false); - - _ListenerView->setMinMaxDistances(minDist, sound->getMaxDistance()); - _ListenerView->setActive(true); - - valid = true; - } -/* } - } -*/ - if (!valid) - { - // not a sound file - _ListenerView->setActive(false); - } -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// PagePosition.cpp : implementation file +// + +#include "std_sound_plugin.h" +#include "georges_plugin_sound.h" +#include "listener_view.h" +#include "sound_dialog.h" +#include "nel/georges/u_form_elm.h" +#include "sound_document_plugin.h" +#include "nel/sound/u_audio_mixer.h" +#include "nel/sound/sound.h" +#include "nel/sound/simple_sound.h" + +#include "PagePosition.h" + +using namespace std; + +///////////////////////////////////////////////////////////////////////////// +// CPagePosition property page + +#undef new +IMPLEMENT_DYNCREATE(CPagePosition, CPageBase) +#define new NL_NEW + +CPagePosition::CPagePosition(NLGEORGES::CSoundDialog *soundDialog) : CPageBase(soundDialog, CPagePosition::IDD) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + //{{AFX_DATA_INIT(CPagePosition) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +CPagePosition::~CPagePosition() +{ +} + +void CPagePosition::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPagePosition) + DDX_Control(pDX, IDC_PSEUDO_PICTURE, _Picture); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CPagePosition, CPropertyPage) + //{{AFX_MSG_MAP(CPagePosition) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPagePosition message handlers + +BOOL CPagePosition::OnInitDialog() +{ + CPropertyPage::OnInitDialog(); + + // TODO: Add extra initialization here + // insert the listener position view inside the pseudo picture control. + WINDOWPLACEMENT place; + _Picture.GetWindowPlacement(&place); + + +#undef new + _ListenerView = new NLGEORGES::CListenerView(); +#define new NL_NEW + _ListenerView->init(SoundDialog->getSoundPlugin(), CRect(place.rcNormalPosition), this); + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +void CPagePosition::onDocChanged() +{ +/* // the document have been modified, update the dialog + NLGEORGES::IEditDocument *pdoc = SoundDialog->getSoundPlugin()->getActiveDocument(); +*/ + bool valid = false; +/* + if (pdoc != NULL) + { + string type, dfnName; + + pdoc->getForm()->getRootNode().getDfnName(dfnName); + if (dfnName == "sound.dfn") + { +*/ NLSOUND::CSound *sound = SoundDialog->getSoundPlugin()->getSound(); + + if (sound != 0) + { + // the sound is available ! + float minDist = 1.0f; + _ListenerView->setAngles(uint32(180 * sound->getConeInnerAngle() / NLMISC::Pi), uint32(180 * sound->getConeOuterAngle() / NLMISC::Pi)); + if (sound->getSoundType() == NLSOUND::CSound::SOUND_SIMPLE) + { + _ListenerView->setAlpha(static_cast(sound)->getAlpha()); + _ListenerView->setShowAlpha(true); + minDist = static_cast(sound)->getMinDistance(); + } + else + _ListenerView->setShowAlpha(false); + + _ListenerView->setMinMaxDistances(minDist, sound->getMaxDistance()); + _ListenerView->setActive(true); + + valid = true; + } +/* } + } +*/ + if (!valid) + { + // not a sound file + _ListenerView->setActive(false); + } +} diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/PagePosition.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/PagePosition.h index 1510c2ea8..2abd46dd2 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/PagePosition.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/PagePosition.h @@ -1,77 +1,77 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_PAGEPOSITION_H__234F9FB4_3803_4973_BC3D_8D398A9C438A__INCLUDED_) -#define AFX_PAGEPOSITION_H__234F9FB4_3803_4973_BC3D_8D398A9C438A__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// PagePosition.h : header file -// -#include "PageBase.h" - -namespace NLGEORGES -{ - class CListenerView; -} - - -///////////////////////////////////////////////////////////////////////////// -// CPagePosition dialog - -class CPagePosition : public CPageBase -{ - DECLARE_DYNCREATE(CPagePosition) - - void onDocChanged(); - -// Construction -public: - CPagePosition(){} - CPagePosition(NLGEORGES::CSoundDialog *soundDialog); - ~CPagePosition(); - -// Dialog Data - //{{AFX_DATA(CPagePosition) - enum { IDD = IDD_PAGE_POSITION }; - CStatic _Picture; - //}}AFX_DATA - - -// Overrides - // ClassWizard generate virtual function overrides - //{{AFX_VIRTUAL(CPagePosition) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - // Generated message map functions - //{{AFX_MSG(CPagePosition) - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - - NLGEORGES::CListenerView *_ListenerView; - -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_PAGEPOSITION_H__234F9FB4_3803_4973_BC3D_8D398A9C438A__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_PAGEPOSITION_H__234F9FB4_3803_4973_BC3D_8D398A9C438A__INCLUDED_) +#define AFX_PAGEPOSITION_H__234F9FB4_3803_4973_BC3D_8D398A9C438A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PagePosition.h : header file +// +#include "PageBase.h" + +namespace NLGEORGES +{ + class CListenerView; +} + + +///////////////////////////////////////////////////////////////////////////// +// CPagePosition dialog + +class CPagePosition : public CPageBase +{ + DECLARE_DYNCREATE(CPagePosition) + + void onDocChanged(); + +// Construction +public: + CPagePosition(){} + CPagePosition(NLGEORGES::CSoundDialog *soundDialog); + ~CPagePosition(); + +// Dialog Data + //{{AFX_DATA(CPagePosition) + enum { IDD = IDD_PAGE_POSITION }; + CStatic _Picture; + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CPagePosition) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CPagePosition) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + NLGEORGES::CListenerView *_ListenerView; + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PAGEPOSITION_H__234F9FB4_3803_4973_BC3D_8D398A9C438A__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageSimple.cpp b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageSimple.cpp index 69e14a074..decd2baca 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageSimple.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageSimple.cpp @@ -1,135 +1,135 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// PageSimple.cpp : implementation file -// - -#include "std_sound_plugin.h" -#include "georges_plugin_sound.h" -#include "georges_plugin_sound.h" -#include "nel/georges/u_form_elm.h" -#include "sound_document_plugin.h" -#include -#include "PageSimple.h" - -using namespace std; - -///////////////////////////////////////////////////////////////////////////// -// CPageSimple property page - -#undef new -IMPLEMENT_DYNCREATE(CPageSimple, CPageBase) -#define new NL_NEW - -CPageSimple::CPageSimple(NLGEORGES::CSoundDialog *soundDialog) : CPageBase(soundDialog, CPageSimple::IDD) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - //{{AFX_DATA_INIT(CPageSimple) - _AudioFormat = _T(""); - _Filename = _T(""); - _Filesize = _T(""); - //}}AFX_DATA_INIT -} - -CPageSimple::~CPageSimple() -{ -} - -void CPageSimple::onDocChanged() -{ - // the document have been modified, update the dialog - NLGEORGES::IEditDocument *pdoc = SoundDialog->getSoundPlugin()->getActiveDocument(); - - bool valid = false; - - if (pdoc != NULL) - { - string type, dfnName; - NLGEORGES::UFormElm *psoundType; - - pdoc->getForm()->getRootNode().getNodeByName(&psoundType, ".SoundType"); - - if (psoundType != NULL) - { - psoundType->getDfnName(dfnName); - if (dfnName == "simple_sound.dfn") - { - uint sampleRate, sampleSize, channels, size; - string filename; - char s[256]; - - psoundType->getValueByName(filename, "Filename"); - - - if (SoundDialog->getFileInfo(filename, sampleRate, sampleSize, channels, size)) - { - -/* if (channels > 1) - { - ::MessageBox(NULL, "3D sounds accept only mono files", _Name.c_str(), MB_OK); - } -*/ -// _Name = _Name.c_str()); - -// SetWindowText((_Name.empty()) ? "Sound plugin" : _Name.c_str()); - _Filename = filename.c_str(); - - _snprintf(s, 256, "%s / %d bits / %d Hz", (channels == 1)? "mono" : "stereo", sampleSize, sampleRate); - _AudioFormat = s; - - _snprintf(s, 256, "%d kb", size / 1024); - _Filesize = s; - - UpdateData(FALSE); - valid = true; - } - } - } - } - - if (!valid) - { - // This is not a valid simple sound... - _AudioFormat = ""; - _Filename = ""; - _Filesize = ""; - UpdateData(FALSE); - } -} - - -void CPageSimple::DoDataExchange(CDataExchange* pDX) -{ - CPropertyPage::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CPageSimple) - DDX_Control(pDX, IDC_FILESIZE, _FilesizeCtrl); - DDX_Control(pDX, IDC_FILENAME, _FilenameCtrl); - DDX_Control(pDX, IDC_AUDIOFORMAT, _AudioFormatCtrl); - DDX_Text(pDX, IDC_AUDIOFORMAT, _AudioFormat); - DDX_Text(pDX, IDC_FILENAME, _Filename); - DDX_Text(pDX, IDC_FILESIZE, _Filesize); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CPageSimple, CPropertyPage) - //{{AFX_MSG_MAP(CPageSimple) - // NOTE: the ClassWizard will add message map macros here - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CPageSimple message handlers +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// PageSimple.cpp : implementation file +// + +#include "std_sound_plugin.h" +#include "georges_plugin_sound.h" +#include "georges_plugin_sound.h" +#include "nel/georges/u_form_elm.h" +#include "sound_document_plugin.h" +#include +#include "PageSimple.h" + +using namespace std; + +///////////////////////////////////////////////////////////////////////////// +// CPageSimple property page + +#undef new +IMPLEMENT_DYNCREATE(CPageSimple, CPageBase) +#define new NL_NEW + +CPageSimple::CPageSimple(NLGEORGES::CSoundDialog *soundDialog) : CPageBase(soundDialog, CPageSimple::IDD) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + //{{AFX_DATA_INIT(CPageSimple) + _AudioFormat = _T(""); + _Filename = _T(""); + _Filesize = _T(""); + //}}AFX_DATA_INIT +} + +CPageSimple::~CPageSimple() +{ +} + +void CPageSimple::onDocChanged() +{ + // the document have been modified, update the dialog + NLGEORGES::IEditDocument *pdoc = SoundDialog->getSoundPlugin()->getActiveDocument(); + + bool valid = false; + + if (pdoc != NULL) + { + string type, dfnName; + NLGEORGES::UFormElm *psoundType; + + pdoc->getForm()->getRootNode().getNodeByName(&psoundType, ".SoundType"); + + if (psoundType != NULL) + { + psoundType->getDfnName(dfnName); + if (dfnName == "simple_sound.dfn") + { + uint sampleRate, sampleSize, channels, size; + string filename; + char s[256]; + + psoundType->getValueByName(filename, "Filename"); + + + if (SoundDialog->getFileInfo(filename, sampleRate, sampleSize, channels, size)) + { + +/* if (channels > 1) + { + ::MessageBox(NULL, "3D sounds accept only mono files", _Name.c_str(), MB_OK); + } +*/ +// _Name = _Name.c_str()); + +// SetWindowText((_Name.empty()) ? "Sound plugin" : _Name.c_str()); + _Filename = filename.c_str(); + + _snprintf(s, 256, "%s / %d bits / %d Hz", (channels == 1)? "mono" : "stereo", sampleSize, sampleRate); + _AudioFormat = s; + + _snprintf(s, 256, "%d kb", size / 1024); + _Filesize = s; + + UpdateData(FALSE); + valid = true; + } + } + } + } + + if (!valid) + { + // This is not a valid simple sound... + _AudioFormat = ""; + _Filename = ""; + _Filesize = ""; + UpdateData(FALSE); + } +} + + +void CPageSimple::DoDataExchange(CDataExchange* pDX) +{ + CPropertyPage::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPageSimple) + DDX_Control(pDX, IDC_FILESIZE, _FilesizeCtrl); + DDX_Control(pDX, IDC_FILENAME, _FilenameCtrl); + DDX_Control(pDX, IDC_AUDIOFORMAT, _AudioFormatCtrl); + DDX_Text(pDX, IDC_AUDIOFORMAT, _AudioFormat); + DDX_Text(pDX, IDC_FILENAME, _Filename); + DDX_Text(pDX, IDC_FILESIZE, _Filesize); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CPageSimple, CPropertyPage) + //{{AFX_MSG_MAP(CPageSimple) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CPageSimple message handlers diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageSimple.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageSimple.h index 935f33acb..e6bb53b41 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/PageSimple.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/PageSimple.h @@ -1,75 +1,75 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_PAGESIMPLE_H__21AC2079_9B99_4F63_AFC8_4DFF4930E31D__INCLUDED_) -#define AFX_PAGESIMPLE_H__21AC2079_9B99_4F63_AFC8_4DFF4930E31D__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// PageSimple.h : header file -// - -#include "PageBase.h" - -///////////////////////////////////////////////////////////////////////////// -// CPageSimple dialog - -class CPageSimple : public CPageBase -{ - DECLARE_DYNCREATE(CPageSimple) - - void onDocChanged(); - -// Construction -public: - CPageSimple() {} - CPageSimple(NLGEORGES::CSoundDialog *soundDialog); - ~CPageSimple(); - -// Dialog Data - //{{AFX_DATA(CPageSimple) - enum { IDD = IDD_PAGE_SIMPLE }; - CStatic _FilesizeCtrl; - CStatic _FilenameCtrl; - CStatic _AudioFormatCtrl; - CString _AudioFormat; - CString _Filename; - CString _Filesize; - //}}AFX_DATA - - -// Overrides - // ClassWizard generate virtual function overrides - //{{AFX_VIRTUAL(CPageSimple) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - // Generated message map functions - //{{AFX_MSG(CPageSimple) - // NOTE: the ClassWizard will add member functions here - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_PAGESIMPLE_H__21AC2079_9B99_4F63_AFC8_4DFF4930E31D__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_PAGESIMPLE_H__21AC2079_9B99_4F63_AFC8_4DFF4930E31D__INCLUDED_) +#define AFX_PAGESIMPLE_H__21AC2079_9B99_4F63_AFC8_4DFF4930E31D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// PageSimple.h : header file +// + +#include "PageBase.h" + +///////////////////////////////////////////////////////////////////////////// +// CPageSimple dialog + +class CPageSimple : public CPageBase +{ + DECLARE_DYNCREATE(CPageSimple) + + void onDocChanged(); + +// Construction +public: + CPageSimple() {} + CPageSimple(NLGEORGES::CSoundDialog *soundDialog); + ~CPageSimple(); + +// Dialog Data + //{{AFX_DATA(CPageSimple) + enum { IDD = IDD_PAGE_SIMPLE }; + CStatic _FilesizeCtrl; + CStatic _FilenameCtrl; + CStatic _AudioFormatCtrl; + CString _AudioFormat; + CString _Filename; + CString _Filesize; + //}}AFX_DATA + + +// Overrides + // ClassWizard generate virtual function overrides + //{{AFX_VIRTUAL(CPageSimple) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + // Generated message map functions + //{{AFX_MSG(CPageSimple) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PAGESIMPLE_H__21AC2079_9B99_4F63_AFC8_4DFF4930E31D__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/georges_plugin_sound.cpp b/code/ryzom/tools/leveldesign/georges_plugin_sound/georges_plugin_sound.cpp index af2eb04c2..292b008ed 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/georges_plugin_sound.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/georges_plugin_sound.cpp @@ -1,63 +1,63 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// georges_plugin_test.cpp : Defines the initialization routines for the DLL. -// - -#include "std_sound_plugin.h" -#include "georges_plugin_sound.h" -#include "sound_plugin.h" - - -using namespace NLGEORGES; -using namespace std; - - -// *************************************************************************** - -NLMISC::CLibraryContext *LibContext = NULL; - - -__declspec( dllexport ) IEditPlugin *IGeorgesEditGetInterface (int version, NLGEORGES::IEdit *globalInterface, NLMISC::INelContext &nelContext) -{ - // init the library nel context - if (LibContext == NULL) - { - LibContext = new NLMISC::CLibraryContext(nelContext); - } - - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - // Same version ? - if (version == NLGEORGES_PLUGIN_INTERFACE_VERSION) - { - try - { - return new CSoundPlugin(globalInterface); - } - catch (std::exception &e) - { - string reason = e.what(); - MessageBox (NULL, reason.c_str(), "Sound plugin", MB_OK); - return NULL; - } - } - else - { - MessageBox (NULL, "Plugin version invalid.", "Sound plugin for georges editor", MB_OK|MB_ICONEXCLAMATION); - return NULL; - } - -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// georges_plugin_test.cpp : Defines the initialization routines for the DLL. +// + +#include "std_sound_plugin.h" +#include "georges_plugin_sound.h" +#include "sound_plugin.h" + + +using namespace NLGEORGES; +using namespace std; + + +// *************************************************************************** + +NLMISC::CLibraryContext *LibContext = NULL; + + +__declspec( dllexport ) IEditPlugin *IGeorgesEditGetInterface (int version, NLGEORGES::IEdit *globalInterface, NLMISC::INelContext &nelContext) +{ + // init the library nel context + if (LibContext == NULL) + { + LibContext = new NLMISC::CLibraryContext(nelContext); + } + + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + // Same version ? + if (version == NLGEORGES_PLUGIN_INTERFACE_VERSION) + { + try + { + return new CSoundPlugin(globalInterface); + } + catch (std::exception &e) + { + string reason = e.what(); + MessageBox (NULL, reason.c_str(), "Sound plugin", MB_OK); + return NULL; + } + } + else + { + MessageBox (NULL, "Plugin version invalid.", "Sound plugin for georges editor", MB_OK|MB_ICONEXCLAMATION); + return NULL; + } + +} diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/georges_plugin_sound.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/georges_plugin_sound.h index befdd9169..cc451f4ff 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/georges_plugin_sound.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/georges_plugin_sound.h @@ -1,25 +1,25 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// georges_plugin_test.h : main header file for the GEORGES_PLUGIN_TEST DLL -// - -#if !defined(AFX_GEORGES_PLUGIN_TEST_H__17C63138_6057_4288_99B4_D1158EE798CA__INCLUDED_) -#define AFX_GEORGES_PLUGIN_TEST_H__17C63138_6057_4288_99B4_D1158EE798CA__INCLUDED_ - - - -#endif // !defined(AFX_GEORGES_PLUGIN_TEST_H__17C63138_6057_4288_99B4_D1158EE798CA__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// georges_plugin_test.h : main header file for the GEORGES_PLUGIN_TEST DLL +// + +#if !defined(AFX_GEORGES_PLUGIN_TEST_H__17C63138_6057_4288_99B4_D1158EE798CA__INCLUDED_) +#define AFX_GEORGES_PLUGIN_TEST_H__17C63138_6057_4288_99B4_D1158EE798CA__INCLUDED_ + + + +#endif // !defined(AFX_GEORGES_PLUGIN_TEST_H__17C63138_6057_4288_99B4_D1158EE798CA__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/listener_view.cpp b/code/ryzom/tools/leveldesign/georges_plugin_sound/listener_view.cpp index 7352be953..78d8d0ce8 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/listener_view.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/listener_view.cpp @@ -1,315 +1,315 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "listener_view.h" -#include "sound_document_plugin.h" -#include "nel/misc/debug.h" -#include "nel/misc/path.h" -#include "nel/misc/vector.h" -#include -#include - -using namespace std; -using namespace NLMISC; - -namespace NLGEORGES -{ - - -#undef new -IMPLEMENT_DYNCREATE(CListenerView, CView) -#define new NL_NEW - -BEGIN_MESSAGE_MAP(CListenerView, CView) - //{{AFX_MSG_MAP(CListenerView) - ON_WM_LBUTTONDOWN() - ON_WM_LBUTTONUP() - ON_WM_MOUSEMOVE() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -bool CListenerView::_Registered = false; -CString CListenerView::_WndClass; -uint CListenerView::_WndId = 0; -CFont CListenerView::_Font; -CBrush CListenerView::_InnerBrush; -CBrush CListenerView::_OuterBrush; -CBrush CListenerView::_ListenerBrush; -CPen CListenerView::_VolumeCurve; - - - -// *************************************************************************** - -bool CListenerView::registerClass() -{ - if (_Registered) - { - return true; - } - - try - { - LPCTSTR className = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW, ::LoadCursor(NULL, IDC_ARROW), (HBRUSH) ::GetStockObject(WHITE_BRUSH)); - _WndClass = className; - } - catch (CResourceException* e) - { - AfxMessageBox("Couldn't register class! (Already registered?)"); - e->Delete(); - return false; - } - - - _OuterBrush.CreateSolidBrush(RGB(255, 0, 0)); - _InnerBrush.CreateSolidBrush(RGB(0, 255, 0)); - _ListenerBrush.CreateSolidBrush(RGB(0, 0, 0)); - _VolumeCurve.CreatePen(PS_SOLID, 1, RGB(255, 0, 128)); - - _Font.CreateFont(14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, - CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial"); - - return true; -} - - -// *************************************************************************** - -void CListenerView::init(CSoundPlugin* plugin, CRect& rect, CWnd* parent) -{ - - registerClass(); - - _Plugin = plugin; - _Listener.SetRect(-1, -1, -1, -1); - _Cones.SetRect(0, 0, 0, 0); - _OuterAngle = 360; - _InnerAngle = 360; - - if (!Create((LPCTSTR) _WndClass, "Listener", WS_CHILD | WS_VISIBLE, rect, parent, ++_WndId)) - { - throw exception("failed to create the listener view"); - } - - EnableWindow (); - ShowWindow(SW_SHOW); -} - -// *************************************************************************** - -void CListenerView::OnLButtonDown(UINT nFlags, CPoint point) -{ - if (_Listener.PtInRect(point)) - { - _DragOrigine = point; - _ListenerOrigine = _Listener.CenterPoint(); - _Dragging = true; - } -} - -// *************************************************************************** - -void CListenerView::OnLButtonUp(UINT nFlags, CPoint point) -{ - if (_Dragging) - { - _Dragging = false; - } -} - -// *************************************************************************** - -void CListenerView::OnMouseMove(UINT nFlags, CPoint point) -{ - if (_Dragging) - { - CVector pos; - CPoint center = _ListenerOrigine + point - _DragOrigine; - CRect updateRect = _Listener; - _Listener.SetRect(center.x - 5, center.y - 5, center.x + 5, center.y + 5); - //updateRect |= _Listener; - //InvalidateRect(&updateRect); - Invalidate(); - - center = _Cones.CenterPoint(); - CPoint listener = _Listener.CenterPoint(); - - CRect rect; - GetClientRect(&rect); - uint fullHeight = rect.bottom - center.y; - uint fullWidth = rect.right - center.x; - - _X = _MaxDist * (listener.x - center.x) / fullHeight; - _Y = (_MaxDist * (listener.y - center.y) / fullHeight); - - pos.set(_X, _Y, 0.0f); - - //nldebug("position=(%.2f, %.2f)", _X, _Y); - - _Plugin->setListenerPos(pos); - _Plugin->setListenerOrientation(CVector(0,1,0), CVector(0,0,1)); - } -} - -// *************************************************************************** - -void CListenerView::OnDraw(CDC* dc) -{ - CRect rect; - - GetClientRect(&rect); - - dc->Rectangle(rect); - - // Initialize the position of the rectangle on the first call to draw - if (_Listener.top < 0) - { - CPoint c = rect.CenterPoint(); - _Listener.SetRect(c.x - 5, rect.top + 25, c.x + 5, rect.top + 35); - _Cones.SetRect(c.x - 20, rect.top + 10, c.x + 20, rect.top + 50); - } - - - if (_Activated) - { - CPoint center = _Cones.CenterPoint(); - - CBrush *oldBrush = dc->SelectObject(&_OuterBrush); - - double angle = NLMISC::Pi * (360.0 - _OuterAngle) / 2.0 / 180.0; - dc->Pie(_Cones, - CPoint((int) (center.x - 10.0 * sin(angle)), (int) (center.y - 10.0 * cos(angle))), - CPoint((int) (center.x + 10.0 * sin(angle)), (int) (center.y - 10.0 * cos(angle)))); - - dc->SelectObject(&_InnerBrush); - - angle = NLMISC::Pi * (360.0 - _InnerAngle) / 2.0 / 180.0; - dc->Pie(_Cones, - CPoint((int) (center.x - 15.0 * sin(angle)), (int) (center.y - 15.0 * cos(angle))), - CPoint((int) (center.x + 15.0 * sin(angle)), (int) (center.y - 15.0 * cos(angle)))); - - dc->SelectObject(&_ListenerBrush); - //dc->Ellipse(_Listener); - - CPoint pts[4]; - pts[0].x = _Listener.left; - pts[0].y = _Listener.bottom; - - pts[1].x = _Listener.right; - pts[1].y = _Listener.bottom; - - pts[2].x = (_Listener.left + _Listener.right) / 2; - pts[2].y = _Listener.top; - - pts[3].x = _Listener.left; - pts[3].y = _Listener.bottom; - - - dc->Polygon(pts, 4); - - dc->SelectObject(oldBrush); - - char s[256]; - _snprintf(s, 256, "%.1f, %.1f", _X, _Y); - - CFont* oldFont = dc->SelectObject(&_Font); - dc->DrawText(s, rect, DT_VCENTER | DT_SINGLELINE | DT_CENTER); - dc->SelectObject(oldFont); - - CPen* oldPen = dc->SelectObject(&_VolumeCurve); - - // Draw the volume curve - CPoint c = _Cones.CenterPoint(); - uint fullHeight = rect.bottom - c.y; - uint fullWidth = rect.right - c.x; - - // Draw the min distance - uint minDistHeight = (uint)(((float) fullHeight * _MinDist) / _MaxDist); - - CPoint p = c; - dc->MoveTo(p); - p.y += minDistHeight; - dc->LineTo(p); - - - if (_ShowAlpha) - { - // calculate the curve in 10 intervals - double dx = (_MaxDist - _MinDist) / 100.0; - double x = _MinDist; - - for (uint i = 0; i < 101; i++) - { - double y; - - // linearly descending volume on a dB scale - double db1 = -100.0 * (x - _MinDist) / (_MaxDist - _MinDist); - - if (_Alpha == 0.0) - { - y = db1; - - } - else if (_Alpha > 0.0) - { - double amp2 = 0.0001 + 0.9999 * (_MaxDist - x) / (_MaxDist - _MinDist); // linear amp between 0.00001 and 1.0 - double db2 = 20. * log10(amp2); - y = ((1.0 - _Alpha) * db1 + _Alpha * db2); - - } - else if (_Alpha < 0.0) - { - double amp3 = _MinDist / x; // linear amplitude is 1/distance - double db3 = 20.0 * log10(amp3); - y = ((1.0 + _Alpha) * db1 - _Alpha * db3); - } - - clamp(y, -100, 0); - - p.x = c.x + (uint)(fullWidth * (y / -100.0)); - p.y = c.y + (uint)(fullHeight * (x / _MaxDist)); - dc->LineTo(p); - - x += dx; - } - } - - dc->SelectObject(oldPen); - } -} - - -#ifdef _DEBUG - -// *************************************************************************** - -void CListenerView::AssertValid() const -{ - CView::AssertValid(); -} - -// *************************************************************************** - -void CListenerView::Dump(CDumpContext& dc) const -{ - CView::Dump(dc); -} - -#endif //_DEBUG - - -} // namespace NLGEORGES - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "listener_view.h" +#include "sound_document_plugin.h" +#include "nel/misc/debug.h" +#include "nel/misc/path.h" +#include "nel/misc/vector.h" +#include +#include + +using namespace std; +using namespace NLMISC; + +namespace NLGEORGES +{ + + +#undef new +IMPLEMENT_DYNCREATE(CListenerView, CView) +#define new NL_NEW + +BEGIN_MESSAGE_MAP(CListenerView, CView) + //{{AFX_MSG_MAP(CListenerView) + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_MOUSEMOVE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +bool CListenerView::_Registered = false; +CString CListenerView::_WndClass; +uint CListenerView::_WndId = 0; +CFont CListenerView::_Font; +CBrush CListenerView::_InnerBrush; +CBrush CListenerView::_OuterBrush; +CBrush CListenerView::_ListenerBrush; +CPen CListenerView::_VolumeCurve; + + + +// *************************************************************************** + +bool CListenerView::registerClass() +{ + if (_Registered) + { + return true; + } + + try + { + LPCTSTR className = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW, ::LoadCursor(NULL, IDC_ARROW), (HBRUSH) ::GetStockObject(WHITE_BRUSH)); + _WndClass = className; + } + catch (CResourceException* e) + { + AfxMessageBox("Couldn't register class! (Already registered?)"); + e->Delete(); + return false; + } + + + _OuterBrush.CreateSolidBrush(RGB(255, 0, 0)); + _InnerBrush.CreateSolidBrush(RGB(0, 255, 0)); + _ListenerBrush.CreateSolidBrush(RGB(0, 0, 0)); + _VolumeCurve.CreatePen(PS_SOLID, 1, RGB(255, 0, 128)); + + _Font.CreateFont(14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, "Arial"); + + return true; +} + + +// *************************************************************************** + +void CListenerView::init(CSoundPlugin* plugin, CRect& rect, CWnd* parent) +{ + + registerClass(); + + _Plugin = plugin; + _Listener.SetRect(-1, -1, -1, -1); + _Cones.SetRect(0, 0, 0, 0); + _OuterAngle = 360; + _InnerAngle = 360; + + if (!Create((LPCTSTR) _WndClass, "Listener", WS_CHILD | WS_VISIBLE, rect, parent, ++_WndId)) + { + throw exception("failed to create the listener view"); + } + + EnableWindow (); + ShowWindow(SW_SHOW); +} + +// *************************************************************************** + +void CListenerView::OnLButtonDown(UINT nFlags, CPoint point) +{ + if (_Listener.PtInRect(point)) + { + _DragOrigine = point; + _ListenerOrigine = _Listener.CenterPoint(); + _Dragging = true; + } +} + +// *************************************************************************** + +void CListenerView::OnLButtonUp(UINT nFlags, CPoint point) +{ + if (_Dragging) + { + _Dragging = false; + } +} + +// *************************************************************************** + +void CListenerView::OnMouseMove(UINT nFlags, CPoint point) +{ + if (_Dragging) + { + CVector pos; + CPoint center = _ListenerOrigine + point - _DragOrigine; + CRect updateRect = _Listener; + _Listener.SetRect(center.x - 5, center.y - 5, center.x + 5, center.y + 5); + //updateRect |= _Listener; + //InvalidateRect(&updateRect); + Invalidate(); + + center = _Cones.CenterPoint(); + CPoint listener = _Listener.CenterPoint(); + + CRect rect; + GetClientRect(&rect); + uint fullHeight = rect.bottom - center.y; + uint fullWidth = rect.right - center.x; + + _X = _MaxDist * (listener.x - center.x) / fullHeight; + _Y = (_MaxDist * (listener.y - center.y) / fullHeight); + + pos.set(_X, _Y, 0.0f); + + //nldebug("position=(%.2f, %.2f)", _X, _Y); + + _Plugin->setListenerPos(pos); + _Plugin->setListenerOrientation(CVector(0,1,0), CVector(0,0,1)); + } +} + +// *************************************************************************** + +void CListenerView::OnDraw(CDC* dc) +{ + CRect rect; + + GetClientRect(&rect); + + dc->Rectangle(rect); + + // Initialize the position of the rectangle on the first call to draw + if (_Listener.top < 0) + { + CPoint c = rect.CenterPoint(); + _Listener.SetRect(c.x - 5, rect.top + 25, c.x + 5, rect.top + 35); + _Cones.SetRect(c.x - 20, rect.top + 10, c.x + 20, rect.top + 50); + } + + + if (_Activated) + { + CPoint center = _Cones.CenterPoint(); + + CBrush *oldBrush = dc->SelectObject(&_OuterBrush); + + double angle = NLMISC::Pi * (360.0 - _OuterAngle) / 2.0 / 180.0; + dc->Pie(_Cones, + CPoint((int) (center.x - 10.0 * sin(angle)), (int) (center.y - 10.0 * cos(angle))), + CPoint((int) (center.x + 10.0 * sin(angle)), (int) (center.y - 10.0 * cos(angle)))); + + dc->SelectObject(&_InnerBrush); + + angle = NLMISC::Pi * (360.0 - _InnerAngle) / 2.0 / 180.0; + dc->Pie(_Cones, + CPoint((int) (center.x - 15.0 * sin(angle)), (int) (center.y - 15.0 * cos(angle))), + CPoint((int) (center.x + 15.0 * sin(angle)), (int) (center.y - 15.0 * cos(angle)))); + + dc->SelectObject(&_ListenerBrush); + //dc->Ellipse(_Listener); + + CPoint pts[4]; + pts[0].x = _Listener.left; + pts[0].y = _Listener.bottom; + + pts[1].x = _Listener.right; + pts[1].y = _Listener.bottom; + + pts[2].x = (_Listener.left + _Listener.right) / 2; + pts[2].y = _Listener.top; + + pts[3].x = _Listener.left; + pts[3].y = _Listener.bottom; + + + dc->Polygon(pts, 4); + + dc->SelectObject(oldBrush); + + char s[256]; + _snprintf(s, 256, "%.1f, %.1f", _X, _Y); + + CFont* oldFont = dc->SelectObject(&_Font); + dc->DrawText(s, rect, DT_VCENTER | DT_SINGLELINE | DT_CENTER); + dc->SelectObject(oldFont); + + CPen* oldPen = dc->SelectObject(&_VolumeCurve); + + // Draw the volume curve + CPoint c = _Cones.CenterPoint(); + uint fullHeight = rect.bottom - c.y; + uint fullWidth = rect.right - c.x; + + // Draw the min distance + uint minDistHeight = (uint)(((float) fullHeight * _MinDist) / _MaxDist); + + CPoint p = c; + dc->MoveTo(p); + p.y += minDistHeight; + dc->LineTo(p); + + + if (_ShowAlpha) + { + // calculate the curve in 10 intervals + double dx = (_MaxDist - _MinDist) / 100.0; + double x = _MinDist; + + for (uint i = 0; i < 101; i++) + { + double y; + + // linearly descending volume on a dB scale + double db1 = -100.0 * (x - _MinDist) / (_MaxDist - _MinDist); + + if (_Alpha == 0.0) + { + y = db1; + + } + else if (_Alpha > 0.0) + { + double amp2 = 0.0001 + 0.9999 * (_MaxDist - x) / (_MaxDist - _MinDist); // linear amp between 0.00001 and 1.0 + double db2 = 20. * log10(amp2); + y = ((1.0 - _Alpha) * db1 + _Alpha * db2); + + } + else if (_Alpha < 0.0) + { + double amp3 = _MinDist / x; // linear amplitude is 1/distance + double db3 = 20.0 * log10(amp3); + y = ((1.0 + _Alpha) * db1 - _Alpha * db3); + } + + clamp(y, -100, 0); + + p.x = c.x + (uint)(fullWidth * (y / -100.0)); + p.y = c.y + (uint)(fullHeight * (x / _MaxDist)); + dc->LineTo(p); + + x += dx; + } + } + + dc->SelectObject(oldPen); + } +} + + +#ifdef _DEBUG + +// *************************************************************************** + +void CListenerView::AssertValid() const +{ + CView::AssertValid(); +} + +// *************************************************************************** + +void CListenerView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +#endif //_DEBUG + + +} // namespace NLGEORGES + diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/listener_view.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/listener_view.h index 51f286812..01f0b0067 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/listener_view.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/listener_view.h @@ -1,113 +1,113 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef _NLGEORGES_LISTENER_VIEW_H -#define _NLGEORGES_LISTENER_VIEW_H - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "std_sound_plugin.h" -#include "../georges_dll/plugin_interface.h" - - -namespace NLGEORGES -{ - -class CSoundPlugin; - - -class CListenerView : public CView -{ -public: - - CListenerView() : CView(), _Dragging(false), _Activated(false), _X(0), _Y(0) {} - virtual ~CListenerView() {}; - - void init(CSoundPlugin* plugin, CRect& rect, CWnd* parent); - void setAngles(uint32 inner, uint32 outer) { _InnerAngle = inner; _OuterAngle = outer; Invalidate(); } - void setActive(bool active) { _Activated = active; Invalidate(); } - void setShowAlpha(bool showAlpha) { _ShowAlpha = showAlpha; Invalidate(); } - void setAlpha(double alpha) { _Alpha = alpha; Invalidate(); } - void setMinMaxDistances(float mindist, float maxdist) { _MinDist = mindist; _MaxDist = maxdist; Invalidate(); } - - -protected: - - static bool registerClass(); - static bool _Registered; - static CString _WndClass; - static uint _WndId; - static CFont _Font; - static CBrush _InnerBrush; - static CBrush _OuterBrush; - static CBrush _ListenerBrush; - static CPen _VolumeCurve; - - CSoundPlugin *_Plugin; - CRect _Listener; - CRect _Cones; - uint32 _InnerAngle; - uint32 _OuterAngle; - bool _Dragging; - CPoint _DragOrigine; - CPoint _ListenerOrigine; - bool _Activated; - bool _ShowAlpha; - float _X; - float _Y; - float _MinDist; - float _MaxDist; - double _Alpha; - - -// MFC crap -public: - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CListenerView) - protected: - virtual void OnDraw(CDC* pDC); // overridden to draw this view - //}}AFX_VIRTUAL - -// Implementation -protected: -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - - DECLARE_DYNCREATE(CListenerView) - - // Generated message map functions - //{{AFX_MSG(CListenerView) - afx_msg void OnLButtonDown(UINT nFlags, CPoint point); - afx_msg void OnLButtonUp(UINT nFlags, CPoint point); - afx_msg void OnMouseMove(UINT nFlags, CPoint point); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -} // namespace NLGEORGES - - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // _NLGEORGES_LISTENER_VIEW_H +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef _NLGEORGES_LISTENER_VIEW_H +#define _NLGEORGES_LISTENER_VIEW_H + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "std_sound_plugin.h" +#include "../georges_dll/plugin_interface.h" + + +namespace NLGEORGES +{ + +class CSoundPlugin; + + +class CListenerView : public CView +{ +public: + + CListenerView() : CView(), _Dragging(false), _Activated(false), _X(0), _Y(0) {} + virtual ~CListenerView() {}; + + void init(CSoundPlugin* plugin, CRect& rect, CWnd* parent); + void setAngles(uint32 inner, uint32 outer) { _InnerAngle = inner; _OuterAngle = outer; Invalidate(); } + void setActive(bool active) { _Activated = active; Invalidate(); } + void setShowAlpha(bool showAlpha) { _ShowAlpha = showAlpha; Invalidate(); } + void setAlpha(double alpha) { _Alpha = alpha; Invalidate(); } + void setMinMaxDistances(float mindist, float maxdist) { _MinDist = mindist; _MaxDist = maxdist; Invalidate(); } + + +protected: + + static bool registerClass(); + static bool _Registered; + static CString _WndClass; + static uint _WndId; + static CFont _Font; + static CBrush _InnerBrush; + static CBrush _OuterBrush; + static CBrush _ListenerBrush; + static CPen _VolumeCurve; + + CSoundPlugin *_Plugin; + CRect _Listener; + CRect _Cones; + uint32 _InnerAngle; + uint32 _OuterAngle; + bool _Dragging; + CPoint _DragOrigine; + CPoint _ListenerOrigine; + bool _Activated; + bool _ShowAlpha; + float _X; + float _Y; + float _MinDist; + float _MaxDist; + double _Alpha; + + +// MFC crap +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CListenerView) + protected: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + //}}AFX_VIRTUAL + +// Implementation +protected: +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + DECLARE_DYNCREATE(CListenerView) + + // Generated message map functions + //{{AFX_MSG(CListenerView) + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +} // namespace NLGEORGES + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // _NLGEORGES_LISTENER_VIEW_H diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/loading_dialog.cpp b/code/ryzom/tools/leveldesign/georges_plugin_sound/loading_dialog.cpp index 4727419ee..371a107bd 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/loading_dialog.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/loading_dialog.cpp @@ -1,54 +1,54 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// LoadingDialog.cpp : implementation file -// - -#include "std_sound_plugin.h" -#include "georges_plugin_sound.h" -#include "loading_dialog.h" - - -///////////////////////////////////////////////////////////////////////////// -// CLoadingDialog dialog - - -CLoadingDialog::CLoadingDialog(CWnd* pParent /*=NULL*/) - : CDialog(CLoadingDialog::IDD, pParent) -{ - //{{AFX_DATA_INIT(CLoadingDialog) - Message = _T(""); - //}}AFX_DATA_INIT -} - - -void CLoadingDialog::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CLoadingDialog) - DDX_Text(pDX, IDC_STATIC_MESSAGE, Message); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CLoadingDialog, CDialog) - //{{AFX_MSG_MAP(CLoadingDialog) - // NOTE: the ClassWizard will add message map macros here - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CLoadingDialog message handlers +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// LoadingDialog.cpp : implementation file +// + +#include "std_sound_plugin.h" +#include "georges_plugin_sound.h" +#include "loading_dialog.h" + + +///////////////////////////////////////////////////////////////////////////// +// CLoadingDialog dialog + + +CLoadingDialog::CLoadingDialog(CWnd* pParent /*=NULL*/) + : CDialog(CLoadingDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CLoadingDialog) + Message = _T(""); + //}}AFX_DATA_INIT +} + + +void CLoadingDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLoadingDialog) + DDX_Text(pDX, IDC_STATIC_MESSAGE, Message); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLoadingDialog, CDialog) + //{{AFX_MSG_MAP(CLoadingDialog) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLoadingDialog message handlers diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/loading_dialog.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/loading_dialog.h index 8dc7c3bf2..adca151c1 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/loading_dialog.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/loading_dialog.h @@ -1,62 +1,62 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_LOADINGDIALOG_H__0E1DE2CA_958F_4A0D_BE90_9264F6DB6F5C__INCLUDED_) -#define AFX_LOADINGDIALOG_H__0E1DE2CA_958F_4A0D_BE90_9264F6DB6F5C__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// LoadingDialog.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CLoadingDialog dialog - -class CLoadingDialog : public CDialog -{ -// Construction -public: - CLoadingDialog(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CLoadingDialog) - enum { IDD = IDD_DIALOG_LOADING }; - CString Message; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CLoadingDialog) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CLoadingDialog) - // NOTE: the ClassWizard will add member functions here - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_LOADINGDIALOG_H__0E1DE2CA_958F_4A0D_BE90_9264F6DB6F5C__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_LOADINGDIALOG_H__0E1DE2CA_958F_4A0D_BE90_9264F6DB6F5C__INCLUDED_) +#define AFX_LOADINGDIALOG_H__0E1DE2CA_958F_4A0D_BE90_9264F6DB6F5C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LoadingDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLoadingDialog dialog + +class CLoadingDialog : public CDialog +{ +// Construction +public: + CLoadingDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CLoadingDialog) + enum { IDD = IDD_DIALOG_LOADING }; + CString Message; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLoadingDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLoadingDialog) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LOADINGDIALOG_H__0E1DE2CA_958F_4A0D_BE90_9264F6DB6F5C__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/resource.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/resource.h index f60566568..d9115500d 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/resource.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/resource.h @@ -1,295 +1,295 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by georges_plugin_sound.rc -// -#define IDC_MESSAGE 1000 -#define IDD_TEST_GLOBAL 1001 -#define IDD_TEST_LOCAL 1002 -#define IDC_FILEINFO 1003 -#define IDC_FILENAME 1004 -#define IDC_FILEFORMAT 1005 -#define IDC_SOUNDFORMAT 1006 -#define IDC_NAME 1007 -#define IDB_START 1008 -#define IDC_CONTROL 1009 -#define IDB_STOP 1010 -#define IDC_NEW 1011 -#define IDC_FORMAT_LABEL 1012 -#define IDC_SIZE_LABEL 1013 -#define IDB_DESACTIVATED 1014 -#define IDC_FILE_LABEL 1015 -#define IDD_PAGE_CONTEXT 1015 -#define IDC_AUDIOFORMAT 1016 -#define IDD_PAGE_COMPLEX 1016 -#define IDB_NEW 1017 -#define IDD_PAGE_POSITION 1017 -#define IDC_FILESIZE 1018 -#define IDD_PAGE_SIMPLE 1018 -#define IDC_NAME_LABEL 1019 -#define IDD_PAGE_BG_FADES 1019 -#define IDC_TIME 1020 -#define IDD_DIALOG_LOADING 1021 -#define IDC_DURATION 1022 -#define IDD_CONTEXT_SOUND_PARAM 1023 -#define IDC_DIVIDER 1024 -#define IDB_CONTEXT 1025 -#define IDD_DIALOG_BG_FLAGS_2 1026 -#define IDD_PAGE_BG_FLAGS 1026 -#define IDC_SPIN1 1027 -#define IDC_ZOOM 1028 -#define IDC_EDIT_SEQ_SIZE 1029 -#define IDC_SPIN2 1030 -#define IDC_BTN_RANDOM_SOUND 1031 -#define IDC_SPIN3 1032 -#define IDC_EDIT_MIN_DELAY 1033 -#define IDC_SPIN4 1034 -#define IDC_EDIT_MAX_DELAY 1035 -#define IDC_SPIN5 1036 -#define IDC_BTN_RANDOM_DELAY 1037 -#define IDC_SPIN6 1038 -#define IDC_FILTER_00 1039 -#define IDC_SPIN7 1040 -#define IDC_FILTER_16 1040 -#define IDC_FILTER_01 1041 -#define IDC_SPIN8 1042 -#define IDC_FILTER_17 1042 -#define IDC_FILTER_02 1043 -#define IDC_SPIN9 1044 -#define IDC_FILTER_18 1044 -#define IDC_FILTER_03 1045 -#define IDC_SPIN10 1046 -#define IDC_FILTER_19 1046 -#define IDC_FILTER_04 1047 -#define IDC_FILTER_20 1048 -#define IDC_FILTER_05 1049 -#define IDC_FILTER_06 1050 -#define IDC_FILTER_07 1051 -#define IDC_FILTER_08 1052 -#define IDC_FILTER_09 1053 -#define IDC_FILTER_10 1054 -#define IDC_FILTER_11 1055 -#define IDC_FILTER_12 1056 -#define IDC_FILTER_13 1057 -#define IDC_FILTER_14 1058 -#define IDC_FILTER_15 1059 -#define IDC_ENV_FLAG_00 1060 -#define IDC_ENV_FLAG_01 1061 -#define IDC_ENV_FLAG_02 1062 -#define IDC_ENV_FLAG_03 1063 -#define IDC_ENV_FLAG_04 1064 -#define IDC_ENV_FLAG_05 1065 -#define IDC_ENV_FLAG_06 1066 -#define IDC_ENV_FLAG_07 1067 -#define IDC_ENV_FLAG_08 1068 -#define IDC_ENV_FLAG_09 1069 -#define IDC_ENV_FLAG_10 1070 -#define IDC_ENV_FLAG_11 1071 -#define IDC_ENV_FLAG_12 1072 -#define IDC_ENV_FLAG_13 1073 -#define IDC_ENV_FLAG_14 1074 -#define IDC_ENV_FLAG_15 1075 -#define IDC_FILTER_NAME_00 1076 -#define IDC_FILTER_NAME_01 1077 -#define IDC_STATIC_MESSAGE 1078 -#define IDC_FILTER_21 1078 -#define IDC_FILTER_NAME_02 1079 -#define IDC_BUTTON_RELOAD_SAMPLES 1080 -#define IDC_FILTER_22 1080 -#define IDC_FILTER_NAME_03 1081 -#define IDC_FILTER_NAME_04 1082 -#define IDC_FILTER_NAME_05 1083 -#define IDC_FILTER_NAME_06 1084 -#define IDC_BUTTON_RELOAD_SOUND_BANKS 1085 -#define IDC_FILTER_23 1085 -#define IDC_FILTER_NAME_07 1086 -#define IDC_FILTER_NAME_08 1087 -#define IDC_FILTER_NAME_09 1088 -#define IDC_FILTER_NAME_10 1089 -#define IDC_FILTER_NAME_11 1090 -#define IDC_FILTER_NAME_12 1091 -#define IDC_FILTER_NAME_13 1092 -#define IDC_FILTER_NAME_14 1093 -#define IDC_FILTER_NAME_15 1094 -#define IDC_ENV_NAME_00 1095 -#define IDC_ENV_NAME_01 1096 -#define IDC_ENV_NAME_02 1097 -#define IDC_ENV_NAME_03 1098 -#define IDC_ENV_NAME_04 1099 -#define IDC_ENV_NAME_05 1100 -#define IDC_ENV_NAME_06 1101 -#define IDC_ENV_NAME_07 1102 -#define IDC_ENV_NAME_08 1103 -#define IDC_ENV_NAME_09 1104 -#define IDC_ENV_NAME_10 1105 -#define IDC_ENV_NAME_11 1106 -#define IDC_ENV_NAME_12 1107 -#define IDC_ENV_NAME_13 1108 -#define IDC_ENV_NAME_14 1109 -#define IDC_ENV_NAME_15 1110 -#define IDC_EDIT_ARG_6 1110 -#define IDC_STATIC_SOUND_FILTER 1111 -#define IDC_FILTER_24 1111 -#define IDC_EDIT_ARG_0 1112 -#define IDC_FILTER_25 1112 -#define IDC_EDIT_ARG_1 1113 -#define IDC_FILTER_26 1113 -#define IDC_CHECK_CONTEXT_ARG 1114 -#define IDC_FILTER_27 1114 -#define IDC_EDIT_ARG_2 1115 -#define IDC_FILTER_28 1115 -#define IDC_TAB1 1116 -#define IDC_FILTER_29 1116 -#define IDC_EDIT_ARG_3 1117 -#define IDC_FILTER_30 1117 -#define IDC_EDIT_ARG_4 1118 -#define IDC_FILTER_31 1118 -#define IDC_EDIT_ARG_5 1119 -#define IDC_FILTER_NAME_16 1119 -#define IDC_FILTER_NAME_17 1120 -#define IDC_EDIT_ARG_7 1121 -#define IDC_FILTER_NAME_18 1121 -#define IDC_EDIT_ARG_8 1122 -#define IDC_FILTER_NAME_19 1122 -#define IDC_EDIT_ARG_9 1123 -#define IDC_FILTER_NAME_20 1123 -#define IDC_FILTER_NAME_21 1124 -#define IDC_FILTER_NAME_22 1125 -#define IDC_FILTER_NAME_23 1126 -#define IDC_FILTER_NAME_24 1127 -#define IDC_FILTER_NAME_25 1128 -#define IDC_FILTER_NAME_26 1129 -#define IDC_FILTER_NAME_27 1130 -#define IDC_FILTER_NAME_28 1131 -#define IDC_FILTER_NAME_29 1132 -#define IDC_FILTER_NAME_30 1133 -#define IDC_FILTER_NAME_31 1134 -#define IDC_ENV_FLAG_16 1135 -#define IDC_ENV_FLAG_17 1136 -#define IDC_ENV_FLAG_18 1137 -#define IDC_ENV_FLAG_19 1138 -#define IDC_ENV_FLAG_20 1139 -#define IDC_ENV_FLAG_21 1140 -#define IDC_ENV_FLAG_22 1141 -#define IDC_ENV_FLAG_23 1142 -#define IDC_ENV_FLAG_24 1143 -#define IDC_ENV_FLAG_25 1144 -#define IDC_ENV_FLAG_26 1145 -#define IDC_ENV_FLAG_27 1146 -#define IDC_ENV_FLAG_28 1147 -#define IDC_ENV_FLAG_29 1148 -#define IDC_ENV_FLAG_30 1149 -#define IDC_ENV_FLAG_31 1150 -#define IDC_ENV_NAME_16 1151 -#define IDC_ENV_NAME_17 1152 -#define IDC_ENV_NAME_18 1153 -#define IDC_ENV_NAME_19 1154 -#define IDC_ENV_NAME_20 1155 -#define IDC_ENV_NAME_21 1156 -#define IDC_ENV_NAME_22 1157 -#define IDC_ENV_NAME_23 1158 -#define IDC_ENV_NAME_24 1159 -#define IDC_ENV_NAME_25 1160 -#define IDC_ENV_NAME_26 1161 -#define IDC_ENV_NAME_27 1162 -#define IDC_ENV_NAME_28 1163 -#define IDC_ENV_NAME_29 1164 -#define IDC_ENV_NAME_30 1165 -#define IDC_ENV_NAME_31 1166 -#define IDC_BTN_EDIT_ALL_ON 1167 -#define IDC_BTN_EDIT_ALL_OFF 1168 -#define IDC_BTN_ENV_ALL_ON 1169 -#define IDC_BTN_ENV_ALL_OFF 1170 -#define IDC_SHEET_POS 1170 -#define IDC_FADE_IN_00 1171 -#define IDC_FADE_OUT_00 1172 -#define IDC_FADE_IN_08 1173 -#define IDC_FADE_OUT_08 1174 -#define IDC_FADE_IN_16 1175 -#define IDC_FADE_OUT_16 1176 -#define IDC_FADE_IN_01 1177 -#define IDC_FADE_OUT_01 1178 -#define IDC_FADE_IN_17 1179 -#define IDC_FADE_OUT_17 1180 -#define IDC_FADE_IN_02 1181 -#define IDC_FADE_OUT_02 1182 -#define IDC_FADE_IN_18 1183 -#define IDC_FADE_OUT_18 1184 -#define IDC_FADE_IN_03 1185 -#define IDC_FADE_OUT_03 1186 -#define IDC_FADE_IN_19 1187 -#define IDC_FADE_OUT_19 1188 -#define IDC_FADE_IN_04 1189 -#define IDC_FADE_OUT_04 1190 -#define IDC_FADE_IN_20 1191 -#define IDC_FADE_OUT_20 1192 -#define IDC_FADE_IN_05 1193 -#define IDC_FADE_OUT_05 1194 -#define IDC_FADE_IN_21 1195 -#define IDC_FADE_OUT_21 1196 -#define IDC_FADE_IN_06 1197 -#define IDC_FADE_OUT_06 1198 -#define IDC_FADE_IN_22 1199 -#define IDC_FADE_OUT_22 1200 -#define IDC_FADE_IN_07 1201 -#define IDC_FADE_OUT_07 1202 -#define IDC_FADE_IN_23 1203 -#define IDC_FADE_OUT_23 1204 -#define IDC_FADE_IN_24 1205 -#define IDC_FADE_OUT_24 1206 -#define IDC_FADE_IN_09 1207 -#define IDC_FADE_OUT_09 1208 -#define IDC_FADE_IN_25 1209 -#define IDC_FADE_OUT_25 1210 -#define IDC_FADE_IN_10 1211 -#define IDC_FADE_OUT_10 1212 -#define IDC_FADE_IN_26 1213 -#define IDC_FADE_OUT_26 1214 -#define IDC_FADE_IN_11 1215 -#define IDC_FADE_OUT_11 1216 -#define IDC_FADE_IN_27 1217 -#define IDC_FADE_OUT_27 1218 -#define IDC_FADE_IN_12 1219 -#define IDC_FADE_OUT_12 1220 -#define IDC_FADE_IN_28 1221 -#define IDC_FADE_OUT_28 1222 -#define IDC_FADE_IN_13 1223 -#define IDC_FADE_OUT_13 1224 -#define IDC_FADE_IN_29 1225 -#define IDC_FADE_OUT_29 1226 -#define IDC_FADE_IN_14 1227 -#define IDC_FADE_OUT_14 1228 -#define IDC_FADE_IN_30 1229 -#define IDC_FADE_OUT_30 1230 -#define IDC_FADE_IN_15 1231 -#define IDC_FADE_OUT_15 1232 -#define IDC_FADE_IN_31 1233 -#define IDC_FADE_OUT_31 1234 -#define IDC_PSEUDO_PICTURE 1244 -#define IDC_SUB_SOUND_NAME 1245 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 1021 -#define _APS_NEXT_COMMAND_VALUE 32773 -#define _APS_NEXT_CONTROL_VALUE 1246 -#define _APS_NEXT_SYMED_VALUE 1000 -#endif -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by georges_plugin_sound.rc +// +#define IDC_MESSAGE 1000 +#define IDD_TEST_GLOBAL 1001 +#define IDD_TEST_LOCAL 1002 +#define IDC_FILEINFO 1003 +#define IDC_FILENAME 1004 +#define IDC_FILEFORMAT 1005 +#define IDC_SOUNDFORMAT 1006 +#define IDC_NAME 1007 +#define IDB_START 1008 +#define IDC_CONTROL 1009 +#define IDB_STOP 1010 +#define IDC_NEW 1011 +#define IDC_FORMAT_LABEL 1012 +#define IDC_SIZE_LABEL 1013 +#define IDB_DESACTIVATED 1014 +#define IDC_FILE_LABEL 1015 +#define IDD_PAGE_CONTEXT 1015 +#define IDC_AUDIOFORMAT 1016 +#define IDD_PAGE_COMPLEX 1016 +#define IDB_NEW 1017 +#define IDD_PAGE_POSITION 1017 +#define IDC_FILESIZE 1018 +#define IDD_PAGE_SIMPLE 1018 +#define IDC_NAME_LABEL 1019 +#define IDD_PAGE_BG_FADES 1019 +#define IDC_TIME 1020 +#define IDD_DIALOG_LOADING 1021 +#define IDC_DURATION 1022 +#define IDD_CONTEXT_SOUND_PARAM 1023 +#define IDC_DIVIDER 1024 +#define IDB_CONTEXT 1025 +#define IDD_DIALOG_BG_FLAGS_2 1026 +#define IDD_PAGE_BG_FLAGS 1026 +#define IDC_SPIN1 1027 +#define IDC_ZOOM 1028 +#define IDC_EDIT_SEQ_SIZE 1029 +#define IDC_SPIN2 1030 +#define IDC_BTN_RANDOM_SOUND 1031 +#define IDC_SPIN3 1032 +#define IDC_EDIT_MIN_DELAY 1033 +#define IDC_SPIN4 1034 +#define IDC_EDIT_MAX_DELAY 1035 +#define IDC_SPIN5 1036 +#define IDC_BTN_RANDOM_DELAY 1037 +#define IDC_SPIN6 1038 +#define IDC_FILTER_00 1039 +#define IDC_SPIN7 1040 +#define IDC_FILTER_16 1040 +#define IDC_FILTER_01 1041 +#define IDC_SPIN8 1042 +#define IDC_FILTER_17 1042 +#define IDC_FILTER_02 1043 +#define IDC_SPIN9 1044 +#define IDC_FILTER_18 1044 +#define IDC_FILTER_03 1045 +#define IDC_SPIN10 1046 +#define IDC_FILTER_19 1046 +#define IDC_FILTER_04 1047 +#define IDC_FILTER_20 1048 +#define IDC_FILTER_05 1049 +#define IDC_FILTER_06 1050 +#define IDC_FILTER_07 1051 +#define IDC_FILTER_08 1052 +#define IDC_FILTER_09 1053 +#define IDC_FILTER_10 1054 +#define IDC_FILTER_11 1055 +#define IDC_FILTER_12 1056 +#define IDC_FILTER_13 1057 +#define IDC_FILTER_14 1058 +#define IDC_FILTER_15 1059 +#define IDC_ENV_FLAG_00 1060 +#define IDC_ENV_FLAG_01 1061 +#define IDC_ENV_FLAG_02 1062 +#define IDC_ENV_FLAG_03 1063 +#define IDC_ENV_FLAG_04 1064 +#define IDC_ENV_FLAG_05 1065 +#define IDC_ENV_FLAG_06 1066 +#define IDC_ENV_FLAG_07 1067 +#define IDC_ENV_FLAG_08 1068 +#define IDC_ENV_FLAG_09 1069 +#define IDC_ENV_FLAG_10 1070 +#define IDC_ENV_FLAG_11 1071 +#define IDC_ENV_FLAG_12 1072 +#define IDC_ENV_FLAG_13 1073 +#define IDC_ENV_FLAG_14 1074 +#define IDC_ENV_FLAG_15 1075 +#define IDC_FILTER_NAME_00 1076 +#define IDC_FILTER_NAME_01 1077 +#define IDC_STATIC_MESSAGE 1078 +#define IDC_FILTER_21 1078 +#define IDC_FILTER_NAME_02 1079 +#define IDC_BUTTON_RELOAD_SAMPLES 1080 +#define IDC_FILTER_22 1080 +#define IDC_FILTER_NAME_03 1081 +#define IDC_FILTER_NAME_04 1082 +#define IDC_FILTER_NAME_05 1083 +#define IDC_FILTER_NAME_06 1084 +#define IDC_BUTTON_RELOAD_SOUND_BANKS 1085 +#define IDC_FILTER_23 1085 +#define IDC_FILTER_NAME_07 1086 +#define IDC_FILTER_NAME_08 1087 +#define IDC_FILTER_NAME_09 1088 +#define IDC_FILTER_NAME_10 1089 +#define IDC_FILTER_NAME_11 1090 +#define IDC_FILTER_NAME_12 1091 +#define IDC_FILTER_NAME_13 1092 +#define IDC_FILTER_NAME_14 1093 +#define IDC_FILTER_NAME_15 1094 +#define IDC_ENV_NAME_00 1095 +#define IDC_ENV_NAME_01 1096 +#define IDC_ENV_NAME_02 1097 +#define IDC_ENV_NAME_03 1098 +#define IDC_ENV_NAME_04 1099 +#define IDC_ENV_NAME_05 1100 +#define IDC_ENV_NAME_06 1101 +#define IDC_ENV_NAME_07 1102 +#define IDC_ENV_NAME_08 1103 +#define IDC_ENV_NAME_09 1104 +#define IDC_ENV_NAME_10 1105 +#define IDC_ENV_NAME_11 1106 +#define IDC_ENV_NAME_12 1107 +#define IDC_ENV_NAME_13 1108 +#define IDC_ENV_NAME_14 1109 +#define IDC_ENV_NAME_15 1110 +#define IDC_EDIT_ARG_6 1110 +#define IDC_STATIC_SOUND_FILTER 1111 +#define IDC_FILTER_24 1111 +#define IDC_EDIT_ARG_0 1112 +#define IDC_FILTER_25 1112 +#define IDC_EDIT_ARG_1 1113 +#define IDC_FILTER_26 1113 +#define IDC_CHECK_CONTEXT_ARG 1114 +#define IDC_FILTER_27 1114 +#define IDC_EDIT_ARG_2 1115 +#define IDC_FILTER_28 1115 +#define IDC_TAB1 1116 +#define IDC_FILTER_29 1116 +#define IDC_EDIT_ARG_3 1117 +#define IDC_FILTER_30 1117 +#define IDC_EDIT_ARG_4 1118 +#define IDC_FILTER_31 1118 +#define IDC_EDIT_ARG_5 1119 +#define IDC_FILTER_NAME_16 1119 +#define IDC_FILTER_NAME_17 1120 +#define IDC_EDIT_ARG_7 1121 +#define IDC_FILTER_NAME_18 1121 +#define IDC_EDIT_ARG_8 1122 +#define IDC_FILTER_NAME_19 1122 +#define IDC_EDIT_ARG_9 1123 +#define IDC_FILTER_NAME_20 1123 +#define IDC_FILTER_NAME_21 1124 +#define IDC_FILTER_NAME_22 1125 +#define IDC_FILTER_NAME_23 1126 +#define IDC_FILTER_NAME_24 1127 +#define IDC_FILTER_NAME_25 1128 +#define IDC_FILTER_NAME_26 1129 +#define IDC_FILTER_NAME_27 1130 +#define IDC_FILTER_NAME_28 1131 +#define IDC_FILTER_NAME_29 1132 +#define IDC_FILTER_NAME_30 1133 +#define IDC_FILTER_NAME_31 1134 +#define IDC_ENV_FLAG_16 1135 +#define IDC_ENV_FLAG_17 1136 +#define IDC_ENV_FLAG_18 1137 +#define IDC_ENV_FLAG_19 1138 +#define IDC_ENV_FLAG_20 1139 +#define IDC_ENV_FLAG_21 1140 +#define IDC_ENV_FLAG_22 1141 +#define IDC_ENV_FLAG_23 1142 +#define IDC_ENV_FLAG_24 1143 +#define IDC_ENV_FLAG_25 1144 +#define IDC_ENV_FLAG_26 1145 +#define IDC_ENV_FLAG_27 1146 +#define IDC_ENV_FLAG_28 1147 +#define IDC_ENV_FLAG_29 1148 +#define IDC_ENV_FLAG_30 1149 +#define IDC_ENV_FLAG_31 1150 +#define IDC_ENV_NAME_16 1151 +#define IDC_ENV_NAME_17 1152 +#define IDC_ENV_NAME_18 1153 +#define IDC_ENV_NAME_19 1154 +#define IDC_ENV_NAME_20 1155 +#define IDC_ENV_NAME_21 1156 +#define IDC_ENV_NAME_22 1157 +#define IDC_ENV_NAME_23 1158 +#define IDC_ENV_NAME_24 1159 +#define IDC_ENV_NAME_25 1160 +#define IDC_ENV_NAME_26 1161 +#define IDC_ENV_NAME_27 1162 +#define IDC_ENV_NAME_28 1163 +#define IDC_ENV_NAME_29 1164 +#define IDC_ENV_NAME_30 1165 +#define IDC_ENV_NAME_31 1166 +#define IDC_BTN_EDIT_ALL_ON 1167 +#define IDC_BTN_EDIT_ALL_OFF 1168 +#define IDC_BTN_ENV_ALL_ON 1169 +#define IDC_BTN_ENV_ALL_OFF 1170 +#define IDC_SHEET_POS 1170 +#define IDC_FADE_IN_00 1171 +#define IDC_FADE_OUT_00 1172 +#define IDC_FADE_IN_08 1173 +#define IDC_FADE_OUT_08 1174 +#define IDC_FADE_IN_16 1175 +#define IDC_FADE_OUT_16 1176 +#define IDC_FADE_IN_01 1177 +#define IDC_FADE_OUT_01 1178 +#define IDC_FADE_IN_17 1179 +#define IDC_FADE_OUT_17 1180 +#define IDC_FADE_IN_02 1181 +#define IDC_FADE_OUT_02 1182 +#define IDC_FADE_IN_18 1183 +#define IDC_FADE_OUT_18 1184 +#define IDC_FADE_IN_03 1185 +#define IDC_FADE_OUT_03 1186 +#define IDC_FADE_IN_19 1187 +#define IDC_FADE_OUT_19 1188 +#define IDC_FADE_IN_04 1189 +#define IDC_FADE_OUT_04 1190 +#define IDC_FADE_IN_20 1191 +#define IDC_FADE_OUT_20 1192 +#define IDC_FADE_IN_05 1193 +#define IDC_FADE_OUT_05 1194 +#define IDC_FADE_IN_21 1195 +#define IDC_FADE_OUT_21 1196 +#define IDC_FADE_IN_06 1197 +#define IDC_FADE_OUT_06 1198 +#define IDC_FADE_IN_22 1199 +#define IDC_FADE_OUT_22 1200 +#define IDC_FADE_IN_07 1201 +#define IDC_FADE_OUT_07 1202 +#define IDC_FADE_IN_23 1203 +#define IDC_FADE_OUT_23 1204 +#define IDC_FADE_IN_24 1205 +#define IDC_FADE_OUT_24 1206 +#define IDC_FADE_IN_09 1207 +#define IDC_FADE_OUT_09 1208 +#define IDC_FADE_IN_25 1209 +#define IDC_FADE_OUT_25 1210 +#define IDC_FADE_IN_10 1211 +#define IDC_FADE_OUT_10 1212 +#define IDC_FADE_IN_26 1213 +#define IDC_FADE_OUT_26 1214 +#define IDC_FADE_IN_11 1215 +#define IDC_FADE_OUT_11 1216 +#define IDC_FADE_IN_27 1217 +#define IDC_FADE_OUT_27 1218 +#define IDC_FADE_IN_12 1219 +#define IDC_FADE_OUT_12 1220 +#define IDC_FADE_IN_28 1221 +#define IDC_FADE_OUT_28 1222 +#define IDC_FADE_IN_13 1223 +#define IDC_FADE_OUT_13 1224 +#define IDC_FADE_IN_29 1225 +#define IDC_FADE_OUT_29 1226 +#define IDC_FADE_IN_14 1227 +#define IDC_FADE_OUT_14 1228 +#define IDC_FADE_IN_30 1229 +#define IDC_FADE_OUT_30 1230 +#define IDC_FADE_IN_15 1231 +#define IDC_FADE_OUT_15 1232 +#define IDC_FADE_IN_31 1233 +#define IDC_FADE_OUT_31 1234 +#define IDC_PSEUDO_PICTURE 1244 +#define IDC_SUB_SOUND_NAME 1245 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 1021 +#define _APS_NEXT_COMMAND_VALUE 32773 +#define _APS_NEXT_CONTROL_VALUE 1246 +#define _APS_NEXT_SYMED_VALUE 1000 +#endif +#endif diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_dialog.cpp b/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_dialog.cpp index 06b92616c..e1f6b317c 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_dialog.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_dialog.cpp @@ -1,574 +1,574 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "std_sound_plugin.h" -#include "PageComplex.h" -#include "PageComtext.h" -#include "PageBgFlags.h" -#include "PageBgFades.h" -#include "PageSimple.h" -#include "PagePosition.h" - -#include "sound_dialog.h" - -#include "listener_view.h" -#include "sound_document_plugin.h" -#include "resource.h" -#include "nel/misc/debug.h" -#include "nel/misc/path.h" -#include "nel/georges/u_form_elm.h" -#include -#include - - -using namespace std; -using namespace NLMISC; - -namespace NLGEORGES -{ - -CBitmap CSoundDialog::_StopBitmap; -CBitmap CSoundDialog::_StartBitmap; -CBitmap CSoundDialog::_DesactivatedBitmap; -CBitmap CSoundDialog::_NewBitmap; -CBitmap CSoundDialog::_ContextBitmap; -CPen CSoundDialog::_Red; - - -BEGIN_MESSAGE_MAP(CSoundDialog, CDialog) - //{{AFX_MSG_MAP(CSoundDialog) - ON_WM_TIMER() - ON_WM_KEYUP() - ON_BN_CLICKED(IDC_CONTROL, OnControlPlayback) - ON_NOTIFY(UDN_DELTAPOS, IDC_ZOOM, OnZoom) - ON_BN_CLICKED(IDC_BUTTON_RELOAD_SAMPLES, OnReloadSamples) - ON_WM_DESTROY() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - - -CSoundDialog::CSoundDialog() -: CDialog(), - _Plugin(0), - _Playing(false), - _Timer(0), - _PagePosition(0), - _PageSimple(0), - _PageComplex(0), - _PageComtext(0), - _PageBgFlags(0) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - //{{AFX_DATA_INIT(CSoundDialog) - //}}AFX_DATA_INIT - -} - -// *************************************************************************** - -CSoundDialog::~CSoundDialog() -{ -} - - -// *************************************************************************** - -void CSoundDialog::init(CSoundPlugin* plugin, HWND documentView) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - _Plugin = plugin; - - if (HBITMAP(_StopBitmap) == 0) - { - _StopBitmap.LoadBitmap(IDB_STOP); - _StartBitmap.LoadBitmap(IDB_START); - _DesactivatedBitmap.LoadBitmap(IDB_DESACTIVATED); - _NewBitmap.LoadBitmap(IDB_NEW); - _ContextBitmap.LoadBitmap(IDB_CONTEXT); - _Red.CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); - } - - _OuterAngle = 360; - _InnerAngle = 360; - - Create(IDD_TEST_LOCAL, CWnd::FromHandle(documentView)); - - NLSOUND::UAudioMixer *mixer = _Plugin->getMixer(); - - // set the name an fade - FilterFades = mixer->getBackgroundFilterFades(); - _BackgroundFlags = mixer->getBackgroundFlags(); - for (uint i=0; igetBackgroundFlagName(i); - envName.ShortName = mixer->getBackgroundFlagShortName(i); - - EnvNames.push_back(envName); - } - -// CConfigFile &cf = _Plugin->getGlobalInterface()->getConfigFile(); - -/* try - { - CConfigFile::CVar *penvNames = cf.getVarPtr("background_sound_environment"); - - EnvNames.clear(); - sint i; - for (i=0; i< min(penvNames->size() / 4, 32); ++i) - { - TEnvName envName; - - envName.Name = penvNames->asString(i*4); - envName.ShortName = penvNames->asString(i*4+1); - FilterFades.FadeIns[i] = penvNames->asInt(i*4+2); - FilterFades.FadeOuts[i] = penvNames->asInt(i*4+3); - - EnvNames.push_back(envName); - } - for (; i < 32; ++i) - { - TEnvName envName; - char tmp[50]; - sprintf(tmp, "Filter %02u", i); - envName.Name = tmp; - sprintf(tmp, "%02u", i); - envName.ShortName = tmp; - EnvNames.push_back(envName); - } - } - catch(...) - { - } - -*/ return; - - CRect rect(0,0,200,200); -#undef new - CWnd *wnd = new CWnd(); -#define new NL_NEW - -} - - -void CSoundDialog::DoDataExchange(CDataExchange *pDX) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - //{{AFX_DATA_MAP(CSoundDialog) - DDX_Control(pDX, IDC_SHEET_POS, _SheetPos); - //}}AFX_DATA_MAP -} - -// *************************************************************************** - -void CSoundDialog::setPlaying(bool play) -{ - _Playing = play; - - updateButton(); -} - -// *************************************************************************** - -// *************************************************************************** - -void CSoundDialog::OnTimer(UINT id) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - updateTime(); -} - -// *************************************************************************** - -void CSoundDialog::OnZoom(NMHDR* pNMHDR, LRESULT* pResult) -{ - NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; - // TODO: Add your control notification handler code here - - *pResult = 0; -} - -// *************************************************************************** - -void CSoundDialog::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) -{ - if ((nChar == VK_SPACE) && _Plugin->isSoundValid()) - { -// _Plugin->play(_Filename); - OnControlPlayback(); - } -} - -// *************************************************************************** - -void CSoundDialog::updateTime() -{ - _Plugin->update(); - uint32 msec = _Plugin->getTime(); - -// if (msec == 0) - if (!_Plugin->isPlaying()) - { - setPlaying(false); - return; - } - - displayTime(msec); -} - -// *************************************************************************** - -void CSoundDialog::displayTime(uint32 msec) -{ - char s[256]; - uint sec = msec / 1000; - uint min = sec / 60; - sec -= min * 60; - _snprintf(s, 256, "%02d:%02d", min, sec); - GetDlgItem(IDC_TIME)->SetWindowText(s); -} - -// *************************************************************************** - -void CSoundDialog::updateButton() -{ - CButton* control = (CButton*) GetDlgItem(IDC_CONTROL); - -// if (_Filename.empty()) - if (!_Plugin->isSoundValid()) - { - control->SetBitmap(_DesactivatedBitmap); - control->SetCheck(0); - } - else - { - if (_Playing) - { - control->SetBitmap(_StopBitmap); - control->SetCheck(1); - } - else - { - control->SetBitmap(_StartBitmap); - control->SetCheck(0); - } - } -} - -void CSoundDialog::setDuration(uint32 msec) -{ - _Duration = msec; - updateInfo(); -} - - - -// *************************************************************************** - -void CSoundDialog::updateInfo() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - CPageBase::docChanged(); - - SetWindowText(_Name.c_str()); - - char s[256]; -/* if (_Filename.empty()) - { - SetWindowText((_Name.empty()) ? "Sound plugin" : _Name.c_str()); - SetWindowText("[no file selected]"); - GetDlgItem(IDC_NAME)->SetWindowText(_Name.c_str()); - GetDlgItem(IDC_FILENAME)->SetWindowText("[no file selected]"); - GetDlgItem(IDC_AUDIOFORMAT)->SetWindowText(""); - GetDlgItem(IDC_FILESIZE)->SetWindowText(""); -// GetDlgItem(IDC_DURATION)->SetWindowText("00:00.000"); - } - else - { - uint sampleRate, sampleSize, channels, size; - - if (getFileInfo(_Filename, sampleRate, sampleSize, channels, size)) - { - - if (channels > 1) - { - ::MessageBox(NULL, "3D sounds accept only mono files", _Name.c_str(), MB_OK); - } - - GetDlgItem(IDC_NAME)->SetWindowText(_Name.c_str()); - - SetWindowText((_Name.empty()) ? "Sound plugin" : _Name.c_str()); - GetDlgItem(IDC_FILENAME)->SetWindowText(_Filename.c_str()); - - _snprintf(s, 256, "%s / %d bits / %d Hz", (channels == 1)? "mono" : "stereo", sampleSize, sampleRate); - GetDlgItem(IDC_AUDIOFORMAT)->SetWindowText(s); - - _snprintf(s, 256, "%d kb", size / 1024); - GetDlgItem(IDC_FILESIZE)->SetWindowText(s); - -// uint msec = 1000 * size / sampleRate; - } - else - { - _Filename.erase(); - SetWindowText((_Name.empty()) ? "Sound plugin" : _Name.c_str()); - GetDlgItem(IDC_NAME)->SetWindowText(_Name.c_str()); - GetDlgItem(IDC_FILENAME)->SetWindowText("[invalid file]"); - GetDlgItem(IDC_AUDIOFORMAT)->SetWindowText(""); - GetDlgItem(IDC_FILESIZE)->SetWindowText(""); -// GetDlgItem(IDC_DURATION)->SetWindowText("00:00.000"); - } - } -*/ - // the duration is always valid. - uint msec = _Duration; - uint sec = msec / 1000; - uint min = sec / 60; - msec -= sec * 1000; - sec -= min * 60; - _snprintf(s, 256, "%02d:%02d.%03d", min, sec, msec); - GetDlgItem(IDC_DURATION)->SetWindowText(s); - - updateButton(); -} - -// *************************************************************************** - -bool CSoundDialog::getFileInfo(string& filename, uint& sampleRate, uint& sampleSize, uint& channels, uint& size) -{ - // Try to find the absolute path of the file - string path = CPath::lookup(filename, false, false, true); - - if (path.empty()) - { - // If we failed try to open the file as a local file anyway - path = filename; - } - - // Open the file - HMMIO hmmio = mmioOpen((char*) path.c_str(), NULL, MMIO_READ | MMIO_DENYWRITE); - if (hmmio == NULL) - { - return false; - } - - - // Check it's a WAVE file - MMCKINFO riff_chunk; - sint error = (sint) mmioDescend(hmmio, &riff_chunk, NULL, 0); - if ((error != 0) || (riff_chunk.ckid != FOURCC_RIFF) || (riff_chunk.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) - { - mmioClose(hmmio, 0); - return false; - } - - - // Search the format chunk - MMCKINFO chunk; - chunk.ckid = mmioFOURCC('f', 'm', 't', ' '); - error = (sint) mmioDescend(hmmio, &chunk, &riff_chunk, MMIO_FINDCHUNK); - if (error != 0) - { - mmioClose(hmmio, 0); - return false; - } - - if (chunk.cksize < (long) sizeof(PCMWAVEFORMAT)) - { - mmioClose(hmmio, 0); - return false; - } - - - // read in the format data - WAVEFORMATEX format; - sint num = mmioRead(hmmio, (HPSTR) &format, (long) sizeof(format)); - if (num != (long) sizeof(format)) - { - mmioClose(hmmio, 0); - return false; - } - format.cbSize = 0; - - // Get out of the format chunk - if (mmioAscend(hmmio, &chunk, 0) != 0) - { - mmioClose(hmmio, 0); - return false; - } - - - // Copy the format data - if (format.wFormatTag != WAVE_FORMAT_PCM) - { - mmioClose(hmmio, 0); - return false; - } - - sampleRate = format.nSamplesPerSec; - channels = format.nChannels; - sampleSize = format.wBitsPerSample; - - - // Set the file position to the beginning of the data chunk - sint32 pos = mmioSeek(hmmio, riff_chunk.dwDataOffset + sizeof(FOURCC), SEEK_SET); - if (pos < 0) - { - mmioClose(hmmio, 0); - return false; - } - - // Read the data chunk - MMCKINFO data_chunk; - data_chunk.ckid = mmioFOURCC('d', 'a', 't', 'a'); - if (mmioDescend(hmmio, &data_chunk, &riff_chunk, MMIO_FINDCHUNK) != 0) - { - mmioClose(hmmio, 0); - return false; - } - - - // Copy the size - size = data_chunk.cksize; - - // We're done - mmioClose(hmmio, 0); - - return true; -} - -// *************************************************************************** - -void CSoundDialog::updateAngles() -{ -// _ListenerView->setActive(!_Filename.empty()); -/* _ListenerView->setActive(true); - _ListenerView->setShowAlpha(_Plugin->hasAlpha()); - _ListenerView->setAngles(_InnerAngle, _OuterAngle); -*/ -} - -void CSoundDialog::fillContextArgs(NLSOUND::CSoundContext *context) -{ - if (_PageComtext != 0) - { - for (uint i =0; iArgs[i] = _PageComtext->SoundContext.Args[i]; - } -} - - -// *************************************************************************** - -void CSoundDialog::OnControlPlayback() -{ - if (!_Playing) - { - // check filename - string str = NLMISC::CFile::getFilename(_Filename); - - if (str == "*.sound") - { - MessageBox("You must save the file before playing it !", "Warning"); - return; - } - } - setPlaying(!_Playing); - - if (_Playing) - { - _Plugin->play(_Filename); - } - else - { - _Plugin->stop(); - } -} - - -void CSoundDialog::OnReloadSamples() -{ - _Plugin->reloadSamples(); -} - -BOOL CSoundDialog::OnInitDialog() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - CDialog::OnInitDialog(); - - WINDOWPLACEMENT place; - _SheetPos.GetWindowPlacement(&place); - - // create the property sheet -#undef new - CPropertySheet *sheet = new CPropertySheet(); - - // create the property page... - _PagePosition = new CPagePosition(this); - _PageSimple = new CPageSimple(this); - _PageComplex = new CPageComplex(this); - _PageComtext = new CPageComtext(this); - _PageBgFlags = new CPageBgFlags(this); - _PageBgFades = new CPageBgFades(this); -#define new NL_NEW - - sheet->AddPage(_PagePosition); - sheet->AddPage(_PageSimple); - sheet->AddPage(_PageComplex); - sheet->AddPage(_PageComtext); - sheet->AddPage(_PageBgFlags); - sheet->AddPage(_PageBgFades); - - sheet->Create(this, WS_CHILD | WS_VISIBLE); - // very important : the folowing two style ensure not entering into an infinite loop ! - sheet->ModifyStyleEx (0, WS_EX_CONTROLPARENT); -// sheet->ModifyStyle( 0, WS_TABSTOP ); - // place the property sheet onver the picture - sheet->SetWindowPos(NULL, place.rcNormalPosition.left, place.rcNormalPosition.top, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER); - sheet->ShowWindow(TRUE); - - // start the timer for mixer update - _Timer = SetTimer(1, 3, 0); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -void CSoundDialog::OnDestroy() -{ - CDialog::OnDestroy(); - KillTimer(_Timer); - - delete _PagePosition; - delete _PageSimple; - delete _PageComplex; - delete _PageComtext; - delete _PageBgFlags; - delete _PageBgFades; - - _PagePosition = NULL; - _PageSimple = NULL; - _PageComplex = NULL; - _PageComtext = NULL; - _PageBgFlags = NULL; - _PageBgFades = NULL; -} - -} // namespace NLGEORGES - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "std_sound_plugin.h" +#include "PageComplex.h" +#include "PageComtext.h" +#include "PageBgFlags.h" +#include "PageBgFades.h" +#include "PageSimple.h" +#include "PagePosition.h" + +#include "sound_dialog.h" + +#include "listener_view.h" +#include "sound_document_plugin.h" +#include "resource.h" +#include "nel/misc/debug.h" +#include "nel/misc/path.h" +#include "nel/georges/u_form_elm.h" +#include +#include + + +using namespace std; +using namespace NLMISC; + +namespace NLGEORGES +{ + +CBitmap CSoundDialog::_StopBitmap; +CBitmap CSoundDialog::_StartBitmap; +CBitmap CSoundDialog::_DesactivatedBitmap; +CBitmap CSoundDialog::_NewBitmap; +CBitmap CSoundDialog::_ContextBitmap; +CPen CSoundDialog::_Red; + + +BEGIN_MESSAGE_MAP(CSoundDialog, CDialog) + //{{AFX_MSG_MAP(CSoundDialog) + ON_WM_TIMER() + ON_WM_KEYUP() + ON_BN_CLICKED(IDC_CONTROL, OnControlPlayback) + ON_NOTIFY(UDN_DELTAPOS, IDC_ZOOM, OnZoom) + ON_BN_CLICKED(IDC_BUTTON_RELOAD_SAMPLES, OnReloadSamples) + ON_WM_DESTROY() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +CSoundDialog::CSoundDialog() +: CDialog(), + _Plugin(0), + _Playing(false), + _Timer(0), + _PagePosition(0), + _PageSimple(0), + _PageComplex(0), + _PageComtext(0), + _PageBgFlags(0) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + //{{AFX_DATA_INIT(CSoundDialog) + //}}AFX_DATA_INIT + +} + +// *************************************************************************** + +CSoundDialog::~CSoundDialog() +{ +} + + +// *************************************************************************** + +void CSoundDialog::init(CSoundPlugin* plugin, HWND documentView) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + _Plugin = plugin; + + if (HBITMAP(_StopBitmap) == 0) + { + _StopBitmap.LoadBitmap(IDB_STOP); + _StartBitmap.LoadBitmap(IDB_START); + _DesactivatedBitmap.LoadBitmap(IDB_DESACTIVATED); + _NewBitmap.LoadBitmap(IDB_NEW); + _ContextBitmap.LoadBitmap(IDB_CONTEXT); + _Red.CreatePen(PS_SOLID, 1, RGB(255, 0, 0)); + } + + _OuterAngle = 360; + _InnerAngle = 360; + + Create(IDD_TEST_LOCAL, CWnd::FromHandle(documentView)); + + NLSOUND::UAudioMixer *mixer = _Plugin->getMixer(); + + // set the name an fade + FilterFades = mixer->getBackgroundFilterFades(); + _BackgroundFlags = mixer->getBackgroundFlags(); + for (uint i=0; igetBackgroundFlagName(i); + envName.ShortName = mixer->getBackgroundFlagShortName(i); + + EnvNames.push_back(envName); + } + +// CConfigFile &cf = _Plugin->getGlobalInterface()->getConfigFile(); + +/* try + { + CConfigFile::CVar *penvNames = cf.getVarPtr("background_sound_environment"); + + EnvNames.clear(); + sint i; + for (i=0; i< min(penvNames->size() / 4, 32); ++i) + { + TEnvName envName; + + envName.Name = penvNames->asString(i*4); + envName.ShortName = penvNames->asString(i*4+1); + FilterFades.FadeIns[i] = penvNames->asInt(i*4+2); + FilterFades.FadeOuts[i] = penvNames->asInt(i*4+3); + + EnvNames.push_back(envName); + } + for (; i < 32; ++i) + { + TEnvName envName; + char tmp[50]; + sprintf(tmp, "Filter %02u", i); + envName.Name = tmp; + sprintf(tmp, "%02u", i); + envName.ShortName = tmp; + EnvNames.push_back(envName); + } + } + catch(...) + { + } + +*/ return; + + CRect rect(0,0,200,200); +#undef new + CWnd *wnd = new CWnd(); +#define new NL_NEW + +} + + +void CSoundDialog::DoDataExchange(CDataExchange *pDX) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + //{{AFX_DATA_MAP(CSoundDialog) + DDX_Control(pDX, IDC_SHEET_POS, _SheetPos); + //}}AFX_DATA_MAP +} + +// *************************************************************************** + +void CSoundDialog::setPlaying(bool play) +{ + _Playing = play; + + updateButton(); +} + +// *************************************************************************** + +// *************************************************************************** + +void CSoundDialog::OnTimer(UINT id) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + updateTime(); +} + +// *************************************************************************** + +void CSoundDialog::OnZoom(NMHDR* pNMHDR, LRESULT* pResult) +{ + NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; + // TODO: Add your control notification handler code here + + *pResult = 0; +} + +// *************************************************************************** + +void CSoundDialog::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + if ((nChar == VK_SPACE) && _Plugin->isSoundValid()) + { +// _Plugin->play(_Filename); + OnControlPlayback(); + } +} + +// *************************************************************************** + +void CSoundDialog::updateTime() +{ + _Plugin->update(); + uint32 msec = _Plugin->getTime(); + +// if (msec == 0) + if (!_Plugin->isPlaying()) + { + setPlaying(false); + return; + } + + displayTime(msec); +} + +// *************************************************************************** + +void CSoundDialog::displayTime(uint32 msec) +{ + char s[256]; + uint sec = msec / 1000; + uint min = sec / 60; + sec -= min * 60; + _snprintf(s, 256, "%02d:%02d", min, sec); + GetDlgItem(IDC_TIME)->SetWindowText(s); +} + +// *************************************************************************** + +void CSoundDialog::updateButton() +{ + CButton* control = (CButton*) GetDlgItem(IDC_CONTROL); + +// if (_Filename.empty()) + if (!_Plugin->isSoundValid()) + { + control->SetBitmap(_DesactivatedBitmap); + control->SetCheck(0); + } + else + { + if (_Playing) + { + control->SetBitmap(_StopBitmap); + control->SetCheck(1); + } + else + { + control->SetBitmap(_StartBitmap); + control->SetCheck(0); + } + } +} + +void CSoundDialog::setDuration(uint32 msec) +{ + _Duration = msec; + updateInfo(); +} + + + +// *************************************************************************** + +void CSoundDialog::updateInfo() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + CPageBase::docChanged(); + + SetWindowText(_Name.c_str()); + + char s[256]; +/* if (_Filename.empty()) + { + SetWindowText((_Name.empty()) ? "Sound plugin" : _Name.c_str()); + SetWindowText("[no file selected]"); + GetDlgItem(IDC_NAME)->SetWindowText(_Name.c_str()); + GetDlgItem(IDC_FILENAME)->SetWindowText("[no file selected]"); + GetDlgItem(IDC_AUDIOFORMAT)->SetWindowText(""); + GetDlgItem(IDC_FILESIZE)->SetWindowText(""); +// GetDlgItem(IDC_DURATION)->SetWindowText("00:00.000"); + } + else + { + uint sampleRate, sampleSize, channels, size; + + if (getFileInfo(_Filename, sampleRate, sampleSize, channels, size)) + { + + if (channels > 1) + { + ::MessageBox(NULL, "3D sounds accept only mono files", _Name.c_str(), MB_OK); + } + + GetDlgItem(IDC_NAME)->SetWindowText(_Name.c_str()); + + SetWindowText((_Name.empty()) ? "Sound plugin" : _Name.c_str()); + GetDlgItem(IDC_FILENAME)->SetWindowText(_Filename.c_str()); + + _snprintf(s, 256, "%s / %d bits / %d Hz", (channels == 1)? "mono" : "stereo", sampleSize, sampleRate); + GetDlgItem(IDC_AUDIOFORMAT)->SetWindowText(s); + + _snprintf(s, 256, "%d kb", size / 1024); + GetDlgItem(IDC_FILESIZE)->SetWindowText(s); + +// uint msec = 1000 * size / sampleRate; + } + else + { + _Filename.erase(); + SetWindowText((_Name.empty()) ? "Sound plugin" : _Name.c_str()); + GetDlgItem(IDC_NAME)->SetWindowText(_Name.c_str()); + GetDlgItem(IDC_FILENAME)->SetWindowText("[invalid file]"); + GetDlgItem(IDC_AUDIOFORMAT)->SetWindowText(""); + GetDlgItem(IDC_FILESIZE)->SetWindowText(""); +// GetDlgItem(IDC_DURATION)->SetWindowText("00:00.000"); + } + } +*/ + // the duration is always valid. + uint msec = _Duration; + uint sec = msec / 1000; + uint min = sec / 60; + msec -= sec * 1000; + sec -= min * 60; + _snprintf(s, 256, "%02d:%02d.%03d", min, sec, msec); + GetDlgItem(IDC_DURATION)->SetWindowText(s); + + updateButton(); +} + +// *************************************************************************** + +bool CSoundDialog::getFileInfo(string& filename, uint& sampleRate, uint& sampleSize, uint& channels, uint& size) +{ + // Try to find the absolute path of the file + string path = CPath::lookup(filename, false, false, true); + + if (path.empty()) + { + // If we failed try to open the file as a local file anyway + path = filename; + } + + // Open the file + HMMIO hmmio = mmioOpen((char*) path.c_str(), NULL, MMIO_READ | MMIO_DENYWRITE); + if (hmmio == NULL) + { + return false; + } + + + // Check it's a WAVE file + MMCKINFO riff_chunk; + sint error = (sint) mmioDescend(hmmio, &riff_chunk, NULL, 0); + if ((error != 0) || (riff_chunk.ckid != FOURCC_RIFF) || (riff_chunk.fccType != mmioFOURCC('W', 'A', 'V', 'E'))) + { + mmioClose(hmmio, 0); + return false; + } + + + // Search the format chunk + MMCKINFO chunk; + chunk.ckid = mmioFOURCC('f', 'm', 't', ' '); + error = (sint) mmioDescend(hmmio, &chunk, &riff_chunk, MMIO_FINDCHUNK); + if (error != 0) + { + mmioClose(hmmio, 0); + return false; + } + + if (chunk.cksize < (long) sizeof(PCMWAVEFORMAT)) + { + mmioClose(hmmio, 0); + return false; + } + + + // read in the format data + WAVEFORMATEX format; + sint num = mmioRead(hmmio, (HPSTR) &format, (long) sizeof(format)); + if (num != (long) sizeof(format)) + { + mmioClose(hmmio, 0); + return false; + } + format.cbSize = 0; + + // Get out of the format chunk + if (mmioAscend(hmmio, &chunk, 0) != 0) + { + mmioClose(hmmio, 0); + return false; + } + + + // Copy the format data + if (format.wFormatTag != WAVE_FORMAT_PCM) + { + mmioClose(hmmio, 0); + return false; + } + + sampleRate = format.nSamplesPerSec; + channels = format.nChannels; + sampleSize = format.wBitsPerSample; + + + // Set the file position to the beginning of the data chunk + sint32 pos = mmioSeek(hmmio, riff_chunk.dwDataOffset + sizeof(FOURCC), SEEK_SET); + if (pos < 0) + { + mmioClose(hmmio, 0); + return false; + } + + // Read the data chunk + MMCKINFO data_chunk; + data_chunk.ckid = mmioFOURCC('d', 'a', 't', 'a'); + if (mmioDescend(hmmio, &data_chunk, &riff_chunk, MMIO_FINDCHUNK) != 0) + { + mmioClose(hmmio, 0); + return false; + } + + + // Copy the size + size = data_chunk.cksize; + + // We're done + mmioClose(hmmio, 0); + + return true; +} + +// *************************************************************************** + +void CSoundDialog::updateAngles() +{ +// _ListenerView->setActive(!_Filename.empty()); +/* _ListenerView->setActive(true); + _ListenerView->setShowAlpha(_Plugin->hasAlpha()); + _ListenerView->setAngles(_InnerAngle, _OuterAngle); +*/ +} + +void CSoundDialog::fillContextArgs(NLSOUND::CSoundContext *context) +{ + if (_PageComtext != 0) + { + for (uint i =0; iArgs[i] = _PageComtext->SoundContext.Args[i]; + } +} + + +// *************************************************************************** + +void CSoundDialog::OnControlPlayback() +{ + if (!_Playing) + { + // check filename + string str = NLMISC::CFile::getFilename(_Filename); + + if (str == "*.sound") + { + MessageBox("You must save the file before playing it !", "Warning"); + return; + } + } + setPlaying(!_Playing); + + if (_Playing) + { + _Plugin->play(_Filename); + } + else + { + _Plugin->stop(); + } +} + + +void CSoundDialog::OnReloadSamples() +{ + _Plugin->reloadSamples(); +} + +BOOL CSoundDialog::OnInitDialog() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + CDialog::OnInitDialog(); + + WINDOWPLACEMENT place; + _SheetPos.GetWindowPlacement(&place); + + // create the property sheet +#undef new + CPropertySheet *sheet = new CPropertySheet(); + + // create the property page... + _PagePosition = new CPagePosition(this); + _PageSimple = new CPageSimple(this); + _PageComplex = new CPageComplex(this); + _PageComtext = new CPageComtext(this); + _PageBgFlags = new CPageBgFlags(this); + _PageBgFades = new CPageBgFades(this); +#define new NL_NEW + + sheet->AddPage(_PagePosition); + sheet->AddPage(_PageSimple); + sheet->AddPage(_PageComplex); + sheet->AddPage(_PageComtext); + sheet->AddPage(_PageBgFlags); + sheet->AddPage(_PageBgFades); + + sheet->Create(this, WS_CHILD | WS_VISIBLE); + // very important : the folowing two style ensure not entering into an infinite loop ! + sheet->ModifyStyleEx (0, WS_EX_CONTROLPARENT); +// sheet->ModifyStyle( 0, WS_TABSTOP ); + // place the property sheet onver the picture + sheet->SetWindowPos(NULL, place.rcNormalPosition.left, place.rcNormalPosition.top, 0, 0, SWP_FRAMECHANGED | SWP_NOSIZE | SWP_NOZORDER); + sheet->ShowWindow(TRUE); + + // start the timer for mixer update + _Timer = SetTimer(1, 3, 0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CSoundDialog::OnDestroy() +{ + CDialog::OnDestroy(); + KillTimer(_Timer); + + delete _PagePosition; + delete _PageSimple; + delete _PageComplex; + delete _PageComtext; + delete _PageBgFlags; + delete _PageBgFades; + + _PagePosition = NULL; + _PageSimple = NULL; + _PageComplex = NULL; + _PageComtext = NULL; + _PageBgFlags = NULL; + _PageBgFades = NULL; +} + +} // namespace NLGEORGES + + diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_dialog.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_dialog.h index d179f7f06..1b8c46e91 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_dialog.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_dialog.h @@ -1,144 +1,144 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef _NLGEORGES_SOUND_DIALOG_H -#define _NLGEORGES_SOUND_DIALOG_H - -#include -#include "std_sound_plugin.h" -#include "listener_view.h" -#include "nel/sound/u_audio_mixer.h" - -#include "../georges_dll/plugin_interface.h" - -class CPageBase; -class CPagePosition; -class CPageSimple; -class CPageComplex; -class CPageComtext; -class CPageBgFlags; -class CPageBgFades; - -namespace NLGEORGES -{ - - -class CSoundPlugin; -class CListenerView; - -class CSoundDialog : public CDialog -{ -public: - - CSoundDialog(); - virtual ~CSoundDialog(); - - // Dialog Data - //{{AFX_DATA(CSoundDialog) - enum { IDD = IDD_TEST_LOCAL }; - CStatic _SheetPos; - //}}AFX_DATA - - - - // Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CSoundDialog) - //}}AFX_VIRTUAL - - void init(CSoundPlugin* plugin, HWND documentView); - void setName(std::string& name) { _Name = name; updateInfo(); } - void setFilename(std::string& filename) { _Filename = filename; updateInfo(); } - void setAngles(uint32 inner, uint32 outer) { _InnerAngle = inner; _OuterAngle = outer; updateAngles(); updateInfo();} - void setPlaying(bool playing); - void setAlpha(double alpha) {/* _ListenerView->setAlpha(alpha); */} - void setMinMaxDistances(float mindist, float maxdist) { /*_ListenerView->setMinMaxDistances(mindist, maxdist);*/ updateInfo();} - void setDuration(uint32 msec); - - void DoDataExchange(CDataExchange *pDX); - - void fillContextArgs(NLSOUND::CSoundContext *context); - - CSoundPlugin *getSoundPlugin() {return _Plugin;}; - bool getFileInfo(std::string& filename, uint& sampleRate, uint& sampleSize, uint& channels, uint& size); - -private: - - - void updateInfo(); - void updateButton(); - void updateTime(); - void displayTime(uint32 msec); - void updateAngles(); - - CSoundPlugin *_Plugin; -// CListenerView *_ListenerView; - std::string _Name; - std::string _Filename; - bool _Playing; - UINT _Timer; - uint32 _InnerAngle; - uint32 _OuterAngle; - uint32 _Duration; - - uint32 _BackgroundIndex; - - NLSOUND::UAudioMixer::TBackgroundFlags _BackgroundFlags; - - // The property sheet page - CPagePosition *_PagePosition; - CPageSimple *_PageSimple; - CPageComplex *_PageComplex; - CPageComtext *_PageComtext; - CPageBgFlags *_PageBgFlags; - CPageBgFades *_PageBgFades; - - struct TEnvName - { - std::string ShortName; - std::string Name; - }; - -public: - std::vector EnvNames; - NLSOUND::UAudioMixer::TBackgroundFilterFades FilterFades; -private: - static CBitmap _StopBitmap; - static CBitmap _StartBitmap; - static CBitmap _DesactivatedBitmap; - static CBitmap _NewBitmap; - static CBitmap _ContextBitmap; - static CPen _Red; - - - // Generated message map functions - //{{AFX_MSG(CSoundDialog) - afx_msg void OnTimer(UINT id); - afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); - afx_msg void OnControlPlayback(); - afx_msg void OnZoom(NMHDR* pNMHDR, LRESULT* pResult); - afx_msg void OnReloadSamples(); - virtual BOOL OnInitDialog(); - afx_msg void OnDestroy(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - -}; - - -} // namespace NLGEORGES - -#endif // _NLGEORGES_SOUND_DIALOG_H +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef _NLGEORGES_SOUND_DIALOG_H +#define _NLGEORGES_SOUND_DIALOG_H + +#include +#include "std_sound_plugin.h" +#include "listener_view.h" +#include "nel/sound/u_audio_mixer.h" + +#include "../georges_dll/plugin_interface.h" + +class CPageBase; +class CPagePosition; +class CPageSimple; +class CPageComplex; +class CPageComtext; +class CPageBgFlags; +class CPageBgFades; + +namespace NLGEORGES +{ + + +class CSoundPlugin; +class CListenerView; + +class CSoundDialog : public CDialog +{ +public: + + CSoundDialog(); + virtual ~CSoundDialog(); + + // Dialog Data + //{{AFX_DATA(CSoundDialog) + enum { IDD = IDD_TEST_LOCAL }; + CStatic _SheetPos; + //}}AFX_DATA + + + + // Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSoundDialog) + //}}AFX_VIRTUAL + + void init(CSoundPlugin* plugin, HWND documentView); + void setName(std::string& name) { _Name = name; updateInfo(); } + void setFilename(std::string& filename) { _Filename = filename; updateInfo(); } + void setAngles(uint32 inner, uint32 outer) { _InnerAngle = inner; _OuterAngle = outer; updateAngles(); updateInfo();} + void setPlaying(bool playing); + void setAlpha(double alpha) {/* _ListenerView->setAlpha(alpha); */} + void setMinMaxDistances(float mindist, float maxdist) { /*_ListenerView->setMinMaxDistances(mindist, maxdist);*/ updateInfo();} + void setDuration(uint32 msec); + + void DoDataExchange(CDataExchange *pDX); + + void fillContextArgs(NLSOUND::CSoundContext *context); + + CSoundPlugin *getSoundPlugin() {return _Plugin;}; + bool getFileInfo(std::string& filename, uint& sampleRate, uint& sampleSize, uint& channels, uint& size); + +private: + + + void updateInfo(); + void updateButton(); + void updateTime(); + void displayTime(uint32 msec); + void updateAngles(); + + CSoundPlugin *_Plugin; +// CListenerView *_ListenerView; + std::string _Name; + std::string _Filename; + bool _Playing; + UINT _Timer; + uint32 _InnerAngle; + uint32 _OuterAngle; + uint32 _Duration; + + uint32 _BackgroundIndex; + + NLSOUND::UAudioMixer::TBackgroundFlags _BackgroundFlags; + + // The property sheet page + CPagePosition *_PagePosition; + CPageSimple *_PageSimple; + CPageComplex *_PageComplex; + CPageComtext *_PageComtext; + CPageBgFlags *_PageBgFlags; + CPageBgFades *_PageBgFades; + + struct TEnvName + { + std::string ShortName; + std::string Name; + }; + +public: + std::vector EnvNames; + NLSOUND::UAudioMixer::TBackgroundFilterFades FilterFades; +private: + static CBitmap _StopBitmap; + static CBitmap _StartBitmap; + static CBitmap _DesactivatedBitmap; + static CBitmap _NewBitmap; + static CBitmap _ContextBitmap; + static CPen _Red; + + + // Generated message map functions + //{{AFX_MSG(CSoundDialog) + afx_msg void OnTimer(UINT id); + afx_msg void OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnControlPlayback(); + afx_msg void OnZoom(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnReloadSamples(); + virtual BOOL OnInitDialog(); + afx_msg void OnDestroy(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + + +} // namespace NLGEORGES + +#endif // _NLGEORGES_SOUND_DIALOG_H diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_document_plugin.cpp b/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_document_plugin.cpp index b6bf4b803..321027d6a 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_document_plugin.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_document_plugin.cpp @@ -1,190 +1,190 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "sound_document_plugin.h" -#include "resource.h" -#include "nel/misc/debug.h" -#include "nel/misc/path.h" -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" -#include -#include - -using namespace std; -using namespace NLMISC; - -namespace NLGEORGES -{ - - -// *************************************************************************** - -void CSoundDocumentPlugin::dialogInit(HWND documentView) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - updateInfo(true); -} - -// *************************************************************************** - -bool CSoundDocumentPlugin::pretranslateMessage(MSG *pMsg) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - return false; -} - -// *************************************************************************** - -void CSoundDocumentPlugin::activate(bool activated) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - if (activated) - { - updateInfo(true); - - _Plugin->setActiveDocument(_Document); - - } - else - { - _Plugin->stop(); - } -} - -// *************************************************************************** - -void CSoundDocumentPlugin::onValueChanged(const char *formName) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - updateInfo(true); -} - -// *************************************************************************** - -void CSoundDocumentPlugin::onNodeChanged() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - updateInfo(false); -} - -// *************************************************************************** -// -// -// FIXME: Should be using CSound.importForm() -// -// -// -void CSoundDocumentPlugin::updateInfo(bool stopSound) -{ - // Filename -// _Document->getForm()->getRootNode().getValueByName(_Filename, ".SoundType.Filename"); - -/* // InternalConeAngle - _Document->getForm()->getRootNode().getValueByName(_InnerAngle, ".InternalConeAngle"); - if (_InnerAngle > 360) - { - _InnerAngle = 360; - } - float inner = (float) (Pi * _InnerAngle / 180.0f); // convert to radians - - // ExternalConeAngle - _Document->getForm()->getRootNode().getValueByName(_OuterAngle, ".ExternalConeAngle"); - if (_OuterAngle > 360) - { - _OuterAngle = 360; - } - float outer = (float) (Pi * _OuterAngle / 180.0f); // convert to radians -*/ -/* // Loop - _Document->getForm()->getRootNode().getValueByName(_Loop, ".Loop"); - - // Gain - _Document->getForm()->getRootNode().getValueByName(_Gain, ".Gain"); - if (_Gain > 0) - { - _Gain = 0; - } - if (_Gain < -100) - { - _Gain = -100; - } - float ampGain = (float) pow(10.0, _Gain / 20.0); // convert dB to linear gain -*/ -/* // External gain - _Document->getForm()->getRootNode().getValueByName(_ExternalGain, ".ExternalGain"); - if (_ExternalGain > 0) - { - _ExternalGain = 0; - } - if (_ExternalGain < -100) - { - _ExternalGain = -100; - } - float ampExtGain = (float) pow(10.0, _ExternalGain / 20.0); // convert dB to linear gain -*/ -/* - // Transpoee - _Document->getForm()->getRootNode().getValueByName(_Transpose, ".Transpose"); - float pitch = (float) pow(1.0594630943592952645618252949463, _Transpose); // convert semi-tones to playback speed -*/ - // MinDistance -/* float mindist; - _Document->getForm()->getRootNode().getValueByName(mindist, ".SoundType.MinDistance"); - - // MaxDistance - float maxdist; - _Document->getForm()->getRootNode().getValueByName(maxdist, ".SoundType.MaxDistance"); - - // Alpha - float alpha; - _Document->getForm()->getRootNode().getValueByName(alpha, ".SoundType.Alpha"); -*/ - // Send the values down the drain - - // For the source -// _Plugin->setLoop(_Loop); -// _Plugin->setGain(ampGain); -// _Plugin->setCone(inner, outer, ampExtGain); -// _Plugin->setPitch(pitch); -// _Plugin->setMinMaxDistances(mindist, maxdist); -// _Plugin->setAlpha(alpha); - - - // For the dialog - string filename; - _Document->getFilename(filename); - string name = NLMISC::CFile::getFilenameWithoutExtension(filename); - - if( stopSound) - _Plugin->setActiveDocument(_Document); - - _Plugin->updateDisplay(); - -// _Plugin->setName(name); -// _Plugin->setFilename(_Filename); -// _Plugin->setAngles(_InnerAngle, _OuterAngle); - - -} - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "sound_document_plugin.h" +#include "resource.h" +#include "nel/misc/debug.h" +#include "nel/misc/path.h" +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" +#include +#include + +using namespace std; +using namespace NLMISC; + +namespace NLGEORGES +{ + + +// *************************************************************************** + +void CSoundDocumentPlugin::dialogInit(HWND documentView) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + updateInfo(true); +} + +// *************************************************************************** + +bool CSoundDocumentPlugin::pretranslateMessage(MSG *pMsg) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + return false; +} + +// *************************************************************************** + +void CSoundDocumentPlugin::activate(bool activated) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + if (activated) + { + updateInfo(true); + + _Plugin->setActiveDocument(_Document); + + } + else + { + _Plugin->stop(); + } +} + +// *************************************************************************** + +void CSoundDocumentPlugin::onValueChanged(const char *formName) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + updateInfo(true); +} + +// *************************************************************************** + +void CSoundDocumentPlugin::onNodeChanged() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + updateInfo(false); +} + +// *************************************************************************** +// +// +// FIXME: Should be using CSound.importForm() +// +// +// +void CSoundDocumentPlugin::updateInfo(bool stopSound) +{ + // Filename +// _Document->getForm()->getRootNode().getValueByName(_Filename, ".SoundType.Filename"); + +/* // InternalConeAngle + _Document->getForm()->getRootNode().getValueByName(_InnerAngle, ".InternalConeAngle"); + if (_InnerAngle > 360) + { + _InnerAngle = 360; + } + float inner = (float) (Pi * _InnerAngle / 180.0f); // convert to radians + + // ExternalConeAngle + _Document->getForm()->getRootNode().getValueByName(_OuterAngle, ".ExternalConeAngle"); + if (_OuterAngle > 360) + { + _OuterAngle = 360; + } + float outer = (float) (Pi * _OuterAngle / 180.0f); // convert to radians +*/ +/* // Loop + _Document->getForm()->getRootNode().getValueByName(_Loop, ".Loop"); + + // Gain + _Document->getForm()->getRootNode().getValueByName(_Gain, ".Gain"); + if (_Gain > 0) + { + _Gain = 0; + } + if (_Gain < -100) + { + _Gain = -100; + } + float ampGain = (float) pow(10.0, _Gain / 20.0); // convert dB to linear gain +*/ +/* // External gain + _Document->getForm()->getRootNode().getValueByName(_ExternalGain, ".ExternalGain"); + if (_ExternalGain > 0) + { + _ExternalGain = 0; + } + if (_ExternalGain < -100) + { + _ExternalGain = -100; + } + float ampExtGain = (float) pow(10.0, _ExternalGain / 20.0); // convert dB to linear gain +*/ +/* + // Transpoee + _Document->getForm()->getRootNode().getValueByName(_Transpose, ".Transpose"); + float pitch = (float) pow(1.0594630943592952645618252949463, _Transpose); // convert semi-tones to playback speed +*/ + // MinDistance +/* float mindist; + _Document->getForm()->getRootNode().getValueByName(mindist, ".SoundType.MinDistance"); + + // MaxDistance + float maxdist; + _Document->getForm()->getRootNode().getValueByName(maxdist, ".SoundType.MaxDistance"); + + // Alpha + float alpha; + _Document->getForm()->getRootNode().getValueByName(alpha, ".SoundType.Alpha"); +*/ + // Send the values down the drain + + // For the source +// _Plugin->setLoop(_Loop); +// _Plugin->setGain(ampGain); +// _Plugin->setCone(inner, outer, ampExtGain); +// _Plugin->setPitch(pitch); +// _Plugin->setMinMaxDistances(mindist, maxdist); +// _Plugin->setAlpha(alpha); + + + // For the dialog + string filename; + _Document->getFilename(filename); + string name = NLMISC::CFile::getFilenameWithoutExtension(filename); + + if( stopSound) + _Plugin->setActiveDocument(_Document); + + _Plugin->updateDisplay(); + +// _Plugin->setName(name); +// _Plugin->setFilename(_Filename); +// _Plugin->setAngles(_InnerAngle, _OuterAngle); + + +} + + + } // namespace NLGEORGES \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_document_plugin.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_document_plugin.h index 8954fc81f..2cabc0b02 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_document_plugin.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_document_plugin.h @@ -1,62 +1,62 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef _NLGEORGES_SNDDOCPLUG_H -#define _NLGEORGES_SNDDOCPLUG_H - -#include "std_sound_plugin.h" -#include "../georges_dll/plugin_interface.h" -#include "sound_plugin.h" -#include "nel/misc/vector.h" - - -namespace NLGEORGES -{ - -class CSoundPlugin; - -class CSoundDocumentPlugin : public IEditDocumentPlugin -{ -public: - CSoundDocumentPlugin(CSoundPlugin *plugin, IEditDocument *document) : _Plugin(plugin), _Document(document), _Filename() {} - virtual ~CSoundDocumentPlugin() {} - - virtual void dialogInit(HWND documentView); - virtual bool pretranslateMessage(MSG *pMsg); - virtual void activate(bool activated); - virtual void onValueChanged(const char *formName); - virtual void onNodeChanged(); - -private: - - void updateInfo(bool stopSound); - - CSoundPlugin *_Plugin; - IEditDocument *_Document; - - std::string _Filename; - uint32 _InnerAngle; - uint32 _OuterAngle; - bool _Loop; - sint32 _Gain; - sint32 _ExternalGain; - sint32 _Transpose; -}; - - -} // namespace NLGEORGES - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef _NLGEORGES_SNDDOCPLUG_H +#define _NLGEORGES_SNDDOCPLUG_H + +#include "std_sound_plugin.h" +#include "../georges_dll/plugin_interface.h" +#include "sound_plugin.h" +#include "nel/misc/vector.h" + + +namespace NLGEORGES +{ + +class CSoundPlugin; + +class CSoundDocumentPlugin : public IEditDocumentPlugin +{ +public: + CSoundDocumentPlugin(CSoundPlugin *plugin, IEditDocument *document) : _Plugin(plugin), _Document(document), _Filename() {} + virtual ~CSoundDocumentPlugin() {} + + virtual void dialogInit(HWND documentView); + virtual bool pretranslateMessage(MSG *pMsg); + virtual void activate(bool activated); + virtual void onValueChanged(const char *formName); + virtual void onNodeChanged(); + +private: + + void updateInfo(bool stopSound); + + CSoundPlugin *_Plugin; + IEditDocument *_Document; + + std::string _Filename; + uint32 _InnerAngle; + uint32 _OuterAngle; + bool _Loop; + sint32 _Gain; + sint32 _ExternalGain; + sint32 _Transpose; +}; + + +} // namespace NLGEORGES + #endif // _NLGEORGES_SNDDOCPLUG_H \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_plugin.cpp b/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_plugin.cpp index 6cd5a5317..d20c0347f 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_plugin.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_plugin.cpp @@ -1,660 +1,660 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "sound_plugin.h" -#include "sound_document_plugin.h" -#include "resource.h" -//#include "sound/driver/buffer.h" -#include "nel/misc/vector.h" -#include "nel/misc/path.h" -#include "nel/sound/u_source.h" -#include "loading_dialog.h" -#include "nel/ligo/primitive.h" - -#include "nel/sound/sound.h" -#include "nel/sound/simple_sound.h" -#include - -using namespace std; -using namespace NLSOUND; -using namespace NLMISC; - - - -namespace NLGEORGES -{ - - - -// *************************************************************************** -/* -__declspec( dllexport ) IEditPlugin *IGeorgesEditGetInterface (int version, NLGEORGES::IEdit *globalInterface) -{ - // Same version ? - if (version == NLGEORGES_PLUGIN_INTERFACE_VERSION) - { - return new CSoundPlugin(globalInterface); - } - else - { - MessageBox (NULL, "Plugin version invalid.", "Sound plugin for georges editor", MB_OK|MB_ICONEXCLAMATION); - return NULL; - } - -} -*/ - -// *************************************************************************** - -CSoundPlugin::CSoundPlugin(IEdit *globalInterface) -: _Source(NULL), - _Sound(NULL), - _FreeSound(false), - _ActiveDoc(NULL), - _InvalidSound(false) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - CVector dir; - - _GlobalInterface = globalInterface; -/* _SoundDriver = ISoundDriver::createDriver(); - _Listener = _SoundDriver->createListener(); - _Listener->setRolloffFactor(1.0f); - _Source = _SoundDriver->createSource(); - dir.set(0, 1, 0); - _Source->setDirection(dir); - _Buffer = 0; -*/ - - CLoadingDialog loadDlg; - - loadDlg.Create(IDD_DIALOG_LOADING); - loadDlg.Message = ""; - loadDlg.UpdateData(FALSE); - loadDlg.ShowWindow(SW_SHOW); - - CConfigFile &cf = globalInterface->getConfigFile(); - // Add the search path - try - { - CConfigFile::CVar *psearchPath = cf.getVarPtr("SearchPath"); - if (psearchPath != 0) - { - for (uint i=0; isize(); ++i) - { - string path = psearchPath->asString(i); - loadDlg.Message = (string("Adding search path \"")+path+"\"").c_str(); - loadDlg.UpdateData(FALSE); - loadDlg.RedrawWindow(); - NLMISC::CPath::addSearchPath(path, true, false); - } - } - } - catch(...) - { - nlwarning("Error while setting search path"); - } - - - loadDlg.Message = "Initializing Audio Mixer"; - loadDlg.UpdateData(FALSE); - loadDlg.RedrawWindow(); - // init the mixer - _Mixer = UAudioMixer::createAudioMixer(); - // the the sample path - _Mixer->setSamplePath(cf.getVar("SamplePath").asString()); - _Mixer->setPackedSheetOption(cf.getVar("PackedSheetPath").asString(), true); - // and init - _Mixer->init(32, true, false, NULL, true); - - _Listener = _Mixer->getListener(); - - // load the sample banks. -/* try - { - _Mixer->setSamplePath(cf.getVar("sample_path").asString()); - CConfigFile::CVar *psampleBanks = cf.getVarPtr("load_sample_bank"); - if (psampleBanks != 0) - { - for (sint i=0; isize(); ++i) - { - loadDlg.Message = (string("Loading sample bank \"")+psampleBanks->asString(i)+"\"").c_str(); - loadDlg.UpdateData(FALSE); - loadDlg.RedrawWindow(); - _Mixer->loadSampleBank(false, psampleBanks->asString(i)); - } - } - } - catch(...) - { - nlwarning("Error while loading sample banks"); - } -*/ - // load the sound banks. -/* try - { - CConfigFile::CVar *psoundBanks = cf.getVarPtr("load_sound_bank"); - if (psoundBanks != 0) - { - for (sint i=0; isize(); ++i) - { - loadDlg.Message = (string("Loading sound bank \"")+psoundBanks->asString(i)+"\"").c_str(); - loadDlg.UpdateData(FALSE); - loadDlg.RedrawWindow(); -// _Mixer->loadSoundBank(psoundBanks->asString(i)); - } - } - } - catch(...) - { - nlwarning("Error while loading sound banks"); - } -*/ -// loadDlg.CloseWindow(); - loadDlg.DestroyWindow(); -} - - -// *************************************************************************** - -CSoundPlugin::~CSoundPlugin () -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - stop(); - - _Dialog.DestroyWindow(); - - -// _Dialog.ShowWindow(SW_HIDE); -// _Dialog.DestroyWindow(); - -/* if (_Buffer != 0) - { - delete _Buffer; - } - -*/ if (_Sound != 0 && _FreeSound) - { - delete _Sound; - } - - delete _Mixer; - -/* - if (_Listener != 0) - { - delete _Listener; - } - - if (_SoundDriver != 0) - { - delete _SoundDriver; - } -*/ -} - - -bool CSoundPlugin::checkSound(CSound *sound, const vector > &subsounds, vector &missingFiles) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - vector >::const_iterator first(subsounds.begin()), last(subsounds.end()); - - for (; first != last; ++first) - { - if (first->second == sound) - return false; - - if (first->second == 0 && !first->first.empty()) - missingFiles.push_back(first->first); - else if (first->second != 0) - { - vector > v2; - first->second->getSubSoundList(v2); - - if (!checkSound(sound, v2, missingFiles)) - return false; - } - } - return true; -} - - -// *************************************************************************** - -void CSoundPlugin::dialogInit(HWND mainFrm) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - // Initilize the search path for CPath::lookup - string searchPath; - _GlobalInterface->getSearchPath(searchPath); - CPath::addSearchPath(searchPath, true, true); - - _Dialog.init(this, mainFrm); -} - -// *************************************************************************** - -bool CSoundPlugin::pretranslateMessage(MSG *pMsg) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_SPACE)) - { - //MessageBox (NULL, "PLAY!", "Sound plugin", MB_OK); - -// if (_Source) -// { -// if (!_Source->isPlaying()) -// { - play(); -/* } - else - { - stop(); - play(); - } -*/// } - return true; - } - - return false; -} - -bool CSoundPlugin::hasAlpha() -{ - if (_Sound) - return _Sound->getSoundType() == CSound::SOUND_SIMPLE; - else - return false; -} - - -void CSoundPlugin::updateDisplay() -{ - if (_Sound != 0) - { - if (_Sound->getSoundType() == CSound::SOUND_SIMPLE) - { - CSimpleSound *ss = static_cast(_Sound); - setMinMaxDistances(ss->getMinDistance(), ss->getMaxDistance()); - _Dialog.setAlpha(static_cast(_Sound)->getAlpha()); - } - else - { - setMinMaxDistances(1, _Sound->getMaxDistance()); // 1m à max dist. - } - _Dialog.setAngles(uint32(180 * _Sound->getConeInnerAngle() / Pi), uint32(180 * _Sound->getConeOuterAngle() / Pi)); - } - -} - - - -void CSoundPlugin::setActiveDocument(IEditDocument *pdoc) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - stop(); - if (_Source != NULL) - { -// _Mixer->removeSource(_Source); - delete _Source; - _Source = NULL; - } - // release old sound. - if (_Sound != NULL && _FreeSound) - { - delete _Sound; - _Sound = NULL; - } - if (_ActiveDoc != pdoc) - { - // we have changed document. - _InvalidSound = false; - } - - _ActiveDoc = pdoc; - if (_ActiveDoc != NULL) - { - //std::string filename; - _ActiveDoc->getFilename(_Filename); - _Filename = NLMISC::CFile::getFilenameWithoutExtension(_Filename); - _Dialog.setName(_Filename); - - // 1st, try to found the sound in the preloaded sound bank. - _Sound = _Mixer->getSoundId(CStringMapper::map(_Filename)); - if (_Sound == NULL) - { - // not found, create a new one. - _Sound = CSound::createSound(_Filename, _ActiveDoc->getForm()->getRootNode()); - _FreeSound = true; - } - else - { - // update the existing sound with the george document - _Sound->importForm(_Filename, _ActiveDoc->getForm()->getRootNode()); - _FreeSound = false; - } - if (_Sound) - { - vector > subsounds; - _Sound->getSubSoundList(subsounds); - vector missingFiles; - bool invalid = !checkSound(_Sound, subsounds, missingFiles); - - if (invalid && !_InvalidSound) - { - MessageBox(NULL, "This sound contains an infinite recursion !", "Sound Error", MB_ICONERROR); - } - - // pre-create the sound to force loading any missing sample bank (thus avoiding unwanted message box) - _Dialog.fillContextArgs(&_Context); - _Source = _Mixer->createSource(_Sound, false, NULL, NULL, NULL, NULL); - if (_Source) - delete _Source; - _Source = NULL; - - // recheck the sound - missingFiles.clear(); - subsounds.clear(); - _Sound->getSubSoundList(subsounds); - invalid = !checkSound(_Sound, subsounds, missingFiles); - - invalid |= !missingFiles.empty(); - if (!missingFiles.empty() && !_InvalidSound) - { -/* // try to load missing sample bank - for (uint i=0; i rep; - explode(path, "/", rep, true); - - _Mixer->loadSampleBank(false, rep.back()); - - goto retrySound; - } - } - } -*/ - string message("The folowing files are missing for this sound :\n"); - vector::iterator first(missingFiles.begin()), last(missingFiles.end()); - for (;first != last;++first) - { - message += (*first)+"\n"; - } - - MessageBox(NULL, message.c_str(), "Sound incomplete", MB_ICONWARNING); - } - - - // NB : _InvalidSound and invalid are used to avoid repetitive warning message. - // After a first warning message, the message masked until the sound become - // valid (ie : no recursion in sound dependance and no missing files). - _InvalidSound = invalid; - - - std::string filename; - _ActiveDoc->getFilename(filename); - _Dialog.setFilename(filename); - _Dialog.fillContextArgs(&_Context); - _Source = _Mixer->createSource(_Sound, false, NULL, NULL, NULL, &_Context); - - if (_Sound->getSoundType() == CSound::SOUND_SIMPLE) - { - CSimpleSound *ss = static_cast(_Sound); - setMinMaxDistances(ss->getMinDistance(), ss->getMaxDistance()); - } - else - { - setMinMaxDistances(1, _Sound->getMaxDistance()); // 1m à max dist. - } - _Dialog.setAngles(uint32(180 * _Sound->getConeInnerAngle() / Pi), uint32(180 * _Sound->getConeOuterAngle() / Pi)); - if (!_InvalidSound) - _Dialog.setDuration(_Sound->getDuration()); - else - _Dialog.setDuration(0); - } - } -} - -void CSoundPlugin::updateEnvFlags(const UAudioMixer::TBackgroundFlags &backgroundFlags) -{ - _Mixer->setBackgroundFlags(backgroundFlags); -} - - -// *************************************************************************** - -void CSoundPlugin::onCreateDocument(IEditDocument *document) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - // Set text in the global dialog - string dfn; - document->getDfnFilename(dfn); - - // Bind an interface on the document - if (dfn.compare("sound.dfn") == 0) - { - document->bind(this, new CSoundDocumentPlugin(this, document)); - } - - stop(); -} - -// *************************************************************************** - -void CSoundPlugin::createNew() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - char BASED_CODE szFilter[] = "Sound (*.sound)|*.sound|All Files (*.*)|*.*||"; - CFileDialog fileDlg(FALSE, ".sound", "*.sound", OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, szFilter); - - if (fileDlg.DoModal() == IDOK) - { - string filename = (const char*) fileDlg.GetPathName(); - _GlobalInterface->createDocument("sound.dfn", filename.c_str()); - } -} - -// *************************************************************************** - -void CSoundPlugin::activate(bool activate) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - if (IsWindow(_Dialog)) - { - _Dialog.ShowWindow(activate? SW_SHOW : SW_HIDE); - } - -} - -// *************************************************************************** - -void CSoundPlugin::getPluginName(std::string &name) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - name = "Sound plugin"; -} - -// *************************************************************************** - -void CSoundPlugin::play(std::string &filename) -{ - try - { - stop(); - // force to recreate the sound (mainly for contextual sound) - setActiveDocument(_ActiveDoc); - - if (_Sound != NULL && !_InvalidSound) - { - // if it is a context source, recreate the source each time - if( _Sound->getSoundType() == CSound::SOUND_CONTEXT) - { - if (_Source != NULL) -// _Mixer->removeSource(_Source); - delete _Source; - _Dialog.fillContextArgs(&_Context); - _Source = _Mixer->createSource(_Sound, false, NULL, NULL, NULL, &_Context); - } - - if (_Sound->getSoundType() == CSound::SOUND_BACKGROUND) - { - // this is a background sound, we must create a pseudo environnent for baground sound - NLLIGO::CPrimRegion region; - - region.Name = "simulation"; - - NLLIGO::CPrimPoint point; - point.Point = NLMISC::CVector::Null; -// point.Name = string("simulation-")+_Sound->getName()+"-000"; - - region.VPoints.push_back(point); - string name = string("simulation-")+CStringMapper::unmap(_Sound->getName())+"-000"; - if (region.VPoints.back().checkProperty("name")) - region.VPoints.back().removePropertyByName("name"); - - region.VPoints.back().addPropertyByName("name", new NLLIGO::CPropertyString(name)); - - - // TODO : repair this -// _Mixer->loadBackgroundSoundFromRegion(region); - _Mixer->setBackgroundFilterFades(_Dialog.FilterFades); - _Mixer->playBackgroundSound(); - _Mixer->setBackgroundFilterFades(_Dialog.FilterFades); - _PlayBackground = true; - } - else if (_Source) - { - _Source->setPos (CVector(0,0,0)); - _Source->play(); - _Dialog.setPlaying(true); - } - } - -/* if (_Buffer != 0) - { - _Source->setStaticBuffer(0); - delete _Buffer; - _Buffer = 0; - } - - if (filename.empty()) - { - return; - } - - _Buffer = _SoundDriver->createBuffer(); - - string path = CPath::lookup(filename, true, true, true); - _SoundDriver->loadWavFile(_Buffer, path.c_str()); - - _Source->setStaticBuffer(_Buffer); - _Source->play(); -*/ - } - catch (ESoundDriver& e) - { - string reason = e.what(); - MessageBox (NULL, reason.c_str(), "Sound plugin", MB_OK); - } -} - -// *************************************************************************** - -void CSoundPlugin::stop() -{ - if (_Sound && _Sound->getSoundType() == CSound::SOUND_BACKGROUND) - { - _Mixer->stopBackgroundSound(); - _PlayBackground = false; - } - else if (_Source) - { - if (_Source->isPlaying()) - { - _Dialog.setPlaying(false); - _Source->stop(); - } - } -} - -// *************************************************************************** - -uint32 CSoundPlugin::getTime() -{ - if ((_Source == 0) /*|| !_Source->isPlaying()*/) - { - return 0; - } - else - { - return _Source->getTime(); - } -} - -void CSoundPlugin::update() -{ - _Mixer->update(); -} - -bool CSoundPlugin::isPlaying() -{ - if (_Sound && _Sound->getSoundType() == NLSOUND::CSound::SOUND_BACKGROUND) - return _PlayBackground; - else if (_Source) - return _Source->isPlaying(); - else - return false; -} - - -void CSoundPlugin::reloadSamples() -{ -/* CLoadingDialog loadDlg; - loadDlg.Create(IDD_DIALOG_LOADING); - loadDlg.Message = "Reloading sample banks..."; - loadDlg.UpdateData(FALSE); - loadDlg.ShowWindow(SW_SHOW); -*/ - _Mixer->reloadSampleBanks(false); - -// loadDlg.CloseWindow(); -// loadDlg.DestroyWindow(); -} - -void CSoundPlugin::reloadSounds() -{ -// _Mixer->reloadSounds(); -} - - - -} // namespace NLGEORGES +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "sound_plugin.h" +#include "sound_document_plugin.h" +#include "resource.h" +//#include "sound/driver/buffer.h" +#include "nel/misc/vector.h" +#include "nel/misc/path.h" +#include "nel/sound/u_source.h" +#include "loading_dialog.h" +#include "nel/ligo/primitive.h" + +#include "nel/sound/sound.h" +#include "nel/sound/simple_sound.h" +#include + +using namespace std; +using namespace NLSOUND; +using namespace NLMISC; + + + +namespace NLGEORGES +{ + + + +// *************************************************************************** +/* +__declspec( dllexport ) IEditPlugin *IGeorgesEditGetInterface (int version, NLGEORGES::IEdit *globalInterface) +{ + // Same version ? + if (version == NLGEORGES_PLUGIN_INTERFACE_VERSION) + { + return new CSoundPlugin(globalInterface); + } + else + { + MessageBox (NULL, "Plugin version invalid.", "Sound plugin for georges editor", MB_OK|MB_ICONEXCLAMATION); + return NULL; + } + +} +*/ + +// *************************************************************************** + +CSoundPlugin::CSoundPlugin(IEdit *globalInterface) +: _Source(NULL), + _Sound(NULL), + _FreeSound(false), + _ActiveDoc(NULL), + _InvalidSound(false) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + CVector dir; + + _GlobalInterface = globalInterface; +/* _SoundDriver = ISoundDriver::createDriver(); + _Listener = _SoundDriver->createListener(); + _Listener->setRolloffFactor(1.0f); + _Source = _SoundDriver->createSource(); + dir.set(0, 1, 0); + _Source->setDirection(dir); + _Buffer = 0; +*/ + + CLoadingDialog loadDlg; + + loadDlg.Create(IDD_DIALOG_LOADING); + loadDlg.Message = ""; + loadDlg.UpdateData(FALSE); + loadDlg.ShowWindow(SW_SHOW); + + CConfigFile &cf = globalInterface->getConfigFile(); + // Add the search path + try + { + CConfigFile::CVar *psearchPath = cf.getVarPtr("SearchPath"); + if (psearchPath != 0) + { + for (uint i=0; isize(); ++i) + { + string path = psearchPath->asString(i); + loadDlg.Message = (string("Adding search path \"")+path+"\"").c_str(); + loadDlg.UpdateData(FALSE); + loadDlg.RedrawWindow(); + NLMISC::CPath::addSearchPath(path, true, false); + } + } + } + catch(...) + { + nlwarning("Error while setting search path"); + } + + + loadDlg.Message = "Initializing Audio Mixer"; + loadDlg.UpdateData(FALSE); + loadDlg.RedrawWindow(); + // init the mixer + _Mixer = UAudioMixer::createAudioMixer(); + // the the sample path + _Mixer->setSamplePath(cf.getVar("SamplePath").asString()); + _Mixer->setPackedSheetOption(cf.getVar("PackedSheetPath").asString(), true); + // and init + _Mixer->init(32, true, false, NULL, true); + + _Listener = _Mixer->getListener(); + + // load the sample banks. +/* try + { + _Mixer->setSamplePath(cf.getVar("sample_path").asString()); + CConfigFile::CVar *psampleBanks = cf.getVarPtr("load_sample_bank"); + if (psampleBanks != 0) + { + for (sint i=0; isize(); ++i) + { + loadDlg.Message = (string("Loading sample bank \"")+psampleBanks->asString(i)+"\"").c_str(); + loadDlg.UpdateData(FALSE); + loadDlg.RedrawWindow(); + _Mixer->loadSampleBank(false, psampleBanks->asString(i)); + } + } + } + catch(...) + { + nlwarning("Error while loading sample banks"); + } +*/ + // load the sound banks. +/* try + { + CConfigFile::CVar *psoundBanks = cf.getVarPtr("load_sound_bank"); + if (psoundBanks != 0) + { + for (sint i=0; isize(); ++i) + { + loadDlg.Message = (string("Loading sound bank \"")+psoundBanks->asString(i)+"\"").c_str(); + loadDlg.UpdateData(FALSE); + loadDlg.RedrawWindow(); +// _Mixer->loadSoundBank(psoundBanks->asString(i)); + } + } + } + catch(...) + { + nlwarning("Error while loading sound banks"); + } +*/ +// loadDlg.CloseWindow(); + loadDlg.DestroyWindow(); +} + + +// *************************************************************************** + +CSoundPlugin::~CSoundPlugin () +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + stop(); + + _Dialog.DestroyWindow(); + + +// _Dialog.ShowWindow(SW_HIDE); +// _Dialog.DestroyWindow(); + +/* if (_Buffer != 0) + { + delete _Buffer; + } + +*/ if (_Sound != 0 && _FreeSound) + { + delete _Sound; + } + + delete _Mixer; + +/* + if (_Listener != 0) + { + delete _Listener; + } + + if (_SoundDriver != 0) + { + delete _SoundDriver; + } +*/ +} + + +bool CSoundPlugin::checkSound(CSound *sound, const vector > &subsounds, vector &missingFiles) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + vector >::const_iterator first(subsounds.begin()), last(subsounds.end()); + + for (; first != last; ++first) + { + if (first->second == sound) + return false; + + if (first->second == 0 && !first->first.empty()) + missingFiles.push_back(first->first); + else if (first->second != 0) + { + vector > v2; + first->second->getSubSoundList(v2); + + if (!checkSound(sound, v2, missingFiles)) + return false; + } + } + return true; +} + + +// *************************************************************************** + +void CSoundPlugin::dialogInit(HWND mainFrm) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + // Initilize the search path for CPath::lookup + string searchPath; + _GlobalInterface->getSearchPath(searchPath); + CPath::addSearchPath(searchPath, true, true); + + _Dialog.init(this, mainFrm); +} + +// *************************************************************************** + +bool CSoundPlugin::pretranslateMessage(MSG *pMsg) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_SPACE)) + { + //MessageBox (NULL, "PLAY!", "Sound plugin", MB_OK); + +// if (_Source) +// { +// if (!_Source->isPlaying()) +// { + play(); +/* } + else + { + stop(); + play(); + } +*/// } + return true; + } + + return false; +} + +bool CSoundPlugin::hasAlpha() +{ + if (_Sound) + return _Sound->getSoundType() == CSound::SOUND_SIMPLE; + else + return false; +} + + +void CSoundPlugin::updateDisplay() +{ + if (_Sound != 0) + { + if (_Sound->getSoundType() == CSound::SOUND_SIMPLE) + { + CSimpleSound *ss = static_cast(_Sound); + setMinMaxDistances(ss->getMinDistance(), ss->getMaxDistance()); + _Dialog.setAlpha(static_cast(_Sound)->getAlpha()); + } + else + { + setMinMaxDistances(1, _Sound->getMaxDistance()); // 1m à max dist. + } + _Dialog.setAngles(uint32(180 * _Sound->getConeInnerAngle() / Pi), uint32(180 * _Sound->getConeOuterAngle() / Pi)); + } + +} + + + +void CSoundPlugin::setActiveDocument(IEditDocument *pdoc) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + stop(); + if (_Source != NULL) + { +// _Mixer->removeSource(_Source); + delete _Source; + _Source = NULL; + } + // release old sound. + if (_Sound != NULL && _FreeSound) + { + delete _Sound; + _Sound = NULL; + } + if (_ActiveDoc != pdoc) + { + // we have changed document. + _InvalidSound = false; + } + + _ActiveDoc = pdoc; + if (_ActiveDoc != NULL) + { + //std::string filename; + _ActiveDoc->getFilename(_Filename); + _Filename = NLMISC::CFile::getFilenameWithoutExtension(_Filename); + _Dialog.setName(_Filename); + + // 1st, try to found the sound in the preloaded sound bank. + _Sound = _Mixer->getSoundId(CStringMapper::map(_Filename)); + if (_Sound == NULL) + { + // not found, create a new one. + _Sound = CSound::createSound(_Filename, _ActiveDoc->getForm()->getRootNode()); + _FreeSound = true; + } + else + { + // update the existing sound with the george document + _Sound->importForm(_Filename, _ActiveDoc->getForm()->getRootNode()); + _FreeSound = false; + } + if (_Sound) + { + vector > subsounds; + _Sound->getSubSoundList(subsounds); + vector missingFiles; + bool invalid = !checkSound(_Sound, subsounds, missingFiles); + + if (invalid && !_InvalidSound) + { + MessageBox(NULL, "This sound contains an infinite recursion !", "Sound Error", MB_ICONERROR); + } + + // pre-create the sound to force loading any missing sample bank (thus avoiding unwanted message box) + _Dialog.fillContextArgs(&_Context); + _Source = _Mixer->createSource(_Sound, false, NULL, NULL, NULL, NULL); + if (_Source) + delete _Source; + _Source = NULL; + + // recheck the sound + missingFiles.clear(); + subsounds.clear(); + _Sound->getSubSoundList(subsounds); + invalid = !checkSound(_Sound, subsounds, missingFiles); + + invalid |= !missingFiles.empty(); + if (!missingFiles.empty() && !_InvalidSound) + { +/* // try to load missing sample bank + for (uint i=0; i rep; + explode(path, "/", rep, true); + + _Mixer->loadSampleBank(false, rep.back()); + + goto retrySound; + } + } + } +*/ + string message("The folowing files are missing for this sound :\n"); + vector::iterator first(missingFiles.begin()), last(missingFiles.end()); + for (;first != last;++first) + { + message += (*first)+"\n"; + } + + MessageBox(NULL, message.c_str(), "Sound incomplete", MB_ICONWARNING); + } + + + // NB : _InvalidSound and invalid are used to avoid repetitive warning message. + // After a first warning message, the message masked until the sound become + // valid (ie : no recursion in sound dependance and no missing files). + _InvalidSound = invalid; + + + std::string filename; + _ActiveDoc->getFilename(filename); + _Dialog.setFilename(filename); + _Dialog.fillContextArgs(&_Context); + _Source = _Mixer->createSource(_Sound, false, NULL, NULL, NULL, &_Context); + + if (_Sound->getSoundType() == CSound::SOUND_SIMPLE) + { + CSimpleSound *ss = static_cast(_Sound); + setMinMaxDistances(ss->getMinDistance(), ss->getMaxDistance()); + } + else + { + setMinMaxDistances(1, _Sound->getMaxDistance()); // 1m à max dist. + } + _Dialog.setAngles(uint32(180 * _Sound->getConeInnerAngle() / Pi), uint32(180 * _Sound->getConeOuterAngle() / Pi)); + if (!_InvalidSound) + _Dialog.setDuration(_Sound->getDuration()); + else + _Dialog.setDuration(0); + } + } +} + +void CSoundPlugin::updateEnvFlags(const UAudioMixer::TBackgroundFlags &backgroundFlags) +{ + _Mixer->setBackgroundFlags(backgroundFlags); +} + + +// *************************************************************************** + +void CSoundPlugin::onCreateDocument(IEditDocument *document) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + // Set text in the global dialog + string dfn; + document->getDfnFilename(dfn); + + // Bind an interface on the document + if (dfn.compare("sound.dfn") == 0) + { + document->bind(this, new CSoundDocumentPlugin(this, document)); + } + + stop(); +} + +// *************************************************************************** + +void CSoundPlugin::createNew() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + char BASED_CODE szFilter[] = "Sound (*.sound)|*.sound|All Files (*.*)|*.*||"; + CFileDialog fileDlg(FALSE, ".sound", "*.sound", OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, szFilter); + + if (fileDlg.DoModal() == IDOK) + { + string filename = (const char*) fileDlg.GetPathName(); + _GlobalInterface->createDocument("sound.dfn", filename.c_str()); + } +} + +// *************************************************************************** + +void CSoundPlugin::activate(bool activate) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + if (IsWindow(_Dialog)) + { + _Dialog.ShowWindow(activate? SW_SHOW : SW_HIDE); + } + +} + +// *************************************************************************** + +void CSoundPlugin::getPluginName(std::string &name) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + name = "Sound plugin"; +} + +// *************************************************************************** + +void CSoundPlugin::play(std::string &filename) +{ + try + { + stop(); + // force to recreate the sound (mainly for contextual sound) + setActiveDocument(_ActiveDoc); + + if (_Sound != NULL && !_InvalidSound) + { + // if it is a context source, recreate the source each time + if( _Sound->getSoundType() == CSound::SOUND_CONTEXT) + { + if (_Source != NULL) +// _Mixer->removeSource(_Source); + delete _Source; + _Dialog.fillContextArgs(&_Context); + _Source = _Mixer->createSource(_Sound, false, NULL, NULL, NULL, &_Context); + } + + if (_Sound->getSoundType() == CSound::SOUND_BACKGROUND) + { + // this is a background sound, we must create a pseudo environnent for baground sound + NLLIGO::CPrimRegion region; + + region.Name = "simulation"; + + NLLIGO::CPrimPoint point; + point.Point = NLMISC::CVector::Null; +// point.Name = string("simulation-")+_Sound->getName()+"-000"; + + region.VPoints.push_back(point); + string name = string("simulation-")+CStringMapper::unmap(_Sound->getName())+"-000"; + if (region.VPoints.back().checkProperty("name")) + region.VPoints.back().removePropertyByName("name"); + + region.VPoints.back().addPropertyByName("name", new NLLIGO::CPropertyString(name)); + + + // TODO : repair this +// _Mixer->loadBackgroundSoundFromRegion(region); + _Mixer->setBackgroundFilterFades(_Dialog.FilterFades); + _Mixer->playBackgroundSound(); + _Mixer->setBackgroundFilterFades(_Dialog.FilterFades); + _PlayBackground = true; + } + else if (_Source) + { + _Source->setPos (CVector(0,0,0)); + _Source->play(); + _Dialog.setPlaying(true); + } + } + +/* if (_Buffer != 0) + { + _Source->setStaticBuffer(0); + delete _Buffer; + _Buffer = 0; + } + + if (filename.empty()) + { + return; + } + + _Buffer = _SoundDriver->createBuffer(); + + string path = CPath::lookup(filename, true, true, true); + _SoundDriver->loadWavFile(_Buffer, path.c_str()); + + _Source->setStaticBuffer(_Buffer); + _Source->play(); +*/ + } + catch (ESoundDriver& e) + { + string reason = e.what(); + MessageBox (NULL, reason.c_str(), "Sound plugin", MB_OK); + } +} + +// *************************************************************************** + +void CSoundPlugin::stop() +{ + if (_Sound && _Sound->getSoundType() == CSound::SOUND_BACKGROUND) + { + _Mixer->stopBackgroundSound(); + _PlayBackground = false; + } + else if (_Source) + { + if (_Source->isPlaying()) + { + _Dialog.setPlaying(false); + _Source->stop(); + } + } +} + +// *************************************************************************** + +uint32 CSoundPlugin::getTime() +{ + if ((_Source == 0) /*|| !_Source->isPlaying()*/) + { + return 0; + } + else + { + return _Source->getTime(); + } +} + +void CSoundPlugin::update() +{ + _Mixer->update(); +} + +bool CSoundPlugin::isPlaying() +{ + if (_Sound && _Sound->getSoundType() == NLSOUND::CSound::SOUND_BACKGROUND) + return _PlayBackground; + else if (_Source) + return _Source->isPlaying(); + else + return false; +} + + +void CSoundPlugin::reloadSamples() +{ +/* CLoadingDialog loadDlg; + loadDlg.Create(IDD_DIALOG_LOADING); + loadDlg.Message = "Reloading sample banks..."; + loadDlg.UpdateData(FALSE); + loadDlg.ShowWindow(SW_SHOW); +*/ + _Mixer->reloadSampleBanks(false); + +// loadDlg.CloseWindow(); +// loadDlg.DestroyWindow(); +} + +void CSoundPlugin::reloadSounds() +{ +// _Mixer->reloadSounds(); +} + + + +} // namespace NLGEORGES diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_plugin.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_plugin.h index 11868dd17..c95077d68 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_plugin.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/sound_plugin.h @@ -1,157 +1,157 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef _NLGEORGES_SOUND_PLUGIN_H -#define _NLGEORGES_SOUND_PLUGIN_H - -#include "std_sound_plugin.h" - -#include -#include -#include - -#ifdef min -#undef min -#endif - -#ifdef max -#undef max -#endif - -#include "sound_dialog.h" - -#include "../georges_dll/plugin_interface.h" - -#include "nel/misc/vector.h" - -#include "nel/sound/driver/sound_driver.h" -#include "nel/sound/driver/source.h" -#include "nel/sound/driver/listener.h" -#include "sound/driver/dsound/source_dsound.h" - -#include "nel/sound/u_audio_mixer.h" -#include "nel/sound/u_listener.h" - - -class NLSOUND::IBuffer; -class NLSOUND::IListener; -class NLSOUND::USource; -class NLSOUND::CSourceDSound; -class NLSOUND::CSound; - - - -namespace NLGEORGES -{ - - -class CSoundPlugin : public IEditPlugin -{ -public: - // From IEditPlugin - CSoundPlugin(NLGEORGES::IEdit *globalInterface); - virtual ~CSoundPlugin(); - - // Overriden methods - virtual void dialogInit(HWND mainFrm); - virtual bool pretranslateMessage(MSG *pMsg); - virtual void onCreateDocument(IEditDocument *document); - virtual void activate(bool activate); - virtual void getPluginName(std::string &name); - - // Source control - virtual void play(std::string &filename); - virtual void play() { play(_Filename); }; - virtual void stop(); - virtual uint32 getTime(); - - void update(); - bool isPlaying(); - - // Source parameters - virtual void setListenerPos(const NLMISC::CVector& pos) { _Listener->setPos(pos); /*commit();*/ } - virtual void setListenerOrientation(const NLMISC::CVector& front, const NLMISC::CVector& up) { _Listener->setOrientation(front, up); /*commit(); */} - virtual void setDirection(const NLMISC::CVector& dir) { /*_Source->setDirection(dir);*/ commit(); } - virtual void setGain(float gain) { /*_Source->setGain(gain);*/ commit(); } - virtual void setPitch(float pitch) { /*_Source->setPitch(pitch);*/ commit(); } - virtual void setMinMaxDistances(float mindist, float maxdist) { /*_Source->setMinMaxDistances(mindist, maxdist);*/ commit(); _Dialog.setMinMaxDistances(mindist, maxdist); } - virtual void setCone(float inner, float outer, float outerGain) { /*_Source->setCone(inner, outer, outerGain);*/ commit(); } - virtual void setLoop(bool v) { /*_Source->setLooping(v);*/ } - virtual void commit() { /*_SoundDriver->commit3DChanges(); */} - virtual void setAlpha(double alpha) { /*_Source->setAlpha(alpha);*/ _Dialog.setAlpha(alpha); } - - // Dialog display - virtual void setName(std::string& name) { _Dialog.setName(name); } - virtual void setFilename(std::string& filename) { _Filename = filename; _Dialog.setFilename(filename); } - virtual void setAngles(uint32 inner, uint32 outer) { _Dialog.setAngles(inner, outer); } - - // Form creation - virtual void createNew(); - - // Boris : hum, simpler ? - void setActiveDocument(IEditDocument *pdoc); - IEditDocument *getActiveDocument() { return _ActiveDoc; } - - /// Ask if the sound has an alpha info (ie simple sound). - bool hasAlpha(); - - bool isSoundValid() { return !_InvalidSound;} - - /// The dialog update the environnement flags. - void updateEnvFlags(const NLSOUND::UAudioMixer::TBackgroundFlags &backgroundFlags); - - // Return the global interface (for dialog) - IEdit *getGlobalInterface() { return _GlobalInterface; } - - void reloadSamples(); - void reloadSounds(); - - void updateDisplay(); - - NLSOUND::UAudioMixer *getMixer() { return _Mixer;} - - NLSOUND::USource *getSource() { return _Source; } - NLSOUND::CSound *getSound() { return _Sound; } - -private: - - bool checkSound(NLSOUND::CSound *sound, const std::vector > &subsounds, std::vector &missingFiles); - - IEdit *_GlobalInterface; - CSoundDialog _Dialog; -// NLSOUND::ISoundDriver *_SoundDriver; -// NLSOUND::IBuffer *_Buffer; - NLSOUND::UListener *_Listener; - NLSOUND::USource *_Source; - NLSOUND::CSound *_Sound; - bool _FreeSound; - bool _PlayBackground; - std::string _Filename; - - NLSOUND::CSoundContext _Context; - - /// Flag for sound with infinite recursion ! - bool _InvalidSound; - - IEditDocument *_ActiveDoc; - NLSOUND::UAudioMixer *_Mixer; - -}; - - -} // namespace NLGEORGES - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef _NLGEORGES_SOUND_PLUGIN_H +#define _NLGEORGES_SOUND_PLUGIN_H + +#include "std_sound_plugin.h" + +#include +#include +#include + +#ifdef min +#undef min +#endif + +#ifdef max +#undef max +#endif + +#include "sound_dialog.h" + +#include "../georges_dll/plugin_interface.h" + +#include "nel/misc/vector.h" + +#include "nel/sound/driver/sound_driver.h" +#include "nel/sound/driver/source.h" +#include "nel/sound/driver/listener.h" +#include "sound/driver/dsound/source_dsound.h" + +#include "nel/sound/u_audio_mixer.h" +#include "nel/sound/u_listener.h" + + +class NLSOUND::IBuffer; +class NLSOUND::IListener; +class NLSOUND::USource; +class NLSOUND::CSourceDSound; +class NLSOUND::CSound; + + + +namespace NLGEORGES +{ + + +class CSoundPlugin : public IEditPlugin +{ +public: + // From IEditPlugin + CSoundPlugin(NLGEORGES::IEdit *globalInterface); + virtual ~CSoundPlugin(); + + // Overriden methods + virtual void dialogInit(HWND mainFrm); + virtual bool pretranslateMessage(MSG *pMsg); + virtual void onCreateDocument(IEditDocument *document); + virtual void activate(bool activate); + virtual void getPluginName(std::string &name); + + // Source control + virtual void play(std::string &filename); + virtual void play() { play(_Filename); }; + virtual void stop(); + virtual uint32 getTime(); + + void update(); + bool isPlaying(); + + // Source parameters + virtual void setListenerPos(const NLMISC::CVector& pos) { _Listener->setPos(pos); /*commit();*/ } + virtual void setListenerOrientation(const NLMISC::CVector& front, const NLMISC::CVector& up) { _Listener->setOrientation(front, up); /*commit(); */} + virtual void setDirection(const NLMISC::CVector& dir) { /*_Source->setDirection(dir);*/ commit(); } + virtual void setGain(float gain) { /*_Source->setGain(gain);*/ commit(); } + virtual void setPitch(float pitch) { /*_Source->setPitch(pitch);*/ commit(); } + virtual void setMinMaxDistances(float mindist, float maxdist) { /*_Source->setMinMaxDistances(mindist, maxdist);*/ commit(); _Dialog.setMinMaxDistances(mindist, maxdist); } + virtual void setCone(float inner, float outer, float outerGain) { /*_Source->setCone(inner, outer, outerGain);*/ commit(); } + virtual void setLoop(bool v) { /*_Source->setLooping(v);*/ } + virtual void commit() { /*_SoundDriver->commit3DChanges(); */} + virtual void setAlpha(double alpha) { /*_Source->setAlpha(alpha);*/ _Dialog.setAlpha(alpha); } + + // Dialog display + virtual void setName(std::string& name) { _Dialog.setName(name); } + virtual void setFilename(std::string& filename) { _Filename = filename; _Dialog.setFilename(filename); } + virtual void setAngles(uint32 inner, uint32 outer) { _Dialog.setAngles(inner, outer); } + + // Form creation + virtual void createNew(); + + // Boris : hum, simpler ? + void setActiveDocument(IEditDocument *pdoc); + IEditDocument *getActiveDocument() { return _ActiveDoc; } + + /// Ask if the sound has an alpha info (ie simple sound). + bool hasAlpha(); + + bool isSoundValid() { return !_InvalidSound;} + + /// The dialog update the environnement flags. + void updateEnvFlags(const NLSOUND::UAudioMixer::TBackgroundFlags &backgroundFlags); + + // Return the global interface (for dialog) + IEdit *getGlobalInterface() { return _GlobalInterface; } + + void reloadSamples(); + void reloadSounds(); + + void updateDisplay(); + + NLSOUND::UAudioMixer *getMixer() { return _Mixer;} + + NLSOUND::USource *getSource() { return _Source; } + NLSOUND::CSound *getSound() { return _Sound; } + +private: + + bool checkSound(NLSOUND::CSound *sound, const std::vector > &subsounds, std::vector &missingFiles); + + IEdit *_GlobalInterface; + CSoundDialog _Dialog; +// NLSOUND::ISoundDriver *_SoundDriver; +// NLSOUND::IBuffer *_Buffer; + NLSOUND::UListener *_Listener; + NLSOUND::USource *_Source; + NLSOUND::CSound *_Sound; + bool _FreeSound; + bool _PlayBackground; + std::string _Filename; + + NLSOUND::CSoundContext _Context; + + /// Flag for sound with infinite recursion ! + bool _InvalidSound; + + IEditDocument *_ActiveDoc; + NLSOUND::UAudioMixer *_Mixer; + +}; + + +} // namespace NLGEORGES + #endif // _NLGEORGES_SOUND_PLUGIN_H \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/georges_plugin_sound/std_sound_plugin.h b/code/ryzom/tools/leveldesign/georges_plugin_sound/std_sound_plugin.h index b605ecdd4..3e5c33d17 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_sound/std_sound_plugin.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_sound/std_sound_plugin.h @@ -1,29 +1,29 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#define NOMINMAX -#define _WIN32_WINNT 0x0500 - -#include // MFC core and standard components -#include // MFC extensions -#include "resource.h" - -#include "nel/misc/types_nl.h" -#include "nel/misc/debug.h" -#include "nel/georges/u_form_elm.h" - -#include "georges_plugin_sound.h" +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#define NOMINMAX +#define _WIN32_WINNT 0x0500 + +#include // MFC core and standard components +#include // MFC extensions +#include "resource.h" + +#include "nel/misc/types_nl.h" +#include "nel/misc/debug.h" +#include "nel/georges/u_form_elm.h" + +#include "georges_plugin_sound.h" diff --git a/code/ryzom/tools/leveldesign/georges_plugin_test/Resource.h b/code/ryzom/tools/leveldesign/georges_plugin_test/Resource.h index a26ed913c..3517c4277 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_test/Resource.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_test/Resource.h @@ -1,39 +1,39 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by georges_plugin_test.rc -// -#define IDC_MESSAGE 1000 -#define IDD_TEST_GLOBAL 1000 -#define IDD_TEST_LOCAL 1001 -#define IDC_MESSAGE2 1001 -#define IDC_REFRESH 1002 -#define IDC_SET 1003 -#define IDC_CREATE_DOC 1003 -#define IDC_SAVE 1004 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 1001 -#define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1004 -#define _APS_NEXT_SYMED_VALUE 1000 -#endif -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by georges_plugin_test.rc +// +#define IDC_MESSAGE 1000 +#define IDD_TEST_GLOBAL 1000 +#define IDD_TEST_LOCAL 1001 +#define IDC_MESSAGE2 1001 +#define IDC_REFRESH 1002 +#define IDC_SET 1003 +#define IDC_CREATE_DOC 1003 +#define IDC_SAVE 1004 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 1001 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1004 +#define _APS_NEXT_SYMED_VALUE 1000 +#endif +#endif diff --git a/code/ryzom/tools/leveldesign/georges_plugin_test/StdAfx.cpp b/code/ryzom/tools/leveldesign/georges_plugin_test/StdAfx.cpp index 1eaa0af77..78580b9f5 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_test/StdAfx.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_test/StdAfx.cpp @@ -1,24 +1,24 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.cpp : source file that includes just the standard includes -// georges_plugin_test.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.cpp : source file that includes just the standard includes +// georges_plugin_test.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/code/ryzom/tools/leveldesign/georges_plugin_test/StdAfx.h b/code/ryzom/tools/leveldesign/georges_plugin_test/StdAfx.h index 4392757c3..230343b59 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_test/StdAfx.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_test/StdAfx.h @@ -1,58 +1,58 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__B0A2DD8B_37A5_4B73_ABC0_99C4E6FECAE1__INCLUDED_) -#define AFX_STDAFX_H__B0A2DD8B_37A5_4B73_ABC0_99C4E6FECAE1__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers - -#include // MFC core and standard components -#include // MFC extensions - -#ifndef _AFX_NO_OLE_SUPPORT -#include // MFC OLE classes -#include // MFC OLE dialog classes -#include // MFC Automation classes -#endif // _AFX_NO_OLE_SUPPORT - - -#ifndef _AFX_NO_DB_SUPPORT -#include // MFC ODBC database classes -#endif // _AFX_NO_DB_SUPPORT - -#ifndef _AFX_NO_DAO_SUPPORT -#include // MFC DAO database classes -#endif // _AFX_NO_DAO_SUPPORT - -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__B0A2DD8B_37A5_4B73_ABC0_99C4E6FECAE1__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__B0A2DD8B_37A5_4B73_ABC0_99C4E6FECAE1__INCLUDED_) +#define AFX_STDAFX_H__B0A2DD8B_37A5_4B73_ABC0_99C4E6FECAE1__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions + +#ifndef _AFX_NO_OLE_SUPPORT +#include // MFC OLE classes +#include // MFC OLE dialog classes +#include // MFC Automation classes +#endif // _AFX_NO_OLE_SUPPORT + + +#ifndef _AFX_NO_DB_SUPPORT +#include // MFC ODBC database classes +#endif // _AFX_NO_DB_SUPPORT + +#ifndef _AFX_NO_DAO_SUPPORT +#include // MFC DAO database classes +#endif // _AFX_NO_DAO_SUPPORT + +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__B0A2DD8B_37A5_4B73_ABC0_99C4E6FECAE1__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/georges_plugin_test/georges_plugin_test.cpp b/code/ryzom/tools/leveldesign/georges_plugin_test/georges_plugin_test.cpp index 20c79d542..7fb7383ac 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_test/georges_plugin_test.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_test/georges_plugin_test.cpp @@ -1,253 +1,253 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// georges_plugin_test.cpp : Defines the initialization routines for the DLL. -// - -#include "stdafx.h" -#include "georges_plugin_test.h" - - -using namespace NLGEORGES; -using namespace std; - -// -// Note! -// -// If this DLL is dynamically linked against the MFC -// DLLs, any functions exported from this DLL which -// call into MFC must have the AFX_MANAGE_STATE macro -// added at the very beginning of the function. -// -// For example: -// -// extern "C" BOOL PASCAL EXPORT ExportedFunction() -// { -// AFX_MANAGE_STATE(AfxGetStaticModuleState()); -// // normal function body here -// } -// -// It is very important that this macro appear in each -// function, prior to any calls into MFC. This means that -// it must appear as the first statement within the -// function, even before any object variable declarations -// as their constructors may generate calls into the MFC -// DLL. -// -// Please see MFC Technical Notes 33 and 58 for additional -// details. -// - -///////////////////////////////////////////////////////////////////////////// -// CGeorges_plugin_testApp - -BEGIN_MESSAGE_MAP(CGeorges_plugin_testApp, CWinApp) - //{{AFX_MSG_MAP(CGeorges_plugin_testApp) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code! - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CGeorges_plugin_testApp construction - -CGeorges_plugin_testApp::CGeorges_plugin_testApp() -{ - // TODO: add construction code here, - // Place all significant initialization in InitInstance -} - -///////////////////////////////////////////////////////////////////////////// -// The one and only CGeorges_plugin_testApp object - -CGeorges_plugin_testApp theApp; - -// *************************************************************************** -// MyDocumentPlugin -// *************************************************************************** - -MyDocumentPlugin::MyDocumentPlugin (IEditDocument *doc) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - Document = doc; - MyLocalDialog.Plugin = this; -} - -// *************************************************************************** - -MyDocumentPlugin::~MyDocumentPlugin () -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - if (IsWindow (MyLocalDialog)) - MyLocalDialog.DestroyWindow (); -} - -// *************************************************************************** - -void MyDocumentPlugin::dialogInit (HWND documentView) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - MyLocalDialog.Create (IDD_TEST_LOCAL, CWnd::FromHandle( documentView )); -} - -// *************************************************************************** - -bool MyDocumentPlugin::pretranslateMessage (MSG *pMsg) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_F3)) - { - MessageBox (NULL, "LOCAL: F3", "Test georges plugin", MB_OK); - } - - return false; -} - -// *************************************************************************** - -void MyDocumentPlugin::activate (bool activated) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - if (IsWindow (MyLocalDialog)) - MyLocalDialog.ShowWindow (activated?SW_SHOW:SW_HIDE); -} - -// *************************************************************************** - -void MyDocumentPlugin::onValueChanged (const char *formName) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - MyLocalDialog.GetDlgItem (IDC_MESSAGE)->SetWindowText (formName); - LastValue = formName; -} - -// *************************************************************************** - -void MyDocumentPlugin::onNodeChanged () -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - string str; - if (Document->getActiveNode (str)) - MyLocalDialog.GetDlgItem (IDC_MESSAGE2)->SetWindowText (str.c_str ()); - else - MyLocalDialog.GetDlgItem (IDC_MESSAGE2)->SetWindowText ("NILL"); -} - -// *************************************************************************** -// MyPlugin -// *************************************************************************** - -MyPlugin::MyPlugin (NLGEORGES::IEdit *globalInterface) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - GlobalInterface = globalInterface; - MyGlobalDialog.Plugin = this; -} - -// *************************************************************************** - -MyPlugin::~MyPlugin () -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - if (IsWindow (MyGlobalDialog)) - MyGlobalDialog.DestroyWindow (); -} - -// *************************************************************************** - -void MyPlugin::dialogInit (HWND mainFrm) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - MyGlobalDialog.Create (IDD_TEST_GLOBAL, CWnd::FromHandle( mainFrm )); -} - -// *************************************************************************** - -bool MyPlugin::pretranslateMessage (MSG *pMsg) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_F1)) - { - MessageBox (NULL, "GLOBAL: F1", "Test georges plugin", MB_OK); - } - - return false; -} - -// *************************************************************************** - -void MyPlugin::onCreateDocument (IEditDocument *document) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - // Set text in the global dialog - string toto; - document->getDfnFilename (toto); - if (IsWindow (MyGlobalDialog)) - MyGlobalDialog.GetDlgItem (IDC_MESSAGE)->SetWindowText (toto.c_str()); - - // Bind an interface on the document - document->bind (this, new MyDocumentPlugin (document)); -} - -// *************************************************************************** - -void MyPlugin::activate (bool activate) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - if (IsWindow (MyGlobalDialog)) - MyGlobalDialog.ShowWindow (activate?SW_SHOW:SW_HIDE); -} - -// *************************************************************************** - -void MyPlugin::getPluginName (std::string &name) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - name = "Test georges plugin"; -} - -// *************************************************************************** - -__declspec( dllexport ) IEditPlugin *IGeorgesEditGetInterface (int version, NLGEORGES::IEdit *globalInterface) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - // Same version ? - if (version == NLGEORGES_PLUGIN_INTERFACE_VERSION) - { - return new MyPlugin (globalInterface); - } - else - { - MessageBox (NULL, "Plugin version invalid.", "Test plugin for georges editor", MB_OK|MB_ICONEXCLAMATION); - return NULL; - } - -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// georges_plugin_test.cpp : Defines the initialization routines for the DLL. +// + +#include "stdafx.h" +#include "georges_plugin_test.h" + + +using namespace NLGEORGES; +using namespace std; + +// +// Note! +// +// If this DLL is dynamically linked against the MFC +// DLLs, any functions exported from this DLL which +// call into MFC must have the AFX_MANAGE_STATE macro +// added at the very beginning of the function. +// +// For example: +// +// extern "C" BOOL PASCAL EXPORT ExportedFunction() +// { +// AFX_MANAGE_STATE(AfxGetStaticModuleState()); +// // normal function body here +// } +// +// It is very important that this macro appear in each +// function, prior to any calls into MFC. This means that +// it must appear as the first statement within the +// function, even before any object variable declarations +// as their constructors may generate calls into the MFC +// DLL. +// +// Please see MFC Technical Notes 33 and 58 for additional +// details. +// + +///////////////////////////////////////////////////////////////////////////// +// CGeorges_plugin_testApp + +BEGIN_MESSAGE_MAP(CGeorges_plugin_testApp, CWinApp) + //{{AFX_MSG_MAP(CGeorges_plugin_testApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGeorges_plugin_testApp construction + +CGeorges_plugin_testApp::CGeorges_plugin_testApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CGeorges_plugin_testApp object + +CGeorges_plugin_testApp theApp; + +// *************************************************************************** +// MyDocumentPlugin +// *************************************************************************** + +MyDocumentPlugin::MyDocumentPlugin (IEditDocument *doc) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + Document = doc; + MyLocalDialog.Plugin = this; +} + +// *************************************************************************** + +MyDocumentPlugin::~MyDocumentPlugin () +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + if (IsWindow (MyLocalDialog)) + MyLocalDialog.DestroyWindow (); +} + +// *************************************************************************** + +void MyDocumentPlugin::dialogInit (HWND documentView) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + MyLocalDialog.Create (IDD_TEST_LOCAL, CWnd::FromHandle( documentView )); +} + +// *************************************************************************** + +bool MyDocumentPlugin::pretranslateMessage (MSG *pMsg) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_F3)) + { + MessageBox (NULL, "LOCAL: F3", "Test georges plugin", MB_OK); + } + + return false; +} + +// *************************************************************************** + +void MyDocumentPlugin::activate (bool activated) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + if (IsWindow (MyLocalDialog)) + MyLocalDialog.ShowWindow (activated?SW_SHOW:SW_HIDE); +} + +// *************************************************************************** + +void MyDocumentPlugin::onValueChanged (const char *formName) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + MyLocalDialog.GetDlgItem (IDC_MESSAGE)->SetWindowText (formName); + LastValue = formName; +} + +// *************************************************************************** + +void MyDocumentPlugin::onNodeChanged () +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + string str; + if (Document->getActiveNode (str)) + MyLocalDialog.GetDlgItem (IDC_MESSAGE2)->SetWindowText (str.c_str ()); + else + MyLocalDialog.GetDlgItem (IDC_MESSAGE2)->SetWindowText ("NILL"); +} + +// *************************************************************************** +// MyPlugin +// *************************************************************************** + +MyPlugin::MyPlugin (NLGEORGES::IEdit *globalInterface) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + GlobalInterface = globalInterface; + MyGlobalDialog.Plugin = this; +} + +// *************************************************************************** + +MyPlugin::~MyPlugin () +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + if (IsWindow (MyGlobalDialog)) + MyGlobalDialog.DestroyWindow (); +} + +// *************************************************************************** + +void MyPlugin::dialogInit (HWND mainFrm) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + MyGlobalDialog.Create (IDD_TEST_GLOBAL, CWnd::FromHandle( mainFrm )); +} + +// *************************************************************************** + +bool MyPlugin::pretranslateMessage (MSG *pMsg) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + if ((pMsg->message == WM_KEYDOWN) && (pMsg->wParam == VK_F1)) + { + MessageBox (NULL, "GLOBAL: F1", "Test georges plugin", MB_OK); + } + + return false; +} + +// *************************************************************************** + +void MyPlugin::onCreateDocument (IEditDocument *document) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + // Set text in the global dialog + string toto; + document->getDfnFilename (toto); + if (IsWindow (MyGlobalDialog)) + MyGlobalDialog.GetDlgItem (IDC_MESSAGE)->SetWindowText (toto.c_str()); + + // Bind an interface on the document + document->bind (this, new MyDocumentPlugin (document)); +} + +// *************************************************************************** + +void MyPlugin::activate (bool activate) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + if (IsWindow (MyGlobalDialog)) + MyGlobalDialog.ShowWindow (activate?SW_SHOW:SW_HIDE); +} + +// *************************************************************************** + +void MyPlugin::getPluginName (std::string &name) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + name = "Test georges plugin"; +} + +// *************************************************************************** + +__declspec( dllexport ) IEditPlugin *IGeorgesEditGetInterface (int version, NLGEORGES::IEdit *globalInterface) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + // Same version ? + if (version == NLGEORGES_PLUGIN_INTERFACE_VERSION) + { + return new MyPlugin (globalInterface); + } + else + { + MessageBox (NULL, "Plugin version invalid.", "Test plugin for georges editor", MB_OK|MB_ICONEXCLAMATION); + return NULL; + } + +} diff --git a/code/ryzom/tools/leveldesign/georges_plugin_test/georges_plugin_test.h b/code/ryzom/tools/leveldesign/georges_plugin_test/georges_plugin_test.h index 8de94f60d..f8b970a9f 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_test/georges_plugin_test.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_test/georges_plugin_test.h @@ -1,96 +1,96 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// georges_plugin_test.h : main header file for the GEORGES_PLUGIN_TEST DLL -// - -#if !defined(AFX_GEORGES_PLUGIN_TEST_H__17C63138_6057_4288_99B4_D1158EE798CA__INCLUDED_) -#define AFX_GEORGES_PLUGIN_TEST_H__17C63138_6057_4288_99B4_D1158EE798CA__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including this file for PCH -#endif - -#include "resource.h" // main symbols - -#include "../georges_dll/plugin_interface.h" -#include "test_local_dialog.h" -#include "test_global_dialog.h" - -///////////////////////////////////////////////////////////////////////////// -// CGeorges_plugin_testApp -// See georges_plugin_test.cpp for the implementation of this class -// - -class CGeorges_plugin_testApp : public CWinApp -{ -public: - CGeorges_plugin_testApp(); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CGeorges_plugin_testApp) - //}}AFX_VIRTUAL - - //{{AFX_MSG(CGeorges_plugin_testApp) - // NOTE - the ClassWizard will add and remove member functions here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -class MyDocumentPlugin : public NLGEORGES::IEditDocumentPlugin -{ -public: - MyDocumentPlugin (NLGEORGES::IEditDocument *doc); - ~MyDocumentPlugin (); - virtual void dialogInit (HWND documentView); - virtual bool pretranslateMessage (MSG *pMsg); - virtual void activate (bool activated); - virtual void onValueChanged (const char *formName); - virtual void onNodeChanged (); - - CTestLocalDialog MyLocalDialog; - NLGEORGES::IEditDocument *Document; - std::string LastValue; -}; - -class MyPlugin : public NLGEORGES::IEditPlugin -{ -public: - // From IEditPlugin - MyPlugin (NLGEORGES::IEdit *globalInterface); - virtual ~MyPlugin (); - virtual void dialogInit (HWND mainFrm); - virtual bool pretranslateMessage (MSG *pMsg); - virtual void onCreateDocument (NLGEORGES::IEditDocument *document); - virtual void activate (bool activate); - virtual void getPluginName (std::string &name); - - CTestGlobalDialog MyGlobalDialog; - NLGEORGES::IEdit *GlobalInterface; -}; - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_GEORGES_PLUGIN_TEST_H__17C63138_6057_4288_99B4_D1158EE798CA__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// georges_plugin_test.h : main header file for the GEORGES_PLUGIN_TEST DLL +// + +#if !defined(AFX_GEORGES_PLUGIN_TEST_H__17C63138_6057_4288_99B4_D1158EE798CA__INCLUDED_) +#define AFX_GEORGES_PLUGIN_TEST_H__17C63138_6057_4288_99B4_D1158EE798CA__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +#include "../georges_dll/plugin_interface.h" +#include "test_local_dialog.h" +#include "test_global_dialog.h" + +///////////////////////////////////////////////////////////////////////////// +// CGeorges_plugin_testApp +// See georges_plugin_test.cpp for the implementation of this class +// + +class CGeorges_plugin_testApp : public CWinApp +{ +public: + CGeorges_plugin_testApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGeorges_plugin_testApp) + //}}AFX_VIRTUAL + + //{{AFX_MSG(CGeorges_plugin_testApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +class MyDocumentPlugin : public NLGEORGES::IEditDocumentPlugin +{ +public: + MyDocumentPlugin (NLGEORGES::IEditDocument *doc); + ~MyDocumentPlugin (); + virtual void dialogInit (HWND documentView); + virtual bool pretranslateMessage (MSG *pMsg); + virtual void activate (bool activated); + virtual void onValueChanged (const char *formName); + virtual void onNodeChanged (); + + CTestLocalDialog MyLocalDialog; + NLGEORGES::IEditDocument *Document; + std::string LastValue; +}; + +class MyPlugin : public NLGEORGES::IEditPlugin +{ +public: + // From IEditPlugin + MyPlugin (NLGEORGES::IEdit *globalInterface); + virtual ~MyPlugin (); + virtual void dialogInit (HWND mainFrm); + virtual bool pretranslateMessage (MSG *pMsg); + virtual void onCreateDocument (NLGEORGES::IEditDocument *document); + virtual void activate (bool activate); + virtual void getPluginName (std::string &name); + + CTestGlobalDialog MyGlobalDialog; + NLGEORGES::IEdit *GlobalInterface; +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_GEORGES_PLUGIN_TEST_H__17C63138_6057_4288_99B4_D1158EE798CA__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/georges_plugin_test/test_global_dialog.cpp b/code/ryzom/tools/leveldesign/georges_plugin_test/test_global_dialog.cpp index eeba056b4..3461b0931 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_test/test_global_dialog.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_test/test_global_dialog.cpp @@ -1,58 +1,58 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// test_global_dialog.cpp : implementation file -// - -#include "stdafx.h" -#include "georges_plugin_test.h" -#include "test_global_dialog.h" - -///////////////////////////////////////////////////////////////////////////// -// CTestGlobalDialog dialog - - -CTestGlobalDialog::CTestGlobalDialog(CWnd* pParent /*=NULL*/) - : CDialog(CTestGlobalDialog::IDD, pParent) -{ - //{{AFX_DATA_INIT(CTestGlobalDialog) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - - -void CTestGlobalDialog::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CTestGlobalDialog) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CTestGlobalDialog, CDialog) - //{{AFX_MSG_MAP(CTestGlobalDialog) - ON_BN_CLICKED(IDC_CREATE_DOC, OnCreateDoc) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CTestGlobalDialog message handlers - -void CTestGlobalDialog::OnCreateDoc() -{ - Plugin->GlobalInterface->createDocument ("item.dfn", "test_new_document_plugin.item"); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// test_global_dialog.cpp : implementation file +// + +#include "stdafx.h" +#include "georges_plugin_test.h" +#include "test_global_dialog.h" + +///////////////////////////////////////////////////////////////////////////// +// CTestGlobalDialog dialog + + +CTestGlobalDialog::CTestGlobalDialog(CWnd* pParent /*=NULL*/) + : CDialog(CTestGlobalDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTestGlobalDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CTestGlobalDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTestGlobalDialog) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTestGlobalDialog, CDialog) + //{{AFX_MSG_MAP(CTestGlobalDialog) + ON_BN_CLICKED(IDC_CREATE_DOC, OnCreateDoc) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CTestGlobalDialog message handlers + +void CTestGlobalDialog::OnCreateDoc() +{ + Plugin->GlobalInterface->createDocument ("item.dfn", "test_new_document_plugin.item"); +} diff --git a/code/ryzom/tools/leveldesign/georges_plugin_test/test_global_dialog.h b/code/ryzom/tools/leveldesign/georges_plugin_test/test_global_dialog.h index 1e2620012..3555b45d1 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_test/test_global_dialog.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_test/test_global_dialog.h @@ -1,63 +1,63 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_TEST_GLOBAL_DIALOG_H__7979954A_B56B_46BB_BD90_F69FD2EE52F7__INCLUDED_) -#define AFX_TEST_GLOBAL_DIALOG_H__7979954A_B56B_46BB_BD90_F69FD2EE52F7__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// test_global_dialog.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CTestGlobalDialog dialog - -class CTestGlobalDialog : public CDialog -{ -// Construction -public: - CTestGlobalDialog(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CTestGlobalDialog) - enum { IDD = IDD_TEST_GLOBAL }; - // NOTE: the ClassWizard will add data members here - //}}AFX_DATA - - class MyPlugin *Plugin; - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CTestGlobalDialog) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CTestGlobalDialog) - afx_msg void OnCreateDoc(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_TEST_GLOBAL_DIALOG_H__7979954A_B56B_46BB_BD90_F69FD2EE52F7__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_TEST_GLOBAL_DIALOG_H__7979954A_B56B_46BB_BD90_F69FD2EE52F7__INCLUDED_) +#define AFX_TEST_GLOBAL_DIALOG_H__7979954A_B56B_46BB_BD90_F69FD2EE52F7__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// test_global_dialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CTestGlobalDialog dialog + +class CTestGlobalDialog : public CDialog +{ +// Construction +public: + CTestGlobalDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CTestGlobalDialog) + enum { IDD = IDD_TEST_GLOBAL }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + class MyPlugin *Plugin; + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CTestGlobalDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CTestGlobalDialog) + afx_msg void OnCreateDoc(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_TEST_GLOBAL_DIALOG_H__7979954A_B56B_46BB_BD90_F69FD2EE52F7__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/georges_plugin_test/test_local_dialog.cpp b/code/ryzom/tools/leveldesign/georges_plugin_test/test_local_dialog.cpp index 860a66ee5..4fc0f2adf 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_test/test_local_dialog.cpp +++ b/code/ryzom/tools/leveldesign/georges_plugin_test/test_local_dialog.cpp @@ -1,84 +1,84 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// test_local_dialog.cpp : implementation file -// - -#include "stdafx.h" -#include "georges_plugin_test.h" -#include "test_local_dialog.h" - -#include "nel/misc/file.h" -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" - -using namespace NLMISC; -using namespace std; - -///////////////////////////////////////////////////////////////////////////// -// CTestLocalDialog dialog - - -CTestLocalDialog::CTestLocalDialog(CWnd* pParent /*=NULL*/) - : CDialog(CTestLocalDialog::IDD, pParent) -{ - //{{AFX_DATA_INIT(CTestLocalDialog) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - - -void CTestLocalDialog::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CTestLocalDialog) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CTestLocalDialog, CDialog) - //{{AFX_MSG_MAP(CTestLocalDialog) - ON_BN_CLICKED(IDC_REFRESH, OnRefresh) - ON_BN_CLICKED(IDC_SET, OnSet) - ON_BN_CLICKED(IDC_SAVE, OnSave) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CTestLocalDialog message handlers - -void CTestLocalDialog::OnRefresh() -{ - Plugin->Document->refreshView (); -} - -void CTestLocalDialog::OnSet() -{ - Plugin->Document->setValue ("test set value", Plugin->LastValue.c_str ()); - // Plugin->Document->refreshView (); -} - -void CTestLocalDialog::OnSave() -{ - CFileDialog dialog (FALSE); - if (dialog.DoModal () == IDOK) - { - string name = (const char*)dialog.GetPathName (); - COFile file (name.c_str ()); - Plugin->Document->getForm ()->write (file, true); - } -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// test_local_dialog.cpp : implementation file +// + +#include "stdafx.h" +#include "georges_plugin_test.h" +#include "test_local_dialog.h" + +#include "nel/misc/file.h" +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" + +using namespace NLMISC; +using namespace std; + +///////////////////////////////////////////////////////////////////////////// +// CTestLocalDialog dialog + + +CTestLocalDialog::CTestLocalDialog(CWnd* pParent /*=NULL*/) + : CDialog(CTestLocalDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTestLocalDialog) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CTestLocalDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTestLocalDialog) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTestLocalDialog, CDialog) + //{{AFX_MSG_MAP(CTestLocalDialog) + ON_BN_CLICKED(IDC_REFRESH, OnRefresh) + ON_BN_CLICKED(IDC_SET, OnSet) + ON_BN_CLICKED(IDC_SAVE, OnSave) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CTestLocalDialog message handlers + +void CTestLocalDialog::OnRefresh() +{ + Plugin->Document->refreshView (); +} + +void CTestLocalDialog::OnSet() +{ + Plugin->Document->setValue ("test set value", Plugin->LastValue.c_str ()); + // Plugin->Document->refreshView (); +} + +void CTestLocalDialog::OnSave() +{ + CFileDialog dialog (FALSE); + if (dialog.DoModal () == IDOK) + { + string name = (const char*)dialog.GetPathName (); + COFile file (name.c_str ()); + Plugin->Document->getForm ()->write (file, true); + } +} diff --git a/code/ryzom/tools/leveldesign/georges_plugin_test/test_local_dialog.h b/code/ryzom/tools/leveldesign/georges_plugin_test/test_local_dialog.h index 7488cc34a..ca6c053a2 100644 --- a/code/ryzom/tools/leveldesign/georges_plugin_test/test_local_dialog.h +++ b/code/ryzom/tools/leveldesign/georges_plugin_test/test_local_dialog.h @@ -1,65 +1,65 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_TEST_LOCAL_DIALOG_H__D6FE10F8_A2E7_4166_AD85_D8C05B599E2A__INCLUDED_) -#define AFX_TEST_LOCAL_DIALOG_H__D6FE10F8_A2E7_4166_AD85_D8C05B599E2A__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// test_local_dialog.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CTestLocalDialog dialog - -class CTestLocalDialog : public CDialog -{ -// Construction -public: - CTestLocalDialog(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CTestLocalDialog) - enum { IDD = IDD_TEST_LOCAL }; - // NOTE: the ClassWizard will add data members here - //}}AFX_DATA - - class MyDocumentPlugin *Plugin; - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CTestLocalDialog) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CTestLocalDialog) - afx_msg void OnRefresh(); - afx_msg void OnSet(); - afx_msg void OnSave(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_TEST_LOCAL_DIALOG_H__D6FE10F8_A2E7_4166_AD85_D8C05B599E2A__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_TEST_LOCAL_DIALOG_H__D6FE10F8_A2E7_4166_AD85_D8C05B599E2A__INCLUDED_) +#define AFX_TEST_LOCAL_DIALOG_H__D6FE10F8_A2E7_4166_AD85_D8C05B599E2A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// test_local_dialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CTestLocalDialog dialog + +class CTestLocalDialog : public CDialog +{ +// Construction +public: + CTestLocalDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CTestLocalDialog) + enum { IDD = IDD_TEST_LOCAL }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + class MyDocumentPlugin *Plugin; + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CTestLocalDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CTestLocalDialog) + afx_msg void OnRefresh(); + afx_msg void OnSet(); + afx_msg void OnSave(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_TEST_LOCAL_DIALOG_H__D6FE10F8_A2E7_4166_AD85_D8C05B599E2A__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/icon_search/icon_search.cpp b/code/ryzom/tools/leveldesign/icon_search/icon_search.cpp index 2e95ad694..7d406ec8c 100644 --- a/code/ryzom/tools/leveldesign/icon_search/icon_search.cpp +++ b/code/ryzom/tools/leveldesign/icon_search/icon_search.cpp @@ -1,392 +1,392 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include -#include -#include -#include -#include - -#include -#include - -#include - -using namespace NLMISC; -using namespace std; - -CSString REP_SRC; //= "R:\\code\\ryzom\\src_v2\\client\\"; -CSString REP_GUI; //= "R:\\code\\ryzom\\data\\gamedev\\interfaces_v3\\"; -CSString REP_ITEM; //= "R:\\code\\ryzom\\data_leveldesign\\leveldesign\\Game_elem\\items\\"; -CSString REP_MISSION; //= "R:\\code\\ryzom\\data_leveldesign\\leveldesign\\Game_elem\\mission\\"; -CSString REP_SITEM; //= "R:\\code\\ryzom\\data_leveldesign\\leveldesign\\game_element\\sitem\\"; -CSString REP_SBRICK; //= "R:\\code\\ryzom\\data_leveldesign\\leveldesign\\game_element\\sbrick\\"; -CSString REP_DFN; //= "R:\\code\\ryzom\\data_leveldesign\\leveldesign\\DFN\\"; -CSString REP_FACTION;// = "R:\\code\\ryzom\\data_leveldesign\\leveldesign\\World\\factions\\"; - -typedef vector StringVector; -StringVector listeIcones; -map citations; - -bool addUsedIcons = true; -bool addFreeIcons = true; - - -// Fill listeIcones from source directories -void findIcons(CConfigFile::CVar *var) -{ - nlassert(var != NULL); - - // clear vector - listeIcones.clear(); - vector files; - - // Scan each directory - for (uint i=0 ; isize() ; i++) - { - // clear files list - files.clear(); - - // get files list - CPath::getPathContent(CPath::standardizePath(var->asString(i)), false, false, true, files); - - // Convert each file - for (uint j=0 ; j 1 && !addUsedIcons)) - return; - - // begin line - writeString(f, ""); - - // write icon as jpg - writeString(f, ""); - - // fix limit based on configuration file - uint n; - if (sizeLimit == 0) - n = (uint)files.size(); - else - n = sizeLimit > files.size() ? (uint)files.size() : sizeLimit; - - // write each file using this icon - for (uint i=0 ; i" + files[i] + ""); - - // end line - writeString(f, "\n"); -} - -void generateHTML(const string &name, uint sizeLimit) -{ - COFile f; - nlassert(f.open(name, false, true)); - - // write header - writeString(f, "\n\nNevrax - Ryzom icons\n\n\n\n"); - - // write lines - for (map::iterator it = citations.begin(); it != citations.end(); ++it) - { - string str = it->second[0]; - writeHTMLline(f, str, it->second, sizeLimit); - } - - // write end - writeString(f, "
\n"); - - f.close(); -} - -void tga2Jpg(const string &tga, const string &jpg) -{ - // read TGA - CIFile fTga; - CBitmap im; - nlassert(fTga.open(tga)); - nlassert(im.load(fTga)); - fTga.close(); - - // write JPG - COFile fJpg; - nlassert(fJpg.open(jpg)); - nlassert(im.writeJPG(fJpg)); - fJpg.close(); -} - -void convertImages(CConfigFile::CVar *var) -{ - nlassert(var != NULL); - - // store current path - string curPath = CPath::standardizePath(CPath::getCurrentPath()); - - // Create 'images' directory in the root folder if not present - if (!CFile::isExists("images")) - CFile::createDirectory("images"); - - // Scan each directory - for (uint i=0 ; isize() ; i++) - { - string path = CPath::standardizePath(var->asString(i)); - vector files; - CPath::getPathContent(path, false, false, true, files); - - // Convert each file - for (uint j=0 ; jsize() << " - " << j+1 << " / " << files.size() << ") : " << file << " ... "; - - // Convert the file - if (!CFile::isExists(dst)) - { - tga2Jpg(src, dst); - cout << " OK\n"; - } - else - { - cout << "skipped\n"; - } - } - } -} - -bool endsWith( const CSString& s, const CSString& substring ) -{ - return ( s.right( (uint)substring.size() ) == substring ); -} - -void ProcessDirectory( const CSString& dir, const StringVector& extensions ) -{ - CSString data; - int nbResults = 0; - int sixieme; - vector files; - - - printf( "%s\n", dir.c_str() ); - CPath::getPathContent ( dir.c_str(), true, false, true, files ); - - sixieme = (int)files.size() / 6; - - printf( "%u files are processed", (uint) files.size() ); - - for (uint32 i=0; i"); - if (n != CSString::npos) - data.erase(n); - - data = data.toLower(); - - for ( uint it=0; itasInt(); - - var = cf.getVarPtr("ClientSrcPath"); - nlassert(var); - REP_SRC = var->asString(); - - var = cf.getVarPtr("SearchGUI"); - nlassert(var); - searchGui = var->asInt(); - - var = cf.getVarPtr("GUIPath"); - nlassert(var); - REP_GUI = var->asString(); - - var = cf.getVarPtr("SearchLevelDesign"); - nlassert(var); - searchLevelDesign = var->asInt(); - - var = cf.getVarPtr("LevelDesignPath"); - nlassert(var); - REP_LEVEL_DESIGN = var->asString(); - - var = cf.getVarPtr("IconPath"); - nlassert(var); - convertImages(var); - findIcons(var); - - var = cf.getVarPtr("SizeLimit"); - if (var) - sizeLimit = (uint)var->asInt(); - - var = cf.getVarPtr("AddUsedIcons"); - if (var) - addUsedIcons = var->asBool(); - - var = cf.getVarPtr("AddFreeIcons"); - if (var) - addFreeIcons = var->asBool(); - - REP_ITEM = REP_LEVEL_DESIGN + "leveldesign\\Game_elem\\items\\"; - REP_MISSION = REP_LEVEL_DESIGN + "leveldesign\\Game_elem\\mission\\"; - REP_SITEM = REP_LEVEL_DESIGN + "leveldesign\\game_element\\sitem\\"; - REP_SBRICK = REP_LEVEL_DESIGN + "leveldesign\\game_element\\sbrick\\"; - REP_DFN = REP_LEVEL_DESIGN + "leveldesign\\DFN\\"; - REP_FACTION = REP_LEVEL_DESIGN + "leveldesign\\World\\factions\\"; - - var = cf.getVarPtr("Wildcard"); - if (var) - for (uint i=0 ; isize() ; i++) - for (uint it=0; itasString(i); - if (testWildCard(listeIcones[it], wild)) - { - citations[listeIcones[it]].push_back("Matched with: " + wild); - } - } - - printf( "\nProcessing Directories\n----------------------\n\n" ); - - - // CLIENT SRC FILES - if ( searchSrcClient ) - { - extensions.push_back( "cpp" ); - extensions.push_back( "h" ); - ProcessDirectory( REP_SRC, extensions ); - } - - // GUI FILES - if ( searchGui ) - { - extensions.clear(); - extensions.push_back( "xml" ); - ProcessDirectory( REP_GUI, extensions ); - } - - if ( searchLevelDesign ) - { - // ITEM FILES - extensions.clear(); - extensions.push_back( "item" ); - ProcessDirectory( REP_ITEM, extensions ); - - // MISSION FILES - extensions.clear(); - extensions.push_back( "mission_icon" ); - ProcessDirectory( REP_MISSION, extensions ); - - // SITEM FILES - extensions.clear(); - extensions.push_back( "sitem" ); - ProcessDirectory( REP_SITEM, extensions ); - - // SBRICK FILES - extensions.clear(); - extensions.push_back( "sbrick" ); - ProcessDirectory( REP_SBRICK, extensions ); - - // DFN FILES - extensions.clear(); - extensions.push_back( "dfn" ); - ProcessDirectory( REP_DFN, extensions ); - - // FACTION FILES - extensions.clear(); - extensions.push_back( "faction" ); - ProcessDirectory( REP_FACTION, extensions ); - } - - generateHTML("icons.html", sizeLimit); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include +#include +#include +#include + +#include +#include + +#include + +using namespace NLMISC; +using namespace std; + +CSString REP_SRC; //= "R:\\code\\ryzom\\src_v2\\client\\"; +CSString REP_GUI; //= "R:\\code\\ryzom\\data\\gamedev\\interfaces_v3\\"; +CSString REP_ITEM; //= "R:\\code\\ryzom\\data_leveldesign\\leveldesign\\Game_elem\\items\\"; +CSString REP_MISSION; //= "R:\\code\\ryzom\\data_leveldesign\\leveldesign\\Game_elem\\mission\\"; +CSString REP_SITEM; //= "R:\\code\\ryzom\\data_leveldesign\\leveldesign\\game_element\\sitem\\"; +CSString REP_SBRICK; //= "R:\\code\\ryzom\\data_leveldesign\\leveldesign\\game_element\\sbrick\\"; +CSString REP_DFN; //= "R:\\code\\ryzom\\data_leveldesign\\leveldesign\\DFN\\"; +CSString REP_FACTION;// = "R:\\code\\ryzom\\data_leveldesign\\leveldesign\\World\\factions\\"; + +typedef vector StringVector; +StringVector listeIcones; +map citations; + +bool addUsedIcons = true; +bool addFreeIcons = true; + + +// Fill listeIcones from source directories +void findIcons(CConfigFile::CVar *var) +{ + nlassert(var != NULL); + + // clear vector + listeIcones.clear(); + vector files; + + // Scan each directory + for (uint i=0 ; isize() ; i++) + { + // clear files list + files.clear(); + + // get files list + CPath::getPathContent(CPath::standardizePath(var->asString(i)), false, false, true, files); + + // Convert each file + for (uint j=0 ; j 1 && !addUsedIcons)) + return; + + // begin line + writeString(f, ""); + + // write icon as jpg + writeString(f, ""); + + // fix limit based on configuration file + uint n; + if (sizeLimit == 0) + n = (uint)files.size(); + else + n = sizeLimit > files.size() ? (uint)files.size() : sizeLimit; + + // write each file using this icon + for (uint i=0 ; i" + files[i] + ""); + + // end line + writeString(f, "\n"); +} + +void generateHTML(const string &name, uint sizeLimit) +{ + COFile f; + nlassert(f.open(name, false, true)); + + // write header + writeString(f, "\n\nNevrax - Ryzom icons\n\n\n\n"); + + // write lines + for (map::iterator it = citations.begin(); it != citations.end(); ++it) + { + string str = it->second[0]; + writeHTMLline(f, str, it->second, sizeLimit); + } + + // write end + writeString(f, "
\n"); + + f.close(); +} + +void tga2Jpg(const string &tga, const string &jpg) +{ + // read TGA + CIFile fTga; + CBitmap im; + nlassert(fTga.open(tga)); + nlassert(im.load(fTga)); + fTga.close(); + + // write JPG + COFile fJpg; + nlassert(fJpg.open(jpg)); + nlassert(im.writeJPG(fJpg)); + fJpg.close(); +} + +void convertImages(CConfigFile::CVar *var) +{ + nlassert(var != NULL); + + // store current path + string curPath = CPath::standardizePath(CPath::getCurrentPath()); + + // Create 'images' directory in the root folder if not present + if (!CFile::isExists("images")) + CFile::createDirectory("images"); + + // Scan each directory + for (uint i=0 ; isize() ; i++) + { + string path = CPath::standardizePath(var->asString(i)); + vector files; + CPath::getPathContent(path, false, false, true, files); + + // Convert each file + for (uint j=0 ; jsize() << " - " << j+1 << " / " << files.size() << ") : " << file << " ... "; + + // Convert the file + if (!CFile::isExists(dst)) + { + tga2Jpg(src, dst); + cout << " OK\n"; + } + else + { + cout << "skipped\n"; + } + } + } +} + +bool endsWith( const CSString& s, const CSString& substring ) +{ + return ( s.right( (uint)substring.size() ) == substring ); +} + +void ProcessDirectory( const CSString& dir, const StringVector& extensions ) +{ + CSString data; + int nbResults = 0; + int sixieme; + vector files; + + + printf( "%s\n", dir.c_str() ); + CPath::getPathContent ( dir.c_str(), true, false, true, files ); + + sixieme = (int)files.size() / 6; + + printf( "%u files are processed", (uint) files.size() ); + + for (uint32 i=0; i"); + if (n != CSString::npos) + data.erase(n); + + data = data.toLower(); + + for ( uint it=0; itasInt(); + + var = cf.getVarPtr("ClientSrcPath"); + nlassert(var); + REP_SRC = var->asString(); + + var = cf.getVarPtr("SearchGUI"); + nlassert(var); + searchGui = var->asInt(); + + var = cf.getVarPtr("GUIPath"); + nlassert(var); + REP_GUI = var->asString(); + + var = cf.getVarPtr("SearchLevelDesign"); + nlassert(var); + searchLevelDesign = var->asInt(); + + var = cf.getVarPtr("LevelDesignPath"); + nlassert(var); + REP_LEVEL_DESIGN = var->asString(); + + var = cf.getVarPtr("IconPath"); + nlassert(var); + convertImages(var); + findIcons(var); + + var = cf.getVarPtr("SizeLimit"); + if (var) + sizeLimit = (uint)var->asInt(); + + var = cf.getVarPtr("AddUsedIcons"); + if (var) + addUsedIcons = var->asBool(); + + var = cf.getVarPtr("AddFreeIcons"); + if (var) + addFreeIcons = var->asBool(); + + REP_ITEM = REP_LEVEL_DESIGN + "leveldesign\\Game_elem\\items\\"; + REP_MISSION = REP_LEVEL_DESIGN + "leveldesign\\Game_elem\\mission\\"; + REP_SITEM = REP_LEVEL_DESIGN + "leveldesign\\game_element\\sitem\\"; + REP_SBRICK = REP_LEVEL_DESIGN + "leveldesign\\game_element\\sbrick\\"; + REP_DFN = REP_LEVEL_DESIGN + "leveldesign\\DFN\\"; + REP_FACTION = REP_LEVEL_DESIGN + "leveldesign\\World\\factions\\"; + + var = cf.getVarPtr("Wildcard"); + if (var) + for (uint i=0 ; isize() ; i++) + for (uint it=0; itasString(i); + if (testWildCard(listeIcones[it], wild)) + { + citations[listeIcones[it]].push_back("Matched with: " + wild); + } + } + + printf( "\nProcessing Directories\n----------------------\n\n" ); + + + // CLIENT SRC FILES + if ( searchSrcClient ) + { + extensions.push_back( "cpp" ); + extensions.push_back( "h" ); + ProcessDirectory( REP_SRC, extensions ); + } + + // GUI FILES + if ( searchGui ) + { + extensions.clear(); + extensions.push_back( "xml" ); + ProcessDirectory( REP_GUI, extensions ); + } + + if ( searchLevelDesign ) + { + // ITEM FILES + extensions.clear(); + extensions.push_back( "item" ); + ProcessDirectory( REP_ITEM, extensions ); + + // MISSION FILES + extensions.clear(); + extensions.push_back( "mission_icon" ); + ProcessDirectory( REP_MISSION, extensions ); + + // SITEM FILES + extensions.clear(); + extensions.push_back( "sitem" ); + ProcessDirectory( REP_SITEM, extensions ); + + // SBRICK FILES + extensions.clear(); + extensions.push_back( "sbrick" ); + ProcessDirectory( REP_SBRICK, extensions ); + + // DFN FILES + extensions.clear(); + extensions.push_back( "dfn" ); + ProcessDirectory( REP_DFN, extensions ); + + // FACTION FILES + extensions.clear(); + extensions.push_back( "faction" ); + ProcessDirectory( REP_FACTION, extensions ); + } + + generateHTML("icons.html", sizeLimit); +} diff --git a/code/ryzom/tools/leveldesign/install/history.txt b/code/ryzom/tools/leveldesign/install/history.txt index 039194ddc..687caacde 100644 --- a/code/ryzom/tools/leveldesign/install/history.txt +++ b/code/ryzom/tools/leveldesign/install/history.txt @@ -1,257 +1,257 @@ -NeL World Editor History - -v0.47 : new age - -Fixed: crash when deleting primitive -Fixed: crash in MOS -Fixed: infinite loop at the startup - -v0.46 - -CHANGED : Better looking for 'search and replace' dialog box - -v0.45 - -FIXED : collapse tree don't work. - -v0.44 - -FIXED : ramdom crash and weird behavior of property editro dialof after a move of primitive in - the tree fdollowed by an edition of properties with ALT+enter - -v0.43 - -CHANGED : edition node properties (hidden, selected and expanded) are all stored as XML comment - int the primitive files. This allow more efficient comparison of real content in - primitive files. - -v0.42 - -FIXED : when reloading a primitive, the tree view is correctly updated. -FIXED : since new stable alias system, WE crash when relading an externaly modified primitive. - -v0.41 - -ADDED : In property dialog, if closing or changing primitive selection without commiting the - changed property, the application will warn the user and propose to save - or discard it's modification. - -ADDED : Keyboard control of the tree view while editing in property dialog. - Just press ALT and arrows keys to change the selection in the tree view. - -v0.40 - -CHANGED : reworked 'properties' dialog, now support keyboard shurtcuts to update/cancel - or validate the dialog. - The dialog also support 'tab' to move between controls - -ADDED : plugin interface to replace the standard primitive drawing code. Each plugin - can claim to be called to draw a liste of primitive types. - -v0.39 - -FIXED : Multiple primitive file open dialog work with more than a few primitives selected. - -v0.38 - -FIXED : load, save edit unicode primitives. - -v0.37 - -FIXED : multiple assert when error detected in the tree structure - -v0.36 - -ADDED : copy / paste in new combo boxes - -v0.35 - -FIXED : Const string keybord selection work fine now - -v0.34 - -FIXED : Select by category is no more case sensitive -FIXED : Can't move root tree nodes anymore. "nouveau projet, ajouter au moins deux landscapes, essayer de changer leur ordre en faisant ctrl + flèche, kaboum rq : pas la peine de spécifier les settings, suffit qu'il y ait deux lands, ça marche aussi avec des primitves, visiblement avec tous les trucs root." -FIXED : Log are flooded using "primitive configurations" -FIXED : "lorsque l'on copie-colle une instance, la première ainsi collée porte le même nom que l'original alors que toutes les autres après ont un numéro bien incrémenté." -FIXED : Copy works when several primitives are selected -ADDED : Button to show / hide collision -ADDED : Meter point grid -FIXED : Properties window get larger when JC's scrollbar is used -ADDED : JC's scrollbar track message handled -ADDED : JC's scrollbar works with the mouse wheel - -v0.33 - -ADDED : Display PACS surfaces, just copy PACS .lr, .rbank and .gr in your "data directory"/pacs. - -v0.32 - -CHANGED : Can read binary and xml .land files - -v0.31 - -FIXED : error and continue when loading prb - -v0.30 - -FIXED : Renommer le fichier après la sauvegarde -FIXED : charge tout de meme le continent, meme si une transition utilise des matériels inconnus. - -v0.29 - -FIXED : Values in const_string_array was always by default. -FIXED : Default values in const_string_array work now. -CHANGED : Autoname for string_array and const_string_array copy all the content of the array and not only the first line. - -v0.28 - -ADDED : ALT + LEFT click to drag the view -FIXED : Si selectionne une primitive dans l'arbre (zone, point ou path), tu fait 'locate' et zoom arriere et paf, ca plante. -FIXED : Peut pas charger 2 .land -FIXED : Lorsque l'on efface des zones dans un .land, la boite englobante du continent est recalculée. -FIXED : Salut on crash le world editor des que l'on zoom peux tu voir ca please merci ! -FIXED : Le bouton View à droite des boites const_string_array crashe. Maintenant il fonctionne. -FIXED : On ne peut pas ajouter autant d'éléments qu'on veut dans un const_string_array car la boite n'a pas d'ascenseur. On peut ajouter des lignes avec "INSERT". -KNOWN BUG : Crash when paint several continent at a time : ask Trap - -v0.27 - -ADDED : Primitive configuration check strings in array too -ADDED : Const string array (new property type, TYPE="const_string_array") -ADDED : Zoom on cursor -ADDED : Option to not add number when copy -FIXED : Copy / paste of generated primitives allowed (for ex: .prim children of a .flora_zone) -FIXED : A right click when draging an object followed by a left click lead to an assert. Now a right click cancel the action. -FIXED : Zoom with left click + shift -FIXED : Crash when UNDO/REDO a copy of a primitive with unique ID parameters - -v0.26 - -FIXED : some bug fixed in configurations selection -ADDED : configurations popup menu with SHOW / HIDE / SELECT options - -v0.25 - -ADDED : primitive configurations - -v0.24 - -ADDED : create a new landscape -FIXED : crash when paint a larger landscape -ADDED : export continent snapshot - -v0.23 - -ADDED : shard monitor plugin for the world editor - -v0.22 - -FIXED : autorename rework with the new default value system -REMARK : auto rename is not working for the moment. You can replace it by set an empty name string in the primitive you want to rename - -v0.21 - -FIXED : multi properties edition fixed - -v0.20 - -CHANGED : edit string array with a multi line text window - -v0.19 - -FIXED : error structure fixed (the node with the error is now marked with the error icon too) -CHANGED : some shortcuts are available in the properties dialog (help, new, open etc..) -CHANGED : ligo use a class primitive xml to get the default value in the application reading primitive files -CHANGED : set node that doesn't exist or are empty to default -FIXED : checkbox default value fixed -ADDED : add a history file -ADDED : show collisions in world editor - -v0.18 - -CHANGED : 3 states choeck box for default value -CHANGED : empty string stand for default value - -v0.17 - -FIXED : Edit string array -ADDED : Search the primitives matching a property value (CTRL+F) - -v0.16 - -ADDED : Dialog non modale -ADDED : Find items in the tree -FIXED : Debug plant on path -ADDED : Reset unique id function -FIXED : Copy / paste -> unique id updated - -v0.15 - -FIXED : select update tree bug -FIXED : expand / collapse update tree bug -FIXED : bigger primitive name -FIXED : "new_" removed - -v0.14 - -FIXED : Bug ctrl + flèches dans l'arbre -ADDED : Initialise default value for hidden values -ADDED : Draw arrow in path -FIXED : Modify the document when initialise default values -FIXED : Ligozone name not cropped anymore - -v0.13 - -CHANGED : The dialog property is always dispayed, even if it is too large. -CHANGED : Empty unique ID properties are initialised when a primitive file is loaded. A message box warn you when properties has been -initialised. - -For the moment, i initialise default values ONLY for properties with unique id. I'm afraid to loose information if i initialise all -the empty properties with their default values. - -v0.12 - -FIXED : Delete primitives and the root lead to a crash -FIXED : Delete a sub primitive and undo -> refresh prb -NOTABUG : Select by position bug -FIXED : Click-select and drag bug -ADDED : Default parameter value can be a unique number - -Pour initialiser une propriété d'une primitive avec un identifiant "unique", ajoutez la ligne - dans le noeud XML de la propriété en question. - -v0.11 - -ADDED : Select primitive by location -ADDED : Locate selected primitives -FIXED : Refresh bug when rename a primitive -FIXED : Crash when try to delete a non deletable primitve then delete all the primitive -FIXED : Crash when delete multiple vertices in sub object - -v0.10 - -FIXED : Select foire un peu.. -FIXED : AddPrimitive crash - -v0.7 - -FIXED : Vegetation -FIXED : Combo parameters can be a list of filename get per extension in a directory context dependent -FIXED : Generate function over a zone or a path primitive -FIXED : Load zones overlapped by generator primitives -FIXED : Test collision with others primitives of class .plant and their radius -FIXED : Radius -FIXED : Mini documentation -FIXED : Relative pathes in .worldeditor - -v0.3 - -CHANGED : Script updaté -CHANGED : Link des points d'un group_fauna -CHANGED : Copier / couper / coller de primitive -CHANGED : Menu click droit plus intelligent -CHANGED : Icone du programme -CHANGED : On ne peut plus effacer les primitives "crées en dure" -CHANGED : Pleins de bugs en moins -CHANGED : Y'avait d'autre truc mais je ne me rappel pas de tout.. :) +NeL World Editor History + +v0.47 : new age + +Fixed: crash when deleting primitive +Fixed: crash in MOS +Fixed: infinite loop at the startup + +v0.46 + +CHANGED : Better looking for 'search and replace' dialog box + +v0.45 + +FIXED : collapse tree don't work. + +v0.44 + +FIXED : ramdom crash and weird behavior of property editro dialof after a move of primitive in + the tree fdollowed by an edition of properties with ALT+enter + +v0.43 + +CHANGED : edition node properties (hidden, selected and expanded) are all stored as XML comment + int the primitive files. This allow more efficient comparison of real content in + primitive files. + +v0.42 + +FIXED : when reloading a primitive, the tree view is correctly updated. +FIXED : since new stable alias system, WE crash when relading an externaly modified primitive. + +v0.41 + +ADDED : In property dialog, if closing or changing primitive selection without commiting the + changed property, the application will warn the user and propose to save + or discard it's modification. + +ADDED : Keyboard control of the tree view while editing in property dialog. + Just press ALT and arrows keys to change the selection in the tree view. + +v0.40 + +CHANGED : reworked 'properties' dialog, now support keyboard shurtcuts to update/cancel + or validate the dialog. + The dialog also support 'tab' to move between controls + +ADDED : plugin interface to replace the standard primitive drawing code. Each plugin + can claim to be called to draw a liste of primitive types. + +v0.39 + +FIXED : Multiple primitive file open dialog work with more than a few primitives selected. + +v0.38 + +FIXED : load, save edit unicode primitives. + +v0.37 + +FIXED : multiple assert when error detected in the tree structure + +v0.36 + +ADDED : copy / paste in new combo boxes + +v0.35 + +FIXED : Const string keybord selection work fine now + +v0.34 + +FIXED : Select by category is no more case sensitive +FIXED : Can't move root tree nodes anymore. "nouveau projet, ajouter au moins deux landscapes, essayer de changer leur ordre en faisant ctrl + flèche, kaboum rq : pas la peine de spécifier les settings, suffit qu'il y ait deux lands, ça marche aussi avec des primitves, visiblement avec tous les trucs root." +FIXED : Log are flooded using "primitive configurations" +FIXED : "lorsque l'on copie-colle une instance, la première ainsi collée porte le même nom que l'original alors que toutes les autres après ont un numéro bien incrémenté." +FIXED : Copy works when several primitives are selected +ADDED : Button to show / hide collision +ADDED : Meter point grid +FIXED : Properties window get larger when JC's scrollbar is used +ADDED : JC's scrollbar track message handled +ADDED : JC's scrollbar works with the mouse wheel + +v0.33 + +ADDED : Display PACS surfaces, just copy PACS .lr, .rbank and .gr in your "data directory"/pacs. + +v0.32 + +CHANGED : Can read binary and xml .land files + +v0.31 + +FIXED : error and continue when loading prb + +v0.30 + +FIXED : Renommer le fichier après la sauvegarde +FIXED : charge tout de meme le continent, meme si une transition utilise des matériels inconnus. + +v0.29 + +FIXED : Values in const_string_array was always by default. +FIXED : Default values in const_string_array work now. +CHANGED : Autoname for string_array and const_string_array copy all the content of the array and not only the first line. + +v0.28 + +ADDED : ALT + LEFT click to drag the view +FIXED : Si selectionne une primitive dans l'arbre (zone, point ou path), tu fait 'locate' et zoom arriere et paf, ca plante. +FIXED : Peut pas charger 2 .land +FIXED : Lorsque l'on efface des zones dans un .land, la boite englobante du continent est recalculée. +FIXED : Salut on crash le world editor des que l'on zoom peux tu voir ca please merci ! +FIXED : Le bouton View à droite des boites const_string_array crashe. Maintenant il fonctionne. +FIXED : On ne peut pas ajouter autant d'éléments qu'on veut dans un const_string_array car la boite n'a pas d'ascenseur. On peut ajouter des lignes avec "INSERT". +KNOWN BUG : Crash when paint several continent at a time : ask Trap + +v0.27 + +ADDED : Primitive configuration check strings in array too +ADDED : Const string array (new property type, TYPE="const_string_array") +ADDED : Zoom on cursor +ADDED : Option to not add number when copy +FIXED : Copy / paste of generated primitives allowed (for ex: .prim children of a .flora_zone) +FIXED : A right click when draging an object followed by a left click lead to an assert. Now a right click cancel the action. +FIXED : Zoom with left click + shift +FIXED : Crash when UNDO/REDO a copy of a primitive with unique ID parameters + +v0.26 + +FIXED : some bug fixed in configurations selection +ADDED : configurations popup menu with SHOW / HIDE / SELECT options + +v0.25 + +ADDED : primitive configurations + +v0.24 + +ADDED : create a new landscape +FIXED : crash when paint a larger landscape +ADDED : export continent snapshot + +v0.23 + +ADDED : shard monitor plugin for the world editor + +v0.22 + +FIXED : autorename rework with the new default value system +REMARK : auto rename is not working for the moment. You can replace it by set an empty name string in the primitive you want to rename + +v0.21 + +FIXED : multi properties edition fixed + +v0.20 + +CHANGED : edit string array with a multi line text window + +v0.19 + +FIXED : error structure fixed (the node with the error is now marked with the error icon too) +CHANGED : some shortcuts are available in the properties dialog (help, new, open etc..) +CHANGED : ligo use a class primitive xml to get the default value in the application reading primitive files +CHANGED : set node that doesn't exist or are empty to default +FIXED : checkbox default value fixed +ADDED : add a history file +ADDED : show collisions in world editor + +v0.18 + +CHANGED : 3 states choeck box for default value +CHANGED : empty string stand for default value + +v0.17 + +FIXED : Edit string array +ADDED : Search the primitives matching a property value (CTRL+F) + +v0.16 + +ADDED : Dialog non modale +ADDED : Find items in the tree +FIXED : Debug plant on path +ADDED : Reset unique id function +FIXED : Copy / paste -> unique id updated + +v0.15 + +FIXED : select update tree bug +FIXED : expand / collapse update tree bug +FIXED : bigger primitive name +FIXED : "new_" removed + +v0.14 + +FIXED : Bug ctrl + flèches dans l'arbre +ADDED : Initialise default value for hidden values +ADDED : Draw arrow in path +FIXED : Modify the document when initialise default values +FIXED : Ligozone name not cropped anymore + +v0.13 + +CHANGED : The dialog property is always dispayed, even if it is too large. +CHANGED : Empty unique ID properties are initialised when a primitive file is loaded. A message box warn you when properties has been +initialised. + +For the moment, i initialise default values ONLY for properties with unique id. I'm afraid to loose information if i initialise all +the empty properties with their default values. + +v0.12 + +FIXED : Delete primitives and the root lead to a crash +FIXED : Delete a sub primitive and undo -> refresh prb +NOTABUG : Select by position bug +FIXED : Click-select and drag bug +ADDED : Default parameter value can be a unique number + +Pour initialiser une propriété d'une primitive avec un identifiant "unique", ajoutez la ligne + dans le noeud XML de la propriété en question. + +v0.11 + +ADDED : Select primitive by location +ADDED : Locate selected primitives +FIXED : Refresh bug when rename a primitive +FIXED : Crash when try to delete a non deletable primitve then delete all the primitive +FIXED : Crash when delete multiple vertices in sub object + +v0.10 + +FIXED : Select foire un peu.. +FIXED : AddPrimitive crash + +v0.7 + +FIXED : Vegetation +FIXED : Combo parameters can be a list of filename get per extension in a directory context dependent +FIXED : Generate function over a zone or a path primitive +FIXED : Load zones overlapped by generator primitives +FIXED : Test collision with others primitives of class .plant and their radius +FIXED : Radius +FIXED : Mini documentation +FIXED : Relative pathes in .worldeditor + +v0.3 + +CHANGED : Script updaté +CHANGED : Link des points d'un group_fauna +CHANGED : Copier / couper / coller de primitive +CHANGED : Menu click droit plus intelligent +CHANGED : Icone du programme +CHANGED : On ne peut plus effacer les primitives "crées en dure" +CHANGED : Pleins de bugs en moins +CHANGED : Y'avait d'autre truc mais je ne me rappel pas de tout.. :) diff --git a/code/ryzom/tools/leveldesign/install/world_editor_script.xml b/code/ryzom/tools/leveldesign/install/world_editor_script.xml index 5c55f9de9..95c5c002d 100644 --- a/code/ryzom/tools/leveldesign/install/world_editor_script.xml +++ b/code/ryzom/tools/leveldesign/install/world_editor_script.xml @@ -1,19 +1,19 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/code/ryzom/tools/leveldesign/master/ChooseDir.cpp b/code/ryzom/tools/leveldesign/master/ChooseDir.cpp index ee88122b6..6231dc4aa 100644 --- a/code/ryzom/tools/leveldesign/master/ChooseDir.cpp +++ b/code/ryzom/tools/leveldesign/master/ChooseDir.cpp @@ -1,118 +1,118 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// ChooseDir.cpp : implementation file -// - -#include "nel/misc/types_nl.h" -#include "stdafx.h" -#include "master.h" -#include "ChooseDir.h" - -using namespace std; - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// CChooseDir dialog - - -CChooseDir::CChooseDir(CWnd* pParent /*=NULL*/) - : CDialog(CChooseDir::IDD, pParent) -{ - //{{AFX_DATA_INIT(CChooseDir) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -// --------------------------------------------------------------------------- -void CChooseDir::setPath (const string &path) -{ - _Path = path; - _Sel = 0; -} - -// --------------------------------------------------------------------------- -BOOL CChooseDir::OnInitDialog () -{ - WIN32_FIND_DATA findData; - HANDLE hFind; - CListBox *pLB = (CListBox*)GetDlgItem(IDC_LIST); - - SetCurrentDirectory (_Path.c_str()); - hFind = FindFirstFile ("*.*", &findData); - - while (hFind != INVALID_HANDLE_VALUE) - { - - if ((stricmp (findData.cFileName, ".") != 0) && (stricmp (findData.cFileName, "..") != 0)) - { - if (findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) - { - pLB->InsertString (-1, findData.cFileName); - string tmp = findData.cFileName; - _Names.push_back (tmp); - } - } - if (FindNextFile (hFind, &findData) == 0) - break; - } - FindClose (hFind); - - return true; -} - -// --------------------------------------------------------------------------- -const char *CChooseDir::getSelected () -{ - if (_Names.size() == 0) - return NULL; - - if (_Sel == LB_ERR) - return _Names[0].c_str(); - else - return _Names[_Sel].c_str(); -} - -// --------------------------------------------------------------------------- -void CChooseDir::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CChooseDir) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CChooseDir, CDialog) - //{{AFX_MSG_MAP(CChooseDir) - ON_LBN_SELCHANGE(IDC_LIST, OnSelChangeList) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CChooseDir message handlers - -void CChooseDir::OnSelChangeList() -{ - // TODO: Add your control notification handler code here - CListBox *pLB = (CListBox*)GetDlgItem(IDC_LIST); - _Sel = pLB->GetCurSel(); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// ChooseDir.cpp : implementation file +// + +#include "nel/misc/types_nl.h" +#include "stdafx.h" +#include "master.h" +#include "ChooseDir.h" + +using namespace std; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CChooseDir dialog + + +CChooseDir::CChooseDir(CWnd* pParent /*=NULL*/) + : CDialog(CChooseDir::IDD, pParent) +{ + //{{AFX_DATA_INIT(CChooseDir) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +// --------------------------------------------------------------------------- +void CChooseDir::setPath (const string &path) +{ + _Path = path; + _Sel = 0; +} + +// --------------------------------------------------------------------------- +BOOL CChooseDir::OnInitDialog () +{ + WIN32_FIND_DATA findData; + HANDLE hFind; + CListBox *pLB = (CListBox*)GetDlgItem(IDC_LIST); + + SetCurrentDirectory (_Path.c_str()); + hFind = FindFirstFile ("*.*", &findData); + + while (hFind != INVALID_HANDLE_VALUE) + { + + if ((stricmp (findData.cFileName, ".") != 0) && (stricmp (findData.cFileName, "..") != 0)) + { + if (findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) + { + pLB->InsertString (-1, findData.cFileName); + string tmp = findData.cFileName; + _Names.push_back (tmp); + } + } + if (FindNextFile (hFind, &findData) == 0) + break; + } + FindClose (hFind); + + return true; +} + +// --------------------------------------------------------------------------- +const char *CChooseDir::getSelected () +{ + if (_Names.size() == 0) + return NULL; + + if (_Sel == LB_ERR) + return _Names[0].c_str(); + else + return _Names[_Sel].c_str(); +} + +// --------------------------------------------------------------------------- +void CChooseDir::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CChooseDir) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CChooseDir, CDialog) + //{{AFX_MSG_MAP(CChooseDir) + ON_LBN_SELCHANGE(IDC_LIST, OnSelChangeList) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CChooseDir message handlers + +void CChooseDir::OnSelChangeList() +{ + // TODO: Add your control notification handler code here + CListBox *pLB = (CListBox*)GetDlgItem(IDC_LIST); + _Sel = pLB->GetCurSel(); +} diff --git a/code/ryzom/tools/leveldesign/master/ChooseDir.h b/code/ryzom/tools/leveldesign/master/ChooseDir.h index bf317902f..d3661249a 100644 --- a/code/ryzom/tools/leveldesign/master/ChooseDir.h +++ b/code/ryzom/tools/leveldesign/master/ChooseDir.h @@ -1,73 +1,73 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_CHOOSEDIR_H__51164D9B_33B9_488B_AA09_75F2EF07A48A__INCLUDED_) -#define AFX_CHOOSEDIR_H__51164D9B_33B9_488B_AA09_75F2EF07A48A__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// ChooseDir.h : header file -// - -#include -#include - - -///////////////////////////////////////////////////////////////////////////// -// CChooseDir dialog - -class CChooseDir : public CDialog -{ - std::string _Path; - std::vector _Names; - int _Sel; -// Construction -public: - CChooseDir(CWnd* pParent = NULL); // standard constructor - - void setPath (const std::string &path); - const char *getSelected (); - -// Dialog Data - //{{AFX_DATA(CChooseDir) - enum { IDD = IDD_CHOOSEDIR }; - // NOTE: the ClassWizard will add data members here - //}}AFX_DATA - - BOOL OnInitDialog (); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CChooseDir) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CChooseDir) - afx_msg void OnSelChangeList(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_CHOOSEDIR_H__51164D9B_33B9_488B_AA09_75F2EF07A48A__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_CHOOSEDIR_H__51164D9B_33B9_488B_AA09_75F2EF07A48A__INCLUDED_) +#define AFX_CHOOSEDIR_H__51164D9B_33B9_488B_AA09_75F2EF07A48A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ChooseDir.h : header file +// + +#include +#include + + +///////////////////////////////////////////////////////////////////////////// +// CChooseDir dialog + +class CChooseDir : public CDialog +{ + std::string _Path; + std::vector _Names; + int _Sel; +// Construction +public: + CChooseDir(CWnd* pParent = NULL); // standard constructor + + void setPath (const std::string &path); + const char *getSelected (); + +// Dialog Data + //{{AFX_DATA(CChooseDir) + enum { IDD = IDD_CHOOSEDIR }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + BOOL OnInitDialog (); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CChooseDir) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CChooseDir) + afx_msg void OnSelChangeList(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CHOOSEDIR_H__51164D9B_33B9_488B_AA09_75F2EF07A48A__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/master/ChooseTag.cpp b/code/ryzom/tools/leveldesign/master/ChooseTag.cpp index 91ee474b0..69d5c6410 100644 --- a/code/ryzom/tools/leveldesign/master/ChooseTag.cpp +++ b/code/ryzom/tools/leveldesign/master/ChooseTag.cpp @@ -1,140 +1,140 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// ChooseTag.cpp : implementation file -// - - - -#include "nel/misc/types_nl.h" -#include "stdafx.h" -#include "master.h" -#include "ChooseTag.h" - -#include - -using namespace std; - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// CChooseTag dialog - - -// --------------------------------------------------------------------------- -CChooseTag::CChooseTag (CWnd* pParent /*=NULL*/) - : CDialog(CChooseTag::IDD, pParent) -{ - //{{AFX_DATA_INIT(CChooseTag) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -// --------------------------------------------------------------------------- -void CChooseTag::setPath (const string &path) -{ - _Path = path; - _Sel = 0; -} - -// --------------------------------------------------------------------------- -BOOL CChooseTag::OnInitDialog () -{ - WIN32_FIND_DATA findData; - HANDLE hFind; - CListBox *pLB = (CListBox*)GetDlgItem(IDC_LIST); - - set allTags; - - SetCurrentDirectory (_Path.c_str()); - hFind = FindFirstFile ("*.*", &findData); - - while (hFind != INVALID_HANDLE_VALUE) - { - - if ((stricmp (findData.cFileName, ".") != 0) && (stricmp (findData.cFileName, "..") != 0)) - { - if (findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) - { - // Get the tag if any - if (findData.cFileName[0] == '_') - { - string tmp; - int i = 1; - while (findData.cFileName[i] != '_') - { - tmp += findData.cFileName[i]; - ++i; - } - if (allTags.find(tmp) == allTags.end()) - { - allTags.insert (tmp); - pLB->InsertString (-1, tmp.c_str()); - tmp = "_" + tmp + "_"; - _Names.push_back (tmp); - } - } - } - } - if (FindNextFile (hFind, &findData) == 0) - break; - } - FindClose (hFind); - - return true; -} - -// --------------------------------------------------------------------------- -const char *CChooseTag::getSelected () -{ - if (_Names.size() == 0) - return NULL; - - if (_Sel == LB_ERR) - return _Names[0].c_str(); - else - return _Names[_Sel].c_str(); -} - -// --------------------------------------------------------------------------- -void CChooseTag::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CChooseTag) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CChooseTag, CDialog) - //{{AFX_MSG_MAP(CChooseTag) - ON_LBN_SELCHANGE(IDC_LIST, OnSelchangeList) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CChooseTag message handlers - -void CChooseTag::OnSelchangeList() -{ - // TODO: Add your control notification handler code here - CListBox *pLB = (CListBox*)GetDlgItem(IDC_LIST); - _Sel = pLB->GetCurSel(); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// ChooseTag.cpp : implementation file +// + + + +#include "nel/misc/types_nl.h" +#include "stdafx.h" +#include "master.h" +#include "ChooseTag.h" + +#include + +using namespace std; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CChooseTag dialog + + +// --------------------------------------------------------------------------- +CChooseTag::CChooseTag (CWnd* pParent /*=NULL*/) + : CDialog(CChooseTag::IDD, pParent) +{ + //{{AFX_DATA_INIT(CChooseTag) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +// --------------------------------------------------------------------------- +void CChooseTag::setPath (const string &path) +{ + _Path = path; + _Sel = 0; +} + +// --------------------------------------------------------------------------- +BOOL CChooseTag::OnInitDialog () +{ + WIN32_FIND_DATA findData; + HANDLE hFind; + CListBox *pLB = (CListBox*)GetDlgItem(IDC_LIST); + + set allTags; + + SetCurrentDirectory (_Path.c_str()); + hFind = FindFirstFile ("*.*", &findData); + + while (hFind != INVALID_HANDLE_VALUE) + { + + if ((stricmp (findData.cFileName, ".") != 0) && (stricmp (findData.cFileName, "..") != 0)) + { + if (findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) + { + // Get the tag if any + if (findData.cFileName[0] == '_') + { + string tmp; + int i = 1; + while (findData.cFileName[i] != '_') + { + tmp += findData.cFileName[i]; + ++i; + } + if (allTags.find(tmp) == allTags.end()) + { + allTags.insert (tmp); + pLB->InsertString (-1, tmp.c_str()); + tmp = "_" + tmp + "_"; + _Names.push_back (tmp); + } + } + } + } + if (FindNextFile (hFind, &findData) == 0) + break; + } + FindClose (hFind); + + return true; +} + +// --------------------------------------------------------------------------- +const char *CChooseTag::getSelected () +{ + if (_Names.size() == 0) + return NULL; + + if (_Sel == LB_ERR) + return _Names[0].c_str(); + else + return _Names[_Sel].c_str(); +} + +// --------------------------------------------------------------------------- +void CChooseTag::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CChooseTag) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CChooseTag, CDialog) + //{{AFX_MSG_MAP(CChooseTag) + ON_LBN_SELCHANGE(IDC_LIST, OnSelchangeList) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CChooseTag message handlers + +void CChooseTag::OnSelchangeList() +{ + // TODO: Add your control notification handler code here + CListBox *pLB = (CListBox*)GetDlgItem(IDC_LIST); + _Sel = pLB->GetCurSel(); +} diff --git a/code/ryzom/tools/leveldesign/master/ChooseTag.h b/code/ryzom/tools/leveldesign/master/ChooseTag.h index dc6414fa9..b1010d70a 100644 --- a/code/ryzom/tools/leveldesign/master/ChooseTag.h +++ b/code/ryzom/tools/leveldesign/master/ChooseTag.h @@ -1,71 +1,71 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_CHOOSETAG_H__4185965E_4D29_491F_8601_7B29BBF28328__INCLUDED_) -#define AFX_CHOOSETAG_H__4185965E_4D29_491F_8601_7B29BBF28328__INCLUDED_ - -#include -#include - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// ChooseTag.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CChooseTag dialog - -class CChooseTag : public CDialog -{ - std::string _Path; - std::vector _Names; - int _Sel; -// Construction -public: - CChooseTag (CWnd* pParent = NULL); // standard constructor - void setPath (const std::string &path); - const char *getSelected (); - -// Dialog Data - //{{AFX_DATA(CChooseTag) - enum { IDD = IDD_CHOOSETAG }; - // NOTE: the ClassWizard will add data members here - //}}AFX_DATA - - BOOL OnInitDialog (); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CChooseTag) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CChooseTag) - afx_msg void OnSelchangeList(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_CHOOSETAG_H__4185965E_4D29_491F_8601_7B29BBF28328__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_CHOOSETAG_H__4185965E_4D29_491F_8601_7B29BBF28328__INCLUDED_) +#define AFX_CHOOSETAG_H__4185965E_4D29_491F_8601_7B29BBF28328__INCLUDED_ + +#include +#include + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ChooseTag.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CChooseTag dialog + +class CChooseTag : public CDialog +{ + std::string _Path; + std::vector _Names; + int _Sel; +// Construction +public: + CChooseTag (CWnd* pParent = NULL); // standard constructor + void setPath (const std::string &path); + const char *getSelected (); + +// Dialog Data + //{{AFX_DATA(CChooseTag) + enum { IDD = IDD_CHOOSETAG }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + BOOL OnInitDialog (); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CChooseTag) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CChooseTag) + afx_msg void OnSelchangeList(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CHOOSETAG_H__4185965E_4D29_491F_8601_7B29BBF28328__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/master/ContinentCfg.cpp b/code/ryzom/tools/leveldesign/master/ContinentCfg.cpp index 84fb7b697..213a6c86e 100644 --- a/code/ryzom/tools/leveldesign/master/ContinentCfg.cpp +++ b/code/ryzom/tools/leveldesign/master/ContinentCfg.cpp @@ -1,72 +1,72 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" -#include "ContinentCfg.h" -#include "nel/misc/config_file.h" - -using namespace NLMISC; -using namespace std; - -// --------------------------------------------------------------------------- -SContinentCfg::SContinentCfg () -{ -} - -// --------------------------------------------------------------------------- -bool SContinentCfg::load (const string &filename) -{ - if (!openRead(filename)) - return false; - - LandFile = getStr ("LandFile"); - LandDir = getStr ("LandDir"); - DfnDir = getStr ("DfnDir"); - GameElemDir = getStr ("GameElemDir"); - - LandBankFile = getStr ("LandBankFile"); - LandFarBankFile = getStr ("LandFarBankFile"); - LandTileNoiseDir = getStr ("LandTileNoiseDir"); - LandZoneWDir = getStr ("LandZoneWDir"); - OutIGDir = getStr ("OutIGDir"); - close(); - return true; -} - -// --------------------------------------------------------------------------- -bool SContinentCfg::save (const string &filename) -{ - if (!openWrite(filename)) - return false; - - putCommentLine ("-------------"); - putCommentLine ("Continent Cfg"); - putCommentLine ("-------------"); - putStr ("LandFile", LandFile); - putStr ("LandDir", LandDir); - putStr ("DfnDir", DfnDir); - putStr ("GameElemDir", GameElemDir); - - putStr ("LandBankFile", LandBankFile); - putStr ("LandFarBankFile", LandFarBankFile); - putStr ("LandTileNoiseDir", LandTileNoiseDir); - putStr ("LandZoneWDir", LandZoneWDir); - putStr ("OutIGDir", OutIGDir); - - close (); - return true; -} - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" +#include "ContinentCfg.h" +#include "nel/misc/config_file.h" + +using namespace NLMISC; +using namespace std; + +// --------------------------------------------------------------------------- +SContinentCfg::SContinentCfg () +{ +} + +// --------------------------------------------------------------------------- +bool SContinentCfg::load (const string &filename) +{ + if (!openRead(filename)) + return false; + + LandFile = getStr ("LandFile"); + LandDir = getStr ("LandDir"); + DfnDir = getStr ("DfnDir"); + GameElemDir = getStr ("GameElemDir"); + + LandBankFile = getStr ("LandBankFile"); + LandFarBankFile = getStr ("LandFarBankFile"); + LandTileNoiseDir = getStr ("LandTileNoiseDir"); + LandZoneWDir = getStr ("LandZoneWDir"); + OutIGDir = getStr ("OutIGDir"); + close(); + return true; +} + +// --------------------------------------------------------------------------- +bool SContinentCfg::save (const string &filename) +{ + if (!openWrite(filename)) + return false; + + putCommentLine ("-------------"); + putCommentLine ("Continent Cfg"); + putCommentLine ("-------------"); + putStr ("LandFile", LandFile); + putStr ("LandDir", LandDir); + putStr ("DfnDir", DfnDir); + putStr ("GameElemDir", GameElemDir); + + putStr ("LandBankFile", LandBankFile); + putStr ("LandFarBankFile", LandFarBankFile); + putStr ("LandTileNoiseDir", LandTileNoiseDir); + putStr ("LandZoneWDir", LandZoneWDir); + putStr ("OutIGDir", OutIGDir); + + close (); + return true; +} + diff --git a/code/ryzom/tools/leveldesign/master/ContinentCfg.h b/code/ryzom/tools/leveldesign/master/ContinentCfg.h index 1e6a0bb72..c74ff9475 100644 --- a/code/ryzom/tools/leveldesign/master/ContinentCfg.h +++ b/code/ryzom/tools/leveldesign/master/ContinentCfg.h @@ -1,49 +1,49 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef LD_CONTINENTCFG_H -#define LD_CONTINENTCFG_H - -// --------------------------------------------------------------------------- - -#include -#include "easy_cfg.h" - -// --------------------------------------------------------------------------- - -struct SContinentCfg : public IEasyCFG -{ - std::string LandFile; // The .land file - std::string LandDir; // Directory where the zoneLigos and zoneBitmaps are (used for the .land) - std::string DfnDir; // Directory where to get georges dfn - std::string GameElemDir; // Directory where to get georges file (pipoti.plant) - - std::string LandBankFile; // .smallbank - std::string LandFarBankFile; // .farbank - std::string LandTileNoiseDir; // displace - std::string LandZoneWDir; // .zoneW - std::string OutIGDir; // Where to put ig - - // ======================================================================= - - SContinentCfg (); - - bool load (const std::string &filename); - bool save (const std::string &filename); - -}; - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef LD_CONTINENTCFG_H +#define LD_CONTINENTCFG_H + +// --------------------------------------------------------------------------- + +#include +#include "easy_cfg.h" + +// --------------------------------------------------------------------------- + +struct SContinentCfg : public IEasyCFG +{ + std::string LandFile; // The .land file + std::string LandDir; // Directory where the zoneLigos and zoneBitmaps are (used for the .land) + std::string DfnDir; // Directory where to get georges dfn + std::string GameElemDir; // Directory where to get georges file (pipoti.plant) + + std::string LandBankFile; // .smallbank + std::string LandFarBankFile; // .farbank + std::string LandTileNoiseDir; // displace + std::string LandZoneWDir; // .zoneW + std::string OutIGDir; // Where to put ig + + // ======================================================================= + + SContinentCfg (); + + bool load (const std::string &filename); + bool save (const std::string &filename); + +}; + #endif // LD_CONTINENTCFG_H \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/master/ContinentPropertiesDlg.cpp b/code/ryzom/tools/leveldesign/master/ContinentPropertiesDlg.cpp index 15c7e7de1..b77cc0313 100644 --- a/code/ryzom/tools/leveldesign/master/ContinentPropertiesDlg.cpp +++ b/code/ryzom/tools/leveldesign/master/ContinentPropertiesDlg.cpp @@ -1,365 +1,365 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// ContinentPropertiesDlg.cpp : implementation file -// - - - - - - - - - - - - - - - -#include "stdafx.h" -#include "master.h" -#include "ContinentPropertiesDlg.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// - -CContinentPropertiesDlg::CContinentPropertiesDlg (CWnd* pParent /*=NULL*/) - : CDialog(CContinentPropertiesDlg::IDD, pParent) -{ - ContinentName = _T(""); - LandFile = _T(""); - LandDir = _T(""); - LandBankFile = _T(""); - LandFarBankFile = _T(""); - LandTileNoiseDir = _T(""); - LandZoneWDir = _T(""); - OutIGDir = _T(""); - DfnDir = _T(""); - GameElemDir = _T(""); -} - - -void CContinentPropertiesDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - - DDX_Text(pDX, IDC_EDIT_CONTINENT_NAME, ContinentName); - DDX_Text(pDX, IDC_EDIT_LANDFILE, LandFile); - DDX_Text(pDX, IDC_EDIT_LANDDIR, LandDir); - - DDX_Text(pDX, IDC_LAND_BANK_FILE, LandBankFile); - DDX_Text(pDX, IDC_LAND_FAR_BANK_FILE, LandFarBankFile); - DDX_Text(pDX, IDC_LAND_TILE_NOISE_DIR, LandTileNoiseDir); - DDX_Text(pDX, IDC_OUT_LANDSCAPE_DIR, LandZoneWDir); - DDX_Text(pDX, IDC_OUT_VEGETABLE_DIR, OutIGDir); - - DDX_Text(pDX, IDC_EDIT_DFNDIR, DfnDir); - DDX_Text(pDX, IDC_EDIT_GAMEELEMDIR, GameElemDir); -} - - -BEGIN_MESSAGE_MAP(CContinentPropertiesDlg, CDialog) - ON_COMMAND(IDC_BUTTON_LANDFILE, OnButtonLandFile) - ON_COMMAND(IDC_BUTTON_LANDDIR, OnButtonLandDir) - - ON_COMMAND(IDC_EXPLORE_LAND_BANK_FILE, OnButtonLandBankFile) - ON_COMMAND(IDC_EXPLORE_LAND_FAR_BANK_FILE, OnButtonLandFarBankFile) - ON_COMMAND(IDC_EXPLORE_LAND_TILE_NOISE_DIR, OnButtonLandTileNoiseDir) - ON_COMMAND(IDC_EXPLORE_LANDSCAPE, OnButtonLandZoneW) - ON_COMMAND(IDC_EXPLORE_VEGETABLE, OnButtonOutIGDir) - - ON_COMMAND(IDC_BUTTON_DFNDIR, OnButtonDfnDir) - ON_COMMAND(IDC_BUTTON_GAMEELEMDIR, OnButtonGameElemDir) -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// - -BOOL CContinentPropertiesDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - GetDlgItem(IDC_EDIT_CONTINENT_NAME)->SetFocus(); - - UpdateData (FALSE); // Upload - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -// --------------------------------------------------------------------------- -// This function serve to initiate the browsing dialog box to the good position in the tree -int CALLBACK cpdBrowseCallbackProc (HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) -{ - switch(uMsg) - { - case BFFM_INITIALIZED: - SendMessage (hwnd, BFFM_SETSELECTION, TRUE, pData); - break; - default: - break; - } - return 0; -} - -// --------------------------------------------------------------------------- -void CContinentPropertiesDlg::OnButtonLandFile () -{ - CFileDialog dialog (true, "land", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Land (*.land)|*.land", this); - CString iniDir; - int k = LandFile.GetLength()-1; - while (k > 0) - { - if (LandFile[k] == '\\') - break; - --k; - } - for (int i = 0; i < k; ++i) - iniDir += LandFile[i]; - dialog.m_ofn.lpstrInitialDir = iniDir; - if (dialog.DoModal() == IDOK) - { - LandFile = dialog.GetPathName (); - UpdateData (FALSE); // Upload - } -} - -// --------------------------------------------------------------------------- -void CContinentPropertiesDlg::OnButtonLandDir () -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the path for land stuff"; - bi.ulFlags = 0; - bi.lpfn = cpdBrowseCallbackProc; - - char sDir[512]; - strcpy(sDir, (LPCSTR)LandDir); - bi.lParam = (LPARAM)sDir; - - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return; - } - LandDir= str; - UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CContinentPropertiesDlg::OnButtonDfnDir () -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the path for DFN"; - bi.ulFlags = 0; - bi.lpfn = cpdBrowseCallbackProc; - - char sDir[512]; - strcpy(sDir, (LPCSTR)DfnDir); - bi.lParam = (LPARAM)sDir; - - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return; - } - DfnDir= str; - UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CContinentPropertiesDlg::OnButtonGameElemDir() -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the path for GameElem"; - bi.ulFlags = 0; - bi.lpfn = cpdBrowseCallbackProc; - - char sDir[512]; - strcpy(sDir, (LPCSTR)GameElemDir); - bi.lParam = (LPARAM)sDir; - - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return; - } - GameElemDir = str; - UpdateData (FALSE); // Upload -} - - -void CContinentPropertiesDlg::OnButtonLandBankFile () -{ - CFileDialog dialog (true, "smallbank", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "smallbank (*.smallbank)|*.smallbank", this); - CString iniDir; - int k = LandBankFile.GetLength()-1; - while (k > 0) - { - if (LandBankFile[k] == '\\') - break; - --k; - } - for (int i = 0; i < k; ++i) - iniDir += LandBankFile[i]; - dialog.m_ofn.lpstrInitialDir = iniDir; - if (dialog.DoModal() == IDOK) - { - LandBankFile = dialog.GetPathName (); - UpdateData (FALSE); // Upload - } -} - -void CContinentPropertiesDlg::OnButtonLandFarBankFile () -{ - CFileDialog dialog (true, "farbank", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "farbank (*.farbank)|*.farbank", this); - CString iniDir; - int k = LandFarBankFile.GetLength()-1; - while (k > 0) - { - if (LandFarBankFile[k] == '\\') - break; - --k; - } - for (int i = 0; i < k; ++i) - iniDir += LandFarBankFile[i]; - dialog.m_ofn.lpstrInitialDir = iniDir; - if (dialog.DoModal() == IDOK) - { - LandFarBankFile = dialog.GetPathName (); - UpdateData (FALSE); // Upload - } -} - -void CContinentPropertiesDlg::OnButtonLandTileNoiseDir () -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the path for Tile Noise"; - bi.ulFlags = 0; - bi.lpfn = cpdBrowseCallbackProc; - - char sDir[512]; - strcpy(sDir, (LPCSTR)LandTileNoiseDir); - bi.lParam = (LPARAM)sDir; - - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return; - } - LandTileNoiseDir = str; - UpdateData (FALSE); // Upload -} - -void CContinentPropertiesDlg::OnButtonLandZoneW () -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the path for ZoneW"; - bi.ulFlags = 0; - bi.lpfn = cpdBrowseCallbackProc; - - char sDir[512]; - strcpy(sDir, (LPCSTR)LandZoneWDir); - bi.lParam = (LPARAM)sDir; - - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return; - } - LandZoneWDir = str; - UpdateData (FALSE); // Upload -} - -void CContinentPropertiesDlg::OnButtonOutIGDir () -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the path for IG output"; - bi.ulFlags = 0; - bi.lpfn = cpdBrowseCallbackProc; - - char sDir[512]; - strcpy(sDir, (LPCSTR)OutIGDir); - bi.lParam = (LPARAM)sDir; - - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return; - } - OutIGDir = str; - UpdateData (FALSE); // Upload -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// ContinentPropertiesDlg.cpp : implementation file +// + + + + + + + + + + + + + + + +#include "stdafx.h" +#include "master.h" +#include "ContinentPropertiesDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// + +CContinentPropertiesDlg::CContinentPropertiesDlg (CWnd* pParent /*=NULL*/) + : CDialog(CContinentPropertiesDlg::IDD, pParent) +{ + ContinentName = _T(""); + LandFile = _T(""); + LandDir = _T(""); + LandBankFile = _T(""); + LandFarBankFile = _T(""); + LandTileNoiseDir = _T(""); + LandZoneWDir = _T(""); + OutIGDir = _T(""); + DfnDir = _T(""); + GameElemDir = _T(""); +} + + +void CContinentPropertiesDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + + DDX_Text(pDX, IDC_EDIT_CONTINENT_NAME, ContinentName); + DDX_Text(pDX, IDC_EDIT_LANDFILE, LandFile); + DDX_Text(pDX, IDC_EDIT_LANDDIR, LandDir); + + DDX_Text(pDX, IDC_LAND_BANK_FILE, LandBankFile); + DDX_Text(pDX, IDC_LAND_FAR_BANK_FILE, LandFarBankFile); + DDX_Text(pDX, IDC_LAND_TILE_NOISE_DIR, LandTileNoiseDir); + DDX_Text(pDX, IDC_OUT_LANDSCAPE_DIR, LandZoneWDir); + DDX_Text(pDX, IDC_OUT_VEGETABLE_DIR, OutIGDir); + + DDX_Text(pDX, IDC_EDIT_DFNDIR, DfnDir); + DDX_Text(pDX, IDC_EDIT_GAMEELEMDIR, GameElemDir); +} + + +BEGIN_MESSAGE_MAP(CContinentPropertiesDlg, CDialog) + ON_COMMAND(IDC_BUTTON_LANDFILE, OnButtonLandFile) + ON_COMMAND(IDC_BUTTON_LANDDIR, OnButtonLandDir) + + ON_COMMAND(IDC_EXPLORE_LAND_BANK_FILE, OnButtonLandBankFile) + ON_COMMAND(IDC_EXPLORE_LAND_FAR_BANK_FILE, OnButtonLandFarBankFile) + ON_COMMAND(IDC_EXPLORE_LAND_TILE_NOISE_DIR, OnButtonLandTileNoiseDir) + ON_COMMAND(IDC_EXPLORE_LANDSCAPE, OnButtonLandZoneW) + ON_COMMAND(IDC_EXPLORE_VEGETABLE, OnButtonOutIGDir) + + ON_COMMAND(IDC_BUTTON_DFNDIR, OnButtonDfnDir) + ON_COMMAND(IDC_BUTTON_GAMEELEMDIR, OnButtonGameElemDir) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// + +BOOL CContinentPropertiesDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + GetDlgItem(IDC_EDIT_CONTINENT_NAME)->SetFocus(); + + UpdateData (FALSE); // Upload + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +// --------------------------------------------------------------------------- +// This function serve to initiate the browsing dialog box to the good position in the tree +int CALLBACK cpdBrowseCallbackProc (HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) +{ + switch(uMsg) + { + case BFFM_INITIALIZED: + SendMessage (hwnd, BFFM_SETSELECTION, TRUE, pData); + break; + default: + break; + } + return 0; +} + +// --------------------------------------------------------------------------- +void CContinentPropertiesDlg::OnButtonLandFile () +{ + CFileDialog dialog (true, "land", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Land (*.land)|*.land", this); + CString iniDir; + int k = LandFile.GetLength()-1; + while (k > 0) + { + if (LandFile[k] == '\\') + break; + --k; + } + for (int i = 0; i < k; ++i) + iniDir += LandFile[i]; + dialog.m_ofn.lpstrInitialDir = iniDir; + if (dialog.DoModal() == IDOK) + { + LandFile = dialog.GetPathName (); + UpdateData (FALSE); // Upload + } +} + +// --------------------------------------------------------------------------- +void CContinentPropertiesDlg::OnButtonLandDir () +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the path for land stuff"; + bi.ulFlags = 0; + bi.lpfn = cpdBrowseCallbackProc; + + char sDir[512]; + strcpy(sDir, (LPCSTR)LandDir); + bi.lParam = (LPARAM)sDir; + + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return; + } + LandDir= str; + UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CContinentPropertiesDlg::OnButtonDfnDir () +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the path for DFN"; + bi.ulFlags = 0; + bi.lpfn = cpdBrowseCallbackProc; + + char sDir[512]; + strcpy(sDir, (LPCSTR)DfnDir); + bi.lParam = (LPARAM)sDir; + + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return; + } + DfnDir= str; + UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CContinentPropertiesDlg::OnButtonGameElemDir() +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the path for GameElem"; + bi.ulFlags = 0; + bi.lpfn = cpdBrowseCallbackProc; + + char sDir[512]; + strcpy(sDir, (LPCSTR)GameElemDir); + bi.lParam = (LPARAM)sDir; + + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return; + } + GameElemDir = str; + UpdateData (FALSE); // Upload +} + + +void CContinentPropertiesDlg::OnButtonLandBankFile () +{ + CFileDialog dialog (true, "smallbank", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "smallbank (*.smallbank)|*.smallbank", this); + CString iniDir; + int k = LandBankFile.GetLength()-1; + while (k > 0) + { + if (LandBankFile[k] == '\\') + break; + --k; + } + for (int i = 0; i < k; ++i) + iniDir += LandBankFile[i]; + dialog.m_ofn.lpstrInitialDir = iniDir; + if (dialog.DoModal() == IDOK) + { + LandBankFile = dialog.GetPathName (); + UpdateData (FALSE); // Upload + } +} + +void CContinentPropertiesDlg::OnButtonLandFarBankFile () +{ + CFileDialog dialog (true, "farbank", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "farbank (*.farbank)|*.farbank", this); + CString iniDir; + int k = LandFarBankFile.GetLength()-1; + while (k > 0) + { + if (LandFarBankFile[k] == '\\') + break; + --k; + } + for (int i = 0; i < k; ++i) + iniDir += LandFarBankFile[i]; + dialog.m_ofn.lpstrInitialDir = iniDir; + if (dialog.DoModal() == IDOK) + { + LandFarBankFile = dialog.GetPathName (); + UpdateData (FALSE); // Upload + } +} + +void CContinentPropertiesDlg::OnButtonLandTileNoiseDir () +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the path for Tile Noise"; + bi.ulFlags = 0; + bi.lpfn = cpdBrowseCallbackProc; + + char sDir[512]; + strcpy(sDir, (LPCSTR)LandTileNoiseDir); + bi.lParam = (LPARAM)sDir; + + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return; + } + LandTileNoiseDir = str; + UpdateData (FALSE); // Upload +} + +void CContinentPropertiesDlg::OnButtonLandZoneW () +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the path for ZoneW"; + bi.ulFlags = 0; + bi.lpfn = cpdBrowseCallbackProc; + + char sDir[512]; + strcpy(sDir, (LPCSTR)LandZoneWDir); + bi.lParam = (LPARAM)sDir; + + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return; + } + LandZoneWDir = str; + UpdateData (FALSE); // Upload +} + +void CContinentPropertiesDlg::OnButtonOutIGDir () +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the path for IG output"; + bi.ulFlags = 0; + bi.lpfn = cpdBrowseCallbackProc; + + char sDir[512]; + strcpy(sDir, (LPCSTR)OutIGDir); + bi.lParam = (LPARAM)sDir; + + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return; + } + OutIGDir = str; + UpdateData (FALSE); // Upload +} diff --git a/code/ryzom/tools/leveldesign/master/ContinentPropertiesDlg.h b/code/ryzom/tools/leveldesign/master/ContinentPropertiesDlg.h index ba8b9b05a..76432fce9 100644 --- a/code/ryzom/tools/leveldesign/master/ContinentPropertiesDlg.h +++ b/code/ryzom/tools/leveldesign/master/ContinentPropertiesDlg.h @@ -1,68 +1,68 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CONTINENT_PROPERTIES_DLG_H -#define CONTINENT_PROPERTIES_DLG_H - -///////////////////////////////////////////////////////////////////////////// -// ContinentProperties dialog - -class CContinentPropertiesDlg : public CDialog -{ -// Construction -public: - CContinentPropertiesDlg(CWnd* pParent = NULL); - -// Dialog Data - enum { IDD = IDD_CONTINENT_PROPERTIES }; - - CString ContinentName; - CString LandFile; - CString LandDir; - - CString LandBankFile; - CString LandFarBankFile; - CString LandTileNoiseDir; - CString LandZoneWDir; - CString OutIGDir; - - CString DfnDir; - CString GameElemDir; - - - afx_msg void OnButtonLandFile (); - afx_msg void OnButtonLandDir (); - afx_msg void OnButtonDfnDir (); - afx_msg void OnButtonGameElemDir (); - afx_msg void OnButtonLandBankFile (); - afx_msg void OnButtonLandFarBankFile (); - afx_msg void OnButtonLandTileNoiseDir (); - afx_msg void OnButtonLandZoneW (); - afx_msg void OnButtonOutIGDir (); - - -protected: - virtual void DoDataExchange (CDataExchange* pDX); - -// Implementation -protected: - - virtual BOOL OnInitDialog(); - DECLARE_MESSAGE_MAP() -}; - - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CONTINENT_PROPERTIES_DLG_H +#define CONTINENT_PROPERTIES_DLG_H + +///////////////////////////////////////////////////////////////////////////// +// ContinentProperties dialog + +class CContinentPropertiesDlg : public CDialog +{ +// Construction +public: + CContinentPropertiesDlg(CWnd* pParent = NULL); + +// Dialog Data + enum { IDD = IDD_CONTINENT_PROPERTIES }; + + CString ContinentName; + CString LandFile; + CString LandDir; + + CString LandBankFile; + CString LandFarBankFile; + CString LandTileNoiseDir; + CString LandZoneWDir; + CString OutIGDir; + + CString DfnDir; + CString GameElemDir; + + + afx_msg void OnButtonLandFile (); + afx_msg void OnButtonLandDir (); + afx_msg void OnButtonDfnDir (); + afx_msg void OnButtonGameElemDir (); + afx_msg void OnButtonLandBankFile (); + afx_msg void OnButtonLandFarBankFile (); + afx_msg void OnButtonLandTileNoiseDir (); + afx_msg void OnButtonLandZoneW (); + afx_msg void OnButtonOutIGDir (); + + +protected: + virtual void DoDataExchange (CDataExchange* pDX); + +// Implementation +protected: + + virtual BOOL OnInitDialog(); + DECLARE_MESSAGE_MAP() +}; + + +#endif diff --git a/code/ryzom/tools/leveldesign/master/ExportCBDlg.cpp b/code/ryzom/tools/leveldesign/master/ExportCBDlg.cpp index 74d516d61..37e42546d 100644 --- a/code/ryzom/tools/leveldesign/master/ExportCBDlg.cpp +++ b/code/ryzom/tools/leveldesign/master/ExportCBDlg.cpp @@ -1,183 +1,183 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// ExportCBDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "master.h" -#include "ExportCBDlg.h" - -#ifdef _DEBUG -# ifdef new -# undef new -# endif -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// CExportCB - -///////////////////////////////////////////////////////////////////////////// -CExportCB::CExportCB() -{ - _Canceled = false; -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::setExportCBDlg (CExportCBDlg *dlg) -{ - _Dialog = dlg; -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::cancel () -{ - _Canceled = true; -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::pump() -{ - MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage (&msg); - DispatchMessage (&msg); - } -} - -///////////////////////////////////////////////////////////////////////////// -bool CExportCB::isCanceled () -{ - pump(); - return _Canceled; -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::dispPass (const std::string &Text) -{ - _Dialog->PassText = Text.c_str(); - _Dialog->ProgressBar.SetPos (0); - _Dialog->UpdateData (FALSE); // Upload - _Dialog->Invalidate(); - pump(); -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::dispPassProgress (float percentage) -{ - _Dialog->ProgressBar.SetPos ((sint32)(100*percentage)); - _Dialog->UpdateData (FALSE); // Upload - pump(); -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::dispInfo (const std::string &Text) -{ - _Dialog->InfoText = CString(Text.c_str()) + "\r\n" + _Dialog->InfoText; - _Dialog->UpdateData (FALSE); // Upload - pump(); -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::dispWarning (const std::string &Text) -{ - _Dialog->InfoText = CString("WARNING : ") + CString(Text.c_str()) + "\r\n" + _Dialog->InfoText; - _Dialog->UpdateData (FALSE); // Upload - pump(); -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::dispError (const std::string &Text) -{ - _Dialog->InfoText = CString("ERROR : ") + CString(Text.c_str()) + "\r\n" + _Dialog->InfoText; - _Dialog->UpdateData (FALSE); // Upload - pump(); -} - -///////////////////////////////////////////////////////////////////////////// -// CExportCBDlg dialog - - -///////////////////////////////////////////////////////////////////////////// -CExportCBDlg::CExportCBDlg(CWnd* pParent /*=NULL*/) - : CDialog(CExportCBDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CExportCBDlg) - PassText = _T(""); - InfoText = _T(""); - _Finished = false; - //}}AFX_DATA_INIT -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCBDlg::setFinishedButton () -{ - CButton *but = (CButton*)GetDlgItem (IDCANCEL); - but->SetWindowText ("FINISHED"); - Invalidate (); - pump (); -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCBDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CExportCBDlg) - DDX_Control(pDX, IDC_EDIT1, EditCtrl); - DDX_Control(pDX, IDC_PROGRESS1, ProgressBar); - DDX_Text(pDX, IDC_PASS, PassText); - DDX_Text(pDX, IDC_EDIT1, InfoText); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CExportCBDlg, CDialog) - //{{AFX_MSG_MAP(CExportCBDlg) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CExportCBDlg message handlers - -///////////////////////////////////////////////////////////////////////////// -void CExportCBDlg::OnCancel() -{ - CButton *but = (CButton*)GetDlgItem (IDCANCEL); - CString zeText; - but->GetWindowText (zeText); - if (zeText == "Cancel") - _ExportCB.cancel (); - else - _Finished = true; - //CDialog::OnCancel(); -} - -///////////////////////////////////////////////////////////////////////////// -BOOL CExportCBDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - _ExportCB.setExportCBDlg (this); - ProgressBar.SetRange (0, 100); - EditCtrl.SetLimitText (200); - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// ExportCBDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "master.h" +#include "ExportCBDlg.h" + +#ifdef _DEBUG +# ifdef new +# undef new +# endif +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CExportCB + +///////////////////////////////////////////////////////////////////////////// +CExportCB::CExportCB() +{ + _Canceled = false; +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::setExportCBDlg (CExportCBDlg *dlg) +{ + _Dialog = dlg; +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::cancel () +{ + _Canceled = true; +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::pump() +{ + MSG msg; + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } +} + +///////////////////////////////////////////////////////////////////////////// +bool CExportCB::isCanceled () +{ + pump(); + return _Canceled; +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::dispPass (const std::string &Text) +{ + _Dialog->PassText = Text.c_str(); + _Dialog->ProgressBar.SetPos (0); + _Dialog->UpdateData (FALSE); // Upload + _Dialog->Invalidate(); + pump(); +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::dispPassProgress (float percentage) +{ + _Dialog->ProgressBar.SetPos ((sint32)(100*percentage)); + _Dialog->UpdateData (FALSE); // Upload + pump(); +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::dispInfo (const std::string &Text) +{ + _Dialog->InfoText = CString(Text.c_str()) + "\r\n" + _Dialog->InfoText; + _Dialog->UpdateData (FALSE); // Upload + pump(); +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::dispWarning (const std::string &Text) +{ + _Dialog->InfoText = CString("WARNING : ") + CString(Text.c_str()) + "\r\n" + _Dialog->InfoText; + _Dialog->UpdateData (FALSE); // Upload + pump(); +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::dispError (const std::string &Text) +{ + _Dialog->InfoText = CString("ERROR : ") + CString(Text.c_str()) + "\r\n" + _Dialog->InfoText; + _Dialog->UpdateData (FALSE); // Upload + pump(); +} + +///////////////////////////////////////////////////////////////////////////// +// CExportCBDlg dialog + + +///////////////////////////////////////////////////////////////////////////// +CExportCBDlg::CExportCBDlg(CWnd* pParent /*=NULL*/) + : CDialog(CExportCBDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CExportCBDlg) + PassText = _T(""); + InfoText = _T(""); + _Finished = false; + //}}AFX_DATA_INIT +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCBDlg::setFinishedButton () +{ + CButton *but = (CButton*)GetDlgItem (IDCANCEL); + but->SetWindowText ("FINISHED"); + Invalidate (); + pump (); +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCBDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CExportCBDlg) + DDX_Control(pDX, IDC_EDIT1, EditCtrl); + DDX_Control(pDX, IDC_PROGRESS1, ProgressBar); + DDX_Text(pDX, IDC_PASS, PassText); + DDX_Text(pDX, IDC_EDIT1, InfoText); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CExportCBDlg, CDialog) + //{{AFX_MSG_MAP(CExportCBDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CExportCBDlg message handlers + +///////////////////////////////////////////////////////////////////////////// +void CExportCBDlg::OnCancel() +{ + CButton *but = (CButton*)GetDlgItem (IDCANCEL); + CString zeText; + but->GetWindowText (zeText); + if (zeText == "Cancel") + _ExportCB.cancel (); + else + _Finished = true; + //CDialog::OnCancel(); +} + +///////////////////////////////////////////////////////////////////////////// +BOOL CExportCBDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + _ExportCB.setExportCBDlg (this); + ProgressBar.SetRange (0, 100); + EditCtrl.SetLimitText (200); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/code/ryzom/tools/leveldesign/master/ExportCBDlg.h b/code/ryzom/tools/leveldesign/master/ExportCBDlg.h index c34f64c51..e2bc965af 100644 --- a/code/ryzom/tools/leveldesign/master/ExportCBDlg.h +++ b/code/ryzom/tools/leveldesign/master/ExportCBDlg.h @@ -1,106 +1,106 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_EXPORTCBDLG_H__34C63700_C8D7_454C_A752_3722257D9160__INCLUDED_) -#define AFX_EXPORTCBDLG_H__34C63700_C8D7_454C_A752_3722257D9160__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// ExportCBDlg.h : header file -// - -#include "../export/export.h" - -///////////////////////////////////////////////////////////////////////////// -class CExportCBDlg; - -///////////////////////////////////////////////////////////////////////////// -// CExportCB - -class CExportCB : public IExportCB -{ - CExportCBDlg *_Dialog; - bool _Canceled; - -public: - CExportCB(); - - void setExportCBDlg (CExportCBDlg *dlg); - void cancel (); - void pump (); - - // Interface - - virtual bool isCanceled (); // Tell the exporter if it must end as quick as possible - // Display callbacks - virtual void dispPass (const std::string &Text); // Pass (generate land, vegetable, etc...) - virtual void dispPassProgress (float percentage); // [ 0.0 , 1.0 ] - virtual void dispInfo (const std::string &Text); // Verbose - virtual void dispWarning (const std::string &Text); // Error but not critical - virtual void dispError (const std::string &Text); // Should block (misfunction) -}; - -///////////////////////////////////////////////////////////////////////////// -// CExportCBDlg dialog - -class CExportCBDlg : public CDialog -{ - - CExportCB _ExportCB; - bool _Finished; - -// Construction -public: - CExportCBDlg(CWnd* pParent = NULL); // standard constructor - CExportCB *getExportCB () { return &_ExportCB; } - - void setFinishedButton (); - bool getFinished () { return _Finished; } - void pump () { _ExportCB.pump (); } - -// Dialog Data - //{{AFX_DATA(CExportCBDlg) - enum { IDD = IDD_EXPORTCB }; - CEdit EditCtrl; - CProgressCtrl ProgressBar; - CString PassText; - CString InfoText; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CExportCBDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CExportCBDlg) - virtual void OnCancel(); - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_EXPORTCBDLG_H__34C63700_C8D7_454C_A752_3722257D9160__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_EXPORTCBDLG_H__34C63700_C8D7_454C_A752_3722257D9160__INCLUDED_) +#define AFX_EXPORTCBDLG_H__34C63700_C8D7_454C_A752_3722257D9160__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ExportCBDlg.h : header file +// + +#include "../export/export.h" + +///////////////////////////////////////////////////////////////////////////// +class CExportCBDlg; + +///////////////////////////////////////////////////////////////////////////// +// CExportCB + +class CExportCB : public IExportCB +{ + CExportCBDlg *_Dialog; + bool _Canceled; + +public: + CExportCB(); + + void setExportCBDlg (CExportCBDlg *dlg); + void cancel (); + void pump (); + + // Interface + + virtual bool isCanceled (); // Tell the exporter if it must end as quick as possible + // Display callbacks + virtual void dispPass (const std::string &Text); // Pass (generate land, vegetable, etc...) + virtual void dispPassProgress (float percentage); // [ 0.0 , 1.0 ] + virtual void dispInfo (const std::string &Text); // Verbose + virtual void dispWarning (const std::string &Text); // Error but not critical + virtual void dispError (const std::string &Text); // Should block (misfunction) +}; + +///////////////////////////////////////////////////////////////////////////// +// CExportCBDlg dialog + +class CExportCBDlg : public CDialog +{ + + CExportCB _ExportCB; + bool _Finished; + +// Construction +public: + CExportCBDlg(CWnd* pParent = NULL); // standard constructor + CExportCB *getExportCB () { return &_ExportCB; } + + void setFinishedButton (); + bool getFinished () { return _Finished; } + void pump () { _ExportCB.pump (); } + +// Dialog Data + //{{AFX_DATA(CExportCBDlg) + enum { IDD = IDD_EXPORTCB }; + CEdit EditCtrl; + CProgressCtrl ProgressBar; + CString PassText; + CString InfoText; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CExportCBDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CExportCBDlg) + virtual void OnCancel(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_EXPORTCBDLG_H__34C63700_C8D7_454C_A752_3722257D9160__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/master/ExportDlg.cpp b/code/ryzom/tools/leveldesign/master/ExportDlg.cpp index bf27dd878..00caee362 100644 --- a/code/ryzom/tools/leveldesign/master/ExportDlg.cpp +++ b/code/ryzom/tools/leveldesign/master/ExportDlg.cpp @@ -1,261 +1,261 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// ExportDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "master.h" -#include "ExportDlg.h" - -#ifdef _DEBUG -# ifdef new -# undef new -# endif -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -using namespace std; - -///////////////////////////////////////////////////////////////////////////// -// CExportDlg dialog - - -// --------------------------------------------------------------------------- -CExportDlg::CExportDlg(CWnd* pParent /*=NULL*/) - : CDialog(CExportDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CExportDlg) - //GenerateLandscape = FALSE; - //GenerateVegetable = FALSE; -/* OutLandscapeDir = _T(""); - OutIGDir = _T("");*/ - ContinentName = _T(""); - /*LandBankFile = _T(""); - LandFarBankFile = _T("");*/ - _Options = NULL; - _Finished = false; - //LandTileNoiseDir = _T(""); - //}}AFX_DATA_INIT -} - -// --------------------------------------------------------------------------- -void CExportDlg::setOptions (SExportOptions &options, vector ®Names) -{ - _Options = &options; - _Continents = ®Names; -} - -// --------------------------------------------------------------------------- -void CExportDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CExportDlg) - DDX_Control(pDX, IDC_CONTINENTLIST, ContinentList); - //DDX_Check(pDX, IDC_GENERATE_VEGETABLE, GenerateVegetable); - //DDX_Text(pDX, IDC_OUT_LANDSCAPE_DIR, OutLandscapeDir); - //DDX_Text(pDX, IDC_OUT_VEGETABLE_DIR, OutIGDir); - DDX_CBString(pDX, IDC_CONTINENTLIST, ContinentName); - //DDX_Text(pDX, IDC_LAND_BANK_FILE, LandBankFile); - //DDX_Text(pDX, IDC_LAND_FAR_BANK_FILE, LandFarBankFile); - //DDX_Text(pDX, IDC_LAND_TILE_NOISE_DIR, LandTileNoiseDir); - //}}AFX_DATA_MAP -} - - -///////////////////////////////////////////////////////////////////////////// -BEGIN_MESSAGE_MAP(CExportDlg, CDialog) - //{{AFX_MSG_MAP(CExportDlg) -/* ON_BN_CLICKED(IDC_EXPLORE_LANDSCAPE, OnExploreOutLandscapeDir) - ON_BN_CLICKED(IDC_EXPLORE_VEGETABLE, OnExploreOutIGDir) - ON_BN_CLICKED(IDC_EXPLORE_LAND_BANK_FILE, OnExploreLandSmallBankFile) - ON_BN_CLICKED(IDC_EXPLORE_LAND_FAR_BANK_FILE, OnExploreLandFarBankFile) - ON_BN_CLICKED(IDC_EXPLORE_LAND_TILE_NOISE_DIR, OnExploreLandTileNoiseDir)*/ - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CExportDlg message handlers - -// --------------------------------------------------------------------------- -BOOL CExportDlg::OnInitDialog () -{ - CDialog::OnInitDialog (); - - // TODO: Add extra initialization here -// OutLandscapeDir = _Options->InLandscapeDir.c_str(); -// OutIGDir = _Options->OutIGDir.c_str (); -// LandBankFile = _Options->LandBankFile.c_str (); -// LandFarBankFile = _Options->LandFarBankFile.c_str (); -// LandTileNoiseDir = _Options->LandTileNoiseDir.c_str (); - for (uint32 i=0; i < _Continents->size(); ++i) - { - ContinentList.InsertString (-1, (_Continents->operator[](i)).c_str()); - } - ContinentName = _Options->PrimFloraDir.c_str (); - sint32 si = _Options->PrimFloraDir.size()-1; - while (si >= 0) - { - if (_Options->PrimFloraDir[si] == '\\') - break; - --si; - } - if (si > -1) - { - ContinentName = ""; - ++si; - for (;si < (sint32)_Options->PrimFloraDir.size(); ++si) - ContinentName += _Options->PrimFloraDir[si]; - } - UpdateData (FALSE); // Upload - - if (ContinentName == "") - ContinentList.SetCurSel (0); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnOK () -{ - UpdateData (TRUE); // Download - - _Options->PrimFloraDir = (LPCSTR)ContinentName; -// _Options->OutIGDir = (LPCSTR)OutIGDir; -// _Options->LandBankFile = (LPCSTR)LandBankFile; -// _Options->LandFarBankFile = (LPCSTR)LandFarBankFile; -// _Options->PrimFloraDir = (LPCSTR)ContinentName; -// _Options->LandTileNoiseDir = (LPCSTR)LandTileNoiseDir; -// _Options->InLandscapeDir = (LPCSTR)OutLandscapeDir; - CDialog::OnOK(); -} -/* -// --------------------------------------------------------------------------- -int CALLBACK expBrowseCallbackProc (HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) -{ - switch(uMsg) - { - case BFFM_INITIALIZED: - SendMessage (hwnd, BFFM_SETSELECTION, TRUE, pData); - break; - default: - break; - } - return 0; -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnExploreOutLandscapeDir () -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the path"; - bi.ulFlags = 0; - bi.lpfn = expBrowseCallbackProc; - bi.lParam = (LPARAM)(LPCSTR)OutLandscapeDir; - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return; - } - OutLandscapeDir = str; - UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnExploreOutIGDir() -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the path"; - bi.ulFlags = 0; - bi.lpfn = expBrowseCallbackProc; - bi.lParam = (LPARAM)(LPCSTR)OutIGDir; - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return; - } - OutIGDir = str; - UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnExploreLandSmallBankFile() -{ - CFileDialog dialog (true, "smallbank", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "SmallBank (*.smallbank)|*.smallbank", this); - if (dialog.DoModal() == IDOK) - { - LandBankFile = dialog.GetPathName (); - } - UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnExploreLandFarBankFile() -{ - CFileDialog dialog (true, "farbank", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "FarBank (*.farbank)|*.farbank", this); - if (dialog.DoModal() == IDOK) - { - LandFarBankFile = dialog.GetPathName(); - } - UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnExploreLandTileNoiseDir() -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the path"; - bi.ulFlags = 0; - bi.lpfn = expBrowseCallbackProc; - bi.lParam = (LPARAM)(LPCSTR)LandTileNoiseDir; - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return; - } - LandTileNoiseDir = str; - UpdateData (FALSE); // Upload -}*/ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// ExportDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "master.h" +#include "ExportDlg.h" + +#ifdef _DEBUG +# ifdef new +# undef new +# endif +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +using namespace std; + +///////////////////////////////////////////////////////////////////////////// +// CExportDlg dialog + + +// --------------------------------------------------------------------------- +CExportDlg::CExportDlg(CWnd* pParent /*=NULL*/) + : CDialog(CExportDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CExportDlg) + //GenerateLandscape = FALSE; + //GenerateVegetable = FALSE; +/* OutLandscapeDir = _T(""); + OutIGDir = _T("");*/ + ContinentName = _T(""); + /*LandBankFile = _T(""); + LandFarBankFile = _T("");*/ + _Options = NULL; + _Finished = false; + //LandTileNoiseDir = _T(""); + //}}AFX_DATA_INIT +} + +// --------------------------------------------------------------------------- +void CExportDlg::setOptions (SExportOptions &options, vector ®Names) +{ + _Options = &options; + _Continents = ®Names; +} + +// --------------------------------------------------------------------------- +void CExportDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CExportDlg) + DDX_Control(pDX, IDC_CONTINENTLIST, ContinentList); + //DDX_Check(pDX, IDC_GENERATE_VEGETABLE, GenerateVegetable); + //DDX_Text(pDX, IDC_OUT_LANDSCAPE_DIR, OutLandscapeDir); + //DDX_Text(pDX, IDC_OUT_VEGETABLE_DIR, OutIGDir); + DDX_CBString(pDX, IDC_CONTINENTLIST, ContinentName); + //DDX_Text(pDX, IDC_LAND_BANK_FILE, LandBankFile); + //DDX_Text(pDX, IDC_LAND_FAR_BANK_FILE, LandFarBankFile); + //DDX_Text(pDX, IDC_LAND_TILE_NOISE_DIR, LandTileNoiseDir); + //}}AFX_DATA_MAP +} + + +///////////////////////////////////////////////////////////////////////////// +BEGIN_MESSAGE_MAP(CExportDlg, CDialog) + //{{AFX_MSG_MAP(CExportDlg) +/* ON_BN_CLICKED(IDC_EXPLORE_LANDSCAPE, OnExploreOutLandscapeDir) + ON_BN_CLICKED(IDC_EXPLORE_VEGETABLE, OnExploreOutIGDir) + ON_BN_CLICKED(IDC_EXPLORE_LAND_BANK_FILE, OnExploreLandSmallBankFile) + ON_BN_CLICKED(IDC_EXPLORE_LAND_FAR_BANK_FILE, OnExploreLandFarBankFile) + ON_BN_CLICKED(IDC_EXPLORE_LAND_TILE_NOISE_DIR, OnExploreLandTileNoiseDir)*/ + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CExportDlg message handlers + +// --------------------------------------------------------------------------- +BOOL CExportDlg::OnInitDialog () +{ + CDialog::OnInitDialog (); + + // TODO: Add extra initialization here +// OutLandscapeDir = _Options->InLandscapeDir.c_str(); +// OutIGDir = _Options->OutIGDir.c_str (); +// LandBankFile = _Options->LandBankFile.c_str (); +// LandFarBankFile = _Options->LandFarBankFile.c_str (); +// LandTileNoiseDir = _Options->LandTileNoiseDir.c_str (); + for (uint32 i=0; i < _Continents->size(); ++i) + { + ContinentList.InsertString (-1, (_Continents->operator[](i)).c_str()); + } + ContinentName = _Options->PrimFloraDir.c_str (); + sint32 si = _Options->PrimFloraDir.size()-1; + while (si >= 0) + { + if (_Options->PrimFloraDir[si] == '\\') + break; + --si; + } + if (si > -1) + { + ContinentName = ""; + ++si; + for (;si < (sint32)_Options->PrimFloraDir.size(); ++si) + ContinentName += _Options->PrimFloraDir[si]; + } + UpdateData (FALSE); // Upload + + if (ContinentName == "") + ContinentList.SetCurSel (0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnOK () +{ + UpdateData (TRUE); // Download + + _Options->PrimFloraDir = (LPCSTR)ContinentName; +// _Options->OutIGDir = (LPCSTR)OutIGDir; +// _Options->LandBankFile = (LPCSTR)LandBankFile; +// _Options->LandFarBankFile = (LPCSTR)LandFarBankFile; +// _Options->PrimFloraDir = (LPCSTR)ContinentName; +// _Options->LandTileNoiseDir = (LPCSTR)LandTileNoiseDir; +// _Options->InLandscapeDir = (LPCSTR)OutLandscapeDir; + CDialog::OnOK(); +} +/* +// --------------------------------------------------------------------------- +int CALLBACK expBrowseCallbackProc (HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) +{ + switch(uMsg) + { + case BFFM_INITIALIZED: + SendMessage (hwnd, BFFM_SETSELECTION, TRUE, pData); + break; + default: + break; + } + return 0; +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnExploreOutLandscapeDir () +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the path"; + bi.ulFlags = 0; + bi.lpfn = expBrowseCallbackProc; + bi.lParam = (LPARAM)(LPCSTR)OutLandscapeDir; + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return; + } + OutLandscapeDir = str; + UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnExploreOutIGDir() +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the path"; + bi.ulFlags = 0; + bi.lpfn = expBrowseCallbackProc; + bi.lParam = (LPARAM)(LPCSTR)OutIGDir; + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return; + } + OutIGDir = str; + UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnExploreLandSmallBankFile() +{ + CFileDialog dialog (true, "smallbank", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "SmallBank (*.smallbank)|*.smallbank", this); + if (dialog.DoModal() == IDOK) + { + LandBankFile = dialog.GetPathName (); + } + UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnExploreLandFarBankFile() +{ + CFileDialog dialog (true, "farbank", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "FarBank (*.farbank)|*.farbank", this); + if (dialog.DoModal() == IDOK) + { + LandFarBankFile = dialog.GetPathName(); + } + UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnExploreLandTileNoiseDir() +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the path"; + bi.ulFlags = 0; + bi.lpfn = expBrowseCallbackProc; + bi.lParam = (LPARAM)(LPCSTR)LandTileNoiseDir; + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return; + } + LandTileNoiseDir = str; + UpdateData (FALSE); // Upload +}*/ diff --git a/code/ryzom/tools/leveldesign/master/ExportDlg.h b/code/ryzom/tools/leveldesign/master/ExportDlg.h index 65bc1bc32..7262313be 100644 --- a/code/ryzom/tools/leveldesign/master/ExportDlg.h +++ b/code/ryzom/tools/leveldesign/master/ExportDlg.h @@ -1,89 +1,89 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_EXPORTDLG_H__D698050D_CF34_4D22_8F5B_FF8BAEFF6774__INCLUDED_) -#define AFX_EXPORTDLG_H__D698050D_CF34_4D22_8F5B_FF8BAEFF6774__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// ExportDlg.h : header file -// - -#include "../export/export.h" - -///////////////////////////////////////////////////////////////////////////// -// CExportDlg dialog - -class CExportDlg : public CDialog -{ - - SExportOptions *_Options; - std::vector *_Continents; - std::string _ActiveContinent; - bool _Finished; - -// Construction -public: - CExportDlg (CWnd* pParent = NULL); // standard constructor - - void setOptions (SExportOptions &options, std::vector ®Names); - -// Dialog Data - //{{AFX_DATA(CExportDlg) - enum { IDD = IDD_EXPORTOPT }; - CComboBox ContinentList; - //BOOL GenerateLandscape; - /* - BOOL GenerateVegetable; - CString OutLandscapeDir; - CString OutIGDir;*/ - CString ContinentName; - /*CString LandBankFile; - CString LandFarBankFile; - CString LandTileNoiseDir;*/ - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CExportDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CExportDlg) - virtual BOOL OnInitDialog(); - virtual void OnOK(); - /* - afx_msg void OnExploreOutLandscapeDir(); - afx_msg void OnExploreOutIGDir(); - afx_msg void OnExploreLandSmallBankFile(); - afx_msg void OnExploreLandFarBankFile(); - afx_msg void OnExploreLandTileNoiseDir(); - */ - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_EXPORTDLG_H__D698050D_CF34_4D22_8F5B_FF8BAEFF6774__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_EXPORTDLG_H__D698050D_CF34_4D22_8F5B_FF8BAEFF6774__INCLUDED_) +#define AFX_EXPORTDLG_H__D698050D_CF34_4D22_8F5B_FF8BAEFF6774__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ExportDlg.h : header file +// + +#include "../export/export.h" + +///////////////////////////////////////////////////////////////////////////// +// CExportDlg dialog + +class CExportDlg : public CDialog +{ + + SExportOptions *_Options; + std::vector *_Continents; + std::string _ActiveContinent; + bool _Finished; + +// Construction +public: + CExportDlg (CWnd* pParent = NULL); // standard constructor + + void setOptions (SExportOptions &options, std::vector ®Names); + +// Dialog Data + //{{AFX_DATA(CExportDlg) + enum { IDD = IDD_EXPORTOPT }; + CComboBox ContinentList; + //BOOL GenerateLandscape; + /* + BOOL GenerateVegetable; + CString OutLandscapeDir; + CString OutIGDir;*/ + CString ContinentName; + /*CString LandBankFile; + CString LandFarBankFile; + CString LandTileNoiseDir;*/ + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CExportDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CExportDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + /* + afx_msg void OnExploreOutLandscapeDir(); + afx_msg void OnExploreOutIGDir(); + afx_msg void OnExploreLandSmallBankFile(); + afx_msg void OnExploreLandFarBankFile(); + afx_msg void OnExploreLandTileNoiseDir(); + */ + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_EXPORTDLG_H__D698050D_CF34_4D22_8F5B_FF8BAEFF6774__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/master/MainFrm.cpp b/code/ryzom/tools/leveldesign/master/MainFrm.cpp index 90b50112f..cde1eaee3 100644 --- a/code/ryzom/tools/leveldesign/master/MainFrm.cpp +++ b/code/ryzom/tools/leveldesign/master/MainFrm.cpp @@ -1,1935 +1,1935 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// MainFrm.cpp : implementation of the CMainFrame class -// - -#include "stdafx.h" -#include "master.h" - -#include "MainFrm.h" -//#include "RegionPropertiesDlg.h" -//#include "NewGeorgesFormDlg.h" -//#include "PrimNameDlg.h" -#include "NameEditDlg.h" -#include "ChooseTag.h" -#include "ChooseDir.h" -#include "exportdlg.h" -#include "exportcbdlg.h" -#include "continentcfg.h" -#include "continentPropertiesDlg.h" - -#include "../georges_dll/georges_interface.h" -#include "../logic_editor_dll/logic_editor_interface.h" - -#include "nel/misc/file.h" -#include "nel/misc/stream.h" - -using namespace NLMISC; -using namespace std; - -#ifdef _DEBUG -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -#ifdef NL_NEW - #undef new -#endif - -///////////////////////////////////////////////////////////////////////////// - -// Do not parse following directories -char *gSysDir[MAX_SYS_DIR] = -{ - ".", - "..", - "ZoneBitmaps", - "ZoneLigos", - "dfn", - "tmp", - "cvs" -}; - -// Do not display files with those extensions -#define MAX_INVALID_EXT 1 -char *gInvalidExt[MAX_INVALID_EXT] = -{ - ".log" -}; - - -///////////////////////////////////////////////////////////////////////////// - -// --------------------------------------------------------------------------- -SEnvironnement::SEnvironnement() -{ - MasterX = 0; - MasterY = 0; - MasterTreeX = 0; - MasterTreeY = 0; - MasterTreeCX = 100; - MasterTreeCY = 100; - MasterTreeLocked = true; - - char tmp[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, tmp); - ContinentsDir = tmp; - ContinentsDir += "\\Continents\\"; - - WorldEdOpened = false; - WorldEdX = 50; - WorldEdY = 50; - WorldEdCX = 600; - WorldEdCY = 400; - - GeorgesOpened = false; - GeorgesX = 50; - GeorgesY = 50; - GeorgesCX = 300; - GeorgesCY = 300; - - LogicEditorOpened = false; - LogicEditorX = 50; - LogicEditorY = 50; - LogicEditorCX = 300; - LogicEditorCY = 300; -} - -// --------------------------------------------------------------------------- -bool SEnvironnement::load (const std::string &filename) -{ - if (!openRead(filename)) - return false; - // Master - MasterX = getInt ("MASTA_PosX"); - MasterY = getInt ("MASTA_PosY"); - MasterTreeX = getInt ("MASTA_TreePosX"); - MasterTreeY = getInt ("MASTA_TreePosY"); - MasterTreeCX = getInt ("MASTA_TreeSizeX"); - MasterTreeCY = getInt ("MASTA_TreeSizeY"); - MasterTreeLocked = getBool ("MASTA_TreeLocked"); - ContinentsDir = getStr ("MASTA_ContinentsDir"); - DefaultDFNDir = getStr ("MASTA_DefaultDFNDir"); - DefaultGameElemDir = getStr ("MASTA_DefaultGameElemDir"); - - // WorldEditor - WorldEdOpened = getBool ("WE_Opened"); - WorldEdX = getInt ("WE_PosX"); - WorldEdY = getInt ("WE_PosY"); - WorldEdCX = getInt ("WE_SizeX"); - WorldEdCY = getInt ("WE_SizeY"); - - // Georges - GeorgesOpened = getBool ("GG_Opened"); - GeorgesX = getInt ("GG_PosX"); - GeorgesY = getInt ("GG_PosY"); - GeorgesCX = getInt ("GG_SizeX"); - GeorgesCY = getInt ("GG_SizeY"); - - // LogicEditor - LogicEditorOpened = getBool ("LE_Opened"); - LogicEditorX = getInt ("LE_PosX"); - LogicEditorY = getInt ("LE_PosY"); - LogicEditorCX = getInt ("LE_SizeX"); - LogicEditorCY = getInt ("LE_SizeY"); - - // Export options - ExportOptions.loadcf (*cf); - close (); - return true; -} - -// --------------------------------------------------------------------------- -bool SEnvironnement::save (const std::string &filename) -{ - if (!openWrite(filename)) - return false; - - putCommentLine ("------"); - putCommentLine ("Master"); - putCommentLine ("------"); - putInt ("MASTA_PosX", MasterX); - putInt ("MASTA_PosY", MasterY); - putInt ("MASTA_TreePosX", MasterTreeX); - putInt ("MASTA_TreePosY", MasterTreeY); - putInt ("MASTA_TreeSizeX", MasterTreeCX); - putInt ("MASTA_TreeSizeY", MasterTreeCY); - putBool ("MASTA_TreeLocked", MasterTreeLocked); - putStr ("MASTA_ContinentsDir", ContinentsDir); - putStr ("MASTA_DefaultDFNDir", DefaultDFNDir); - putStr ("MASTA_DefaultGameElemDir",DefaultGameElemDir); - - putCommentLine ("-----------"); - putCommentLine ("WorldEditor"); - putCommentLine ("-----------"); - putBool ("WE_Opened", WorldEdOpened); - putInt ("WE_PosX", WorldEdX); - putInt ("WE_PosY", WorldEdY); - putInt ("WE_SizeX", WorldEdCX); - putInt ("WE_SizeY", WorldEdCY); - - putCommentLine ("-------"); - putCommentLine ("Georges"); - putCommentLine ("-------"); - putBool ("GG_Opened", GeorgesOpened); - putInt ("GG_PosX", GeorgesX); - putInt ("GG_PosY", GeorgesY); - putInt ("GG_SizeX", GeorgesCX); - putInt ("GG_SizeY", GeorgesCY); - - putCommentLine ("-----------"); - putCommentLine ("LogicEditor"); - putCommentLine ("-----------"); - putBool ("LE_Opened", LogicEditorOpened); - putInt ("LE_PosX", LogicEditorX); - putInt ("LE_PosY", LogicEditorY); - putInt ("LE_SizeX", LogicEditorCX); - putInt ("LE_SizeY", LogicEditorCY); - - // Export options - ExportOptions.save (f); - close(); - return true; -} - - -///////////////////////////////////////////////////////////////////////////// -// CMasterCB -///////////////////////////////////////////////////////////////////////////// - -// --------------------------------------------------------------------------- -CMasterCB::CMasterCB () -{ - _MainFrame = NULL; -} - -// --------------------------------------------------------------------------- -void CMasterCB::setMainFrame (CMainFrame*pMF) -{ - _MainFrame = pMF; -} - -// --------------------------------------------------------------------------- -vector &CMasterCB::getAllPrimZoneNames () -{ - return _PrimZoneList; -} - -// --------------------------------------------------------------------------- -void CMasterCB::setAllPrimZoneNames (vector &primZoneList) -{ - _PrimZoneList = primZoneList; - //_MainFrame->georgesUpdatePatatoid(); -} - -// --------------------------------------------------------------------------- -void CMasterCB::multiTransfert (const std::vector &vText, bool append) -{ - _GroupPrimList = vText; - _MainFrame->georgesPutGroupText (_GroupPrimList, append); -} - -// --------------------------------------------------------------------------- -void CMasterCB::transfert (const string &sText) -{ - _Text = sText; - _MainFrame->georgesPutText (_Text); -} - -// --------------------------------------------------------------------------- -void CMasterCB::lineUp () -{ - _MainFrame->georgesLineUp (); -} - -// --------------------------------------------------------------------------- -void CMasterCB::lineDown () -{ - _MainFrame->georgesLineDown (); -} - -///////////////////////////////////////////////////////////////////////////// -// CMainFrame -///////////////////////////////////////////////////////////////////////////// - -//IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) - -BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) - //{{AFX_MSG_MAP(CMainFrame) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code ! - - ON_COMMAND(ID_CONTINENT_SAVE, onContinentSave) - ON_COMMAND(ID_CONTINENT_EXPORT, onContinentExport) - - //ON_COMMAND(ID_CONTINENT_DELETE, OnContinentDelete) - - ON_COMMAND(ID_OPTIONS_TREELOCK, onOptionsTreeLock) - - ON_COMMAND(ID_OPTIONS_SETCONTINENTSDIR, onOptionsSetContinentsDir) - ON_COMMAND(ID_OPTIONS_SETDEFAULTDFNDIR, onOptionsSetDefaultDFNDir) - ON_COMMAND(ID_OPTIONS_SETDEFAULTGAMEELEMDIR, onOptionsSetDefaultGameElemDir) - - ON_COMMAND(ID_WINDOWS_WORLDEDITOR, onWindowsWorldEditor) - ON_COMMAND(ID_WINDOWS_GEORGES, onWindowsGeorges) - ON_COMMAND(ID_WINDOWS_LOGICEDITOR, onWindowsLogicEditor) - ON_COMMAND(ID_WINDOWS_RESET, onWindowsReset) - - ON_WM_CREATE() - ON_WM_ERASEBKGND() - ON_WM_SIZE() - ON_WM_MOVE() - ON_WM_CLOSE() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CMainFrame construction/destruction - -// --------------------------------------------------------------------------- -CMainFrame::CMainFrame() -{ - _WorldEditor = NULL; - _Georges = NULL; - _LogicEditor = NULL; - _Tree = NULL; - _Export = NULL; - _ExportCBDlg = NULL; -} - -// --------------------------------------------------------------------------- -CMainFrame::~CMainFrame() -{ - delete _Export; -} - -// --------------------------------------------------------------------------- -// Used by getAllInterfaces method to retrieve all DLLs and tools Interfaces - -typedef IWorldEditor* (*IWORLDEDITOR_GETINTERFACE)(int version); -const char *IWORLDEDITOR_GETINTERFACE_NAME = "IWorldEditorGetInterface"; -typedef void (*IWORLDEDITOR_RELINTERFACE)(IWorldEditor*pWE); -const char *IWORLDEDITOR_RELINTERFACE_NAME = "IWorldEditorReleaseInterface"; - -typedef IGeorges* (*IGEORGES_GETINTERFACE)(int version); -const char *IGEORGES_GETINTERFACE_NAME = "IGeorgesGetInterface"; -typedef void (*IGEORGES_RELINTERFACE)(IGeorges *pGeorges); -const char *IGEORGES_RELINTERFACE_NAME = "IGeorgesReleaseInterface"; - -typedef ILogicEditor* (*ILOGICEDITOR_GETINTERFACE)(int version); -const char *ILOGICEDITOR_GETINTERFACE_NAME = "ILogicEditorGetInterface"; -typedef void (*ILOGICEDITOR_RELINTERFACE)(ILogicEditor *pLogicEditor); -const char *ILOGICEDITOR_RELINTERFACE_NAME = "ILogicEditorReleaseInterface"; - -// --------------------------------------------------------------------------- -void CMainFrame::getAllInterfaces () -{ - SetCurrentDirectory (_MasterExeDir.c_str()); - - // Get WorldEditor Interface - if (_WorldEditor == NULL) - { - IWORLDEDITOR_GETINTERFACE IWEGetInterface = NULL; - - #if defined NL_RELEASE_DEBUG - _WorldEditorModule = AfxLoadLibrary ("WorldEditor_rd.dll"); - #elif defined NL_DEBUG_FAST - _WorldEditorModule = AfxLoadLibrary ("WorldEditor_df.dll"); - #elif defined _DEBUG - _WorldEditorModule = AfxLoadLibrary ("WorldEditor_debug.dll"); - #elif defined NDEBUG - _WorldEditorModule = AfxLoadLibrary ("WorldEditor.dll"); - #endif - if (_WorldEditorModule != NULL) - { - IWEGetInterface = (IWORLDEDITOR_GETINTERFACE)::GetProcAddress (_WorldEditorModule, IWORLDEDITOR_GETINTERFACE_NAME); - if (IWEGetInterface != NULL) - _WorldEditor = IWEGetInterface (WORLDEDITOR_VERSION); - } - else - { - MessageBox("WorldEditor dll not Loaded", "Warning"); - } - } - - // Get Georges Interface - if (_Georges == NULL) - { - IGEORGES_GETINTERFACE IGGetInterface = NULL; - - #if defined NL_RELEASE_DEBUG - _GeorgesModule = AfxLoadLibrary ("Georges_dll_rd.dll"); - #elif defined NL_DEBUG_FAST - _GeorgesModule = AfxLoadLibrary ("Georges_dll_debug_fast.dll"); - #elif defined _DEBUG - _GeorgesModule = AfxLoadLibrary ("Georges_dll_debug.dll"); - #elif defined NDEBUG - _GeorgesModule = AfxLoadLibrary ("Georges_dll.dll"); - #endif - if (_GeorgesModule != NULL) - { - IGGetInterface = (IGEORGES_GETINTERFACE)::GetProcAddress (_GeorgesModule, IGEORGES_GETINTERFACE_NAME); - if (IGGetInterface != NULL) - _Georges = IGGetInterface (GEORGES_VERSION); - } - else - { - MessageBox("Georges dll not Loaded", "Warning"); - } - } - - // Get LogicEditor Interface - if (_LogicEditor == NULL) - { - ILOGICEDITOR_GETINTERFACE ILEGetInterface = NULL; - - #if defined NL_RELEASE_DEBUG - _LogicEditorModule = AfxLoadLibrary ("Logic_Editor_rd.dll"); - #elif defined NL_DEBUG_FAST - _LogicEditorModule = AfxLoadLibrary ("Logic_Editor_df.dll"); - #elif defined _DEBUG - _LogicEditorModule = AfxLoadLibrary ("Logic_Editor_debug.dll"); - #elif defined NDEBUG - _LogicEditorModule = AfxLoadLibrary ("Logic_Editor.dll"); - #endif - if (_LogicEditorModule != NULL) - { - ILEGetInterface = (ILOGICEDITOR_GETINTERFACE)::GetProcAddress (_LogicEditorModule, ILOGICEDITOR_GETINTERFACE_NAME); - if (ILEGetInterface != NULL) - _LogicEditor = ILEGetInterface (LOGIC_EDITOR_VERSION); - } - else - { - MessageBox("LogicEditor dll not Loaded", "Warning"); - } - } -} - -// --------------------------------------------------------------------------- -void CMainFrame::releaseAllInterfaces() -{ - // Release the WorldEditor interface - if (_WorldEditor != NULL) - { - IWORLDEDITOR_RELINTERFACE IWERelInterface = NULL; - IWERelInterface = (IWORLDEDITOR_RELINTERFACE)::GetProcAddress (_WorldEditorModule, IWORLDEDITOR_RELINTERFACE_NAME); - IWERelInterface (_WorldEditor); - } - - // Release the Georges interface - if (_Georges != NULL) - { - IGEORGES_RELINTERFACE IGRelInterface = NULL; - IGRelInterface = (IGEORGES_RELINTERFACE)::GetProcAddress (_GeorgesModule, IGEORGES_RELINTERFACE_NAME); - IGRelInterface (_Georges); - } - - // Release the LogicEditor interface - if (_LogicEditor != NULL) - { - ILOGICEDITOR_RELINTERFACE ILERelInterface = NULL; - ILERelInterface = (ILOGICEDITOR_RELINTERFACE)::GetProcAddress (_LogicEditorModule, ILOGICEDITOR_RELINTERFACE_NAME); - ILERelInterface (_LogicEditor); - } -} - -// --------------------------------------------------------------------------- -void CMainFrame::openFile (const string &fname) -{ - char curdir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, curdir); - - string sFullName; - sFullName = _Environnement.ContinentsDir; - - sFullName += fname; - - int size = fname.size(); - - if ((size >= 13) && (stricmp(&fname[size-13],"continent.cfg") == 0)) - { - openContinentCfgFile (sFullName.c_str()); - } - else if ((stricmp(&fname[size-5],".prim") == 0) || (stricmp(&fname[size-5],".land") == 0)) - { - openWorldEditor (); - openWorldEditorFile (sFullName.c_str()); - } - else if (stricmp(&fname[size-6],".logic") == 0) - { - openLogicEditor (); - openLogicEditorFile (sFullName.c_str()); - } - else - { - openGeorges (); - openGeorgesFile (sFullName.c_str()); - } - - SetCurrentDirectory (curdir); -} - -// --------------------------------------------------------------------------- -void CMainFrame::openDir (const string &fname) -{ - if (_ActivePath == "") return; - - char curdir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, curdir); - - string sBaseName; - sBaseName = _Environnement.ContinentsDir; - - openDirParse (sBaseName, fname); - - SetCurrentDirectory (curdir); -} - -// --------------------------------------------------------------------------- -void CMainFrame::openDirParse (const std::string &sBaseNameDir, const std::string &sRelativeNameDir) -{ - WIN32_FIND_DATA findData; - HANDLE hFind; - - char sCurDir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, sCurDir); - - string sFullNamedDir = sBaseNameDir + sRelativeNameDir; - if (!SetCurrentDirectory (sFullNamedDir.c_str())) - { - SetCurrentDirectory (sCurDir); - return; - } - - hFind = FindFirstFile ("*.*", &findData); - while (hFind != INVALID_HANDLE_VALUE) - { - if (GetFileAttributes(findData.cFileName)&FILE_ATTRIBUTE_DIRECTORY) - { - // Look if the name is a system directory - bool bFound = false; - for (uint32 i = 0; i < MAX_SYS_DIR; ++i) - if (stricmp (findData.cFileName, gSysDir[i]) == 0) - { - bFound = true; - break; - } - if (!bFound) // No, ok lets recurse it - { - string newPath = sRelativeNameDir + string("\\") + string(findData.cFileName); - openDirParse (sBaseNameDir, newPath); - } - } - else - { - // Check for invalid extension - bool bFound = false; - for (uint32 j = 0; j < MAX_INVALID_EXT; ++j) - if (strlen(findData.cFileName) > strlen(gInvalidExt[j])) - if (stricmp(&findData.cFileName[strlen(findData.cFileName)-strlen(gInvalidExt[j])], gInvalidExt[j]) == 0) - { - bFound = true; - break; - } - // If the extension is an invalid one -> Do not open the file - if (!bFound) - { - string fileName = sRelativeNameDir + "\\" + findData.cFileName; - openFile (fileName.c_str()); - } - } - if (FindNextFile (hFind, &findData) == 0) - break; - } - FindClose (hFind); - - SetCurrentDirectory (sCurDir); -} - -// --------------------------------------------------------------------------- -void CMainFrame::openContinentCfgFile (const string &filename) -{ - SContinentCfg cfg; - cfg.load (filename); - _WorldEditor->setDataDir (cfg.LandDir.c_str()); - openWorldEditor (); - openWorldEditorFile (cfg.LandFile.c_str()); -} - -// --------------------------------------------------------------------------- -void CMainFrame::openWorldEditor() -{ - if (_Environnement.WorldEdOpened) - return; - _Environnement.WorldEdOpened = true; - if (_WorldEditor != NULL) - _WorldEditor->initUILight (_Environnement.WorldEdX, _Environnement.WorldEdY, - _Environnement.WorldEdCX, _Environnement.WorldEdCY); - GetMenu()->CheckMenuItem (ID_WINDOWS_WORLDEDITOR, MF_CHECKED); -} - -// --------------------------------------------------------------------------- -void CMainFrame::openWorldEditorFile (const string &fileName) -{ - _WorldEditor->loadFile (fileName.c_str()); -} - -// --------------------------------------------------------------------------- -void CMainFrame::closeWorldEditor() -{ - if (_WorldEditor == NULL) return; - if (!_Environnement.WorldEdOpened) return; - - //onContinentSave (); - _Environnement.WorldEdOpened = false; - RECT r; - CFrameWnd *pFW = (CFrameWnd*)_WorldEditor->getMainFrame(); - pFW->GetWindowRect(&r); - WINDOWPLACEMENT wp; - pFW->GetWindowPlacement (&wp); - if (wp.showCmd == SW_SHOWNORMAL) - { - _Environnement.WorldEdY = r.top; - _Environnement.WorldEdX = r.left; - _Environnement.WorldEdCY = r.bottom - r.top; - _Environnement.WorldEdCX = r.right - r.left; - } - _WorldEditor->releaseUI (); - GetMenu()->CheckMenuItem (ID_WINDOWS_WORLDEDITOR, MF_UNCHECKED); -} - -// --------------------------------------------------------------------------- -void CMainFrame::openGeorges () -{ - if (_Georges == NULL) return; - if (_Environnement.GeorgesOpened) - return; - _Environnement.GeorgesOpened = true; - if (_Georges != NULL) - { - _Georges->initUILight (SW_SHOW, _Environnement.GeorgesX, _Environnement.GeorgesY, - _Environnement.GeorgesCX, _Environnement.GeorgesCY); - } - GetMenu()->CheckMenuItem (ID_WINDOWS_GEORGES, MF_CHECKED); -} - -// --------------------------------------------------------------------------- -void CMainFrame::openGeorgesFile (const string &fileName) -{ - if (_Georges == NULL) return; - georgesSetPathesFromActive (); - _Georges->LoadDocument (fileName); -} - -// --------------------------------------------------------------------------- -void CMainFrame::closeGeorges () -{ - if (_Georges == NULL) return; - if (!_Environnement.GeorgesOpened) return; - - _Environnement.GeorgesOpened = false; - RECT r; - CFrameWnd *pFW = (CFrameWnd*)_Georges->getMainFrame(); - pFW->GetWindowRect(&r); - WINDOWPLACEMENT wp; - pFW->GetWindowPlacement (&wp); - if (wp.showCmd == SW_SHOWNORMAL) - { - _Environnement.GeorgesY = r.top; - _Environnement.GeorgesX = r.left; - _Environnement.GeorgesCY = r.bottom - r.top; - _Environnement.GeorgesCX = r.right - r.left; - } - _Georges->releaseUI (); - GetMenu()->CheckMenuItem (ID_WINDOWS_GEORGES, MF_UNCHECKED); -} - -// --------------------------------------------------------------------------- -void CMainFrame::georgesSetPathesFromActive () -{ - if (_Georges == NULL) return; - if (_ActivePath == "") - { - string sDir; - sDir = _Environnement.ContinentsDir; - _Georges->SetDirLevel (sDir); - - _Georges->SetDirDfnTyp (_Environnement.DefaultDFNDir); - _Georges->SetDirPrototype (_Environnement.DefaultGameElemDir); - } - else - { - string sDir; - - int i = 0; - if (_ActivePath[i] == '\\') ++i; - for (; i < (int)_ActivePath.size(); ++i) - { - if (_ActivePath[i] == '\\') break; - sDir += _ActivePath[i]; - } - - sDir = _Environnement.ContinentsDir + sDir + "\\"; - - _Georges->SetDirLevel (sDir); - - SContinentCfg cfg; - string sTmp = sDir + "continent.cfg"; - cfg.load (sTmp.c_str()); - _Georges->SetDirDfnTyp (cfg.DfnDir); - _Georges->SetDirPrototype (cfg.GameElemDir); - } -} - -// --------------------------------------------------------------------------- -/* -void CMainFrame::georgesUpdatePatatoid () -{ - if (_Georges == NULL) return; - if ((_ActiveWorld == "") || (_ActiveContinent == "") || (_ActiveRegion == "")) return; - - string sCurDir; - if (_ActiveWorld == "Continents") - sCurDir = _Environnement.ContinentsDir; - else if (_ActiveWorld == "Trash") - sCurDir = _Environnement.TrashDir; - else if (_ActiveWorld == "Backup") - sCurDir = _Environnement.BackupDir; - sCurDir += _ActiveContinent + "\\" + _ActiveRegion + "\\"; - _Georges->SetDirLevel (sCurDir); - - if (_ActiveContinent != "") - _Georges->SetTypPredef (sCurDir + "tmp\\patat_name.typ", _MasterCB.getAllPrimZoneNames()); -} -*/ - -// --------------------------------------------------------------------------- -void CMainFrame::georgesPutGroupText (const std::vector &vText, bool append) -{ - if (_Georges == NULL) return; - _Georges->PutGroupText (vText, append); -} - -// --------------------------------------------------------------------------- -void CMainFrame::georgesPutText (const std::string &sText) -{ - if (_Georges == NULL) return; - _Georges->PutText (sText); -} - -// --------------------------------------------------------------------------- -void CMainFrame::georgesLineUp () -{ - if (_Georges == NULL) return; - _Georges->LineUp (); -} - -// --------------------------------------------------------------------------- -void CMainFrame::georgesLineDown () -{ - if (_Georges == NULL) return; - _Georges->LineDown (); -} - -// --------------------------------------------------------------------------- -/* -void CMainFrame::georgesCreateFilesWhenNewRegion () -{ - // When we arrive in this function the current directory is the new Continent being created - if (_Georges == NULL) - return; - - CreateDirectory ("tmp", NULL); - char curdir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, curdir); - string fullname = string(curdir) + "\\tmp\\patat_name.typ"; - vector< pair< string, string > > lpsx; - vector< pair< string, string > > lpsx2; - lpsx.push_back (make_pair(string("PatatFrite"), string("PatatFrite"))); - lpsx.push_back (make_pair(string("PatatVapeur"), string("PatatVapeur"))); - _Georges->MakeTyp (fullname, "String", "PATAT", "true", "", "", "PatatFrite", &lpsx, &lpsx2); -} -*/ - -// --------------------------------------------------------------------------- -void CMainFrame::georgesCreatePlantName () -{ - if (_Georges == NULL) return; - WIN32_FIND_DATA fdTmp; - char curdir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, curdir); - - try - { - string plantname = _Environnement.DefaultDFNDir; - if (!SetCurrentDirectory(plantname.c_str())) - return; - - plantname += "tmp\\plant_name.typ"; - - // If plantname file do not already exists - HANDLE hFind = FindFirstFile(plantname.c_str(), &fdTmp); - if (hFind != INVALID_HANDLE_VALUE) - { - FindClose (hFind); - if (!DeleteFile (plantname.c_str())) - { - MessageBox (plantname.c_str(), "Cannot overwrite"); - return; - } - } - - vector< pair< string, string > > lpsx; - vector< pair< string, string > > lpsx2; - lpsx.push_back (std::make_pair(string("xxx.plant"), string("xxx.plant"))); - lpsx.push_back (std::make_pair(string("yyy.plant"), string("yyy.plant"))); - _Georges->MakeTyp (plantname, String, FileBrowser, "", "", "xxx.plant", &lpsx); - - // Parse the plant directory and add all these predef - string plantdir = _Environnement.DefaultGameElemDir; - if (!SetCurrentDirectory (plantdir.c_str())) - return; - - vector allPlants; - CExport::getAllFiles (".plant", allPlants); - - for (uint32 i = 0; i < allPlants.size(); ++i) - { - char fName[_MAX_FNAME]; - char ext[_MAX_FNAME]; - ::_splitpath((const char*)allPlants[i].c_str(), NULL, NULL, fName, ext); - allPlants[i] = string(fName) + string(ext); - } - - // todo Hulud : handle this another way.. - // _Georges->SetTypPredef ("plant_name.typ", allPlants); - } - catch(NLMISC::Exception &e) - { - MessageBox (e.what(), "Warning", MB_ICONERROR|MB_OK); - } - SetCurrentDirectory (curdir); -} - -// --------------------------------------------------------------------------- -void CMainFrame::openLogicEditor () -{ - if (_Environnement.LogicEditorOpened) - return; - _Environnement.LogicEditorOpened = true; - if (_LogicEditor != NULL) - _LogicEditor->initUILight (_Environnement.LogicEditorX, _Environnement.LogicEditorY, - _Environnement.LogicEditorCX, _Environnement.LogicEditorCY); - GetMenu()->CheckMenuItem (ID_WINDOWS_LOGICEDITOR, MF_CHECKED); -} - -// --------------------------------------------------------------------------- -void CMainFrame::openLogicEditorFile (const string &fileName) -{ - _LogicEditor->loadFile (fileName.c_str()); -} - -// --------------------------------------------------------------------------- -void CMainFrame::closeLogicEditor () -{ - if (!_Environnement.LogicEditorOpened) - return; - _Environnement.LogicEditorOpened = false; - RECT r; - CFrameWnd *pFW = (CFrameWnd*)_LogicEditor->getMainFrame(); - pFW->GetWindowRect(&r); - WINDOWPLACEMENT wp; - pFW->GetWindowPlacement (&wp); - if (wp.showCmd == SW_SHOWNORMAL) - { - _Environnement.LogicEditorY = r.top; - _Environnement.LogicEditorX = r.left; - _Environnement.LogicEditorCY = r.bottom - r.top; - _Environnement.LogicEditorCX = r.right - r.left; - } - _LogicEditor->releaseUI (); - GetMenu()->CheckMenuItem (ID_WINDOWS_LOGICEDITOR, MF_UNCHECKED); -} - -// --------------------------------------------------------------------------- -void CMainFrame::updateTree() -{ - _Tree->update (_Environnement.ContinentsDir); -} - -// --------------------------------------------------------------------------- -void CMainFrame::deltree (const std::string &dirName) -{ - // Get all directory object - vector toremovelist; - WIN32_FIND_DATA findData; - HANDLE hFind; - char sCurDir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, sCurDir); - if (!SetCurrentDirectory (dirName.c_str())) - return; - hFind = FindFirstFile ("*.*", &findData); - while (hFind != INVALID_HANDLE_VALUE) - { - // Look if the name is a system directory - if ((stricmp (findData.cFileName, ".") != 0) && (stricmp (findData.cFileName, "..") != 0)) - { - if (findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) - { - // If this is a directory deltree and delete the directory - deltree (findData.cFileName); - toremovelist.push_back (findData.cFileName); - } - else - { - // If this is a file delete - if (!DeleteFile (findData.cFileName)) - displayLastErrorDialog (); - } - } - if (FindNextFile (hFind, &findData) == 0) - break; - } - FindClose (hFind); - SetCurrentDirectory (dirName.c_str()); - for (uint32 i = 0; i < toremovelist.size(); ++i) - { - if (!RemoveDirectory (toremovelist[i].c_str())) - displayLastErrorDialog (); - } - SetCurrentDirectory (sCurDir); -} - -// --------------------------------------------------------------------------- -void CMainFrame::displayLastErrorDialog () -{ - LPVOID lpMsgBuf; - FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, 0, NULL); - // Display the string. - MessageBox ((LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONERROR); - // Free the buffer. - LocalFree (lpMsgBuf); -} - -// --------------------------------------------------------------------------- -/*int getMaxTag(const std::string &dirName, const std::string &tagName) -{ - WIN32_FIND_DATA findData; - HANDLE hFind; - char sCurDir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, sCurDir); - SetCurrentDirectory (dirName.c_str()); - string tmp = tagName + "*"; - hFind = FindFirstFile (tmp.c_str(), &findData); - int ret = 0; - while (hFind != INVALID_HANDLE_VALUE) - { - int nb = (findData.cFileName[tagName.size()+0]-'0')*100 + - (findData.cFileName[tagName.size()+1]-'0')*10 + - (findData.cFileName[tagName.size()+2]-'0')*1; - if (nb > ret) - ret = nb; - if (FindNextFile (hFind, &findData) == 0) - break; - } - FindClose (hFind); - SetCurrentDirectory (sCurDir); - return ret; -}*/ - -// --------------------------------------------------------------------------- -void CMainFrame::copytree (const string &srcDir, const string &dstDir) -{ - WIN32_FIND_DATA findData; - HANDLE hFind; - string tmp = srcDir + "\\*"; - hFind = FindFirstFile (tmp.c_str(), &findData); - while (hFind != INVALID_HANDLE_VALUE) - { - bool bFound = false; - for (uint32 i = 0; i < MAX_SYS_DIR; ++i) - if (stricmp (findData.cFileName, gSysDir[i]) == 0) - { - bFound = true; - break; - } - if (!bFound) - { - if (findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) - { - string newDirSrc = srcDir + "\\" + findData.cFileName; - string newDirDst = dstDir + "\\" + findData.cFileName; - if (!CreateDirectory(newDirDst.c_str(), NULL)) - displayLastErrorDialog (); - copytree (newDirSrc, newDirDst); - } - else - { - string fnameSrc = srcDir + "\\" + findData.cFileName; - string fnameDst = dstDir + "\\" + findData.cFileName; - if (!CopyFile(fnameSrc.c_str(), fnameDst.c_str(), false)) - displayLastErrorDialog (); - } - } - - if (FindNextFile (hFind, &findData) == 0) - break; - } - FindClose (hFind); -} - - -// --------------------------------------------------------------------------- -void CMainFrame::continentDelete (const string &contName) -{ - string srcDir = _Environnement.ContinentsDir + contName; - deltree (srcDir); - RemoveDirectory (srcDir.c_str()); - updateTree (); -} - -// --------------------------------------------------------------------------- -void CMainFrame::regionOpen (const string &path) -{ - setActivePath (path); - openDir (path); -} - -// --------------------------------------------------------------------------- -void CMainFrame::regionRename (const string &path) -{ - if (path == "") return; - int pos = path.rfind('\\'); - if (pos == string::npos) return; - string smallpath; - int i; - for (i = 0; i <= pos; ++i) - smallpath += path[i]; - string dirname; - for (; i < (int)path.size(); ++i) - dirname += path[i]; - smallpath = _Environnement.ContinentsDir + smallpath; - char curdir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, curdir); - SetCurrentDirectory (smallpath.c_str()); - - CNameEditDlg dlg; - dlg.Title = "Change the directory name"; - dlg.Comment = "Enter the new directory name"; - dlg.Name = dirname.c_str(); - - if (dlg.DoModal() == IDOK) - { - if (!MoveFile (dirname.c_str(), dlg.Name)) - displayLastErrorDialog (); - } - - SetCurrentDirectory (curdir); -} - -// --------------------------------------------------------------------------- -void CMainFrame::regionNewPrim (const string &path) -{ - if (path == "") return; - if (_WorldEditor == NULL) return; - - // Ask the name to the user - CNameEditDlg dlg; - dlg.Title = "New Prim File Name"; - dlg.Comment = "Enter the name of the new .PRIM file"; - dlg.Name = "NewPrim"; - if (dlg.DoModal() == IDOK) - { - string primname = dlg.Name; - if (primname != "") - { - string sTmp = _Environnement.ContinentsDir + path + "\\" + primname; - _WorldEditor->createEmptyPrimFile (sTmp.c_str()); - updateTree (); - } - } -} - -// --------------------------------------------------------------------------- -void CMainFrame::regionNewGeorges (const string &path) -{ - if (path == "") - return; - if (_Georges == NULL) - return; - - // Ask the user the .dfn to use - CNameEditDlg dlg; - dlg.Title = "New Form File Name"; - dlg.Comment = "Enter the name of the new Form file"; - dlg.Name = "NewForm"; - if (dlg.DoModal() == IDOK) - { - char curdir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, curdir); - - // setActivePath (path); - - // \todo load from the continent.cfg - string newDir = _Georges->GetDirDfnTyp (); - - CFileDialog fd (true, "*.dfn", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, - "Definition (*.dfn)|*.dfn", this); - fd.m_ofn.lpstrInitialDir = newDir.c_str(); - if (fd.DoModal() == IDOK) - { - string sTmp = _Environnement.ContinentsDir + path + "\\" + (LPCSTR)dlg.Name; - _Georges->createInstanceFile (sTmp, (LPCSTR)fd.GetFileName()); - } - - SetCurrentDirectory (curdir); - updateTree (); - } -} - -// --------------------------------------------------------------------------- -void CMainFrame::regionNewSubRegion (const std::string &path) -{ - char sCurDir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, sCurDir); - - CNameEditDlg dlg(this); - dlg.Title = "New Sub Region"; - dlg.Comment = "Enter the name of the new sub region"; - dlg.Name = "NewSubRegion"; - - if (dlg.DoModal() == IDOK) - { - if (dlg.Name != "") - { - string tmpDir = _Environnement.ContinentsDir + path; - SetCurrentDirectory (tmpDir.c_str()); - CreateDirectory ((LPCSTR)dlg.Name, NULL); - SetCurrentDirectory (dlg.Name); - updateTree (); - } - } - - SetCurrentDirectory (sCurDir); -} - -// --------------------------------------------------------------------------- -void CMainFrame::regionDelete (const std::string &path) -{ - string srcDir = _Environnement.ContinentsDir + path; - deltree (srcDir); - if (!RemoveDirectory (srcDir.c_str())) - displayLastErrorDialog (); - updateTree (); -} - -// --------------------------------------------------------------------------- -void CMainFrame::fileOpen (const std::string &sFileFullName) -{ - openFile (sFileFullName); -} - -// --------------------------------------------------------------------------- -void CMainFrame::fileRename (const std::string &sFileFullName) -{ - if (sFileFullName == "") return; - int pos = sFileFullName.rfind('\\'); - if (pos == string::npos) return; - string smallpath; - int i; - for (i = 0; i <= pos; ++i) - smallpath += sFileFullName[i]; - string filename; - for (; i < (int)sFileFullName.size(); ++i) - filename += sFileFullName[i]; - smallpath = _Environnement.ContinentsDir + smallpath; - char curdir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, curdir); - SetCurrentDirectory (smallpath.c_str()); - - CNameEditDlg dlg; - dlg.Title = "Change the name of the file"; - dlg.Comment = "Enter the new file name"; - dlg.Name = filename.c_str(); - - if (dlg.DoModal() == IDOK) - { - if (!MoveFile (filename.c_str(), dlg.Name)) - { - MessageBox ("Cannot rename file", "Error", MB_ICONERROR|MB_OK); - } - } - - SetCurrentDirectory (curdir); -} - -// --------------------------------------------------------------------------- -void CMainFrame::fileDelete (const std::string &sFileFullName) -{ - if (sFileFullName.size() > 4) - if (stricmp(&sFileFullName.c_str()[sFileFullName.size()-4], ".cfg") == 0) - return; - string fullname = _Environnement.ContinentsDir + sFileFullName; - DeleteFile (fullname.c_str()); - updateTree (); -} - -// --------------------------------------------------------------------------- -void CMainFrame::copy (const std::string &sPathSrc, const std::string &sPathDst) -{ - string sSrc = _Environnement.ContinentsDir + sPathSrc; - string sDst = _Environnement.ContinentsDir + sPathDst; - - if (GetFileAttributes(sSrc.c_str())&FILE_ATTRIBUTE_DIRECTORY) - { - copytree (sSrc, sDst); - } - else - { - int zepos = sSrc.rfind('\\'); - for (int i = zepos; i < (int)sSrc.size(); ++i) - sDst += sSrc[i]; - if (!CopyFile (sSrc.c_str(), sDst.c_str(), TRUE)) - displayLastErrorDialog (); - } - updateTree(); -} - -// --------------------------------------------------------------------------- -void CMainFrame::setActivePath (const std::string &pathName) -{ - _ActivePath = pathName; - if (_ActivePath == "") return; - string sContinentDir; - int i = 0; - if (pathName[i] == '\\') ++i; - for (; i < (int)pathName.size(); ++i) - { - if (pathName[i] == '\\') break; - sContinentDir += pathName[i]; - } - - sContinentDir = _Environnement.ContinentsDir + sContinentDir; - - if (_Georges != NULL) - { - georgesSetPathesFromActive (); - } - - if ((_Environnement.WorldEdOpened) && (_ActivePath != "")) - { - // Open continent.cfg to load the .land - SContinentCfg cfg; - string sTmp = sContinentDir + "\\continent.cfg"; - cfg.load (sTmp.c_str()); - _WorldEditor->setDataDir(cfg.LandDir.c_str()); - _WorldEditor->loadFile (cfg.LandFile.c_str()); - } -} - -// --------------------------------------------------------------------------- -void CMainFrame::OnSize (UINT nType, int cx, int cy) -{ -} - -// --------------------------------------------------------------------------- -void CMainFrame::OnMove (int x, int y) -{ - RECT r; - GetWindowRect (&r); - _Environnement.MasterY = r.top; - _Environnement.MasterX = r.left; - if ((_Tree != NULL) && (_Environnement.MasterTreeLocked)) - { - _Tree->SetWindowPos (&wndTop, x, y, 0, 0, SWP_NOSIZE); - SetFocus(); - } -} - -// --------------------------------------------------------------------------- -int CMainFrame::OnCreate (LPCREATESTRUCT lpCreateStruct) -{ - // Create the menu - if (CFrameWnd::OnCreate(lpCreateStruct) == -1) - return -1; - - CoInitialize (NULL); - - // Create the tree - _Tree = new CMasterTreeDlg (); - _Tree->Create (IDD_MASTERTREE, this); - - // Load tools and get interface - getAllInterfaces (); - - // Restore all (windows position and size, menu checked, etc...) - // TREE - _Tree->SetWindowPos (&wndTop, _Environnement.MasterTreeX, _Environnement.MasterTreeY, - _Environnement.MasterTreeCX, _Environnement.MasterTreeCY, SWP_SHOWWINDOW); - _Tree->ShowWindow (SW_SHOW); - _Tree->update (_Environnement.ContinentsDir); - if (_Environnement.MasterTreeLocked) - GetMenu()->CheckMenuItem (ID_OPTIONS_TREELOCK, MF_CHECKED); - - // WORLDEDITOR - if (_WorldEditor != NULL) - { - _MasterCB.setMainFrame (this); - _WorldEditor->setMasterCB (&_MasterCB); - _WorldEditor->setDataDir (_Environnement.ContinentsDir.c_str()); - } - if (_Environnement.WorldEdOpened) - { - _Environnement.WorldEdOpened = false; - openWorldEditor (); - } - - // GEORGES - if (_Georges != NULL) - { - _Georges->SetDirDfnTyp (_Environnement.DefaultDFNDir); - _Georges->SetDirPrototype (_Environnement.DefaultGameElemDir); - georgesCreatePlantName (); - } - if (_Environnement.GeorgesOpened) - { - _Environnement.GeorgesOpened = false; - openGeorges (); - } - - // LOGICEDITOR -// if (_LogicEditor != NULL) -// _LogicEditor->setRootDir (_Environnement.RootDir.c_str()); - if (_Environnement.LogicEditorOpened) - { - _Environnement.LogicEditorOpened = false; - openLogicEditor (); - } - - return 0; -} - -// --------------------------------------------------------------------------- -BOOL CMainFrame::PreCreateWindow (CREATESTRUCT& cs) -{ - // Load the config file - char sCurDir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, sCurDir); - _MasterExeDir = string(sCurDir) + "\\"; - try - { - _Environnement.load (_MasterExeDir+"master.cfg"); - } - catch (Exception&e) - { - MessageBox (e.what(), "Warning"); - } - - // Restore the master window position - cs.x = _Environnement.MasterX; - cs.y = _Environnement.MasterY; - - if (!CFrameWnd::PreCreateWindow(cs)) - return FALSE; - - cs.style = WS_OVERLAPPED; - cs.cx = 360; - cs.cy = GetSystemMetrics (SM_CYCAPTION) + - GetSystemMetrics (SM_CYMENU) + - GetSystemMetrics (SM_CYFRAME); - - return TRUE; -} - -// --------------------------------------------------------------------------- -BOOL CMainFrame::PreTranslateMessage (MSG*pMsg) -{ - if (_Georges != NULL) - { - CWnd *pWnd = (CWnd*)_Georges->getMainFrame(); - CWnd *pFocusWnd = CWnd::GetFocus(); - if (pWnd != NULL) - { - while (pFocusWnd != NULL) - { - if (pWnd->m_hWnd == pFocusWnd->m_hWnd) - return _Georges->PreTranslateMessage (pMsg); - pFocusWnd = pFocusWnd->GetParent(); - } - } - } - return CFrameWnd::PreTranslateMessage (pMsg); -} - -// --------------------------------------------------------------------------- -BOOL CMainFrame::OnEraseBkgnd (CDC* pDC) -{ - return true; -} - -// --------------------------------------------------------------------------- -bool CMainFrame::createDirIfNotExist (const string& dirName, const string& errorMsg) -{ - char sCurDir[MAX_PATH]; - SECURITY_ATTRIBUTES sa; - sa.nLength = sizeof(sa); - sa.lpSecurityDescriptor = NULL; - sa.bInheritHandle = true; - GetCurrentDirectory (MAX_PATH, sCurDir); - if (!SetCurrentDirectory (dirName.c_str())) - { - if (!CreateDirectory (dirName.c_str(), &sa)) - { - MessageBox (errorMsg.c_str(), "Error", MB_ICONERROR|MB_OK); - SetCurrentDirectory (sCurDir); - return false; - } - } - SetCurrentDirectory (sCurDir); - return true; -} -// --------------------------------------------------------------------------- -void CMainFrame::continentNew () -{ - if (!createDirIfNotExist (_Environnement.ContinentsDir, "Cannot create Continents system directory")) - return; - - // Create the new continent - char sCurDir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, sCurDir); - SetCurrentDirectory (_Environnement.ContinentsDir.c_str()); - CreateDirectory ("NewContinent", NULL); - SContinentCfg cfg; - cfg.save ("NewContinent\\continent.cfg"); - - SetCurrentDirectory (_Environnement.ContinentsDir.c_str()); - SetCurrentDirectory ("NewContinent"); - - // Ok so now create default files -// _WorldEditor->createDefaultFiles (newDirName.c_str()); -// georgesCreateFilesWhenNewContinent (); - - continentProperties ("NewContinent"); - - _Tree->update (_Environnement.ContinentsDir); - SetCurrentDirectory (sCurDir); -} - -// --------------------------------------------------------------------------- -void CMainFrame::continentOpen (const std::string &contName) -{ - setActivePath (contName); - openDir (contName); -} - -// --------------------------------------------------------------------------- -void CMainFrame::continentProperties (const string &contName) -{ - CContinentPropertiesDlg cp(this); - - char sCurDir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, sCurDir); - - string worldDir; - worldDir = _Environnement.ContinentsDir; - - if (!SetCurrentDirectory (worldDir.c_str())) - return; - if (!SetCurrentDirectory (contName.c_str())) - return; - - SContinentCfg cfg; - cfg.load ("continent.cfg"); - - cp.ContinentName = contName.c_str(); - - cp.LandFile = cfg.LandFile.c_str(); - cp.LandDir = cfg.LandDir.c_str(); - cp.DfnDir = cfg.DfnDir.c_str(); - cp.GameElemDir = cfg.GameElemDir.c_str(); - - cp.LandBankFile = cfg.LandBankFile.c_str(); - cp.LandFarBankFile = cfg.LandFarBankFile.c_str(); - cp.LandTileNoiseDir = cfg.LandTileNoiseDir.c_str(); - cp.LandZoneWDir = cfg.LandZoneWDir.c_str(); - cp.OutIGDir = cfg.OutIGDir.c_str(); - - if (cp.DoModal() == IDOK) - { - cfg.LandFile = cp.LandFile; - cfg.LandDir = cp.LandDir; - cfg.DfnDir = cp.DfnDir; - cfg.GameElemDir = cp.GameElemDir; - - cfg.LandBankFile = cp.LandBankFile; - cfg.LandFarBankFile = cp.LandFarBankFile; - cfg.LandTileNoiseDir = cp.LandTileNoiseDir; - cfg.LandZoneWDir = cp.LandZoneWDir; - cfg.OutIGDir = cp.OutIGDir; - - SetCurrentDirectory (worldDir.c_str()); - SetCurrentDirectory (contName.c_str()); - cfg.save ("continent.cfg"); - if (cp.ContinentName != CString(contName.c_str())) - { - // Rename the directory - SetCurrentDirectory (worldDir.c_str()); - if (!MoveFile (contName.c_str(), cp.ContinentName)) - { - MessageBox ("Cannot rename directory", "Error", MB_ICONERROR|MB_OK); - } - } - } - else - { - SetCurrentDirectory (_Environnement.ContinentsDir.c_str()); - deltree ("NewContinent"); - RemoveDirectory("NewContinent"); - } - SetCurrentDirectory (sCurDir); - updateTree (); -} - -// --------------------------------------------------------------------------- -void CMainFrame::continentNewRegion (const string &contName) -{ - char sCurDir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, sCurDir); - - CNameEditDlg dlg(this); - dlg.Title = "New Region"; - dlg.Comment = "Enter the name of the new region"; - dlg.Name = "NewRegion"; - - if (dlg.DoModal() == IDOK) - { - if (dlg.Name != "") - { - string tmpDir = _Environnement.ContinentsDir + contName; - SetCurrentDirectory (tmpDir.c_str()); - CreateDirectory ((LPCSTR)dlg.Name, NULL); - SetCurrentDirectory (dlg.Name); - updateTree (); - } - } - - SetCurrentDirectory (sCurDir); -} - -// --------------------------------------------------------------------------- -// Save all in all modules -void CMainFrame::onContinentSave () -{ - if (_Environnement.WorldEdOpened) - { - if (_WorldEditor) - _WorldEditor->saveOpenedFiles(); - } - if (_Environnement.GeorgesOpened) - { -// if (_Georges) -// _Georges->saveOpenedFiles(); - } - if (_Environnement.LogicEditorOpened) - { -// if (_LogicEditor) -// _LogicEditor->saveOpenedFiles(); - } -} - -// --------------------------------------------------------------------------- -void CMainFrame::onContinentExport () -{ - onContinentSave (); - - char sCurDir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, sCurDir); - string sTmp = _Environnement.ContinentsDir; - SetCurrentDirectory (sTmp.c_str()); - - vector vRegNames; - WIN32_FIND_DATA fd; - HANDLE hFind = FindFirstFile ("*.*", &fd); - while (hFind != INVALID_HANDLE_VALUE) - { - bool bFound = false; - for (uint32 i = 0; i < MAX_SYS_DIR; ++i) - if (stricmp (fd.cFileName, gSysDir[i]) == 0) - { - bFound = true; - break; - } - if (!bFound) - { - if ((fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) != 0) - { - vRegNames.push_back (string(fd.cFileName)); - } - } - if (FindNextFile (hFind, &fd) == 0) - break; - } - FindClose (hFind); - - if (vRegNames.size() == 0) - return; - - CExportDlg dlg (this); - -// _Environnement.ExportOptions.SourceDir = _ActiveContinent; - dlg.setOptions (_Environnement.ExportOptions, vRegNames); - if (dlg.DoModal() == IDOK) - { - if (_ExportCBDlg != NULL) - _ExportCBDlg->DestroyWindow(); - _ExportCBDlg = new CExportCBDlg(); - //Check if new succeeded and we got a valid pointer to a dialog object - if (_Export == NULL) - _Export = new CExport; - if (_ExportCBDlg != NULL) - { - BOOL ret = _ExportCBDlg->Create (IDD_EXPORTCB, this); - if (!ret) //Create failed. - { - delete _ExportCBDlg; - _ExportCBDlg = NULL; - } - _ExportCBDlg->ShowWindow (SW_SHOW); - } - - _Environnement.ExportOptions.PrimFloraDir = _Environnement.ContinentsDir + _Environnement.ExportOptions.PrimFloraDir; - - SetCurrentDirectory (_MasterExeDir.c_str()); - try - { - _Environnement.save (_MasterExeDir+"master.cfg"); - - _Export->newExport (_Environnement.ExportOptions, _ExportCBDlg->getExportCB()); - - } - catch(Exception&e) - { - MessageBox (e.what(), "Error", MB_ICONERROR|MB_OK); - } - - _ExportCBDlg->setFinishedButton (); - while (_ExportCBDlg->getFinished () == false) - { - _ExportCBDlg->pump (); - } - _ExportCBDlg->DestroyWindow (); - } - SetCurrentDirectory (sCurDir); -} - -// --------------------------------------------------------------------------- -/*void CMainFrame::OnContinentDelete () -{ - CChooseDir chooseDir(this); - chooseDir.setPath (_Environnement.ContinentsDir); - if (chooseDir.DoModal() == IDOK) - { - continentDelete (chooseDir.getSelected()); - } -}*/ - -// --------------------------------------------------------------------------- -void CMainFrame::onOptionsTreeLock () -{ - _Environnement.MasterTreeLocked = !_Environnement.MasterTreeLocked; - if (_Environnement.MasterTreeLocked) - { - GetMenu()->CheckMenuItem (ID_OPTIONS_TREELOCK, MF_CHECKED); - _Tree->SetWindowPos (&wndTop, _Environnement.MasterX, _Environnement.MasterY+45, 0, 0, SWP_NOSIZE); - SetFocus(); - } - else - GetMenu()->CheckMenuItem (ID_OPTIONS_TREELOCK, MF_UNCHECKED); -} - -// --------------------------------------------------------------------------- -int CALLBACK BrowseCallbackProc (HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) -{ - switch(uMsg) - { - case BFFM_INITIALIZED: - SendMessage (hwnd, BFFM_SETSELECTION, TRUE, pData); - break; - default: - break; - } - return 0; -} - -// --------------------------------------------------------------------------- -void CMainFrame::onOptionsSetContinentsDir () -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the continents path"; - bi.ulFlags = 0; - bi.lpfn = BrowseCallbackProc; - - char sDir[512]; - strcpy(sDir, _Environnement.ContinentsDir.c_str()); - bi.lParam = (LPARAM)sDir; - - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return; - } - _Environnement.ContinentsDir = str; - if (_Environnement.ContinentsDir[_Environnement.ContinentsDir.size()-1] != '\\') - _Environnement.ContinentsDir += "\\"; - // TREE - _Tree->update (_Environnement.ContinentsDir); - // WORLDEDITOR - if (_WorldEditor != NULL) - _WorldEditor->setDataDir (_Environnement.ContinentsDir.c_str()); - // GEORGES - if (_Georges != NULL) - { - //_Georges->SetRootDirectory (_Environnement.RootDir + "common"); - //_Georges->SetWorkDirectory (_Environnement.RootDir + "common\\dfn"); - georgesCreatePlantName (); - } - // LOGICEDITOR -// if (_LogicEditor != NULL) -// _LogicEditor->setRootDir (_Environnement.RootDir.c_str()); -} - -// --------------------------------------------------------------------------- -void CMainFrame::onOptionsSetDefaultDFNDir () -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the default DFN path"; - bi.ulFlags = 0; - bi.lpfn = BrowseCallbackProc; - - char sDir[512]; - strcpy(sDir, _Environnement.DefaultDFNDir.c_str()); - bi.lParam = (LPARAM)sDir; - - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return; - } - _Environnement.DefaultDFNDir = str; - if (_Environnement.DefaultDFNDir[_Environnement.DefaultDFNDir.size()-1] != '\\') - _Environnement.DefaultDFNDir += "\\"; - - // GEORGES - if (_Georges != NULL) - { - _Georges->SetDirDfnTyp (_Environnement.DefaultDFNDir); - georgesCreatePlantName (); - } - // LOGICEDITOR -// if (_LogicEditor != NULL) -// _LogicEditor->setRootDir (_Environnement.RootDir.c_str()); -} - -// --------------------------------------------------------------------------- -void CMainFrame::onOptionsSetDefaultGameElemDir () -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the default GameElem path"; - bi.ulFlags = 0; - bi.lpfn = BrowseCallbackProc; - - char sDir[512]; - strcpy(sDir, _Environnement.DefaultGameElemDir.c_str()); - bi.lParam = (LPARAM)sDir; - - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return; - } - _Environnement.DefaultGameElemDir = str; - if (_Environnement.DefaultGameElemDir[_Environnement.DefaultGameElemDir.size()-1] != '\\') - _Environnement.DefaultGameElemDir += "\\"; - - // GEORGES - if (_Georges != NULL) - { - _Georges->SetDirPrototype (_Environnement.DefaultGameElemDir); - georgesCreatePlantName (); - } - // LOGICEDITOR -// if (_LogicEditor != NULL) -// _LogicEditor->setRootDir (_Environnement.RootDir.c_str()); -} - -// --------------------------------------------------------------------------- -void CMainFrame::onWindowsWorldEditor () -{ - if (!_Environnement.WorldEdOpened) - openWorldEditor (); - else - closeWorldEditor (); -} - -// --------------------------------------------------------------------------- -void CMainFrame::onWindowsGeorges () -{ - if (!_Environnement.GeorgesOpened) - openGeorges (); - else - closeGeorges (); -} - -// --------------------------------------------------------------------------- -void CMainFrame::onWindowsLogicEditor () -{ - if (!_Environnement.LogicEditorOpened) - openLogicEditor (); - else - closeLogicEditor (); -} - -// --------------------------------------------------------------------------- -void CMainFrame::onWindowsReset () -{ - bool redo = false; - - redo = (_Environnement.WorldEdOpened == true); - closeWorldEditor (); - _Environnement.WorldEdX = 50; - _Environnement.WorldEdY = 50; - _Environnement.WorldEdCX = 600; - _Environnement.WorldEdCY = 400; - if (redo) - openWorldEditor (); - - redo = (_Environnement.GeorgesOpened == true); - closeGeorges (); - _Environnement.GeorgesX = 50; - _Environnement.GeorgesY = 50; - _Environnement.GeorgesCX = 300; - _Environnement.GeorgesCY = 300; - if (redo) - openGeorges (); - - redo = (_Environnement.LogicEditorOpened == true); - closeLogicEditor (); - _Environnement.LogicEditorX = 50; - _Environnement.LogicEditorY = 50; - _Environnement.LogicEditorCX = 300; - _Environnement.LogicEditorCY = 300; - if (redo) - openLogicEditor (); -} - -// --------------------------------------------------------------------------- -void CMainFrame::OnClose () -{ - RECT r; - - // Master Tree saves - _Tree->GetWindowRect (&r); - _Environnement.MasterTreeX = r.left; - _Environnement.MasterTreeY = r.top; - _Environnement.MasterTreeCX = r.right-r.left; - _Environnement.MasterTreeCY = r.bottom-r.top; - - // WorldEditor saves - if (_Environnement.WorldEdOpened) - { - closeWorldEditor (); - _Environnement.WorldEdOpened = true; - } - - // Georges saves - if (_Environnement.GeorgesOpened) - { - closeGeorges (); - _Environnement.GeorgesOpened = true; - } - - // LogicEditor saves - if (_Environnement.LogicEditorOpened) - { - closeLogicEditor (); - _Environnement.LogicEditorOpened = true; - } - - // Save the environnement - SetCurrentDirectory (_MasterExeDir.c_str()); - try - { - _Environnement.save (_MasterExeDir+"master.cfg"); - } - catch(Exception&e) - { - MessageBox (e.what(), "Error", MB_ICONERROR|MB_OK); - } - - releaseAllInterfaces (); - - DestroyWindow(); -} - -///////////////////////////////////////////////////////////////////////////// -// CMainFrame diagnostics - -#ifdef _DEBUG -void CMainFrame::AssertValid() const -{ - CFrameWnd::AssertValid(); -} - -void CMainFrame::Dump(CDumpContext& dc) const -{ - CFrameWnd::Dump(dc); -} - -#endif //_DEBUG - -///////////////////////////////////////////////////////////////////////////// -// CMainFrame message handlers - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// MainFrm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" +#include "master.h" + +#include "MainFrm.h" +//#include "RegionPropertiesDlg.h" +//#include "NewGeorgesFormDlg.h" +//#include "PrimNameDlg.h" +#include "NameEditDlg.h" +#include "ChooseTag.h" +#include "ChooseDir.h" +#include "exportdlg.h" +#include "exportcbdlg.h" +#include "continentcfg.h" +#include "continentPropertiesDlg.h" + +#include "../georges_dll/georges_interface.h" +#include "../logic_editor_dll/logic_editor_interface.h" + +#include "nel/misc/file.h" +#include "nel/misc/stream.h" + +using namespace NLMISC; +using namespace std; + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#ifdef NL_NEW + #undef new +#endif + +///////////////////////////////////////////////////////////////////////////// + +// Do not parse following directories +char *gSysDir[MAX_SYS_DIR] = +{ + ".", + "..", + "ZoneBitmaps", + "ZoneLigos", + "dfn", + "tmp", + "cvs" +}; + +// Do not display files with those extensions +#define MAX_INVALID_EXT 1 +char *gInvalidExt[MAX_INVALID_EXT] = +{ + ".log" +}; + + +///////////////////////////////////////////////////////////////////////////// + +// --------------------------------------------------------------------------- +SEnvironnement::SEnvironnement() +{ + MasterX = 0; + MasterY = 0; + MasterTreeX = 0; + MasterTreeY = 0; + MasterTreeCX = 100; + MasterTreeCY = 100; + MasterTreeLocked = true; + + char tmp[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, tmp); + ContinentsDir = tmp; + ContinentsDir += "\\Continents\\"; + + WorldEdOpened = false; + WorldEdX = 50; + WorldEdY = 50; + WorldEdCX = 600; + WorldEdCY = 400; + + GeorgesOpened = false; + GeorgesX = 50; + GeorgesY = 50; + GeorgesCX = 300; + GeorgesCY = 300; + + LogicEditorOpened = false; + LogicEditorX = 50; + LogicEditorY = 50; + LogicEditorCX = 300; + LogicEditorCY = 300; +} + +// --------------------------------------------------------------------------- +bool SEnvironnement::load (const std::string &filename) +{ + if (!openRead(filename)) + return false; + // Master + MasterX = getInt ("MASTA_PosX"); + MasterY = getInt ("MASTA_PosY"); + MasterTreeX = getInt ("MASTA_TreePosX"); + MasterTreeY = getInt ("MASTA_TreePosY"); + MasterTreeCX = getInt ("MASTA_TreeSizeX"); + MasterTreeCY = getInt ("MASTA_TreeSizeY"); + MasterTreeLocked = getBool ("MASTA_TreeLocked"); + ContinentsDir = getStr ("MASTA_ContinentsDir"); + DefaultDFNDir = getStr ("MASTA_DefaultDFNDir"); + DefaultGameElemDir = getStr ("MASTA_DefaultGameElemDir"); + + // WorldEditor + WorldEdOpened = getBool ("WE_Opened"); + WorldEdX = getInt ("WE_PosX"); + WorldEdY = getInt ("WE_PosY"); + WorldEdCX = getInt ("WE_SizeX"); + WorldEdCY = getInt ("WE_SizeY"); + + // Georges + GeorgesOpened = getBool ("GG_Opened"); + GeorgesX = getInt ("GG_PosX"); + GeorgesY = getInt ("GG_PosY"); + GeorgesCX = getInt ("GG_SizeX"); + GeorgesCY = getInt ("GG_SizeY"); + + // LogicEditor + LogicEditorOpened = getBool ("LE_Opened"); + LogicEditorX = getInt ("LE_PosX"); + LogicEditorY = getInt ("LE_PosY"); + LogicEditorCX = getInt ("LE_SizeX"); + LogicEditorCY = getInt ("LE_SizeY"); + + // Export options + ExportOptions.loadcf (*cf); + close (); + return true; +} + +// --------------------------------------------------------------------------- +bool SEnvironnement::save (const std::string &filename) +{ + if (!openWrite(filename)) + return false; + + putCommentLine ("------"); + putCommentLine ("Master"); + putCommentLine ("------"); + putInt ("MASTA_PosX", MasterX); + putInt ("MASTA_PosY", MasterY); + putInt ("MASTA_TreePosX", MasterTreeX); + putInt ("MASTA_TreePosY", MasterTreeY); + putInt ("MASTA_TreeSizeX", MasterTreeCX); + putInt ("MASTA_TreeSizeY", MasterTreeCY); + putBool ("MASTA_TreeLocked", MasterTreeLocked); + putStr ("MASTA_ContinentsDir", ContinentsDir); + putStr ("MASTA_DefaultDFNDir", DefaultDFNDir); + putStr ("MASTA_DefaultGameElemDir",DefaultGameElemDir); + + putCommentLine ("-----------"); + putCommentLine ("WorldEditor"); + putCommentLine ("-----------"); + putBool ("WE_Opened", WorldEdOpened); + putInt ("WE_PosX", WorldEdX); + putInt ("WE_PosY", WorldEdY); + putInt ("WE_SizeX", WorldEdCX); + putInt ("WE_SizeY", WorldEdCY); + + putCommentLine ("-------"); + putCommentLine ("Georges"); + putCommentLine ("-------"); + putBool ("GG_Opened", GeorgesOpened); + putInt ("GG_PosX", GeorgesX); + putInt ("GG_PosY", GeorgesY); + putInt ("GG_SizeX", GeorgesCX); + putInt ("GG_SizeY", GeorgesCY); + + putCommentLine ("-----------"); + putCommentLine ("LogicEditor"); + putCommentLine ("-----------"); + putBool ("LE_Opened", LogicEditorOpened); + putInt ("LE_PosX", LogicEditorX); + putInt ("LE_PosY", LogicEditorY); + putInt ("LE_SizeX", LogicEditorCX); + putInt ("LE_SizeY", LogicEditorCY); + + // Export options + ExportOptions.save (f); + close(); + return true; +} + + +///////////////////////////////////////////////////////////////////////////// +// CMasterCB +///////////////////////////////////////////////////////////////////////////// + +// --------------------------------------------------------------------------- +CMasterCB::CMasterCB () +{ + _MainFrame = NULL; +} + +// --------------------------------------------------------------------------- +void CMasterCB::setMainFrame (CMainFrame*pMF) +{ + _MainFrame = pMF; +} + +// --------------------------------------------------------------------------- +vector &CMasterCB::getAllPrimZoneNames () +{ + return _PrimZoneList; +} + +// --------------------------------------------------------------------------- +void CMasterCB::setAllPrimZoneNames (vector &primZoneList) +{ + _PrimZoneList = primZoneList; + //_MainFrame->georgesUpdatePatatoid(); +} + +// --------------------------------------------------------------------------- +void CMasterCB::multiTransfert (const std::vector &vText, bool append) +{ + _GroupPrimList = vText; + _MainFrame->georgesPutGroupText (_GroupPrimList, append); +} + +// --------------------------------------------------------------------------- +void CMasterCB::transfert (const string &sText) +{ + _Text = sText; + _MainFrame->georgesPutText (_Text); +} + +// --------------------------------------------------------------------------- +void CMasterCB::lineUp () +{ + _MainFrame->georgesLineUp (); +} + +// --------------------------------------------------------------------------- +void CMasterCB::lineDown () +{ + _MainFrame->georgesLineDown (); +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame +///////////////////////////////////////////////////////////////////////////// + +//IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) + //{{AFX_MSG_MAP(CMainFrame) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code ! + + ON_COMMAND(ID_CONTINENT_SAVE, onContinentSave) + ON_COMMAND(ID_CONTINENT_EXPORT, onContinentExport) + + //ON_COMMAND(ID_CONTINENT_DELETE, OnContinentDelete) + + ON_COMMAND(ID_OPTIONS_TREELOCK, onOptionsTreeLock) + + ON_COMMAND(ID_OPTIONS_SETCONTINENTSDIR, onOptionsSetContinentsDir) + ON_COMMAND(ID_OPTIONS_SETDEFAULTDFNDIR, onOptionsSetDefaultDFNDir) + ON_COMMAND(ID_OPTIONS_SETDEFAULTGAMEELEMDIR, onOptionsSetDefaultGameElemDir) + + ON_COMMAND(ID_WINDOWS_WORLDEDITOR, onWindowsWorldEditor) + ON_COMMAND(ID_WINDOWS_GEORGES, onWindowsGeorges) + ON_COMMAND(ID_WINDOWS_LOGICEDITOR, onWindowsLogicEditor) + ON_COMMAND(ID_WINDOWS_RESET, onWindowsReset) + + ON_WM_CREATE() + ON_WM_ERASEBKGND() + ON_WM_SIZE() + ON_WM_MOVE() + ON_WM_CLOSE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame construction/destruction + +// --------------------------------------------------------------------------- +CMainFrame::CMainFrame() +{ + _WorldEditor = NULL; + _Georges = NULL; + _LogicEditor = NULL; + _Tree = NULL; + _Export = NULL; + _ExportCBDlg = NULL; +} + +// --------------------------------------------------------------------------- +CMainFrame::~CMainFrame() +{ + delete _Export; +} + +// --------------------------------------------------------------------------- +// Used by getAllInterfaces method to retrieve all DLLs and tools Interfaces + +typedef IWorldEditor* (*IWORLDEDITOR_GETINTERFACE)(int version); +const char *IWORLDEDITOR_GETINTERFACE_NAME = "IWorldEditorGetInterface"; +typedef void (*IWORLDEDITOR_RELINTERFACE)(IWorldEditor*pWE); +const char *IWORLDEDITOR_RELINTERFACE_NAME = "IWorldEditorReleaseInterface"; + +typedef IGeorges* (*IGEORGES_GETINTERFACE)(int version); +const char *IGEORGES_GETINTERFACE_NAME = "IGeorgesGetInterface"; +typedef void (*IGEORGES_RELINTERFACE)(IGeorges *pGeorges); +const char *IGEORGES_RELINTERFACE_NAME = "IGeorgesReleaseInterface"; + +typedef ILogicEditor* (*ILOGICEDITOR_GETINTERFACE)(int version); +const char *ILOGICEDITOR_GETINTERFACE_NAME = "ILogicEditorGetInterface"; +typedef void (*ILOGICEDITOR_RELINTERFACE)(ILogicEditor *pLogicEditor); +const char *ILOGICEDITOR_RELINTERFACE_NAME = "ILogicEditorReleaseInterface"; + +// --------------------------------------------------------------------------- +void CMainFrame::getAllInterfaces () +{ + SetCurrentDirectory (_MasterExeDir.c_str()); + + // Get WorldEditor Interface + if (_WorldEditor == NULL) + { + IWORLDEDITOR_GETINTERFACE IWEGetInterface = NULL; + + #if defined NL_RELEASE_DEBUG + _WorldEditorModule = AfxLoadLibrary ("WorldEditor_rd.dll"); + #elif defined NL_DEBUG_FAST + _WorldEditorModule = AfxLoadLibrary ("WorldEditor_df.dll"); + #elif defined _DEBUG + _WorldEditorModule = AfxLoadLibrary ("WorldEditor_debug.dll"); + #elif defined NDEBUG + _WorldEditorModule = AfxLoadLibrary ("WorldEditor.dll"); + #endif + if (_WorldEditorModule != NULL) + { + IWEGetInterface = (IWORLDEDITOR_GETINTERFACE)::GetProcAddress (_WorldEditorModule, IWORLDEDITOR_GETINTERFACE_NAME); + if (IWEGetInterface != NULL) + _WorldEditor = IWEGetInterface (WORLDEDITOR_VERSION); + } + else + { + MessageBox("WorldEditor dll not Loaded", "Warning"); + } + } + + // Get Georges Interface + if (_Georges == NULL) + { + IGEORGES_GETINTERFACE IGGetInterface = NULL; + + #if defined NL_RELEASE_DEBUG + _GeorgesModule = AfxLoadLibrary ("Georges_dll_rd.dll"); + #elif defined NL_DEBUG_FAST + _GeorgesModule = AfxLoadLibrary ("Georges_dll_debug_fast.dll"); + #elif defined _DEBUG + _GeorgesModule = AfxLoadLibrary ("Georges_dll_debug.dll"); + #elif defined NDEBUG + _GeorgesModule = AfxLoadLibrary ("Georges_dll.dll"); + #endif + if (_GeorgesModule != NULL) + { + IGGetInterface = (IGEORGES_GETINTERFACE)::GetProcAddress (_GeorgesModule, IGEORGES_GETINTERFACE_NAME); + if (IGGetInterface != NULL) + _Georges = IGGetInterface (GEORGES_VERSION); + } + else + { + MessageBox("Georges dll not Loaded", "Warning"); + } + } + + // Get LogicEditor Interface + if (_LogicEditor == NULL) + { + ILOGICEDITOR_GETINTERFACE ILEGetInterface = NULL; + + #if defined NL_RELEASE_DEBUG + _LogicEditorModule = AfxLoadLibrary ("Logic_Editor_rd.dll"); + #elif defined NL_DEBUG_FAST + _LogicEditorModule = AfxLoadLibrary ("Logic_Editor_df.dll"); + #elif defined _DEBUG + _LogicEditorModule = AfxLoadLibrary ("Logic_Editor_debug.dll"); + #elif defined NDEBUG + _LogicEditorModule = AfxLoadLibrary ("Logic_Editor.dll"); + #endif + if (_LogicEditorModule != NULL) + { + ILEGetInterface = (ILOGICEDITOR_GETINTERFACE)::GetProcAddress (_LogicEditorModule, ILOGICEDITOR_GETINTERFACE_NAME); + if (ILEGetInterface != NULL) + _LogicEditor = ILEGetInterface (LOGIC_EDITOR_VERSION); + } + else + { + MessageBox("LogicEditor dll not Loaded", "Warning"); + } + } +} + +// --------------------------------------------------------------------------- +void CMainFrame::releaseAllInterfaces() +{ + // Release the WorldEditor interface + if (_WorldEditor != NULL) + { + IWORLDEDITOR_RELINTERFACE IWERelInterface = NULL; + IWERelInterface = (IWORLDEDITOR_RELINTERFACE)::GetProcAddress (_WorldEditorModule, IWORLDEDITOR_RELINTERFACE_NAME); + IWERelInterface (_WorldEditor); + } + + // Release the Georges interface + if (_Georges != NULL) + { + IGEORGES_RELINTERFACE IGRelInterface = NULL; + IGRelInterface = (IGEORGES_RELINTERFACE)::GetProcAddress (_GeorgesModule, IGEORGES_RELINTERFACE_NAME); + IGRelInterface (_Georges); + } + + // Release the LogicEditor interface + if (_LogicEditor != NULL) + { + ILOGICEDITOR_RELINTERFACE ILERelInterface = NULL; + ILERelInterface = (ILOGICEDITOR_RELINTERFACE)::GetProcAddress (_LogicEditorModule, ILOGICEDITOR_RELINTERFACE_NAME); + ILERelInterface (_LogicEditor); + } +} + +// --------------------------------------------------------------------------- +void CMainFrame::openFile (const string &fname) +{ + char curdir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, curdir); + + string sFullName; + sFullName = _Environnement.ContinentsDir; + + sFullName += fname; + + int size = fname.size(); + + if ((size >= 13) && (stricmp(&fname[size-13],"continent.cfg") == 0)) + { + openContinentCfgFile (sFullName.c_str()); + } + else if ((stricmp(&fname[size-5],".prim") == 0) || (stricmp(&fname[size-5],".land") == 0)) + { + openWorldEditor (); + openWorldEditorFile (sFullName.c_str()); + } + else if (stricmp(&fname[size-6],".logic") == 0) + { + openLogicEditor (); + openLogicEditorFile (sFullName.c_str()); + } + else + { + openGeorges (); + openGeorgesFile (sFullName.c_str()); + } + + SetCurrentDirectory (curdir); +} + +// --------------------------------------------------------------------------- +void CMainFrame::openDir (const string &fname) +{ + if (_ActivePath == "") return; + + char curdir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, curdir); + + string sBaseName; + sBaseName = _Environnement.ContinentsDir; + + openDirParse (sBaseName, fname); + + SetCurrentDirectory (curdir); +} + +// --------------------------------------------------------------------------- +void CMainFrame::openDirParse (const std::string &sBaseNameDir, const std::string &sRelativeNameDir) +{ + WIN32_FIND_DATA findData; + HANDLE hFind; + + char sCurDir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, sCurDir); + + string sFullNamedDir = sBaseNameDir + sRelativeNameDir; + if (!SetCurrentDirectory (sFullNamedDir.c_str())) + { + SetCurrentDirectory (sCurDir); + return; + } + + hFind = FindFirstFile ("*.*", &findData); + while (hFind != INVALID_HANDLE_VALUE) + { + if (GetFileAttributes(findData.cFileName)&FILE_ATTRIBUTE_DIRECTORY) + { + // Look if the name is a system directory + bool bFound = false; + for (uint32 i = 0; i < MAX_SYS_DIR; ++i) + if (stricmp (findData.cFileName, gSysDir[i]) == 0) + { + bFound = true; + break; + } + if (!bFound) // No, ok lets recurse it + { + string newPath = sRelativeNameDir + string("\\") + string(findData.cFileName); + openDirParse (sBaseNameDir, newPath); + } + } + else + { + // Check for invalid extension + bool bFound = false; + for (uint32 j = 0; j < MAX_INVALID_EXT; ++j) + if (strlen(findData.cFileName) > strlen(gInvalidExt[j])) + if (stricmp(&findData.cFileName[strlen(findData.cFileName)-strlen(gInvalidExt[j])], gInvalidExt[j]) == 0) + { + bFound = true; + break; + } + // If the extension is an invalid one -> Do not open the file + if (!bFound) + { + string fileName = sRelativeNameDir + "\\" + findData.cFileName; + openFile (fileName.c_str()); + } + } + if (FindNextFile (hFind, &findData) == 0) + break; + } + FindClose (hFind); + + SetCurrentDirectory (sCurDir); +} + +// --------------------------------------------------------------------------- +void CMainFrame::openContinentCfgFile (const string &filename) +{ + SContinentCfg cfg; + cfg.load (filename); + _WorldEditor->setDataDir (cfg.LandDir.c_str()); + openWorldEditor (); + openWorldEditorFile (cfg.LandFile.c_str()); +} + +// --------------------------------------------------------------------------- +void CMainFrame::openWorldEditor() +{ + if (_Environnement.WorldEdOpened) + return; + _Environnement.WorldEdOpened = true; + if (_WorldEditor != NULL) + _WorldEditor->initUILight (_Environnement.WorldEdX, _Environnement.WorldEdY, + _Environnement.WorldEdCX, _Environnement.WorldEdCY); + GetMenu()->CheckMenuItem (ID_WINDOWS_WORLDEDITOR, MF_CHECKED); +} + +// --------------------------------------------------------------------------- +void CMainFrame::openWorldEditorFile (const string &fileName) +{ + _WorldEditor->loadFile (fileName.c_str()); +} + +// --------------------------------------------------------------------------- +void CMainFrame::closeWorldEditor() +{ + if (_WorldEditor == NULL) return; + if (!_Environnement.WorldEdOpened) return; + + //onContinentSave (); + _Environnement.WorldEdOpened = false; + RECT r; + CFrameWnd *pFW = (CFrameWnd*)_WorldEditor->getMainFrame(); + pFW->GetWindowRect(&r); + WINDOWPLACEMENT wp; + pFW->GetWindowPlacement (&wp); + if (wp.showCmd == SW_SHOWNORMAL) + { + _Environnement.WorldEdY = r.top; + _Environnement.WorldEdX = r.left; + _Environnement.WorldEdCY = r.bottom - r.top; + _Environnement.WorldEdCX = r.right - r.left; + } + _WorldEditor->releaseUI (); + GetMenu()->CheckMenuItem (ID_WINDOWS_WORLDEDITOR, MF_UNCHECKED); +} + +// --------------------------------------------------------------------------- +void CMainFrame::openGeorges () +{ + if (_Georges == NULL) return; + if (_Environnement.GeorgesOpened) + return; + _Environnement.GeorgesOpened = true; + if (_Georges != NULL) + { + _Georges->initUILight (SW_SHOW, _Environnement.GeorgesX, _Environnement.GeorgesY, + _Environnement.GeorgesCX, _Environnement.GeorgesCY); + } + GetMenu()->CheckMenuItem (ID_WINDOWS_GEORGES, MF_CHECKED); +} + +// --------------------------------------------------------------------------- +void CMainFrame::openGeorgesFile (const string &fileName) +{ + if (_Georges == NULL) return; + georgesSetPathesFromActive (); + _Georges->LoadDocument (fileName); +} + +// --------------------------------------------------------------------------- +void CMainFrame::closeGeorges () +{ + if (_Georges == NULL) return; + if (!_Environnement.GeorgesOpened) return; + + _Environnement.GeorgesOpened = false; + RECT r; + CFrameWnd *pFW = (CFrameWnd*)_Georges->getMainFrame(); + pFW->GetWindowRect(&r); + WINDOWPLACEMENT wp; + pFW->GetWindowPlacement (&wp); + if (wp.showCmd == SW_SHOWNORMAL) + { + _Environnement.GeorgesY = r.top; + _Environnement.GeorgesX = r.left; + _Environnement.GeorgesCY = r.bottom - r.top; + _Environnement.GeorgesCX = r.right - r.left; + } + _Georges->releaseUI (); + GetMenu()->CheckMenuItem (ID_WINDOWS_GEORGES, MF_UNCHECKED); +} + +// --------------------------------------------------------------------------- +void CMainFrame::georgesSetPathesFromActive () +{ + if (_Georges == NULL) return; + if (_ActivePath == "") + { + string sDir; + sDir = _Environnement.ContinentsDir; + _Georges->SetDirLevel (sDir); + + _Georges->SetDirDfnTyp (_Environnement.DefaultDFNDir); + _Georges->SetDirPrototype (_Environnement.DefaultGameElemDir); + } + else + { + string sDir; + + int i = 0; + if (_ActivePath[i] == '\\') ++i; + for (; i < (int)_ActivePath.size(); ++i) + { + if (_ActivePath[i] == '\\') break; + sDir += _ActivePath[i]; + } + + sDir = _Environnement.ContinentsDir + sDir + "\\"; + + _Georges->SetDirLevel (sDir); + + SContinentCfg cfg; + string sTmp = sDir + "continent.cfg"; + cfg.load (sTmp.c_str()); + _Georges->SetDirDfnTyp (cfg.DfnDir); + _Georges->SetDirPrototype (cfg.GameElemDir); + } +} + +// --------------------------------------------------------------------------- +/* +void CMainFrame::georgesUpdatePatatoid () +{ + if (_Georges == NULL) return; + if ((_ActiveWorld == "") || (_ActiveContinent == "") || (_ActiveRegion == "")) return; + + string sCurDir; + if (_ActiveWorld == "Continents") + sCurDir = _Environnement.ContinentsDir; + else if (_ActiveWorld == "Trash") + sCurDir = _Environnement.TrashDir; + else if (_ActiveWorld == "Backup") + sCurDir = _Environnement.BackupDir; + sCurDir += _ActiveContinent + "\\" + _ActiveRegion + "\\"; + _Georges->SetDirLevel (sCurDir); + + if (_ActiveContinent != "") + _Georges->SetTypPredef (sCurDir + "tmp\\patat_name.typ", _MasterCB.getAllPrimZoneNames()); +} +*/ + +// --------------------------------------------------------------------------- +void CMainFrame::georgesPutGroupText (const std::vector &vText, bool append) +{ + if (_Georges == NULL) return; + _Georges->PutGroupText (vText, append); +} + +// --------------------------------------------------------------------------- +void CMainFrame::georgesPutText (const std::string &sText) +{ + if (_Georges == NULL) return; + _Georges->PutText (sText); +} + +// --------------------------------------------------------------------------- +void CMainFrame::georgesLineUp () +{ + if (_Georges == NULL) return; + _Georges->LineUp (); +} + +// --------------------------------------------------------------------------- +void CMainFrame::georgesLineDown () +{ + if (_Georges == NULL) return; + _Georges->LineDown (); +} + +// --------------------------------------------------------------------------- +/* +void CMainFrame::georgesCreateFilesWhenNewRegion () +{ + // When we arrive in this function the current directory is the new Continent being created + if (_Georges == NULL) + return; + + CreateDirectory ("tmp", NULL); + char curdir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, curdir); + string fullname = string(curdir) + "\\tmp\\patat_name.typ"; + vector< pair< string, string > > lpsx; + vector< pair< string, string > > lpsx2; + lpsx.push_back (make_pair(string("PatatFrite"), string("PatatFrite"))); + lpsx.push_back (make_pair(string("PatatVapeur"), string("PatatVapeur"))); + _Georges->MakeTyp (fullname, "String", "PATAT", "true", "", "", "PatatFrite", &lpsx, &lpsx2); +} +*/ + +// --------------------------------------------------------------------------- +void CMainFrame::georgesCreatePlantName () +{ + if (_Georges == NULL) return; + WIN32_FIND_DATA fdTmp; + char curdir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, curdir); + + try + { + string plantname = _Environnement.DefaultDFNDir; + if (!SetCurrentDirectory(plantname.c_str())) + return; + + plantname += "tmp\\plant_name.typ"; + + // If plantname file do not already exists + HANDLE hFind = FindFirstFile(plantname.c_str(), &fdTmp); + if (hFind != INVALID_HANDLE_VALUE) + { + FindClose (hFind); + if (!DeleteFile (plantname.c_str())) + { + MessageBox (plantname.c_str(), "Cannot overwrite"); + return; + } + } + + vector< pair< string, string > > lpsx; + vector< pair< string, string > > lpsx2; + lpsx.push_back (std::make_pair(string("xxx.plant"), string("xxx.plant"))); + lpsx.push_back (std::make_pair(string("yyy.plant"), string("yyy.plant"))); + _Georges->MakeTyp (plantname, String, FileBrowser, "", "", "xxx.plant", &lpsx); + + // Parse the plant directory and add all these predef + string plantdir = _Environnement.DefaultGameElemDir; + if (!SetCurrentDirectory (plantdir.c_str())) + return; + + vector allPlants; + CExport::getAllFiles (".plant", allPlants); + + for (uint32 i = 0; i < allPlants.size(); ++i) + { + char fName[_MAX_FNAME]; + char ext[_MAX_FNAME]; + ::_splitpath((const char*)allPlants[i].c_str(), NULL, NULL, fName, ext); + allPlants[i] = string(fName) + string(ext); + } + + // todo Hulud : handle this another way.. + // _Georges->SetTypPredef ("plant_name.typ", allPlants); + } + catch(NLMISC::Exception &e) + { + MessageBox (e.what(), "Warning", MB_ICONERROR|MB_OK); + } + SetCurrentDirectory (curdir); +} + +// --------------------------------------------------------------------------- +void CMainFrame::openLogicEditor () +{ + if (_Environnement.LogicEditorOpened) + return; + _Environnement.LogicEditorOpened = true; + if (_LogicEditor != NULL) + _LogicEditor->initUILight (_Environnement.LogicEditorX, _Environnement.LogicEditorY, + _Environnement.LogicEditorCX, _Environnement.LogicEditorCY); + GetMenu()->CheckMenuItem (ID_WINDOWS_LOGICEDITOR, MF_CHECKED); +} + +// --------------------------------------------------------------------------- +void CMainFrame::openLogicEditorFile (const string &fileName) +{ + _LogicEditor->loadFile (fileName.c_str()); +} + +// --------------------------------------------------------------------------- +void CMainFrame::closeLogicEditor () +{ + if (!_Environnement.LogicEditorOpened) + return; + _Environnement.LogicEditorOpened = false; + RECT r; + CFrameWnd *pFW = (CFrameWnd*)_LogicEditor->getMainFrame(); + pFW->GetWindowRect(&r); + WINDOWPLACEMENT wp; + pFW->GetWindowPlacement (&wp); + if (wp.showCmd == SW_SHOWNORMAL) + { + _Environnement.LogicEditorY = r.top; + _Environnement.LogicEditorX = r.left; + _Environnement.LogicEditorCY = r.bottom - r.top; + _Environnement.LogicEditorCX = r.right - r.left; + } + _LogicEditor->releaseUI (); + GetMenu()->CheckMenuItem (ID_WINDOWS_LOGICEDITOR, MF_UNCHECKED); +} + +// --------------------------------------------------------------------------- +void CMainFrame::updateTree() +{ + _Tree->update (_Environnement.ContinentsDir); +} + +// --------------------------------------------------------------------------- +void CMainFrame::deltree (const std::string &dirName) +{ + // Get all directory object + vector toremovelist; + WIN32_FIND_DATA findData; + HANDLE hFind; + char sCurDir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, sCurDir); + if (!SetCurrentDirectory (dirName.c_str())) + return; + hFind = FindFirstFile ("*.*", &findData); + while (hFind != INVALID_HANDLE_VALUE) + { + // Look if the name is a system directory + if ((stricmp (findData.cFileName, ".") != 0) && (stricmp (findData.cFileName, "..") != 0)) + { + if (findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) + { + // If this is a directory deltree and delete the directory + deltree (findData.cFileName); + toremovelist.push_back (findData.cFileName); + } + else + { + // If this is a file delete + if (!DeleteFile (findData.cFileName)) + displayLastErrorDialog (); + } + } + if (FindNextFile (hFind, &findData) == 0) + break; + } + FindClose (hFind); + SetCurrentDirectory (dirName.c_str()); + for (uint32 i = 0; i < toremovelist.size(); ++i) + { + if (!RemoveDirectory (toremovelist[i].c_str())) + displayLastErrorDialog (); + } + SetCurrentDirectory (sCurDir); +} + +// --------------------------------------------------------------------------- +void CMainFrame::displayLastErrorDialog () +{ + LPVOID lpMsgBuf; + FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL); + // Display the string. + MessageBox ((LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONERROR); + // Free the buffer. + LocalFree (lpMsgBuf); +} + +// --------------------------------------------------------------------------- +/*int getMaxTag(const std::string &dirName, const std::string &tagName) +{ + WIN32_FIND_DATA findData; + HANDLE hFind; + char sCurDir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, sCurDir); + SetCurrentDirectory (dirName.c_str()); + string tmp = tagName + "*"; + hFind = FindFirstFile (tmp.c_str(), &findData); + int ret = 0; + while (hFind != INVALID_HANDLE_VALUE) + { + int nb = (findData.cFileName[tagName.size()+0]-'0')*100 + + (findData.cFileName[tagName.size()+1]-'0')*10 + + (findData.cFileName[tagName.size()+2]-'0')*1; + if (nb > ret) + ret = nb; + if (FindNextFile (hFind, &findData) == 0) + break; + } + FindClose (hFind); + SetCurrentDirectory (sCurDir); + return ret; +}*/ + +// --------------------------------------------------------------------------- +void CMainFrame::copytree (const string &srcDir, const string &dstDir) +{ + WIN32_FIND_DATA findData; + HANDLE hFind; + string tmp = srcDir + "\\*"; + hFind = FindFirstFile (tmp.c_str(), &findData); + while (hFind != INVALID_HANDLE_VALUE) + { + bool bFound = false; + for (uint32 i = 0; i < MAX_SYS_DIR; ++i) + if (stricmp (findData.cFileName, gSysDir[i]) == 0) + { + bFound = true; + break; + } + if (!bFound) + { + if (findData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) + { + string newDirSrc = srcDir + "\\" + findData.cFileName; + string newDirDst = dstDir + "\\" + findData.cFileName; + if (!CreateDirectory(newDirDst.c_str(), NULL)) + displayLastErrorDialog (); + copytree (newDirSrc, newDirDst); + } + else + { + string fnameSrc = srcDir + "\\" + findData.cFileName; + string fnameDst = dstDir + "\\" + findData.cFileName; + if (!CopyFile(fnameSrc.c_str(), fnameDst.c_str(), false)) + displayLastErrorDialog (); + } + } + + if (FindNextFile (hFind, &findData) == 0) + break; + } + FindClose (hFind); +} + + +// --------------------------------------------------------------------------- +void CMainFrame::continentDelete (const string &contName) +{ + string srcDir = _Environnement.ContinentsDir + contName; + deltree (srcDir); + RemoveDirectory (srcDir.c_str()); + updateTree (); +} + +// --------------------------------------------------------------------------- +void CMainFrame::regionOpen (const string &path) +{ + setActivePath (path); + openDir (path); +} + +// --------------------------------------------------------------------------- +void CMainFrame::regionRename (const string &path) +{ + if (path == "") return; + int pos = path.rfind('\\'); + if (pos == string::npos) return; + string smallpath; + int i; + for (i = 0; i <= pos; ++i) + smallpath += path[i]; + string dirname; + for (; i < (int)path.size(); ++i) + dirname += path[i]; + smallpath = _Environnement.ContinentsDir + smallpath; + char curdir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, curdir); + SetCurrentDirectory (smallpath.c_str()); + + CNameEditDlg dlg; + dlg.Title = "Change the directory name"; + dlg.Comment = "Enter the new directory name"; + dlg.Name = dirname.c_str(); + + if (dlg.DoModal() == IDOK) + { + if (!MoveFile (dirname.c_str(), dlg.Name)) + displayLastErrorDialog (); + } + + SetCurrentDirectory (curdir); +} + +// --------------------------------------------------------------------------- +void CMainFrame::regionNewPrim (const string &path) +{ + if (path == "") return; + if (_WorldEditor == NULL) return; + + // Ask the name to the user + CNameEditDlg dlg; + dlg.Title = "New Prim File Name"; + dlg.Comment = "Enter the name of the new .PRIM file"; + dlg.Name = "NewPrim"; + if (dlg.DoModal() == IDOK) + { + string primname = dlg.Name; + if (primname != "") + { + string sTmp = _Environnement.ContinentsDir + path + "\\" + primname; + _WorldEditor->createEmptyPrimFile (sTmp.c_str()); + updateTree (); + } + } +} + +// --------------------------------------------------------------------------- +void CMainFrame::regionNewGeorges (const string &path) +{ + if (path == "") + return; + if (_Georges == NULL) + return; + + // Ask the user the .dfn to use + CNameEditDlg dlg; + dlg.Title = "New Form File Name"; + dlg.Comment = "Enter the name of the new Form file"; + dlg.Name = "NewForm"; + if (dlg.DoModal() == IDOK) + { + char curdir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, curdir); + + // setActivePath (path); + + // \todo load from the continent.cfg + string newDir = _Georges->GetDirDfnTyp (); + + CFileDialog fd (true, "*.dfn", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, + "Definition (*.dfn)|*.dfn", this); + fd.m_ofn.lpstrInitialDir = newDir.c_str(); + if (fd.DoModal() == IDOK) + { + string sTmp = _Environnement.ContinentsDir + path + "\\" + (LPCSTR)dlg.Name; + _Georges->createInstanceFile (sTmp, (LPCSTR)fd.GetFileName()); + } + + SetCurrentDirectory (curdir); + updateTree (); + } +} + +// --------------------------------------------------------------------------- +void CMainFrame::regionNewSubRegion (const std::string &path) +{ + char sCurDir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, sCurDir); + + CNameEditDlg dlg(this); + dlg.Title = "New Sub Region"; + dlg.Comment = "Enter the name of the new sub region"; + dlg.Name = "NewSubRegion"; + + if (dlg.DoModal() == IDOK) + { + if (dlg.Name != "") + { + string tmpDir = _Environnement.ContinentsDir + path; + SetCurrentDirectory (tmpDir.c_str()); + CreateDirectory ((LPCSTR)dlg.Name, NULL); + SetCurrentDirectory (dlg.Name); + updateTree (); + } + } + + SetCurrentDirectory (sCurDir); +} + +// --------------------------------------------------------------------------- +void CMainFrame::regionDelete (const std::string &path) +{ + string srcDir = _Environnement.ContinentsDir + path; + deltree (srcDir); + if (!RemoveDirectory (srcDir.c_str())) + displayLastErrorDialog (); + updateTree (); +} + +// --------------------------------------------------------------------------- +void CMainFrame::fileOpen (const std::string &sFileFullName) +{ + openFile (sFileFullName); +} + +// --------------------------------------------------------------------------- +void CMainFrame::fileRename (const std::string &sFileFullName) +{ + if (sFileFullName == "") return; + int pos = sFileFullName.rfind('\\'); + if (pos == string::npos) return; + string smallpath; + int i; + for (i = 0; i <= pos; ++i) + smallpath += sFileFullName[i]; + string filename; + for (; i < (int)sFileFullName.size(); ++i) + filename += sFileFullName[i]; + smallpath = _Environnement.ContinentsDir + smallpath; + char curdir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, curdir); + SetCurrentDirectory (smallpath.c_str()); + + CNameEditDlg dlg; + dlg.Title = "Change the name of the file"; + dlg.Comment = "Enter the new file name"; + dlg.Name = filename.c_str(); + + if (dlg.DoModal() == IDOK) + { + if (!MoveFile (filename.c_str(), dlg.Name)) + { + MessageBox ("Cannot rename file", "Error", MB_ICONERROR|MB_OK); + } + } + + SetCurrentDirectory (curdir); +} + +// --------------------------------------------------------------------------- +void CMainFrame::fileDelete (const std::string &sFileFullName) +{ + if (sFileFullName.size() > 4) + if (stricmp(&sFileFullName.c_str()[sFileFullName.size()-4], ".cfg") == 0) + return; + string fullname = _Environnement.ContinentsDir + sFileFullName; + DeleteFile (fullname.c_str()); + updateTree (); +} + +// --------------------------------------------------------------------------- +void CMainFrame::copy (const std::string &sPathSrc, const std::string &sPathDst) +{ + string sSrc = _Environnement.ContinentsDir + sPathSrc; + string sDst = _Environnement.ContinentsDir + sPathDst; + + if (GetFileAttributes(sSrc.c_str())&FILE_ATTRIBUTE_DIRECTORY) + { + copytree (sSrc, sDst); + } + else + { + int zepos = sSrc.rfind('\\'); + for (int i = zepos; i < (int)sSrc.size(); ++i) + sDst += sSrc[i]; + if (!CopyFile (sSrc.c_str(), sDst.c_str(), TRUE)) + displayLastErrorDialog (); + } + updateTree(); +} + +// --------------------------------------------------------------------------- +void CMainFrame::setActivePath (const std::string &pathName) +{ + _ActivePath = pathName; + if (_ActivePath == "") return; + string sContinentDir; + int i = 0; + if (pathName[i] == '\\') ++i; + for (; i < (int)pathName.size(); ++i) + { + if (pathName[i] == '\\') break; + sContinentDir += pathName[i]; + } + + sContinentDir = _Environnement.ContinentsDir + sContinentDir; + + if (_Georges != NULL) + { + georgesSetPathesFromActive (); + } + + if ((_Environnement.WorldEdOpened) && (_ActivePath != "")) + { + // Open continent.cfg to load the .land + SContinentCfg cfg; + string sTmp = sContinentDir + "\\continent.cfg"; + cfg.load (sTmp.c_str()); + _WorldEditor->setDataDir(cfg.LandDir.c_str()); + _WorldEditor->loadFile (cfg.LandFile.c_str()); + } +} + +// --------------------------------------------------------------------------- +void CMainFrame::OnSize (UINT nType, int cx, int cy) +{ +} + +// --------------------------------------------------------------------------- +void CMainFrame::OnMove (int x, int y) +{ + RECT r; + GetWindowRect (&r); + _Environnement.MasterY = r.top; + _Environnement.MasterX = r.left; + if ((_Tree != NULL) && (_Environnement.MasterTreeLocked)) + { + _Tree->SetWindowPos (&wndTop, x, y, 0, 0, SWP_NOSIZE); + SetFocus(); + } +} + +// --------------------------------------------------------------------------- +int CMainFrame::OnCreate (LPCREATESTRUCT lpCreateStruct) +{ + // Create the menu + if (CFrameWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + CoInitialize (NULL); + + // Create the tree + _Tree = new CMasterTreeDlg (); + _Tree->Create (IDD_MASTERTREE, this); + + // Load tools and get interface + getAllInterfaces (); + + // Restore all (windows position and size, menu checked, etc...) + // TREE + _Tree->SetWindowPos (&wndTop, _Environnement.MasterTreeX, _Environnement.MasterTreeY, + _Environnement.MasterTreeCX, _Environnement.MasterTreeCY, SWP_SHOWWINDOW); + _Tree->ShowWindow (SW_SHOW); + _Tree->update (_Environnement.ContinentsDir); + if (_Environnement.MasterTreeLocked) + GetMenu()->CheckMenuItem (ID_OPTIONS_TREELOCK, MF_CHECKED); + + // WORLDEDITOR + if (_WorldEditor != NULL) + { + _MasterCB.setMainFrame (this); + _WorldEditor->setMasterCB (&_MasterCB); + _WorldEditor->setDataDir (_Environnement.ContinentsDir.c_str()); + } + if (_Environnement.WorldEdOpened) + { + _Environnement.WorldEdOpened = false; + openWorldEditor (); + } + + // GEORGES + if (_Georges != NULL) + { + _Georges->SetDirDfnTyp (_Environnement.DefaultDFNDir); + _Georges->SetDirPrototype (_Environnement.DefaultGameElemDir); + georgesCreatePlantName (); + } + if (_Environnement.GeorgesOpened) + { + _Environnement.GeorgesOpened = false; + openGeorges (); + } + + // LOGICEDITOR +// if (_LogicEditor != NULL) +// _LogicEditor->setRootDir (_Environnement.RootDir.c_str()); + if (_Environnement.LogicEditorOpened) + { + _Environnement.LogicEditorOpened = false; + openLogicEditor (); + } + + return 0; +} + +// --------------------------------------------------------------------------- +BOOL CMainFrame::PreCreateWindow (CREATESTRUCT& cs) +{ + // Load the config file + char sCurDir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, sCurDir); + _MasterExeDir = string(sCurDir) + "\\"; + try + { + _Environnement.load (_MasterExeDir+"master.cfg"); + } + catch (Exception&e) + { + MessageBox (e.what(), "Warning"); + } + + // Restore the master window position + cs.x = _Environnement.MasterX; + cs.y = _Environnement.MasterY; + + if (!CFrameWnd::PreCreateWindow(cs)) + return FALSE; + + cs.style = WS_OVERLAPPED; + cs.cx = 360; + cs.cy = GetSystemMetrics (SM_CYCAPTION) + + GetSystemMetrics (SM_CYMENU) + + GetSystemMetrics (SM_CYFRAME); + + return TRUE; +} + +// --------------------------------------------------------------------------- +BOOL CMainFrame::PreTranslateMessage (MSG*pMsg) +{ + if (_Georges != NULL) + { + CWnd *pWnd = (CWnd*)_Georges->getMainFrame(); + CWnd *pFocusWnd = CWnd::GetFocus(); + if (pWnd != NULL) + { + while (pFocusWnd != NULL) + { + if (pWnd->m_hWnd == pFocusWnd->m_hWnd) + return _Georges->PreTranslateMessage (pMsg); + pFocusWnd = pFocusWnd->GetParent(); + } + } + } + return CFrameWnd::PreTranslateMessage (pMsg); +} + +// --------------------------------------------------------------------------- +BOOL CMainFrame::OnEraseBkgnd (CDC* pDC) +{ + return true; +} + +// --------------------------------------------------------------------------- +bool CMainFrame::createDirIfNotExist (const string& dirName, const string& errorMsg) +{ + char sCurDir[MAX_PATH]; + SECURITY_ATTRIBUTES sa; + sa.nLength = sizeof(sa); + sa.lpSecurityDescriptor = NULL; + sa.bInheritHandle = true; + GetCurrentDirectory (MAX_PATH, sCurDir); + if (!SetCurrentDirectory (dirName.c_str())) + { + if (!CreateDirectory (dirName.c_str(), &sa)) + { + MessageBox (errorMsg.c_str(), "Error", MB_ICONERROR|MB_OK); + SetCurrentDirectory (sCurDir); + return false; + } + } + SetCurrentDirectory (sCurDir); + return true; +} +// --------------------------------------------------------------------------- +void CMainFrame::continentNew () +{ + if (!createDirIfNotExist (_Environnement.ContinentsDir, "Cannot create Continents system directory")) + return; + + // Create the new continent + char sCurDir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, sCurDir); + SetCurrentDirectory (_Environnement.ContinentsDir.c_str()); + CreateDirectory ("NewContinent", NULL); + SContinentCfg cfg; + cfg.save ("NewContinent\\continent.cfg"); + + SetCurrentDirectory (_Environnement.ContinentsDir.c_str()); + SetCurrentDirectory ("NewContinent"); + + // Ok so now create default files +// _WorldEditor->createDefaultFiles (newDirName.c_str()); +// georgesCreateFilesWhenNewContinent (); + + continentProperties ("NewContinent"); + + _Tree->update (_Environnement.ContinentsDir); + SetCurrentDirectory (sCurDir); +} + +// --------------------------------------------------------------------------- +void CMainFrame::continentOpen (const std::string &contName) +{ + setActivePath (contName); + openDir (contName); +} + +// --------------------------------------------------------------------------- +void CMainFrame::continentProperties (const string &contName) +{ + CContinentPropertiesDlg cp(this); + + char sCurDir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, sCurDir); + + string worldDir; + worldDir = _Environnement.ContinentsDir; + + if (!SetCurrentDirectory (worldDir.c_str())) + return; + if (!SetCurrentDirectory (contName.c_str())) + return; + + SContinentCfg cfg; + cfg.load ("continent.cfg"); + + cp.ContinentName = contName.c_str(); + + cp.LandFile = cfg.LandFile.c_str(); + cp.LandDir = cfg.LandDir.c_str(); + cp.DfnDir = cfg.DfnDir.c_str(); + cp.GameElemDir = cfg.GameElemDir.c_str(); + + cp.LandBankFile = cfg.LandBankFile.c_str(); + cp.LandFarBankFile = cfg.LandFarBankFile.c_str(); + cp.LandTileNoiseDir = cfg.LandTileNoiseDir.c_str(); + cp.LandZoneWDir = cfg.LandZoneWDir.c_str(); + cp.OutIGDir = cfg.OutIGDir.c_str(); + + if (cp.DoModal() == IDOK) + { + cfg.LandFile = cp.LandFile; + cfg.LandDir = cp.LandDir; + cfg.DfnDir = cp.DfnDir; + cfg.GameElemDir = cp.GameElemDir; + + cfg.LandBankFile = cp.LandBankFile; + cfg.LandFarBankFile = cp.LandFarBankFile; + cfg.LandTileNoiseDir = cp.LandTileNoiseDir; + cfg.LandZoneWDir = cp.LandZoneWDir; + cfg.OutIGDir = cp.OutIGDir; + + SetCurrentDirectory (worldDir.c_str()); + SetCurrentDirectory (contName.c_str()); + cfg.save ("continent.cfg"); + if (cp.ContinentName != CString(contName.c_str())) + { + // Rename the directory + SetCurrentDirectory (worldDir.c_str()); + if (!MoveFile (contName.c_str(), cp.ContinentName)) + { + MessageBox ("Cannot rename directory", "Error", MB_ICONERROR|MB_OK); + } + } + } + else + { + SetCurrentDirectory (_Environnement.ContinentsDir.c_str()); + deltree ("NewContinent"); + RemoveDirectory("NewContinent"); + } + SetCurrentDirectory (sCurDir); + updateTree (); +} + +// --------------------------------------------------------------------------- +void CMainFrame::continentNewRegion (const string &contName) +{ + char sCurDir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, sCurDir); + + CNameEditDlg dlg(this); + dlg.Title = "New Region"; + dlg.Comment = "Enter the name of the new region"; + dlg.Name = "NewRegion"; + + if (dlg.DoModal() == IDOK) + { + if (dlg.Name != "") + { + string tmpDir = _Environnement.ContinentsDir + contName; + SetCurrentDirectory (tmpDir.c_str()); + CreateDirectory ((LPCSTR)dlg.Name, NULL); + SetCurrentDirectory (dlg.Name); + updateTree (); + } + } + + SetCurrentDirectory (sCurDir); +} + +// --------------------------------------------------------------------------- +// Save all in all modules +void CMainFrame::onContinentSave () +{ + if (_Environnement.WorldEdOpened) + { + if (_WorldEditor) + _WorldEditor->saveOpenedFiles(); + } + if (_Environnement.GeorgesOpened) + { +// if (_Georges) +// _Georges->saveOpenedFiles(); + } + if (_Environnement.LogicEditorOpened) + { +// if (_LogicEditor) +// _LogicEditor->saveOpenedFiles(); + } +} + +// --------------------------------------------------------------------------- +void CMainFrame::onContinentExport () +{ + onContinentSave (); + + char sCurDir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, sCurDir); + string sTmp = _Environnement.ContinentsDir; + SetCurrentDirectory (sTmp.c_str()); + + vector vRegNames; + WIN32_FIND_DATA fd; + HANDLE hFind = FindFirstFile ("*.*", &fd); + while (hFind != INVALID_HANDLE_VALUE) + { + bool bFound = false; + for (uint32 i = 0; i < MAX_SYS_DIR; ++i) + if (stricmp (fd.cFileName, gSysDir[i]) == 0) + { + bFound = true; + break; + } + if (!bFound) + { + if ((fd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) != 0) + { + vRegNames.push_back (string(fd.cFileName)); + } + } + if (FindNextFile (hFind, &fd) == 0) + break; + } + FindClose (hFind); + + if (vRegNames.size() == 0) + return; + + CExportDlg dlg (this); + +// _Environnement.ExportOptions.SourceDir = _ActiveContinent; + dlg.setOptions (_Environnement.ExportOptions, vRegNames); + if (dlg.DoModal() == IDOK) + { + if (_ExportCBDlg != NULL) + _ExportCBDlg->DestroyWindow(); + _ExportCBDlg = new CExportCBDlg(); + //Check if new succeeded and we got a valid pointer to a dialog object + if (_Export == NULL) + _Export = new CExport; + if (_ExportCBDlg != NULL) + { + BOOL ret = _ExportCBDlg->Create (IDD_EXPORTCB, this); + if (!ret) //Create failed. + { + delete _ExportCBDlg; + _ExportCBDlg = NULL; + } + _ExportCBDlg->ShowWindow (SW_SHOW); + } + + _Environnement.ExportOptions.PrimFloraDir = _Environnement.ContinentsDir + _Environnement.ExportOptions.PrimFloraDir; + + SetCurrentDirectory (_MasterExeDir.c_str()); + try + { + _Environnement.save (_MasterExeDir+"master.cfg"); + + _Export->newExport (_Environnement.ExportOptions, _ExportCBDlg->getExportCB()); + + } + catch(Exception&e) + { + MessageBox (e.what(), "Error", MB_ICONERROR|MB_OK); + } + + _ExportCBDlg->setFinishedButton (); + while (_ExportCBDlg->getFinished () == false) + { + _ExportCBDlg->pump (); + } + _ExportCBDlg->DestroyWindow (); + } + SetCurrentDirectory (sCurDir); +} + +// --------------------------------------------------------------------------- +/*void CMainFrame::OnContinentDelete () +{ + CChooseDir chooseDir(this); + chooseDir.setPath (_Environnement.ContinentsDir); + if (chooseDir.DoModal() == IDOK) + { + continentDelete (chooseDir.getSelected()); + } +}*/ + +// --------------------------------------------------------------------------- +void CMainFrame::onOptionsTreeLock () +{ + _Environnement.MasterTreeLocked = !_Environnement.MasterTreeLocked; + if (_Environnement.MasterTreeLocked) + { + GetMenu()->CheckMenuItem (ID_OPTIONS_TREELOCK, MF_CHECKED); + _Tree->SetWindowPos (&wndTop, _Environnement.MasterX, _Environnement.MasterY+45, 0, 0, SWP_NOSIZE); + SetFocus(); + } + else + GetMenu()->CheckMenuItem (ID_OPTIONS_TREELOCK, MF_UNCHECKED); +} + +// --------------------------------------------------------------------------- +int CALLBACK BrowseCallbackProc (HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) +{ + switch(uMsg) + { + case BFFM_INITIALIZED: + SendMessage (hwnd, BFFM_SETSELECTION, TRUE, pData); + break; + default: + break; + } + return 0; +} + +// --------------------------------------------------------------------------- +void CMainFrame::onOptionsSetContinentsDir () +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the continents path"; + bi.ulFlags = 0; + bi.lpfn = BrowseCallbackProc; + + char sDir[512]; + strcpy(sDir, _Environnement.ContinentsDir.c_str()); + bi.lParam = (LPARAM)sDir; + + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return; + } + _Environnement.ContinentsDir = str; + if (_Environnement.ContinentsDir[_Environnement.ContinentsDir.size()-1] != '\\') + _Environnement.ContinentsDir += "\\"; + // TREE + _Tree->update (_Environnement.ContinentsDir); + // WORLDEDITOR + if (_WorldEditor != NULL) + _WorldEditor->setDataDir (_Environnement.ContinentsDir.c_str()); + // GEORGES + if (_Georges != NULL) + { + //_Georges->SetRootDirectory (_Environnement.RootDir + "common"); + //_Georges->SetWorkDirectory (_Environnement.RootDir + "common\\dfn"); + georgesCreatePlantName (); + } + // LOGICEDITOR +// if (_LogicEditor != NULL) +// _LogicEditor->setRootDir (_Environnement.RootDir.c_str()); +} + +// --------------------------------------------------------------------------- +void CMainFrame::onOptionsSetDefaultDFNDir () +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the default DFN path"; + bi.ulFlags = 0; + bi.lpfn = BrowseCallbackProc; + + char sDir[512]; + strcpy(sDir, _Environnement.DefaultDFNDir.c_str()); + bi.lParam = (LPARAM)sDir; + + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return; + } + _Environnement.DefaultDFNDir = str; + if (_Environnement.DefaultDFNDir[_Environnement.DefaultDFNDir.size()-1] != '\\') + _Environnement.DefaultDFNDir += "\\"; + + // GEORGES + if (_Georges != NULL) + { + _Georges->SetDirDfnTyp (_Environnement.DefaultDFNDir); + georgesCreatePlantName (); + } + // LOGICEDITOR +// if (_LogicEditor != NULL) +// _LogicEditor->setRootDir (_Environnement.RootDir.c_str()); +} + +// --------------------------------------------------------------------------- +void CMainFrame::onOptionsSetDefaultGameElemDir () +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the default GameElem path"; + bi.ulFlags = 0; + bi.lpfn = BrowseCallbackProc; + + char sDir[512]; + strcpy(sDir, _Environnement.DefaultGameElemDir.c_str()); + bi.lParam = (LPARAM)sDir; + + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return; + } + _Environnement.DefaultGameElemDir = str; + if (_Environnement.DefaultGameElemDir[_Environnement.DefaultGameElemDir.size()-1] != '\\') + _Environnement.DefaultGameElemDir += "\\"; + + // GEORGES + if (_Georges != NULL) + { + _Georges->SetDirPrototype (_Environnement.DefaultGameElemDir); + georgesCreatePlantName (); + } + // LOGICEDITOR +// if (_LogicEditor != NULL) +// _LogicEditor->setRootDir (_Environnement.RootDir.c_str()); +} + +// --------------------------------------------------------------------------- +void CMainFrame::onWindowsWorldEditor () +{ + if (!_Environnement.WorldEdOpened) + openWorldEditor (); + else + closeWorldEditor (); +} + +// --------------------------------------------------------------------------- +void CMainFrame::onWindowsGeorges () +{ + if (!_Environnement.GeorgesOpened) + openGeorges (); + else + closeGeorges (); +} + +// --------------------------------------------------------------------------- +void CMainFrame::onWindowsLogicEditor () +{ + if (!_Environnement.LogicEditorOpened) + openLogicEditor (); + else + closeLogicEditor (); +} + +// --------------------------------------------------------------------------- +void CMainFrame::onWindowsReset () +{ + bool redo = false; + + redo = (_Environnement.WorldEdOpened == true); + closeWorldEditor (); + _Environnement.WorldEdX = 50; + _Environnement.WorldEdY = 50; + _Environnement.WorldEdCX = 600; + _Environnement.WorldEdCY = 400; + if (redo) + openWorldEditor (); + + redo = (_Environnement.GeorgesOpened == true); + closeGeorges (); + _Environnement.GeorgesX = 50; + _Environnement.GeorgesY = 50; + _Environnement.GeorgesCX = 300; + _Environnement.GeorgesCY = 300; + if (redo) + openGeorges (); + + redo = (_Environnement.LogicEditorOpened == true); + closeLogicEditor (); + _Environnement.LogicEditorX = 50; + _Environnement.LogicEditorY = 50; + _Environnement.LogicEditorCX = 300; + _Environnement.LogicEditorCY = 300; + if (redo) + openLogicEditor (); +} + +// --------------------------------------------------------------------------- +void CMainFrame::OnClose () +{ + RECT r; + + // Master Tree saves + _Tree->GetWindowRect (&r); + _Environnement.MasterTreeX = r.left; + _Environnement.MasterTreeY = r.top; + _Environnement.MasterTreeCX = r.right-r.left; + _Environnement.MasterTreeCY = r.bottom-r.top; + + // WorldEditor saves + if (_Environnement.WorldEdOpened) + { + closeWorldEditor (); + _Environnement.WorldEdOpened = true; + } + + // Georges saves + if (_Environnement.GeorgesOpened) + { + closeGeorges (); + _Environnement.GeorgesOpened = true; + } + + // LogicEditor saves + if (_Environnement.LogicEditorOpened) + { + closeLogicEditor (); + _Environnement.LogicEditorOpened = true; + } + + // Save the environnement + SetCurrentDirectory (_MasterExeDir.c_str()); + try + { + _Environnement.save (_MasterExeDir+"master.cfg"); + } + catch(Exception&e) + { + MessageBox (e.what(), "Error", MB_ICONERROR|MB_OK); + } + + releaseAllInterfaces (); + + DestroyWindow(); +} + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CMainFrame message handlers + diff --git a/code/ryzom/tools/leveldesign/master/MainFrm.h b/code/ryzom/tools/leveldesign/master/MainFrm.h index 7dfaddf91..72a9becaa 100644 --- a/code/ryzom/tools/leveldesign/master/MainFrm.h +++ b/code/ryzom/tools/leveldesign/master/MainFrm.h @@ -1,286 +1,286 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// --------------------------------------------------------------------------- -// MainFrm.h : interface of the CMainFrame class -// --------------------------------------------------------------------------- - -#if !defined(AFX_MAINFRM_H__D9ABC57D_9514_49B1_A65F_1CC64C6D6BB6__INCLUDED_) -#define AFX_MAINFRM_H__D9ABC57D_9514_49B1_A65F_1CC64C6D6BB6__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -// --------------------------------------------------------------------------- - -#include "nel/misc/stream.h" -#include "nel/misc/file.h" -#include "MasterTree.h" -#include - -#include "../export/export.h" - -#include "../../3d/ligo/worldeditor/worldeditor_interface.h" // MasterCB - -#include "easy_cfg.h" - -// --------------------------------------------------------------------------- -// Interface to the tools -// --------------------------------------------------------------------------- - -class IWorldEditor; -class IGeorges; -class ILogicEditor; -class CMainFrame; -class CExportCBDlg; -// --------------------------------------------------------------------------- - -// Do not parse following directories -#define MAX_SYS_DIR 7 -extern char *gSysDir[MAX_SYS_DIR]; -// Do not display files with those extensions -#define MAX_INVALID_EXT 1 -extern char *gInvalidExt[MAX_INVALID_EXT]; - -// --------------------------------------------------------------------------- - -struct SEnvironnement : public IEasyCFG -{ - // Master params - sint32 MasterX, MasterY; - sint32 MasterTreeX, MasterTreeY; - sint32 MasterTreeCX, MasterTreeCY; - bool MasterTreeLocked; - std::string ContinentsDir; - std::string DefaultDFNDir; - std::string DefaultGameElemDir; - - // WorldEditor params - bool WorldEdOpened; - sint32 WorldEdX, WorldEdY, WorldEdCX, WorldEdCY; - - // Georges params - bool GeorgesOpened; - sint32 GeorgesX, GeorgesY, GeorgesCX, GeorgesCY; - - // LogicEditor params - bool LogicEditorOpened; - sint32 LogicEditorX, LogicEditorY, LogicEditorCX, LogicEditorCY; - - // Export params - SExportOptions ExportOptions; - - SEnvironnement (); - - bool load (const std::string &filename); - bool save (const std::string &filename); -}; - - -// --------------------------------------------------------------------------- - -class CMasterCB : public IMasterCB -{ - CMainFrame *_MainFrame; - std::vector _PrimZoneList; - std::string _Text; - std::vector _GroupPrimList; - -public: - - CMasterCB (); - void setMainFrame (CMainFrame*pMF); // Link to master - - // Accessors - std::vector &getAllPrimZoneNames (); - - // Overridables - // setAllPrimZoneNames : called when the list of patatoid changes - virtual void setAllPrimZoneNames (std::vector &primZoneList); - // transfert : called when WE want to transfert text to georges - virtual void multiTransfert (const std::vector &vText, bool append); - virtual void transfert (const std::string &sText); - // Selection line up and down - virtual void lineUp (); - virtual void lineDown (); -}; - -// --------------------------------------------------------------------------- - -class CMainFrame : public CFrameWnd -{ - SEnvironnement _Environnement; - - IWorldEditor *_WorldEditor; - HMODULE _WorldEditorModule; - - IGeorges *_Georges; - HMODULE _GeorgesModule; - - ILogicEditor *_LogicEditor; - HMODULE _LogicEditorModule; - - CMasterTreeDlg *_Tree; - - std::string _ActivePath; - CMasterCB _MasterCB; - - std::string _MasterExeDir; - - CExport *_Export; - CExportCBDlg *_ExportCBDlg; - -public: - - CMainFrame (); - virtual ~CMainFrame (); - - void getAllInterfaces (); // Load all dlls and get tools interfaces - void releaseAllInterfaces (); - - void openFile (const std::string &fname); - void openDir (const std::string &fname); - void openDirParse (const std::string &sBaseName, const std::string &sRelativeName); - - void openContinentCfgFile (const std::string &filename); - - // *********** - // WORLDEDITOR - // *********** - - void openWorldEditor (); - void openWorldEditorFile (const std::string &fileName); - void closeWorldEditor (); - - // ******* - // GEORGES - // ******* - - void openGeorges (); - void openGeorgesFile (const std::string &fileName); - void closeGeorges (); - - void georgesSetPathesFromActive (); // Set Path from _ActiveContinent/_ActiveWorld/etc... - void georgesPutGroupText (const std::vector &vText, bool append); - void georgesPutText (const std::string &sText); - void georgesLineUp (); - void georgesLineDown (); - void georgesCreatePlantName (); - - // *********** - // LOGICEDITOR - // *********** - - void openLogicEditor (); - void openLogicEditorFile (const std::string &fileName); - void closeLogicEditor (); - - // ***** - // TOOLS - // ***** - - // Tree and directories manipulation - - bool createDirIfNotExist (const std::string& dirName, const std::string& errorMsg); - void deltree (const std::string &dirName); - void copytree (const std::string &srcDir, const std::string &dstDir); - void displayLastErrorDialog (); - void updateTree (); - - // Continent methods - // ----------------- - - void continentNew (); - - void continentOpen (const std::string &contName); - void continentProperties (const std::string &contName); - void continentNewRegion (const std::string &contName); - void continentDelete (const std::string &contName); - - // Active path - void setActivePath (const std::string &contName); - std::string getActivePath () { return _ActivePath; } - - // Region methods - // -------------- - - void regionOpen (const std::string &path); - void regionRename (const std::string &path); - void regionNewPrim (const std::string &path); - void regionNewGeorges (const std::string &path); - void regionNewSubRegion (const std::string &path); - void regionDelete (const std::string &path); - - // File methods - // ------------ - - void fileOpen (const std::string &sFileFullName); - void fileRename (const std::string &sFileFullName); - void fileDelete (const std::string &sFileFullName); - - void copy (const std::string &sPathSrc, const std::string &sPathDst); - -#ifdef _DEBUG - virtual void AssertValid () const; - virtual void Dump (CDumpContext& dc) const; -#endif - - virtual BOOL PreCreateWindow (CREATESTRUCT& cs); - virtual BOOL PreTranslateMessage (MSG*pMsg); - -protected: - - afx_msg void OnSize (UINT nType, int cx, int cy); - afx_msg void OnMove (int x, int y); - afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct); - afx_msg BOOL OnEraseBkgnd (CDC* pDC); - -protected: - - // Menu methods - - afx_msg void onContinentSave (); - afx_msg void onContinentExport (); - - afx_msg void OnContinentDelete (); - - afx_msg void onOptionsTreeLock (); - afx_msg void onOptionsSetContinentsDir (); - afx_msg void onOptionsSetDefaultDFNDir (); - afx_msg void onOptionsSetDefaultGameElemDir (); - - - afx_msg void onWindowsWorldEditor (); - afx_msg void onWindowsGeorges (); - afx_msg void onWindowsLogicEditor (); - afx_msg void onWindowsReset (); - - afx_msg void OnClose (); - // NOTE - the ClassWizard will add and remove member functions here. - // DO NOT EDIT what you see in these blocks of generated code! - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - - -}; - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_MAINFRM_H__D9ABC57D_9514_49B1_A65F_1CC64C6D6BB6__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// --------------------------------------------------------------------------- +// MainFrm.h : interface of the CMainFrame class +// --------------------------------------------------------------------------- + +#if !defined(AFX_MAINFRM_H__D9ABC57D_9514_49B1_A65F_1CC64C6D6BB6__INCLUDED_) +#define AFX_MAINFRM_H__D9ABC57D_9514_49B1_A65F_1CC64C6D6BB6__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// --------------------------------------------------------------------------- + +#include "nel/misc/stream.h" +#include "nel/misc/file.h" +#include "MasterTree.h" +#include + +#include "../export/export.h" + +#include "../../3d/ligo/worldeditor/worldeditor_interface.h" // MasterCB + +#include "easy_cfg.h" + +// --------------------------------------------------------------------------- +// Interface to the tools +// --------------------------------------------------------------------------- + +class IWorldEditor; +class IGeorges; +class ILogicEditor; +class CMainFrame; +class CExportCBDlg; +// --------------------------------------------------------------------------- + +// Do not parse following directories +#define MAX_SYS_DIR 7 +extern char *gSysDir[MAX_SYS_DIR]; +// Do not display files with those extensions +#define MAX_INVALID_EXT 1 +extern char *gInvalidExt[MAX_INVALID_EXT]; + +// --------------------------------------------------------------------------- + +struct SEnvironnement : public IEasyCFG +{ + // Master params + sint32 MasterX, MasterY; + sint32 MasterTreeX, MasterTreeY; + sint32 MasterTreeCX, MasterTreeCY; + bool MasterTreeLocked; + std::string ContinentsDir; + std::string DefaultDFNDir; + std::string DefaultGameElemDir; + + // WorldEditor params + bool WorldEdOpened; + sint32 WorldEdX, WorldEdY, WorldEdCX, WorldEdCY; + + // Georges params + bool GeorgesOpened; + sint32 GeorgesX, GeorgesY, GeorgesCX, GeorgesCY; + + // LogicEditor params + bool LogicEditorOpened; + sint32 LogicEditorX, LogicEditorY, LogicEditorCX, LogicEditorCY; + + // Export params + SExportOptions ExportOptions; + + SEnvironnement (); + + bool load (const std::string &filename); + bool save (const std::string &filename); +}; + + +// --------------------------------------------------------------------------- + +class CMasterCB : public IMasterCB +{ + CMainFrame *_MainFrame; + std::vector _PrimZoneList; + std::string _Text; + std::vector _GroupPrimList; + +public: + + CMasterCB (); + void setMainFrame (CMainFrame*pMF); // Link to master + + // Accessors + std::vector &getAllPrimZoneNames (); + + // Overridables + // setAllPrimZoneNames : called when the list of patatoid changes + virtual void setAllPrimZoneNames (std::vector &primZoneList); + // transfert : called when WE want to transfert text to georges + virtual void multiTransfert (const std::vector &vText, bool append); + virtual void transfert (const std::string &sText); + // Selection line up and down + virtual void lineUp (); + virtual void lineDown (); +}; + +// --------------------------------------------------------------------------- + +class CMainFrame : public CFrameWnd +{ + SEnvironnement _Environnement; + + IWorldEditor *_WorldEditor; + HMODULE _WorldEditorModule; + + IGeorges *_Georges; + HMODULE _GeorgesModule; + + ILogicEditor *_LogicEditor; + HMODULE _LogicEditorModule; + + CMasterTreeDlg *_Tree; + + std::string _ActivePath; + CMasterCB _MasterCB; + + std::string _MasterExeDir; + + CExport *_Export; + CExportCBDlg *_ExportCBDlg; + +public: + + CMainFrame (); + virtual ~CMainFrame (); + + void getAllInterfaces (); // Load all dlls and get tools interfaces + void releaseAllInterfaces (); + + void openFile (const std::string &fname); + void openDir (const std::string &fname); + void openDirParse (const std::string &sBaseName, const std::string &sRelativeName); + + void openContinentCfgFile (const std::string &filename); + + // *********** + // WORLDEDITOR + // *********** + + void openWorldEditor (); + void openWorldEditorFile (const std::string &fileName); + void closeWorldEditor (); + + // ******* + // GEORGES + // ******* + + void openGeorges (); + void openGeorgesFile (const std::string &fileName); + void closeGeorges (); + + void georgesSetPathesFromActive (); // Set Path from _ActiveContinent/_ActiveWorld/etc... + void georgesPutGroupText (const std::vector &vText, bool append); + void georgesPutText (const std::string &sText); + void georgesLineUp (); + void georgesLineDown (); + void georgesCreatePlantName (); + + // *********** + // LOGICEDITOR + // *********** + + void openLogicEditor (); + void openLogicEditorFile (const std::string &fileName); + void closeLogicEditor (); + + // ***** + // TOOLS + // ***** + + // Tree and directories manipulation + + bool createDirIfNotExist (const std::string& dirName, const std::string& errorMsg); + void deltree (const std::string &dirName); + void copytree (const std::string &srcDir, const std::string &dstDir); + void displayLastErrorDialog (); + void updateTree (); + + // Continent methods + // ----------------- + + void continentNew (); + + void continentOpen (const std::string &contName); + void continentProperties (const std::string &contName); + void continentNewRegion (const std::string &contName); + void continentDelete (const std::string &contName); + + // Active path + void setActivePath (const std::string &contName); + std::string getActivePath () { return _ActivePath; } + + // Region methods + // -------------- + + void regionOpen (const std::string &path); + void regionRename (const std::string &path); + void regionNewPrim (const std::string &path); + void regionNewGeorges (const std::string &path); + void regionNewSubRegion (const std::string &path); + void regionDelete (const std::string &path); + + // File methods + // ------------ + + void fileOpen (const std::string &sFileFullName); + void fileRename (const std::string &sFileFullName); + void fileDelete (const std::string &sFileFullName); + + void copy (const std::string &sPathSrc, const std::string &sPathDst); + +#ifdef _DEBUG + virtual void AssertValid () const; + virtual void Dump (CDumpContext& dc) const; +#endif + + virtual BOOL PreCreateWindow (CREATESTRUCT& cs); + virtual BOOL PreTranslateMessage (MSG*pMsg); + +protected: + + afx_msg void OnSize (UINT nType, int cx, int cy); + afx_msg void OnMove (int x, int y); + afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct); + afx_msg BOOL OnEraseBkgnd (CDC* pDC); + +protected: + + // Menu methods + + afx_msg void onContinentSave (); + afx_msg void onContinentExport (); + + afx_msg void OnContinentDelete (); + + afx_msg void onOptionsTreeLock (); + afx_msg void onOptionsSetContinentsDir (); + afx_msg void onOptionsSetDefaultDFNDir (); + afx_msg void onOptionsSetDefaultGameElemDir (); + + + afx_msg void onWindowsWorldEditor (); + afx_msg void onWindowsGeorges (); + afx_msg void onWindowsLogicEditor (); + afx_msg void onWindowsReset (); + + afx_msg void OnClose (); + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAINFRM_H__D9ABC57D_9514_49B1_A65F_1CC64C6D6BB6__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/master/MasterTree.cpp b/code/ryzom/tools/leveldesign/master/MasterTree.cpp index 8b573512a..dd9c0b771 100644 --- a/code/ryzom/tools/leveldesign/master/MasterTree.cpp +++ b/code/ryzom/tools/leveldesign/master/MasterTree.cpp @@ -1,998 +1,998 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// MasterTree.cpp : implementation file -// - -#include "stdafx.h" -#include "master.h" -#include "MasterTree.h" -#include "Mainfrm.h" -#include "nel/misc/types_nl.h" -#ifdef NL_NEW - #undef new -#endif -using namespace std; - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -// --------------------------------------------------------------------------- - -#define IDC_TREE 0x1000 - -// Top level menus -#define ID_MENU_CONTINENT_NEW 0x0044 - -#define ID_MENU_SORT_NAME_INC 0x0047 -#define ID_MENU_SORT_NAME_DEC 0x0048 -#define ID_MENU_SORT_DATE_INC 0x0049 -#define ID_MENU_SORT_DATE_DEC 0x0050 - -// Continent menus (a level under the top) - -#define ID_MENU_CONTINENT_DELETE 0x0064 -#define ID_MENU_CONTINENT_OPEN 0x0066 -#define ID_MENU_CONTINENT_PROPERTIES 0x0067 -#define ID_MENU_CONTINENT_NEW_REGION 0x0068 - -#define ID_MENU_REGION_OPEN 0x0070 -#define ID_MENU_REGION_RENAME 0x0071 -#define ID_MENU_REGION_NEW_SUBREGION 0x0072 -#define ID_MENU_REGION_NEW_PRIM 0x0073 -#define ID_MENU_REGION_NEW_GEORGES 0x0074 -#define ID_MENU_REGION_DELETE 0x0075 - -#define ID_MENU_FILE_OPEN 0x0080 -#define ID_MENU_FILE_RENAME 0x0081 -#define ID_MENU_FILE_DELETE 0x0082 - -// --------------------------------------------------------------------------- - -///////////////////////////////////////////////////////////////////////////// -// CMasterTreeDlg dialog -///////////////////////////////////////////////////////////////////////////// - -BEGIN_MESSAGE_MAP (CMasterTree, CTreeCtrl) - - ON_WM_TIMER() - - ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnLBeginDrag) - - ON_WM_MOUSEMOVE() - ON_WM_LBUTTONDBLCLK() - ON_WM_LBUTTONDOWN() - ON_WM_LBUTTONUP() - ON_WM_RBUTTONDOWN() - - ON_COMMAND(ID_MENU_CONTINENT_NEW, OnMenuNewContinent) - - ON_COMMAND(ID_MENU_CONTINENT_DELETE, OnMenuContinentDelete) - ON_COMMAND(ID_MENU_CONTINENT_OPEN, OnMenuContinentOpen) - ON_COMMAND(ID_MENU_CONTINENT_PROPERTIES, OnMenuContinentProperties) - ON_COMMAND(ID_MENU_CONTINENT_NEW_REGION, OnMenuContinentNewRegion) - - ON_COMMAND(ID_MENU_REGION_OPEN, OnMenuRegionOpen) - ON_COMMAND(ID_MENU_REGION_RENAME, OnMenuRegionRename) - ON_COMMAND(ID_MENU_REGION_NEW_PRIM, OnMenuRegionNewPrim) - ON_COMMAND(ID_MENU_REGION_NEW_GEORGES, OnMenuRegionNewGeorges) - ON_COMMAND(ID_MENU_REGION_DELETE, OnMenuRegionDelete) - ON_COMMAND(ID_MENU_REGION_NEW_SUBREGION, OnMenuRegionNewSubRegion) - - ON_COMMAND(ID_MENU_FILE_OPEN, OnMenuFileOpen) - ON_COMMAND(ID_MENU_FILE_RENAME, OnMenuFileRename) - ON_COMMAND(ID_MENU_FILE_DELETE, OnMenuFileDelete) - -END_MESSAGE_MAP() - -// --------------------------------------------------------------------------- -CMasterTree::CMasterTree () -{ - _LDrag = false; - _LastItemSelected = NULL; - _LastActiveContinent = NULL; -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnTimer (UINT nIDEvent) -{ - if( nIDEvent != m_nTimerID ) - { - CTreeCtrl::OnTimer(nIDEvent); - return; - } - - // Doesn't matter that we didn't initialize m_timerticks - m_timerticks++; - - POINT pt; - GetCursorPos (&pt); - RECT rect; - GetClientRect (&rect); - ClientToScreen (&rect); - - if( pt.y < rect.top + 10 ) - { - CImageList::DragShowNolock (FALSE); - SendMessage (WM_VSCROLL, SB_LINEUP); - CImageList::DragShowNolock (TRUE); - } - else if( pt.y > rect.bottom - 10 ) - { - CImageList::DragShowNolock (FALSE); - SendMessage (WM_VSCROLL, SB_LINEDOWN); - CImageList::DragShowNolock (TRUE); - } -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnLBeginDrag (NMHDR* pNMHDR, LRESULT* pResult) -{ - NMTREEVIEW *pNMTV = (NMTREEVIEW*)pNMHDR; - _DragItem = pNMTV->itemNew.hItem; - HTREEITEM hParent = GetParentItem (_DragItem); - if (hParent == NULL) - { - *pResult = true; - return; - } - _LDrag = true; - m_nTimerID = SetTimer (1, 50, NULL); - _DragImg = CreateDragImage (_DragItem); - _DragImg->BeginDrag (0, CPoint (8, 8)); - _DragImg->DragEnter (this, ((NM_TREEVIEW *)pNMHDR)->ptDrag); - SetCapture (); - Invalidate (); - *pResult = false; -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnLButtonDown (UINT nFlags, CPoint point) -{ - /*HTREEITEM NewItem = HitTest (point); - - if (NewItem == NULL) - return; - */ - CTreeCtrl::OnLButtonDown (nFlags, point); -/* - HTREEITEM LastContinent, LastRegion; - HTREEITEM NewContinent, NewRegion; - LastContinent = getContinent (_LastItemSelected); - LastRegion = getRegion (_LastItemSelected); - - NewContinent = getContinent (NewItem); - NewRegion = getRegion (NewItem); - - if (LastRegion != NewRegion) - { - Expand (LastRegion, TVE_COLLAPSE); - Expand (NewRegion, TVE_EXPAND); - } - - if (LastContinent != NewContinent) - { - Expand (LastContinent, TVE_COLLAPSE); - Expand (NewContinent, TVE_EXPAND); - } - - _LastItemSelected = NewItem; - Expand (NewItem, TVE_EXPAND); - Select (NewItem, TVGN_CARET);*/ -} -// --------------------------------------------------------------------------- -void CMasterTree::OnLButtonDblClk (UINT nFlags, CPoint point) -{ - CTreeCtrl::OnLButtonDblClk (nFlags, point); - - HTREEITEM hItem = HitTest (point); - - if (hItem != NULL) - { - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - - if (isFile(hItem)) - { - pDlg->openFile (getPath(hItem)); - } - } -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnLButtonUp (UINT nFlags, CPoint point) -{ - if (_LDrag) - { - SelectDropTarget (NULL); - _DragImg->DragLeave (this); - _DragImg->EndDrag (); - ReleaseCapture (); - KillTimer (m_nTimerID); - _LDrag = false; - delete _DragImg; - Invalidate (); - - HTREEITEM dragEndItem = HitTest (point); - if ((_DragItem == NULL) || (dragEndItem == NULL)) - return; - - if (isFile(dragEndItem)) - return; - - Select (dragEndItem, TVGN_CARET); - - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - pDlg->copy (getPath(_DragItem), getPath(dragEndItem)); - } -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMouseMove (UINT nFlags, CPoint point) -{ - if (_LDrag) - { - _DragImg->DragMove (point); - _DragImg->DragShowNolock (FALSE); - - UINT Flags; - HTREEITEM hItem = HitTest (point, &Flags); - HTREEITEM hParent = GetParentItem (hItem) ; - - if ((_DragItem == NULL) || (hItem == NULL)) - return; - - if (!isFile(hItem)) - SelectDropTarget (hItem); - - _DragImg->DragShowNolock (TRUE); - } -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnRButtonDown (UINT nFlags, CPoint point) -{ - UINT uFlags; - HTREEITEM hItem = HitTest (point, &uFlags); - HTREEITEM hParent = GetParentItem (hItem); - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - - CRect r; - this->GetWindowRect (r); - - CMenu *pMenu = new CMenu; - pMenu->CreatePopupMenu (); - - if (hItem == NULL) - { - pMenu->AppendMenu (MF_STRING, ID_MENU_CONTINENT_NEW, "&New Continent"); - pMenu->AppendMenu (MF_SEPARATOR); - pMenu->AppendMenu (MF_STRING, ID_MENU_SORT_NAME_DEC, "Sort By Name (A-Z)"); - pMenu->AppendMenu (MF_STRING, ID_MENU_SORT_NAME_INC, "Sort By Name (Z-A)"); - pMenu->AppendMenu (MF_STRING, ID_MENU_SORT_DATE_INC, "Sort By Date (New-Old)"); - pMenu->AppendMenu (MF_STRING, ID_MENU_SORT_DATE_DEC, "Sort By Date (Old-New)"); - } - else if (TVHT_ONITEM & uFlags) - { - Select (hItem, TVGN_CARET); - - // System roots == continents - if (hParent == NULL) - { - pMenu->AppendMenu (MF_STRING, ID_MENU_CONTINENT_OPEN, "&Open"); - pMenu->AppendMenu (MF_STRING, ID_MENU_CONTINENT_PROPERTIES, "&Properties"); - pMenu->AppendMenu (MF_STRING, ID_MENU_CONTINENT_NEW_REGION, "New &Region"); - pMenu->AppendMenu (MF_STRING, ID_MENU_CONTINENT_DELETE, "&Delete"); - } - // Under the continents == regions and sub-regions - else - { - if (!isFile (hItem)) - { - pMenu->AppendMenu (MF_STRING, ID_MENU_REGION_OPEN, "&Open"); - pMenu->AppendMenu (MF_STRING, ID_MENU_REGION_RENAME, "&Rename"); - pMenu->AppendMenu (MF_STRING, ID_MENU_REGION_NEW_SUBREGION, "New &SubRegion"); - pMenu->AppendMenu (MF_STRING, ID_MENU_REGION_NEW_GEORGES, "New &Form"); - pMenu->AppendMenu (MF_STRING, ID_MENU_REGION_NEW_PRIM, "New &Patatoid"); - pMenu->AppendMenu (MF_STRING, ID_MENU_REGION_DELETE, "&Delete"); - } - else - { - pMenu->AppendMenu (MF_STRING, ID_MENU_FILE_OPEN, "&Open"); - pMenu->AppendMenu (MF_STRING, ID_MENU_FILE_RENAME, "&Rename"); - pMenu->AppendMenu (MF_STRING, ID_MENU_FILE_DELETE, "&Delete"); - } - } - } - pMenu->TrackPopupMenu (TPM_LEFTALIGN | TPM_LEFTBUTTON, - r.left+point.x, r.top+point.y, this); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuNewContinent () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - pDlg->continentNew (); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuContinentDelete () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - pDlg->continentDelete ((LPCSTR)GetItemText(GetSelectedItem())); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuContinentOpen () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent (); - HTREEITEM hItem = GetSelectedItem (); - HTREEITEM hParent = GetParentItem (hItem); - - if (_LastActiveContinent != NULL) - SetItem (_LastActiveContinent, TVIF_STATE, NULL, 0, 0, 0, TVIS_BOLD, 0); - SetItem (hItem, TVIF_STATE, NULL, 0, 0, TVIS_BOLD, TVIS_BOLD, 0); - _LastActiveContinent = hItem; - pDlg->continentOpen (string((LPCSTR)GetItemText(hItem))); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuContinentProperties () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - pDlg->continentProperties ((LPCSTR)GetItemText(GetSelectedItem())); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuContinentNewRegion () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - pDlg->continentNewRegion ((LPCSTR)GetItemText(GetSelectedItem())); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuRegionOpen () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - HTREEITEM ht = GetSelectedItem(); - pDlg->regionOpen (getPath(ht)); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuRegionRename () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - HTREEITEM ht = GetSelectedItem(); - pDlg->regionRename (getPath(ht)); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuRegionNewSubRegion () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - HTREEITEM ht = GetSelectedItem(); - pDlg->regionNewSubRegion (getPath(ht)); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuRegionNewPrim () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - HTREEITEM ht = GetSelectedItem(); - pDlg->regionNewPrim (getPath(ht)); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuRegionNewGeorges () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - HTREEITEM ht = GetSelectedItem(); - pDlg->regionNewGeorges (getPath(ht)); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuRegionDelete () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - HTREEITEM ht = GetSelectedItem(); - pDlg->regionDelete (getPath(ht)); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuFileOpen () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - HTREEITEM hItem = GetSelectedItem(); - bool bFile = isFile (hItem); - if (!bFile) return; - pDlg->fileOpen (getPath(hItem)); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuFileRename () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - HTREEITEM hItem = GetSelectedItem(); - bool bFile = isFile (hItem); - if (!bFile) return; - pDlg->fileRename (getPath(hItem)); -} - -// --------------------------------------------------------------------------- -void CMasterTree::OnMenuFileDelete () -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - HTREEITEM hItem = GetSelectedItem(); - bool bFile = isFile (hItem); - if (!bFile) return; - pDlg->fileDelete (getPath(hItem)); -} - -// --------------------------------------------------------------------------- -string CMasterTree::getCurrentPath () -{ - return getPath(GetSelectedItem()); -} - -// TOOLS - -// --------------------------------------------------------------------------- -string CMasterTree::getPath (HTREEITEM ht) -{ - string sTmp = ""; - - while (ht != NULL) - { - sTmp = string("\\") + (LPCSTR)GetItemText(ht) + sTmp; - ht = GetParentItem(ht); - } - - return sTmp; -} - -// --------------------------------------------------------------------------- -HTREEITEM CMasterTree::getContinent (HTREEITEM ht) -{ - if (ht == NULL) return NULL; - if (GetParentItem(ht) == NULL) return NULL; - while (GetParentItem(GetParentItem(ht)) != NULL) - ht = GetParentItem(ht); - if (isFile(ht)) return NULL; - return ht; -} - -// --------------------------------------------------------------------------- -HTREEITEM CMasterTree::getRegion (HTREEITEM ht) -{ - if (ht == NULL) return NULL; - if (GetParentItem(ht) == NULL) return NULL; - if (GetParentItem(GetParentItem(ht)) == NULL) return NULL; - while (GetParentItem(GetParentItem(GetParentItem(ht))) != NULL) - ht = GetParentItem(ht); - if (isFile(ht)) return NULL; - return ht; -} - -// --------------------------------------------------------------------------- -bool CMasterTree::isFile (HTREEITEM ht) -{ - CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); - map::iterator it = pDlg->_Files.find (ht); - if (it != pDlg->_Files.end()) - return true; - else - return false; -} - - -///////////////////////////////////////////////////////////////////////////// -// CMasterTreeDlg dialog -///////////////////////////////////////////////////////////////////////////// - -BEGIN_MESSAGE_MAP(CMasterTreeDlg, CDialog) - //{{AFX_MSG_MAP(CMasterTreeDlg) - ON_WM_SIZE() - ON_NOTIFY(TVN_ITEMEXPANDING, IDC_TREE, OnExpanding) - //ON_NOTIFY(NM_DBLCLK, IDC_TREE, OnLDblClkTree) - ON_WM_CREATE() - ON_WM_CLOSE() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - - - -// --------------------------------------------------------------------------- -CMasterTreeDlg::CMasterTreeDlg () -{ - _Tree = NULL; - ContinentSortBy = 1; // 0/1 - by name - TrashSortBy = 1; // 2/3 - by date - BackupSortBy = 2; -} - -// --------------------------------------------------------------------------- -FILETIME getFileTime (const string &fname) -{ - WIN32_FIND_DATA FindFileData; - HANDLE hFind; - FILETIME ret = { 0xFFFFFFFF, 0xFFFFFFFF }; - - hFind = FindFirstFile (fname.c_str(), &FindFileData); - - if (hFind != INVALID_HANDLE_VALUE) - { - ret = FindFileData.ftLastWriteTime; - FindClose (hFind); - } - return ret; -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::parseAdd (HTREEITEM itRoot, const string &path, char SortType, int DirDepth) -{ - WIN32_FIND_DATA findData; - HANDLE hFind; - CTreeCtrl *pTree = (CTreeCtrl*)GetDlgItem(IDC_TREE); - vector SortTable; - sint32 i, j; - - char sCurDir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, sCurDir); - - if (!SetCurrentDirectory (path.c_str())) - { - SetCurrentDirectory (sCurDir); - return; - } - - hFind = FindFirstFile ("*.*", &findData); - if (hFind != INVALID_HANDLE_VALUE) - { - do - { - // Look if the name is a system directory - bool bFound = false; - for (uint32 i = 0; i < MAX_SYS_DIR; ++i) - if (stricmp (findData.cFileName, gSysDir[i]) == 0) - { - bFound = true; - break; - } - if (!bFound) // No ok lets add it - { - SortTable.push_back (findData.cFileName); - } - } - while (FindNextFile(hFind, &findData) != 0); - FindClose (hFind); - } - - if (SortTable.size() == 0) - { - SetCurrentDirectory (sCurDir); - return; - } - - if (SortType == 0) // Sort By Name increasing (z-a) - { - for (i = 0; i < (sint32)SortTable.size()-1; ++i) - for (j = i+1; j < (sint32)SortTable.size(); ++j) - if (strcmp(SortTable[i].c_str(), SortTable[j].c_str()) < 0) - { - string tmp = SortTable[i]; - SortTable[i] = SortTable[j]; - SortTable[j] = tmp; - } - } - if (SortType == 1) // Sort By Name decreasing (a-z) - { - for (i = 0; i < (sint32)SortTable.size()-1; ++i) - for (j = i+1; j < (sint32)SortTable.size(); ++j) - if (strcmp(SortTable[i].c_str(), SortTable[j].c_str()) > 0) - { - string tmp = SortTable[i]; - SortTable[i] = SortTable[j]; - SortTable[j] = tmp; - } - } - if (SortType == 2) // Sort By Date increasing - { - for (i = 0; i < (sint32)SortTable.size()-1; ++i) - { - FILETIME timeI = getFileTime (SortTable[i]); - for (j = i+1; j < (sint32)SortTable.size(); ++j) - { - FILETIME timeJ = getFileTime (SortTable[j]); - if ((timeI.dwHighDateTime < timeJ.dwHighDateTime) || - ( - (timeI.dwHighDateTime == timeJ.dwHighDateTime) && - (timeI.dwLowDateTime < timeJ.dwLowDateTime) - )) - { - string tmp = SortTable[i]; - SortTable[i] = SortTable[j]; - SortTable[j] = tmp; - timeI = timeJ; - } - } - } - } - - if (SortType == 3) // Sort By Date decreasing - { - for (i = 0; i < (sint32)SortTable.size()-1; ++i) - { - FILETIME timeI = getFileTime (SortTable[i]); - for (j = i+1; j < (sint32)SortTable.size(); ++j) - { - FILETIME timeJ = getFileTime (SortTable[j]); - if ((timeI.dwHighDateTime > timeJ.dwHighDateTime) || - ( - (timeI.dwHighDateTime == timeJ.dwHighDateTime) && - (timeI.dwLowDateTime > timeJ.dwLowDateTime) - )) - { - string tmp = SortTable[i]; - SortTable[i] = SortTable[j]; - SortTable[j] = tmp; - timeI = timeJ; - } - } - } - } - - // Put directories first ! - vector SortTable2; - for (i = 0; i < (sint32)SortTable.size(); ++i) - { - if (GetFileAttributes(SortTable[i].c_str())&FILE_ATTRIBUTE_DIRECTORY) - SortTable2.push_back(SortTable[i]); - } - for (i = 0; i < (sint32)SortTable.size(); ++i) - { - if (!(GetFileAttributes(SortTable[i].c_str())&FILE_ATTRIBUTE_DIRECTORY)) - SortTable2.push_back(SortTable[i]); - } - SortTable = SortTable2; - - // Recurse - for (i = 0; i < (sint32)SortTable.size(); ++i) - { - if (GetFileAttributes(SortTable[i].c_str())&FILE_ATTRIBUTE_DIRECTORY) - { - HTREEITEM item; - - if (DirDepth == 0) - item = pTree->InsertItem (SortTable[i].c_str(), 2, 2, itRoot); - else - item = pTree->InsertItem (SortTable[i].c_str(), 0, 0, itRoot); - string newPath = path; - if (newPath[newPath.size()-1] != '\\') - newPath += "\\"; - newPath += SortTable[i].c_str(); - parseAdd (item, newPath, SortType, DirDepth+1); - } - else - { - // Look if the name is a valid filename (look at the extension) - bool bFound = false; - for (uint32 j = 0; j < MAX_INVALID_EXT; ++j) - if (strlen(SortTable[i].c_str()) > strlen(gInvalidExt[j])) - if (stricmp(&SortTable[i].c_str()[strlen(SortTable[i].c_str())-strlen(gInvalidExt[j])], gInvalidExt[j]) == 0) - { - bFound = true; - break; - } - // If the extension is an invalid one -> Do not display file - if (!bFound) - { - HTREEITEM item = pTree->InsertItem (SortTable[i].c_str(), 1, 1, itRoot); - string sTemp = path; - if (sTemp[sTemp.size()-1] != '\\') - sTemp += "\\"; - sTemp += SortTable[i].c_str(); - _Files.insert(map::value_type(item, sTemp)); - } - - } - } - SetCurrentDirectory (sCurDir); -} - -// --------------------------------------------------------------------------- -HTREEITEM CMasterTreeDlg::activate (const std::string &name, HTREEITEM parent) -{ - // Extract the eltName - string eltName; - string resName; - uint32 i = 0; - if (name.size() == 0) return NULL; - if (name[i] == '\\') ++i; - for (; i < name.size(); ++i) - { - if (name[i] == '\\') break; - eltName += name[i]; - } - ++i; - for (; i < name.size(); ++i) - { - resName += name[i]; - } - - CTreeCtrl *pTree = (CTreeCtrl*)GetDlgItem (IDC_TREE); - HTREEITEM hChildItem = pTree->GetChildItem (parent); - bool bFound = false; - while (hChildItem != NULL) - { - if (eltName == (LPCSTR)pTree->GetItemText(hChildItem)) - { - pTree->SetItem (hChildItem, TVIF_STATE, NULL, 0, 0, TVIS_BOLD, TVIS_BOLD, 0); - pTree->Expand (hChildItem, TVE_EXPAND); - activate (resName, hChildItem); - bFound = true; - break; - } - - hChildItem = pTree->GetNextItem (hChildItem, TVGN_NEXT); - } - if (bFound) - return hChildItem; - else - return NULL; -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::update (const std::string& ContinentsPath) -{ - CMasterTree *pTree = (CMasterTree*)GetDlgItem (IDC_TREE); - string sCurPath = pTree->getCurrentPath(); - _Files.clear(); - pTree->DeleteAllItems (); - // Parse all the path - char sCurDir[MAX_PATH]; - GetCurrentDirectory (MAX_PATH, sCurDir); - parseAdd (TVI_ROOT, ContinentsPath, ContinentSortBy); - SetCurrentDirectory (sCurDir); - // Hilight active Continent - CMainFrame *pMF = (CMainFrame *)GetParent (); - activate (sCurPath, TVI_ROOT); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::DoDataExchange (CDataExchange* pDX) -{ - CDialog::DoDataExchange (pDX); - //{{AFX_DATA_MAP(CMasterTreeDlg) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP -} - -// --------------------------------------------------------------------------- -BOOL CMasterTreeDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - _Tree = new CMasterTree; - RECT r; - r.left = r.top = 10; - r.right = r.bottom = 40; - _Tree->Create (WS_VISIBLE|WS_BORDER, r, this, IDC_TREE); - // Load image list - CImageList *pImgList = new CImageList; - pImgList->Create (16, 16, ILC_MASK, 0, 5); - pImgList->Add (AfxGetApp()->LoadIcon(IDI_FOLDER)); - pImgList->Add (AfxGetApp()->LoadIcon(IDI_FILE)); - pImgList->Add (AfxGetApp()->LoadIcon(IDI_CONTINENTS)); - pImgList->Add (AfxGetApp()->LoadIcon(IDI_BACKUP)); - pImgList->Add (AfxGetApp()->LoadIcon(IDI_TRASH)); - - _Tree->SetImageList (pImgList, TVSIL_NORMAL); - return true; -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::OnSize (UINT nType, int cx, int cy) -{ - if (_Tree) - _Tree->SetWindowPos (&wndTop, 0, 0, cx-20, cy-20, SWP_NOMOVE); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::OnExpanding (LPNMHDR pnmhdr, LRESULT *pLResult) -{ - /*CTreeCtrl *pTree = (CTreeCtrl*)GetDlgItem (IDC_TREE); - NMTREEVIEW *pnmtv = (LPNMTREEVIEW) pnmhdr; - - if ((pnmtv->itemNew.state & TVIS_EXPANDED) != 0) - { - // We want to collapse this item -> forbid it - *pLResult = true; - }*/ -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::openFile (const std::string &fname) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->openFile (fname.c_str()); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::openDir (const std::string &fname) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->openDir (fname.c_str()); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::continentNew () -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->continentNew (); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::continentDelete (const string &contName) -{ - CMainFrame *pMF = (CMainFrame*)GetParent(); - pMF->continentDelete (contName); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::continentProperties (const string &contName) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->continentProperties (contName); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::continentNewRegion (const string &contName) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->continentNewRegion (contName); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::continentOpen (const string &contName) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->continentOpen (contName); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::regionOpen (const string &path) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->regionOpen (path); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::regionRename (const string &path) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->regionRename (path); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::regionNewPrim (const string &path) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->regionNewPrim (path); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::regionNewGeorges (const string &path) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->regionNewGeorges (path); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::regionNewSubRegion (const std::string &path) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->regionNewSubRegion (path); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::regionDelete (const std::string &path) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->regionDelete (path); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::fileOpen (const std::string &sFileFullName) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->fileOpen (sFileFullName); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::fileRename (const std::string &sFileFullName) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->fileRename (sFileFullName); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::fileDelete (const std::string &sFileFullName) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->fileDelete (sFileFullName); -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::copy (const std::string &pathSrc, const std::string &pathDst) -{ - CMainFrame *pMF = (CMainFrame *)GetParent(); - pMF->copy (pathSrc, pathDst); -} - -// --------------------------------------------------------------------------- -/* -void CMasterTreeDlg::OnLDblClkTree(NMHDR* pNMHDR, LRESULT* pResult) -{ - CTreeCtrl *pTree = (CTreeCtrl*)GetDlgItem (IDC_TREE); - NMTREEVIEW *pnmtv = (LPNMTREEVIEW) pNMHDR; - HTREEITEM hItem = pTree->GetSelectedItem(); - HTREEITEM hParent = pTree->GetParentItem (hItem); - - *pResult = 0; - if (hItem != NULL) - { - map::iterator it = _Files.find (hItem); - - if (it != _Files.end()) - { - // Double click on a file open the corresponding editor - openAnyFile (it->second.c_str()); - return; - } - - if ((hParent != NULL) && (pTree->GetParentItem (hParent) == NULL)) - { - // Double click on a Continent open all editors - // Parse all files and open them in the good editor - HTREEITEM hChildItem = pTree->GetChildItem (hItem); - - while (hChildItem != NULL) - { - it = _Files.find (hChildItem); - if (it != _Files.end()) - { - openAnyFile (it->second.c_str()); - } - hChildItem = pTree->GetNextItem (hChildItem, TVGN_NEXT); - } - return; - } - } - -} -*/ -// --------------------------------------------------------------------------- -void CMasterTreeDlg::OnCancel () -{ -} - -// --------------------------------------------------------------------------- -void CMasterTreeDlg::OnOK () -{ -} - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// MasterTree.cpp : implementation file +// + +#include "stdafx.h" +#include "master.h" +#include "MasterTree.h" +#include "Mainfrm.h" +#include "nel/misc/types_nl.h" +#ifdef NL_NEW + #undef new +#endif +using namespace std; + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +// --------------------------------------------------------------------------- + +#define IDC_TREE 0x1000 + +// Top level menus +#define ID_MENU_CONTINENT_NEW 0x0044 + +#define ID_MENU_SORT_NAME_INC 0x0047 +#define ID_MENU_SORT_NAME_DEC 0x0048 +#define ID_MENU_SORT_DATE_INC 0x0049 +#define ID_MENU_SORT_DATE_DEC 0x0050 + +// Continent menus (a level under the top) + +#define ID_MENU_CONTINENT_DELETE 0x0064 +#define ID_MENU_CONTINENT_OPEN 0x0066 +#define ID_MENU_CONTINENT_PROPERTIES 0x0067 +#define ID_MENU_CONTINENT_NEW_REGION 0x0068 + +#define ID_MENU_REGION_OPEN 0x0070 +#define ID_MENU_REGION_RENAME 0x0071 +#define ID_MENU_REGION_NEW_SUBREGION 0x0072 +#define ID_MENU_REGION_NEW_PRIM 0x0073 +#define ID_MENU_REGION_NEW_GEORGES 0x0074 +#define ID_MENU_REGION_DELETE 0x0075 + +#define ID_MENU_FILE_OPEN 0x0080 +#define ID_MENU_FILE_RENAME 0x0081 +#define ID_MENU_FILE_DELETE 0x0082 + +// --------------------------------------------------------------------------- + +///////////////////////////////////////////////////////////////////////////// +// CMasterTreeDlg dialog +///////////////////////////////////////////////////////////////////////////// + +BEGIN_MESSAGE_MAP (CMasterTree, CTreeCtrl) + + ON_WM_TIMER() + + ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnLBeginDrag) + + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONDBLCLK() + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_RBUTTONDOWN() + + ON_COMMAND(ID_MENU_CONTINENT_NEW, OnMenuNewContinent) + + ON_COMMAND(ID_MENU_CONTINENT_DELETE, OnMenuContinentDelete) + ON_COMMAND(ID_MENU_CONTINENT_OPEN, OnMenuContinentOpen) + ON_COMMAND(ID_MENU_CONTINENT_PROPERTIES, OnMenuContinentProperties) + ON_COMMAND(ID_MENU_CONTINENT_NEW_REGION, OnMenuContinentNewRegion) + + ON_COMMAND(ID_MENU_REGION_OPEN, OnMenuRegionOpen) + ON_COMMAND(ID_MENU_REGION_RENAME, OnMenuRegionRename) + ON_COMMAND(ID_MENU_REGION_NEW_PRIM, OnMenuRegionNewPrim) + ON_COMMAND(ID_MENU_REGION_NEW_GEORGES, OnMenuRegionNewGeorges) + ON_COMMAND(ID_MENU_REGION_DELETE, OnMenuRegionDelete) + ON_COMMAND(ID_MENU_REGION_NEW_SUBREGION, OnMenuRegionNewSubRegion) + + ON_COMMAND(ID_MENU_FILE_OPEN, OnMenuFileOpen) + ON_COMMAND(ID_MENU_FILE_RENAME, OnMenuFileRename) + ON_COMMAND(ID_MENU_FILE_DELETE, OnMenuFileDelete) + +END_MESSAGE_MAP() + +// --------------------------------------------------------------------------- +CMasterTree::CMasterTree () +{ + _LDrag = false; + _LastItemSelected = NULL; + _LastActiveContinent = NULL; +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnTimer (UINT nIDEvent) +{ + if( nIDEvent != m_nTimerID ) + { + CTreeCtrl::OnTimer(nIDEvent); + return; + } + + // Doesn't matter that we didn't initialize m_timerticks + m_timerticks++; + + POINT pt; + GetCursorPos (&pt); + RECT rect; + GetClientRect (&rect); + ClientToScreen (&rect); + + if( pt.y < rect.top + 10 ) + { + CImageList::DragShowNolock (FALSE); + SendMessage (WM_VSCROLL, SB_LINEUP); + CImageList::DragShowNolock (TRUE); + } + else if( pt.y > rect.bottom - 10 ) + { + CImageList::DragShowNolock (FALSE); + SendMessage (WM_VSCROLL, SB_LINEDOWN); + CImageList::DragShowNolock (TRUE); + } +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnLBeginDrag (NMHDR* pNMHDR, LRESULT* pResult) +{ + NMTREEVIEW *pNMTV = (NMTREEVIEW*)pNMHDR; + _DragItem = pNMTV->itemNew.hItem; + HTREEITEM hParent = GetParentItem (_DragItem); + if (hParent == NULL) + { + *pResult = true; + return; + } + _LDrag = true; + m_nTimerID = SetTimer (1, 50, NULL); + _DragImg = CreateDragImage (_DragItem); + _DragImg->BeginDrag (0, CPoint (8, 8)); + _DragImg->DragEnter (this, ((NM_TREEVIEW *)pNMHDR)->ptDrag); + SetCapture (); + Invalidate (); + *pResult = false; +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnLButtonDown (UINT nFlags, CPoint point) +{ + /*HTREEITEM NewItem = HitTest (point); + + if (NewItem == NULL) + return; + */ + CTreeCtrl::OnLButtonDown (nFlags, point); +/* + HTREEITEM LastContinent, LastRegion; + HTREEITEM NewContinent, NewRegion; + LastContinent = getContinent (_LastItemSelected); + LastRegion = getRegion (_LastItemSelected); + + NewContinent = getContinent (NewItem); + NewRegion = getRegion (NewItem); + + if (LastRegion != NewRegion) + { + Expand (LastRegion, TVE_COLLAPSE); + Expand (NewRegion, TVE_EXPAND); + } + + if (LastContinent != NewContinent) + { + Expand (LastContinent, TVE_COLLAPSE); + Expand (NewContinent, TVE_EXPAND); + } + + _LastItemSelected = NewItem; + Expand (NewItem, TVE_EXPAND); + Select (NewItem, TVGN_CARET);*/ +} +// --------------------------------------------------------------------------- +void CMasterTree::OnLButtonDblClk (UINT nFlags, CPoint point) +{ + CTreeCtrl::OnLButtonDblClk (nFlags, point); + + HTREEITEM hItem = HitTest (point); + + if (hItem != NULL) + { + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + + if (isFile(hItem)) + { + pDlg->openFile (getPath(hItem)); + } + } +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnLButtonUp (UINT nFlags, CPoint point) +{ + if (_LDrag) + { + SelectDropTarget (NULL); + _DragImg->DragLeave (this); + _DragImg->EndDrag (); + ReleaseCapture (); + KillTimer (m_nTimerID); + _LDrag = false; + delete _DragImg; + Invalidate (); + + HTREEITEM dragEndItem = HitTest (point); + if ((_DragItem == NULL) || (dragEndItem == NULL)) + return; + + if (isFile(dragEndItem)) + return; + + Select (dragEndItem, TVGN_CARET); + + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + pDlg->copy (getPath(_DragItem), getPath(dragEndItem)); + } +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMouseMove (UINT nFlags, CPoint point) +{ + if (_LDrag) + { + _DragImg->DragMove (point); + _DragImg->DragShowNolock (FALSE); + + UINT Flags; + HTREEITEM hItem = HitTest (point, &Flags); + HTREEITEM hParent = GetParentItem (hItem) ; + + if ((_DragItem == NULL) || (hItem == NULL)) + return; + + if (!isFile(hItem)) + SelectDropTarget (hItem); + + _DragImg->DragShowNolock (TRUE); + } +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnRButtonDown (UINT nFlags, CPoint point) +{ + UINT uFlags; + HTREEITEM hItem = HitTest (point, &uFlags); + HTREEITEM hParent = GetParentItem (hItem); + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + + CRect r; + this->GetWindowRect (r); + + CMenu *pMenu = new CMenu; + pMenu->CreatePopupMenu (); + + if (hItem == NULL) + { + pMenu->AppendMenu (MF_STRING, ID_MENU_CONTINENT_NEW, "&New Continent"); + pMenu->AppendMenu (MF_SEPARATOR); + pMenu->AppendMenu (MF_STRING, ID_MENU_SORT_NAME_DEC, "Sort By Name (A-Z)"); + pMenu->AppendMenu (MF_STRING, ID_MENU_SORT_NAME_INC, "Sort By Name (Z-A)"); + pMenu->AppendMenu (MF_STRING, ID_MENU_SORT_DATE_INC, "Sort By Date (New-Old)"); + pMenu->AppendMenu (MF_STRING, ID_MENU_SORT_DATE_DEC, "Sort By Date (Old-New)"); + } + else if (TVHT_ONITEM & uFlags) + { + Select (hItem, TVGN_CARET); + + // System roots == continents + if (hParent == NULL) + { + pMenu->AppendMenu (MF_STRING, ID_MENU_CONTINENT_OPEN, "&Open"); + pMenu->AppendMenu (MF_STRING, ID_MENU_CONTINENT_PROPERTIES, "&Properties"); + pMenu->AppendMenu (MF_STRING, ID_MENU_CONTINENT_NEW_REGION, "New &Region"); + pMenu->AppendMenu (MF_STRING, ID_MENU_CONTINENT_DELETE, "&Delete"); + } + // Under the continents == regions and sub-regions + else + { + if (!isFile (hItem)) + { + pMenu->AppendMenu (MF_STRING, ID_MENU_REGION_OPEN, "&Open"); + pMenu->AppendMenu (MF_STRING, ID_MENU_REGION_RENAME, "&Rename"); + pMenu->AppendMenu (MF_STRING, ID_MENU_REGION_NEW_SUBREGION, "New &SubRegion"); + pMenu->AppendMenu (MF_STRING, ID_MENU_REGION_NEW_GEORGES, "New &Form"); + pMenu->AppendMenu (MF_STRING, ID_MENU_REGION_NEW_PRIM, "New &Patatoid"); + pMenu->AppendMenu (MF_STRING, ID_MENU_REGION_DELETE, "&Delete"); + } + else + { + pMenu->AppendMenu (MF_STRING, ID_MENU_FILE_OPEN, "&Open"); + pMenu->AppendMenu (MF_STRING, ID_MENU_FILE_RENAME, "&Rename"); + pMenu->AppendMenu (MF_STRING, ID_MENU_FILE_DELETE, "&Delete"); + } + } + } + pMenu->TrackPopupMenu (TPM_LEFTALIGN | TPM_LEFTBUTTON, + r.left+point.x, r.top+point.y, this); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuNewContinent () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + pDlg->continentNew (); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuContinentDelete () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + pDlg->continentDelete ((LPCSTR)GetItemText(GetSelectedItem())); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuContinentOpen () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent (); + HTREEITEM hItem = GetSelectedItem (); + HTREEITEM hParent = GetParentItem (hItem); + + if (_LastActiveContinent != NULL) + SetItem (_LastActiveContinent, TVIF_STATE, NULL, 0, 0, 0, TVIS_BOLD, 0); + SetItem (hItem, TVIF_STATE, NULL, 0, 0, TVIS_BOLD, TVIS_BOLD, 0); + _LastActiveContinent = hItem; + pDlg->continentOpen (string((LPCSTR)GetItemText(hItem))); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuContinentProperties () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + pDlg->continentProperties ((LPCSTR)GetItemText(GetSelectedItem())); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuContinentNewRegion () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + pDlg->continentNewRegion ((LPCSTR)GetItemText(GetSelectedItem())); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuRegionOpen () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + HTREEITEM ht = GetSelectedItem(); + pDlg->regionOpen (getPath(ht)); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuRegionRename () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + HTREEITEM ht = GetSelectedItem(); + pDlg->regionRename (getPath(ht)); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuRegionNewSubRegion () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + HTREEITEM ht = GetSelectedItem(); + pDlg->regionNewSubRegion (getPath(ht)); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuRegionNewPrim () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + HTREEITEM ht = GetSelectedItem(); + pDlg->regionNewPrim (getPath(ht)); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuRegionNewGeorges () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + HTREEITEM ht = GetSelectedItem(); + pDlg->regionNewGeorges (getPath(ht)); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuRegionDelete () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + HTREEITEM ht = GetSelectedItem(); + pDlg->regionDelete (getPath(ht)); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuFileOpen () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + HTREEITEM hItem = GetSelectedItem(); + bool bFile = isFile (hItem); + if (!bFile) return; + pDlg->fileOpen (getPath(hItem)); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuFileRename () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + HTREEITEM hItem = GetSelectedItem(); + bool bFile = isFile (hItem); + if (!bFile) return; + pDlg->fileRename (getPath(hItem)); +} + +// --------------------------------------------------------------------------- +void CMasterTree::OnMenuFileDelete () +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + HTREEITEM hItem = GetSelectedItem(); + bool bFile = isFile (hItem); + if (!bFile) return; + pDlg->fileDelete (getPath(hItem)); +} + +// --------------------------------------------------------------------------- +string CMasterTree::getCurrentPath () +{ + return getPath(GetSelectedItem()); +} + +// TOOLS + +// --------------------------------------------------------------------------- +string CMasterTree::getPath (HTREEITEM ht) +{ + string sTmp = ""; + + while (ht != NULL) + { + sTmp = string("\\") + (LPCSTR)GetItemText(ht) + sTmp; + ht = GetParentItem(ht); + } + + return sTmp; +} + +// --------------------------------------------------------------------------- +HTREEITEM CMasterTree::getContinent (HTREEITEM ht) +{ + if (ht == NULL) return NULL; + if (GetParentItem(ht) == NULL) return NULL; + while (GetParentItem(GetParentItem(ht)) != NULL) + ht = GetParentItem(ht); + if (isFile(ht)) return NULL; + return ht; +} + +// --------------------------------------------------------------------------- +HTREEITEM CMasterTree::getRegion (HTREEITEM ht) +{ + if (ht == NULL) return NULL; + if (GetParentItem(ht) == NULL) return NULL; + if (GetParentItem(GetParentItem(ht)) == NULL) return NULL; + while (GetParentItem(GetParentItem(GetParentItem(ht))) != NULL) + ht = GetParentItem(ht); + if (isFile(ht)) return NULL; + return ht; +} + +// --------------------------------------------------------------------------- +bool CMasterTree::isFile (HTREEITEM ht) +{ + CMasterTreeDlg *pDlg = (CMasterTreeDlg*)GetParent(); + map::iterator it = pDlg->_Files.find (ht); + if (it != pDlg->_Files.end()) + return true; + else + return false; +} + + +///////////////////////////////////////////////////////////////////////////// +// CMasterTreeDlg dialog +///////////////////////////////////////////////////////////////////////////// + +BEGIN_MESSAGE_MAP(CMasterTreeDlg, CDialog) + //{{AFX_MSG_MAP(CMasterTreeDlg) + ON_WM_SIZE() + ON_NOTIFY(TVN_ITEMEXPANDING, IDC_TREE, OnExpanding) + //ON_NOTIFY(NM_DBLCLK, IDC_TREE, OnLDblClkTree) + ON_WM_CREATE() + ON_WM_CLOSE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + + +// --------------------------------------------------------------------------- +CMasterTreeDlg::CMasterTreeDlg () +{ + _Tree = NULL; + ContinentSortBy = 1; // 0/1 - by name + TrashSortBy = 1; // 2/3 - by date + BackupSortBy = 2; +} + +// --------------------------------------------------------------------------- +FILETIME getFileTime (const string &fname) +{ + WIN32_FIND_DATA FindFileData; + HANDLE hFind; + FILETIME ret = { 0xFFFFFFFF, 0xFFFFFFFF }; + + hFind = FindFirstFile (fname.c_str(), &FindFileData); + + if (hFind != INVALID_HANDLE_VALUE) + { + ret = FindFileData.ftLastWriteTime; + FindClose (hFind); + } + return ret; +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::parseAdd (HTREEITEM itRoot, const string &path, char SortType, int DirDepth) +{ + WIN32_FIND_DATA findData; + HANDLE hFind; + CTreeCtrl *pTree = (CTreeCtrl*)GetDlgItem(IDC_TREE); + vector SortTable; + sint32 i, j; + + char sCurDir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, sCurDir); + + if (!SetCurrentDirectory (path.c_str())) + { + SetCurrentDirectory (sCurDir); + return; + } + + hFind = FindFirstFile ("*.*", &findData); + if (hFind != INVALID_HANDLE_VALUE) + { + do + { + // Look if the name is a system directory + bool bFound = false; + for (uint32 i = 0; i < MAX_SYS_DIR; ++i) + if (stricmp (findData.cFileName, gSysDir[i]) == 0) + { + bFound = true; + break; + } + if (!bFound) // No ok lets add it + { + SortTable.push_back (findData.cFileName); + } + } + while (FindNextFile(hFind, &findData) != 0); + FindClose (hFind); + } + + if (SortTable.size() == 0) + { + SetCurrentDirectory (sCurDir); + return; + } + + if (SortType == 0) // Sort By Name increasing (z-a) + { + for (i = 0; i < (sint32)SortTable.size()-1; ++i) + for (j = i+1; j < (sint32)SortTable.size(); ++j) + if (strcmp(SortTable[i].c_str(), SortTable[j].c_str()) < 0) + { + string tmp = SortTable[i]; + SortTable[i] = SortTable[j]; + SortTable[j] = tmp; + } + } + if (SortType == 1) // Sort By Name decreasing (a-z) + { + for (i = 0; i < (sint32)SortTable.size()-1; ++i) + for (j = i+1; j < (sint32)SortTable.size(); ++j) + if (strcmp(SortTable[i].c_str(), SortTable[j].c_str()) > 0) + { + string tmp = SortTable[i]; + SortTable[i] = SortTable[j]; + SortTable[j] = tmp; + } + } + if (SortType == 2) // Sort By Date increasing + { + for (i = 0; i < (sint32)SortTable.size()-1; ++i) + { + FILETIME timeI = getFileTime (SortTable[i]); + for (j = i+1; j < (sint32)SortTable.size(); ++j) + { + FILETIME timeJ = getFileTime (SortTable[j]); + if ((timeI.dwHighDateTime < timeJ.dwHighDateTime) || + ( + (timeI.dwHighDateTime == timeJ.dwHighDateTime) && + (timeI.dwLowDateTime < timeJ.dwLowDateTime) + )) + { + string tmp = SortTable[i]; + SortTable[i] = SortTable[j]; + SortTable[j] = tmp; + timeI = timeJ; + } + } + } + } + + if (SortType == 3) // Sort By Date decreasing + { + for (i = 0; i < (sint32)SortTable.size()-1; ++i) + { + FILETIME timeI = getFileTime (SortTable[i]); + for (j = i+1; j < (sint32)SortTable.size(); ++j) + { + FILETIME timeJ = getFileTime (SortTable[j]); + if ((timeI.dwHighDateTime > timeJ.dwHighDateTime) || + ( + (timeI.dwHighDateTime == timeJ.dwHighDateTime) && + (timeI.dwLowDateTime > timeJ.dwLowDateTime) + )) + { + string tmp = SortTable[i]; + SortTable[i] = SortTable[j]; + SortTable[j] = tmp; + timeI = timeJ; + } + } + } + } + + // Put directories first ! + vector SortTable2; + for (i = 0; i < (sint32)SortTable.size(); ++i) + { + if (GetFileAttributes(SortTable[i].c_str())&FILE_ATTRIBUTE_DIRECTORY) + SortTable2.push_back(SortTable[i]); + } + for (i = 0; i < (sint32)SortTable.size(); ++i) + { + if (!(GetFileAttributes(SortTable[i].c_str())&FILE_ATTRIBUTE_DIRECTORY)) + SortTable2.push_back(SortTable[i]); + } + SortTable = SortTable2; + + // Recurse + for (i = 0; i < (sint32)SortTable.size(); ++i) + { + if (GetFileAttributes(SortTable[i].c_str())&FILE_ATTRIBUTE_DIRECTORY) + { + HTREEITEM item; + + if (DirDepth == 0) + item = pTree->InsertItem (SortTable[i].c_str(), 2, 2, itRoot); + else + item = pTree->InsertItem (SortTable[i].c_str(), 0, 0, itRoot); + string newPath = path; + if (newPath[newPath.size()-1] != '\\') + newPath += "\\"; + newPath += SortTable[i].c_str(); + parseAdd (item, newPath, SortType, DirDepth+1); + } + else + { + // Look if the name is a valid filename (look at the extension) + bool bFound = false; + for (uint32 j = 0; j < MAX_INVALID_EXT; ++j) + if (strlen(SortTable[i].c_str()) > strlen(gInvalidExt[j])) + if (stricmp(&SortTable[i].c_str()[strlen(SortTable[i].c_str())-strlen(gInvalidExt[j])], gInvalidExt[j]) == 0) + { + bFound = true; + break; + } + // If the extension is an invalid one -> Do not display file + if (!bFound) + { + HTREEITEM item = pTree->InsertItem (SortTable[i].c_str(), 1, 1, itRoot); + string sTemp = path; + if (sTemp[sTemp.size()-1] != '\\') + sTemp += "\\"; + sTemp += SortTable[i].c_str(); + _Files.insert(map::value_type(item, sTemp)); + } + + } + } + SetCurrentDirectory (sCurDir); +} + +// --------------------------------------------------------------------------- +HTREEITEM CMasterTreeDlg::activate (const std::string &name, HTREEITEM parent) +{ + // Extract the eltName + string eltName; + string resName; + uint32 i = 0; + if (name.size() == 0) return NULL; + if (name[i] == '\\') ++i; + for (; i < name.size(); ++i) + { + if (name[i] == '\\') break; + eltName += name[i]; + } + ++i; + for (; i < name.size(); ++i) + { + resName += name[i]; + } + + CTreeCtrl *pTree = (CTreeCtrl*)GetDlgItem (IDC_TREE); + HTREEITEM hChildItem = pTree->GetChildItem (parent); + bool bFound = false; + while (hChildItem != NULL) + { + if (eltName == (LPCSTR)pTree->GetItemText(hChildItem)) + { + pTree->SetItem (hChildItem, TVIF_STATE, NULL, 0, 0, TVIS_BOLD, TVIS_BOLD, 0); + pTree->Expand (hChildItem, TVE_EXPAND); + activate (resName, hChildItem); + bFound = true; + break; + } + + hChildItem = pTree->GetNextItem (hChildItem, TVGN_NEXT); + } + if (bFound) + return hChildItem; + else + return NULL; +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::update (const std::string& ContinentsPath) +{ + CMasterTree *pTree = (CMasterTree*)GetDlgItem (IDC_TREE); + string sCurPath = pTree->getCurrentPath(); + _Files.clear(); + pTree->DeleteAllItems (); + // Parse all the path + char sCurDir[MAX_PATH]; + GetCurrentDirectory (MAX_PATH, sCurDir); + parseAdd (TVI_ROOT, ContinentsPath, ContinentSortBy); + SetCurrentDirectory (sCurDir); + // Hilight active Continent + CMainFrame *pMF = (CMainFrame *)GetParent (); + activate (sCurPath, TVI_ROOT); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::DoDataExchange (CDataExchange* pDX) +{ + CDialog::DoDataExchange (pDX); + //{{AFX_DATA_MAP(CMasterTreeDlg) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + +// --------------------------------------------------------------------------- +BOOL CMasterTreeDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + _Tree = new CMasterTree; + RECT r; + r.left = r.top = 10; + r.right = r.bottom = 40; + _Tree->Create (WS_VISIBLE|WS_BORDER, r, this, IDC_TREE); + // Load image list + CImageList *pImgList = new CImageList; + pImgList->Create (16, 16, ILC_MASK, 0, 5); + pImgList->Add (AfxGetApp()->LoadIcon(IDI_FOLDER)); + pImgList->Add (AfxGetApp()->LoadIcon(IDI_FILE)); + pImgList->Add (AfxGetApp()->LoadIcon(IDI_CONTINENTS)); + pImgList->Add (AfxGetApp()->LoadIcon(IDI_BACKUP)); + pImgList->Add (AfxGetApp()->LoadIcon(IDI_TRASH)); + + _Tree->SetImageList (pImgList, TVSIL_NORMAL); + return true; +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::OnSize (UINT nType, int cx, int cy) +{ + if (_Tree) + _Tree->SetWindowPos (&wndTop, 0, 0, cx-20, cy-20, SWP_NOMOVE); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::OnExpanding (LPNMHDR pnmhdr, LRESULT *pLResult) +{ + /*CTreeCtrl *pTree = (CTreeCtrl*)GetDlgItem (IDC_TREE); + NMTREEVIEW *pnmtv = (LPNMTREEVIEW) pnmhdr; + + if ((pnmtv->itemNew.state & TVIS_EXPANDED) != 0) + { + // We want to collapse this item -> forbid it + *pLResult = true; + }*/ +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::openFile (const std::string &fname) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->openFile (fname.c_str()); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::openDir (const std::string &fname) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->openDir (fname.c_str()); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::continentNew () +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->continentNew (); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::continentDelete (const string &contName) +{ + CMainFrame *pMF = (CMainFrame*)GetParent(); + pMF->continentDelete (contName); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::continentProperties (const string &contName) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->continentProperties (contName); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::continentNewRegion (const string &contName) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->continentNewRegion (contName); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::continentOpen (const string &contName) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->continentOpen (contName); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::regionOpen (const string &path) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->regionOpen (path); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::regionRename (const string &path) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->regionRename (path); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::regionNewPrim (const string &path) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->regionNewPrim (path); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::regionNewGeorges (const string &path) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->regionNewGeorges (path); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::regionNewSubRegion (const std::string &path) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->regionNewSubRegion (path); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::regionDelete (const std::string &path) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->regionDelete (path); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::fileOpen (const std::string &sFileFullName) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->fileOpen (sFileFullName); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::fileRename (const std::string &sFileFullName) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->fileRename (sFileFullName); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::fileDelete (const std::string &sFileFullName) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->fileDelete (sFileFullName); +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::copy (const std::string &pathSrc, const std::string &pathDst) +{ + CMainFrame *pMF = (CMainFrame *)GetParent(); + pMF->copy (pathSrc, pathDst); +} + +// --------------------------------------------------------------------------- +/* +void CMasterTreeDlg::OnLDblClkTree(NMHDR* pNMHDR, LRESULT* pResult) +{ + CTreeCtrl *pTree = (CTreeCtrl*)GetDlgItem (IDC_TREE); + NMTREEVIEW *pnmtv = (LPNMTREEVIEW) pNMHDR; + HTREEITEM hItem = pTree->GetSelectedItem(); + HTREEITEM hParent = pTree->GetParentItem (hItem); + + *pResult = 0; + if (hItem != NULL) + { + map::iterator it = _Files.find (hItem); + + if (it != _Files.end()) + { + // Double click on a file open the corresponding editor + openAnyFile (it->second.c_str()); + return; + } + + if ((hParent != NULL) && (pTree->GetParentItem (hParent) == NULL)) + { + // Double click on a Continent open all editors + // Parse all files and open them in the good editor + HTREEITEM hChildItem = pTree->GetChildItem (hItem); + + while (hChildItem != NULL) + { + it = _Files.find (hChildItem); + if (it != _Files.end()) + { + openAnyFile (it->second.c_str()); + } + hChildItem = pTree->GetNextItem (hChildItem, TVGN_NEXT); + } + return; + } + } + +} +*/ +// --------------------------------------------------------------------------- +void CMasterTreeDlg::OnCancel () +{ +} + +// --------------------------------------------------------------------------- +void CMasterTreeDlg::OnOK () +{ +} + diff --git a/code/ryzom/tools/leveldesign/master/MasterTree.h b/code/ryzom/tools/leveldesign/master/MasterTree.h index e8a3c9d6c..adfbedeb0 100644 --- a/code/ryzom/tools/leveldesign/master/MasterTree.h +++ b/code/ryzom/tools/leveldesign/master/MasterTree.h @@ -1,182 +1,182 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef __MASTERTREE_H__ -#define __MASTERTREE_H__ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// MasterTree.h : header file -// - -#include -#include - -///////////////////////////////////////////////////////////////////////////// - -#define MT_SORT_BY_NAME_INC 0 -#define MT_SORT_BY_NAME_DEC 1 -#define MT_SORT_BY_DATE_INC 2 -#define MT_SORT_BY_DATE_DEC 3 - -///////////////////////////////////////////////////////////////////////////// -// CMasterTree Control -///////////////////////////////////////////////////////////////////////////// - -class CMasterTree : public CTreeCtrl -{ - - bool _LDrag; - CImageList *_DragImg; - HTREEITEM _DragItem; - HTREEITEM _LastItemSelected; - HTREEITEM _LastActiveContinent; - - UINT m_nTimerID; - UINT m_timerticks; - -public: - - CMasterTree (); - - afx_msg void OnTimer(UINT nIDEvent); - afx_msg void OnLBeginDrag (NMHDR* pNMHDR, LRESULT* pResult); - - afx_msg void OnMouseMove (UINT nFlags, CPoint point); - afx_msg void OnLButtonDown (UINT nFlags, CPoint point); - afx_msg void OnLButtonUp (UINT nFlags, CPoint point); - afx_msg void OnLButtonDblClk (UINT nFlags, CPoint point); - - afx_msg void OnRButtonDown (UINT nFlags, CPoint point); - - - // Continent menus (a level under the root) - - afx_msg void OnMenuNewContinent (); - - afx_msg void OnMenuContinentOpen (); - afx_msg void OnMenuContinentProperties (); - afx_msg void OnMenuContinentNewRegion (); - afx_msg void OnMenuContinentDelete (); - - // Regions menus (a level under the continent) - - afx_msg void OnMenuRegionOpen (); - afx_msg void OnMenuRegionRename (); - afx_msg void OnMenuRegionNewSubRegion (); - afx_msg void OnMenuRegionNewPrim (); - afx_msg void OnMenuRegionNewGeorges (); - afx_msg void OnMenuRegionDelete (); - - // File menus (a level under the Region) - - afx_msg void OnMenuFileOpen (); - afx_msg void OnMenuFileRename (); - afx_msg void OnMenuFileDelete (); - - std::string getCurrentPath (); - - DECLARE_MESSAGE_MAP() - -private: - - // TOOLS - std::string getPath (HTREEITEM ht); - HTREEITEM getContinent (HTREEITEM ht); - HTREEITEM getRegion (HTREEITEM ht); - bool isFile (HTREEITEM ht); - -}; - -///////////////////////////////////////////////////////////////////////////// -// CMasterTreeDlg Dialog -///////////////////////////////////////////////////////////////////////////// - -class CMasterTreeDlg : public CDialog -{ - CMasterTree *_Tree; - std::map _Files; - - char ContinentSortBy; // 0/1 - Sort by name increasing(z-a)/decreasing(a-z) - char TrashSortBy; // 2/3 - Sort by date increasing(new-old)/decreasing(old-new) - char BackupSortBy; - -private: - - void parseAdd (HTREEITEM itRoot, const std::string &path, char nSortType, int DirDepth = 0); - -public: - - CMasterTreeDlg(); // standard constructor - - HTREEITEM activate (const std::string& EltName, HTREEITEM parent); - void update (const std::string& ContinentsPath); - - void openFile (const std::string &fname); - void openDir (const std::string &fname); - - void continentNew (); - void sortContinentBy (int mt_sort_type); - - // Continent byPass - - void continentDelete (const std::string &Continent); - void continentProperties (const std::string &Continent); - void continentNewRegion (const std::string &Continent); - void continentOpen (const std::string &Continent); - - // Region byPass - - void regionOpen (const std::string &path); - void regionRename (const std::string &path); - void regionNewPrim (const std::string &path); - void regionNewGeorges (const std::string &path); - void regionNewSubRegion (const std::string &path); - void regionDelete (const std::string &path); - - // File byPass - - void fileOpen (const std::string &sFileFullName); - void fileRename (const std::string &sFileFullName); - void fileDelete (const std::string &sFileFullName); - - void copy (const std::string &pathSrc, const std::string &pathDst); - - enum { IDD = IDD_MASTERTREE }; - -protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - - -// Implementation -protected: - - BOOL OnInitDialog (); - void OnCancel (); - void OnOK (); - - afx_msg void OnSize (UINT nType, int cx, int cy); - afx_msg void OnExpanding (LPNMHDR pnmhdr, LRESULT *pLResult); - afx_msg void OnLDblClkTree(NMHDR* pNMHDR, LRESULT* pResult); - DECLARE_MESSAGE_MAP() - - // Friends - - friend class CMasterTree; -}; - -#endif // __MASTERTREE_H__ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef __MASTERTREE_H__ +#define __MASTERTREE_H__ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MasterTree.h : header file +// + +#include +#include + +///////////////////////////////////////////////////////////////////////////// + +#define MT_SORT_BY_NAME_INC 0 +#define MT_SORT_BY_NAME_DEC 1 +#define MT_SORT_BY_DATE_INC 2 +#define MT_SORT_BY_DATE_DEC 3 + +///////////////////////////////////////////////////////////////////////////// +// CMasterTree Control +///////////////////////////////////////////////////////////////////////////// + +class CMasterTree : public CTreeCtrl +{ + + bool _LDrag; + CImageList *_DragImg; + HTREEITEM _DragItem; + HTREEITEM _LastItemSelected; + HTREEITEM _LastActiveContinent; + + UINT m_nTimerID; + UINT m_timerticks; + +public: + + CMasterTree (); + + afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnLBeginDrag (NMHDR* pNMHDR, LRESULT* pResult); + + afx_msg void OnMouseMove (UINT nFlags, CPoint point); + afx_msg void OnLButtonDown (UINT nFlags, CPoint point); + afx_msg void OnLButtonUp (UINT nFlags, CPoint point); + afx_msg void OnLButtonDblClk (UINT nFlags, CPoint point); + + afx_msg void OnRButtonDown (UINT nFlags, CPoint point); + + + // Continent menus (a level under the root) + + afx_msg void OnMenuNewContinent (); + + afx_msg void OnMenuContinentOpen (); + afx_msg void OnMenuContinentProperties (); + afx_msg void OnMenuContinentNewRegion (); + afx_msg void OnMenuContinentDelete (); + + // Regions menus (a level under the continent) + + afx_msg void OnMenuRegionOpen (); + afx_msg void OnMenuRegionRename (); + afx_msg void OnMenuRegionNewSubRegion (); + afx_msg void OnMenuRegionNewPrim (); + afx_msg void OnMenuRegionNewGeorges (); + afx_msg void OnMenuRegionDelete (); + + // File menus (a level under the Region) + + afx_msg void OnMenuFileOpen (); + afx_msg void OnMenuFileRename (); + afx_msg void OnMenuFileDelete (); + + std::string getCurrentPath (); + + DECLARE_MESSAGE_MAP() + +private: + + // TOOLS + std::string getPath (HTREEITEM ht); + HTREEITEM getContinent (HTREEITEM ht); + HTREEITEM getRegion (HTREEITEM ht); + bool isFile (HTREEITEM ht); + +}; + +///////////////////////////////////////////////////////////////////////////// +// CMasterTreeDlg Dialog +///////////////////////////////////////////////////////////////////////////// + +class CMasterTreeDlg : public CDialog +{ + CMasterTree *_Tree; + std::map _Files; + + char ContinentSortBy; // 0/1 - Sort by name increasing(z-a)/decreasing(a-z) + char TrashSortBy; // 2/3 - Sort by date increasing(new-old)/decreasing(old-new) + char BackupSortBy; + +private: + + void parseAdd (HTREEITEM itRoot, const std::string &path, char nSortType, int DirDepth = 0); + +public: + + CMasterTreeDlg(); // standard constructor + + HTREEITEM activate (const std::string& EltName, HTREEITEM parent); + void update (const std::string& ContinentsPath); + + void openFile (const std::string &fname); + void openDir (const std::string &fname); + + void continentNew (); + void sortContinentBy (int mt_sort_type); + + // Continent byPass + + void continentDelete (const std::string &Continent); + void continentProperties (const std::string &Continent); + void continentNewRegion (const std::string &Continent); + void continentOpen (const std::string &Continent); + + // Region byPass + + void regionOpen (const std::string &path); + void regionRename (const std::string &path); + void regionNewPrim (const std::string &path); + void regionNewGeorges (const std::string &path); + void regionNewSubRegion (const std::string &path); + void regionDelete (const std::string &path); + + // File byPass + + void fileOpen (const std::string &sFileFullName); + void fileRename (const std::string &sFileFullName); + void fileDelete (const std::string &sFileFullName); + + void copy (const std::string &pathSrc, const std::string &pathDst); + + enum { IDD = IDD_MASTERTREE }; + +protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + + +// Implementation +protected: + + BOOL OnInitDialog (); + void OnCancel (); + void OnOK (); + + afx_msg void OnSize (UINT nType, int cx, int cy); + afx_msg void OnExpanding (LPNMHDR pnmhdr, LRESULT *pLResult); + afx_msg void OnLDblClkTree(NMHDR* pNMHDR, LRESULT* pResult); + DECLARE_MESSAGE_MAP() + + // Friends + + friend class CMasterTree; +}; + +#endif // __MASTERTREE_H__ diff --git a/code/ryzom/tools/leveldesign/master/NameEditDlg.cpp b/code/ryzom/tools/leveldesign/master/NameEditDlg.cpp index 86f0e5140..f40f7ac75 100644 --- a/code/ryzom/tools/leveldesign/master/NameEditDlg.cpp +++ b/code/ryzom/tools/leveldesign/master/NameEditDlg.cpp @@ -1,79 +1,79 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// NewRegion.cpp : implementation file -// - -#include "stdafx.h" -#include "master.h" -#include "NameEditDlg.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -///////////////////////////////////////////////////////////////////////////// -// CRegionPropertiesDlg dialog - - -CNameEditDlg::CNameEditDlg(CWnd* pParent /*=NULL*/) - : CDialog(CNameEditDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CRegionPropertiesDlg) - Title = _T(""); - Comment = _T(""); - Name = _T(""); - //}}AFX_DATA_INIT -} - -void CNameEditDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CRegionPropertiesDlg) - DDX_Text(pDX, IDC_EDIT_NAME, Name); - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(CNameEditDlg, CDialog) - //{{AFX_MSG_MAP(CRegionPropertiesDlg) - ON_WM_SHOWWINDOW () - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CRegionPropertiesDlg message handlers - -BOOL CNameEditDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - SetWindowText (Title); - CStatic *pS = (CStatic*)GetDlgItem (IDC_COMMENT); - pS->SetWindowText (Comment); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -void CNameEditDlg::OnShowWindow (BOOL bShow, UINT nStatus) -{ - CEdit *pEd = (CEdit*)GetDlgItem(IDC_EDIT_NAME); - pEd->SetSel (0,-1); - pEd->SetFocus (); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// NewRegion.cpp : implementation file +// + +#include "stdafx.h" +#include "master.h" +#include "NameEditDlg.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +///////////////////////////////////////////////////////////////////////////// +// CRegionPropertiesDlg dialog + + +CNameEditDlg::CNameEditDlg(CWnd* pParent /*=NULL*/) + : CDialog(CNameEditDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CRegionPropertiesDlg) + Title = _T(""); + Comment = _T(""); + Name = _T(""); + //}}AFX_DATA_INIT +} + +void CNameEditDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CRegionPropertiesDlg) + DDX_Text(pDX, IDC_EDIT_NAME, Name); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CNameEditDlg, CDialog) + //{{AFX_MSG_MAP(CRegionPropertiesDlg) + ON_WM_SHOWWINDOW () + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CRegionPropertiesDlg message handlers + +BOOL CNameEditDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + SetWindowText (Title); + CStatic *pS = (CStatic*)GetDlgItem (IDC_COMMENT); + pS->SetWindowText (Comment); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CNameEditDlg::OnShowWindow (BOOL bShow, UINT nStatus) +{ + CEdit *pEd = (CEdit*)GetDlgItem(IDC_EDIT_NAME); + pEd->SetSel (0,-1); + pEd->SetFocus (); +} diff --git a/code/ryzom/tools/leveldesign/master/NameEditDlg.h b/code/ryzom/tools/leveldesign/master/NameEditDlg.h index 39fce8ae4..5fa1e3378 100644 --- a/code/ryzom/tools/leveldesign/master/NameEditDlg.h +++ b/code/ryzom/tools/leveldesign/master/NameEditDlg.h @@ -1,62 +1,62 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef __REGION_PROPERTIES_DLG__ -#define __REGION_PROPERTIES_DLG__ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// NewRegion.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// NewRegion dialog - -class CNameEditDlg : public CDialog -{ -// Construction -public: - CNameEditDlg (CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CNewRegion) - enum { IDD = IDD_NAME_EDIT }; - CString Title; - CString Comment; - CString Name; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CNewRegion) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CNewRegion) - virtual BOOL OnInitDialog (); - afx_msg void OnShowWindow( BOOL bShow, UINT nStatus ); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -#endif // __REGION_PROPERTIES_DLG__ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef __REGION_PROPERTIES_DLG__ +#define __REGION_PROPERTIES_DLG__ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// NewRegion.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// NewRegion dialog + +class CNameEditDlg : public CDialog +{ +// Construction +public: + CNameEditDlg (CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CNewRegion) + enum { IDD = IDD_NAME_EDIT }; + CString Title; + CString Comment; + CString Name; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CNewRegion) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CNewRegion) + virtual BOOL OnInitDialog (); + afx_msg void OnShowWindow( BOOL bShow, UINT nStatus ); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +#endif // __REGION_PROPERTIES_DLG__ diff --git a/code/ryzom/tools/leveldesign/master/ReadMe.txt b/code/ryzom/tools/leveldesign/master/ReadMe.txt index 5140448d0..257cea277 100644 --- a/code/ryzom/tools/leveldesign/master/ReadMe.txt +++ b/code/ryzom/tools/leveldesign/master/ReadMe.txt @@ -1,98 +1,98 @@ -**************** -* Master Tools * -**************** - -3 Main directories : Continents / Backup / Trash ------------------------------------------------- - -A World (like Continents or Backup) is a group of directories. -Each directory is a continent. And a continent is made by a -file continent.cfg which contains basics information about the -continent. A continent contains directories which represents regions - -Example of directories - -+ Continents - + Fyros - + near_the_city - + oasis - oasis.flora - oasisflora.prim - fyros.tribe - respawn.prim - + near_holes - continent.cfg - fyros.continent - + Matis - + Tryker -+ Backup -+ Trash - - -Backup/clean : keep the most recent version of all inside the backup -including continent and tag (tags are all the Continents world at a certain date) - - - -Other launchable tools ----------------------- - -This tools regroup the 3 other tools in a common workspace. -- WorldEditor : Easily generates landscapes and primitives -- LogicEditor : Condition and trigger tools -- Georges : Edit the monsters, the primitives description and so on - -With the master tool you can export vegetable through the landscape. -Simply create a new form herited from a vegetable.dfn and edit it. -The fields are - + Include_patats A set of patats in which we will plant the "Plants" - + Exclude_patats A set of patats in which the "Plants" will never appear - + Plants A structure of plants - + Name The name of the plant - + Shape The .shape associated - + Shadow The shape that will generate the shadows on the landscape - + CollisionRadius The radius of the base of the plant (serve to plant it on the ground) - + BundingRadius The minimum radius that between the center of the plant and another plant - + Jitter_Pos The "randomness" of the position of the plants in the patat (from 0.0 (order) to 1.0 (random)) - + Scale_Min Minimum scaling for all plants ( normal scale is 1.0) - + Scale_Max Maximum scale for all plants - + Put_On_Water Do we have to put the plant on the water ? - + Water_Height If we put the plant on water at which height is the water. - + Random_Seed Number between 0 and 4,294,967,295 that initialize the random generation - - - -WorldEditor ------------ - -WorldEditor needs some directories to functionnate : -ZoneBitmaps (contains the .TGA from the max plugin) -ZoneLigos (contains the .LIGOZONE from the max plugin) -In the integrated mode (when launched from the master tool) you cannot paint zones. -This functionnality is accessible when you execute the stand alone program which is just -a DLL loader. You have access to the .prim edition of the zone and can link your primitives -to contents (vegetable plants, construction, IA zones, etc.) with the georges tool. - - - -LogicEditor ------------ - -This is a stand alone tool. It does not need any system data. - - - -Georges -------- - -Georges needs a root directory with a subdirectory called "DFN" (This directory regroups -the .DFN definition of a type class). - - - -RESTRICTIONS -************ - -Do not use prim.dfn, land.dfn nor logic.dfn in georges, else if you -instanciate those you will get xxx.logic or something like that which +**************** +* Master Tools * +**************** + +3 Main directories : Continents / Backup / Trash +------------------------------------------------ + +A World (like Continents or Backup) is a group of directories. +Each directory is a continent. And a continent is made by a +file continent.cfg which contains basics information about the +continent. A continent contains directories which represents regions + +Example of directories + ++ Continents + + Fyros + + near_the_city + + oasis + oasis.flora + oasisflora.prim + fyros.tribe + respawn.prim + + near_holes + continent.cfg + fyros.continent + + Matis + + Tryker ++ Backup ++ Trash + + +Backup/clean : keep the most recent version of all inside the backup +including continent and tag (tags are all the Continents world at a certain date) + + + +Other launchable tools +---------------------- + +This tools regroup the 3 other tools in a common workspace. +- WorldEditor : Easily generates landscapes and primitives +- LogicEditor : Condition and trigger tools +- Georges : Edit the monsters, the primitives description and so on + +With the master tool you can export vegetable through the landscape. +Simply create a new form herited from a vegetable.dfn and edit it. +The fields are + + Include_patats A set of patats in which we will plant the "Plants" + + Exclude_patats A set of patats in which the "Plants" will never appear + + Plants A structure of plants + + Name The name of the plant + + Shape The .shape associated + + Shadow The shape that will generate the shadows on the landscape + + CollisionRadius The radius of the base of the plant (serve to plant it on the ground) + + BundingRadius The minimum radius that between the center of the plant and another plant + + Jitter_Pos The "randomness" of the position of the plants in the patat (from 0.0 (order) to 1.0 (random)) + + Scale_Min Minimum scaling for all plants ( normal scale is 1.0) + + Scale_Max Maximum scale for all plants + + Put_On_Water Do we have to put the plant on the water ? + + Water_Height If we put the plant on water at which height is the water. + + Random_Seed Number between 0 and 4,294,967,295 that initialize the random generation + + + +WorldEditor +----------- + +WorldEditor needs some directories to functionnate : +ZoneBitmaps (contains the .TGA from the max plugin) +ZoneLigos (contains the .LIGOZONE from the max plugin) +In the integrated mode (when launched from the master tool) you cannot paint zones. +This functionnality is accessible when you execute the stand alone program which is just +a DLL loader. You have access to the .prim edition of the zone and can link your primitives +to contents (vegetable plants, construction, IA zones, etc.) with the georges tool. + + + +LogicEditor +----------- + +This is a stand alone tool. It does not need any system data. + + + +Georges +------- + +Georges needs a root directory with a subdirectory called "DFN" (This directory regroups +the .DFN definition of a type class). + + + +RESTRICTIONS +************ + +Do not use prim.dfn, land.dfn nor logic.dfn in georges, else if you +instanciate those you will get xxx.logic or something like that which could be not easy to differenciate from a worldeditor logic file. \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/master/StdAfx.cpp b/code/ryzom/tools/leveldesign/master/StdAfx.cpp index 16055a375..0a269b0ae 100644 --- a/code/ryzom/tools/leveldesign/master/StdAfx.cpp +++ b/code/ryzom/tools/leveldesign/master/StdAfx.cpp @@ -1,24 +1,24 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.cpp : source file that includes just the standard includes -// master.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.cpp : source file that includes just the standard includes +// master.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/code/ryzom/tools/leveldesign/master/StdAfx.h b/code/ryzom/tools/leveldesign/master/StdAfx.h index 736a3aa04..6141684dc 100644 --- a/code/ryzom/tools/leveldesign/master/StdAfx.h +++ b/code/ryzom/tools/leveldesign/master/StdAfx.h @@ -1,49 +1,49 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__9C164BA4_D949_42A3_897E_0DF639A02E19__INCLUDED_) -#define AFX_STDAFX_H__9C164BA4_D949_42A3_897E_0DF639A02E19__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#ifndef _CONSOLE - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC Automation classes -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -#endif // _CONSOLE - -#undef min -#undef max - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__9C164BA4_D949_42A3_897E_0DF639A02E19__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__9C164BA4_D949_42A3_897E_0DF639A02E19__INCLUDED_) +#define AFX_STDAFX_H__9C164BA4_D949_42A3_897E_0DF639A02E19__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef _CONSOLE + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#endif // _CONSOLE + +#undef min +#undef max + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__9C164BA4_D949_42A3_897E_0DF639A02E19__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/master/easy_cfg.cpp b/code/ryzom/tools/leveldesign/master/easy_cfg.cpp index 2b5b5d4d7..f8307de88 100644 --- a/code/ryzom/tools/leveldesign/master/easy_cfg.cpp +++ b/code/ryzom/tools/leveldesign/master/easy_cfg.cpp @@ -1,158 +1,158 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" -#include "easy_cfg.h" - -#include "nel/misc/config_file.h" - -using namespace NLMISC; -using namespace std; - -// --------------------------------------------------------------------------- -IEasyCFG::IEasyCFG() -{ - cf = NULL; - f = NULL; -} - -// --------------------------------------------------------------------------- -IEasyCFG::~IEasyCFG() -{ - if (cf != NULL) - delete cf; - cf = NULL; - if (f != NULL) - fclose(f); - f = NULL; -} - -// --------------------------------------------------------------------------- -bool IEasyCFG::openRead (const std::string &filename) -{ - try - { - FILE *fTemp = fopen (filename.c_str(), "rt"); - if (fTemp == NULL) - return false; - else - fclose(fTemp); - - cf = new CConfigFile; - cf->load (filename); - - } - catch (Exception &) - { - return false; - } - return true; -} - -// --------------------------------------------------------------------------- -bool IEasyCFG::openWrite (const std::string &filename) -{ - f = fopen (filename.c_str(), "wt"); - if (f == NULL) - return false; - return true; -} - -// --------------------------------------------------------------------------- -void IEasyCFG::close () -{ - if (cf != NULL) - delete cf; - cf = NULL; - if (f != NULL) - fclose (f); - f = NULL; -} - -// --------------------------------------------------------------------------- -sint32 IEasyCFG::getInt (const string &sVarName) -{ - if (cf == NULL) - return 0; - try - { - CConfigFile::CVar &cv = cf->getVar(sVarName); - return cv.asInt(); - } - catch (Exception &) - { - return 0; - } -} - -// --------------------------------------------------------------------------- -void IEasyCFG::putInt (const string &sVarName, sint32 sVarValue) -{ - if (f == NULL) - return; - fprintf (f, "%s = %d;\n", sVarName.c_str(), sVarValue); -} - -// --------------------------------------------------------------------------- -string IEasyCFG::getStr (const string &sVarName) -{ - if (cf == NULL) - return string(""); - try - { - CConfigFile::CVar &cv = cf->getVar(sVarName); - return cv.asString(); - } - catch (Exception &) - { - return string(""); - } -} - -// --------------------------------------------------------------------------- -void IEasyCFG::putStr (const string &sVarName, const string &sVarValue) -{ - if (f == NULL) - return; - fprintf (f, "%s = \"%s\";\n", sVarName.c_str(), sVarValue.c_str()); -} - -// --------------------------------------------------------------------------- -bool IEasyCFG::getBool (const string &sVarName) -{ - if (cf == NULL) - return false; - return (getStr (sVarName) == "true" ? true : false); -} - -// --------------------------------------------------------------------------- -void IEasyCFG::putBool (const string &sVarName, bool sVarValue) -{ - if (f == NULL) - return; - if (sVarValue) - fprintf (f, "%s = \"true\";\n", sVarName.c_str()); - else - fprintf (f, "%s = \"false\";\n", sVarName.c_str()); -} - -// --------------------------------------------------------------------------- -void IEasyCFG::putCommentLine (const std::string &sComments) -{ - if (f == NULL) - return; - fprintf (f, "// %s\n", sComments.c_str()); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" +#include "easy_cfg.h" + +#include "nel/misc/config_file.h" + +using namespace NLMISC; +using namespace std; + +// --------------------------------------------------------------------------- +IEasyCFG::IEasyCFG() +{ + cf = NULL; + f = NULL; +} + +// --------------------------------------------------------------------------- +IEasyCFG::~IEasyCFG() +{ + if (cf != NULL) + delete cf; + cf = NULL; + if (f != NULL) + fclose(f); + f = NULL; +} + +// --------------------------------------------------------------------------- +bool IEasyCFG::openRead (const std::string &filename) +{ + try + { + FILE *fTemp = fopen (filename.c_str(), "rt"); + if (fTemp == NULL) + return false; + else + fclose(fTemp); + + cf = new CConfigFile; + cf->load (filename); + + } + catch (Exception &) + { + return false; + } + return true; +} + +// --------------------------------------------------------------------------- +bool IEasyCFG::openWrite (const std::string &filename) +{ + f = fopen (filename.c_str(), "wt"); + if (f == NULL) + return false; + return true; +} + +// --------------------------------------------------------------------------- +void IEasyCFG::close () +{ + if (cf != NULL) + delete cf; + cf = NULL; + if (f != NULL) + fclose (f); + f = NULL; +} + +// --------------------------------------------------------------------------- +sint32 IEasyCFG::getInt (const string &sVarName) +{ + if (cf == NULL) + return 0; + try + { + CConfigFile::CVar &cv = cf->getVar(sVarName); + return cv.asInt(); + } + catch (Exception &) + { + return 0; + } +} + +// --------------------------------------------------------------------------- +void IEasyCFG::putInt (const string &sVarName, sint32 sVarValue) +{ + if (f == NULL) + return; + fprintf (f, "%s = %d;\n", sVarName.c_str(), sVarValue); +} + +// --------------------------------------------------------------------------- +string IEasyCFG::getStr (const string &sVarName) +{ + if (cf == NULL) + return string(""); + try + { + CConfigFile::CVar &cv = cf->getVar(sVarName); + return cv.asString(); + } + catch (Exception &) + { + return string(""); + } +} + +// --------------------------------------------------------------------------- +void IEasyCFG::putStr (const string &sVarName, const string &sVarValue) +{ + if (f == NULL) + return; + fprintf (f, "%s = \"%s\";\n", sVarName.c_str(), sVarValue.c_str()); +} + +// --------------------------------------------------------------------------- +bool IEasyCFG::getBool (const string &sVarName) +{ + if (cf == NULL) + return false; + return (getStr (sVarName) == "true" ? true : false); +} + +// --------------------------------------------------------------------------- +void IEasyCFG::putBool (const string &sVarName, bool sVarValue) +{ + if (f == NULL) + return; + if (sVarValue) + fprintf (f, "%s = \"true\";\n", sVarName.c_str()); + else + fprintf (f, "%s = \"false\";\n", sVarName.c_str()); +} + +// --------------------------------------------------------------------------- +void IEasyCFG::putCommentLine (const std::string &sComments) +{ + if (f == NULL) + return; + fprintf (f, "// %s\n", sComments.c_str()); +} diff --git a/code/ryzom/tools/leveldesign/master/easy_cfg.h b/code/ryzom/tools/leveldesign/master/easy_cfg.h index 1d117afea..e011afa84 100644 --- a/code/ryzom/tools/leveldesign/master/easy_cfg.h +++ b/code/ryzom/tools/leveldesign/master/easy_cfg.h @@ -1,58 +1,58 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef __EASY_CFG_H__ -#define __EASY_CFG_H__ - -#include -#include "nel/misc/types_nl.h" - -namespace NLMISC -{ - class CConfigFile; -} - -struct IEasyCFG -{ - - IEasyCFG (); - ~IEasyCFG (); - - bool openRead (const std::string &filename); - bool openWrite (const std::string &filename); - void close (); - - // Read/Write int - sint32 getInt (const std::string &sVarName); - void putInt (const std::string &sVarName, sint32 sVarValue); - // Read/Write string - std::string getStr (const std::string &sVarName); - void putStr (const std::string &sVarName, const std::string &sVarValue); - // Read/Write boolean - bool getBool (const std::string &sVarName); - void putBool (const std::string &sVarName, bool sVarValue); - // Put a comment line (in write mode only) - void putCommentLine (const std::string &sComments); - - virtual bool load (const std::string &filename) = 0; - virtual bool save (const std::string &filename) = 0; - - - NLMISC::CConfigFile *cf; - FILE *f; -}; - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef __EASY_CFG_H__ +#define __EASY_CFG_H__ + +#include +#include "nel/misc/types_nl.h" + +namespace NLMISC +{ + class CConfigFile; +} + +struct IEasyCFG +{ + + IEasyCFG (); + ~IEasyCFG (); + + bool openRead (const std::string &filename); + bool openWrite (const std::string &filename); + void close (); + + // Read/Write int + sint32 getInt (const std::string &sVarName); + void putInt (const std::string &sVarName, sint32 sVarValue); + // Read/Write string + std::string getStr (const std::string &sVarName); + void putStr (const std::string &sVarName, const std::string &sVarValue); + // Read/Write boolean + bool getBool (const std::string &sVarName); + void putBool (const std::string &sVarName, bool sVarValue); + // Put a comment line (in write mode only) + void putCommentLine (const std::string &sComments); + + virtual bool load (const std::string &filename) = 0; + virtual bool save (const std::string &filename) = 0; + + + NLMISC::CConfigFile *cf; + FILE *f; +}; + #endif // __EASY_CFG_H__ \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/master/master.cpp b/code/ryzom/tools/leveldesign/master/master.cpp index c02efa77c..6d2b17d92 100644 --- a/code/ryzom/tools/leveldesign/master/master.cpp +++ b/code/ryzom/tools/leveldesign/master/master.cpp @@ -1,169 +1,169 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// master.cpp : Defines the class behaviors for the application. -// - -#include "stdafx.h" -#include "master.h" - -#include "MainFrm.h" - -#ifdef _DEBUG -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif - -#ifdef NL_NEW - #undef new -#endif - -///////////////////////////////////////////////////////////////////////////// -// CMasterApp - -BEGIN_MESSAGE_MAP(CMasterApp, CWinApp) - //{{AFX_MSG_MAP(CMasterApp) - ON_COMMAND(ID_APP_ABOUT, OnAppAbout) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code! - //}}AFX_MSG_MAP - // Standard file based document commands - ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) - ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CMasterApp construction - -CMasterApp::CMasterApp() -{ - // TODO: add construction code here, - // Place all significant initialization in InitInstance - m_pMainWnd = NULL; -} - -///////////////////////////////////////////////////////////////////////////// -// The one and only CMasterApp object - -CMasterApp theApp; - -///////////////////////////////////////////////////////////////////////////// -// CMasterApp initialization - -BOOL CMasterApp::InitInstance() -{ - AfxEnableControlContainer(); - - // Standard initialization - // If you are not using these features and wish to reduce the size - // of your final executable, you should remove from the following - // the specific initialization routines you do not need. - -#ifdef _AFXDLL - Enable3dControls(); // Call this when using MFC in a shared DLL -#else - Enable3dControlsStatic(); // Call this when linking to MFC statically -#endif - - // Change the registry key under which our settings are stored. - // TODO: You should modify this string to be something appropriate - // such as the name of your company or organization. - SetRegistryKey(_T("Local AppWizard-Generated Applications")); - - LoadStdProfileSettings(); // Load standard INI file options (including MRU) - - CMainFrame *pMF = new CMainFrame(); - pMF->LoadFrame(IDR_MAINFRAME); - - m_pMainWnd = pMF; - // Parse command line for standard shell commands, DDE, file open - CCommandLineInfo cmdInfo; - ParseCommandLine(cmdInfo); - - // Dispatch commands specified on the command line - if (!ProcessShellCommand(cmdInfo)) - return FALSE; - - // The one and only window has been initialized, so show and update it. - m_pMainWnd->ShowWindow(SW_SHOW); - m_pMainWnd->UpdateWindow(); - - return TRUE; -} - -BOOL CMasterApp::PreTranslateMessage (MSG*pMsg) -{ - if (m_pMainWnd != NULL) - return ((CMainFrame*)m_pMainWnd)->PreTranslateMessage (pMsg); - return FALSE; -} - -///////////////////////////////////////////////////////////////////////////// -// CAboutDlg dialog used for App About - -class CAboutDlg : public CDialog -{ -public: - CAboutDlg(); - -// Dialog Data - //{{AFX_DATA(CAboutDlg) - enum { IDD = IDD_ABOUTBOX }; - //}}AFX_DATA - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CAboutDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - //{{AFX_MSG(CAboutDlg) - // No message handlers - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) -{ - //{{AFX_DATA_INIT(CAboutDlg) - //}}AFX_DATA_INIT -} - -void CAboutDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CAboutDlg) - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) - //{{AFX_MSG_MAP(CAboutDlg) - // No message handlers - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// App command to run the dialog -void CMasterApp::OnAppAbout() -{ - CAboutDlg aboutDlg; - aboutDlg.DoModal(); -} - -///////////////////////////////////////////////////////////////////////////// -// CMasterApp message handlers - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// master.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "master.h" + +#include "MainFrm.h" + +#ifdef _DEBUG +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +#ifdef NL_NEW + #undef new +#endif + +///////////////////////////////////////////////////////////////////////////// +// CMasterApp + +BEGIN_MESSAGE_MAP(CMasterApp, CWinApp) + //{{AFX_MSG_MAP(CMasterApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMasterApp construction + +CMasterApp::CMasterApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance + m_pMainWnd = NULL; +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CMasterApp object + +CMasterApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CMasterApp initialization + +BOOL CMasterApp::InitInstance() +{ + AfxEnableControlContainer(); + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + // Change the registry key under which our settings are stored. + // TODO: You should modify this string to be something appropriate + // such as the name of your company or organization. + SetRegistryKey(_T("Local AppWizard-Generated Applications")); + + LoadStdProfileSettings(); // Load standard INI file options (including MRU) + + CMainFrame *pMF = new CMainFrame(); + pMF->LoadFrame(IDR_MAINFRAME); + + m_pMainWnd = pMF; + // Parse command line for standard shell commands, DDE, file open + CCommandLineInfo cmdInfo; + ParseCommandLine(cmdInfo); + + // Dispatch commands specified on the command line + if (!ProcessShellCommand(cmdInfo)) + return FALSE; + + // The one and only window has been initialized, so show and update it. + m_pMainWnd->ShowWindow(SW_SHOW); + m_pMainWnd->UpdateWindow(); + + return TRUE; +} + +BOOL CMasterApp::PreTranslateMessage (MSG*pMsg) +{ + if (m_pMainWnd != NULL) + return ((CMainFrame*)m_pMainWnd)->PreTranslateMessage (pMsg); + return FALSE; +} + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + // No message handlers + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void CMasterApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////// +// CMasterApp message handlers + diff --git a/code/ryzom/tools/leveldesign/master/master.h b/code/ryzom/tools/leveldesign/master/master.h index 138a27889..d5e4dd815 100644 --- a/code/ryzom/tools/leveldesign/master/master.h +++ b/code/ryzom/tools/leveldesign/master/master.h @@ -1,66 +1,66 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// master.h : main header file for the MASTER application -// - -#if !defined(AFX_MASTER_H__D57178C3_47CE_46E4_948A_55FCB49181A9__INCLUDED_) -#define AFX_MASTER_H__D57178C3_47CE_46E4_948A_55FCB49181A9__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including this file for PCH -#endif - -#include "resource.h" // main symbols - -///////////////////////////////////////////////////////////////////////////// -// CMasterApp: -// See master.cpp for the implementation of this class -// - -class CMasterApp : public CWinApp -{ -public: - CMasterApp(); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CMasterApp) - public: - virtual BOOL InitInstance(); - virtual BOOL PreTranslateMessage(MSG*pMsg); - //}}AFX_VIRTUAL - -// Implementation - //{{AFX_MSG(CMasterApp) - afx_msg void OnAppAbout(); - // NOTE - the ClassWizard will add and remove member functions here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_MASTER_H__D57178C3_47CE_46E4_948A_55FCB49181A9__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// master.h : main header file for the MASTER application +// + +#if !defined(AFX_MASTER_H__D57178C3_47CE_46E4_948A_55FCB49181A9__INCLUDED_) +#define AFX_MASTER_H__D57178C3_47CE_46E4_948A_55FCB49181A9__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CMasterApp: +// See master.cpp for the implementation of this class +// + +class CMasterApp : public CWinApp +{ +public: + CMasterApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMasterApp) + public: + virtual BOOL InitInstance(); + virtual BOOL PreTranslateMessage(MSG*pMsg); + //}}AFX_VIRTUAL + +// Implementation + //{{AFX_MSG(CMasterApp) + afx_msg void OnAppAbout(); + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MASTER_H__D57178C3_47CE_46E4_948A_55FCB49181A9__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/master/resource.h b/code/ryzom/tools/leveldesign/master/resource.h index b40830c23..78ba79036 100644 --- a/code/ryzom/tools/leveldesign/master/resource.h +++ b/code/ryzom/tools/leveldesign/master/resource.h @@ -1,108 +1,108 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by master.rc -// -#define IDOK2 2 -#define IDOK3 3 -#define IDOK4 4 -#define IDD_ABOUTBOX 100 -#define IDR_MAINFRAME 128 -#define IDR_MASTERTYPE 129 -#define IDD_MASTERTREE 130 -#define IDI_FOLDER 131 -#define IDI_FILE 132 -#define IDD_NEWREGION 133 -#define IDI_CONTINENTS 134 -#define IDI_BACKUP 135 -#define IDI_TRASH 136 -#define IDD_CHOOSETAG 137 -#define IDD_CHOOSEDIR 138 -#define IDD_PRIMNAME 139 -#define IDD_GEORGESFORM 140 -#define IDD_EXPORTOPT 141 -#define IDD_EXPORTCB 142 -#define IDD_REGION_PROPERTIES 143 -#define IDD_NAME_EDIT 143 -#define IDD_CONTINENT_PROPERTIES 148 -#define IDC_EDIT1 1001 -#define IDC_LIST 1002 -#define IDC_EDIT_CONTINENT_NAME 1002 -#define IDC_GENERATE_LANDSCAPE 1004 -#define IDC_GENERATE_VEGETABLE 1005 -#define IDC_OUT_LANDSCAPE_DIR 1006 -#define IDC_EXPLORE_LANDSCAPE 1007 -#define IDC_OUT_VEGETABLE_DIR 1008 -#define IDC_EXPLORE_VEGETABLE 1009 -#define IDC_CONTINENTLIST 1010 -#define IDC_LAND_BANK_FILE 1011 -#define IDC_EXPLORE_LAND_BANK_FILE 1012 -#define IDC_LAND_FAR_BANK_FILE 1013 -#define IDC_EDIT_REGION_NAME 1013 -#define IDC_EDIT_NAME 1013 -#define IDC_EXPLORE_LAND_FAR_BANK_FILE 1014 -#define IDC_COMMENT 1014 -#define IDC_LAND_TILE_NOISE_DIR 1015 -#define IDC_EXPLORE_LAND_TILE_NOISE_DIR 1016 -#define IDC_BUTTON_LANDDIR 1017 -#define IDC_EDIT_DFNDIR 1018 -#define IDC_BUTTON_DFNDIR 1019 -#define IDC_EDIT_GAMEELEMDIR 1020 -#define IDC_BUTTON_GAMEELEMDIR 1021 -#define IDC_PASS 1111 -#define IDC_PROGRESS1 1112 -#define IDC_EDIT_LANDFILE 1114 -#define IDC_BUTTON_LANDFILE 1115 -#define IDC_EDIT_LANDDIR 1116 -#define ID_CONTINENT_NEW 32771 -#define ID_CONTINENT_SAVE 32773 -#define ID_OPTIONS_TREELOCK 32774 -#define ID_WINDOWS_WORLDEDITOR 32775 -#define ID_OPTIONS_SETROOT 32776 -#define ID_OPTIONS_SETCONTINENTSDIR 32776 -#define ID_CONTINENT_EMPTY_TRASH 32777 -#define ID_CONTINENT_EMPTY_BACKUP 32778 -#define ID_CONTINENT_CONTINENT_BACKUP_ALL 32779 -#define ID_CONTINENT_TRASH_CONTINENTS 32780 -#define ID_CONTINENT_RESTORE_TAG 32781 -#define ID_CONTINENT_DELETE_IN_TRASH 32782 -#define ID_CONTINENT_DELETE_IN_BACKUP 32783 -#define ID_CONTINENT_DELETE 32784 -#define ID_CONTINENT_RESTORE_FROM_TRASH 32785 -#define ID_CONTINENT_RESTORE_FROM_BACKUP 32786 -#define ID_CONTINENT_BACKUP 32787 -#define ID_WINDOWS_GEORGES 32788 -#define ID_WINDOWS_LOGICEDITOR 32789 -#define ID_CONTINENT_EXPORT 32790 -#define ID_WINDOWS_RESET 32791 -#define ID_OPTIONS_SETBACKUPDIR 32792 -#define ID_OPTIONS_SETTRASHDIR 32793 -#define ID_OPTIONS_SETDEFAULTDFNDIR 32794 -#define ID_OPTIONS_SETDEFAULTGAMEELEMDIR 32795 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 144 -#define _APS_NEXT_COMMAND_VALUE 32796 -#define _APS_NEXT_CONTROL_VALUE 1015 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by master.rc +// +#define IDOK2 2 +#define IDOK3 3 +#define IDOK4 4 +#define IDD_ABOUTBOX 100 +#define IDR_MAINFRAME 128 +#define IDR_MASTERTYPE 129 +#define IDD_MASTERTREE 130 +#define IDI_FOLDER 131 +#define IDI_FILE 132 +#define IDD_NEWREGION 133 +#define IDI_CONTINENTS 134 +#define IDI_BACKUP 135 +#define IDI_TRASH 136 +#define IDD_CHOOSETAG 137 +#define IDD_CHOOSEDIR 138 +#define IDD_PRIMNAME 139 +#define IDD_GEORGESFORM 140 +#define IDD_EXPORTOPT 141 +#define IDD_EXPORTCB 142 +#define IDD_REGION_PROPERTIES 143 +#define IDD_NAME_EDIT 143 +#define IDD_CONTINENT_PROPERTIES 148 +#define IDC_EDIT1 1001 +#define IDC_LIST 1002 +#define IDC_EDIT_CONTINENT_NAME 1002 +#define IDC_GENERATE_LANDSCAPE 1004 +#define IDC_GENERATE_VEGETABLE 1005 +#define IDC_OUT_LANDSCAPE_DIR 1006 +#define IDC_EXPLORE_LANDSCAPE 1007 +#define IDC_OUT_VEGETABLE_DIR 1008 +#define IDC_EXPLORE_VEGETABLE 1009 +#define IDC_CONTINENTLIST 1010 +#define IDC_LAND_BANK_FILE 1011 +#define IDC_EXPLORE_LAND_BANK_FILE 1012 +#define IDC_LAND_FAR_BANK_FILE 1013 +#define IDC_EDIT_REGION_NAME 1013 +#define IDC_EDIT_NAME 1013 +#define IDC_EXPLORE_LAND_FAR_BANK_FILE 1014 +#define IDC_COMMENT 1014 +#define IDC_LAND_TILE_NOISE_DIR 1015 +#define IDC_EXPLORE_LAND_TILE_NOISE_DIR 1016 +#define IDC_BUTTON_LANDDIR 1017 +#define IDC_EDIT_DFNDIR 1018 +#define IDC_BUTTON_DFNDIR 1019 +#define IDC_EDIT_GAMEELEMDIR 1020 +#define IDC_BUTTON_GAMEELEMDIR 1021 +#define IDC_PASS 1111 +#define IDC_PROGRESS1 1112 +#define IDC_EDIT_LANDFILE 1114 +#define IDC_BUTTON_LANDFILE 1115 +#define IDC_EDIT_LANDDIR 1116 +#define ID_CONTINENT_NEW 32771 +#define ID_CONTINENT_SAVE 32773 +#define ID_OPTIONS_TREELOCK 32774 +#define ID_WINDOWS_WORLDEDITOR 32775 +#define ID_OPTIONS_SETROOT 32776 +#define ID_OPTIONS_SETCONTINENTSDIR 32776 +#define ID_CONTINENT_EMPTY_TRASH 32777 +#define ID_CONTINENT_EMPTY_BACKUP 32778 +#define ID_CONTINENT_CONTINENT_BACKUP_ALL 32779 +#define ID_CONTINENT_TRASH_CONTINENTS 32780 +#define ID_CONTINENT_RESTORE_TAG 32781 +#define ID_CONTINENT_DELETE_IN_TRASH 32782 +#define ID_CONTINENT_DELETE_IN_BACKUP 32783 +#define ID_CONTINENT_DELETE 32784 +#define ID_CONTINENT_RESTORE_FROM_TRASH 32785 +#define ID_CONTINENT_RESTORE_FROM_BACKUP 32786 +#define ID_CONTINENT_BACKUP 32787 +#define ID_WINDOWS_GEORGES 32788 +#define ID_WINDOWS_LOGICEDITOR 32789 +#define ID_CONTINENT_EXPORT 32790 +#define ID_WINDOWS_RESET 32791 +#define ID_OPTIONS_SETBACKUPDIR 32792 +#define ID_OPTIONS_SETTRASHDIR 32793 +#define ID_OPTIONS_SETDEFAULTDFNDIR 32794 +#define ID_OPTIONS_SETDEFAULTGAMEELEMDIR 32795 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 144 +#define _APS_NEXT_COMMAND_VALUE 32796 +#define _APS_NEXT_CONTROL_VALUE 1015 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/AddPathDlg.cpp b/code/ryzom/tools/leveldesign/mission_compiler_fe/AddPathDlg.cpp index 77d395a2b..773f8e2ac 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/AddPathDlg.cpp +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/AddPathDlg.cpp @@ -1,53 +1,53 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// AddPathDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "mission_compiler_fe.h" -#include "AddPathDlg.h" - -///////////////////////////////////////////////////////////////////////////// -// CAddPathDlg dialog - - -CAddPathDlg::CAddPathDlg(CWnd* pParent /*=NULL*/) - : CDialog(CAddPathDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CAddPathDlg) - m_addPathLog = _T(""); - //}}AFX_DATA_INIT -} - - -void CAddPathDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CAddPathDlg) - DDX_Text(pDX, IDC_ADD_PATH, m_addPathLog); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CAddPathDlg, CDialog) - //{{AFX_MSG_MAP(CAddPathDlg) - // NOTE: the ClassWizard will add message map macros here - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CAddPathDlg message handlers +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// AddPathDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "mission_compiler_fe.h" +#include "AddPathDlg.h" + +///////////////////////////////////////////////////////////////////////////// +// CAddPathDlg dialog + + +CAddPathDlg::CAddPathDlg(CWnd* pParent /*=NULL*/) + : CDialog(CAddPathDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CAddPathDlg) + m_addPathLog = _T(""); + //}}AFX_DATA_INIT +} + + +void CAddPathDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAddPathDlg) + DDX_Text(pDX, IDC_ADD_PATH, m_addPathLog); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CAddPathDlg, CDialog) + //{{AFX_MSG_MAP(CAddPathDlg) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CAddPathDlg message handlers diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/AddPathDlg.h b/code/ryzom/tools/leveldesign/mission_compiler_fe/AddPathDlg.h index ba5b2471c..ae23fe6fa 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/AddPathDlg.h +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/AddPathDlg.h @@ -1,62 +1,62 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_ADDPATHDLG_H__794D160D_4E32_4B4C_B3D9_AE1432FFDCF8__INCLUDED_) -#define AFX_ADDPATHDLG_H__794D160D_4E32_4B4C_B3D9_AE1432FFDCF8__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// AddPathDlg.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CAddPathDlg dialog - -class CAddPathDlg : public CDialog -{ -// Construction -public: - CAddPathDlg(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CAddPathDlg) - enum { IDD = IDD_DIALOG_ADD_PATH }; - CString m_addPathLog; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CAddPathDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CAddPathDlg) - // NOTE: the ClassWizard will add member functions here - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_ADDPATHDLG_H__794D160D_4E32_4B4C_B3D9_AE1432FFDCF8__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_ADDPATHDLG_H__794D160D_4E32_4B4C_B3D9_AE1432FFDCF8__INCLUDED_) +#define AFX_ADDPATHDLG_H__794D160D_4E32_4B4C_B3D9_AE1432FFDCF8__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// AddPathDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CAddPathDlg dialog + +class CAddPathDlg : public CDialog +{ +// Construction +public: + CAddPathDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CAddPathDlg) + enum { IDD = IDD_DIALOG_ADD_PATH }; + CString m_addPathLog; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAddPathDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CAddPathDlg) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_ADDPATHDLG_H__794D160D_4E32_4B4C_B3D9_AE1432FFDCF8__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/CompilDialog.cpp b/code/ryzom/tools/leveldesign/mission_compiler_fe/CompilDialog.cpp index db005ad78..3d4a56172 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/CompilDialog.cpp +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/CompilDialog.cpp @@ -1,59 +1,59 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// CompilDialog.cpp : implementation file -// - -#include "stdafx.h" -#include "mission_compiler_fe.h" -#include "CompilDialog.h" - -///////////////////////////////////////////////////////////////////////////// -// CCompilDialog dialog - - -CCompilDialog::CCompilDialog(CWnd* pParent /*=NULL*/) - : CDialog(CCompilDialog::IDD, pParent) -{ - //{{AFX_DATA_INIT(CCompilDialog) - m_compileLog = _T(""); - //}}AFX_DATA_INIT -} - - -void CCompilDialog::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CCompilDialog) - DDX_Control(pDX, IDC_COMPIL_LOG, m_compileLogCtrl); - DDX_Control(pDX, IDOK, m_okBtn); - DDX_Text(pDX, IDC_COMPIL_LOG, m_compileLog); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CCompilDialog, CDialog) - //{{AFX_MSG_MAP(CCompilDialog) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CCompilDialog message handlers - -void CCompilDialog::OnOK() -{ - CDialog::OnOK(); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// CompilDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "mission_compiler_fe.h" +#include "CompilDialog.h" + +///////////////////////////////////////////////////////////////////////////// +// CCompilDialog dialog + + +CCompilDialog::CCompilDialog(CWnd* pParent /*=NULL*/) + : CDialog(CCompilDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CCompilDialog) + m_compileLog = _T(""); + //}}AFX_DATA_INIT +} + + +void CCompilDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCompilDialog) + DDX_Control(pDX, IDC_COMPIL_LOG, m_compileLogCtrl); + DDX_Control(pDX, IDOK, m_okBtn); + DDX_Text(pDX, IDC_COMPIL_LOG, m_compileLog); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CCompilDialog, CDialog) + //{{AFX_MSG_MAP(CCompilDialog) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CCompilDialog message handlers + +void CCompilDialog::OnOK() +{ + CDialog::OnOK(); +} diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/CompilDialog.h b/code/ryzom/tools/leveldesign/mission_compiler_fe/CompilDialog.h index b3041db03..adeaa49fc 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/CompilDialog.h +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/CompilDialog.h @@ -1,64 +1,64 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_COMPILDIALOG_H__A1192050_A0DB_4928_B153_0271CCF7DF99__INCLUDED_) -#define AFX_COMPILDIALOG_H__A1192050_A0DB_4928_B153_0271CCF7DF99__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// CompilDialog.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CCompilDialog dialog - -class CCompilDialog : public CDialog -{ -// Construction -public: - CCompilDialog(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CCompilDialog) - enum { IDD = IDD_COMPIL }; - CEdit m_compileLogCtrl; - CButton m_okBtn; - CString m_compileLog; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CCompilDialog) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CCompilDialog) - virtual void OnOK(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_COMPILDIALOG_H__A1192050_A0DB_4928_B153_0271CCF7DF99__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_COMPILDIALOG_H__A1192050_A0DB_4928_B153_0271CCF7DF99__INCLUDED_) +#define AFX_COMPILDIALOG_H__A1192050_A0DB_4928_B153_0271CCF7DF99__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// CompilDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CCompilDialog dialog + +class CCompilDialog : public CDialog +{ +// Construction +public: + CCompilDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CCompilDialog) + enum { IDD = IDD_COMPIL }; + CEdit m_compileLogCtrl; + CButton m_okBtn; + CString m_compileLog; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CCompilDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CCompilDialog) + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_COMPILDIALOG_H__A1192050_A0DB_4928_B153_0271CCF7DF99__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/Resource.h b/code/ryzom/tools/leveldesign/mission_compiler_fe/Resource.h index df9fe4995..28608ab10 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/Resource.h +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/Resource.h @@ -1,69 +1,69 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by mission_compiler_fe.rc -// -#define IDM_ABOUTBOX 0x0010 -#define IDD_ABOUTBOX 100 -#define IDS_ABOUTBOX 101 -#define IDD_MISSION_COMPILER_FE_DIALOG 102 -#define IDR_MAINFRAME 128 -#define IDD_COMPIL 129 -#define IDI_ICON_FILTER 130 -#define IDR_MENU1 131 -#define IDD_DIALOG_ADD_PATH 132 -#define IDD_DIALOG_MODE 133 -#define IDC_LIST_SRC 1000 -#define IDC_LIST_DST 1001 -#define IDC_ADD 1002 -#define IDC_REMOVE 1003 -#define IDC_REMOVE_ALL 1004 -#define IDC_ADD_ALL 1005 -#define IDC_COMPILE 1006 -#define IDC_PUBLISH 1007 -#define IDC_FILTER 1008 -#define IDC_PRIMITIVE_NAME 1009 -#define IDC_VALIDATE 1009 -#define IDC_COMPIL_LOG 1010 -#define IDC_ADD_PATH 1012 -#define ID_MODE_COMPILE 1013 -#define ID_MODE_PUBLISH 1014 -#define IDC_DATA_DIRECTORY 1015 -#define IDC_CHANGE_DIR 1016 -#define IDC_PATH_WARNING 1018 -#define IDC_CHECK_SRV1 1021 -#define IDC_CHECK_SRV2 1022 -#define IDC_CHECK_SRV3 1023 -#define IDC_CHECK_SRV4 1024 -#define IDC_CHECK_SRV5 1025 -#define IDC_CHECK_SRV6 1026 -#define IDC_CHECK_SRV7 1028 -#define IDC_CHECK_SRV8 1029 -#define ID_SPECIAL_RUNCOMPILERTEST 32771 -#define ID_SPECIAL_VALIDATE_MISSIONS 32772 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 134 -#define _APS_NEXT_COMMAND_VALUE 32773 -#define _APS_NEXT_CONTROL_VALUE 1030 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by mission_compiler_fe.rc +// +#define IDM_ABOUTBOX 0x0010 +#define IDD_ABOUTBOX 100 +#define IDS_ABOUTBOX 101 +#define IDD_MISSION_COMPILER_FE_DIALOG 102 +#define IDR_MAINFRAME 128 +#define IDD_COMPIL 129 +#define IDI_ICON_FILTER 130 +#define IDR_MENU1 131 +#define IDD_DIALOG_ADD_PATH 132 +#define IDD_DIALOG_MODE 133 +#define IDC_LIST_SRC 1000 +#define IDC_LIST_DST 1001 +#define IDC_ADD 1002 +#define IDC_REMOVE 1003 +#define IDC_REMOVE_ALL 1004 +#define IDC_ADD_ALL 1005 +#define IDC_COMPILE 1006 +#define IDC_PUBLISH 1007 +#define IDC_FILTER 1008 +#define IDC_PRIMITIVE_NAME 1009 +#define IDC_VALIDATE 1009 +#define IDC_COMPIL_LOG 1010 +#define IDC_ADD_PATH 1012 +#define ID_MODE_COMPILE 1013 +#define ID_MODE_PUBLISH 1014 +#define IDC_DATA_DIRECTORY 1015 +#define IDC_CHANGE_DIR 1016 +#define IDC_PATH_WARNING 1018 +#define IDC_CHECK_SRV1 1021 +#define IDC_CHECK_SRV2 1022 +#define IDC_CHECK_SRV3 1023 +#define IDC_CHECK_SRV4 1024 +#define IDC_CHECK_SRV5 1025 +#define IDC_CHECK_SRV6 1026 +#define IDC_CHECK_SRV7 1028 +#define IDC_CHECK_SRV8 1029 +#define ID_SPECIAL_RUNCOMPILERTEST 32771 +#define ID_SPECIAL_VALIDATE_MISSIONS 32772 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 134 +#define _APS_NEXT_COMMAND_VALUE 32773 +#define _APS_NEXT_CONTROL_VALUE 1030 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/StdAfx.cpp b/code/ryzom/tools/leveldesign/mission_compiler_fe/StdAfx.cpp index 279e79198..b9e8aedf9 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/StdAfx.cpp +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/StdAfx.cpp @@ -1,24 +1,24 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.cpp : source file that includes just the standard includes -// mission_compiler_fe.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.cpp : source file that includes just the standard includes +// mission_compiler_fe.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/StdAfx.h b/code/ryzom/tools/leveldesign/mission_compiler_fe/StdAfx.h index 40629dba3..3732ca0f8 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/StdAfx.h +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/StdAfx.h @@ -1,54 +1,54 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__79CA33FC_8CE1_4558_A98F_5AB64042C02B__INCLUDED_) -#define AFX_STDAFX_H__79CA33FC_8CE1_4558_A98F_5AB64042C02B__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#define NOMINMAX -#define _WIN32_WINNT 0x0500 - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC Automation classes -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -# include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -#include - -enum TToolMode -{ - mode_compile, - mode_publish -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - - - -#endif // !defined(AFX_STDAFX_H__79CA33FC_8CE1_4558_A98F_5AB64042C02B__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__79CA33FC_8CE1_4558_A98F_5AB64042C02B__INCLUDED_) +#define AFX_STDAFX_H__79CA33FC_8CE1_4558_A98F_5AB64042C02B__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#define NOMINMAX +#define _WIN32_WINNT 0x0500 + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +# include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include + +enum TToolMode +{ + mode_compile, + mode_publish +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + + + +#endif // !defined(AFX_STDAFX_H__79CA33FC_8CE1_4558_A98F_5AB64042C02B__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/dialog_mode.cpp b/code/ryzom/tools/leveldesign/mission_compiler_fe/dialog_mode.cpp index 7643c41cf..55b44fc8b 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/dialog_mode.cpp +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/dialog_mode.cpp @@ -1,69 +1,69 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// dialog_mode.cpp : implementation file -// - -#include "stdafx.h" -#include "mission_compiler_fe.h" -#include "dialog_mode.h" - -///////////////////////////////////////////////////////////////////////////// -// CDialogMode dialog - - -CDialogMode::CDialogMode(CWnd* pParent /*=NULL*/) - : CDialog(CDialogMode::IDD, pParent) -{ - Mode = mode_compile; - //{{AFX_DATA_INIT(CDialogMode) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - - -void CDialogMode::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CDialogMode) - // NOTE: the ClassWizard will add DDX and DDV calls here - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CDialogMode, CDialog) - //{{AFX_MSG_MAP(CDialogMode) - ON_BN_CLICKED(ID_MODE_COMPILE, OnModeCompile) - ON_BN_CLICKED(ID_MODE_PUBLISH, OnModePublish) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CDialogMode message handlers - -void CDialogMode::OnModeCompile() -{ - Mode = mode_compile; - - this->EndDialog(IDOK); -} - -void CDialogMode::OnModePublish() -{ - Mode = mode_publish; - - this->EndDialog(IDOK); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// dialog_mode.cpp : implementation file +// + +#include "stdafx.h" +#include "mission_compiler_fe.h" +#include "dialog_mode.h" + +///////////////////////////////////////////////////////////////////////////// +// CDialogMode dialog + + +CDialogMode::CDialogMode(CWnd* pParent /*=NULL*/) + : CDialog(CDialogMode::IDD, pParent) +{ + Mode = mode_compile; + //{{AFX_DATA_INIT(CDialogMode) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CDialogMode::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDialogMode) + // NOTE: the ClassWizard will add DDX and DDV calls here + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDialogMode, CDialog) + //{{AFX_MSG_MAP(CDialogMode) + ON_BN_CLICKED(ID_MODE_COMPILE, OnModeCompile) + ON_BN_CLICKED(ID_MODE_PUBLISH, OnModePublish) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDialogMode message handlers + +void CDialogMode::OnModeCompile() +{ + Mode = mode_compile; + + this->EndDialog(IDOK); +} + +void CDialogMode::OnModePublish() +{ + Mode = mode_publish; + + this->EndDialog(IDOK); +} diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/dialog_mode.h b/code/ryzom/tools/leveldesign/mission_compiler_fe/dialog_mode.h index 7d23baf85..79ba91616 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/dialog_mode.h +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/dialog_mode.h @@ -1,66 +1,66 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_DIALOG_MODE_H__2662605B_D96D_4739_9FCE_FF639513FEFD__INCLUDED_) -#define AFX_DIALOG_MODE_H__2662605B_D96D_4739_9FCE_FF639513FEFD__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// dialog_mode.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CDialogMode dialog - -class CDialogMode : public CDialog -{ -// Construction -public: - CDialogMode(CWnd* pParent = NULL); // standard constructor - - TToolMode Mode; - -// Dialog Data - //{{AFX_DATA(CDialogMode) - enum { IDD = IDD_DIALOG_MODE }; - // NOTE: the ClassWizard will add data members here - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CDialogMode) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CDialogMode) - afx_msg void OnModeCompile(); - afx_msg void OnModePublish(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_DIALOG_MODE_H__2662605B_D96D_4739_9FCE_FF639513FEFD__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_DIALOG_MODE_H__2662605B_D96D_4739_9FCE_FF639513FEFD__INCLUDED_) +#define AFX_DIALOG_MODE_H__2662605B_D96D_4739_9FCE_FF639513FEFD__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// dialog_mode.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CDialogMode dialog + +class CDialogMode : public CDialog +{ +// Construction +public: + CDialogMode(CWnd* pParent = NULL); // standard constructor + + TToolMode Mode; + +// Dialog Data + //{{AFX_DATA(CDialogMode) + enum { IDD = IDD_DIALOG_MODE }; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDialogMode) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDialogMode) + afx_msg void OnModeCompile(); + afx_msg void OnModePublish(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DIALOG_MODE_H__2662605B_D96D_4739_9FCE_FF639513FEFD__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_fe.cpp b/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_fe.cpp index 943b21d84..0bf9693cc 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_fe.cpp +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_fe.cpp @@ -1,168 +1,168 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// mission_compiler_fe.cpp : Defines the class behaviors for the application. -// - -#include "stdafx.h" -#include "mission_compiler_fe.h" -#include "mission_compiler_feDlg.h" -#include "dialog_mode.h" -#include -#include "nel/misc/debug.h" -#include "nel/misc/path.h" -#include "nel/ligo/primitive.h" -#include "nel/ligo/primitive_utils.h" -#include "nel/misc/config_file.h" -#include "../mission_compiler_lib/mission_compiler.h" - -using namespace std; - -///////////////////////////////////////////////////////////////////////////// -// CMissionCompilerFeApp - -BEGIN_MESSAGE_MAP(CMissionCompilerFeApp, CWinApp) - //{{AFX_MSG_MAP(CMissionCompilerFeApp) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code! - //}}AFX_MSG - ON_COMMAND(ID_HELP, CWinApp::OnHelp) -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CMissionCompilerFeApp construction - -CMissionCompilerFeApp::CMissionCompilerFeApp() -{ - // TODO: add construction code here, - // Place all significant initialization in InitInstance -} - -// The nel context -NLMISC::CApplicationContext AppContext; - -///////////////////////////////////////////////////////////////////////////// -// The one and only CMissionCompilerFeApp object - -CMissionCompilerFeApp theApp; - - -///////////////////////////////////////////////////////////////////////////// -// CMissionCompilerFeApp initialization - -BOOL CMissionCompilerFeApp::InitInstance() -{ - AfxEnableControlContainer(); - - // Standard initialization - // If you are not using these features and wish to reduce the size - // of your final executable, you should remove from the following - // the specific initialization routines you do not need. - -#ifdef _AFXDLL - Enable3dControls(); // Call this when using MFC in a shared DLL -#else - Enable3dControlsStatic(); // Call this when linking to MFC statically -#endif - - // look at the command line parameters for command line mode - string cmdLine = m_lpCmdLine; - if (cmdLine.find("-c") != string::npos) - { - NLMISC::createDebug(); - NLMISC::CStdDisplayer disp; - NLMISC::DebugLog->addDisplayer(&disp); - NLMISC::InfoLog->addDisplayer(&disp); - NLMISC::WarningLog->addDisplayer(&disp); - NLMISC::ErrorLog->addDisplayer(&disp); - - CMissionCompilerFeDlg dlg; - - // init the config file and other params - if (!dlg.readConfigFile()) - exit(-1); - - // get the primitive file to compile - string::size_type pos = cmdLine.find("-c"); - string fileName = cmdLine.substr(pos+2); - fileName = fileName.substr(0, fileName.find(" ")); - - if (!NLMISC::CFile::isExists(NLMISC::CPath::lookup(fileName, false, true))) - { - nlwarning("Can't find file '%s'", fileName.c_str()); - return -1; - } - - uint32 nbMission = 0; - - nlinfo("Compiling primitive file '%s' in '%s'", fileName.c_str(), NLMISC::CPath::lookup(fileName, false, true).c_str()); - NLLIGO::CPrimitives primDoc; - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = &primDoc; - NLLIGO::loadXmlPrimitiveFile(primDoc, fileName, dlg.LigoConfig); - NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; - try - { - CMissionCompiler mc; - mc.compileMissions(primDoc.RootNode, fileName); - nlinfo("Found %u valid missions",mc.getMissionsCount()); - mc.installCompiledMission(dlg.LigoConfig, fileName); - nbMission += mc.getMissionsCount(); - } - catch(EParseException e) - { - string msg; - msg + "\r\n"; - if (e.Primitive != NULL) - { - msg += "In '"+NLLIGO::buildPrimPath(e.Primitive)+"'\r\n"; - } - msg += "Error while compiling '"+fileName+"' :\r\n"+e.Why+"\r\n"; - nlwarning(msg.c_str()); - exit(-1); - } - nlinfo("Compiled and installed %u missions", nbMission); - - NLMISC::DebugLog->removeDisplayer(&disp); - NLMISC::InfoLog->removeDisplayer(&disp); - NLMISC::WarningLog->removeDisplayer(&disp); - NLMISC::ErrorLog->removeDisplayer(&disp); - - return FALSE; - } - - //CDialogMode dlgMode; - //dlgMode.DoModal(); - - CMissionCompilerFeDlg dlg; - //dlg.Mode = dlgMode.Mode; - dlg.Mode = mode_compile; - m_pMainWnd = &dlg; - int nResponse = dlg.DoModal(); - if (nResponse == IDOK) - { - // TODO: Place code here to handle when the dialog is - // dismissed with OK - } - else if (nResponse == IDCANCEL) - { - // TODO: Place code here to handle when the dialog is - // dismissed with Cancel - } - - // Since the dialog has been closed, return FALSE so that we exit the - // application, rather than start the application's message pump. - return FALSE; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// mission_compiler_fe.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "mission_compiler_fe.h" +#include "mission_compiler_feDlg.h" +#include "dialog_mode.h" +#include +#include "nel/misc/debug.h" +#include "nel/misc/path.h" +#include "nel/ligo/primitive.h" +#include "nel/ligo/primitive_utils.h" +#include "nel/misc/config_file.h" +#include "../mission_compiler_lib/mission_compiler.h" + +using namespace std; + +///////////////////////////////////////////////////////////////////////////// +// CMissionCompilerFeApp + +BEGIN_MESSAGE_MAP(CMissionCompilerFeApp, CWinApp) + //{{AFX_MSG_MAP(CMissionCompilerFeApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMissionCompilerFeApp construction + +CMissionCompilerFeApp::CMissionCompilerFeApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +// The nel context +NLMISC::CApplicationContext AppContext; + +///////////////////////////////////////////////////////////////////////////// +// The one and only CMissionCompilerFeApp object + +CMissionCompilerFeApp theApp; + + +///////////////////////////////////////////////////////////////////////////// +// CMissionCompilerFeApp initialization + +BOOL CMissionCompilerFeApp::InitInstance() +{ + AfxEnableControlContainer(); + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + // look at the command line parameters for command line mode + string cmdLine = m_lpCmdLine; + if (cmdLine.find("-c") != string::npos) + { + NLMISC::createDebug(); + NLMISC::CStdDisplayer disp; + NLMISC::DebugLog->addDisplayer(&disp); + NLMISC::InfoLog->addDisplayer(&disp); + NLMISC::WarningLog->addDisplayer(&disp); + NLMISC::ErrorLog->addDisplayer(&disp); + + CMissionCompilerFeDlg dlg; + + // init the config file and other params + if (!dlg.readConfigFile()) + exit(-1); + + // get the primitive file to compile + string::size_type pos = cmdLine.find("-c"); + string fileName = cmdLine.substr(pos+2); + fileName = fileName.substr(0, fileName.find(" ")); + + if (!NLMISC::CFile::isExists(NLMISC::CPath::lookup(fileName, false, true))) + { + nlwarning("Can't find file '%s'", fileName.c_str()); + return -1; + } + + uint32 nbMission = 0; + + nlinfo("Compiling primitive file '%s' in '%s'", fileName.c_str(), NLMISC::CPath::lookup(fileName, false, true).c_str()); + NLLIGO::CPrimitives primDoc; + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = &primDoc; + NLLIGO::loadXmlPrimitiveFile(primDoc, fileName, dlg.LigoConfig); + NLLIGO::CPrimitiveContext::instance().CurrentPrimitive = NULL; + try + { + CMissionCompiler mc; + mc.compileMissions(primDoc.RootNode, fileName); + nlinfo("Found %u valid missions",mc.getMissionsCount()); + mc.installCompiledMission(dlg.LigoConfig, fileName); + nbMission += mc.getMissionsCount(); + } + catch(EParseException e) + { + string msg; + msg + "\r\n"; + if (e.Primitive != NULL) + { + msg += "In '"+NLLIGO::buildPrimPath(e.Primitive)+"'\r\n"; + } + msg += "Error while compiling '"+fileName+"' :\r\n"+e.Why+"\r\n"; + nlwarning(msg.c_str()); + exit(-1); + } + nlinfo("Compiled and installed %u missions", nbMission); + + NLMISC::DebugLog->removeDisplayer(&disp); + NLMISC::InfoLog->removeDisplayer(&disp); + NLMISC::WarningLog->removeDisplayer(&disp); + NLMISC::ErrorLog->removeDisplayer(&disp); + + return FALSE; + } + + //CDialogMode dlgMode; + //dlgMode.DoModal(); + + CMissionCompilerFeDlg dlg; + //dlg.Mode = dlgMode.Mode; + dlg.Mode = mode_compile; + m_pMainWnd = &dlg; + int nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_fe.h b/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_fe.h index 45bb1411b..a696fa625 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_fe.h +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_fe.h @@ -1,65 +1,65 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// mission_compiler_fe.h : main header file for the MISSION_COMPILER_FE application -// - -#if !defined(AFX_MISSION_COMPILER_FE_H__BBB671A5_D31E_43CD_879A_B901DED3C746__INCLUDED_) -#define AFX_MISSION_COMPILER_FE_H__BBB671A5_D31E_43CD_879A_B901DED3C746__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including this file for PCH -#endif - -#include "resource.h" // main symbols - -///////////////////////////////////////////////////////////////////////////// -// CMissionCompilerFeApp: -// See mission_compiler_fe.cpp for the implementation of this class -// - -class CMissionCompilerFeApp : public CWinApp -{ -public: - CMissionCompilerFeApp(); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CMissionCompilerFeApp) - public: - virtual BOOL InitInstance(); - //}}AFX_VIRTUAL - -// Implementation - - //{{AFX_MSG(CMissionCompilerFeApp) - // NOTE - the ClassWizard will add and remove member functions here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_MISSION_COMPILER_FE_H__BBB671A5_D31E_43CD_879A_B901DED3C746__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// mission_compiler_fe.h : main header file for the MISSION_COMPILER_FE application +// + +#if !defined(AFX_MISSION_COMPILER_FE_H__BBB671A5_D31E_43CD_879A_B901DED3C746__INCLUDED_) +#define AFX_MISSION_COMPILER_FE_H__BBB671A5_D31E_43CD_879A_B901DED3C746__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CMissionCompilerFeApp: +// See mission_compiler_fe.cpp for the implementation of this class +// + +class CMissionCompilerFeApp : public CWinApp +{ +public: + CMissionCompilerFeApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMissionCompilerFeApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + + //{{AFX_MSG(CMissionCompilerFeApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MISSION_COMPILER_FE_H__BBB671A5_D31E_43CD_879A_B901DED3C746__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_feDlg.cpp b/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_feDlg.cpp index 738ff7bf3..dbd917b0f 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_feDlg.cpp +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_feDlg.cpp @@ -1,1029 +1,1029 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// mission_compiler_feDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "mission_compiler_fe.h" -#include "mission_compiler_feDlg.h" -#include "CompilDialog.h" - -#include "nel/misc/path.h" -#include "nel/ligo/primitive.h" -#include "../mission_compiler_lib/mission_compiler.h" -#include "nel/misc/config_file.h" -#include "AddPathDlg.h" - -using namespace NLMISC; -using namespace NLLIGO; -using namespace std; - -///////////////////////////////////////////////////////////////////////////// -// CAboutDlg dialog used for App About - -class CAboutDlg : public CDialog -{ -public: - CAboutDlg(); - -// Dialog Data - //{{AFX_DATA(CAboutDlg) - enum { IDD = IDD_ABOUTBOX }; - //}}AFX_DATA - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CAboutDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - //{{AFX_MSG(CAboutDlg) - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) -{ - //{{AFX_DATA_INIT(CAboutDlg) - //}}AFX_DATA_INIT -} - -void CAboutDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CAboutDlg) - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) - //{{AFX_MSG_MAP(CAboutDlg) - // No message handlers - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CMissionCompilerFeDlg dialog - -CMissionCompilerFeDlg::CMissionCompilerFeDlg(CWnd* pParent /*=NULL*/) - : CDialog(CMissionCompilerFeDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CMissionCompilerFeDlg) - m_filter = _T(""); - m_dataDirectory = _T(""); - //}}AFX_DATA_INIT - // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 - m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); -} - -void CMissionCompilerFeDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CMissionCompilerFeDlg) - DDX_Control(pDX, IDC_VALIDATE, m_validateBtn); - DDX_Control(pDX, IDC_COMPILE, m_compileBtn); - DDX_Control(pDX, IDC_PUBLISH, m_publishBtn); - DDX_Control(pDX, IDC_LIST_DST, m_listDst); - DDX_Control(pDX, IDC_LIST_SRC, m_listSrc); - DDX_Text(pDX, IDC_FILTER, m_filter); - DDX_Text(pDX, IDC_DATA_DIRECTORY, m_dataDirectory); - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(CMissionCompilerFeDlg, CDialog) - //{{AFX_MSG_MAP(CMissionCompilerFeDlg) - ON_WM_SYSCOMMAND() - ON_WM_PAINT() - ON_WM_QUERYDRAGICON() - ON_BN_CLICKED(IDC_ADD, OnAdd) - ON_BN_CLICKED(IDC_ADD_ALL, OnAddAll) - ON_BN_CLICKED(IDC_REMOVE, OnRemove) - ON_BN_CLICKED(IDC_REMOVE_ALL, OnRemoveAll) - ON_EN_CHANGE(IDC_FILTER, OnChangeFilter) - ON_BN_CLICKED(IDC_COMPILE, OnCompile) - ON_COMMAND(ID_SPECIAL_RUNCOMPILERTEST, OnSpecialRuncompilertest) - ON_LBN_DBLCLK(IDC_LIST_SRC, OnDblclkListSrc) - ON_LBN_DBLCLK(IDC_LIST_DST, OnDblclkListDst) - ON_BN_CLICKED(IDC_PUBLISH, OnPublish) - ON_COMMAND(ID_SPECIAL_VALIDATE_MISSIONS, OnSpecialValidateMissions) - ON_BN_CLICKED(IDC_VALIDATE, OnValidate) - ON_BN_CLICKED(IDC_CHANGE_DIR, OnChangeDir) - ON_EN_CHANGE(IDC_DATA_DIRECTORY, OnChangeDataDir) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CMissionCompilerFeDlg message handlers - -BOOL CMissionCompilerFeDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - switch(Mode) - { - case mode_publish: - m_publishBtn.EnableWindow(TRUE); - m_compileBtn.EnableWindow(FALSE); - m_validateBtn.EnableWindow(FALSE); - break; - case mode_compile: - m_publishBtn.EnableWindow(FALSE); - m_compileBtn.EnableWindow(TRUE); - m_validateBtn.EnableWindow(TRUE); - break; - - } - - // Add "About..." menu item to system menu. - // IDM_ABOUTBOX must be in the system command range. - ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); - ASSERT(IDM_ABOUTBOX < 0xF000); - - CMenu* pSysMenu = GetSystemMenu(FALSE); - if (pSysMenu != NULL) - { - CString strAboutMenu; - strAboutMenu.LoadString(IDS_ABOUTBOX); - if (!strAboutMenu.IsEmpty()) - { - pSysMenu->AppendMenu(MF_SEPARATOR); - pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); - } - } - - // Set the icon for this dialog. The framework does this automatically - // when the application's main window is not a dialog - SetIcon(m_hIcon, TRUE); // Set big icon - SetIcon(m_hIcon, FALSE); // Set small icon - - // TODO: Add extra initialization here - - if (!readConfigFile()) - return TRUE; - - // Initial Data directory - m_dataDirectory = CPath::standardizeDosPath(SearchPaths[0]).c_str(); - - // Print a warning if there is more than one path - if (SearchPaths.size() > 1) - { - CWnd* pWnd = GetDlgItem(IDC_PATH_WARNING); - pWnd->SetWindowText("Warning ! config file contains more than one path ! Only the first is shown ! "); - } - - UpdateData(FALSE); - fillSourceList(); - CenterWindow(); - ShowWindow(SW_SHOW); - updateFileList(); - - // Check if the file "tmptool.txt" exists in system temp directory - // It's that way world_editor pass arguments to the program - // The file contains a list of primitives to select - char tmpPath[MAX_PATH]; - GetEnvironmentVariable("TMP", tmpPath, MAX_PATH); - strcat(tmpPath, "\\tmptool.txt"); - - if (NLMISC::CFile::fileExists(tmpPath)) - { - FILE *f = fopen(tmpPath, "r"); - if (f == NULL) - { - nlinfo("Can't open the file for reading !\n%s", tmpPath); - return TRUE; - } - - // read the list of selected primitives from world_editor - vector files; - char filePath[MAX_PATH]; - while (fgets(filePath, MAX_PATH, f)) - { - // remove endline - filePath[strlen(filePath)-1] = '\0'; - files.push_back(filePath); - } - - fclose(f); - - // delete temp file - NLMISC::CFile::deleteFile(tmpPath); - - // Test to check if the primitive is in src list - // If it is, erase it form src and add it to dest - for (uint i=0 ; isecond; - srcPath = toUpper(CPath::standardizeDosPath(srcPath)); - files[i] = toUpper(CPath::standardizeDosPath(files[i])); - if (srcPath != files[i]) - { - ::MessageBox(NULL, "Primitive path and working directory are not the same !", - "Mission compiler", MB_OK|MB_ICONEXCLAMATION); - } - else - { - _DstList.insert(make_pair(filename, files[i])); - _SrcList.erase(filename); - } - } - else - { - char buffer[1024]; - sprintf(buffer, "Can't find primitive in the directory !\n%s\n", files[i].c_str(), m_dataDirectory); - ::MessageBox(NULL, buffer, "Mission compiler", MB_OK|MB_ICONEXCLAMATION); - } - } - - updateFileList(); - } - - return TRUE; // return TRUE unless you set the focus to a control -} - -void CMissionCompilerFeDlg::fillSourceList() -{ - CAddPathDlg addPath; - - CPath::clearMap(); - _SrcList.clear(); - - addPath.Create(IDD_DIALOG_ADD_PATH, this); - addPath.CenterWindow(); - addPath.ShowWindow(SW_SHOW); - - string log(addPath.m_addPathLog); - log += "Reading config file\r\n"; - addPath.m_addPathLog = log.c_str(); - addPath.UpdateData(FALSE); - addPath.RedrawWindow(); - - // Fill the src list with available primitives - for (uint i=0; i paths; - CPath::getFileList("primitive", paths); - - // fill the src file list - set files; - for (uint i=0; isize(); ++i) - SearchPaths.push_back(var->asString(i)); - updateSearchPath(); - } - else - { - AfxMessageBox("Can't find configuration var 'SearchPath', fatal", MB_OK); - PostQuitMessage(-1); - return false; - } - - var = cf.getVarPtr("LigoConfig"); - if (var) - LigoConfigFile = var->asString(); - else - { - AfxMessageBox("Can't find configuration var 'ligo_config', fatal", MB_OK); - PostQuitMessage(-1); - return false; - } - - var = cf.getVarPtr("DefaultFilter"); - if (var) - DefaultFilter = var->asString(); - - m_filter = DefaultFilter.c_str(); - - var = cf.getVarPtr("TestPrimitive"); - if (var) - TestPrimitive = var->asString(); - else - TestPrimitive = "test_compilateur.primitive"; - - var = cf.getVarPtr("TestPrimitiveDest"); - if (var) - TestPrimitiveDest = var->asString(); - else - TestPrimitiveDest = "test_compilateur_gn.primitive"; - - var = cf.getVarPtr("ReferenceScript"); - if (var) - ReferenceScript = var->asString(); - else - ReferenceScript = "test_compilateur.script"; - - var = cf.getVarPtr("LocalTextPath"); - if (var) - LocalTextPath = var->asString(); - - // read data to publish - CConfigFile::CVar *pathsPrim = cf.getVarPtr("ServerPathPrim"); - CConfigFile::CVar *pathsText = cf.getVarPtr("ServerPathText"); - CConfigFile::CVar *names = cf.getVarPtr("ServerName"); - if (pathsPrim && pathsText && names) - { - if ((pathsPrim->size() != names->size()) || (pathsText->size() != names->size())) - { - AfxMessageBox("Config file : ServerPathPrim, ServerPathText and ServerName are different in size !", MB_OK); - PostQuitMessage(-1); - return false; - } - - if (pathsPrim->size() > 0) - GetDlgItem(IDC_PUBLISH)->EnableWindow(TRUE); - - // activate servers if present in config file - for (uint i=0 ; isize() ; i++) - { - CWnd* pWnd = GetDlgItem(IDC_CHECK_SRV1 + i); - pWnd->EnableWindow(TRUE); - pWnd->SetWindowText(names->asString(i).c_str()); - - ServerName.push_back(names->asString(i)); - ServerPathPrim.push_back(pathsPrim->asString(i)); - ServerPathText.push_back(pathsText->asString(i)); - } - } - - // init ligo - NLLIGO::Register(); - LigoConfig.readPrimitiveClass(LigoConfigFile.c_str(), false); - CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig; - - return true; -} - -void CMissionCompilerFeDlg::updateFileList() -{ - while (m_listSrc.GetCount() != 0) - m_listSrc.DeleteString(0); - while (m_listDst.GetCount() != 0) - m_listDst.DeleteString(0); - - // fill the src list - { - TFileList::iterator first(_SrcList.begin()), last(_SrcList.end()); - for (uint i=0; first != last; ++first) - { - if (m_filter.GetLength() == 0) - m_listSrc.InsertString(i++, first->first.c_str()); - else - { - // check the filter - string filter(m_filter.LockBuffer()); - m_filter.UnlockBuffer(); - - if (first->first.find(filter) != string::npos) - m_listSrc.InsertString(i++, first->first.c_str()); - } - } - } - // fill the dst list - { - TFileList::iterator first(_DstList.begin()), last(_DstList.end()); - for (uint i=0; first != last; ++first,++i) - { - m_listDst.InsertString(i, first->first.c_str()); - } - } -} - -void CMissionCompilerFeDlg::compile(BOOL publish) -{ - CCompilDialog dlg; - dlg.Create(IDD_COMPIL, this); - EnableWindow(FALSE); - dlg.m_okBtn.EnableWindow(FALSE); - dlg.ShowWindow(SW_SHOW); - string compileLog; - uint nbMission = 0; - TFileList::iterator first(_DstList.begin()), last(_DstList.end()); - for (; first != last; ++first) - { - compileLog += "Compiling '"+first->first+"'...\r\n"; - dlg.m_compileLog = compileLog.c_str(); - dlg.UpdateData(FALSE); - dlg.RedrawWindow(); - - NLLIGO::CPrimitives primDoc; - CPrimitiveContext::instance().CurrentPrimitive = &primDoc; - NLLIGO::loadXmlPrimitiveFile(primDoc, first->second, LigoConfig); - CPrimitiveContext::instance().CurrentPrimitive = NULL; - try - { - CMissionCompiler mc; - mc.compileMissions(primDoc.RootNode, first->first); - compileLog += toString("Found %u valid missions\r\n",mc.getMissionsCount()); - dlg.m_compileLog = compileLog.c_str(); - dlg.UpdateData(FALSE); - dlg.RedrawWindow(); - mc.installCompiledMission(LigoConfig, first->first); - nbMission += mc.getMissionsCount(); - - // publish files to selected servers - if (publish) - for (uint i=0 ; ifirst+"' :\r\n"+e.Why+"\r\n"; - compileLog += msg; - dlg.m_compileLog = compileLog.c_str(); - dlg.UpdateData(FALSE); -// dlg.m_compileLogCtrl.SetSel(compileLog.size(), compileLog.size(), FALSE); - dlg.RedrawWindow(); - AfxMessageBox(msg.c_str()); - break; - } - } - compileLog += toString("\r\nCompiled and installed %u missions", nbMission); - dlg.m_compileLog = compileLog.c_str(); - dlg.UpdateData(FALSE); - dlg.m_compileLogCtrl.SetSel(compileLog.size(), compileLog.size(), FALSE); - dlg.RedrawWindow(); - - dlg.m_okBtn.EnableWindow(TRUE); - dlg.RunModalLoop(); - dlg.DestroyWindow(); - EnableWindow(TRUE); -} - -void CMissionCompilerFeDlg::OnSysCommand(UINT nID, LPARAM lParam) -{ - if ((nID & 0xFFF0) == IDM_ABOUTBOX) - { - CAboutDlg dlgAbout; - dlgAbout.DoModal(); - } - else - { - CDialog::OnSysCommand(nID, lParam); - } -} - -// If you add a minimize button to your dialog, you will need the code below -// to draw the icon. For MFC applications using the document/view model, -// this is automatically done for you by the framework. - -void CMissionCompilerFeDlg::OnPaint() -{ - if (IsIconic()) - { - CPaintDC dc(this); // device context for painting - - SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); - - // Center icon in client rectangle - int cxIcon = GetSystemMetrics(SM_CXICON); - int cyIcon = GetSystemMetrics(SM_CYICON); - CRect rect; - GetClientRect(&rect); - int x = (rect.Width() - cxIcon + 1) / 2; - int y = (rect.Height() - cyIcon + 1) / 2; - - // Draw the icon - dc.DrawIcon(x, y, m_hIcon); - } - else - { - CDialog::OnPaint(); - } -} - -// The system calls this to obtain the cursor to display while the user drags -// the minimized window. -HCURSOR CMissionCompilerFeDlg::OnQueryDragIcon() -{ - return (HCURSOR) m_hIcon; -} - -void CMissionCompilerFeDlg::OnAdd() -{ - // read all selected prim in src, move them to dst - vector sel; - sel.resize(m_listSrc.GetSelCount()); - m_listSrc.GetSelItems(sel.size(), &sel[0]); - - for (uint i=0; i sel; - sel.resize(m_listDst.GetSelCount()); - m_listDst.GetSelItems(sel.size(), &sel[0]); - - for (uint i=0; igenerateMissionScript(sourceDocName); - script += "======================================================"+NL; - script += testMission->generatePhraseFile(); - script += "======================================================"+NL; - script += testMission->generateDotScript(); - - // add the compiled in mission primitive - mc.installCompiledMission(LigoConfig, sourceDocName); - char *buffer = NULL; - CIFile dst(dstDocName); - buffer = new char[dst.getFileSize()+1]; - dst.serialBuffer((uint8*)buffer, dst.getFileSize()); - buffer[dst.getFileSize()] = 0; - script += "======================================================"+NL; - script += buffer; - delete [] buffer; - - // cleanup CR/LF with a single \n - script = script.replace(NL.c_str(), "\n"); - - char *tmp = ::getenv("TEMP"); - - FILE *fp = ::fopen((string(tmp)+"/compiled_mission.script").c_str(), "w"); - ::fwrite(script.data(), script.size(), 1, fp); - ::fclose(fp); - - system((string("\"C:\\Program Files\\Beyond Compare 2\\bc2.exe\" ")+string(tmp)+"/compiled_mission.script "+ReferenceScript).c_str()); - } - catch(EParseException e) - { - string msg = "In primitive "; - msg += buildPrimPath(e.Primitive) +" : "+e.Why; - AfxMessageBox(msg.c_str()); - } - -} - -void CValidationFile::loadMissionValidationFile(string filename) -{ - using namespace std; - - // load the configuration file - CConfigFile cf; - string pathName = CPath::lookup(filename, false); - - if (pathName.empty()) - { - nlwarning("Can't find index file '%s' in search path, no mission will be valid", filename.c_str()); - return; - } - cf.load(pathName); - - // get the variable - CConfigFile::CVar* var = cf.getVarPtr("AuthorizedStates"); - if (var) - { - for (uint i=0; isize(); ++i) - _AuthorizedStates.push_back(var->asString(i)); - } - int missionStatesFields = 3; - var = cf.getVarPtr("MissionStatesFields"); - if (var) - { - missionStatesFields = var->asInt(); - } - else - { - nlwarning("Mission validation file does not contain MissionStatesFields variable. Parsing may fail and corrupt data."); - } - var = cf.getVarPtr("MissionStates"); - if (var) - { - for (uint i=0; isize()/missionStatesFields; ++i) - { - string mission = var->asString(i*missionStatesFields); - string stateName = var->asString(i*missionStatesFields+1); - string hashKey = var->asString(i*missionStatesFields+2); - - // if (_AuthorizedStates.empty() || _AuthorizedStates.find(state)!=_AuthorizedStates.end()) - _MissionStates.insert(make_pair(mission, CMissionState(mission, stateName, hashKey))); - } - } -} - -void CValidationFile::saveMissionValidationFile(string filename) -{ - using namespace std; - - // load the configuration file - string pathName = CPath::lookup(filename, false); - - if (pathName.empty()) - { - nlwarning("Can't find index file '%s' in search path, no mission will be valid", filename.c_str()); - return; - } - FILE* file = fopen(pathName.c_str(), "w"); - nlassert(file!=NULL); - - // AuthorizedStates - fprintf(file, "%s", - "// AuthorizedStates contains the list of authorized states. EGS mission\n" - "// manager can accept any number of states. Default state is the first one.\n" - "AuthorizedStates = {\n"); - deque::iterator itAuth, itAuthEnd = _AuthorizedStates.end(); - for (itAuth=_AuthorizedStates.begin(); itAuth!=itAuthEnd; ++itAuth) - fprintf(file, "\t\"%s\",\n", itAuth->c_str()); - fprintf(file, "%s", "};\n\n"); - - // MissionStatesFields - fprintf(file, "%s", - "// MissionStatesFields contains the number of fields in MissionStates, for\n" - "// future compatibility purpose.\n" - "MissionStatesFields = "); - fprintf(file, "%d", 3); // 3 fields: name, state, hash key - fprintf(file, "%s", ";\n\n"); - - // MissionStates - fprintf(file, "%s", - "// MissionStates contains a list of mission with for each the state of the\n" - "// mission and its hash key. The tool will add new missions with the default\n" - "// state. It will flag missions with a modified hash key with default state to\n" - "// prevent untested modified missions to be published.\n" - "// :NOTE: You can add a field to this structure without the need to modify EGS\n" - "// code. Simply update MissionStatesFields.\n" - "MissionStates = {\n"); - TMissionStateContainer::iterator itMission, itMissionEnd = _MissionStates.end(); - for (itMission=_MissionStates.begin(); itMission!=itMissionEnd; ++itMission) - fprintf(file, "\t%-42s %-12s \"%s\",\n", ("\""+itMission->second.name+"\",").c_str(), ("\""+itMission->second.state+"\",").c_str(), itMission->second.hashKey.c_str()); - fprintf(file, "};\n\n"); - - fclose(file); -} - -// :NOTE: This function exists in mission_template.cpp. If you change it here modify the other file. -std::string buildHashKey(std::string const& content) -{ - uint32 sum = 0; - size_t size = content.length()/4; - for (size_t i=0; i>1 | 0x80000000; - else - sum = sum>>1; - } - return NLMISC::toString("0x%08X", sum); -} - -bool CMission::parsePrim(NLLIGO::IPrimitive const* prim) -{ - // init default values - vector* params; - // get the mission script - if (!prim->getPropertyByName("script", params) || !params) - { - nlwarning("ERROR : cant find mission script!!!!!!"); - return false; - } - - // parse them - string content; - vector::iterator itParam, itParamEnd = params->end(); - for (itParam=params->begin(); itParam!=itParamEnd; ++itParam) - { - content += *itParam + "\n"; - } - hashKey = buildHashKey(content); - return true; -} - -void CMissionCompilerFeDlg::OnSpecialValidateMissions() -{ - CCompilDialog dlg; - dlg.Create(IDD_COMPIL, this); - EnableWindow(FALSE); - dlg.m_okBtn.EnableWindow(FALSE); - dlg.ShowWindow(SW_SHOW); - string compileLog; - - // Load existing validation - CValidationFile validation; - validation.loadMissionValidationFile("mission_validation.cfg"); - // Find real paths - typedef map TFileContainer; - TFileContainer files; - TFileList::iterator itDst, itDstEnd = _DstList.end(); - for (itDst=_DstList.begin(); itDst!=itDstEnd; ++itDst) - files.insert(make_pair(itDst->first, itDst->second)); - - // Parse primitives to get missions - TFileContainer::iterator itFile, itFileEnd = files.end(); - for (itFile=files.begin(); itFile!=itFileEnd; ++itFile) - { - compileLog += "Parsing '"+itFile->first+"'...\r\n"; - dlg.m_compileLog = compileLog.c_str(); - dlg.UpdateData(FALSE); - dlg.RedrawWindow(); - - string filename = itFile->second; - - TMissionContainer missions; - - // Load primitive - NLLIGO::CPrimitives primDoc; - CPrimitiveContext::instance().CurrentPrimitive = &primDoc; - NLLIGO::loadXmlPrimitiveFile(primDoc, filename, LigoConfig); - CPrimitiveContext::instance().CurrentPrimitive = NULL; - parsePrimForMissions(primDoc.RootNode, missions); - - // Parse missions to check modification - std::map::iterator itMission, itMissionEnd = missions.end(); - for (itMission=missions.begin(); itMission!=itMissionEnd; ++itMission) - { - CValidationFile::TMissionStateContainer::iterator itMissionValidation = validation._MissionStates.find(itMission->first); - if (itMissionValidation!=validation._MissionStates.end()) - { - // Mission already registered, check hash key - if (itMissionValidation->second.hashKey!=itMission->second.hashKey) - { - itMissionValidation->second.hashKey = itMission->second.hashKey; - itMissionValidation->second.state = validation.defaultState(); - } - } - else - { - // New mission - validation.insertMission(itMission->first, itMission->second.hashKey); - } - compileLog += "Mission: '"+itMission->first+"->"+itMission->second.hashKey+"\r\n"; - dlg.m_compileLog = compileLog.c_str(); - dlg.UpdateData(FALSE); - dlg.RedrawWindow(); - } - } - validation.saveMissionValidationFile("mission_validation.cfg"); - - compileLog += toString("Validation finished"); - dlg.m_compileLog = compileLog.c_str(); - dlg.UpdateData(FALSE); - dlg.m_compileLogCtrl.SetSel(compileLog.size(), compileLog.size(), FALSE); - dlg.RedrawWindow(); - - dlg.m_okBtn.EnableWindow(TRUE); - dlg.RunModalLoop(); - dlg.DestroyWindow(); - EnableWindow(TRUE); -} - -bool CMissionCompilerFeDlg::parsePrimForMissions(NLLIGO::IPrimitive const* prim, TMissionContainer& missions) -{ - string value; - // if the node is a mission parse it - if (prim->getPropertyByName("class",value) && !nlstricmp(value.c_str(),"mission") ) - { - string name; - prim->getPropertyByName("name",name); - - // parse the mission and put it in our manager - CMission mission(value, ""); - if (!mission.parsePrim(prim) ) - { - nlwarning("Previous errors in mission '%s'", name.c_str()); - // MissionLog.Log->displayNL(" \n"); - return false; - } - missions.insert(make_pair(name, mission)); - return true; - } - else - { - //this is not a mission node, so lookup recursively in the children - bool ok = true; - for (uint i=0;igetNumChildren();++i) - { - const IPrimitive *child; - if ( !prim->getChild(child,i) || !parsePrimForMissions(child, missions) ) - ok = false; - } - return ok; - } -} - -void CMissionCompilerFeDlg::OnValidate() -{ - OnSpecialValidateMissions(); -} - -void CMissionCompilerFeDlg::OnPublish() -{ - compile(TRUE); -} - -void CMissionCompilerFeDlg::updateSearchPath() -{ - for (uint i=0; im_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp; - bi.lpszTitle = "Choose the data directory"; - bi.ulFlags = 0; - bi.lpfn = dataDirBrowseCallbackProc; - - char sDir[512]; - strcpy(sDir, m_dataDirectory); - bi.lParam = (LPARAM)sDir; - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - - if (SHGetPathFromIDList(pidl, str)) - { - m_dataDirectory = str; - SearchPaths[0] = str; - fillSourceList(); - updateFileList(); - UpdateData(FALSE); - } -} - -void CMissionCompilerFeDlg::OnChangeDataDir() -{ - UpdateData(TRUE); - SearchPaths[0] = m_dataDirectory; - fillSourceList(); - updateFileList(); - UpdateData(FALSE); +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// mission_compiler_feDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "mission_compiler_fe.h" +#include "mission_compiler_feDlg.h" +#include "CompilDialog.h" + +#include "nel/misc/path.h" +#include "nel/ligo/primitive.h" +#include "../mission_compiler_lib/mission_compiler.h" +#include "nel/misc/config_file.h" +#include "AddPathDlg.h" + +using namespace NLMISC; +using namespace NLLIGO; +using namespace std; + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMissionCompilerFeDlg dialog + +CMissionCompilerFeDlg::CMissionCompilerFeDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMissionCompilerFeDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMissionCompilerFeDlg) + m_filter = _T(""); + m_dataDirectory = _T(""); + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void CMissionCompilerFeDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMissionCompilerFeDlg) + DDX_Control(pDX, IDC_VALIDATE, m_validateBtn); + DDX_Control(pDX, IDC_COMPILE, m_compileBtn); + DDX_Control(pDX, IDC_PUBLISH, m_publishBtn); + DDX_Control(pDX, IDC_LIST_DST, m_listDst); + DDX_Control(pDX, IDC_LIST_SRC, m_listSrc); + DDX_Text(pDX, IDC_FILTER, m_filter); + DDX_Text(pDX, IDC_DATA_DIRECTORY, m_dataDirectory); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CMissionCompilerFeDlg, CDialog) + //{{AFX_MSG_MAP(CMissionCompilerFeDlg) + ON_WM_SYSCOMMAND() + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + ON_BN_CLICKED(IDC_ADD, OnAdd) + ON_BN_CLICKED(IDC_ADD_ALL, OnAddAll) + ON_BN_CLICKED(IDC_REMOVE, OnRemove) + ON_BN_CLICKED(IDC_REMOVE_ALL, OnRemoveAll) + ON_EN_CHANGE(IDC_FILTER, OnChangeFilter) + ON_BN_CLICKED(IDC_COMPILE, OnCompile) + ON_COMMAND(ID_SPECIAL_RUNCOMPILERTEST, OnSpecialRuncompilertest) + ON_LBN_DBLCLK(IDC_LIST_SRC, OnDblclkListSrc) + ON_LBN_DBLCLK(IDC_LIST_DST, OnDblclkListDst) + ON_BN_CLICKED(IDC_PUBLISH, OnPublish) + ON_COMMAND(ID_SPECIAL_VALIDATE_MISSIONS, OnSpecialValidateMissions) + ON_BN_CLICKED(IDC_VALIDATE, OnValidate) + ON_BN_CLICKED(IDC_CHANGE_DIR, OnChangeDir) + ON_EN_CHANGE(IDC_DATA_DIRECTORY, OnChangeDataDir) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMissionCompilerFeDlg message handlers + +BOOL CMissionCompilerFeDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + switch(Mode) + { + case mode_publish: + m_publishBtn.EnableWindow(TRUE); + m_compileBtn.EnableWindow(FALSE); + m_validateBtn.EnableWindow(FALSE); + break; + case mode_compile: + m_publishBtn.EnableWindow(FALSE); + m_compileBtn.EnableWindow(TRUE); + m_validateBtn.EnableWindow(TRUE); + break; + + } + + // Add "About..." menu item to system menu. + // IDM_ABOUTBOX must be in the system command range. + ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); + ASSERT(IDM_ABOUTBOX < 0xF000); + + CMenu* pSysMenu = GetSystemMenu(FALSE); + if (pSysMenu != NULL) + { + CString strAboutMenu; + strAboutMenu.LoadString(IDS_ABOUTBOX); + if (!strAboutMenu.IsEmpty()) + { + pSysMenu->AppendMenu(MF_SEPARATOR); + pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); + } + } + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // TODO: Add extra initialization here + + if (!readConfigFile()) + return TRUE; + + // Initial Data directory + m_dataDirectory = CPath::standardizeDosPath(SearchPaths[0]).c_str(); + + // Print a warning if there is more than one path + if (SearchPaths.size() > 1) + { + CWnd* pWnd = GetDlgItem(IDC_PATH_WARNING); + pWnd->SetWindowText("Warning ! config file contains more than one path ! Only the first is shown ! "); + } + + UpdateData(FALSE); + fillSourceList(); + CenterWindow(); + ShowWindow(SW_SHOW); + updateFileList(); + + // Check if the file "tmptool.txt" exists in system temp directory + // It's that way world_editor pass arguments to the program + // The file contains a list of primitives to select + char tmpPath[MAX_PATH]; + GetEnvironmentVariable("TMP", tmpPath, MAX_PATH); + strcat(tmpPath, "\\tmptool.txt"); + + if (NLMISC::CFile::fileExists(tmpPath)) + { + FILE *f = fopen(tmpPath, "r"); + if (f == NULL) + { + nlinfo("Can't open the file for reading !\n%s", tmpPath); + return TRUE; + } + + // read the list of selected primitives from world_editor + vector files; + char filePath[MAX_PATH]; + while (fgets(filePath, MAX_PATH, f)) + { + // remove endline + filePath[strlen(filePath)-1] = '\0'; + files.push_back(filePath); + } + + fclose(f); + + // delete temp file + NLMISC::CFile::deleteFile(tmpPath); + + // Test to check if the primitive is in src list + // If it is, erase it form src and add it to dest + for (uint i=0 ; isecond; + srcPath = toUpper(CPath::standardizeDosPath(srcPath)); + files[i] = toUpper(CPath::standardizeDosPath(files[i])); + if (srcPath != files[i]) + { + ::MessageBox(NULL, "Primitive path and working directory are not the same !", + "Mission compiler", MB_OK|MB_ICONEXCLAMATION); + } + else + { + _DstList.insert(make_pair(filename, files[i])); + _SrcList.erase(filename); + } + } + else + { + char buffer[1024]; + sprintf(buffer, "Can't find primitive in the directory !\n%s\n", files[i].c_str(), m_dataDirectory); + ::MessageBox(NULL, buffer, "Mission compiler", MB_OK|MB_ICONEXCLAMATION); + } + } + + updateFileList(); + } + + return TRUE; // return TRUE unless you set the focus to a control +} + +void CMissionCompilerFeDlg::fillSourceList() +{ + CAddPathDlg addPath; + + CPath::clearMap(); + _SrcList.clear(); + + addPath.Create(IDD_DIALOG_ADD_PATH, this); + addPath.CenterWindow(); + addPath.ShowWindow(SW_SHOW); + + string log(addPath.m_addPathLog); + log += "Reading config file\r\n"; + addPath.m_addPathLog = log.c_str(); + addPath.UpdateData(FALSE); + addPath.RedrawWindow(); + + // Fill the src list with available primitives + for (uint i=0; i paths; + CPath::getFileList("primitive", paths); + + // fill the src file list + set files; + for (uint i=0; isize(); ++i) + SearchPaths.push_back(var->asString(i)); + updateSearchPath(); + } + else + { + AfxMessageBox("Can't find configuration var 'SearchPath', fatal", MB_OK); + PostQuitMessage(-1); + return false; + } + + var = cf.getVarPtr("LigoConfig"); + if (var) + LigoConfigFile = var->asString(); + else + { + AfxMessageBox("Can't find configuration var 'ligo_config', fatal", MB_OK); + PostQuitMessage(-1); + return false; + } + + var = cf.getVarPtr("DefaultFilter"); + if (var) + DefaultFilter = var->asString(); + + m_filter = DefaultFilter.c_str(); + + var = cf.getVarPtr("TestPrimitive"); + if (var) + TestPrimitive = var->asString(); + else + TestPrimitive = "test_compilateur.primitive"; + + var = cf.getVarPtr("TestPrimitiveDest"); + if (var) + TestPrimitiveDest = var->asString(); + else + TestPrimitiveDest = "test_compilateur_gn.primitive"; + + var = cf.getVarPtr("ReferenceScript"); + if (var) + ReferenceScript = var->asString(); + else + ReferenceScript = "test_compilateur.script"; + + var = cf.getVarPtr("LocalTextPath"); + if (var) + LocalTextPath = var->asString(); + + // read data to publish + CConfigFile::CVar *pathsPrim = cf.getVarPtr("ServerPathPrim"); + CConfigFile::CVar *pathsText = cf.getVarPtr("ServerPathText"); + CConfigFile::CVar *names = cf.getVarPtr("ServerName"); + if (pathsPrim && pathsText && names) + { + if ((pathsPrim->size() != names->size()) || (pathsText->size() != names->size())) + { + AfxMessageBox("Config file : ServerPathPrim, ServerPathText and ServerName are different in size !", MB_OK); + PostQuitMessage(-1); + return false; + } + + if (pathsPrim->size() > 0) + GetDlgItem(IDC_PUBLISH)->EnableWindow(TRUE); + + // activate servers if present in config file + for (uint i=0 ; isize() ; i++) + { + CWnd* pWnd = GetDlgItem(IDC_CHECK_SRV1 + i); + pWnd->EnableWindow(TRUE); + pWnd->SetWindowText(names->asString(i).c_str()); + + ServerName.push_back(names->asString(i)); + ServerPathPrim.push_back(pathsPrim->asString(i)); + ServerPathText.push_back(pathsText->asString(i)); + } + } + + // init ligo + NLLIGO::Register(); + LigoConfig.readPrimitiveClass(LigoConfigFile.c_str(), false); + CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig; + + return true; +} + +void CMissionCompilerFeDlg::updateFileList() +{ + while (m_listSrc.GetCount() != 0) + m_listSrc.DeleteString(0); + while (m_listDst.GetCount() != 0) + m_listDst.DeleteString(0); + + // fill the src list + { + TFileList::iterator first(_SrcList.begin()), last(_SrcList.end()); + for (uint i=0; first != last; ++first) + { + if (m_filter.GetLength() == 0) + m_listSrc.InsertString(i++, first->first.c_str()); + else + { + // check the filter + string filter(m_filter.LockBuffer()); + m_filter.UnlockBuffer(); + + if (first->first.find(filter) != string::npos) + m_listSrc.InsertString(i++, first->first.c_str()); + } + } + } + // fill the dst list + { + TFileList::iterator first(_DstList.begin()), last(_DstList.end()); + for (uint i=0; first != last; ++first,++i) + { + m_listDst.InsertString(i, first->first.c_str()); + } + } +} + +void CMissionCompilerFeDlg::compile(BOOL publish) +{ + CCompilDialog dlg; + dlg.Create(IDD_COMPIL, this); + EnableWindow(FALSE); + dlg.m_okBtn.EnableWindow(FALSE); + dlg.ShowWindow(SW_SHOW); + string compileLog; + uint nbMission = 0; + TFileList::iterator first(_DstList.begin()), last(_DstList.end()); + for (; first != last; ++first) + { + compileLog += "Compiling '"+first->first+"'...\r\n"; + dlg.m_compileLog = compileLog.c_str(); + dlg.UpdateData(FALSE); + dlg.RedrawWindow(); + + NLLIGO::CPrimitives primDoc; + CPrimitiveContext::instance().CurrentPrimitive = &primDoc; + NLLIGO::loadXmlPrimitiveFile(primDoc, first->second, LigoConfig); + CPrimitiveContext::instance().CurrentPrimitive = NULL; + try + { + CMissionCompiler mc; + mc.compileMissions(primDoc.RootNode, first->first); + compileLog += toString("Found %u valid missions\r\n",mc.getMissionsCount()); + dlg.m_compileLog = compileLog.c_str(); + dlg.UpdateData(FALSE); + dlg.RedrawWindow(); + mc.installCompiledMission(LigoConfig, first->first); + nbMission += mc.getMissionsCount(); + + // publish files to selected servers + if (publish) + for (uint i=0 ; ifirst+"' :\r\n"+e.Why+"\r\n"; + compileLog += msg; + dlg.m_compileLog = compileLog.c_str(); + dlg.UpdateData(FALSE); +// dlg.m_compileLogCtrl.SetSel(compileLog.size(), compileLog.size(), FALSE); + dlg.RedrawWindow(); + AfxMessageBox(msg.c_str()); + break; + } + } + compileLog += toString("\r\nCompiled and installed %u missions", nbMission); + dlg.m_compileLog = compileLog.c_str(); + dlg.UpdateData(FALSE); + dlg.m_compileLogCtrl.SetSel(compileLog.size(), compileLog.size(), FALSE); + dlg.RedrawWindow(); + + dlg.m_okBtn.EnableWindow(TRUE); + dlg.RunModalLoop(); + dlg.DestroyWindow(); + EnableWindow(TRUE); +} + +void CMissionCompilerFeDlg::OnSysCommand(UINT nID, LPARAM lParam) +{ + if ((nID & 0xFFF0) == IDM_ABOUTBOX) + { + CAboutDlg dlgAbout; + dlgAbout.DoModal(); + } + else + { + CDialog::OnSysCommand(nID, lParam); + } +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void CMissionCompilerFeDlg::OnPaint() +{ + if (IsIconic()) + { + CPaintDC dc(this); // device context for painting + + SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); + + // Center icon in client rectangle + int cxIcon = GetSystemMetrics(SM_CXICON); + int cyIcon = GetSystemMetrics(SM_CYICON); + CRect rect; + GetClientRect(&rect); + int x = (rect.Width() - cxIcon + 1) / 2; + int y = (rect.Height() - cyIcon + 1) / 2; + + // Draw the icon + dc.DrawIcon(x, y, m_hIcon); + } + else + { + CDialog::OnPaint(); + } +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR CMissionCompilerFeDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +void CMissionCompilerFeDlg::OnAdd() +{ + // read all selected prim in src, move them to dst + vector sel; + sel.resize(m_listSrc.GetSelCount()); + m_listSrc.GetSelItems(sel.size(), &sel[0]); + + for (uint i=0; i sel; + sel.resize(m_listDst.GetSelCount()); + m_listDst.GetSelItems(sel.size(), &sel[0]); + + for (uint i=0; igenerateMissionScript(sourceDocName); + script += "======================================================"+NL; + script += testMission->generatePhraseFile(); + script += "======================================================"+NL; + script += testMission->generateDotScript(); + + // add the compiled in mission primitive + mc.installCompiledMission(LigoConfig, sourceDocName); + char *buffer = NULL; + CIFile dst(dstDocName); + buffer = new char[dst.getFileSize()+1]; + dst.serialBuffer((uint8*)buffer, dst.getFileSize()); + buffer[dst.getFileSize()] = 0; + script += "======================================================"+NL; + script += buffer; + delete [] buffer; + + // cleanup CR/LF with a single \n + script = script.replace(NL.c_str(), "\n"); + + char *tmp = ::getenv("TEMP"); + + FILE *fp = ::fopen((string(tmp)+"/compiled_mission.script").c_str(), "w"); + ::fwrite(script.data(), script.size(), 1, fp); + ::fclose(fp); + + system((string("\"C:\\Program Files\\Beyond Compare 2\\bc2.exe\" ")+string(tmp)+"/compiled_mission.script "+ReferenceScript).c_str()); + } + catch(EParseException e) + { + string msg = "In primitive "; + msg += buildPrimPath(e.Primitive) +" : "+e.Why; + AfxMessageBox(msg.c_str()); + } + +} + +void CValidationFile::loadMissionValidationFile(string filename) +{ + using namespace std; + + // load the configuration file + CConfigFile cf; + string pathName = CPath::lookup(filename, false); + + if (pathName.empty()) + { + nlwarning("Can't find index file '%s' in search path, no mission will be valid", filename.c_str()); + return; + } + cf.load(pathName); + + // get the variable + CConfigFile::CVar* var = cf.getVarPtr("AuthorizedStates"); + if (var) + { + for (uint i=0; isize(); ++i) + _AuthorizedStates.push_back(var->asString(i)); + } + int missionStatesFields = 3; + var = cf.getVarPtr("MissionStatesFields"); + if (var) + { + missionStatesFields = var->asInt(); + } + else + { + nlwarning("Mission validation file does not contain MissionStatesFields variable. Parsing may fail and corrupt data."); + } + var = cf.getVarPtr("MissionStates"); + if (var) + { + for (uint i=0; isize()/missionStatesFields; ++i) + { + string mission = var->asString(i*missionStatesFields); + string stateName = var->asString(i*missionStatesFields+1); + string hashKey = var->asString(i*missionStatesFields+2); + + // if (_AuthorizedStates.empty() || _AuthorizedStates.find(state)!=_AuthorizedStates.end()) + _MissionStates.insert(make_pair(mission, CMissionState(mission, stateName, hashKey))); + } + } +} + +void CValidationFile::saveMissionValidationFile(string filename) +{ + using namespace std; + + // load the configuration file + string pathName = CPath::lookup(filename, false); + + if (pathName.empty()) + { + nlwarning("Can't find index file '%s' in search path, no mission will be valid", filename.c_str()); + return; + } + FILE* file = fopen(pathName.c_str(), "w"); + nlassert(file!=NULL); + + // AuthorizedStates + fprintf(file, "%s", + "// AuthorizedStates contains the list of authorized states. EGS mission\n" + "// manager can accept any number of states. Default state is the first one.\n" + "AuthorizedStates = {\n"); + deque::iterator itAuth, itAuthEnd = _AuthorizedStates.end(); + for (itAuth=_AuthorizedStates.begin(); itAuth!=itAuthEnd; ++itAuth) + fprintf(file, "\t\"%s\",\n", itAuth->c_str()); + fprintf(file, "%s", "};\n\n"); + + // MissionStatesFields + fprintf(file, "%s", + "// MissionStatesFields contains the number of fields in MissionStates, for\n" + "// future compatibility purpose.\n" + "MissionStatesFields = "); + fprintf(file, "%d", 3); // 3 fields: name, state, hash key + fprintf(file, "%s", ";\n\n"); + + // MissionStates + fprintf(file, "%s", + "// MissionStates contains a list of mission with for each the state of the\n" + "// mission and its hash key. The tool will add new missions with the default\n" + "// state. It will flag missions with a modified hash key with default state to\n" + "// prevent untested modified missions to be published.\n" + "// :NOTE: You can add a field to this structure without the need to modify EGS\n" + "// code. Simply update MissionStatesFields.\n" + "MissionStates = {\n"); + TMissionStateContainer::iterator itMission, itMissionEnd = _MissionStates.end(); + for (itMission=_MissionStates.begin(); itMission!=itMissionEnd; ++itMission) + fprintf(file, "\t%-42s %-12s \"%s\",\n", ("\""+itMission->second.name+"\",").c_str(), ("\""+itMission->second.state+"\",").c_str(), itMission->second.hashKey.c_str()); + fprintf(file, "};\n\n"); + + fclose(file); +} + +// :NOTE: This function exists in mission_template.cpp. If you change it here modify the other file. +std::string buildHashKey(std::string const& content) +{ + uint32 sum = 0; + size_t size = content.length()/4; + for (size_t i=0; i>1 | 0x80000000; + else + sum = sum>>1; + } + return NLMISC::toString("0x%08X", sum); +} + +bool CMission::parsePrim(NLLIGO::IPrimitive const* prim) +{ + // init default values + vector* params; + // get the mission script + if (!prim->getPropertyByName("script", params) || !params) + { + nlwarning("ERROR : cant find mission script!!!!!!"); + return false; + } + + // parse them + string content; + vector::iterator itParam, itParamEnd = params->end(); + for (itParam=params->begin(); itParam!=itParamEnd; ++itParam) + { + content += *itParam + "\n"; + } + hashKey = buildHashKey(content); + return true; +} + +void CMissionCompilerFeDlg::OnSpecialValidateMissions() +{ + CCompilDialog dlg; + dlg.Create(IDD_COMPIL, this); + EnableWindow(FALSE); + dlg.m_okBtn.EnableWindow(FALSE); + dlg.ShowWindow(SW_SHOW); + string compileLog; + + // Load existing validation + CValidationFile validation; + validation.loadMissionValidationFile("mission_validation.cfg"); + // Find real paths + typedef map TFileContainer; + TFileContainer files; + TFileList::iterator itDst, itDstEnd = _DstList.end(); + for (itDst=_DstList.begin(); itDst!=itDstEnd; ++itDst) + files.insert(make_pair(itDst->first, itDst->second)); + + // Parse primitives to get missions + TFileContainer::iterator itFile, itFileEnd = files.end(); + for (itFile=files.begin(); itFile!=itFileEnd; ++itFile) + { + compileLog += "Parsing '"+itFile->first+"'...\r\n"; + dlg.m_compileLog = compileLog.c_str(); + dlg.UpdateData(FALSE); + dlg.RedrawWindow(); + + string filename = itFile->second; + + TMissionContainer missions; + + // Load primitive + NLLIGO::CPrimitives primDoc; + CPrimitiveContext::instance().CurrentPrimitive = &primDoc; + NLLIGO::loadXmlPrimitiveFile(primDoc, filename, LigoConfig); + CPrimitiveContext::instance().CurrentPrimitive = NULL; + parsePrimForMissions(primDoc.RootNode, missions); + + // Parse missions to check modification + std::map::iterator itMission, itMissionEnd = missions.end(); + for (itMission=missions.begin(); itMission!=itMissionEnd; ++itMission) + { + CValidationFile::TMissionStateContainer::iterator itMissionValidation = validation._MissionStates.find(itMission->first); + if (itMissionValidation!=validation._MissionStates.end()) + { + // Mission already registered, check hash key + if (itMissionValidation->second.hashKey!=itMission->second.hashKey) + { + itMissionValidation->second.hashKey = itMission->second.hashKey; + itMissionValidation->second.state = validation.defaultState(); + } + } + else + { + // New mission + validation.insertMission(itMission->first, itMission->second.hashKey); + } + compileLog += "Mission: '"+itMission->first+"->"+itMission->second.hashKey+"\r\n"; + dlg.m_compileLog = compileLog.c_str(); + dlg.UpdateData(FALSE); + dlg.RedrawWindow(); + } + } + validation.saveMissionValidationFile("mission_validation.cfg"); + + compileLog += toString("Validation finished"); + dlg.m_compileLog = compileLog.c_str(); + dlg.UpdateData(FALSE); + dlg.m_compileLogCtrl.SetSel(compileLog.size(), compileLog.size(), FALSE); + dlg.RedrawWindow(); + + dlg.m_okBtn.EnableWindow(TRUE); + dlg.RunModalLoop(); + dlg.DestroyWindow(); + EnableWindow(TRUE); +} + +bool CMissionCompilerFeDlg::parsePrimForMissions(NLLIGO::IPrimitive const* prim, TMissionContainer& missions) +{ + string value; + // if the node is a mission parse it + if (prim->getPropertyByName("class",value) && !nlstricmp(value.c_str(),"mission") ) + { + string name; + prim->getPropertyByName("name",name); + + // parse the mission and put it in our manager + CMission mission(value, ""); + if (!mission.parsePrim(prim) ) + { + nlwarning("Previous errors in mission '%s'", name.c_str()); + // MissionLog.Log->displayNL(" \n"); + return false; + } + missions.insert(make_pair(name, mission)); + return true; + } + else + { + //this is not a mission node, so lookup recursively in the children + bool ok = true; + for (uint i=0;igetNumChildren();++i) + { + const IPrimitive *child; + if ( !prim->getChild(child,i) || !parsePrimForMissions(child, missions) ) + ok = false; + } + return ok; + } +} + +void CMissionCompilerFeDlg::OnValidate() +{ + OnSpecialValidateMissions(); +} + +void CMissionCompilerFeDlg::OnPublish() +{ + compile(TRUE); +} + +void CMissionCompilerFeDlg::updateSearchPath() +{ + for (uint i=0; im_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp; + bi.lpszTitle = "Choose the data directory"; + bi.ulFlags = 0; + bi.lpfn = dataDirBrowseCallbackProc; + + char sDir[512]; + strcpy(sDir, m_dataDirectory); + bi.lParam = (LPARAM)sDir; + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + + if (SHGetPathFromIDList(pidl, str)) + { + m_dataDirectory = str; + SearchPaths[0] = str; + fillSourceList(); + updateFileList(); + UpdateData(FALSE); + } +} + +void CMissionCompilerFeDlg::OnChangeDataDir() +{ + UpdateData(TRUE); + SearchPaths[0] = m_dataDirectory; + fillSourceList(); + updateFileList(); + UpdateData(FALSE); } \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_feDlg.h b/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_feDlg.h index 5de5bde59..788d8cd42 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_feDlg.h +++ b/code/ryzom/tools/leveldesign/mission_compiler_fe/mission_compiler_feDlg.h @@ -1,168 +1,168 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// mission_compiler_feDlg.h : header file -// - -#if !defined(AFX_MISSION_COMPILER_FEDLG_H__5A765948_0BD6_4A62_982F_11C11323C840__INCLUDED_) -#define AFX_MISSION_COMPILER_FEDLG_H__5A765948_0BD6_4A62_982F_11C11323C840__INCLUDED_ - -#include "nel/misc/types_nl.h" -#include -#include -#include -#include "nel/ligo/ligo_config.h" - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -///////////////////////////////////////////////////////////////////////////// -// CMissionCompilerFeDlg dialog - -struct CMissionState -{ - std::string name; - std::string state; - std::string hashKey; - CMissionState(std::string _name, std::string _state, std::string _hashKey) - : name(_name), state(_state), hashKey(_hashKey) { } -}; - -struct CMission -{ - std::string name; - std::string hashKey; - CMission(std::string _name, std::string _hashKey) - : name(_name), hashKey(_hashKey) { } - bool parsePrim(NLLIGO::IPrimitive const* prim); -}; - -class CValidationFile -{ -public: - typedef std::map TMissionStateContainer; - std::deque _AuthorizedStates; - TMissionStateContainer _MissionStates; -public: - // CValidationFile() { } - void loadMissionValidationFile(std::string filename); - void saveMissionValidationFile(std::string filename); - void insertMission(std::string const& mission, std::string const& hashKey) - { - _MissionStates.insert(std::make_pair(mission, CMissionState(mission, defaultState(), hashKey))); - } - std::string defaultState() - { - if (!_AuthorizedStates.empty()) - return _AuthorizedStates.front(); - else - return ""; - } -}; - - -class CMissionCompilerFeDlg : public CDialog -{ -// Construction -public: - CMissionCompilerFeDlg(CWnd* pParent = NULL); // standard constructor - - TToolMode Mode; - - bool readConfigFile(); - - void updateSearchPath(); - -// Dialog Data - //{{AFX_DATA(CMissionCompilerFeDlg) - enum { IDD = IDD_MISSION_COMPILER_FE_DIALOG }; - CButton m_validateBtn; - CButton m_compileBtn; - CButton m_publishBtn; - CListBox m_listDst; - CListBox m_listSrc; - CString m_filter; - CString m_dataDirectory; - //}}AFX_DATA - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CMissionCompilerFeDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - -public: - NLLIGO::CLigoConfig LigoConfig; -// Implementation -protected: - HICON m_hIcon; - - std::vector SearchPaths; - std::string LigoConfigFile; - std::string DefaultFilter; - - std::string TestPrimitive; - std::string TestPrimitiveDest; - std::string ReferenceScript; - - // Publish data - std::vector ServerName; - std::vector ServerPathPrim; - std::vector ServerPathText; - std::string LocalTextPath; - - - typedef std::map TFileList; - - TFileList _SrcList; - TFileList _DstList; - - void fillSourceList(); - void updateFileList(); - typedef std::map TMissionContainer; - bool parsePrimForMissions(NLLIGO::IPrimitive const* prim, TMissionContainer& missions); - void compile(BOOL publish); - - // Generated message map functions - //{{AFX_MSG(CMissionCompilerFeDlg) - virtual BOOL OnInitDialog(); - afx_msg void OnSysCommand(UINT nID, LPARAM lParam); - afx_msg void OnPaint(); - afx_msg HCURSOR OnQueryDragIcon(); - afx_msg void OnAdd(); - afx_msg void OnAddAll(); - afx_msg void OnRemove(); - afx_msg void OnRemoveAll(); - afx_msg void OnChangeFilter(); - afx_msg void OnCompile(); - afx_msg void OnSpecialRuncompilertest(); - afx_msg void OnDblclkListSrc(); - afx_msg void OnDblclkListDst(); - afx_msg void OnPublish(); - afx_msg void OnSpecialValidateMissions(); - afx_msg void OnValidate(); - afx_msg void OnChangeDir(); - afx_msg void OnChangeDataDir(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_MISSION_COMPILER_FEDLG_H__5A765948_0BD6_4A62_982F_11C11323C840__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// mission_compiler_feDlg.h : header file +// + +#if !defined(AFX_MISSION_COMPILER_FEDLG_H__5A765948_0BD6_4A62_982F_11C11323C840__INCLUDED_) +#define AFX_MISSION_COMPILER_FEDLG_H__5A765948_0BD6_4A62_982F_11C11323C840__INCLUDED_ + +#include "nel/misc/types_nl.h" +#include +#include +#include +#include "nel/ligo/ligo_config.h" + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +///////////////////////////////////////////////////////////////////////////// +// CMissionCompilerFeDlg dialog + +struct CMissionState +{ + std::string name; + std::string state; + std::string hashKey; + CMissionState(std::string _name, std::string _state, std::string _hashKey) + : name(_name), state(_state), hashKey(_hashKey) { } +}; + +struct CMission +{ + std::string name; + std::string hashKey; + CMission(std::string _name, std::string _hashKey) + : name(_name), hashKey(_hashKey) { } + bool parsePrim(NLLIGO::IPrimitive const* prim); +}; + +class CValidationFile +{ +public: + typedef std::map TMissionStateContainer; + std::deque _AuthorizedStates; + TMissionStateContainer _MissionStates; +public: + // CValidationFile() { } + void loadMissionValidationFile(std::string filename); + void saveMissionValidationFile(std::string filename); + void insertMission(std::string const& mission, std::string const& hashKey) + { + _MissionStates.insert(std::make_pair(mission, CMissionState(mission, defaultState(), hashKey))); + } + std::string defaultState() + { + if (!_AuthorizedStates.empty()) + return _AuthorizedStates.front(); + else + return ""; + } +}; + + +class CMissionCompilerFeDlg : public CDialog +{ +// Construction +public: + CMissionCompilerFeDlg(CWnd* pParent = NULL); // standard constructor + + TToolMode Mode; + + bool readConfigFile(); + + void updateSearchPath(); + +// Dialog Data + //{{AFX_DATA(CMissionCompilerFeDlg) + enum { IDD = IDD_MISSION_COMPILER_FE_DIALOG }; + CButton m_validateBtn; + CButton m_compileBtn; + CButton m_publishBtn; + CListBox m_listDst; + CListBox m_listSrc; + CString m_filter; + CString m_dataDirectory; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMissionCompilerFeDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + +public: + NLLIGO::CLigoConfig LigoConfig; +// Implementation +protected: + HICON m_hIcon; + + std::vector SearchPaths; + std::string LigoConfigFile; + std::string DefaultFilter; + + std::string TestPrimitive; + std::string TestPrimitiveDest; + std::string ReferenceScript; + + // Publish data + std::vector ServerName; + std::vector ServerPathPrim; + std::vector ServerPathText; + std::string LocalTextPath; + + + typedef std::map TFileList; + + TFileList _SrcList; + TFileList _DstList; + + void fillSourceList(); + void updateFileList(); + typedef std::map TMissionContainer; + bool parsePrimForMissions(NLLIGO::IPrimitive const* prim, TMissionContainer& missions); + void compile(BOOL publish); + + // Generated message map functions + //{{AFX_MSG(CMissionCompilerFeDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnSysCommand(UINT nID, LPARAM lParam); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnAdd(); + afx_msg void OnAddAll(); + afx_msg void OnRemove(); + afx_msg void OnRemoveAll(); + afx_msg void OnChangeFilter(); + afx_msg void OnCompile(); + afx_msg void OnSpecialRuncompilertest(); + afx_msg void OnDblclkListSrc(); + afx_msg void OnDblclkListDst(); + afx_msg void OnPublish(); + afx_msg void OnSpecialValidateMissions(); + afx_msg void OnValidate(); + afx_msg void OnChangeDir(); + afx_msg void OnChangeDataDir(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MISSION_COMPILER_FEDLG_H__5A765948_0BD6_4A62_982F_11C11323C840__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/mission_compiler_lib/main.cpp b/code/ryzom/tools/leveldesign/mission_compiler_lib/main.cpp index 550091c8f..88d04883a 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_lib/main.cpp +++ b/code/ryzom/tools/leveldesign/mission_compiler_lib/main.cpp @@ -1,270 +1,270 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/misc/i18n.h" -#include "mission_compiler.h" -#include "nel/misc/config_file.h" - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; - -class CMissionData; - - -class IStep; - -int main(int argc, char *argv[]) -{ - new NLMISC::CApplicationContext; - CPath::addSearchPath("L:\\primitives\\", true, false); - - bool test = false; - if (argc == 4 && string(argv[3]) == "-test") - { - test = true; - } - else if ( argc != 3) - { - printf("%s [-test]", argv[0]); - return -1; - } - - string sourceDocName; - if (!test) - sourceDocName = argv[2]; - else - sourceDocName = "test_compilateur.primitive"; - - // remove the path - sourceDocName = CFile::getFilename(sourceDocName); - // init ligo - NLLIGO::CLigoConfig LigoConfig; - - CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig; - - nlinfo("Reading ligo configuration file..."); - if (!LigoConfig.readPrimitiveClass (argv[1], false)) - { - nlwarning("Can't read '%s' !", argv[1]); - return -1; - } - - NLLIGO::Register(); - - nlinfo("Reading primitive file..."); - - CPrimitives primDoc; - CPrimitiveContext::instance().CurrentPrimitive = &primDoc; - loadXmlPrimitiveFile(primDoc, sourceDocName, LigoConfig); - - CMissionCompiler mc; - - if (test) - { - nlinfo("Compiling test mission"); - - try - { - mc.compileMissions(primDoc.RootNode, sourceDocName); - TMissionDataPtr testMission = mc.getMission(0); - - CSString script = testMission->generateMissionScript(sourceDocName); - script += "======================================================"+NL; - script += testMission->generatePhraseFile(); - script += "======================================================"+NL; - script += testMission->generateDotScript(); - script = script.replace(NL.c_str(), "\n"); - - char *tmp = ::getenv("TEMP"); - - FILE *fp = ::fopen((string(tmp)+"/compiled_mission.script").c_str(), "w"); - ::fwrite(script.data(), script.size(), 1, fp); - ::fclose(fp); - - system((string("\"C:\\Program Files\\Beyond Compare 2\\bc2.exe\" ")+string(tmp)+"/compiled_mission.script test_compilateur.script").c_str()); - } - catch(const EParseException &e) - { - nlwarning(e.Why.c_str()); - return -1; - } - return 0; - } - - nlinfo("Compiling missions..."); - try - { - mc.compileMissions(primDoc.RootNode, sourceDocName); - - mc.installCompiledMission(LigoConfig, sourceDocName); -/* std::vector &missions = mc.getMissions(); - // generate the mission script into the npcs... - { - map loadedPrimitives; - - // First loop to remove any mission that belong to the compiled primitive file - for (uint i=0; i filter; - filter.buildSet(primDoc->RootNode, TPrimitiveClassPredicate("mission"), scripts); - - // for each script, check if it was generated, and if so, check the name - // of the source primitive file. - for (uint i=0; i *script; - if (scripts[i]->getPropertyByName("script", script) && !script->empty()) - { - // Format should be : #compiled from - if (script->front().find("compiled from")) - { - // we have a compiled mission - if (script->front().find(sourceDocName)) - { - // ok, this mission is compiled from the same primitive, remove it - scripts[i]->getParent()->removeChild(scripts[i]); - } - } - } - } - } - - // second loop to assign compiled mission to giver npc - for (uint i=0; i filter; - filter.buildSet(primDoc->RootNode, TPrimitiveClassAndNamePredicate("npc_bot", mission.getGiverName()), bots); - - if (bots.empty()) - { - nlwarning("Can't find bot '%s' in primitive '%s' !", - mission.getGiverName().c_str(), - fileName.c_str()); - throw EParseException(NULL, "Can't find giver in primitive"); - } - else if (bots.size() > 1) - { - nlwarning("Found more than one bot named '%s' in primitive '%s' !", - mission.getGiverName().c_str(), - fileName.c_str()); - throw EParseException(NULL, "More than one bot with giver name in primitive"); - } - - // ok, all is good, we can add the mission node to the giver - IPrimitive *giver = bots.front(); - // create a new node for the mission - IPrimitive *script = new CPrimNode; - // set the class - script->addPropertyByName("class", new CPropertyString("mission")); - // set the name - script->addPropertyByName("name", new CPropertyString(mission.getMissionName())); -// string alias(toString("%u", makeHash32(mission.getMissionName()))); - script->addPropertyByName("alias", new CPropertyString(mission.getAlias())); - string scriptLines = mission.generateMissionScript(); - vector lines; - explode(scriptLines, NL, lines, false); - - script->addPropertyByName("script", new CPropertyStringArray(lines)); - - // insert the script into the giver - giver->insertChild(script); - } - - // Save the modified primitive files - while (!loadedPrimitives.empty()) - { - TLoadedPrimitive &loadedPrim = loadedPrimitives.begin()->second; - saveXmlPrimitiveFile(*(loadedPrim.PrimDoc), loadedPrim.FullFileName); - - // Free the memory - delete loadedPrim.PrimDoc; - - loadedPrimitives.erase(loadedPrimitives.begin()); - } - } - - // generate the phrase file (in any) - { - string phraseFileName = CFile::getFilenameWithoutExtension(sourceDocName) + "_en.txt"; - - CSString content; - - for (uint i=0; igeneratePhraseFile(); - } - // transform NL (\n\r) into single \n - content = content.replace(NL.c_str(), "\n"); - ucstring ucs; - ucs.fromUtf8(content); - - CI18N::writeTextFile(phraseFileName, ucs, true); - } -*/ - } - catch (const EParseException &e) - { - CPrimitiveContext::instance().CurrentLigoConfig = NULL; - nlerror("Compilation error : '%s'", e.Why.c_str()); - } - - CPrimitiveContext::instance().CurrentLigoConfig = NULL; -} - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/misc/i18n.h" +#include "mission_compiler.h" +#include "nel/misc/config_file.h" + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; + +class CMissionData; + + +class IStep; + +int main(int argc, char *argv[]) +{ + new NLMISC::CApplicationContext; + CPath::addSearchPath("L:\\primitives\\", true, false); + + bool test = false; + if (argc == 4 && string(argv[3]) == "-test") + { + test = true; + } + else if ( argc != 3) + { + printf("%s [-test]", argv[0]); + return -1; + } + + string sourceDocName; + if (!test) + sourceDocName = argv[2]; + else + sourceDocName = "test_compilateur.primitive"; + + // remove the path + sourceDocName = CFile::getFilename(sourceDocName); + // init ligo + NLLIGO::CLigoConfig LigoConfig; + + CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig; + + nlinfo("Reading ligo configuration file..."); + if (!LigoConfig.readPrimitiveClass (argv[1], false)) + { + nlwarning("Can't read '%s' !", argv[1]); + return -1; + } + + NLLIGO::Register(); + + nlinfo("Reading primitive file..."); + + CPrimitives primDoc; + CPrimitiveContext::instance().CurrentPrimitive = &primDoc; + loadXmlPrimitiveFile(primDoc, sourceDocName, LigoConfig); + + CMissionCompiler mc; + + if (test) + { + nlinfo("Compiling test mission"); + + try + { + mc.compileMissions(primDoc.RootNode, sourceDocName); + TMissionDataPtr testMission = mc.getMission(0); + + CSString script = testMission->generateMissionScript(sourceDocName); + script += "======================================================"+NL; + script += testMission->generatePhraseFile(); + script += "======================================================"+NL; + script += testMission->generateDotScript(); + script = script.replace(NL.c_str(), "\n"); + + char *tmp = ::getenv("TEMP"); + + FILE *fp = ::fopen((string(tmp)+"/compiled_mission.script").c_str(), "w"); + ::fwrite(script.data(), script.size(), 1, fp); + ::fclose(fp); + + system((string("\"C:\\Program Files\\Beyond Compare 2\\bc2.exe\" ")+string(tmp)+"/compiled_mission.script test_compilateur.script").c_str()); + } + catch(const EParseException &e) + { + nlwarning(e.Why.c_str()); + return -1; + } + return 0; + } + + nlinfo("Compiling missions..."); + try + { + mc.compileMissions(primDoc.RootNode, sourceDocName); + + mc.installCompiledMission(LigoConfig, sourceDocName); +/* std::vector &missions = mc.getMissions(); + // generate the mission script into the npcs... + { + map loadedPrimitives; + + // First loop to remove any mission that belong to the compiled primitive file + for (uint i=0; i filter; + filter.buildSet(primDoc->RootNode, TPrimitiveClassPredicate("mission"), scripts); + + // for each script, check if it was generated, and if so, check the name + // of the source primitive file. + for (uint i=0; i *script; + if (scripts[i]->getPropertyByName("script", script) && !script->empty()) + { + // Format should be : #compiled from + if (script->front().find("compiled from")) + { + // we have a compiled mission + if (script->front().find(sourceDocName)) + { + // ok, this mission is compiled from the same primitive, remove it + scripts[i]->getParent()->removeChild(scripts[i]); + } + } + } + } + } + + // second loop to assign compiled mission to giver npc + for (uint i=0; i filter; + filter.buildSet(primDoc->RootNode, TPrimitiveClassAndNamePredicate("npc_bot", mission.getGiverName()), bots); + + if (bots.empty()) + { + nlwarning("Can't find bot '%s' in primitive '%s' !", + mission.getGiverName().c_str(), + fileName.c_str()); + throw EParseException(NULL, "Can't find giver in primitive"); + } + else if (bots.size() > 1) + { + nlwarning("Found more than one bot named '%s' in primitive '%s' !", + mission.getGiverName().c_str(), + fileName.c_str()); + throw EParseException(NULL, "More than one bot with giver name in primitive"); + } + + // ok, all is good, we can add the mission node to the giver + IPrimitive *giver = bots.front(); + // create a new node for the mission + IPrimitive *script = new CPrimNode; + // set the class + script->addPropertyByName("class", new CPropertyString("mission")); + // set the name + script->addPropertyByName("name", new CPropertyString(mission.getMissionName())); +// string alias(toString("%u", makeHash32(mission.getMissionName()))); + script->addPropertyByName("alias", new CPropertyString(mission.getAlias())); + string scriptLines = mission.generateMissionScript(); + vector lines; + explode(scriptLines, NL, lines, false); + + script->addPropertyByName("script", new CPropertyStringArray(lines)); + + // insert the script into the giver + giver->insertChild(script); + } + + // Save the modified primitive files + while (!loadedPrimitives.empty()) + { + TLoadedPrimitive &loadedPrim = loadedPrimitives.begin()->second; + saveXmlPrimitiveFile(*(loadedPrim.PrimDoc), loadedPrim.FullFileName); + + // Free the memory + delete loadedPrim.PrimDoc; + + loadedPrimitives.erase(loadedPrimitives.begin()); + } + } + + // generate the phrase file (in any) + { + string phraseFileName = CFile::getFilenameWithoutExtension(sourceDocName) + "_en.txt"; + + CSString content; + + for (uint i=0; igeneratePhraseFile(); + } + // transform NL (\n\r) into single \n + content = content.replace(NL.c_str(), "\n"); + ucstring ucs; + ucs.fromUtf8(content); + + CI18N::writeTextFile(phraseFileName, ucs, true); + } +*/ + } + catch (const EParseException &e) + { + CPrimitiveContext::instance().CurrentLigoConfig = NULL; + nlerror("Compilation error : '%s'", e.Why.c_str()); + } + + CPrimitiveContext::instance().CurrentLigoConfig = NULL; +} + + diff --git a/code/ryzom/tools/leveldesign/mission_compiler_lib/mission_compiler.cpp b/code/ryzom/tools/leveldesign/mission_compiler_lib/mission_compiler.cpp index 016157564..20e957859 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_lib/mission_compiler.cpp +++ b/code/ryzom/tools/leveldesign/mission_compiler_lib/mission_compiler.cpp @@ -1,2270 +1,2270 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "mission_compiler.h" -#include "step.h" -#include "nel/misc/i18n.h" -#include "nel/ligo/primitive_utils.h" - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; - - -// hack to get access to string manager item enumeration to string without including -// almost all of the Ryzom server side project -namespace STRING_MANAGER -{ - NL_BEGIN_STRING_CONVERSION_TABLE (TParamType) - NL_STRING_CONVERSION_TABLE_ENTRY( item ) - NL_STRING_CONVERSION_TABLE_ENTRY( place ) - NL_STRING_CONVERSION_TABLE_ENTRY( creature ) - NL_STRING_CONVERSION_TABLE_ENTRY( skill ) - NL_STRING_CONVERSION_TABLE_ENTRY( role ) - NL_STRING_CONVERSION_TABLE_ENTRY( ecosystem ) - NL_STRING_CONVERSION_TABLE_ENTRY( race ) - NL_STRING_CONVERSION_TABLE_ENTRY( sbrick ) - NL_STRING_CONVERSION_TABLE_ENTRY( faction ) - NL_STRING_CONVERSION_TABLE_ENTRY( guild ) - NL_STRING_CONVERSION_TABLE_ENTRY( player ) - NL_STRING_CONVERSION_TABLE_ENTRY( bot ) - { "int", integer}, -// NL_STRING_CONVERSION_TABLE_ENTRY( integer ) - NL_STRING_CONVERSION_TABLE_ENTRY( time ) - NL_STRING_CONVERSION_TABLE_ENTRY( money ) - NL_STRING_CONVERSION_TABLE_ENTRY( compass ) - NL_STRING_CONVERSION_TABLE_ENTRY( string_id ) - NL_STRING_CONVERSION_TABLE_ENTRY( dyn_string_id ) - NL_STRING_CONVERSION_TABLE_ENTRY( self ) - NL_STRING_CONVERSION_TABLE_ENTRY( creature_model ) - NL_STRING_CONVERSION_TABLE_ENTRY( entity ) - NL_STRING_CONVERSION_TABLE_ENTRY( body_part ) - NL_STRING_CONVERSION_TABLE_ENTRY( score ) - NL_STRING_CONVERSION_TABLE_ENTRY( sphrase ) - NL_STRING_CONVERSION_TABLE_ENTRY( characteristic ) - NL_STRING_CONVERSION_TABLE_ENTRY( damage_type ) - NL_STRING_CONVERSION_TABLE_ENTRY( bot_name) - NL_STRING_CONVERSION_TABLE_ENTRY( power_type ) - NL_STRING_CONVERSION_TABLE_ENTRY( literal ) - NL_END_STRING_CONVERSION_TABLE(TParamType, ParamTypeConversion, NB_PARAM_TYPES) - - //----------------------------------------------- - // stringToParamType - //----------------------------------------------- - TParamType stringToParamType( const std::string & str ) - { - return ParamTypeConversion.fromString( str ); - } - - //----------------------------------------------- - // stringToParamType - //----------------------------------------------- - const std::string & paramTypeToString( TParamType type ) - { - return ParamTypeConversion.toString( type ); - } -} - -// utility to 'tabulate' the lines in a string -void tabulateLine(std::string &text, uint nbTabs) -{ - if (text.empty()) - return; - string::size_type pos = 0; - string tabs; - - for (uint i=0; i 2) - { - if (_EntityName[0] == '$' && _EntityName[_EntityName.size() - 1] == '$') - { - _EntityName = _EntityName.substr(1, _EntityName.size() - 2); - } - } - - std::string newLiteral = before + after; - - bool isFemale = parseMarkup(newLiteral,f,newPhrase, true); - if ( isFemale) - { - parseMarkup(newPhrase,h,newPhrase, false); - femaleText = newPhrase; - } - - bool isMale = parseMarkup(newLiteral, h, newPhrase, true); - if (isMale) - { - - parseMarkup(newPhrase, f, newPhrase, false); - maleText = newPhrase; - } - - if (isMale != isFemale) - { - std::string goodMarkup = isMale ? std::string("") +"<" + h + ">" : std::string("")+"<"+f+">"; - std::string badMarkup = isFemale ? std::string("") +"<" + h + ">" : std::string("")+"<"+f+">"; - std::string exceptionText = std::string("La phrase ") + identifier + " qui contient une balise " + goodMarkup + " nécessite aussi les balises " + badMarkup + " même vide."; - throw EParseException(0, exceptionText.c_str()); - } - - if (!isMale && !isFemale) - { - _Text = literal; - _Female = 0; - _Male = 0; - - } - else - { - if (!_Entity) { _EntityName = "self"; } - _Female = new GenderExtractor(femaleText, identifier, level+1); - _Male = new GenderExtractor(maleText, identifier, level+1); - } - - - -} - -bool GenderExtractor::extractMarkup(const std::string& literal, const std::string & markup, std::string &before, std::string &inside, std::string & after) -{ - std::string::size_type posBegin; - std::string::size_type posEnd; - std::string::size_type posInside; - - std::string beginMarkup = std::string("<") + markup + std::string(">"); - std::string endMarkup = std::string(""); - posBegin = literal.find(beginMarkup); - if ( posBegin != std::string::npos ) - { - posEnd = literal.find(endMarkup, posBegin + beginMarkup.size()); - if (posEnd != std::string::npos) - { - before = literal.substr(0, posBegin); - posInside = posBegin + beginMarkup.size(); - inside = literal.substr(posInside, posEnd - posInside); - after = literal.substr(posEnd+endMarkup.size()); - return true; - } - } - after = literal; - return false; -} - -bool GenderExtractor::parseMarkup(const std::string& literal, const std::string & markup, std::string& newPhrase, bool include ) -{ - - bool markupExist; - bool changed = false; - std::string oldPhrase = literal; - - newPhrase = ""; - do - { - std::string before; - std::string inside; - std::string after; - markupExist = extractMarkup(oldPhrase, markup, before, inside, after); - newPhrase += before; - if (include){ newPhrase += inside; } - oldPhrase = after; - if (markupExist){ changed = true; } - - } while(markupExist); - - newPhrase += oldPhrase; - return changed; -} - -std::string GenderExtractor::getPhrase(unsigned int i) const -{ - if ( i%2 == 0) { return _Male ? _Male->getPhrase(i/2) : _Text; } - if ( i%2 == 1) { nlassert(_Female); return _Female->getPhrase(i/2);} - nlassert(0); - return ""; -} - -std::string GenderExtractor::getExtension(unsigned int i) const -{ - if ( i%2 == 0) { return _Male ? std::string("_m") + _Male->getExtension(i/2) : ""; } - if ( i%2 == 1) { nlassert(_Female); return std::string("_f") + _Female->getExtension(i/2);} - nlassert(0); - return ""; -} - -std::string GenderExtractor::getCondition(unsigned int i) const -{ - - //if ( i%2 == 0) { return _Male ? std::string("\t(") + _Male->getExtension(i/2) : "\t"; } - //if ( i%2 == 1) { nlassert(_Female); return std::string("_f") + _Female->getExtension(i/2);} - - if ( i%2 == 0) - { - if (_Male) - { - std::string next = _Male->getCondition(i/2); - std::string current = _EntityName + ".gender = male"; - return next.size() ? current + " & " + next : current; - - } - else - { - return ""; - } - } - - if ( i%2 == 1) - { - std::string next = _Female->getCondition(i/2); - std::string current = _EntityName + ".gender = female"; - return next.size() ? current + " & " + next : current; - } - - nlassert(0); - - return ""; -} - -unsigned int GenderExtractor::size() const -{ - return _Male ? _Male->size() + _Female->size(): 1; -} - - -string CPhrase::genPhrase() -{ - string ret; - if (!_PhraseLiterals.empty()) - { - for (uint p=0; p<_PhraseLiterals.size(); ++p) - { - string identifier = _PhraseId; - if (_NumEntry != 0) - identifier += toString("_%u", p+1); - - GenderExtractor gender(_PhraseLiterals[p], identifier, 0); - - ret += identifier + " ("; - // generate default param list - if (_DefaultParams.size() > p) - { - for (uint i=0; i<_DefaultParams[p].size(); ++i) - { - ret += STRING_MANAGER::paramTypeToString(_DefaultParams[p][i].ParamType) + " "+_DefaultParams[p][i].ParamName; - if (i != _DefaultParams[p].size()-1 || !_AdditionalParams.empty()) - ret += ", "; - } - } - // generate additional param list - for (uint i=0; i<_AdditionalParams.size(); ++i) - { - ret += STRING_MANAGER::paramTypeToString(_AdditionalParams[i].ParamType) + " "+_AdditionalParams[i].ParamName; - if (i != _AdditionalParams.size()-1) - ret += ", "; - } - ret += ")" + NL; - ret += "{" + NL; - - for (unsigned int i = 0; i < gender.size(); ++i) - { - ret += gender(i); - } - - ret += "}" + NL + NL; - } - } -nlinfo("genphrase: %s", ret.c_str()); - return ret; -} - - - - -bool CMissionCompiler::generateDotScript(NLLIGO::IPrimitive *missionPrim, std::string &dotScript, std::string &log) -{ - //assume that the mission is compiled in the last compiled mission slot - try - { - if (compileMission(missionPrim, string())) - { - dotScript = _CompiledMission.back()->generateDotScript(); - return true; - } - else - { - return false; - } - } - catch(const EParseException & e) - { - log = e.Why; - return false; - } -} - -/* -bool CMissionCompiler::parseGlobalMissionData(IPrimitive *mission, CMissionData &md) -{ - // Mission name - string *s; - if (!mission->getPropertyByName("name", s) || s->empty()) - throw EParseException(mission, "missing mission name !"); - md.setMissionName(*s); - - // giver primitive file - if (!mission->getPropertyByName("giver_primitive", s) || s->empty()) - throw EParseException(mission, "missing giver primitive !"); - md.setGiverPrimitive(*s); - - // giver name - if (!mission->getPropertyByName("giver_primitive", s) || s->empty()) - throw EParseException(mission, "missing giver primitive !"); - md.setGiverName(*s); - // If the mission is under a npc_bot node, then the giver is directly taken - // from the npc name - if (mission->getParent()) - { - if (mission->getParent()->getPropertyByName("class", s) && *s == "npc_bot") - { - if (mission->getParent()->getPropertyByName("name", s)) - md.setGiverName(*s); - } - } - - // TODO : read all other params... - - return true; -} -*/ - -void CMissionData::initHeaderPhrase(IPrimitive *prim) -{ - CPhrase::TPredefParams params; - params.resize(1); - params[0].push_back(CPhrase::TParamInfo("giver", STRING_MANAGER::bot)); - _MissionTitle.initPhrase(*this, prim, _MissionTitleRaw, 0, params); - _MissionDescription.initPhrase(*this, prim, _MissionDescriptionRaw, 0, params); - _MissionAutoMenu.initPhrase(*this, prim, _MissionAutoMenuRaw); -} - -bool CMissionCompiler::compileMission(NLLIGO::IPrimitive *rootPrim, const std::string &primFileName) -{ - TPrimitiveClassPredicate pred("mission_tree"); - if (!pred(rootPrim)) - return false; - - IPrimitive *mission = rootPrim; - CMissionData *pmd = new CMissionData; - CMissionData &md = *pmd; - - // Read the mission name - string missionName = md.getProperty(mission, "name", false, false); - if( missionName.find(' ') != string::npos) - { - throw EParseException(mission, toString("Mission name '%s' must not contains space", missionName.c_str()).c_str()); - } - md.setMissionName(missionName); - // Create a temporary primitive node to create default variable - { - // giver default var - IPrimitive *temp = new CPrimNode(); - temp->addPropertyByName("class", new CPropertyString("var_npc")); - temp->addPropertyByName("name", new CPropertyString("giver = giver")); - temp->addPropertyByName("npc_name", new CPropertyString("giver")); - temp->addPropertyByName("var_name", new CPropertyString("giver")); - - IVar *var = IVar::createVar(md, temp); - md.addVariable(NULL, var); - - delete temp; - } - - { - // player default var - IPrimitive *temp = new CPrimNode(); - temp->addPropertyByName("class", new CPropertyString("var_npc")); - temp->addPropertyByName("name", new CPropertyString("player = player")); - temp->addPropertyByName("npc_name", new CPropertyString("player")); - temp->addPropertyByName("var_name", new CPropertyString("player")); - - IVar *var = IVar::createVar(md, temp); - md.addVariable(NULL, var); - - delete temp; - } - - { - // guild_name default var - IPrimitive *temp = new CPrimNode(); - temp->addPropertyByName("class", new CPropertyString("var_text")); - temp->addPropertyByName("name", new CPropertyString("guild_name = guild_name")); - temp->addPropertyByName("npc_name", new CPropertyString("guild_name")); - temp->addPropertyByName("var_name", new CPropertyString("guild_name")); - - IVar *var = IVar::createVar(md, temp); - md.addVariable(NULL, var); - - delete temp; - } - - // first, start by reading mission variables - IPrimitive *variables; - { - TPrimitiveClassPredicate predTmp("variables"); - variables= NLLIGO::getPrimitiveChild(mission, predTmp); - } - - if (!variables) - { - nlwarning("Can't find variables !"); - return false; - } - parseVariables(md, variables); - - // read global mission data - md.parseMissionHeader(rootPrim); - - // now, we can init the mission header phrase (they need variable knwoled) - md.initHeaderPhrase(rootPrim); - - IPrimitive *preReq; - { - TPrimitiveClassPredicate predTmp("pre_requisite"); - preReq = getPrimitiveChild(mission, predTmp); - } - - if (!preReq) - { - nlwarning("Can't find pre requisite !"); - return false; - } - parsePreRequisite(md, preReq); - -/* IPrimitive *steps = getPrimitiveChild(mission, TPrimitivePropertyPredicate("step_tag", "true")); - if (!steps) - { - nlwarning("Can't find steps !"); - return false; - } -*/ parseSteps(md, mission); - - // Store the compiled mission - _CompiledMission.push_back(pmd); - - string script = md.generateMissionScript(primFileName); - - nlinfo("The script :"); - nlinfo("%s", script.c_str()); - - string phrases = md.generatePhraseFile(); - nlinfo("The phrase file is :"); - { - vector lines; - explode(phrases, string("\n"), lines, false); - for (uint i=0; i lines; - explode(dot, string("\n"), lines, false); - for (uint i=0; i scriptsSet; - - TPrimitiveClassPredicate pred("mission_tree"); - scriptsSet.buildSet(rootPrim, pred, missionTrees); - - nlinfo("Found %u mission tree in the primitive file", missionTrees.size()); - - for (uint i=0; i loadedPrimitives; - - // store the previous alias value - map missionAlias; - - // First loop to remove any mission that belong to the compiled primitive file - for (uint i=0; i<_CompiledMission.size(); ++i) - { - CMissionData &mission = *(_CompiledMission[i]); - // first, look for the primitive file to load - string fileName = mission.getGiverPrimitive(); - if (fileName.empty()) - { - // use mission primitive instead - fileName = primFileName; - } - if (loadedPrimitives.find(toLower(fileName)) == loadedPrimitives.end()) - { - string fullFileName = CPath::lookup(fileName, false); - if (fullFileName.empty()) - { - throw EParseException(NULL, toString("Can't find primitive file '%s' in path", fileName.c_str()).c_str()); - } - // we need to load this primitive file. - CPrimitives *primDoc = new CPrimitives; - CPrimitiveContext::instance().CurrentPrimitive = primDoc; - if (loadXmlPrimitiveFile(*primDoc, fullFileName, ligoConfig)) - { - // the primitive file is loaded correctly - loadedPrimitives.insert(make_pair(toLower(fileName), TLoadedPrimitive(primDoc, fullFileName))); - CPrimitiveContext::instance().CurrentPrimitive = NULL; - } - else - { - CPrimitiveContext::instance().CurrentPrimitive = NULL; - throw EParseException(NULL, toString("Can't read primitive file '%s'", fullFileName.c_str()).c_str()); - } - } - TLoadedPrimitive &loadedPrim = loadedPrimitives[toLower(fileName)]; - CPrimitives *primDoc = loadedPrim.PrimDoc; - - TPrimitiveSet scripts; - CPrimitiveSet filter; - TPrimitiveClassPredicate pred("mission"); - filter.buildSet(primDoc->RootNode, pred, scripts); - - // for each script, check if it was generated, and if so, check the name - // of the source primitive file. - for (uint i=0; i *script; - if (scripts[i]->getPropertyByName("script", script) && !script->empty()) - { - string missionName; - - scripts[i]->getPropertyByName("name", missionName); - - // Format should be : #compiled from - if (script->front().find("generated from") != string::npos) - { - // we have a compiled mission - if (script->front().find(CFile::getFilename(primFileName)) != string::npos) - { - // ok, this mission is compiled from the same primitive - - // store it's alias - TPrimitiveClassPredicate pred("alias"); - - IPrimitive *p = getPrimitiveChild(scripts[i], pred); - - if (p) - { - CPrimAlias *pa = dynamic_cast(p); - if (pa) - { - uint32 alias = pa->getAlias(); - missionAlias.insert(make_pair(missionName, alias)); - } - } - else - { - nlwarning("Can't find alias prim in primitive '%s'", buildPrimPath(scripts[i]).c_str()); - } - - // and remove it - scripts[i]->getParent()->removeChild(scripts[i]); - } - } - } - } - } - - // second loop to assign compiled mission to giver npc - for (uint i=0; i<_CompiledMission.size(); ++i) - { - CMissionData &mission = *(_CompiledMission[i]); - string fileName = mission.getGiverPrimitive(); - if (fileName.empty()) - { - // no giver primitive file specified in the mission, use the mission primitive instead - fileName = primFileName; - } - - TLoadedPrimitive &loadedPrim = loadedPrimitives[toLower(fileName)]; - CPrimitives *primDoc = loadedPrim.PrimDoc; - CPrimitiveContext::instance().CurrentPrimitive = primDoc; - - TPrimitiveSet bots; - CPrimitiveSet filter; - TPrimitiveClassAndNamePredicate pred("npc_bot", mission.getGiverName()); - filter.buildSet(primDoc->RootNode, pred, bots); - - if (bots.empty()) - { - string err = toString("Can't find bot '%s' in primitive '%s' !", - mission.getGiverName().c_str(), - fileName.c_str()); - throw EParseException(NULL, err.c_str()); - } - else if (bots.size() > 1) - { - string err = toString("Found more than one bot named '%s' in primitive '%s' !", - mission.getGiverName().c_str(), - fileName.c_str()); - throw EParseException(NULL, err.c_str()); - } - - // ok, all is good, we can add the mission node to the giver - IPrimitive *giver = bots.front(); - // create a new node for the mission - IPrimitive *script = new CPrimNode; - // set the class - script->addPropertyByName("class", new CPropertyString("mission")); - // set the name - script->addPropertyByName("name", new CPropertyString(mission.getMissionName())); -// string alias(toString("%u", makeHash32(mission.getMissionName()))); -// script->addPropertyByName("alias", new CPropertyString(mission.getAlias())); - string scriptLines = mission.generateMissionScript(primFileName); - vector lines; - explode(scriptLines, NL, lines, false); - - script->addPropertyByName("script", new CPropertyStringArray(lines)); - - // insert the script into the giver - giver->insertChild(script); - - // add the alias - { - CPrimAlias *pa = new CPrimAlias; - pa->addPropertyByName("class", new CPropertyString ("alias")); - pa->addPropertyByName("name", new CPropertyString ("alias")); - - if (missionAlias.find(mission.getMissionName()) != missionAlias.end()) - { - // restore the previous alias - primDoc->forceAlias(pa, missionAlias.find(mission.getMissionName())->second); - } - - // insert in first place - script->insertChild(pa, 0); - } - - CPrimitiveContext::instance().CurrentPrimitive = NULL; - } - - // Save the modified primitive files - while (!loadedPrimitives.empty()) - { - TLoadedPrimitive &loadedPrim = loadedPrimitives.begin()->second; - if (!saveXmlPrimitiveFile(*(loadedPrim.PrimDoc), loadedPrim.FullFileName)) - return false; - - _FilesToPublish.push_back(loadedPrim.FullFileName); - - // Free the memory - delete loadedPrim.PrimDoc; - - loadedPrimitives.erase(loadedPrimitives.begin()); - } - } - - // generate the phrase file (if any) - { - string phraseFileName = CFile::getFilenameWithoutExtension(primFileName) + "_wk.txt"; - - CSString content; - - for (uint i=0; i<_CompiledMission.size(); ++i) - { - content += _CompiledMission[i]->generatePhraseFile(); - } - // transform NL (\n\r) into single \n - content = content.replace(NL.c_str(), "\n"); - ucstring ucs; - ucs.fromUtf8(content); - - CI18N::writeTextFile(phraseFileName, ucs, true); - - _FilesToPublish.push_back(phraseFileName); - } - - return true; -} - - -bool CMissionCompiler::publishFiles(const std::string &serverPathPrim, const std::string &serverPathText, const std::string &localPathText) -{ - for (uint i=0 ; i<_FilesToPublish.size() ; i++) - { - string dst, src = _FilesToPublish[i]; - - string::size_type n = src.find("primitives"); - if (n == string::npos) - { - // text files : copy it and check include in phrase_rites_wk.txt - - // server - string textFile = CPath::standardizePath(serverPathText) + "phrase_rites_wk.txt"; - includeText(textFile, string("#include \"") + src + string("\"\n")); - dst = CPath::standardizePath(serverPathText) + src; - NLMISC::CFile::copyFile(dst, src); - - // local - textFile = CPath::standardizePath(localPathText) + "phrase_rites_wk.txt"; - includeText(textFile, string("#include \"") + src + string("\"\n")); - dst = CPath::standardizePath(localPathText) + src; - NLMISC::CFile::copyFile(dst, src); - } - else - { - // primitive file : copy to server - dst = CPath::standardizePath(serverPathPrim) + string(src, n, src.size()); - NLMISC::CFile::copyFile(dst, src); - } - } - return true; -} - -bool CMissionCompiler::includeText(const std::string filename, const std::string text) -{ - FILE *f = fopen(filename.c_str(), "r+"); - if (f == NULL) - return false; - - bool isIn = false; - char buffer[1024]; - - // Check for UTF8 format - fread(buffer, 1, 3, f); - if (buffer[0] != -17 || buffer[1] != -69 || buffer[2] != -65) - fseek(f, 0, SEEK_SET); - - // Compare each line - while(fgets(buffer, 1024, f)) - { - if (!strcmp(text.c_str(), buffer)) - { - isIn = true; - break; - } - } - - if (!isIn) - fputs(text.c_str(), f); - - fclose(f); - return true; -} - -bool CMissionCompiler::parsePreRequisite(CMissionData &md, IPrimitive *preReq) -{ - md.parsePrerequisites(preReq); - return true; -} - -bool CMissionCompiler::parseOneStep(CMissionData &md, IPrimitive *stepToParse, IStep *parent, bool bEndOfBranch) -{ - IStep *step = IStep::createStep(md, stepToParse); - if (step != NULL) - { - - if (!step->isAJump() && !step->getStepName().empty()) - { - if (md.getStepByName(step->getStepName()) != NULL) - { - string err = toString("Step '%s' already defined !", step->getStepName().c_str()); - throw EParseException(step->getPrimitive(), err.c_str()); - } - - if (step->getStepName().find(' ') != string::npos) - { - throw EParseException(step->getPrimitive(), toString("Step name '%s' must not contains space", step->getStepName().c_str()).c_str()); - } - md.addStepName(step->getStepName(), step); - } - - TPrimitiveSet subBranchs = step->getSubBranchs(); - - // Add the step (if no parent add to the mission data) - if (parent == NULL) - { - if (!md.addStep(step)) - { - throw EParseException(stepToParse, "Error parsing mission step"); - } - } - else - { - parent->addSubStep(step); - } - - CStepIf *pSI = dynamic_cast(step); - // If this is a IF step : parse with 'step' as a parent - - IStep *pParentStep = NULL; - - if ((dynamic_cast(step) != NULL) || - (dynamic_cast(step) != NULL)) - pParentStep = step; - - if (!subBranchs.empty()) - { - // need to parse subbranch before continuing - for (uint i=0; iEndOfBranch = bEndOfBranch; - } - return true; -} - -bool CMissionCompiler::parseSteps(CMissionData &md, IPrimitive *steps, IStep *parent) -{ - TPrimitiveSet childs; - TPrimitivePropertyPredicate pred("step_tag", "true"); - filterPrimitiveChilds(steps, pred, childs); - - if (childs.empty()) - { - CPrimNode node; - node.addPropertyByName("class", new CPropertyString("end")); - node.addPropertyByName("name", new CPropertyString("")); - IStep *step = IStep::createStep(md, &node); - delete step; -// md.addStep(step); - } - if (!childs.empty()) - { - for (uint i=0; igetPropertyByName(propName.c_str(), s); - if (!ret) - throw EParseException(prim, toString("Property %s does't exist", propName.c_str()).c_str()); - - return s; -} - -string CMissionCompiler::getClass(IPrimitive *prim) -{ - string className; - bool ret = prim->getPropertyByName("class", className); - nlassert(ret); - return className; -} - -bool CMissionCompiler::parseVariables(CMissionData &md, IPrimitive *variables) -{ - for (uint i=0; igetNumChildren(); ++i) - { - IPrimitive *child; - if (variables->getChild(child, i)) - { - IVar *var = IVar::createVar(md, child); - if (var) - { - nldebug("Adding variable '%s' as type %u", var->getVarName().c_str(), var->getVarType()); - md.addVariable(child, var); - } - } - } - return true; -} - -template -bool strtokquote(const string &src, VectorType &tokens) -{ - enum TMode - { - read_blank, - read_token, - read_quoted - }; - - string temp; - TMode mode = read_blank; - - for (uint i=0; i -bool strtokquote(const vector &src, VectorType &tokens) -{ - for (uint i=0; i -{ - string Name; - TFindParamPred(const std::string &name) - : Name (name) - {} - - bool operator() (const CPhrase::TParamInfo ¶mInfo) const - { - return paramInfo.ParamName == Name; - } -}; - - -bool CPhrase::isEmpty() -{ - return _PhraseId.empty(); -} - -bool CPhrase::asAdditionnalParams() -{ - return !_AdditionalParams.empty(); -} - - -void CPhrase::initPhrase (CMissionData &md, - IPrimitive *prim, - const vector &texts, - uint32 numEntry, - const TPredefParams &predefParams ) -{ -// nlassert(numEntry == predefParams.size()); - - // store the predefined/default parameters - _DefaultParams = predefParams; - // store the number of entry to generate (for literal with variant) - _NumEntry = numEntry; - - numEntry = max(uint32(1), numEntry); - - _PhraseLiterals.clear(); -// _PhraseLiterals.resize(numEntry); - - // first, concatenate the text vector - string text; - for (uint i=0; i params; - -retry: - // ok, the string is parsed, now we can analyze it - // look at the first letter of the first token to determine the type of data we have - if (tokens[0][0] == '\"') - { - // we have a literal, so we must found numEntry literal, then a suffix tag for the phrase name - if (tokens.size() != numEntry +1) - throw EParseException(prim, toString("bad number of tokens in phrase : need %u (%u entries + 1 suffix), found %u\n(in : '%s')", - numEntry+1, - numEntry, - tokens.size(), - text.c_str() - ).c_str()); - - _PhraseLiterals.resize(numEntry); - for (uint i=0; i= predefParams.size() || find_if(predefParams[i].begin(), predefParams[i].end(), TFindParamPred(static_cast(p))) == predefParams[i].end()) - { - // this param is not in the predefined params list, add it to the optional params - params.push_back(p); - } - - // remove any compiler param from the phrase literal - if (p.find("@") != string::npos) - { - string::size_type pos = _PhraseLiterals[i].find(p, paramStart); - if (pos != string::npos) - { - string::size_type pos2 = _PhraseLiterals[i].find("@", pos); - if (pos2 != string::npos) - { - while (pos2 < _PhraseLiterals[i].size() - && _PhraseLiterals[i][pos2] != '.' - && _PhraseLiterals[i][pos2] != '$') - { - _PhraseLiterals[i].erase(pos2, 1); - } - } - - } - } - } - else - { - // this is an escaped $, skip it - text.leftCrop(1); - } - } - } - } - // last, read the suffix - _Suffixe = tokens.back(); - - // generate identifier - _PhraseId = toUpper(md.getMissionName()+"_"+_Suffixe); - - set ps; - // select only unique params - ps.insert(params.begin(), params.end()); - - vector temp(ps.begin(), ps.end()); - params.swap(temp); - - } - else if (tokens[0][0] == '$') - { - // we have a variable substitution. Retrieve the var and recall init - - // do the var replacement - CVectorSString tokens2; - - tokens[0] = md.replaceVar(prim, tokens[0]); - - if (!strtokquote(tokens[0], tokens2)) - throw EParseException(prim, toString("failed to tokenize the string ('%s')", tokens[0].c_str()).c_str()); - - tokens2.insert(tokens2.end(), tokens.begin()+1, tokens.end()); - tokens.swap(tokens2); - - // and retry the decoding - goto retry; - } - else - { - // this should be a simple identifier, followed by any number of additional parameters - - // do the var replacement -// tokens = md.replaceVar(prim, tokens); -// untagVar(tokens[0]); - - // ok, now extract the phrase label and the additional parameters - _PhraseId = tokens[0]; - for (uint i=1; i(tokens[i]))) == predefParams[0].end()) - { - // this param is not in the predefined params list, add it to the optional params - params.push_back(tokens[i]); - } - } - } - - // now, build the parameter list - - vector::iterator first(params.begin()), last(params.end()); - for (; first != last; ++first) - { - string name, param; - vector parts; - NLMISC::explode(*first, string("@"), parts, false); - - if (parts.size() > 0) - name = parts[0]; - if (parts.size() > 1) - param = parts[1]; - - const string &varName = name; - - if (varName != "self") - { - IVar *var = md.getVariable(varName); - if (var == NULL) - { - string err = toString("Can't find variable '%s' referenced from a phrase", - name.c_str()); - throw EParseException(prim, err.c_str()); - } - - TParamInfo pi; - pi.ParamName = name; - pi.CompilerParam = param; - pi.ParamType = var->getStringManagerType(); - _AdditionalParams.push_back(pi); - } - } -} - -std::string CPhrase::genScript(CMissionData &md) -{ - std::string ret; - - ret = _PhraseId; - for (uint i=0; i<_AdditionalParams.size(); ++i) - { - IVar *var = md.getVariable(_AdditionalParams[i].ParamName); - if (var == NULL) - { - string err = toString("Can't find variable named '%s' to generate phrase param", _AdditionalParams[i].ParamName.c_str()); - throw EParseException(NULL, err.c_str()); - } - ret += "; " + var->evalVar(_AdditionalParams[i].CompilerParam); - } - - return ret; -} - -CMissionData::CMissionData() -{ - // init all datas - _MonoInstance = false; - _MissionAuto = false; - _RunOnce = false; - _Replayable = false; - _Solo = false; - _Guild = false; - _NotInJournal = false; - _AutoRemoveFromJournal = false; - _PlayerReplayTimer = 0; - _GlobalReplayTimer = 0; - _NotProposed = false; - _NonAbandonnable = false; - _NeedValidation = false; - _FailIfInventoryIsFull = false; -} - -CMissionData::~CMissionData() -{ - while (!_Variables.empty()) - { - delete _Variables.begin()->second; - _Variables.erase(_Variables.begin()); - } - - while (!_Steps.empty()) - { - delete _Steps.back(); - _Steps.pop_back(); - } -} - -void CMissionData::setMissionName(const string &missionName) -{ - _MissionName = missionName; -} - -const string &CMissionData::getMissionName() { return _MissionName;} - -bool CMissionData::addVariable(NLLIGO::IPrimitive *prim, IVar *var) -{ - if (_Variables.find(var->getVarName()) != _Variables.end()) - throw EParseException(prim, toString("Variable '%s' already defined !", var->getVarName().c_str()).c_str()); - - _Variables.insert(make_pair(var->getVarName(), var)); - _VariablesOrder.push_back(var); - return true; -} - -IVar *CMissionData::getVariable(const string &varName) -{ - map::iterator it(_Variables.find(varName)); - if (it != _Variables.end()) - return it->second; - return NULL; -} - -IStep *CMissionData::getNextStep(IStep *current) -{ - for (uint i=0; i<_Steps.size(); ++i) - { - if (_Steps[i] == current && i < _Steps.size()-1) - return _Steps[i+1]; - } - return NULL; -} - -IStep *CMissionData::getStepByName(const std::string &stepName) -{ - if (_StepsByNames.find(stepName) != _StepsByNames.end()) - { - return _StepsByNames[stepName]; - } - - return NULL; -} - - -bool CMissionData::addStep(IStep *step) -{ - _Steps.push_back(step); - return true; -} - -string CMissionData::genPreRequisites() -{ - string ret; - if (!_ReqSkills.empty()) - { - ret += "req_skill : "; - for (uint i=0; i<_ReqSkills.size(); ++i) - { - ret += _ReqSkills[i].Skill+" "+_ReqSkills[i].MinLevel+" "+_ReqSkills[i].MaxLevel; - if (i < _ReqSkills.size()-1) - ret +="; "; - else - ret += NL; - } - } - if (!_ReqMissionDone.empty()) - { - for (uint i=0; i<_ReqMissionDone.size(); ++i) - { - ret += "req_mission : "+ _ReqMissionDone[i]+NL; - } - } - if (!_ReqMissionNotDone.empty()) - { - for (uint i=0; i<_ReqMissionNotDone.size(); ++i) - { - ret += "req_mission_neg : "+_ReqMissionNotDone[i]+NL; - } - } - if (!_ReqMissionRunning.empty()) - { - for (uint i=0; i<_ReqMissionRunning.size(); ++i) - { - ret += "req_mission_running : "+_ReqMissionRunning[i]+NL; - } - } - if (!_ReqMissionNotRunning.empty()) - { - - for (uint i=0; i<_ReqMissionNotRunning.size(); ++i) - { - ret += "req_mission_running_neg : "+_ReqMissionNotRunning[i]+NL; - } - } - if (!_ReqWearItem.empty()) - { - ret += "req_wear : "; - for (uint i=0; i<_ReqWearItem.size(); ++i) - { - ret += _ReqWearItem[i]; - if(i < _ReqWearItem.size()-1) - ret +="; "; - ret += NL; - } - } - if (!_ReqOwnItem.empty()) - { - ret += "req_item : "; - for (uint i=0; i<_ReqOwnItem.size(); ++i) - { - ret += _ReqOwnItem[i]; - if(i < _ReqOwnItem.size()-1) - ret +="; "; - ret += NL; - } - } - if (!_ReqTitle.empty()) - { - ret += "req_title : "+_ReqTitle+NL; - } - if (!_ReqFames.empty()) - { - for (uint i=0; i<_ReqFames.size(); ++i) - { - ret += "req_fame : "+_ReqFames[i].Faction+" "+_ReqFames[i].Fame; - ret += NL; - } - } - if(_ReqGuild) - { - ret += "req_guild"+NL; - } - if (!_ReqGrade.empty()) - { - ret += "req_grade : "+_ReqGrade+NL; - } - if (!_ReqTeamSize.empty()) - { - ret += "req_team_size : "+_ReqTeamSize+NL; - } - if (!_ReqBrick.empty()) - { - ret += "req_brick : "; - for (uint i=0; i<_ReqBrick.size(); ++i) - { - ret += _ReqBrick[i]; - if(i < _ReqBrick.size()-1) - ret +="; "; - ret += NL; - } - } - if (!_ReqSeason.empty()) - { - ret += "req_season : "+_ReqSeason+NL; - } - if (!_ReqEncyclo.empty()) - { - ret += "req_encyclo_thema : " + _ReqEncyclo + NL; - } - if (!_ReqEncycloNeg.empty()) - { - ret += "req_encyclo_thema_neg : " + _ReqEncycloNeg + NL; - } - if (!_ReqEventFaction.empty()) - { - ret += "req_event_faction : " + _ReqEventFaction + NL; - } - - return ret; -} - - -string CMissionData::generateMissionScript(const std::string &primFileName) -{ - _JumpPoints.clear(); - // first, gather jump point list - for (uint i=0; i<_Steps.size(); ++i) - { - set temp; - _Steps[i]->fillStepJump(*this, temp); - - // remove any jump to the next step (normal flow) - if (i < _Steps.size()-1) - { - set::iterator first(temp.begin()), last(temp.end()); - for (; first != last; ) - { - const TJumpInfo &ji = *first; - - if (ji.StepName == _Steps[i+1]->getStepName() && ji.Discardable) - { - temp.erase(first); - first = temp.begin(); - } - else - ++first; - } - } - - _JumpPoints.insert(temp.begin(), temp.end()); - } - // generate the script - string script; - // generate mission header - script += "# script generated from '"+CFile::getFilename(primFileName)+"'"+NL+NL; - script += "#mission tags and pre-requisites"+NL; - if (_MonoInstance) - script += "mono"+NL; - if (_RunOnce) - script += "once"+NL; - if (_Replayable) - script += "replayable"+NL; - if (_Solo) - script += "solo"+NL; - if (_Guild) - script += "guild"+NL; - if (_NotInJournal) - script += "no_list"+NL; - if (_AutoRemoveFromJournal) - script += "auto_remove"+NL; - if (!_MissionCategory.empty()) - script += "mission_category : "+_MissionCategory+NL; - if (_PlayerReplayTimer != 0) - script += "player_replay_timer : "+toString("%u", _PlayerReplayTimer)+NL; - if (_GlobalReplayTimer != 0) - script += "global_replay_timer : "+toString("%u", _GlobalReplayTimer)+NL; - if (_NotProposed) - script += "not_proposed"+NL; - if (_MissionAuto) - script += string("auto : ")+_MissionAutoMenu.genScript(*this)+NL; - if (_NonAbandonnable) - script += "non_abandonnable"+NL; - if (!_MissionIcon.empty()) - script += "mission_icon : "+_MissionIcon+NL; - if (_NeedValidation) - script += "need_validation"+NL; - if (_FailIfInventoryIsFull) - script += "fail_if_inventory_is_full"+NL; - - if (!_ParentMissions.empty()) - { - set::iterator first(_ParentMissions.begin()), last(_ParentMissions.end()); - for (; first != last; ++first) - { - script += "parent : "+ *first+NL; - } - } - - script += NL+"#Variables declaration"+NL; - - // declare all the variables - { - std::vector::iterator first(_VariablesOrder.begin()), last(_VariablesOrder.end()); - for (; first != last; ++first) - { - script += (*first)->genDecl(*this); - } - } - - script += NL+"#pre-requisites"+NL; - script += genPreRequisites(); - - script += NL+"#script"+NL; - // generate mission title and desc - script += "mission_title : "+_MissionTitle.genScript(*this)+NL; - script += "mission_desc : "+_MissionDescription.genScript(*this)+NL; - - // generate steps scripts - for (uint i=0; i<_Steps.size(); ++i) - { - script += "# "+_Steps[i]->getStepName()+NL; - if (_JumpPoints.find(_Steps[i]->getStepName()) != _JumpPoints.end() - && !_Steps[i]->isAJump()) - { - // insert a jump point - script += "jump_point : " + _Steps[i]->getStepName() + NL; - } - - script += _Steps[i]->genCode(*this); - //if (_Steps[i]->EndOfBranch && !_Steps[i]->isAJump()) - // script += "end"+NL; - } - - return script; -} - -string CMissionData::generatePhraseFile() -{ - string ret; - // generate header phrase - ret = _MissionTitle.genPhrase(); - ret += _MissionDescription.genPhrase(); - ret += _MissionAutoMenu.genPhrase(); - - // generate var phrase - for (uint i=0; i<_VariablesOrder.size(); ++i) - { - ret += _VariablesOrder[i]->genPhrase(); - } - - // generate step phrase - for (uint i=0; i<_Steps.size(); ++i) - { - ret += _Steps[i]->genPhrase(); - } - return ret; -} - -string CMissionData::generateDotScript() -{ - string ret = "digraph " + _MissionName + NL; - ret += "{" + NL; - - // set default shape to 'record' - ret += "node [shape=record]"+NL; - - ret += "\t__start__ [shape=\"point\", peripheries=2, label=\"\"]"+NL; - - // 1st pass, generate node for each step - for (uint i=0; i<_Steps.size(); ++i) - { - if (!_Steps[i]->isEnd() && !_Steps[i]->isAJump()) - { - ret += "\t"+_Steps[i]->getStepName(); - ret += " [URL=\""+buildPrimPath(_Steps[i]->getPrimitive())+"\"]"+NL; - } - } - - ret += "\t__end__ [shape=\"point\"]"+NL; - - // activate red color for shapes that are created after this points - ret += "node [color=red]"+NL; - - // 2nd pass, generate link between steps - for (uint i=0; i<_Steps.size(); ++i) - { - if (_Steps[i]->isAJump()) - continue; - - if (i == 0) - { - ret += "\t__start__ -> " + _Steps[i]->getStepName() + NL; - } - set jumps; - _Steps[i]->fillStepJump(*this, jumps); - // there is a link there - while (!jumps.empty()) - { - const TJumpInfo &ji = *(jumps.begin()); - if (_StepsByNames.find(ji.StepName) != _StepsByNames.end() - && _StepsByNames[ji.StepName]->isAJump()) - { - // this step is a jump, skip to link to the jump destination - IStep *jumpStep = _StepsByNames[ji.StepName]; - set jumpJump; - jumpStep->fillStepJump(*this, jumpJump); - if (jumpJump.size() != 1) - { - string str = toString("Step jump contains %u jumps destination instead of 1", jumpJump.size()); - throw EParseException(jumpStep->getPrimitive(), str.c_str()); - } - - ret += "\t"+_Steps[i]->getStepName() + " -> " + jumpJump.begin()->StepName+" [label=\""+ji.JumpName+"\"]" + NL; - } - else - { - ret += "\t"+_Steps[i]->getStepName() + " -> " + ji.StepName+" [label=\""+jumps.begin()->JumpName+"\"]" + NL; - } - jumps.erase(jumps.begin()); - } - - } - - ret += "}" + NL; - - return ret; -} - - -void CMissionData::parseMissionHeader(NLLIGO::IPrimitive *prim) -{ -// _MissionName = getProperty(prim, "name", false, false); -// if( _MissionName.find(' ') != string::npos) -// { -// throw EParseException(prim, toString("Mission name '%s' must not contains space", _MissionName.c_str()).c_str()); -// } - _GiverPrimitive = getProperty(prim,"giver_primitive", true, false); - _MissionGiver = getProperty(prim, "mission_giver", true, false); - -// _Alias = getProperty(prim, "alias", false, false); - - // If the mission is under a npc_bot node, then the giver is directly taken - // from the npc name - if (prim->getParent()) - { - if (getProperty(prim->getParent(), "class", false, false) == "npc_bot") - { - _MissionGiver = getProperty(prim->getParent(), "name", false, false); - } - } - - vector vs; - _MissionTitleRaw = getPropertyArray(prim, "mission_title", false, false); -// _MissionTitle.init(*this, prim, vs); - _MissionDescriptionRaw = getPropertyArray(prim, "mission_description", false, false); -// _MissionDescription.init(*this, prim, vs); - _MonoInstance = strlwr(getProperty(prim, "mono_instance", true, false)) == "true"; - _RunOnce = strlwr(getProperty(prim, "run_only_once", true, false)) == "true"; - _Replayable = strlwr(getProperty(prim, "replayable", true, false)) == "true"; - - _NeedValidation = strlwr(getProperty(prim, "need_validation", true, false)) == "true"; - - _MissionAutoMenuRaw = getPropertyArray(prim, "phrase_auto_menu", false, false); - - // audience setting - string s = getProperty(prim, "audience", false, false); - if (s == "solo") - _Solo = true; - else if (s == "guild") - _Guild = true; - - _NotInJournal = NLMISC::toLower(getProperty(prim, "not_in_journal", false, false)) == "true"; - _AutoRemoveFromJournal = NLMISC::toLower(getProperty(prim, "auto_remove_from_journal", false, false)) == "true"; - _MissionCategory = getProperty(prim, "mission_category", false, false); - NLMISC::fromString(getProperty(prim, "player_replay_timer", true, false), _PlayerReplayTimer); - NLMISC::fromString(getProperty(prim, "global_replay_timer", true, false), _GlobalReplayTimer); - _NotProposed = NLMISC::toLower(getProperty(prim, "not_proposed", false, false)) == "true"; - _MissionAuto = NLMISC::toLower(getProperty(prim, "automatic", false, false)) == "true"; - _NonAbandonnable = NLMISC::toLower(getProperty(prim, "non_abandonnable", false, false)) == "true"; - _FailIfInventoryIsFull = NLMISC::toLower(getProperty(prim, "fail_if_inventory_is_full", false, false)) == "true"; - _MissionIcon = getProperty(prim, "mission_icon", false, false); - - if (_MissionAuto) - { - if (_MissionAutoMenuRaw.empty()) - { - string error = toString("Mission is flagged automatic, but no phrase_auto_menu defined !"); - throw EParseException(prim, error.c_str()); - } - } - - vs = getPropertyArray(prim, "parent_missions", true, false); - _ParentMissions.insert(vs.begin(), vs.end()); - -} - -void CMissionData::parsePrerequisites(NLLIGO::IPrimitive *prim) -{ - // skills - vector vs; - vs = getPropertyArray(prim, "require_skill/min_level/max_level", true, false); - for (uint i=0; i parts; - strtokquote(vs[i], parts); - if (parts.size() != 3) - { - throw EParseException(prim, toString("Invalide argument count in line %u of require_skill array. Need 3, found %u", i, parts.size()).c_str()); - } - TReqSkill rs; - rs.Skill = parts[0]; - rs.MinLevel = parts[1]; - rs.MaxLevel = parts[2]; - - _ReqSkills.push_back(rs); - - } - } - // Mission done - vs = getPropertyArray(prim, "require_mission_done", true, false); - for (uint i=0; i parts; - strtokquote(vs[i], parts); - if (parts.size() != 1) - { - throw EParseException(prim, toString("Invalide argument count in line %u of require_mission_done array. Need 1, found %u", i, parts.size()).c_str()); - } - _ReqMissionDone.push_back(parts[0]); - } - } - // Mission not done - vs = getPropertyArray(prim, "require_mission_not_done", true, false); - for (uint i=0; i parts; - strtokquote(vs[i], parts); - if (parts.size() != 1) - { - throw EParseException(prim, toString("Invalide argument count in line %u of require_mission_not_done array. Need 1, found %u", i, parts.size()).c_str()); - } - _ReqMissionNotDone.push_back(parts[0]); - } - } - // Mission running - vs = getPropertyArray(prim, "require_mission_running", true, false); - for (uint i=0; i parts; - strtokquote(vs[i], parts); - if (parts.size() != 1) - { - throw EParseException(prim, toString("Invalide argument count in line %u of require_mission_running array. Need 1, found %u", i, parts.size()).c_str()); - } - _ReqMissionRunning.push_back(parts[0]); - } - } - // Mission not running - vs = getPropertyArray(prim, "require_mission_not_running", true, false); - for (uint i=0; i parts; - strtokquote(vs[i], parts); - if (parts.size() != 1) - { - throw EParseException(prim, toString("Invalide argument count in line %u of require_mission_not_running array. Need 1, found %u", i, parts.size()).c_str()); - } - _ReqMissionNotRunning.push_back(parts[0]); - } - } - // wearing item - vs = getPropertyArray(prim, "require_wearing_item", true, false); - for (uint i=0; i parts; - strtokquote(vs[i], parts); - if (parts.size() != 1) - { - throw EParseException(prim, toString("Invalide argument count in line %u of require_wearing_item array. Need 1, found %u", i, parts.size()).c_str()); - } - _ReqWearItem.push_back(parts[0]); - } - } - // own item - vs = getPropertyArray(prim, "require_own_item", true, false); - for (uint i=0; i parts; - strtokquote(vs[i], parts); - if (parts.size() != 1) - { - throw EParseException(prim, toString("Invalide argument count in line %u of require_own_item array. Need 1, found %u", i, parts.size()).c_str()); - } - _ReqOwnItem.push_back(parts[0]); - } - } - // title - _ReqTitle = getProperty(prim, "require_title", true, false); - // fame - vs = getPropertyArray(prim, "require_faction/fame", true, false); - for (uint i=0; i parts; - strtokquote(vs[i], parts); - if (parts.size() != 2) - { - throw EParseException(prim, toString("Invalide argument count in line %u of require_faction/fame array. Need 2, found %u", i, parts.size()).c_str()); - } - TReqFame rf; - rf.Faction = parts[0]; - rf.Fame = parts[1]; - - _ReqFames.push_back(rf); - } - } - // guild - if (getProperty(prim, "require_guild_membership", true, false) == "true") - _ReqGuild = true; - else - _ReqGuild = false; - // grade - _ReqGrade = getProperty(prim, "require_guild_grade", true, false); - // team size - _ReqTeamSize = getProperty(prim, "require_team_size", true, false); - // brick - vs = getPropertyArray(prim, "require_brick_knowledge", true, false); - for (uint i=0; i parts; - strtokquote(vs[i], parts); - if (parts.size() != 1) - { - throw EParseException(prim, toString("Invalide argument count in line %u of require_brick_knowledge array. Need 1, found %u", i, parts.size()).c_str()); - } - _ReqBrick.push_back(parts[0]); - } - } - // season - _ReqSeason = getProperty(prim, "require_season", true, false); - // encyclopedia - _ReqEncyclo = getProperty(prim, "require_encyclo_thema", true, false); - _ReqEncycloNeg = getProperty(prim, "require_encyclo_thema_neg", true, false); - - if ((!_ReqEncyclo.empty() && !_ReqEncycloNeg.empty()) - || (!_ReqEncycloNeg.empty() && !_ReqEncyclo.empty())) - { - string err = toString("You can't mix positive and negative encyclopedy requirement"); - throw EParseException(prim, err.c_str()); - } - // event faction - _ReqEventFaction = getProperty(prim, "require_event_faction", true, false); -} - -std::string CMissionData::replaceVar(NLLIGO::IPrimitive *prim, const std::string &str) -{ - string::size_type pos = 0; - string::size_type pos2 = 0; - string ret; - - while (pos < str.size()) - { - if (str[pos] != '$') - { - ret += str[pos++]; - } - else if (pos+1 < str.size() && str[pos+1] == '$') - { - // check that this $ is not escaped - ret += '$'; - pos+=2; - } - else - { - // ok, this is not an escaped $ - CSString varName; - // skip the initial '$' - pos++; -// while (str[pos] != ' ' && str[pos] != '\t' && str[pos] != '\n' && str[pos] != '\r') - while (pos < str.size() && str[pos] != '$') - varName += str[pos++]; - - if (pos >= str.size()) - { - string err = toString("Error while parsing variable in '%s', missing closing '$'", str.c_str()); - throw EParseException (NULL, err.c_str()); - } - - // skip the final '$' - pos++; - - // split the var name and subpart - vector varParts; - explode(string(varName), string("@"), varParts, true); - - if (varParts.empty() || varParts.size() > 2) - { - throw EParseException(prim, toString("Error parsing varName '%s' in string '%s'", varName.c_str(), str.c_str()).c_str()); - } - - if (_Variables.find(varParts.front()) == _Variables.end()) - { - string err = toString("Unknown variable '%s' in string '%s'", varParts.front().c_str(), str.c_str()); - throw EParseException (prim, err.c_str()); - } - - IVar *var = _Variables[varParts[0]]; - - if (varParts.size() == 1) - ret += var->evalVar(""); - else - ret += var->evalVar(varParts[1]); - - } - } - - return ret; -} - -std::vector CMissionData::replaceVar(NLLIGO::IPrimitive *prim, const std::vector &strs) -{ - vector ret; - - for (uint i=0; igetPropertyByName(propertyName.c_str(), s)) - { - if (!canFail) - { - string err = toString("Can't find property '%s'", propertyName.c_str()); - throw EParseException (prim, err.c_str()); - } - } - else - { - ret = *s; - } - - if (replaceVar) - { - ret = this->replaceVar(prim, ret); - } - - return ret; -} - -std::vector CMissionData::getPropertyArray(NLLIGO::IPrimitive *prim, const std::string &propertyName, bool replaceVar, bool canFail) -{ - vector ret; - vector *vs; - if (!prim->getPropertyByName(propertyName.c_str(), vs)) - { - if (!canFail) - { - string err = toString("Can't find property '%s'", propertyName.c_str()); - throw EParseException (prim, err.c_str()); - } - } - else - { - ret = *vs; - } - - if (replaceVar) - { - ret = this->replaceVar(prim, ret); - } - return ret; -} - -bool CMissionData::isThereAJumpTo(const std::string &stepName) -{ - if (_JumpPoints.find(stepName) != _JumpPoints.end()) - return true; - else - return false; -} - -void TCompilerVarName::init(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string propName) -{ - _DefaultName = defaultName; - _ParamType = type; - - _VarName = md.getProperty(prim, propName, false, false); - // remove the variable tag if any - untagVar(_VarName); - - _VarValue = md.getProperty(prim, propName, true, false); -} - -void TCompilerVarName::initWithText(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string &text) -{ - _DefaultName = defaultName; - _ParamType = type; - - _VarName = text; - // remove the variable tag if any - untagVar(_VarName); - - _VarValue = md.replaceVar(prim, text); -} - - -CPhrase::TParamInfo TCompilerVarName::getParamInfo() const -{ - if (_VarName.empty()) - return CPhrase::TParamInfo(_DefaultName, _ParamType); - else - return CPhrase::TParamInfo(_VarName, _ParamType); -} - - -bool TCompilerVarName::empty() const -{ - return _VarValue.empty(); -} - -TCompilerVarName::operator const std::string () const -{ - return _VarValue; -} - -TCompilerVarName::operator CPhrase::TParamInfo() const -{ - return getParamInfo(); -} - - -std::string operator+(const TCompilerVarName& left, const std::string & right) { return left._VarValue + right;} - -std::string operator+(const std::string & left, const TCompilerVarName& right) { return left + right._VarValue;} - -std::vector TCompilerVarName::getPropertyArrayWithText(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string & arrayProperyName) -{ - std::vector compilerParams; - - std::vector values = md.getPropertyArray(prim, arrayProperyName,false, false); - uint first = 0; - uint last = (uint)values.size(); - compilerParams.resize(last); - for ( ; first != last; ++first) - { - compilerParams[first].initWithText( toString("%s%d", defaultName.c_str(), first+1) , type, md, prim, values[first]); - } - - return compilerParams; -} - -std::vector TCompilerVarName::getPropertyArrayWithTextStaticDefaultName(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string & arrayProperyName) -{ - std::vector compilerParams; - std::vector values = md.getPropertyArray(prim, arrayProperyName,false, false); - uint first = 0; - uint last = (uint)values.size(); - compilerParams.resize(last); - for ( ; first != last; ++first) - { - compilerParams[first].initWithText( defaultName, type, md, prim, values[first]); - } - return compilerParams; -} - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "mission_compiler.h" +#include "step.h" +#include "nel/misc/i18n.h" +#include "nel/ligo/primitive_utils.h" + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; + + +// hack to get access to string manager item enumeration to string without including +// almost all of the Ryzom server side project +namespace STRING_MANAGER +{ + NL_BEGIN_STRING_CONVERSION_TABLE (TParamType) + NL_STRING_CONVERSION_TABLE_ENTRY( item ) + NL_STRING_CONVERSION_TABLE_ENTRY( place ) + NL_STRING_CONVERSION_TABLE_ENTRY( creature ) + NL_STRING_CONVERSION_TABLE_ENTRY( skill ) + NL_STRING_CONVERSION_TABLE_ENTRY( role ) + NL_STRING_CONVERSION_TABLE_ENTRY( ecosystem ) + NL_STRING_CONVERSION_TABLE_ENTRY( race ) + NL_STRING_CONVERSION_TABLE_ENTRY( sbrick ) + NL_STRING_CONVERSION_TABLE_ENTRY( faction ) + NL_STRING_CONVERSION_TABLE_ENTRY( guild ) + NL_STRING_CONVERSION_TABLE_ENTRY( player ) + NL_STRING_CONVERSION_TABLE_ENTRY( bot ) + { "int", integer}, +// NL_STRING_CONVERSION_TABLE_ENTRY( integer ) + NL_STRING_CONVERSION_TABLE_ENTRY( time ) + NL_STRING_CONVERSION_TABLE_ENTRY( money ) + NL_STRING_CONVERSION_TABLE_ENTRY( compass ) + NL_STRING_CONVERSION_TABLE_ENTRY( string_id ) + NL_STRING_CONVERSION_TABLE_ENTRY( dyn_string_id ) + NL_STRING_CONVERSION_TABLE_ENTRY( self ) + NL_STRING_CONVERSION_TABLE_ENTRY( creature_model ) + NL_STRING_CONVERSION_TABLE_ENTRY( entity ) + NL_STRING_CONVERSION_TABLE_ENTRY( body_part ) + NL_STRING_CONVERSION_TABLE_ENTRY( score ) + NL_STRING_CONVERSION_TABLE_ENTRY( sphrase ) + NL_STRING_CONVERSION_TABLE_ENTRY( characteristic ) + NL_STRING_CONVERSION_TABLE_ENTRY( damage_type ) + NL_STRING_CONVERSION_TABLE_ENTRY( bot_name) + NL_STRING_CONVERSION_TABLE_ENTRY( power_type ) + NL_STRING_CONVERSION_TABLE_ENTRY( literal ) + NL_END_STRING_CONVERSION_TABLE(TParamType, ParamTypeConversion, NB_PARAM_TYPES) + + //----------------------------------------------- + // stringToParamType + //----------------------------------------------- + TParamType stringToParamType( const std::string & str ) + { + return ParamTypeConversion.fromString( str ); + } + + //----------------------------------------------- + // stringToParamType + //----------------------------------------------- + const std::string & paramTypeToString( TParamType type ) + { + return ParamTypeConversion.toString( type ); + } +} + +// utility to 'tabulate' the lines in a string +void tabulateLine(std::string &text, uint nbTabs) +{ + if (text.empty()) + return; + string::size_type pos = 0; + string tabs; + + for (uint i=0; i 2) + { + if (_EntityName[0] == '$' && _EntityName[_EntityName.size() - 1] == '$') + { + _EntityName = _EntityName.substr(1, _EntityName.size() - 2); + } + } + + std::string newLiteral = before + after; + + bool isFemale = parseMarkup(newLiteral,f,newPhrase, true); + if ( isFemale) + { + parseMarkup(newPhrase,h,newPhrase, false); + femaleText = newPhrase; + } + + bool isMale = parseMarkup(newLiteral, h, newPhrase, true); + if (isMale) + { + + parseMarkup(newPhrase, f, newPhrase, false); + maleText = newPhrase; + } + + if (isMale != isFemale) + { + std::string goodMarkup = isMale ? std::string("") +"<" + h + ">" : std::string("")+"<"+f+">"; + std::string badMarkup = isFemale ? std::string("") +"<" + h + ">" : std::string("")+"<"+f+">"; + std::string exceptionText = std::string("La phrase ") + identifier + " qui contient une balise " + goodMarkup + " nécessite aussi les balises " + badMarkup + " même vide."; + throw EParseException(0, exceptionText.c_str()); + } + + if (!isMale && !isFemale) + { + _Text = literal; + _Female = 0; + _Male = 0; + + } + else + { + if (!_Entity) { _EntityName = "self"; } + _Female = new GenderExtractor(femaleText, identifier, level+1); + _Male = new GenderExtractor(maleText, identifier, level+1); + } + + + +} + +bool GenderExtractor::extractMarkup(const std::string& literal, const std::string & markup, std::string &before, std::string &inside, std::string & after) +{ + std::string::size_type posBegin; + std::string::size_type posEnd; + std::string::size_type posInside; + + std::string beginMarkup = std::string("<") + markup + std::string(">"); + std::string endMarkup = std::string(""); + posBegin = literal.find(beginMarkup); + if ( posBegin != std::string::npos ) + { + posEnd = literal.find(endMarkup, posBegin + beginMarkup.size()); + if (posEnd != std::string::npos) + { + before = literal.substr(0, posBegin); + posInside = posBegin + beginMarkup.size(); + inside = literal.substr(posInside, posEnd - posInside); + after = literal.substr(posEnd+endMarkup.size()); + return true; + } + } + after = literal; + return false; +} + +bool GenderExtractor::parseMarkup(const std::string& literal, const std::string & markup, std::string& newPhrase, bool include ) +{ + + bool markupExist; + bool changed = false; + std::string oldPhrase = literal; + + newPhrase = ""; + do + { + std::string before; + std::string inside; + std::string after; + markupExist = extractMarkup(oldPhrase, markup, before, inside, after); + newPhrase += before; + if (include){ newPhrase += inside; } + oldPhrase = after; + if (markupExist){ changed = true; } + + } while(markupExist); + + newPhrase += oldPhrase; + return changed; +} + +std::string GenderExtractor::getPhrase(unsigned int i) const +{ + if ( i%2 == 0) { return _Male ? _Male->getPhrase(i/2) : _Text; } + if ( i%2 == 1) { nlassert(_Female); return _Female->getPhrase(i/2);} + nlassert(0); + return ""; +} + +std::string GenderExtractor::getExtension(unsigned int i) const +{ + if ( i%2 == 0) { return _Male ? std::string("_m") + _Male->getExtension(i/2) : ""; } + if ( i%2 == 1) { nlassert(_Female); return std::string("_f") + _Female->getExtension(i/2);} + nlassert(0); + return ""; +} + +std::string GenderExtractor::getCondition(unsigned int i) const +{ + + //if ( i%2 == 0) { return _Male ? std::string("\t(") + _Male->getExtension(i/2) : "\t"; } + //if ( i%2 == 1) { nlassert(_Female); return std::string("_f") + _Female->getExtension(i/2);} + + if ( i%2 == 0) + { + if (_Male) + { + std::string next = _Male->getCondition(i/2); + std::string current = _EntityName + ".gender = male"; + return next.size() ? current + " & " + next : current; + + } + else + { + return ""; + } + } + + if ( i%2 == 1) + { + std::string next = _Female->getCondition(i/2); + std::string current = _EntityName + ".gender = female"; + return next.size() ? current + " & " + next : current; + } + + nlassert(0); + + return ""; +} + +unsigned int GenderExtractor::size() const +{ + return _Male ? _Male->size() + _Female->size(): 1; +} + + +string CPhrase::genPhrase() +{ + string ret; + if (!_PhraseLiterals.empty()) + { + for (uint p=0; p<_PhraseLiterals.size(); ++p) + { + string identifier = _PhraseId; + if (_NumEntry != 0) + identifier += toString("_%u", p+1); + + GenderExtractor gender(_PhraseLiterals[p], identifier, 0); + + ret += identifier + " ("; + // generate default param list + if (_DefaultParams.size() > p) + { + for (uint i=0; i<_DefaultParams[p].size(); ++i) + { + ret += STRING_MANAGER::paramTypeToString(_DefaultParams[p][i].ParamType) + " "+_DefaultParams[p][i].ParamName; + if (i != _DefaultParams[p].size()-1 || !_AdditionalParams.empty()) + ret += ", "; + } + } + // generate additional param list + for (uint i=0; i<_AdditionalParams.size(); ++i) + { + ret += STRING_MANAGER::paramTypeToString(_AdditionalParams[i].ParamType) + " "+_AdditionalParams[i].ParamName; + if (i != _AdditionalParams.size()-1) + ret += ", "; + } + ret += ")" + NL; + ret += "{" + NL; + + for (unsigned int i = 0; i < gender.size(); ++i) + { + ret += gender(i); + } + + ret += "}" + NL + NL; + } + } +nlinfo("genphrase: %s", ret.c_str()); + return ret; +} + + + + +bool CMissionCompiler::generateDotScript(NLLIGO::IPrimitive *missionPrim, std::string &dotScript, std::string &log) +{ + //assume that the mission is compiled in the last compiled mission slot + try + { + if (compileMission(missionPrim, string())) + { + dotScript = _CompiledMission.back()->generateDotScript(); + return true; + } + else + { + return false; + } + } + catch(const EParseException & e) + { + log = e.Why; + return false; + } +} + +/* +bool CMissionCompiler::parseGlobalMissionData(IPrimitive *mission, CMissionData &md) +{ + // Mission name + string *s; + if (!mission->getPropertyByName("name", s) || s->empty()) + throw EParseException(mission, "missing mission name !"); + md.setMissionName(*s); + + // giver primitive file + if (!mission->getPropertyByName("giver_primitive", s) || s->empty()) + throw EParseException(mission, "missing giver primitive !"); + md.setGiverPrimitive(*s); + + // giver name + if (!mission->getPropertyByName("giver_primitive", s) || s->empty()) + throw EParseException(mission, "missing giver primitive !"); + md.setGiverName(*s); + // If the mission is under a npc_bot node, then the giver is directly taken + // from the npc name + if (mission->getParent()) + { + if (mission->getParent()->getPropertyByName("class", s) && *s == "npc_bot") + { + if (mission->getParent()->getPropertyByName("name", s)) + md.setGiverName(*s); + } + } + + // TODO : read all other params... + + return true; +} +*/ + +void CMissionData::initHeaderPhrase(IPrimitive *prim) +{ + CPhrase::TPredefParams params; + params.resize(1); + params[0].push_back(CPhrase::TParamInfo("giver", STRING_MANAGER::bot)); + _MissionTitle.initPhrase(*this, prim, _MissionTitleRaw, 0, params); + _MissionDescription.initPhrase(*this, prim, _MissionDescriptionRaw, 0, params); + _MissionAutoMenu.initPhrase(*this, prim, _MissionAutoMenuRaw); +} + +bool CMissionCompiler::compileMission(NLLIGO::IPrimitive *rootPrim, const std::string &primFileName) +{ + TPrimitiveClassPredicate pred("mission_tree"); + if (!pred(rootPrim)) + return false; + + IPrimitive *mission = rootPrim; + CMissionData *pmd = new CMissionData; + CMissionData &md = *pmd; + + // Read the mission name + string missionName = md.getProperty(mission, "name", false, false); + if( missionName.find(' ') != string::npos) + { + throw EParseException(mission, toString("Mission name '%s' must not contains space", missionName.c_str()).c_str()); + } + md.setMissionName(missionName); + // Create a temporary primitive node to create default variable + { + // giver default var + IPrimitive *temp = new CPrimNode(); + temp->addPropertyByName("class", new CPropertyString("var_npc")); + temp->addPropertyByName("name", new CPropertyString("giver = giver")); + temp->addPropertyByName("npc_name", new CPropertyString("giver")); + temp->addPropertyByName("var_name", new CPropertyString("giver")); + + IVar *var = IVar::createVar(md, temp); + md.addVariable(NULL, var); + + delete temp; + } + + { + // player default var + IPrimitive *temp = new CPrimNode(); + temp->addPropertyByName("class", new CPropertyString("var_npc")); + temp->addPropertyByName("name", new CPropertyString("player = player")); + temp->addPropertyByName("npc_name", new CPropertyString("player")); + temp->addPropertyByName("var_name", new CPropertyString("player")); + + IVar *var = IVar::createVar(md, temp); + md.addVariable(NULL, var); + + delete temp; + } + + { + // guild_name default var + IPrimitive *temp = new CPrimNode(); + temp->addPropertyByName("class", new CPropertyString("var_text")); + temp->addPropertyByName("name", new CPropertyString("guild_name = guild_name")); + temp->addPropertyByName("npc_name", new CPropertyString("guild_name")); + temp->addPropertyByName("var_name", new CPropertyString("guild_name")); + + IVar *var = IVar::createVar(md, temp); + md.addVariable(NULL, var); + + delete temp; + } + + // first, start by reading mission variables + IPrimitive *variables; + { + TPrimitiveClassPredicate predTmp("variables"); + variables= NLLIGO::getPrimitiveChild(mission, predTmp); + } + + if (!variables) + { + nlwarning("Can't find variables !"); + return false; + } + parseVariables(md, variables); + + // read global mission data + md.parseMissionHeader(rootPrim); + + // now, we can init the mission header phrase (they need variable knwoled) + md.initHeaderPhrase(rootPrim); + + IPrimitive *preReq; + { + TPrimitiveClassPredicate predTmp("pre_requisite"); + preReq = getPrimitiveChild(mission, predTmp); + } + + if (!preReq) + { + nlwarning("Can't find pre requisite !"); + return false; + } + parsePreRequisite(md, preReq); + +/* IPrimitive *steps = getPrimitiveChild(mission, TPrimitivePropertyPredicate("step_tag", "true")); + if (!steps) + { + nlwarning("Can't find steps !"); + return false; + } +*/ parseSteps(md, mission); + + // Store the compiled mission + _CompiledMission.push_back(pmd); + + string script = md.generateMissionScript(primFileName); + + nlinfo("The script :"); + nlinfo("%s", script.c_str()); + + string phrases = md.generatePhraseFile(); + nlinfo("The phrase file is :"); + { + vector lines; + explode(phrases, string("\n"), lines, false); + for (uint i=0; i lines; + explode(dot, string("\n"), lines, false); + for (uint i=0; i scriptsSet; + + TPrimitiveClassPredicate pred("mission_tree"); + scriptsSet.buildSet(rootPrim, pred, missionTrees); + + nlinfo("Found %u mission tree in the primitive file", missionTrees.size()); + + for (uint i=0; i loadedPrimitives; + + // store the previous alias value + map missionAlias; + + // First loop to remove any mission that belong to the compiled primitive file + for (uint i=0; i<_CompiledMission.size(); ++i) + { + CMissionData &mission = *(_CompiledMission[i]); + // first, look for the primitive file to load + string fileName = mission.getGiverPrimitive(); + if (fileName.empty()) + { + // use mission primitive instead + fileName = primFileName; + } + if (loadedPrimitives.find(toLower(fileName)) == loadedPrimitives.end()) + { + string fullFileName = CPath::lookup(fileName, false); + if (fullFileName.empty()) + { + throw EParseException(NULL, toString("Can't find primitive file '%s' in path", fileName.c_str()).c_str()); + } + // we need to load this primitive file. + CPrimitives *primDoc = new CPrimitives; + CPrimitiveContext::instance().CurrentPrimitive = primDoc; + if (loadXmlPrimitiveFile(*primDoc, fullFileName, ligoConfig)) + { + // the primitive file is loaded correctly + loadedPrimitives.insert(make_pair(toLower(fileName), TLoadedPrimitive(primDoc, fullFileName))); + CPrimitiveContext::instance().CurrentPrimitive = NULL; + } + else + { + CPrimitiveContext::instance().CurrentPrimitive = NULL; + throw EParseException(NULL, toString("Can't read primitive file '%s'", fullFileName.c_str()).c_str()); + } + } + TLoadedPrimitive &loadedPrim = loadedPrimitives[toLower(fileName)]; + CPrimitives *primDoc = loadedPrim.PrimDoc; + + TPrimitiveSet scripts; + CPrimitiveSet filter; + TPrimitiveClassPredicate pred("mission"); + filter.buildSet(primDoc->RootNode, pred, scripts); + + // for each script, check if it was generated, and if so, check the name + // of the source primitive file. + for (uint i=0; i *script; + if (scripts[i]->getPropertyByName("script", script) && !script->empty()) + { + string missionName; + + scripts[i]->getPropertyByName("name", missionName); + + // Format should be : #compiled from + if (script->front().find("generated from") != string::npos) + { + // we have a compiled mission + if (script->front().find(CFile::getFilename(primFileName)) != string::npos) + { + // ok, this mission is compiled from the same primitive + + // store it's alias + TPrimitiveClassPredicate pred("alias"); + + IPrimitive *p = getPrimitiveChild(scripts[i], pred); + + if (p) + { + CPrimAlias *pa = dynamic_cast(p); + if (pa) + { + uint32 alias = pa->getAlias(); + missionAlias.insert(make_pair(missionName, alias)); + } + } + else + { + nlwarning("Can't find alias prim in primitive '%s'", buildPrimPath(scripts[i]).c_str()); + } + + // and remove it + scripts[i]->getParent()->removeChild(scripts[i]); + } + } + } + } + } + + // second loop to assign compiled mission to giver npc + for (uint i=0; i<_CompiledMission.size(); ++i) + { + CMissionData &mission = *(_CompiledMission[i]); + string fileName = mission.getGiverPrimitive(); + if (fileName.empty()) + { + // no giver primitive file specified in the mission, use the mission primitive instead + fileName = primFileName; + } + + TLoadedPrimitive &loadedPrim = loadedPrimitives[toLower(fileName)]; + CPrimitives *primDoc = loadedPrim.PrimDoc; + CPrimitiveContext::instance().CurrentPrimitive = primDoc; + + TPrimitiveSet bots; + CPrimitiveSet filter; + TPrimitiveClassAndNamePredicate pred("npc_bot", mission.getGiverName()); + filter.buildSet(primDoc->RootNode, pred, bots); + + if (bots.empty()) + { + string err = toString("Can't find bot '%s' in primitive '%s' !", + mission.getGiverName().c_str(), + fileName.c_str()); + throw EParseException(NULL, err.c_str()); + } + else if (bots.size() > 1) + { + string err = toString("Found more than one bot named '%s' in primitive '%s' !", + mission.getGiverName().c_str(), + fileName.c_str()); + throw EParseException(NULL, err.c_str()); + } + + // ok, all is good, we can add the mission node to the giver + IPrimitive *giver = bots.front(); + // create a new node for the mission + IPrimitive *script = new CPrimNode; + // set the class + script->addPropertyByName("class", new CPropertyString("mission")); + // set the name + script->addPropertyByName("name", new CPropertyString(mission.getMissionName())); +// string alias(toString("%u", makeHash32(mission.getMissionName()))); +// script->addPropertyByName("alias", new CPropertyString(mission.getAlias())); + string scriptLines = mission.generateMissionScript(primFileName); + vector lines; + explode(scriptLines, NL, lines, false); + + script->addPropertyByName("script", new CPropertyStringArray(lines)); + + // insert the script into the giver + giver->insertChild(script); + + // add the alias + { + CPrimAlias *pa = new CPrimAlias; + pa->addPropertyByName("class", new CPropertyString ("alias")); + pa->addPropertyByName("name", new CPropertyString ("alias")); + + if (missionAlias.find(mission.getMissionName()) != missionAlias.end()) + { + // restore the previous alias + primDoc->forceAlias(pa, missionAlias.find(mission.getMissionName())->second); + } + + // insert in first place + script->insertChild(pa, 0); + } + + CPrimitiveContext::instance().CurrentPrimitive = NULL; + } + + // Save the modified primitive files + while (!loadedPrimitives.empty()) + { + TLoadedPrimitive &loadedPrim = loadedPrimitives.begin()->second; + if (!saveXmlPrimitiveFile(*(loadedPrim.PrimDoc), loadedPrim.FullFileName)) + return false; + + _FilesToPublish.push_back(loadedPrim.FullFileName); + + // Free the memory + delete loadedPrim.PrimDoc; + + loadedPrimitives.erase(loadedPrimitives.begin()); + } + } + + // generate the phrase file (if any) + { + string phraseFileName = CFile::getFilenameWithoutExtension(primFileName) + "_wk.txt"; + + CSString content; + + for (uint i=0; i<_CompiledMission.size(); ++i) + { + content += _CompiledMission[i]->generatePhraseFile(); + } + // transform NL (\n\r) into single \n + content = content.replace(NL.c_str(), "\n"); + ucstring ucs; + ucs.fromUtf8(content); + + CI18N::writeTextFile(phraseFileName, ucs, true); + + _FilesToPublish.push_back(phraseFileName); + } + + return true; +} + + +bool CMissionCompiler::publishFiles(const std::string &serverPathPrim, const std::string &serverPathText, const std::string &localPathText) +{ + for (uint i=0 ; i<_FilesToPublish.size() ; i++) + { + string dst, src = _FilesToPublish[i]; + + string::size_type n = src.find("primitives"); + if (n == string::npos) + { + // text files : copy it and check include in phrase_rites_wk.txt + + // server + string textFile = CPath::standardizePath(serverPathText) + "phrase_rites_wk.txt"; + includeText(textFile, string("#include \"") + src + string("\"\n")); + dst = CPath::standardizePath(serverPathText) + src; + NLMISC::CFile::copyFile(dst, src); + + // local + textFile = CPath::standardizePath(localPathText) + "phrase_rites_wk.txt"; + includeText(textFile, string("#include \"") + src + string("\"\n")); + dst = CPath::standardizePath(localPathText) + src; + NLMISC::CFile::copyFile(dst, src); + } + else + { + // primitive file : copy to server + dst = CPath::standardizePath(serverPathPrim) + string(src, n, src.size()); + NLMISC::CFile::copyFile(dst, src); + } + } + return true; +} + +bool CMissionCompiler::includeText(const std::string filename, const std::string text) +{ + FILE *f = fopen(filename.c_str(), "r+"); + if (f == NULL) + return false; + + bool isIn = false; + char buffer[1024]; + + // Check for UTF8 format + fread(buffer, 1, 3, f); + if (buffer[0] != -17 || buffer[1] != -69 || buffer[2] != -65) + fseek(f, 0, SEEK_SET); + + // Compare each line + while(fgets(buffer, 1024, f)) + { + if (!strcmp(text.c_str(), buffer)) + { + isIn = true; + break; + } + } + + if (!isIn) + fputs(text.c_str(), f); + + fclose(f); + return true; +} + +bool CMissionCompiler::parsePreRequisite(CMissionData &md, IPrimitive *preReq) +{ + md.parsePrerequisites(preReq); + return true; +} + +bool CMissionCompiler::parseOneStep(CMissionData &md, IPrimitive *stepToParse, IStep *parent, bool bEndOfBranch) +{ + IStep *step = IStep::createStep(md, stepToParse); + if (step != NULL) + { + + if (!step->isAJump() && !step->getStepName().empty()) + { + if (md.getStepByName(step->getStepName()) != NULL) + { + string err = toString("Step '%s' already defined !", step->getStepName().c_str()); + throw EParseException(step->getPrimitive(), err.c_str()); + } + + if (step->getStepName().find(' ') != string::npos) + { + throw EParseException(step->getPrimitive(), toString("Step name '%s' must not contains space", step->getStepName().c_str()).c_str()); + } + md.addStepName(step->getStepName(), step); + } + + TPrimitiveSet subBranchs = step->getSubBranchs(); + + // Add the step (if no parent add to the mission data) + if (parent == NULL) + { + if (!md.addStep(step)) + { + throw EParseException(stepToParse, "Error parsing mission step"); + } + } + else + { + parent->addSubStep(step); + } + + CStepIf *pSI = dynamic_cast(step); + // If this is a IF step : parse with 'step' as a parent + + IStep *pParentStep = NULL; + + if ((dynamic_cast(step) != NULL) || + (dynamic_cast(step) != NULL)) + pParentStep = step; + + if (!subBranchs.empty()) + { + // need to parse subbranch before continuing + for (uint i=0; iEndOfBranch = bEndOfBranch; + } + return true; +} + +bool CMissionCompiler::parseSteps(CMissionData &md, IPrimitive *steps, IStep *parent) +{ + TPrimitiveSet childs; + TPrimitivePropertyPredicate pred("step_tag", "true"); + filterPrimitiveChilds(steps, pred, childs); + + if (childs.empty()) + { + CPrimNode node; + node.addPropertyByName("class", new CPropertyString("end")); + node.addPropertyByName("name", new CPropertyString("")); + IStep *step = IStep::createStep(md, &node); + delete step; +// md.addStep(step); + } + if (!childs.empty()) + { + for (uint i=0; igetPropertyByName(propName.c_str(), s); + if (!ret) + throw EParseException(prim, toString("Property %s does't exist", propName.c_str()).c_str()); + + return s; +} + +string CMissionCompiler::getClass(IPrimitive *prim) +{ + string className; + bool ret = prim->getPropertyByName("class", className); + nlassert(ret); + return className; +} + +bool CMissionCompiler::parseVariables(CMissionData &md, IPrimitive *variables) +{ + for (uint i=0; igetNumChildren(); ++i) + { + IPrimitive *child; + if (variables->getChild(child, i)) + { + IVar *var = IVar::createVar(md, child); + if (var) + { + nldebug("Adding variable '%s' as type %u", var->getVarName().c_str(), var->getVarType()); + md.addVariable(child, var); + } + } + } + return true; +} + +template +bool strtokquote(const string &src, VectorType &tokens) +{ + enum TMode + { + read_blank, + read_token, + read_quoted + }; + + string temp; + TMode mode = read_blank; + + for (uint i=0; i +bool strtokquote(const vector &src, VectorType &tokens) +{ + for (uint i=0; i +{ + string Name; + TFindParamPred(const std::string &name) + : Name (name) + {} + + bool operator() (const CPhrase::TParamInfo ¶mInfo) const + { + return paramInfo.ParamName == Name; + } +}; + + +bool CPhrase::isEmpty() +{ + return _PhraseId.empty(); +} + +bool CPhrase::asAdditionnalParams() +{ + return !_AdditionalParams.empty(); +} + + +void CPhrase::initPhrase (CMissionData &md, + IPrimitive *prim, + const vector &texts, + uint32 numEntry, + const TPredefParams &predefParams ) +{ +// nlassert(numEntry == predefParams.size()); + + // store the predefined/default parameters + _DefaultParams = predefParams; + // store the number of entry to generate (for literal with variant) + _NumEntry = numEntry; + + numEntry = max(uint32(1), numEntry); + + _PhraseLiterals.clear(); +// _PhraseLiterals.resize(numEntry); + + // first, concatenate the text vector + string text; + for (uint i=0; i params; + +retry: + // ok, the string is parsed, now we can analyze it + // look at the first letter of the first token to determine the type of data we have + if (tokens[0][0] == '\"') + { + // we have a literal, so we must found numEntry literal, then a suffix tag for the phrase name + if (tokens.size() != numEntry +1) + throw EParseException(prim, toString("bad number of tokens in phrase : need %u (%u entries + 1 suffix), found %u\n(in : '%s')", + numEntry+1, + numEntry, + tokens.size(), + text.c_str() + ).c_str()); + + _PhraseLiterals.resize(numEntry); + for (uint i=0; i= predefParams.size() || find_if(predefParams[i].begin(), predefParams[i].end(), TFindParamPred(static_cast(p))) == predefParams[i].end()) + { + // this param is not in the predefined params list, add it to the optional params + params.push_back(p); + } + + // remove any compiler param from the phrase literal + if (p.find("@") != string::npos) + { + string::size_type pos = _PhraseLiterals[i].find(p, paramStart); + if (pos != string::npos) + { + string::size_type pos2 = _PhraseLiterals[i].find("@", pos); + if (pos2 != string::npos) + { + while (pos2 < _PhraseLiterals[i].size() + && _PhraseLiterals[i][pos2] != '.' + && _PhraseLiterals[i][pos2] != '$') + { + _PhraseLiterals[i].erase(pos2, 1); + } + } + + } + } + } + else + { + // this is an escaped $, skip it + text.leftCrop(1); + } + } + } + } + // last, read the suffix + _Suffixe = tokens.back(); + + // generate identifier + _PhraseId = toUpper(md.getMissionName()+"_"+_Suffixe); + + set ps; + // select only unique params + ps.insert(params.begin(), params.end()); + + vector temp(ps.begin(), ps.end()); + params.swap(temp); + + } + else if (tokens[0][0] == '$') + { + // we have a variable substitution. Retrieve the var and recall init + + // do the var replacement + CVectorSString tokens2; + + tokens[0] = md.replaceVar(prim, tokens[0]); + + if (!strtokquote(tokens[0], tokens2)) + throw EParseException(prim, toString("failed to tokenize the string ('%s')", tokens[0].c_str()).c_str()); + + tokens2.insert(tokens2.end(), tokens.begin()+1, tokens.end()); + tokens.swap(tokens2); + + // and retry the decoding + goto retry; + } + else + { + // this should be a simple identifier, followed by any number of additional parameters + + // do the var replacement +// tokens = md.replaceVar(prim, tokens); +// untagVar(tokens[0]); + + // ok, now extract the phrase label and the additional parameters + _PhraseId = tokens[0]; + for (uint i=1; i(tokens[i]))) == predefParams[0].end()) + { + // this param is not in the predefined params list, add it to the optional params + params.push_back(tokens[i]); + } + } + } + + // now, build the parameter list + + vector::iterator first(params.begin()), last(params.end()); + for (; first != last; ++first) + { + string name, param; + vector parts; + NLMISC::explode(*first, string("@"), parts, false); + + if (parts.size() > 0) + name = parts[0]; + if (parts.size() > 1) + param = parts[1]; + + const string &varName = name; + + if (varName != "self") + { + IVar *var = md.getVariable(varName); + if (var == NULL) + { + string err = toString("Can't find variable '%s' referenced from a phrase", + name.c_str()); + throw EParseException(prim, err.c_str()); + } + + TParamInfo pi; + pi.ParamName = name; + pi.CompilerParam = param; + pi.ParamType = var->getStringManagerType(); + _AdditionalParams.push_back(pi); + } + } +} + +std::string CPhrase::genScript(CMissionData &md) +{ + std::string ret; + + ret = _PhraseId; + for (uint i=0; i<_AdditionalParams.size(); ++i) + { + IVar *var = md.getVariable(_AdditionalParams[i].ParamName); + if (var == NULL) + { + string err = toString("Can't find variable named '%s' to generate phrase param", _AdditionalParams[i].ParamName.c_str()); + throw EParseException(NULL, err.c_str()); + } + ret += "; " + var->evalVar(_AdditionalParams[i].CompilerParam); + } + + return ret; +} + +CMissionData::CMissionData() +{ + // init all datas + _MonoInstance = false; + _MissionAuto = false; + _RunOnce = false; + _Replayable = false; + _Solo = false; + _Guild = false; + _NotInJournal = false; + _AutoRemoveFromJournal = false; + _PlayerReplayTimer = 0; + _GlobalReplayTimer = 0; + _NotProposed = false; + _NonAbandonnable = false; + _NeedValidation = false; + _FailIfInventoryIsFull = false; +} + +CMissionData::~CMissionData() +{ + while (!_Variables.empty()) + { + delete _Variables.begin()->second; + _Variables.erase(_Variables.begin()); + } + + while (!_Steps.empty()) + { + delete _Steps.back(); + _Steps.pop_back(); + } +} + +void CMissionData::setMissionName(const string &missionName) +{ + _MissionName = missionName; +} + +const string &CMissionData::getMissionName() { return _MissionName;} + +bool CMissionData::addVariable(NLLIGO::IPrimitive *prim, IVar *var) +{ + if (_Variables.find(var->getVarName()) != _Variables.end()) + throw EParseException(prim, toString("Variable '%s' already defined !", var->getVarName().c_str()).c_str()); + + _Variables.insert(make_pair(var->getVarName(), var)); + _VariablesOrder.push_back(var); + return true; +} + +IVar *CMissionData::getVariable(const string &varName) +{ + map::iterator it(_Variables.find(varName)); + if (it != _Variables.end()) + return it->second; + return NULL; +} + +IStep *CMissionData::getNextStep(IStep *current) +{ + for (uint i=0; i<_Steps.size(); ++i) + { + if (_Steps[i] == current && i < _Steps.size()-1) + return _Steps[i+1]; + } + return NULL; +} + +IStep *CMissionData::getStepByName(const std::string &stepName) +{ + if (_StepsByNames.find(stepName) != _StepsByNames.end()) + { + return _StepsByNames[stepName]; + } + + return NULL; +} + + +bool CMissionData::addStep(IStep *step) +{ + _Steps.push_back(step); + return true; +} + +string CMissionData::genPreRequisites() +{ + string ret; + if (!_ReqSkills.empty()) + { + ret += "req_skill : "; + for (uint i=0; i<_ReqSkills.size(); ++i) + { + ret += _ReqSkills[i].Skill+" "+_ReqSkills[i].MinLevel+" "+_ReqSkills[i].MaxLevel; + if (i < _ReqSkills.size()-1) + ret +="; "; + else + ret += NL; + } + } + if (!_ReqMissionDone.empty()) + { + for (uint i=0; i<_ReqMissionDone.size(); ++i) + { + ret += "req_mission : "+ _ReqMissionDone[i]+NL; + } + } + if (!_ReqMissionNotDone.empty()) + { + for (uint i=0; i<_ReqMissionNotDone.size(); ++i) + { + ret += "req_mission_neg : "+_ReqMissionNotDone[i]+NL; + } + } + if (!_ReqMissionRunning.empty()) + { + for (uint i=0; i<_ReqMissionRunning.size(); ++i) + { + ret += "req_mission_running : "+_ReqMissionRunning[i]+NL; + } + } + if (!_ReqMissionNotRunning.empty()) + { + + for (uint i=0; i<_ReqMissionNotRunning.size(); ++i) + { + ret += "req_mission_running_neg : "+_ReqMissionNotRunning[i]+NL; + } + } + if (!_ReqWearItem.empty()) + { + ret += "req_wear : "; + for (uint i=0; i<_ReqWearItem.size(); ++i) + { + ret += _ReqWearItem[i]; + if(i < _ReqWearItem.size()-1) + ret +="; "; + ret += NL; + } + } + if (!_ReqOwnItem.empty()) + { + ret += "req_item : "; + for (uint i=0; i<_ReqOwnItem.size(); ++i) + { + ret += _ReqOwnItem[i]; + if(i < _ReqOwnItem.size()-1) + ret +="; "; + ret += NL; + } + } + if (!_ReqTitle.empty()) + { + ret += "req_title : "+_ReqTitle+NL; + } + if (!_ReqFames.empty()) + { + for (uint i=0; i<_ReqFames.size(); ++i) + { + ret += "req_fame : "+_ReqFames[i].Faction+" "+_ReqFames[i].Fame; + ret += NL; + } + } + if(_ReqGuild) + { + ret += "req_guild"+NL; + } + if (!_ReqGrade.empty()) + { + ret += "req_grade : "+_ReqGrade+NL; + } + if (!_ReqTeamSize.empty()) + { + ret += "req_team_size : "+_ReqTeamSize+NL; + } + if (!_ReqBrick.empty()) + { + ret += "req_brick : "; + for (uint i=0; i<_ReqBrick.size(); ++i) + { + ret += _ReqBrick[i]; + if(i < _ReqBrick.size()-1) + ret +="; "; + ret += NL; + } + } + if (!_ReqSeason.empty()) + { + ret += "req_season : "+_ReqSeason+NL; + } + if (!_ReqEncyclo.empty()) + { + ret += "req_encyclo_thema : " + _ReqEncyclo + NL; + } + if (!_ReqEncycloNeg.empty()) + { + ret += "req_encyclo_thema_neg : " + _ReqEncycloNeg + NL; + } + if (!_ReqEventFaction.empty()) + { + ret += "req_event_faction : " + _ReqEventFaction + NL; + } + + return ret; +} + + +string CMissionData::generateMissionScript(const std::string &primFileName) +{ + _JumpPoints.clear(); + // first, gather jump point list + for (uint i=0; i<_Steps.size(); ++i) + { + set temp; + _Steps[i]->fillStepJump(*this, temp); + + // remove any jump to the next step (normal flow) + if (i < _Steps.size()-1) + { + set::iterator first(temp.begin()), last(temp.end()); + for (; first != last; ) + { + const TJumpInfo &ji = *first; + + if (ji.StepName == _Steps[i+1]->getStepName() && ji.Discardable) + { + temp.erase(first); + first = temp.begin(); + } + else + ++first; + } + } + + _JumpPoints.insert(temp.begin(), temp.end()); + } + // generate the script + string script; + // generate mission header + script += "# script generated from '"+CFile::getFilename(primFileName)+"'"+NL+NL; + script += "#mission tags and pre-requisites"+NL; + if (_MonoInstance) + script += "mono"+NL; + if (_RunOnce) + script += "once"+NL; + if (_Replayable) + script += "replayable"+NL; + if (_Solo) + script += "solo"+NL; + if (_Guild) + script += "guild"+NL; + if (_NotInJournal) + script += "no_list"+NL; + if (_AutoRemoveFromJournal) + script += "auto_remove"+NL; + if (!_MissionCategory.empty()) + script += "mission_category : "+_MissionCategory+NL; + if (_PlayerReplayTimer != 0) + script += "player_replay_timer : "+toString("%u", _PlayerReplayTimer)+NL; + if (_GlobalReplayTimer != 0) + script += "global_replay_timer : "+toString("%u", _GlobalReplayTimer)+NL; + if (_NotProposed) + script += "not_proposed"+NL; + if (_MissionAuto) + script += string("auto : ")+_MissionAutoMenu.genScript(*this)+NL; + if (_NonAbandonnable) + script += "non_abandonnable"+NL; + if (!_MissionIcon.empty()) + script += "mission_icon : "+_MissionIcon+NL; + if (_NeedValidation) + script += "need_validation"+NL; + if (_FailIfInventoryIsFull) + script += "fail_if_inventory_is_full"+NL; + + if (!_ParentMissions.empty()) + { + set::iterator first(_ParentMissions.begin()), last(_ParentMissions.end()); + for (; first != last; ++first) + { + script += "parent : "+ *first+NL; + } + } + + script += NL+"#Variables declaration"+NL; + + // declare all the variables + { + std::vector::iterator first(_VariablesOrder.begin()), last(_VariablesOrder.end()); + for (; first != last; ++first) + { + script += (*first)->genDecl(*this); + } + } + + script += NL+"#pre-requisites"+NL; + script += genPreRequisites(); + + script += NL+"#script"+NL; + // generate mission title and desc + script += "mission_title : "+_MissionTitle.genScript(*this)+NL; + script += "mission_desc : "+_MissionDescription.genScript(*this)+NL; + + // generate steps scripts + for (uint i=0; i<_Steps.size(); ++i) + { + script += "# "+_Steps[i]->getStepName()+NL; + if (_JumpPoints.find(_Steps[i]->getStepName()) != _JumpPoints.end() + && !_Steps[i]->isAJump()) + { + // insert a jump point + script += "jump_point : " + _Steps[i]->getStepName() + NL; + } + + script += _Steps[i]->genCode(*this); + //if (_Steps[i]->EndOfBranch && !_Steps[i]->isAJump()) + // script += "end"+NL; + } + + return script; +} + +string CMissionData::generatePhraseFile() +{ + string ret; + // generate header phrase + ret = _MissionTitle.genPhrase(); + ret += _MissionDescription.genPhrase(); + ret += _MissionAutoMenu.genPhrase(); + + // generate var phrase + for (uint i=0; i<_VariablesOrder.size(); ++i) + { + ret += _VariablesOrder[i]->genPhrase(); + } + + // generate step phrase + for (uint i=0; i<_Steps.size(); ++i) + { + ret += _Steps[i]->genPhrase(); + } + return ret; +} + +string CMissionData::generateDotScript() +{ + string ret = "digraph " + _MissionName + NL; + ret += "{" + NL; + + // set default shape to 'record' + ret += "node [shape=record]"+NL; + + ret += "\t__start__ [shape=\"point\", peripheries=2, label=\"\"]"+NL; + + // 1st pass, generate node for each step + for (uint i=0; i<_Steps.size(); ++i) + { + if (!_Steps[i]->isEnd() && !_Steps[i]->isAJump()) + { + ret += "\t"+_Steps[i]->getStepName(); + ret += " [URL=\""+buildPrimPath(_Steps[i]->getPrimitive())+"\"]"+NL; + } + } + + ret += "\t__end__ [shape=\"point\"]"+NL; + + // activate red color for shapes that are created after this points + ret += "node [color=red]"+NL; + + // 2nd pass, generate link between steps + for (uint i=0; i<_Steps.size(); ++i) + { + if (_Steps[i]->isAJump()) + continue; + + if (i == 0) + { + ret += "\t__start__ -> " + _Steps[i]->getStepName() + NL; + } + set jumps; + _Steps[i]->fillStepJump(*this, jumps); + // there is a link there + while (!jumps.empty()) + { + const TJumpInfo &ji = *(jumps.begin()); + if (_StepsByNames.find(ji.StepName) != _StepsByNames.end() + && _StepsByNames[ji.StepName]->isAJump()) + { + // this step is a jump, skip to link to the jump destination + IStep *jumpStep = _StepsByNames[ji.StepName]; + set jumpJump; + jumpStep->fillStepJump(*this, jumpJump); + if (jumpJump.size() != 1) + { + string str = toString("Step jump contains %u jumps destination instead of 1", jumpJump.size()); + throw EParseException(jumpStep->getPrimitive(), str.c_str()); + } + + ret += "\t"+_Steps[i]->getStepName() + " -> " + jumpJump.begin()->StepName+" [label=\""+ji.JumpName+"\"]" + NL; + } + else + { + ret += "\t"+_Steps[i]->getStepName() + " -> " + ji.StepName+" [label=\""+jumps.begin()->JumpName+"\"]" + NL; + } + jumps.erase(jumps.begin()); + } + + } + + ret += "}" + NL; + + return ret; +} + + +void CMissionData::parseMissionHeader(NLLIGO::IPrimitive *prim) +{ +// _MissionName = getProperty(prim, "name", false, false); +// if( _MissionName.find(' ') != string::npos) +// { +// throw EParseException(prim, toString("Mission name '%s' must not contains space", _MissionName.c_str()).c_str()); +// } + _GiverPrimitive = getProperty(prim,"giver_primitive", true, false); + _MissionGiver = getProperty(prim, "mission_giver", true, false); + +// _Alias = getProperty(prim, "alias", false, false); + + // If the mission is under a npc_bot node, then the giver is directly taken + // from the npc name + if (prim->getParent()) + { + if (getProperty(prim->getParent(), "class", false, false) == "npc_bot") + { + _MissionGiver = getProperty(prim->getParent(), "name", false, false); + } + } + + vector vs; + _MissionTitleRaw = getPropertyArray(prim, "mission_title", false, false); +// _MissionTitle.init(*this, prim, vs); + _MissionDescriptionRaw = getPropertyArray(prim, "mission_description", false, false); +// _MissionDescription.init(*this, prim, vs); + _MonoInstance = strlwr(getProperty(prim, "mono_instance", true, false)) == "true"; + _RunOnce = strlwr(getProperty(prim, "run_only_once", true, false)) == "true"; + _Replayable = strlwr(getProperty(prim, "replayable", true, false)) == "true"; + + _NeedValidation = strlwr(getProperty(prim, "need_validation", true, false)) == "true"; + + _MissionAutoMenuRaw = getPropertyArray(prim, "phrase_auto_menu", false, false); + + // audience setting + string s = getProperty(prim, "audience", false, false); + if (s == "solo") + _Solo = true; + else if (s == "guild") + _Guild = true; + + _NotInJournal = NLMISC::toLower(getProperty(prim, "not_in_journal", false, false)) == "true"; + _AutoRemoveFromJournal = NLMISC::toLower(getProperty(prim, "auto_remove_from_journal", false, false)) == "true"; + _MissionCategory = getProperty(prim, "mission_category", false, false); + NLMISC::fromString(getProperty(prim, "player_replay_timer", true, false), _PlayerReplayTimer); + NLMISC::fromString(getProperty(prim, "global_replay_timer", true, false), _GlobalReplayTimer); + _NotProposed = NLMISC::toLower(getProperty(prim, "not_proposed", false, false)) == "true"; + _MissionAuto = NLMISC::toLower(getProperty(prim, "automatic", false, false)) == "true"; + _NonAbandonnable = NLMISC::toLower(getProperty(prim, "non_abandonnable", false, false)) == "true"; + _FailIfInventoryIsFull = NLMISC::toLower(getProperty(prim, "fail_if_inventory_is_full", false, false)) == "true"; + _MissionIcon = getProperty(prim, "mission_icon", false, false); + + if (_MissionAuto) + { + if (_MissionAutoMenuRaw.empty()) + { + string error = toString("Mission is flagged automatic, but no phrase_auto_menu defined !"); + throw EParseException(prim, error.c_str()); + } + } + + vs = getPropertyArray(prim, "parent_missions", true, false); + _ParentMissions.insert(vs.begin(), vs.end()); + +} + +void CMissionData::parsePrerequisites(NLLIGO::IPrimitive *prim) +{ + // skills + vector vs; + vs = getPropertyArray(prim, "require_skill/min_level/max_level", true, false); + for (uint i=0; i parts; + strtokquote(vs[i], parts); + if (parts.size() != 3) + { + throw EParseException(prim, toString("Invalide argument count in line %u of require_skill array. Need 3, found %u", i, parts.size()).c_str()); + } + TReqSkill rs; + rs.Skill = parts[0]; + rs.MinLevel = parts[1]; + rs.MaxLevel = parts[2]; + + _ReqSkills.push_back(rs); + + } + } + // Mission done + vs = getPropertyArray(prim, "require_mission_done", true, false); + for (uint i=0; i parts; + strtokquote(vs[i], parts); + if (parts.size() != 1) + { + throw EParseException(prim, toString("Invalide argument count in line %u of require_mission_done array. Need 1, found %u", i, parts.size()).c_str()); + } + _ReqMissionDone.push_back(parts[0]); + } + } + // Mission not done + vs = getPropertyArray(prim, "require_mission_not_done", true, false); + for (uint i=0; i parts; + strtokquote(vs[i], parts); + if (parts.size() != 1) + { + throw EParseException(prim, toString("Invalide argument count in line %u of require_mission_not_done array. Need 1, found %u", i, parts.size()).c_str()); + } + _ReqMissionNotDone.push_back(parts[0]); + } + } + // Mission running + vs = getPropertyArray(prim, "require_mission_running", true, false); + for (uint i=0; i parts; + strtokquote(vs[i], parts); + if (parts.size() != 1) + { + throw EParseException(prim, toString("Invalide argument count in line %u of require_mission_running array. Need 1, found %u", i, parts.size()).c_str()); + } + _ReqMissionRunning.push_back(parts[0]); + } + } + // Mission not running + vs = getPropertyArray(prim, "require_mission_not_running", true, false); + for (uint i=0; i parts; + strtokquote(vs[i], parts); + if (parts.size() != 1) + { + throw EParseException(prim, toString("Invalide argument count in line %u of require_mission_not_running array. Need 1, found %u", i, parts.size()).c_str()); + } + _ReqMissionNotRunning.push_back(parts[0]); + } + } + // wearing item + vs = getPropertyArray(prim, "require_wearing_item", true, false); + for (uint i=0; i parts; + strtokquote(vs[i], parts); + if (parts.size() != 1) + { + throw EParseException(prim, toString("Invalide argument count in line %u of require_wearing_item array. Need 1, found %u", i, parts.size()).c_str()); + } + _ReqWearItem.push_back(parts[0]); + } + } + // own item + vs = getPropertyArray(prim, "require_own_item", true, false); + for (uint i=0; i parts; + strtokquote(vs[i], parts); + if (parts.size() != 1) + { + throw EParseException(prim, toString("Invalide argument count in line %u of require_own_item array. Need 1, found %u", i, parts.size()).c_str()); + } + _ReqOwnItem.push_back(parts[0]); + } + } + // title + _ReqTitle = getProperty(prim, "require_title", true, false); + // fame + vs = getPropertyArray(prim, "require_faction/fame", true, false); + for (uint i=0; i parts; + strtokquote(vs[i], parts); + if (parts.size() != 2) + { + throw EParseException(prim, toString("Invalide argument count in line %u of require_faction/fame array. Need 2, found %u", i, parts.size()).c_str()); + } + TReqFame rf; + rf.Faction = parts[0]; + rf.Fame = parts[1]; + + _ReqFames.push_back(rf); + } + } + // guild + if (getProperty(prim, "require_guild_membership", true, false) == "true") + _ReqGuild = true; + else + _ReqGuild = false; + // grade + _ReqGrade = getProperty(prim, "require_guild_grade", true, false); + // team size + _ReqTeamSize = getProperty(prim, "require_team_size", true, false); + // brick + vs = getPropertyArray(prim, "require_brick_knowledge", true, false); + for (uint i=0; i parts; + strtokquote(vs[i], parts); + if (parts.size() != 1) + { + throw EParseException(prim, toString("Invalide argument count in line %u of require_brick_knowledge array. Need 1, found %u", i, parts.size()).c_str()); + } + _ReqBrick.push_back(parts[0]); + } + } + // season + _ReqSeason = getProperty(prim, "require_season", true, false); + // encyclopedia + _ReqEncyclo = getProperty(prim, "require_encyclo_thema", true, false); + _ReqEncycloNeg = getProperty(prim, "require_encyclo_thema_neg", true, false); + + if ((!_ReqEncyclo.empty() && !_ReqEncycloNeg.empty()) + || (!_ReqEncycloNeg.empty() && !_ReqEncyclo.empty())) + { + string err = toString("You can't mix positive and negative encyclopedy requirement"); + throw EParseException(prim, err.c_str()); + } + // event faction + _ReqEventFaction = getProperty(prim, "require_event_faction", true, false); +} + +std::string CMissionData::replaceVar(NLLIGO::IPrimitive *prim, const std::string &str) +{ + string::size_type pos = 0; + string::size_type pos2 = 0; + string ret; + + while (pos < str.size()) + { + if (str[pos] != '$') + { + ret += str[pos++]; + } + else if (pos+1 < str.size() && str[pos+1] == '$') + { + // check that this $ is not escaped + ret += '$'; + pos+=2; + } + else + { + // ok, this is not an escaped $ + CSString varName; + // skip the initial '$' + pos++; +// while (str[pos] != ' ' && str[pos] != '\t' && str[pos] != '\n' && str[pos] != '\r') + while (pos < str.size() && str[pos] != '$') + varName += str[pos++]; + + if (pos >= str.size()) + { + string err = toString("Error while parsing variable in '%s', missing closing '$'", str.c_str()); + throw EParseException (NULL, err.c_str()); + } + + // skip the final '$' + pos++; + + // split the var name and subpart + vector varParts; + explode(string(varName), string("@"), varParts, true); + + if (varParts.empty() || varParts.size() > 2) + { + throw EParseException(prim, toString("Error parsing varName '%s' in string '%s'", varName.c_str(), str.c_str()).c_str()); + } + + if (_Variables.find(varParts.front()) == _Variables.end()) + { + string err = toString("Unknown variable '%s' in string '%s'", varParts.front().c_str(), str.c_str()); + throw EParseException (prim, err.c_str()); + } + + IVar *var = _Variables[varParts[0]]; + + if (varParts.size() == 1) + ret += var->evalVar(""); + else + ret += var->evalVar(varParts[1]); + + } + } + + return ret; +} + +std::vector CMissionData::replaceVar(NLLIGO::IPrimitive *prim, const std::vector &strs) +{ + vector ret; + + for (uint i=0; igetPropertyByName(propertyName.c_str(), s)) + { + if (!canFail) + { + string err = toString("Can't find property '%s'", propertyName.c_str()); + throw EParseException (prim, err.c_str()); + } + } + else + { + ret = *s; + } + + if (replaceVar) + { + ret = this->replaceVar(prim, ret); + } + + return ret; +} + +std::vector CMissionData::getPropertyArray(NLLIGO::IPrimitive *prim, const std::string &propertyName, bool replaceVar, bool canFail) +{ + vector ret; + vector *vs; + if (!prim->getPropertyByName(propertyName.c_str(), vs)) + { + if (!canFail) + { + string err = toString("Can't find property '%s'", propertyName.c_str()); + throw EParseException (prim, err.c_str()); + } + } + else + { + ret = *vs; + } + + if (replaceVar) + { + ret = this->replaceVar(prim, ret); + } + return ret; +} + +bool CMissionData::isThereAJumpTo(const std::string &stepName) +{ + if (_JumpPoints.find(stepName) != _JumpPoints.end()) + return true; + else + return false; +} + +void TCompilerVarName::init(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string propName) +{ + _DefaultName = defaultName; + _ParamType = type; + + _VarName = md.getProperty(prim, propName, false, false); + // remove the variable tag if any + untagVar(_VarName); + + _VarValue = md.getProperty(prim, propName, true, false); +} + +void TCompilerVarName::initWithText(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string &text) +{ + _DefaultName = defaultName; + _ParamType = type; + + _VarName = text; + // remove the variable tag if any + untagVar(_VarName); + + _VarValue = md.replaceVar(prim, text); +} + + +CPhrase::TParamInfo TCompilerVarName::getParamInfo() const +{ + if (_VarName.empty()) + return CPhrase::TParamInfo(_DefaultName, _ParamType); + else + return CPhrase::TParamInfo(_VarName, _ParamType); +} + + +bool TCompilerVarName::empty() const +{ + return _VarValue.empty(); +} + +TCompilerVarName::operator const std::string () const +{ + return _VarValue; +} + +TCompilerVarName::operator CPhrase::TParamInfo() const +{ + return getParamInfo(); +} + + +std::string operator+(const TCompilerVarName& left, const std::string & right) { return left._VarValue + right;} + +std::string operator+(const std::string & left, const TCompilerVarName& right) { return left + right._VarValue;} + +std::vector TCompilerVarName::getPropertyArrayWithText(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string & arrayProperyName) +{ + std::vector compilerParams; + + std::vector values = md.getPropertyArray(prim, arrayProperyName,false, false); + uint first = 0; + uint last = (uint)values.size(); + compilerParams.resize(last); + for ( ; first != last; ++first) + { + compilerParams[first].initWithText( toString("%s%d", defaultName.c_str(), first+1) , type, md, prim, values[first]); + } + + return compilerParams; +} + +std::vector TCompilerVarName::getPropertyArrayWithTextStaticDefaultName(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string & arrayProperyName) +{ + std::vector compilerParams; + std::vector values = md.getPropertyArray(prim, arrayProperyName,false, false); + uint first = 0; + uint last = (uint)values.size(); + compilerParams.resize(last); + for ( ; first != last; ++first) + { + compilerParams[first].initWithText( defaultName, type, md, prim, values[first]); + } + return compilerParams; +} + diff --git a/code/ryzom/tools/leveldesign/mission_compiler_lib/mission_compiler.h b/code/ryzom/tools/leveldesign/mission_compiler_lib/mission_compiler.h index 6f993679b..1f2323fdf 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_lib/mission_compiler.h +++ b/code/ryzom/tools/leveldesign/mission_compiler_lib/mission_compiler.h @@ -1,547 +1,547 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/misc/types_nl.h" -#include "nel/misc/debug.h" -#include "nel/misc/string_common.h" -#include "nel/misc/path.h" -#include "nel/misc/sstring.h" -#include "nel/misc/smart_ptr.h" -#include "nel/misc/factory.h" -#include "nel/ligo/primitive.h" -#include "nel/ligo/primitive_utils.h" -#include "nel/ligo/ligo_config.h" -#include "../../../common/src/game_share/string_manager_sender.h" -#include "nel/misc/string_conversion.h" -#include -#include - -class CMissionData; -class IStep; - -const std::string NL("\n\r"); - -/// Exception thows when the parser meet somethink invalid. -struct EParseException -{ - EParseException(NLLIGO::IPrimitive *prim, const char *why) - : Primitive(prim), - Why(why) - { - } - - NLLIGO::IPrimitive *Primitive; - std::string Why; -}; - - -// utility to untag a variable (tag are the '$' added before and after the var name) -inline void untagVar(std::string &var) -{ - if (!var.empty()) - { - if (var[0] != '$') - var = ""; - else - { - var = var.substr(1); - if (var[var.size()-1] != '$') - var = ""; - else - var = var.substr(0, var.size()-1); - } - } -} - -// utility to 'tabulate' the lines in a string -void tabulateLine(std::string &text, uint nbTabs); - - -/* Interface class for variables types*/ -class IVar -{ -public: - - typedef NLLIGO::IPrimitive * TCtorParam; - - enum TVarType - { - vt_integer, - vt_npc, - vt_item, - vt_place, - vt_text - }; - - IVar(TVarType type, NLLIGO::IPrimitive *prim) - { - _VarType = type; - _VarName = getPrimProperty(prim, "var_name"); - } - - // force virtual destructor - virtual ~IVar() {} - - /** Return the variable type. Should return a string to - * limit coupling with implementation ? - */ - TVarType getVarType() const - { - return _VarType; - } - - /** Return the type of the variable as defined in the string manager. - * Can return NB_ENTITY_TYPES for compiler variable that don't match - * to a type in the string manager. - */ - virtual STRING_MANAGER::TParamType getStringManagerType()=0; - - /// Return the name of the variable. - const std::string getVarName() const - { - return _VarName; - } - - /// Evaluate the content of the variable with an optional sub part. - virtual std::string evalVar(const std::string &subPart) = 0; - - /** Factory method to create new variable. Caller become responsible - * for deleting the allocated variable. - */ - static IVar *createVar(CMissionData &md, NLLIGO::IPrimitive *prim); - - /// Generate variable declaration in mission script - virtual std::string genDecl(CMissionData &md) = 0; - - /// Generate the phrase - virtual std::string genPhrase() - { - static std::string emptyString; - return emptyString; - } - -protected: - /// Helper function to read a primitive property. - std::string getPrimProperty(NLLIGO::IPrimitive *prim, const std::string &propName) - { - std::string *s; - if (prim->getPropertyByName(propName.c_str(), s)) - return *s; - else - return ""; - } - - /// Helper function to read a primitive array property - std::vector getPrimPropertyArray(NLLIGO::IPrimitive *prim, const std::string &propName) - { - std::vector *sv; - if (prim->getPropertyByName(propName.c_str(), sv)) - return *sv; - else - return std::vector(); - } -protected: - /// Variable type. - TVarType _VarType; - /// Variable name. - std::string _VarName; -}; - -class CMissionData; - - -/** Class for text management. - * Handle different expression of text such - * phrase identifier, reference to text variable - * or literal string. - * The class also handle the parameter list for - * the phrase. - */ -class CPhrase -{ -public: - /// Structure to store phrase parameters infos. - struct TParamInfo - { - /// The name of the parameter - std::string ParamName; - /// Compiler param - std::string CompilerParam; - /// The type of the parameters (as defined in the string manager). - STRING_MANAGER::TParamType ParamType; - - TParamInfo() - : ParamType(STRING_MANAGER::NB_PARAM_TYPES) - { - } - - TParamInfo(const std::string &name, STRING_MANAGER::TParamType type, const std::string &compilerParam = "") - : ParamName(name), - ParamType(type), - CompilerParam(compilerParam) - { - } - }; - - typedef std::vector > TPredefParams; - -private: - - /** Number of variant for this phrase. - * Zero denote that there is no variant, thus no need to add - * a postfix number after the phrase identifier for literal - * generated phrase. - */ - uint32 _NumEntry; - - /** The phrase id. This is the identifier that must be use with the - * string manager. - */ - std::string _PhraseId; - /** String literal value. When the user fill a quoted string, then - * this property receive the string value of the quoted string. - */ - std::vector _PhraseLiterals; - /** Suffixe for literal string identifier */ - std::string _Suffixe; - /// The list of default parameters. - TPredefParams _DefaultParams; - /// The list of additional parameters. - std::vector _AdditionalParams; -public: - - - /// init the phrase - void initPhrase (CMissionData &md, - NLLIGO::IPrimitive *prim, - const std::vector &texts, - uint32 numEntry = 0, - const TPredefParams &predefParams = TPredefParams()); - - /// generate the common string script for any script instruction. - std::string genScript(CMissionData &md); - - /** generate the phrase file content. Return empty string - * if the phrase is not a literal. - */ - std::string genPhrase(); - - /// Test if the phrase is empty - bool isEmpty(); - - /// Test if the phrase contains some additionnal parameters - bool asAdditionnalParams(); -}; - - -/* Class for jumps */ -struct TJumpInfo -{ - std::string StepName; - std::string JumpName; - bool Discardable; - - TJumpInfo(const std::string &stepName, const std::string &jumpName = std::string(), bool discardable = true) - : StepName(stepName), - JumpName(jumpName), - Discardable(discardable) - {} - - bool operator <(const TJumpInfo &other) const - { - return StepName < other.StepName; - } -}; - - -/* Class for mission information storing */ -class CMissionData : public NLMISC::CRefCount -{ -public: - - CMissionData(); - ~CMissionData(); - - -// void setAlias(const std::string &alias) { _Alias = alias; } -// const std::string &getAlias() { return _Alias; } - - void setMissionName(const std::string &missionName); - const std::string &getMissionName(); - - const std::string &getGiverPrimitive() { return _GiverPrimitive; } - void setGiverPrimitive(const std::string &giverPrimitive) { _GiverPrimitive = giverPrimitive; } - - const std::string &getGiverName() { return _MissionGiver; } - void setGiverName(const std::string &giverName) { _MissionGiver = giverName; } - - bool addVariable(NLLIGO::IPrimitive *prim, IVar *var); - - IVar *getVariable(const std::string &varName); - - bool addStep(IStep *step); - void addStepName(const std::string &name, IStep *step) { _StepsByNames[name] = step; } - - IStep *getNextStep(IStep *current); - - IStep *getStepByName(const std::string &stepName); - - std::string generateMissionScript(const std::string &primFileName); - - std::string generatePhraseFile(); - - std::string generateDotScript(); - - void parseMissionHeader(NLLIGO::IPrimitive *prim); - void initHeaderPhrase(NLLIGO::IPrimitive *prim); - void parsePrerequisites(NLLIGO::IPrimitive *prim); - - std::string replaceVar(NLLIGO::IPrimitive *prim, const std::string &str); - std::vector replaceVar(NLLIGO::IPrimitive *prim, const std::vector &strs); - - std::string getProperty(NLLIGO::IPrimitive *prim, const std::string &propertyName, bool replaceVar, bool canFail); - std::vector getPropertyArray(NLLIGO::IPrimitive *prim, const std::string &propertyName, bool replaceVar, bool canFail); - - - bool isThereAJumpTo(const std::string &stepName); - - bool isGuildMission() const - { - return _Guild; - } - -private: - - std::string genPreRequisites(); - - // forbidden copy constructor ! - CMissionData(const CMissionData &other) - { - nlstop; - } - -// std::string _Alias; - std::string _MissionName; - std::string _MissionGiver; - std::string _GiverPrimitive; - bool _MonoInstance; - bool _RunOnce; - bool _Replayable; - bool _Solo; - bool _Guild; - bool _NotInJournal; - bool _AutoRemoveFromJournal; // When mission ends (fail or success) automatically remove it from the journal - std::string _MissionCategory; - uint32 _PlayerReplayTimer; - uint32 _GlobalReplayTimer; - bool _NotProposed; - bool _NonAbandonnable; - bool _NeedValidation; - bool _FailIfInventoryIsFull; - std::string _MissionIcon; - - std::vector _MissionTitleRaw; - CPhrase _MissionTitle; - std::vector _MissionDescriptionRaw; - CPhrase _MissionDescription; - - bool _MissionAuto; - std::vector _MissionAutoMenuRaw; - CPhrase _MissionAutoMenu; - - ////// Pre requisites ///////// - struct TReqSkill - { - std::string Skill; - std::string MinLevel; - std::string MaxLevel; - }; - - struct TReqFame - { - std::string Faction; - std::string Fame; - }; - std::vector _ReqSkills; - std::vector _ReqMissionDone; - std::vector _ReqMissionNotDone; - std::vector _ReqMissionRunning; - std::vector _ReqMissionNotRunning; - std::vector _ReqWearItem; - std::vector _ReqOwnItem; - std::string _ReqTitle; - std::vector _ReqFames; - bool _ReqGuild; - std::string _ReqGrade; - std::string _ReqTeamSize; - std::vector _ReqBrick; - std::string _ReqSeason; -// bool _ReqEncycloTasksDone; - std::string _ReqEncyclo; - std::string _ReqEncycloNeg; - std::string _ReqEventFaction; - - /// The list of parent missions - std::set _ParentMissions; - /// The list of variable by name - std::map _Variables; - /// The list of variable in primitive order - std::vector _VariablesOrder; - /// the list of step in execution order - std::vector _Steps; - /// The list of step sorted by step name - std::map _StepsByNames; - - std::set _JumpPoints; - -}; - -typedef NLMISC::CSmartPtr TMissionDataPtr; - -/** This class manage the compilation of missions contained under a - * primitive file node. - */ -class CMissionCompiler -{ -public: - - /** Generate the dot language script for the missions under the specified node. - * This method is primarily used for world editor mission display. - */ -// std::vector generateDotScript(NLLIGO::NLLIGO::IPrimitive *rootPrim); - bool generateDotScript(NLLIGO::IPrimitive *missionPrim, std::string &dotScript, std::string &log); - - /** compile one mission. The primitive node must be - * a mission tree root node. - * fileName must receive the primitive file name. It is used - */ - bool compileMission(NLLIGO::IPrimitive *rootPrim, const std::string &primFileName); - - /** Compile all the missions found under the given primitive node. - * The primitive tree is searched recursively ti find all the - * mission tree nodes. - * All the compiled missions are stored internaly in precompiled form. - */ - bool compileMissions(NLLIGO::IPrimitive *rootPrim, const std::string &primFileName); - - /** Install the generated script into the destination primitive files */ - bool installCompiledMission(NLLIGO::CLigoConfig &ligoConfig, const std::string &primFileName); - - /// Publish the modified to the path parameter - bool publishFiles(const std::string &serverPathPrim, const std::string &serverPathText, const std::string &localPathText); - - /// Search for text in the file : add it if it's not in - bool includeText(const std::string filename, const std::string text); - - /// Parse the pre requisite node of a mission. - bool parsePreRequisite(CMissionData &md, NLLIGO::IPrimitive *preReq); - - /// Parse the steps of a missions. - bool parseSteps(CMissionData &md, NLLIGO::IPrimitive *steps, IStep *parent=NULL); - bool parseOneStep(CMissionData &md, NLLIGO::IPrimitive *stepToParse, IStep *parent, bool bEndOfBranch); - - /// Helper to retrive a property in a primitive node. - std::string getProp(NLLIGO::IPrimitive *prim, const std::string &propName); - /// Helper to retreive the class name of a primitive node. - std::string getClass(NLLIGO::IPrimitive *prim); - /// Parse the variable of a missions. - bool parseVariables(CMissionData &md, NLLIGO::IPrimitive *variables); - - - /// Get full paths of files to publish - uint getFileToPublishCount() { return (uint)_FilesToPublish.size(); } - std::string getFileToPublish(uint index) { nlassert(index < _FilesToPublish.size()); return _FilesToPublish[index]; } - - - std::vector &getMissions() - { - return _CompiledMission; - } - uint getMissionsCount() - { - return (uint)_CompiledMission.size(); - } - TMissionDataPtr getMission(uint index) - { - nlassert(index < _CompiledMission.size()); - return _CompiledMission[index]; - } - - -private: - - /// Storage for loaded primitive - struct TLoadedPrimitive - { - NLLIGO::CPrimitives *PrimDoc; - std::string FullFileName; - - TLoadedPrimitive() - : PrimDoc(NULL) - {} - - TLoadedPrimitive(NLLIGO::CPrimitives *primDoc, const std::string &fullFileName) - : PrimDoc(primDoc), - FullFileName(fullFileName) - { - } - }; - - /// Storage for precompiled missions. - std::vector _CompiledMission; - - /// Storage for files to publish - std::vector _FilesToPublish; -}; - - -// Class to easily handle var and var name pair -struct TCompilerVarName -{ - typedef std::vector > TPredefParams; - // Default parameter name - std::string _DefaultName; - // Type of script parameter - STRING_MANAGER::TParamType _ParamType; - // the name of the compiler var, like 'the_creature' in $the_creature$ = chab1 - std::string _VarName; - // the value of the compiler var line 'chab1' in $the_creature$ = chab1 - std::string _VarValue; - - void init(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string propName); - - void initWithText(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string &text); - - CPhrase::TParamInfo getParamInfo() const; - - bool empty() const; - - operator const std::string () const; - - operator CPhrase::TParamInfo() const; - - //static void getPhrasePredef(const TCompilerVarName::TPredefParams& compilerParams, CPhrase::TPredefParams& params); - - static std::vector getPropertyArrayWithText(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string & arrayProperyName); - static std::vector getPropertyArrayWithTextStaticDefaultName(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string & arrayProperyName); - - -}; - -std::string operator+(const TCompilerVarName& left, const std::string & right); -std::string operator+(const std::string & left, const TCompilerVarName& right); - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/misc/types_nl.h" +#include "nel/misc/debug.h" +#include "nel/misc/string_common.h" +#include "nel/misc/path.h" +#include "nel/misc/sstring.h" +#include "nel/misc/smart_ptr.h" +#include "nel/misc/factory.h" +#include "nel/ligo/primitive.h" +#include "nel/ligo/primitive_utils.h" +#include "nel/ligo/ligo_config.h" +#include "../../../common/src/game_share/string_manager_sender.h" +#include "nel/misc/string_conversion.h" +#include +#include + +class CMissionData; +class IStep; + +const std::string NL("\n\r"); + +/// Exception thows when the parser meet somethink invalid. +struct EParseException +{ + EParseException(NLLIGO::IPrimitive *prim, const char *why) + : Primitive(prim), + Why(why) + { + } + + NLLIGO::IPrimitive *Primitive; + std::string Why; +}; + + +// utility to untag a variable (tag are the '$' added before and after the var name) +inline void untagVar(std::string &var) +{ + if (!var.empty()) + { + if (var[0] != '$') + var = ""; + else + { + var = var.substr(1); + if (var[var.size()-1] != '$') + var = ""; + else + var = var.substr(0, var.size()-1); + } + } +} + +// utility to 'tabulate' the lines in a string +void tabulateLine(std::string &text, uint nbTabs); + + +/* Interface class for variables types*/ +class IVar +{ +public: + + typedef NLLIGO::IPrimitive * TCtorParam; + + enum TVarType + { + vt_integer, + vt_npc, + vt_item, + vt_place, + vt_text + }; + + IVar(TVarType type, NLLIGO::IPrimitive *prim) + { + _VarType = type; + _VarName = getPrimProperty(prim, "var_name"); + } + + // force virtual destructor + virtual ~IVar() {} + + /** Return the variable type. Should return a string to + * limit coupling with implementation ? + */ + TVarType getVarType() const + { + return _VarType; + } + + /** Return the type of the variable as defined in the string manager. + * Can return NB_ENTITY_TYPES for compiler variable that don't match + * to a type in the string manager. + */ + virtual STRING_MANAGER::TParamType getStringManagerType()=0; + + /// Return the name of the variable. + const std::string getVarName() const + { + return _VarName; + } + + /// Evaluate the content of the variable with an optional sub part. + virtual std::string evalVar(const std::string &subPart) = 0; + + /** Factory method to create new variable. Caller become responsible + * for deleting the allocated variable. + */ + static IVar *createVar(CMissionData &md, NLLIGO::IPrimitive *prim); + + /// Generate variable declaration in mission script + virtual std::string genDecl(CMissionData &md) = 0; + + /// Generate the phrase + virtual std::string genPhrase() + { + static std::string emptyString; + return emptyString; + } + +protected: + /// Helper function to read a primitive property. + std::string getPrimProperty(NLLIGO::IPrimitive *prim, const std::string &propName) + { + std::string *s; + if (prim->getPropertyByName(propName.c_str(), s)) + return *s; + else + return ""; + } + + /// Helper function to read a primitive array property + std::vector getPrimPropertyArray(NLLIGO::IPrimitive *prim, const std::string &propName) + { + std::vector *sv; + if (prim->getPropertyByName(propName.c_str(), sv)) + return *sv; + else + return std::vector(); + } +protected: + /// Variable type. + TVarType _VarType; + /// Variable name. + std::string _VarName; +}; + +class CMissionData; + + +/** Class for text management. + * Handle different expression of text such + * phrase identifier, reference to text variable + * or literal string. + * The class also handle the parameter list for + * the phrase. + */ +class CPhrase +{ +public: + /// Structure to store phrase parameters infos. + struct TParamInfo + { + /// The name of the parameter + std::string ParamName; + /// Compiler param + std::string CompilerParam; + /// The type of the parameters (as defined in the string manager). + STRING_MANAGER::TParamType ParamType; + + TParamInfo() + : ParamType(STRING_MANAGER::NB_PARAM_TYPES) + { + } + + TParamInfo(const std::string &name, STRING_MANAGER::TParamType type, const std::string &compilerParam = "") + : ParamName(name), + ParamType(type), + CompilerParam(compilerParam) + { + } + }; + + typedef std::vector > TPredefParams; + +private: + + /** Number of variant for this phrase. + * Zero denote that there is no variant, thus no need to add + * a postfix number after the phrase identifier for literal + * generated phrase. + */ + uint32 _NumEntry; + + /** The phrase id. This is the identifier that must be use with the + * string manager. + */ + std::string _PhraseId; + /** String literal value. When the user fill a quoted string, then + * this property receive the string value of the quoted string. + */ + std::vector _PhraseLiterals; + /** Suffixe for literal string identifier */ + std::string _Suffixe; + /// The list of default parameters. + TPredefParams _DefaultParams; + /// The list of additional parameters. + std::vector _AdditionalParams; +public: + + + /// init the phrase + void initPhrase (CMissionData &md, + NLLIGO::IPrimitive *prim, + const std::vector &texts, + uint32 numEntry = 0, + const TPredefParams &predefParams = TPredefParams()); + + /// generate the common string script for any script instruction. + std::string genScript(CMissionData &md); + + /** generate the phrase file content. Return empty string + * if the phrase is not a literal. + */ + std::string genPhrase(); + + /// Test if the phrase is empty + bool isEmpty(); + + /// Test if the phrase contains some additionnal parameters + bool asAdditionnalParams(); +}; + + +/* Class for jumps */ +struct TJumpInfo +{ + std::string StepName; + std::string JumpName; + bool Discardable; + + TJumpInfo(const std::string &stepName, const std::string &jumpName = std::string(), bool discardable = true) + : StepName(stepName), + JumpName(jumpName), + Discardable(discardable) + {} + + bool operator <(const TJumpInfo &other) const + { + return StepName < other.StepName; + } +}; + + +/* Class for mission information storing */ +class CMissionData : public NLMISC::CRefCount +{ +public: + + CMissionData(); + ~CMissionData(); + + +// void setAlias(const std::string &alias) { _Alias = alias; } +// const std::string &getAlias() { return _Alias; } + + void setMissionName(const std::string &missionName); + const std::string &getMissionName(); + + const std::string &getGiverPrimitive() { return _GiverPrimitive; } + void setGiverPrimitive(const std::string &giverPrimitive) { _GiverPrimitive = giverPrimitive; } + + const std::string &getGiverName() { return _MissionGiver; } + void setGiverName(const std::string &giverName) { _MissionGiver = giverName; } + + bool addVariable(NLLIGO::IPrimitive *prim, IVar *var); + + IVar *getVariable(const std::string &varName); + + bool addStep(IStep *step); + void addStepName(const std::string &name, IStep *step) { _StepsByNames[name] = step; } + + IStep *getNextStep(IStep *current); + + IStep *getStepByName(const std::string &stepName); + + std::string generateMissionScript(const std::string &primFileName); + + std::string generatePhraseFile(); + + std::string generateDotScript(); + + void parseMissionHeader(NLLIGO::IPrimitive *prim); + void initHeaderPhrase(NLLIGO::IPrimitive *prim); + void parsePrerequisites(NLLIGO::IPrimitive *prim); + + std::string replaceVar(NLLIGO::IPrimitive *prim, const std::string &str); + std::vector replaceVar(NLLIGO::IPrimitive *prim, const std::vector &strs); + + std::string getProperty(NLLIGO::IPrimitive *prim, const std::string &propertyName, bool replaceVar, bool canFail); + std::vector getPropertyArray(NLLIGO::IPrimitive *prim, const std::string &propertyName, bool replaceVar, bool canFail); + + + bool isThereAJumpTo(const std::string &stepName); + + bool isGuildMission() const + { + return _Guild; + } + +private: + + std::string genPreRequisites(); + + // forbidden copy constructor ! + CMissionData(const CMissionData &other) + { + nlstop; + } + +// std::string _Alias; + std::string _MissionName; + std::string _MissionGiver; + std::string _GiverPrimitive; + bool _MonoInstance; + bool _RunOnce; + bool _Replayable; + bool _Solo; + bool _Guild; + bool _NotInJournal; + bool _AutoRemoveFromJournal; // When mission ends (fail or success) automatically remove it from the journal + std::string _MissionCategory; + uint32 _PlayerReplayTimer; + uint32 _GlobalReplayTimer; + bool _NotProposed; + bool _NonAbandonnable; + bool _NeedValidation; + bool _FailIfInventoryIsFull; + std::string _MissionIcon; + + std::vector _MissionTitleRaw; + CPhrase _MissionTitle; + std::vector _MissionDescriptionRaw; + CPhrase _MissionDescription; + + bool _MissionAuto; + std::vector _MissionAutoMenuRaw; + CPhrase _MissionAutoMenu; + + ////// Pre requisites ///////// + struct TReqSkill + { + std::string Skill; + std::string MinLevel; + std::string MaxLevel; + }; + + struct TReqFame + { + std::string Faction; + std::string Fame; + }; + std::vector _ReqSkills; + std::vector _ReqMissionDone; + std::vector _ReqMissionNotDone; + std::vector _ReqMissionRunning; + std::vector _ReqMissionNotRunning; + std::vector _ReqWearItem; + std::vector _ReqOwnItem; + std::string _ReqTitle; + std::vector _ReqFames; + bool _ReqGuild; + std::string _ReqGrade; + std::string _ReqTeamSize; + std::vector _ReqBrick; + std::string _ReqSeason; +// bool _ReqEncycloTasksDone; + std::string _ReqEncyclo; + std::string _ReqEncycloNeg; + std::string _ReqEventFaction; + + /// The list of parent missions + std::set _ParentMissions; + /// The list of variable by name + std::map _Variables; + /// The list of variable in primitive order + std::vector _VariablesOrder; + /// the list of step in execution order + std::vector _Steps; + /// The list of step sorted by step name + std::map _StepsByNames; + + std::set _JumpPoints; + +}; + +typedef NLMISC::CSmartPtr TMissionDataPtr; + +/** This class manage the compilation of missions contained under a + * primitive file node. + */ +class CMissionCompiler +{ +public: + + /** Generate the dot language script for the missions under the specified node. + * This method is primarily used for world editor mission display. + */ +// std::vector generateDotScript(NLLIGO::NLLIGO::IPrimitive *rootPrim); + bool generateDotScript(NLLIGO::IPrimitive *missionPrim, std::string &dotScript, std::string &log); + + /** compile one mission. The primitive node must be + * a mission tree root node. + * fileName must receive the primitive file name. It is used + */ + bool compileMission(NLLIGO::IPrimitive *rootPrim, const std::string &primFileName); + + /** Compile all the missions found under the given primitive node. + * The primitive tree is searched recursively ti find all the + * mission tree nodes. + * All the compiled missions are stored internaly in precompiled form. + */ + bool compileMissions(NLLIGO::IPrimitive *rootPrim, const std::string &primFileName); + + /** Install the generated script into the destination primitive files */ + bool installCompiledMission(NLLIGO::CLigoConfig &ligoConfig, const std::string &primFileName); + + /// Publish the modified to the path parameter + bool publishFiles(const std::string &serverPathPrim, const std::string &serverPathText, const std::string &localPathText); + + /// Search for text in the file : add it if it's not in + bool includeText(const std::string filename, const std::string text); + + /// Parse the pre requisite node of a mission. + bool parsePreRequisite(CMissionData &md, NLLIGO::IPrimitive *preReq); + + /// Parse the steps of a missions. + bool parseSteps(CMissionData &md, NLLIGO::IPrimitive *steps, IStep *parent=NULL); + bool parseOneStep(CMissionData &md, NLLIGO::IPrimitive *stepToParse, IStep *parent, bool bEndOfBranch); + + /// Helper to retrive a property in a primitive node. + std::string getProp(NLLIGO::IPrimitive *prim, const std::string &propName); + /// Helper to retreive the class name of a primitive node. + std::string getClass(NLLIGO::IPrimitive *prim); + /// Parse the variable of a missions. + bool parseVariables(CMissionData &md, NLLIGO::IPrimitive *variables); + + + /// Get full paths of files to publish + uint getFileToPublishCount() { return (uint)_FilesToPublish.size(); } + std::string getFileToPublish(uint index) { nlassert(index < _FilesToPublish.size()); return _FilesToPublish[index]; } + + + std::vector &getMissions() + { + return _CompiledMission; + } + uint getMissionsCount() + { + return (uint)_CompiledMission.size(); + } + TMissionDataPtr getMission(uint index) + { + nlassert(index < _CompiledMission.size()); + return _CompiledMission[index]; + } + + +private: + + /// Storage for loaded primitive + struct TLoadedPrimitive + { + NLLIGO::CPrimitives *PrimDoc; + std::string FullFileName; + + TLoadedPrimitive() + : PrimDoc(NULL) + {} + + TLoadedPrimitive(NLLIGO::CPrimitives *primDoc, const std::string &fullFileName) + : PrimDoc(primDoc), + FullFileName(fullFileName) + { + } + }; + + /// Storage for precompiled missions. + std::vector _CompiledMission; + + /// Storage for files to publish + std::vector _FilesToPublish; +}; + + +// Class to easily handle var and var name pair +struct TCompilerVarName +{ + typedef std::vector > TPredefParams; + // Default parameter name + std::string _DefaultName; + // Type of script parameter + STRING_MANAGER::TParamType _ParamType; + // the name of the compiler var, like 'the_creature' in $the_creature$ = chab1 + std::string _VarName; + // the value of the compiler var line 'chab1' in $the_creature$ = chab1 + std::string _VarValue; + + void init(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string propName); + + void initWithText(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string &text); + + CPhrase::TParamInfo getParamInfo() const; + + bool empty() const; + + operator const std::string () const; + + operator CPhrase::TParamInfo() const; + + //static void getPhrasePredef(const TCompilerVarName::TPredefParams& compilerParams, CPhrase::TPredefParams& params); + + static std::vector getPropertyArrayWithText(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string & arrayProperyName); + static std::vector getPropertyArrayWithTextStaticDefaultName(const std::string &defaultName, STRING_MANAGER::TParamType type, CMissionData &md, NLLIGO::IPrimitive *prim, const std::string & arrayProperyName); + + +}; + +std::string operator+(const TCompilerVarName& left, const std::string & right); +std::string operator+(const std::string & left, const TCompilerVarName& right); + + diff --git a/code/ryzom/tools/leveldesign/mission_compiler_lib/step.h b/code/ryzom/tools/leveldesign/mission_compiler_lib/step.h index 3a38f8689..24f80a19a 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_lib/step.h +++ b/code/ryzom/tools/leveldesign/mission_compiler_lib/step.h @@ -1,268 +1,268 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/misc/types_nl.h" -#include "nel/ligo/primitive.h" -#include - -#ifndef __STEP_H__ -#define __STEP_H__ - - -/** Action and objective base class */ -class IStepContent -{ -public: - enum TStepContentType - { - objective, - action - }; -protected: - std::string _ContentName; - TStepContentType _ContentType; - /// post action list - std::vector _PostActions; - - // called by base class to retrieve the predefined parameters lists - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) = 0; -public: - - virtual void init(CMissionData &md, NLLIGO::IPrimitive *prim); - - /// Generate the mission script code for this step content. - std::string genStepContentCode(CMissionData &md); - - /// Generate the phrase string. - std::string genStepContentPhrase(); - - static IStepContent *createStepContent(CMissionData &md, NLLIGO::IPrimitive *prim); - - virtual void fillJump(CMissionData &md, std::set &jumpPoints); - -protected: - /// Generate the mission script code for this step content. - virtual std::string genCode(CMissionData &md) = 0; - /// Generate the phrase string. - virtual std::string genPhrase() { return std::string();} -}; - - -/** Step base class */ -class IStep -{ -protected: - /// The name of the step - std::string _StepName; - /// The type of the step - std::string _StepType; - /// Pointer on primitive that generate this step - NLLIGO::IPrimitive *_Primitive; - - /// The list of pre-action - std::vector _PreActions; - /// The list of objectives - std::vector _Objectives; - /// The list of post action - std::vector _PostActions; - /// Substeps used for sequence interruption (like an if) - std::vector _SubSteps; -public: - /// Flag this step a last of a branch, the compiler will generate a fail after it. - bool EndOfBranch; - /// Flag this step as a jump point. This mean that there is a jump that jump on this step. - bool JumpPoint; - - IStep(CMissionData &md, NLLIGO::IPrimitive *prim); - virtual ~IStep() {} - - virtual void init(CMissionData &md, NLLIGO::IPrimitive *prim) {} - - - /// Get the step name - const std::string &getStepName() - { - return _StepName; - } - - NLLIGO::IPrimitive *getPrimitive() - { - return _Primitive; - } - - /// Return true if the step is an action step. -// virtual bool isAction() { return false; } - - virtual bool isAJump() { return false; } - - virtual bool isEnd() { return false; } - - /// Return a set of primitive pointer on the sub branch of this step (if any) - virtual NLLIGO::TPrimitiveSet getSubBranchs() { return NLLIGO::TPrimitiveSet(); } - - /// Fill a vector of step name where this step eventualy jump (if any) - void fillStepJump(CMissionData &md, std::set &jumpPoints); - - /// Generate the mission script code for this step. - virtual std::string genCode(CMissionData &md); - - virtual std::string genCodePreActions(CMissionData &md); - virtual std::string genCodeObjectives(CMissionData &md); - virtual std::string genCodePostActions(CMissionData &md); - - void addSubStep(IStep *s) { _SubSteps.push_back(s); } - - - /// Generate the string phrase text. - virtual std::string genPhrase(); - - /// Factory function to create a new step. The caller is responsible for deleting the allocated object. - static IStep *createStep(CMissionData &md, NLLIGO::IPrimitive *prim); - -protected: - /// Fill a vector of step name where this step eventualy jump (if any) - virtual void fillJump(CMissionData &md, std::set &jumpPoints); - -}; - - -/** StepContent FACTORY **/ -class IStepContentFactory -{ -public: - virtual IStepContent *createStepContent(CMissionData &md, NLLIGO::IPrimitive *prim) =0; -}; - -template -class CStepContentFactory : public IStepContentFactory -{ -public: - IStepContent *createStepContent(CMissionData &md, NLLIGO::IPrimitive *prim) - { - IStepContent *ret = new contentClass; - ret->init(md, prim); - return ret; - } -}; - -#define REGISTER_STEP_CONTENT(className, key) typedef CStepContentFactory TStepContentFactory##className; \ - NLMISC_REGISTER_OBJECT_INDIRECT(IStepContentFactory, TStepContentFactory##className, string, key) - - - -/** Step FACTORY **/ -class IStepFactory -{ -public: - virtual IStep *createStep(CMissionData &md, NLLIGO::IPrimitive *prim) = 0; -}; - -template -class CStepFactory : public IStepFactory -{ - IStep *createStep(CMissionData &md, NLLIGO::IPrimitive *prim) - { - return new StepClass(md, prim); - } -}; - -#define REGISTER_STEP_INDIRECT(stepClass, key) typedef CStepFactory TStepFactory##stepClass; \ - NLMISC_REGISTER_OBJECT_INDIRECT(IStepFactory, TStepFactory##stepClass, string, string(key)); - - -/** objective base class **/ -class CContentObjective : public IStepContent -{ -protected: - std::vector _OverloadObj; - CPhrase _OverloadPhrase; - std::vector _RoleplayObj; - CPhrase _RoleplayPhrase; - bool _HideObj; - - // Option nb_guild_members_needed, available for each objective - /*int _NbGuildMembersNeeded; - - std::string genNbGuildMembersNeededOption(CMissionData &md);*/ - -public: - void init(CMissionData &md, NLLIGO::IPrimitive *prim); - - std::string genCode(CMissionData &md); - - std::string genPhrase(); -}; - -/** special case for step if **/ - -class CStepIf : public IStep -{ - - enum TIfType - { - it_mission_done, - it_skills, - it_bricks, - it_sdb, - it_race, - it_cult, - it_civ, - it_faction_point, - it_guild_cult, - it_guild_civ, - it_guild_fame, - it_no_trial, - it_item_in_inv, - }; - -public: - - CStepIf(CMissionData &md, NLLIGO::IPrimitive *prim); - - NLLIGO::TPrimitiveSet getSubBranchs(); - - void fillJump(CMissionData &md, std::set &jumpPoints); - - std::string genCode(CMissionData &md); - - /// type of test - TIfType _IfType; - /// If parameters - std::vector _IfParams; - /// the list of sub branch for the dyn chat. - NLLIGO::TPrimitiveSet _SubBranchs; -}; - -/** special case for step player reconnect **/ - -class CStepPlayerReconnect : public IStep -{ - // Optional jump at end of failure - std::string _JumpTo; - /// the list of sub branch - NLLIGO::TPrimitiveSet _SubBranchs; - -public: - CStepPlayerReconnect(CMissionData &md, NLLIGO::IPrimitive *prim); - - NLLIGO::TPrimitiveSet getSubBranchs(); - - std::string genCode(CMissionData &md); - - void fillJump(CMissionData &md, std::set &jumpPoints); -}; - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/misc/types_nl.h" +#include "nel/ligo/primitive.h" +#include + +#ifndef __STEP_H__ +#define __STEP_H__ + + +/** Action and objective base class */ +class IStepContent +{ +public: + enum TStepContentType + { + objective, + action + }; +protected: + std::string _ContentName; + TStepContentType _ContentType; + /// post action list + std::vector _PostActions; + + // called by base class to retrieve the predefined parameters lists + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) = 0; +public: + + virtual void init(CMissionData &md, NLLIGO::IPrimitive *prim); + + /// Generate the mission script code for this step content. + std::string genStepContentCode(CMissionData &md); + + /// Generate the phrase string. + std::string genStepContentPhrase(); + + static IStepContent *createStepContent(CMissionData &md, NLLIGO::IPrimitive *prim); + + virtual void fillJump(CMissionData &md, std::set &jumpPoints); + +protected: + /// Generate the mission script code for this step content. + virtual std::string genCode(CMissionData &md) = 0; + /// Generate the phrase string. + virtual std::string genPhrase() { return std::string();} +}; + + +/** Step base class */ +class IStep +{ +protected: + /// The name of the step + std::string _StepName; + /// The type of the step + std::string _StepType; + /// Pointer on primitive that generate this step + NLLIGO::IPrimitive *_Primitive; + + /// The list of pre-action + std::vector _PreActions; + /// The list of objectives + std::vector _Objectives; + /// The list of post action + std::vector _PostActions; + /// Substeps used for sequence interruption (like an if) + std::vector _SubSteps; +public: + /// Flag this step a last of a branch, the compiler will generate a fail after it. + bool EndOfBranch; + /// Flag this step as a jump point. This mean that there is a jump that jump on this step. + bool JumpPoint; + + IStep(CMissionData &md, NLLIGO::IPrimitive *prim); + virtual ~IStep() {} + + virtual void init(CMissionData &md, NLLIGO::IPrimitive *prim) {} + + + /// Get the step name + const std::string &getStepName() + { + return _StepName; + } + + NLLIGO::IPrimitive *getPrimitive() + { + return _Primitive; + } + + /// Return true if the step is an action step. +// virtual bool isAction() { return false; } + + virtual bool isAJump() { return false; } + + virtual bool isEnd() { return false; } + + /// Return a set of primitive pointer on the sub branch of this step (if any) + virtual NLLIGO::TPrimitiveSet getSubBranchs() { return NLLIGO::TPrimitiveSet(); } + + /// Fill a vector of step name where this step eventualy jump (if any) + void fillStepJump(CMissionData &md, std::set &jumpPoints); + + /// Generate the mission script code for this step. + virtual std::string genCode(CMissionData &md); + + virtual std::string genCodePreActions(CMissionData &md); + virtual std::string genCodeObjectives(CMissionData &md); + virtual std::string genCodePostActions(CMissionData &md); + + void addSubStep(IStep *s) { _SubSteps.push_back(s); } + + + /// Generate the string phrase text. + virtual std::string genPhrase(); + + /// Factory function to create a new step. The caller is responsible for deleting the allocated object. + static IStep *createStep(CMissionData &md, NLLIGO::IPrimitive *prim); + +protected: + /// Fill a vector of step name where this step eventualy jump (if any) + virtual void fillJump(CMissionData &md, std::set &jumpPoints); + +}; + + +/** StepContent FACTORY **/ +class IStepContentFactory +{ +public: + virtual IStepContent *createStepContent(CMissionData &md, NLLIGO::IPrimitive *prim) =0; +}; + +template +class CStepContentFactory : public IStepContentFactory +{ +public: + IStepContent *createStepContent(CMissionData &md, NLLIGO::IPrimitive *prim) + { + IStepContent *ret = new contentClass; + ret->init(md, prim); + return ret; + } +}; + +#define REGISTER_STEP_CONTENT(className, key) typedef CStepContentFactory TStepContentFactory##className; \ + NLMISC_REGISTER_OBJECT_INDIRECT(IStepContentFactory, TStepContentFactory##className, string, key) + + + +/** Step FACTORY **/ +class IStepFactory +{ +public: + virtual IStep *createStep(CMissionData &md, NLLIGO::IPrimitive *prim) = 0; +}; + +template +class CStepFactory : public IStepFactory +{ + IStep *createStep(CMissionData &md, NLLIGO::IPrimitive *prim) + { + return new StepClass(md, prim); + } +}; + +#define REGISTER_STEP_INDIRECT(stepClass, key) typedef CStepFactory TStepFactory##stepClass; \ + NLMISC_REGISTER_OBJECT_INDIRECT(IStepFactory, TStepFactory##stepClass, string, string(key)); + + +/** objective base class **/ +class CContentObjective : public IStepContent +{ +protected: + std::vector _OverloadObj; + CPhrase _OverloadPhrase; + std::vector _RoleplayObj; + CPhrase _RoleplayPhrase; + bool _HideObj; + + // Option nb_guild_members_needed, available for each objective + /*int _NbGuildMembersNeeded; + + std::string genNbGuildMembersNeededOption(CMissionData &md);*/ + +public: + void init(CMissionData &md, NLLIGO::IPrimitive *prim); + + std::string genCode(CMissionData &md); + + std::string genPhrase(); +}; + +/** special case for step if **/ + +class CStepIf : public IStep +{ + + enum TIfType + { + it_mission_done, + it_skills, + it_bricks, + it_sdb, + it_race, + it_cult, + it_civ, + it_faction_point, + it_guild_cult, + it_guild_civ, + it_guild_fame, + it_no_trial, + it_item_in_inv, + }; + +public: + + CStepIf(CMissionData &md, NLLIGO::IPrimitive *prim); + + NLLIGO::TPrimitiveSet getSubBranchs(); + + void fillJump(CMissionData &md, std::set &jumpPoints); + + std::string genCode(CMissionData &md); + + /// type of test + TIfType _IfType; + /// If parameters + std::vector _IfParams; + /// the list of sub branch for the dyn chat. + NLLIGO::TPrimitiveSet _SubBranchs; +}; + +/** special case for step player reconnect **/ + +class CStepPlayerReconnect : public IStep +{ + // Optional jump at end of failure + std::string _JumpTo; + /// the list of sub branch + NLLIGO::TPrimitiveSet _SubBranchs; + +public: + CStepPlayerReconnect(CMissionData &md, NLLIGO::IPrimitive *prim); + + NLLIGO::TPrimitiveSet getSubBranchs(); + + std::string genCode(CMissionData &md); + + void fillJump(CMissionData &md, std::set &jumpPoints); +}; + #endif // __STEP_H__ \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/mission_compiler_lib/step_content.cpp b/code/ryzom/tools/leveldesign/mission_compiler_lib/step_content.cpp index f327f836a..0e24b05e6 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_lib/step_content.cpp +++ b/code/ryzom/tools/leveldesign/mission_compiler_lib/step_content.cpp @@ -1,3466 +1,3466 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "mission_compiler.h" -#include "step.h" - -#include "nel/ligo/primitive_utils.h" - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; - - -// ************ -// IStepContent -// ************ - -IStepContent *IStepContent::createStepContent(CMissionData &md, NLLIGO::IPrimitive *prim) -{ - string className; - prim->getPropertyByName("class", className); - - IStepContentFactory *factory = CFactoryIndirect::instance().getFactory(className); - if (factory == NULL) - { - string err = toString("Can't find factory for class '%s'", className.c_str()); - throw EParseException(prim, err.c_str()); - } - - IStepContent *content = factory->createStepContent(md, prim); - return content; -} - -void IStepContent::init(CMissionData &md, NLLIGO::IPrimitive *prim) -{ - prim->getPropertyByName("name", _ContentName); - - // parse the post actions - for (uint i=0; igetNumChildren(); ++i) - { - IPrimitive *child; - prim->getChild(child, i); - if (child) - { - // ok, we got one - IStepContent *sc = IStepContent::createStepContent(md, child); - if (sc) - _PostActions.push_back(sc); - } - } -} - -std::string IStepContent::genStepContentCode(CMissionData &md) -{ - string ret; - // call the derived class code generation - ret += genCode(md); - - // generate the code for the post action - for (uint i=0; i<_PostActions.size(); ++i) - { - ret += _PostActions[i]->genCode(md); - } - - return ret; -} - -std::string IStepContent::genStepContentPhrase() -{ - string ret; - - // call ther derived class phrase generation - ret += genPhrase(); - - // generate the phrase for the post action - for (uint i=0; i<_PostActions.size(); ++i) - { - ret += _PostActions[i]->genPhrase(); - } - - return ret; -} - -void IStepContent::fillJump(CMissionData &md, std::set &jumpPoints) -{ - for (uint i=0; i<_PostActions.size(); ++i) - { - _PostActions[i]->fillJump(md, jumpPoints); - } -} - - -////////////////////// Actions and objectives ///////////////////// - -class CActionJumpTo : public IStepContent -{ - string _JumpTo; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _JumpTo = md.getProperty(prim, "target", true, false); - } - - string genCode(CMissionData &md) - { - if (!_JumpTo.empty()) - return "jump : "+_JumpTo+NL; - else - return string(); - } - - void fillJump(CMissionData &md, std::set &jumpPoints) - { - IStepContent::fillJump(md, jumpPoints); - jumpPoints.insert(TJumpInfo(_JumpTo, "", false)); - } - -}; -REGISTER_STEP_CONTENT(CActionJumpTo, "jump_to"); - - -// --------------------------------------------------------------------------- -class CActionRecvMoney : public IStepContent -{ - string _Amount; - bool _Guild; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _Amount = md.getProperty(prim, "amount", true, false); - - _Guild = md.getProperty(prim, "guild", false, true) == "true"; - // Check: if _Guild is true then check if we are in a guild mission - if (_Guild && !md.isGuildMission()) - { - string err = toString("primitive(%s): 'guild' option true 1 for non guild mission.", prim->getName().c_str()); - throw EParseException(prim, err.c_str()); - } - } - - string genCode(CMissionData &md) - { - if (!_Amount.empty()) - { - string ret; - ret = "recv_money : "+_Amount; - if (_Guild) - ret += ": guild"; - ret += NL; - return ret; - } - else - return string(); - } - -}; -REGISTER_STEP_CONTENT(CActionRecvMoney, "recv_money"); - - -// --------------------------------------------------------------------------- -class CActionRecvChargePoint : public IStepContent -{ - string _Amount; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _Amount = md.getProperty(prim, "charge_points", true, false); - } - - string genCode(CMissionData &md) - { - if (!_Amount.empty()) - { - string ret; - ret = "recv_charge_point : "+_Amount; - ret += NL; - return ret; - } - else - return string(); - } - -}; -REGISTER_STEP_CONTENT(CActionRecvChargePoint, "recv_charge_point"); - - -// --------------------------------------------------------------------------- -class CActionGiveOutpostControl : public IStepContent -{ - string _OutpostName; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _OutpostName = md.getProperty(prim, "outpost_name", true, false); - } - - string genCode(CMissionData &md) - { - if (!_OutpostName.empty()) - { - string ret; - ret = "give_control : "+_OutpostName; - ret += NL; - return ret; - } - else - return string(); - } - -}; -REGISTER_STEP_CONTENT(CActionGiveOutpostControl, "give_control"); - - -// --------------------------------------------------------------------------- -class CActionSpawnMission : public IStepContent -{ -protected: - string _MissionName; - string _GiverName; - bool _Guild; -private: - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _MissionName = md.getProperty(prim, "mission_name", true, false); - _GiverName = md.getProperty(prim, "giver_name", true, false); - if (_GiverName.empty()) - { - throw EParseException(prim, "giver_name is empty !"); - } - - _Guild = md.getProperty(prim, "guild", false, true) == "true"; - // Check: if _Guild is true then check if we are in a guild mission - if (_Guild && !md.isGuildMission()) - { - string err = toString("primitive(%s): 'guild' option true 1 for non guild mission.", prim->getName().c_str()); - throw EParseException(prim, err.c_str()); - } - } - - string genCode(CMissionData &md) - { - string ret = ""; - if (!_MissionName.empty()) - { - ret = "spawn_mission : " + _MissionName + " : " + _GiverName; - if (_Guild) - ret += " : guild"; - ret += NL; - } - return ret; - } -}; -REGISTER_STEP_CONTENT(CActionSpawnMission, "spawn_mission"); - - -// --------------------------------------------------------------------------- -class CActionChainMission : public CActionSpawnMission -{ -public: - - string genCode(CMissionData &md) - { - - if (!_MissionName.empty()) - { - - - return "chain_mission : " + _MissionName + " : " + _GiverName + NL; - } - else - return string(); - } - -}; -REGISTER_STEP_CONTENT(CActionChainMission, "chain_mission"); - - -// --------------------------------------------------------------------------- -class CActionEncycloUnlock : public IStepContent -{ - string _AlbumThema; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _AlbumThema = md.getProperty(prim, "album_thema", true, false); - } - - string genCode(CMissionData &md) - { - if (!_AlbumThema.empty()) - return "encyclo_unlock : " + _AlbumThema + NL; - else - return string(); - } - -}; -REGISTER_STEP_CONTENT(CActionEncycloUnlock, "encyclo_unlock"); - - -// --------------------------------------------------------------------------- -class CActionHandleCreate : public IStepContent -{ -protected: - string _Group; - string _DespawnTimer; -private: - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _Group = md.getProperty(prim, "group", true, false); - _DespawnTimer = md.getProperty(prim, "despawn_timer", true, false); - } - - string genCode(CMissionData &md) - { - if (!_Group.empty()) - { - if (!_DespawnTimer.empty()) - return "handle_create : " + _Group + " : " + _DespawnTimer + NL; - else - return "handle_create : " + _Group + NL; - } - else - return string(); - } - -}; -REGISTER_STEP_CONTENT(CActionHandleCreate, "handle_create"); - - -// --------------------------------------------------------------------------- -class CActionHandleRelease : public IStepContent -{ -protected: - string _Group; - -private: - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _Group = md.getProperty(prim, "group", true, false); - } - - string genCode(CMissionData &md) - { - if (!_Group.empty()) - return "handle_release : " + _Group + NL; - else - return string(); - } - -}; -REGISTER_STEP_CONTENT(CActionHandleRelease, "handle_release"); - - -// --------------------------------------------------------------------------- -class CActionSetEventFaction : public IStepContent -{ - string _EventFaction; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _EventFaction = md.getProperty(prim, "event_faction", true, false); - } - - string genCode(CMissionData &md) - { - if (!_EventFaction.empty()) - return "set_event_faction : " + _EventFaction + NL; - else - return string(); - } - -}; -REGISTER_STEP_CONTENT(CActionSetEventFaction, "set_event_faction"); - - -// --------------------------------------------------------------------------- -class CActionSetRespawnPoints : public IStepContent -{ - string _Continent; - vector _RespawnPoints; - bool _HideOthers; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _Continent = md.getProperty(prim, "continent", true, false); - - vector vs; - vs = md.getPropertyArray(prim, "respawn_points", true, false); - - for (uint i=0; igetName().c_str()); - throw EParseException(prim, err.c_str()); - } - } - - string genCode(CMissionData &md) - { - if (!_Faction.empty() && !_Fame.empty()) - { - string ret; - ret = "recv_fame : "+_Faction+" "+_Fame; - if (_Guild) - ret += ": guild"; - ret += NL; - return ret; - } - else - return string(); - } -}; -REGISTER_STEP_CONTENT(CActionRecvFame, "recv_fame"); - -// --------------------------------------------------------------------------- -struct TItemDesc -{ - string ItemName; - string ItemQuant; - string ItemQual; -}; - -class CActionRecvItem : public IStepContent -{ - string _BotGiver; - vector _Items; - bool _QualSpec; - bool _Group; - bool _Guild; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - _BotGiver =md.getProperty(prim, "npc_name", true, false); - vector vs; - vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); - for (uint i=0; i args; - if (!vs[i].empty()) - { - explode(vs[i], string(" "), args, false); - if (args.size() != 3 && args.size() != 2) - { - string err = toString("can't find 2 or 3 part ( []) in item line '%s', found %u instead", vs[i].c_str(), args.size()); - throw EParseException(prim, err.c_str()); - } - - if (i == 0) - { - _QualSpec = (args.size() == 3); - } - else if (args.size() == 3 && !_QualSpec) - { - string err = toString("can't mix item with quality and item without quality in item line '%s'", vs[i].c_str()); - throw EParseException(prim, err.c_str()); - } - - TItemDesc item; - item.ItemName = args[0]; - item.ItemQuant = args[1]; - if (_QualSpec) - item.ItemQual = args[2]; - - _Items.push_back(item); - } - } - - string s; - s = md.getProperty(prim, "group", true, false); - _Group = (NLMISC::toLower(s) == "true"); - - _Guild = md.getProperty(prim, "guild", false, true) == "true"; - // Check: if _Guild is true then check if we are in a guild mission - if (_Guild && !md.isGuildMission()) - { - string err = toString("primitive(%s): 'guild' option true 1 for non guild mission.", prim->getName().c_str()); - throw EParseException(prim, err.c_str()); - } - - IStepContent::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - for (uint i=0; i<_Items.size(); ++i) - { - TItemDesc &item = _Items[i]; - - ret += "recv_item : "+item.ItemName+" "+item.ItemQuant; - if (_QualSpec) - ret +=" "+item.ItemQual; - if (!_BotGiver.empty()) - ret += " : "+_BotGiver; - if (_Group) - ret += " : group"; - if (_Guild) - ret += ": guild"; - ret += NL; - } - - return ret; - - } -}; -REGISTER_STEP_CONTENT(CActionRecvItem, "recv_item"); - -// --------------------------------------------------------------------------- -class CActionRecvNamedItem : public IStepContent -{ - vector _Items; - bool _Group; - bool _Guild; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - vector vs; - vs = md.getPropertyArray(prim, "item/quantity", true, false); - for (uint i=0; i args; - if (!vs[i].empty()) - { - explode(vs[i], string(" "), args, false); - if (args.size() != 1 && args.size() != 2) - { - string err = toString("can't find 1 or 2 part ( []) in item line '%s', found %u instead", vs[i].c_str(), args.size()); - throw EParseException(prim, err.c_str()); - } - - TItemDesc item; - item.ItemName = args[0]; - item.ItemQuant = "1"; - if(args.size()>=2 && atoi(args[1].c_str())>0) - item.ItemQuant = args[1]; - - _Items.push_back(item); - } - } - - string s; - s = md.getProperty(prim, "group", true, false); - _Group = (NLMISC::toLower(s) == "true"); - - _Guild = md.getProperty(prim, "guild", false, true) == "true"; - // Check: if _Guild is true then check if we are in a guild mission - if (_Guild && !md.isGuildMission()) - { - string err = toString("primitive(%s): 'guild' option true 1 for non guild mission.", prim->getName().c_str()); - throw EParseException(prim, err.c_str()); - } - - IStepContent::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - for (uint i=0; i<_Items.size(); ++i) - { - TItemDesc &item = _Items[i]; - - ret += "recv_named_item : "+item.ItemName+" "+item.ItemQuant; - if (_Group) - ret += " : group"; - if (_Guild) - ret += ": guild"; - ret += NL; - } - - return ret; - - } -}; -REGISTER_STEP_CONTENT(CActionRecvNamedItem, "recv_named_item"); - -// --------------------------------------------------------------------------- -class CActionDestroyItem : public IStepContent -{ - struct CItemDesc - { - TItemDesc Desc; - bool QuantSpec; - bool QualSpec; - }; - - string _BotDestroyer; - vector _Items; - bool _Guild; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - // get the bot who destroys the item - _BotDestroyer =md.getProperty(prim, "npc_name", true, false); - - // read list of items to destroy - vector vs; - vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); - for (uint i=0; i args; - if (!vs[i].empty()) - { - // parse - explode(vs[i], string(" "), args, false); - if (args.size()<1 || args.size()>3) - { - string err = toString("can't find 1, 2 or 3 part ( [] []) in item line '%s', found %u instead", vs[i].c_str(), args.size()); - throw EParseException(prim, err.c_str()); - } - - // add the item in desc - CItemDesc item; - item.Desc.ItemName = args[0]; - if(args.size()>=2) - { - item.QuantSpec= true; - item.Desc.ItemQuant = args[1]; - } - if(args.size()>=3) - { - item.QualSpec= true; - item.Desc.ItemQual = args[2]; - } - - _Items.push_back(item); - } - } - - _Guild = md.getProperty(prim, "guild", false, true) == "true"; - // Check: if _Guild is true then check if we are in a guild mission - if (_Guild && !md.isGuildMission()) - { - string err = toString("primitive(%s): 'guild' option true 1 for non guild mission.", prim->getName().c_str()); - throw EParseException(prim, err.c_str()); - } - - IStepContent::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - for (uint i=0; i<_Items.size(); ++i) - { - CItemDesc &item = _Items[i]; - - ret += "destroy_item : "+item.Desc.ItemName; - if (item.QuantSpec) - ret +=" "+item.Desc.ItemQuant; - if (item.QualSpec) - ret +=" "+item.Desc.ItemQual; - if (!_BotDestroyer.empty()) - ret += " : "+_BotDestroyer; - if (_Guild) - ret += ": guild"; - ret += NL; - } - - return ret; - - } -}; -REGISTER_STEP_CONTENT(CActionDestroyItem, "destroy_item"); - -// --------------------------------------------------------------------------- -class CActionRecvXp : public IStepContent -{ - string _Skill; - sint32 _Value; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _Skill = md.getProperty(prim, "skill", true, false); - _Value = atoi(md.getProperty(prim, "value", true, false).c_str()); - if(_Skill.empty() || tolower(_Skill[0])!='s' || _Value<=0) - { - string err = toString("Bad skill name or value: '%s' '%d' ", _Skill.c_str(), _Value); - throw EParseException(prim, err.c_str()); - } - } - - string genCode(CMissionData &md) - { - if (!_Skill.empty()) - return toString("recv_xp : %s %d", _Skill.c_str(), _Value) + NL; - else - return string(); - } -}; -REGISTER_STEP_CONTENT(CActionRecvXp, "recv_xp"); - -// --------------------------------------------------------------------------- -class CActionLearnAction : public IStepContent -{ - string _BotGiver; - vector _Actions; - bool _Group; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - _BotGiver = md.getProperty(prim, "npc_name", true, false); - vector vs; - vs = md.getPropertyArray(prim, "actions", true, false); - - for (uint i=0; i _Bricks; - bool _Group; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - _BotGiver = md.getProperty(prim, "npc_name", true, false); - vector vs; - vs = md.getPropertyArray(prim, "bricks", true, false); - - for (uint i=0; i vs; - vs = md.getPropertyArray(prim, "phrase", false, false); - _Phrase.initPhrase(md, prim, vs); - - _ChatMode = md.getProperty(prim, "chat_type", true, false); - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "bot_chat : "+_ChatMode+" : "+_BotName+" : "+_Phrase.genScript(md)+NL; - return ret; - } - - string genPhrase() - { - return _Phrase.genPhrase(); - } -}; -REGISTER_STEP_CONTENT(CActionBotChat, "bot_chat"); - -// --------------------------------------------------------------------------- -class CActionBotEmote : public IStepContent -{ - string _BotName; - string _Emote; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - _BotName = md.getProperty(prim, "npc_name", true, false); - _Emote = md.getProperty(prim, "emote", true, false); - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "bot_emot : "+_BotName+" "+_Emote+NL; - return ret; - } -}; -REGISTER_STEP_CONTENT(CActionBotEmote, "bot_emote"); - -// --------------------------------------------------------------------------- -class CActionAIEvent : public IStepContent -{ - string _GroupName; - string _EventNumber; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - _GroupName = md.getProperty(prim, "group_name", true, false); - _EventNumber = md.getProperty(prim, "event_number", true, false); - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "ai_event : "+_GroupName+"; "+_EventNumber+NL; - return ret; - } -}; -REGISTER_STEP_CONTENT(CActionAIEvent, "ai_event"); - -// --------------------------------------------------------------------------- -class CActionSetTeleport : public CActionBotChat -{ - string _WorldPosition; - bool _Once; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - CActionBotChat::init(md, prim); - - _WorldPosition = md.getProperty(prim, "world_position", true, false); - string s; - prim->getPropertyByName("once", s); - _Once = (NLMISC::toLower(s) == "true"); - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "set_teleport : "+_BotName+" : "+_WorldPosition+" : "; - - if (_Once) - ret += "once : "; - ret += _Phrase.genScript(md) + NL; - return ret; - } -}; -REGISTER_STEP_CONTENT(CActionSetTeleport, "set_teleport"); - -// --------------------------------------------------------------------------- -class CActionTeleport : public IStepContent -{ - string _WorldPosition; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - _WorldPosition = md.getProperty(prim, "world_position", true, false); - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "teleport : "+_WorldPosition+NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CActionTeleport, "teleport"); - -// --------------------------------------------------------------------------- -class CActionSetCult : public IStepContent -{ - string _Cult; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - _Cult = md.getProperty(prim, "cult", true, false); - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "set_cult : " + _Cult + NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CActionSetCult, "set_cult"); - -// --------------------------------------------------------------------------- -class CActionSetCiv : public IStepContent -{ - string _Civ; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - _Civ = md.getProperty(prim, "civ", true, false); - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "set_civ : " + _Civ + NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CActionSetCiv, "set_civ"); - -// --------------------------------------------------------------------------- -class CActionSetGuildCult : public IStepContent -{ - string _Cult; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - _Cult = md.getProperty(prim, "cult", true, false); - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "set_guild_cult : " + _Cult + NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CActionSetGuildCult, "set_guild_cult"); - -// --------------------------------------------------------------------------- -class CActionSetGuildCiv : public IStepContent -{ - string _Civ; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - _Civ = md.getProperty(prim, "civ", true, false); - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "set_guild_civ : " + _Civ + NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CActionSetGuildCiv, "set_guild_civ"); - -// --------------------------------------------------------------------------- -class CActionAddCompass : public IStepContent -{ - string _NpcName; - string _PlaceName; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - _NpcName = md.getProperty(prim, "npc_to_add", true, false); - _PlaceName = md.getProperty(prim, "place_to_add", true, false); - } - - string genCode(CMissionData &md) - { - string ret; - - if (!_NpcName.empty()) - ret = "add_compass_npc : "+_NpcName+NL; - if (!_PlaceName.empty()) - ret += "add_compass_place : "+_PlaceName+NL; - return ret; - } -}; -REGISTER_STEP_CONTENT(CActionAddCompass, "add_compass"); - -// --------------------------------------------------------------------------- -class CActionRemoveCompass : public IStepContent -{ - string _NpcName; - string _PlaceName; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - _NpcName = md.getProperty(prim, "npc_to_remove", true, false); - _PlaceName = md.getProperty(prim, "place_to_remove", true, false); - } - - string genCode(CMissionData &md) - { - string ret; - - if (!_NpcName.empty()) - ret = "remove_compass_npc : "+_NpcName+NL; - if (!_PlaceName.empty()) - ret += "remove_compass_place : "+_PlaceName+NL; - return ret; - } -}; -REGISTER_STEP_CONTENT(CActionRemoveCompass, "remove_compass"); - -// --------------------------------------------------------------------------- -class CActionFail : public IStepContent -{ - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - } - - string genCode(CMissionData &md) - { - return string("fail")+NL; - } -}; -REGISTER_STEP_CONTENT(CActionFail, "fail"); - -// --------------------------------------------------------------------------- -class CActionFailIfSDB : public IStepContent -{ - - string _Condition; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _Condition = md.getProperty(prim, "condition", true, false); - } - - string genCode(CMissionData &md) - { - return string("fail_if_sdb : ")+_Condition+NL; - } -}; -REGISTER_STEP_CONTENT(CActionFailIfSDB, "fail_if_sdb"); - -// --------------------------------------------------------------------------- -class CActionFailMissionCat : public IStepContent -{ - - string _MissionCategory; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _MissionCategory = md.getProperty(prim, "category", true, false); - } - - string genCode(CMissionData &md) - { - return string("fail_mission_cat : ")+_MissionCategory+NL; - } -}; -REGISTER_STEP_CONTENT(CActionFailMissionCat, "fail_mission_cat"); - -// --------------------------------------------------------------------------- -class CActionSystemMsg : public IStepContent -{ - CPhrase _Message; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - vector vs = md.getPropertyArray(prim, "msg_to_display", false, false); - - _Message.initPhrase(md, prim, vs); - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "system_msg : "+_Message.genScript(md)+NL; - return ret; - } - - string genPhrase() - { - return _Message.genPhrase(); - } -}; -REGISTER_STEP_CONTENT(CActionSystemMsg, "system_msg"); - -// --------------------------------------------------------------------------- -class CActionPopupMsg : public IStepContent -{ - CPhrase _Title; - CPhrase _Message; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - vector vst = md.getPropertyArray(prim, "title_to_display", false, false); - vector vsm = md.getPropertyArray(prim, "msg_to_display", false, false); - - _Title.initPhrase(md, prim, vst); - _Message.initPhrase(md, prim, vsm); - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "popup_msg : " + _Title.genScript(md) + " : " + _Message.genScript(md) + NL; - return ret; - } - - string genPhrase() - { - return _Title.genPhrase() + _Message.genPhrase(); - } -}; -REGISTER_STEP_CONTENT(CActionPopupMsg, "popup_msg"); - -// --------------------------------------------------------------------------- -class CActionDeclareWar : public IStepContent -{ - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - } - - string genCode(CMissionData &md) - { - return string("declare_war")+NL; - } -}; -REGISTER_STEP_CONTENT(CActionDeclareWar, "declare_war"); - -// --------------------------------------------------------------------------- -class CActionSetConstrains : public IStepContent -{ - string _Timer; - string _TimePeriod; - string _InsidePlace; - string _InsidePlaceDelay; - string _OutsidePlace; - string _OutsidePlaceDelay; - vector _Wears; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - _Timer = md.getProperty(prim, "timer", true, false); - _TimePeriod = md.getProperty(prim, "time_period", true, false); - _InsidePlace = md.getProperty(prim, "inside_place", true, false); - _InsidePlaceDelay = md.getProperty(prim, "inside_place_delay", true, false); - _OutsidePlace = md.getProperty(prim, "outside_place", true, false); - _OutsidePlaceDelay = md.getProperty(prim, "outside_place_delay", true, false); - _Wears = md.getPropertyArray(prim, "wear", true, false); - } - - string genCode(CMissionData &md) - { - string ret; - - if (!_Timer.empty()) - ret += "timer : "+_Timer+NL; - if (!_TimePeriod.empty()) - { - if ( _TimePeriod == "winter" - || _TimePeriod == "spring" - || _TimePeriod == "summer" - || _TimePeriod == "autumn" - || _TimePeriod == "none") - { - ret += "season : "+_TimePeriod+NL; - } - else - ret += "day_period : "+_TimePeriod+NL; - } - if (!_InsidePlace.empty()) - { - if (_InsidePlace != "none") - { - ret += "inside : "+_InsidePlace; - if (!_InsidePlaceDelay.empty()) - ret += " : "+_InsidePlaceDelay; - } - else - ret += "inside"; - ret += NL; - } - if (!_OutsidePlace.empty()) - { - if (_OutsidePlace != "none") - { - ret += "outside : "+_OutsidePlace; - if (!_OutsidePlaceDelay.empty()) - ret += " : "+_OutsidePlaceDelay; - } - else - ret += "outside"; - ret += NL; - } - if (!_Wears.empty()) - nlwarning("wear constraint not implemented yet"); - return ret; - } -}; -REGISTER_STEP_CONTENT(CActionSetConstrains, "set_constrains"); - -// --------------------------------------------------------------------------- -class CActionSetDesc : public IStepContent -{ - CPhrase _Description; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - - std::vector vs = md.getPropertyArray(prim, "mission_description", false, false); - - _Description.initPhrase(md, prim, vs); - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "set_desc : "+_Description.genScript(md)+NL; - return ret; - } - - string genPhrase() - { - return _Description.genPhrase(); - } - -}; -REGISTER_STEP_CONTENT(CActionSetDesc, "set_desc"); - -// ***************** -// CContentObjective -// ***************** -// base class for step content objectives -// --------------------------------------------------------------------------- -void CContentObjective::init(CMissionData &md, IPrimitive *prim) -{ - IStepContent::init(md, prim); - - _HideObj = md.getProperty(prim, "hide_obj", true, false) == "true"; - _OverloadObj = md.getPropertyArray(prim, "overload_objective", false, false); - _RoleplayObj = md.getPropertyArray(prim, "roleplay_objective", false, false); - uint32 numEntry; - CPhrase::TPredefParams params; - // ask derived class for predefined params - getPredefParam(numEntry, params); - // init the overload phrase - _OverloadPhrase.initPhrase(md, prim, _OverloadObj, numEntry, params); - // init the roleplay phrase - _RoleplayPhrase.initPhrase(md, prim, _RoleplayObj, numEntry, params); - - // check for the 'nb_guild_members_needed' option and see if it's correct for this mission - /*string nbGuildMembersNeeded = md.getProperty(prim, "nb_guild_members_needed", false, true); - if (nbGuildMembersNeeded.empty()) - nbGuildMembersNeeded = "1"; - if (!fromString(nbGuildMembersNeeded.c_str(), _NbGuildMembersNeeded)) - _NbGuildMembersNeeded = 1; - - // Check: - if (!md.isGuildMission() && _NbGuildMembersNeeded != 1) - { - string err = toString("primitive(%s): nb_guild_members_needed != 1 for non guild mission.", prim->getName().c_str()); - throw EParseException(prim, err.c_str()); - }*/ -} - -// --------------------------------------------------------------------------- -string CContentObjective::genCode(CMissionData &md) -{ - string ret; - if (_HideObj) - ret = "hide_obj"+NL; - if (!_OverloadObj.empty()) - { - ret += "set_obj : " + _OverloadPhrase.genScript(md)+NL; - } - if (!_RoleplayObj.empty()) - { - ret += "set_obj_rp : " + _RoleplayPhrase.genScript(md)+NL; - } - return ret; -} - -// --------------------------------------------------------------------------- -/*std::string CContentObjective::genNbGuildMembersNeededOption(CMissionData &md) -{ - string ret = ""; - // If we are in a guild mission we add the 'nb_guild_members_needed' option to the script - if (md.isGuildMission()) - { - ret = ": nb_guild_members_needed "; - ret += toString(_NbGuildMembersNeeded); - } - - return ret; -}*/ - -// --------------------------------------------------------------------------- -string CContentObjective::genPhrase() -{ - if (!_OverloadObj.empty()) - return _OverloadPhrase.genPhrase(); - else - return _RoleplayPhrase.genPhrase(); -} - -// --------------------------------------------------------------------------- -// --------------------------------------------------------------------------- - -struct TKillFaunaInfo -{ - TCompilerVarName SheetName; - TCompilerVarName Quantity; -}; - -struct TKillRaceInfo -{ - TCompilerVarName RaceName; - TCompilerVarName Quantity; -}; - - -class CContentKill : public CContentObjective -{ - vector _KillFaunas; - vector _KillRaces; - TCompilerVarName _KillGroup; - vector _KillNpcs; - TCompilerVarName _KillNpcByNames; - TCompilerVarName _KillNpcByNamesQuantity; - TCompilerVarName _KillFactionName; - TCompilerVarName _KillFactionQuantity; - vector _PredefVarName; - TCompilerVarName _Place; - - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - if (!_KillFaunas.empty()) - { - numEntry = (uint32)_KillFaunas.size(); - predef.resize(numEntry); - for (uint i=0; i<_KillFaunas.size(); ++i) - { - predef[i].resize(2*(i+1)); - for (uint j=0; j vs; - vs = md.getPropertyArray(prim, "fauna/quantity", false, false); - for (uint i=0; i args; - explode(vs[i], string(" "), args, true); - if (args.size() != 2) - { - string err = toString("Syntax error in kill fauna : '%s', need ", vs[i].c_str()); - throw EParseException (prim, err.c_str()); - } - TKillFaunaInfo kfi; - kfi.SheetName.initWithText(toString("c%u", i+1), STRING_MANAGER::creature_model, md, prim, args[0]); - kfi.Quantity.initWithText(toString("q%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); - _KillFaunas.push_back(kfi); - } - - vs = md.getPropertyArray(prim, "race/quantity", false, false); - for (uint i=0; i args; - explode(vs[i], string(" "), args, true); - if (args.size() != 2) - { - string err = toString("Syntax error in kill race : '%s', need ", vs[i].c_str()); - throw EParseException (prim, err.c_str()); - } - TKillRaceInfo kri; - kri.RaceName.initWithText(toString("r%u", i+1), STRING_MANAGER::creature_model, md, prim, args[0]); - kri.Quantity.initWithText(toString("q%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); - _KillRaces.push_back(kri); - } - string s; - //s = md.getProperty(prim, "group", false, true); - vs = md.getPropertyArray(prim, "group", false, false); - if (!vs.empty()) - { - if (vs.size() != 1) - { - string err = "Syntax error in kill group"; - throw EParseException (prim, err.c_str()); - } - - _KillGroup.initWithText("group_name", STRING_MANAGER::bot_name, md, prim, vs[0] ); - - } - - - vs = md.getPropertyArray(prim, "npc", false, false); - for (uint i=0; i args; - explode(s, string(" "), args, true); - if (args.size() != 2) - { - string err = toString("Syntax error in kill npc by name : '%s', need ", s.c_str()); - throw EParseException(prim, err.c_str()); - } - _KillNpcByNames.initWithText("npc", STRING_MANAGER::bot_name, md, prim, args[0]); - _KillNpcByNamesQuantity.initWithText("qt", STRING_MANAGER::integer, md, prim, args[1]); - } - - s = md.getProperty(prim, "faction/quantity", false, false); - if (!s.empty()) - { - vector args; - explode(s, string(" "), args, true); - if (args.size() != 2) - { - string err = toString("Syntax error in kill faction : '%s', need ", s.c_str()); - throw EParseException (prim, err.c_str()); - } - _KillFactionName.initWithText("faction", STRING_MANAGER::faction, md, prim, args[0]); - _KillFactionQuantity.initWithText("qt", STRING_MANAGER::integer, md, prim, args[1]); - } - - bool check = false; - if (!_KillFaunas.empty()) - check = true; - if (!_KillRaces.empty()) - { - if (check) - throw EParseException(prim, "Merging of multiple kill mode is forbidden !"); - check = true; - } - if (!_KillGroup.empty()) - { - if (check) - throw EParseException(prim, "Merging of multiple kill mode is forbidden !"); - - check = true; - } - if (!_KillNpcs.empty()) - { - if (check) - throw EParseException(prim, "Merging of multiple kill mode is forbidden !"); - check = true; - } - if (!_KillNpcByNames._VarValue.empty()) - { - if (check) - throw EParseException(prim, "Merging of multiple kill mode is forbidden !"); - check = true; - } - if (!_KillFactionName.empty()) - { - if (check) - throw EParseException(prim, "Merging of multiple kill mode is forbidden !"); - check = true; - } - - _Place.init("p", STRING_MANAGER::place, md, prim, "place"); - - if (!_Place.empty() && !_KillGroup.empty()) - { - throw EParseException(prim, "Using location with kill group instruction is forbidden!"); - } - // init base class - CContentObjective::init(md, prim); - - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - if (!_KillFaunas.empty()) - { - ret += "kill_fauna : "; - for (uint i=0; i<_KillFaunas.size(); ++i) - { - ret += _KillFaunas[i].SheetName+" "+_KillFaunas[i].Quantity; - if (i < _KillFaunas.size()-1) - ret += "; "; - } - } - else if (!_KillRaces.empty()) - { - ret += "kill_race : "; - for (uint i=0; i<_KillRaces.size(); ++i) - { - ret += _KillRaces[i].RaceName+" "+_KillRaces[i].Quantity; - if (i < _KillRaces.size()-1) - ret += "; "; - } - } - else if (!_KillGroup.empty()) - { - ret += "kill_group : " + _KillGroup; - } - else if (!_KillNpcs.empty()) - { - ret += "kill_npc : "; - for (uint i=0; i<_KillNpcs.size(); ++i) - { - ret += _KillNpcs[i]; - if (i < _KillNpcs.size()-1) - ret += "; "; - } - } - else if (!_KillNpcByNames.empty()) - { - ret += "kill_npc_by_name : "+_KillNpcByNames+" "+_KillNpcByNamesQuantity; - } - else if (!_KillFactionName.empty()) - { - ret += "kill_faction : "+_KillFactionName+" "+_KillFactionQuantity; - } - - if (!_Place.empty()) - ret += " : "+_Place; - - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentKill, "kill"); - -class CContentTalkTo : public CContentObjective -{ - TCompilerVarName _BotName; - CPhrase _Phrase; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - predef.resize(1); - predef[0].resize(1); - predef[0][0] = _BotName; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - - - _BotName.init("npc", STRING_MANAGER::bot, md, prim, "npc_name" ); - - CPhrase::TPredefParams pp(1); - pp[0].push_back(_BotName.getParamInfo()); - - vector vs; - vs = md.getPropertyArray(prim, "phrase", false, false); - _Phrase.initPhrase(md, prim, vs, 0, pp); - -// _Phrase.initPhrase(md, prim, vs); - -// if (_Phrase.asAdditionnalParams()) -// { -// // we need to remove the default 'npc' parameter if add params are found -// CPhrase temp; -// temp.initPhrase(md, prim, vs); -// -// _Phrase = temp; -// } - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "talk_to : "+_BotName; - - if (!_Phrase.isEmpty()) - ret += " : "+_Phrase.genScript(md); - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } - - string genPhrase() - { - string ret; - ret = CContentObjective::genPhrase(); - ret += _Phrase.genPhrase(); - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentTalkTo, "talk_to"); - -class CContentCast : public CContentObjective -{ - vector _Actions; - TCompilerVarName _Place; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - - { - numEntry = (uint32)_Actions.size(); - predef.resize(numEntry); - for (uint i=0; i _Mps; - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = (uint32)_Mps.size(); - predef.resize(numEntry); - for (uint i=0; i vs; - vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); - - for (uint i=0; i args; - explode(vs[i], string(" "), args, true); - if (args.size() != 3) - { - string err = toString("Invalid forage item in '%s', need ", vs[i].c_str()); - throw EParseException(prim, err.c_str()); - } - - TForageInfo fi; - fi.Item.initWithText(toString("i%u", i+1), STRING_MANAGER::item, md, prim, args[0]); - fi.Qt.initWithText(toString("qt%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); - fi.Ql.initWithText(toString("qual%u", i+1), STRING_MANAGER::integer, md, prim, args[2]); - - _Mps.push_back(fi); - } - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "forage : "; - - for (uint i=0; i<_Mps.size(); ++i) - { - ret += _Mps[i].Item+" "+_Mps[i].Qt+" "+_Mps[i].Ql; - if (i < _Mps.size()-1) - ret += "; "; - } - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentForage, "forage"); - -struct TLootInfo -{ - TCompilerVarName Item; - TCompilerVarName Qt; - TCompilerVarName Ql; -}; - -class CContentLoot : public CContentObjective -{ - enum TLootMode - { - lm_unknown, - lm_item, - lm_mp - }; - - TLootMode _Mode; - vector _Items; - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - if (_Mode == lm_item) - { - numEntry = (uint32)_Items.size(); - predef.resize(numEntry); - for (uint i=0; i vs; - vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); - - for (uint i=0; i args; - explode(vs[i], string(" "), args, true); - if (args.size() != 1 && args.size() != 3) - { - string err = toString("Invalid loot item in '%s', need or ", vs[i].c_str()); - throw EParseException(prim, err.c_str()); - } - - if (args.size() == 1) - { - if (_Mode == lm_mp) - throw EParseException(prim, "Can't mix item and mps loot"); - _Mode = lm_item; - } - else if (args.size() == 3) - { - if (_Mode == lm_item) - throw EParseException(prim, "Can't mix item and mps loot"); - _Mode = lm_mp; - } - - TLootInfo li; - li.Item.initWithText(toString("i%u", i+1), STRING_MANAGER::item, md, prim, args[0]); - - if (args.size() > 1) - { - li.Qt.initWithText(toString("qt%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); - - li.Ql.initWithText(toString("qual%u", i+1), STRING_MANAGER::integer, md, prim, args[2]); - - } - _Items.push_back(li); - } - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - if (_Mode == lm_item) - ret += "loot_item : "; - else - ret += "loot_mp : "; - - for (uint i=0; i<_Items.size(); ++i) - { - ret += _Items[i].Item; - if (_Mode == lm_mp) - ret += " "+_Items[i].Qt+" "+_Items[i].Ql; - if (i < _Items.size()-1) - ret += "; "; - } - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentLoot, "loot"); - -struct TCraftInfo -{ - TCompilerVarName Item; - TCompilerVarName Qt; - TCompilerVarName Ql; -}; - -class CContentCraft : public CContentObjective -{ - vector _Items; - - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = (uint32)_Items.size(); - predef.resize(numEntry); - for (uint i=0; i vs; - vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); - - for (uint i=0; i args; - explode(vs[i], string(" "), args, true); - if (args.size() != 3) - { - string err = toString("Invalid craft item in '%s', need ", vs[i].c_str()); - throw EParseException(prim, err.c_str()); - } - - TCraftInfo ci; - ci.Item.initWithText(toString("i%u", i+1), STRING_MANAGER::item, md, prim, args[0]); - ci.Qt.initWithText(toString("qt%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); - ci.Ql.initWithText(toString("qual%u", i+1), STRING_MANAGER::integer, md, prim, args[2]); - _Items.push_back(ci); - } - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "craft : "; - - for (uint i=0; i<_Items.size(); ++i) - { - ret += _Items[i].Item+" "+_Items[i].Qt+" "+_Items[i].Ql; - if (i < _Items.size()-1) - ret += "; "; - } - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentCraft, "craft"); - -class CContentTarget : public CContentObjective -{ - - vector _Npcs; - vector _Faunas; - vector _Races; - TCompilerVarName _Place; - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - // phrase 0 - 1 parameter - // phrase 1 - 2 parameters - // etc ... as many (bots,faunas,race) as specified - - - if (!_Npcs.empty()) - { - numEntry = (uint32)_Npcs.size(); - predef.resize(numEntry); - for (uint i=0; i _Items; - TCompilerVarName _Npc; - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = (uint32)_Items.size(); - predef.resize(numEntry); - for (uint i=0; i vs; - vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); - - for (uint i=0; i args; - explode(vs[i], string(" "), args, true); - if (args.size() != 3) - { - string err = toString("Invalid sell item in '%s', need ", vs[i].c_str()); - throw EParseException(prim, err.c_str()); - } - - TSellInfo si; - si.Item.initWithText(toString("i%u", i+1), STRING_MANAGER::item, md, prim, args[0]); - si.Qt.initWithText(toString("qt%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); - si.Ql.initWithText(toString("qual%u", i+1), STRING_MANAGER::integer, md, prim, args[2]); - _Items.push_back(si); - } - - _Npc.init("npc", STRING_MANAGER::bot, md, prim, "npc_name"); - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "sell : "; - - for (uint i=0; i<_Items.size(); ++i) - { - ret += _Items[i].Item+" "+_Items[i].Qt+" "+_Items[i].Ql; - if (i < _Items.size()-1) - ret += "; "; - }; - if (!_Npc.empty()) - { - ret += " : "+_Npc; - } - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentSell, "sell"); - -struct TBuyInfo -{ - TCompilerVarName Item; - TCompilerVarName Qt; - TCompilerVarName Ql; -}; - -class CContentBuy : public CContentObjective -{ - vector _Items; - TCompilerVarName _Npc; - - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = (uint32)_Items.size(); - predef.resize(numEntry); - for (uint i=0; i vs; - vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); - - for (uint i=0; i args; - explode(vs[i], string(" "), args, true); - if (args.size() != 3) - { - string err = toString("Invalid buy item in '%s', need ", vs[i].c_str()); - throw EParseException(prim, err.c_str()); - } - - TBuyInfo bi; - bi.Item.initWithText(toString("i%u", i+1), STRING_MANAGER::item, md, prim, args[0]); - bi.Qt.initWithText(toString("qt%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); - bi.Ql.initWithText(toString("qual%u", i+1), STRING_MANAGER::integer, md, prim, args[2]); - _Items.push_back(bi); - } - - _Npc.init("npc", STRING_MANAGER::bot, md, prim, "npc_name"); - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "buy : "; - - for (uint i=0; i<_Items.size(); ++i) - { - ret += _Items[i].Item+" "+_Items[i].Qt+" "+_Items[i].Ql; - if (i < _Items.size()-1) - ret += "; "; - }; - if (!_Npc.empty()) - { - ret += " : "+_Npc; - } - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; - -REGISTER_STEP_CONTENT(CContentBuy, "buy"); - -struct TGiveInfo -{ - TCompilerVarName Item; - TCompilerVarName Qt; - TCompilerVarName Ql; -}; - -class CContentGive : public CContentObjective -{ - vector _Items; - TCompilerVarName _Npc; - bool _QualSpec; - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = (uint32)_Items.size(); - predef.resize(numEntry); - for (uint i=0; i vs; - vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); - - for (uint i=0; i args; - explode(vs[i], string(" "), args, true); - if (args.size() != 3 && args.size() != 2) - { - string err = toString("Invalid give item in '%s', need []", vs[i].c_str()); - throw EParseException(prim, err.c_str()); - } - - if (i == 0) - { - _QualSpec = args.size() == 3; - } - else - { - if (_QualSpec && args.size() == 2) - { - string err = toString("Invalid give item in '%s', mixing of item with quality and item without quality is not supported", vs[i].c_str()); - throw EParseException(prim, err.c_str()); - } - } - - TGiveInfo gi; - gi.Item.initWithText(toString("i%u", i+1), STRING_MANAGER::item, md, prim, args[0]); - gi.Qt.initWithText(toString("qt%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); - - if (_QualSpec) - gi.Ql.initWithText(toString("qual%u", i+1), STRING_MANAGER::integer, md, prim, args[2]); - - _Items.push_back(gi); - } - - _Npc.init("npc", STRING_MANAGER::bot, md, prim, "npc_name"); - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "give_item : "; - - for (uint i=0; i<_Items.size(); ++i) - { - ret += _Items[i].Item+" "+_Items[i].Qt; - if (_QualSpec) - ret += " "+_Items[i].Ql; - if (i < _Items.size()-1) - ret += "; "; - }; - ret += " : "+_Npc; - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentGive, "give_item"); - -class CContentGiveMoney : public CContentObjective -{ - TCompilerVarName _Amount; - TCompilerVarName _Npc; - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - predef.resize(1); - predef[0].resize(2); - - predef[0][0] = _Amount; - predef[0][1] = _Npc; - - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - _Amount.init("amount", STRING_MANAGER::integer, md, prim, "amount"); - _Npc.init("npc", STRING_MANAGER::bot, md, prim, "npc_name"); - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "give_money : "+_Amount+" : "+_Npc; - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentGiveMoney, "give_money"); - -class CContentVisit : public CContentObjective -{ - TCompilerVarName _Place; - TCompilerVarName _PlaceVar; - vector _Items; - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - predef.resize(1); - predef[0].resize(1+_Items.size()); - predef[0][0] = _Place; - - for (uint i=0; i<_Items.size(); ++i) - predef[0][i+1] = _Items[i]; - - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - - _Place.init("place", STRING_MANAGER::place, md, prim, "place"); - _Items = TCompilerVarName::getPropertyArrayWithText("i", STRING_MANAGER::item, md, prim, "items_worn" ); - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "visit : "+_Place; - - if (!_Items.empty()) - { - ret += " : "; - for (uint i=0; i<_Items.size(); ++i) - { - ret += _Items[i]; - if (i < _Items.size()-1) - ret += "; "; - } - } - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentVisit, "visit"); - -class CContentEscort : public CContentObjective -{ - string _GroupName; - bool _SaveAll; - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init (CMissionData &md, IPrimitive *prim) - { - _GroupName = md.getProperty(prim, "group_to_escort", true, false); - string s = md.getProperty(prim, "save_all", true, false); - _SaveAll = (NLMISC::toLower(s) == "true"); - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "escort : "+_GroupName; - - if (_SaveAll) - ret += " : save_all"; - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentEscort, "escort"); - -struct TSkillInfo -{ - TCompilerVarName _SkillName; - TCompilerVarName _Level; -}; - -class CContentSkill: public CContentObjective -{ - vector _Skills; - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = (uint32)_Skills.size(); - predef.resize(numEntry); - - for (uint i=0; i vs; - vs = md.getPropertyArray(prim, "skill_name/level", true, false); - - for (uint i=0; i args; - explode(vs[i], string(" "), args, true); - - if (args.size() != 2) - { - string err = toString("Invalid skill in '%s', need ", vs[i].c_str()); - throw EParseException(prim, err.c_str()); - } - - TSkillInfo si; - si._SkillName.initWithText(toString("s%u", i+1), STRING_MANAGER::skill, md, prim, args[0]); - si._Level.initWithText(toString("level%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); - _Skills.push_back(si); - } - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "skill : "; - - for (uint i=0; i<_Skills.size(); ++i) - { - ret += _Skills[i]._SkillName+" "+_Skills[i]._Level; - if (i < _Skills.size()-1) - ret += "; "; - } - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentSkill, "skill"); - -class CContentMission: public CContentObjective -{ - vector _Missions; - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } - -public: - CContentMission(): _Prim(0) {} - - void init(CMissionData &md, IPrimitive *prim) - { - _Missions = md.getPropertyArray(prim, "mission_names", true, false); - _Prim = prim; - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "mission : "; - - for (uint i=0; i<_Missions.size(); ++i) - { - ret += _Missions[i]; - if (i < _Missions.size()-1) - ret += "; "; - - // We check to see if we specified a number after the mission name. If so, we check if it's a guild mission - std::size_t pos = _Missions[i].find_first_of(" \t"); - if (pos != std::string::npos && !md.isGuildMission()) - { - string err = toString("primitive(%s): CContentMission: Number of members needed to complete the mission specified but the mission is not a guild mission.", _Prim->getName().c_str()); - throw EParseException(_Prim, err.c_str()); - } - } - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } - - IPrimitive *_Prim; -}; -REGISTER_STEP_CONTENT(CContentMission, "do_mission"); - -class CContentWaitAIMsg : public CContentObjective -{ - vector _MsgContent; - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } - -public: - void init(CMissionData &md, IPrimitive *prim) - { - _MsgContent = md.getPropertyArray(prim, "msg_content", true, false); - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "wait_msg : "; - - for (uint i=0; i<_MsgContent.size(); ++i) - { - ret += _MsgContent[i]; - if (i < _MsgContent.size()-1) - ret += " "; - } - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentWaitAIMsg, "wait_ai_msg"); - -// *********** -// queue_start -// *********** - -class CContentQueueStart : public CContentObjective -{ - string _StepName; - string _QueueName; - string _Timer; - vector _AIInstances; - vector _GroupsToSpawn; - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } - -public: - void init(CMissionData &md, IPrimitive *prim) - { - _StepName = md.getProperty(prim, "step_name", true, true); - _QueueName = md.getProperty(prim, "queue_name", true, false); - if (_StepName.empty()) - _StepName = "queue_start_" + _QueueName; - - _Timer = md.getProperty(prim, "timer", true, false); - _GroupsToSpawn = md.getPropertyArray(prim, "groups_to_spawn", true, true); - if (_GroupsToSpawn.empty()) - _AIInstances = md.getPropertyArray(prim, "ai_instances", true, true); - else - _AIInstances = md.getPropertyArray(prim, "ai_instances", true, false); - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - uint32 i; - string ret; - ret = CContentObjective::genCode(md); - - ret += "jump_point : " + _StepName + NL; - ret += "queue_start : " + _QueueName + " : " + _Timer + NL; - ret += NL; - - if (!_GroupsToSpawn.empty()) - { - // crash : ai_instance_1 : ai_instance_2 : ... - ret += "crash"; - nlassert(_AIInstances.size() > 0); - for (i = 0; i < _AIInstances.size(); ++i) - ret += " : " + _AIInstances[i]; - ret += NL; - - for (i = 0; i < _GroupsToSpawn.size(); ++i) - ret += "handle_release : " + _GroupsToSpawn[i] + NL; - - ret += "/crash" + NL; - ret += NL; - - ret += "failure" + NL; - for (i = 0; i < _GroupsToSpawn.size(); ++i) - ret += "handle_release : " + _GroupsToSpawn[i] + NL; - ret += "/failure" + NL; - ret += NL; - } - - ret += "player_reconnect" + NL; - for (i = 0; i < _GroupsToSpawn.size(); ++i) - ret += "handle_release : " + _GroupsToSpawn[i] + NL; - ret += "jump : " + _StepName + NL; - ret += "/player_reconnect" + NL; - ret += NL; - - for (i = 0; i < _GroupsToSpawn.size(); ++i) - ret += "handle_create : " + _GroupsToSpawn[i] + NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentQueueStart, "queue_start"); - -// ********* -// queue_end -// ********* - -class CActionQueueEnd : public IStepContent -{ - string _ActionName; - string _QueueName; - // Find the following info in the queue_start node - vector _AIInstances; - vector _GroupsToSpawn; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } -public: - void init(CMissionData &md, IPrimitive *prim) - { - IStepContent::init(md, prim); - _ActionName = md.getProperty(prim, "action_name", true, true); - _QueueName = md.getProperty(prim, "queue_name", true, false); - if (_ActionName.empty()) - _ActionName = "queue_end_" + _QueueName; - - // Search in the queue_start node - IPrimitive *primParent = prim; - while (primParent->getParent() != NULL) - { - string className; - if (primParent->getPropertyByName("class", className)) - if (className == "mission_tree") - break; - primParent = primParent->getParent(); - } - TPrimitiveClassPredicate condClass("queue_start"); - CPrimitiveSet s; - TPrimitiveSet ps; - s.buildSet(primParent, condClass, ps); - - TPrimitivePropertyPredicate condProp("queue_name", _QueueName); - CPrimitiveSetFilter filter; - TPrimitiveSet psFinal; - filter.filterSet(ps, condProp, psFinal); - - if (psFinal.size() == 0) - { - string err = toString("Can't find queue_start for queue_end : '%s'", _QueueName.c_str()); - throw EParseException(prim, err.c_str()); - } - if (psFinal.size() > 1) - { - string err = toString("More than 1 queue_start for queue_end : '%s'", _QueueName.c_str()); - throw EParseException(prim, err.c_str()); - } - - _GroupsToSpawn = md.getPropertyArray(psFinal[0], "groups_to_spawn", true, true); - if (_GroupsToSpawn.empty()) - _AIInstances = md.getPropertyArray(psFinal[0], "ai_instances", true, true); - else - _AIInstances = md.getPropertyArray(psFinal[0], "ai_instances", true, false); - - } - - string genCode(CMissionData &md) - { - uint32 i; - string ret; - - if (_GroupsToSpawn.size() > 0) - { - for (i = 0; i < _GroupsToSpawn.size(); ++i) - ret += "handle_release : " + _GroupsToSpawn[i] + NL; - ret += NL; - } - - if (_AIInstances.size() > 0) - { - ret += "crash"; - for (i = 0; i < _AIInstances.size(); ++i) - ret += " : " + _AIInstances[i]; - ret += NL; - ret += "/crash" + NL; - ret += NL; - } - - ret += "failure" + NL; - ret += "/failure" + NL; - ret += NL; - - ret += "player_reconnect" + NL; - ret += "/player_reconnect" + NL; - ret += NL; - ret += "queue_end : " +_QueueName + NL; - - return ret; - } - -}; -REGISTER_STEP_CONTENT(CActionQueueEnd, "queue_end"); - - -class CContentRingScenario: public CContentObjective -{ - string _ScenarioTag; - - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - } - -public: - void init(CMissionData &md, IPrimitive *prim) - { - _ScenarioTag = md.getProperty(prim, "scenario_tag", true, false); - - CContentObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CContentObjective::genCode(md); - - ret += "ring_scenario : "; - ret += _ScenarioTag; - // Add the 'nb_guild_members_needed' parameter if needed - //ret += CContentObjective::genNbGuildMembersNeededOption(md); - ret += NL; - - return ret; - } -}; -REGISTER_STEP_CONTENT(CContentRingScenario, "ring_scenario"); - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "mission_compiler.h" +#include "step.h" + +#include "nel/ligo/primitive_utils.h" + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; + + +// ************ +// IStepContent +// ************ + +IStepContent *IStepContent::createStepContent(CMissionData &md, NLLIGO::IPrimitive *prim) +{ + string className; + prim->getPropertyByName("class", className); + + IStepContentFactory *factory = CFactoryIndirect::instance().getFactory(className); + if (factory == NULL) + { + string err = toString("Can't find factory for class '%s'", className.c_str()); + throw EParseException(prim, err.c_str()); + } + + IStepContent *content = factory->createStepContent(md, prim); + return content; +} + +void IStepContent::init(CMissionData &md, NLLIGO::IPrimitive *prim) +{ + prim->getPropertyByName("name", _ContentName); + + // parse the post actions + for (uint i=0; igetNumChildren(); ++i) + { + IPrimitive *child; + prim->getChild(child, i); + if (child) + { + // ok, we got one + IStepContent *sc = IStepContent::createStepContent(md, child); + if (sc) + _PostActions.push_back(sc); + } + } +} + +std::string IStepContent::genStepContentCode(CMissionData &md) +{ + string ret; + // call the derived class code generation + ret += genCode(md); + + // generate the code for the post action + for (uint i=0; i<_PostActions.size(); ++i) + { + ret += _PostActions[i]->genCode(md); + } + + return ret; +} + +std::string IStepContent::genStepContentPhrase() +{ + string ret; + + // call ther derived class phrase generation + ret += genPhrase(); + + // generate the phrase for the post action + for (uint i=0; i<_PostActions.size(); ++i) + { + ret += _PostActions[i]->genPhrase(); + } + + return ret; +} + +void IStepContent::fillJump(CMissionData &md, std::set &jumpPoints) +{ + for (uint i=0; i<_PostActions.size(); ++i) + { + _PostActions[i]->fillJump(md, jumpPoints); + } +} + + +////////////////////// Actions and objectives ///////////////////// + +class CActionJumpTo : public IStepContent +{ + string _JumpTo; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _JumpTo = md.getProperty(prim, "target", true, false); + } + + string genCode(CMissionData &md) + { + if (!_JumpTo.empty()) + return "jump : "+_JumpTo+NL; + else + return string(); + } + + void fillJump(CMissionData &md, std::set &jumpPoints) + { + IStepContent::fillJump(md, jumpPoints); + jumpPoints.insert(TJumpInfo(_JumpTo, "", false)); + } + +}; +REGISTER_STEP_CONTENT(CActionJumpTo, "jump_to"); + + +// --------------------------------------------------------------------------- +class CActionRecvMoney : public IStepContent +{ + string _Amount; + bool _Guild; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _Amount = md.getProperty(prim, "amount", true, false); + + _Guild = md.getProperty(prim, "guild", false, true) == "true"; + // Check: if _Guild is true then check if we are in a guild mission + if (_Guild && !md.isGuildMission()) + { + string err = toString("primitive(%s): 'guild' option true 1 for non guild mission.", prim->getName().c_str()); + throw EParseException(prim, err.c_str()); + } + } + + string genCode(CMissionData &md) + { + if (!_Amount.empty()) + { + string ret; + ret = "recv_money : "+_Amount; + if (_Guild) + ret += ": guild"; + ret += NL; + return ret; + } + else + return string(); + } + +}; +REGISTER_STEP_CONTENT(CActionRecvMoney, "recv_money"); + + +// --------------------------------------------------------------------------- +class CActionRecvChargePoint : public IStepContent +{ + string _Amount; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _Amount = md.getProperty(prim, "charge_points", true, false); + } + + string genCode(CMissionData &md) + { + if (!_Amount.empty()) + { + string ret; + ret = "recv_charge_point : "+_Amount; + ret += NL; + return ret; + } + else + return string(); + } + +}; +REGISTER_STEP_CONTENT(CActionRecvChargePoint, "recv_charge_point"); + + +// --------------------------------------------------------------------------- +class CActionGiveOutpostControl : public IStepContent +{ + string _OutpostName; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _OutpostName = md.getProperty(prim, "outpost_name", true, false); + } + + string genCode(CMissionData &md) + { + if (!_OutpostName.empty()) + { + string ret; + ret = "give_control : "+_OutpostName; + ret += NL; + return ret; + } + else + return string(); + } + +}; +REGISTER_STEP_CONTENT(CActionGiveOutpostControl, "give_control"); + + +// --------------------------------------------------------------------------- +class CActionSpawnMission : public IStepContent +{ +protected: + string _MissionName; + string _GiverName; + bool _Guild; +private: + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _MissionName = md.getProperty(prim, "mission_name", true, false); + _GiverName = md.getProperty(prim, "giver_name", true, false); + if (_GiverName.empty()) + { + throw EParseException(prim, "giver_name is empty !"); + } + + _Guild = md.getProperty(prim, "guild", false, true) == "true"; + // Check: if _Guild is true then check if we are in a guild mission + if (_Guild && !md.isGuildMission()) + { + string err = toString("primitive(%s): 'guild' option true 1 for non guild mission.", prim->getName().c_str()); + throw EParseException(prim, err.c_str()); + } + } + + string genCode(CMissionData &md) + { + string ret = ""; + if (!_MissionName.empty()) + { + ret = "spawn_mission : " + _MissionName + " : " + _GiverName; + if (_Guild) + ret += " : guild"; + ret += NL; + } + return ret; + } +}; +REGISTER_STEP_CONTENT(CActionSpawnMission, "spawn_mission"); + + +// --------------------------------------------------------------------------- +class CActionChainMission : public CActionSpawnMission +{ +public: + + string genCode(CMissionData &md) + { + + if (!_MissionName.empty()) + { + + + return "chain_mission : " + _MissionName + " : " + _GiverName + NL; + } + else + return string(); + } + +}; +REGISTER_STEP_CONTENT(CActionChainMission, "chain_mission"); + + +// --------------------------------------------------------------------------- +class CActionEncycloUnlock : public IStepContent +{ + string _AlbumThema; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _AlbumThema = md.getProperty(prim, "album_thema", true, false); + } + + string genCode(CMissionData &md) + { + if (!_AlbumThema.empty()) + return "encyclo_unlock : " + _AlbumThema + NL; + else + return string(); + } + +}; +REGISTER_STEP_CONTENT(CActionEncycloUnlock, "encyclo_unlock"); + + +// --------------------------------------------------------------------------- +class CActionHandleCreate : public IStepContent +{ +protected: + string _Group; + string _DespawnTimer; +private: + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _Group = md.getProperty(prim, "group", true, false); + _DespawnTimer = md.getProperty(prim, "despawn_timer", true, false); + } + + string genCode(CMissionData &md) + { + if (!_Group.empty()) + { + if (!_DespawnTimer.empty()) + return "handle_create : " + _Group + " : " + _DespawnTimer + NL; + else + return "handle_create : " + _Group + NL; + } + else + return string(); + } + +}; +REGISTER_STEP_CONTENT(CActionHandleCreate, "handle_create"); + + +// --------------------------------------------------------------------------- +class CActionHandleRelease : public IStepContent +{ +protected: + string _Group; + +private: + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _Group = md.getProperty(prim, "group", true, false); + } + + string genCode(CMissionData &md) + { + if (!_Group.empty()) + return "handle_release : " + _Group + NL; + else + return string(); + } + +}; +REGISTER_STEP_CONTENT(CActionHandleRelease, "handle_release"); + + +// --------------------------------------------------------------------------- +class CActionSetEventFaction : public IStepContent +{ + string _EventFaction; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _EventFaction = md.getProperty(prim, "event_faction", true, false); + } + + string genCode(CMissionData &md) + { + if (!_EventFaction.empty()) + return "set_event_faction : " + _EventFaction + NL; + else + return string(); + } + +}; +REGISTER_STEP_CONTENT(CActionSetEventFaction, "set_event_faction"); + + +// --------------------------------------------------------------------------- +class CActionSetRespawnPoints : public IStepContent +{ + string _Continent; + vector _RespawnPoints; + bool _HideOthers; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _Continent = md.getProperty(prim, "continent", true, false); + + vector vs; + vs = md.getPropertyArray(prim, "respawn_points", true, false); + + for (uint i=0; igetName().c_str()); + throw EParseException(prim, err.c_str()); + } + } + + string genCode(CMissionData &md) + { + if (!_Faction.empty() && !_Fame.empty()) + { + string ret; + ret = "recv_fame : "+_Faction+" "+_Fame; + if (_Guild) + ret += ": guild"; + ret += NL; + return ret; + } + else + return string(); + } +}; +REGISTER_STEP_CONTENT(CActionRecvFame, "recv_fame"); + +// --------------------------------------------------------------------------- +struct TItemDesc +{ + string ItemName; + string ItemQuant; + string ItemQual; +}; + +class CActionRecvItem : public IStepContent +{ + string _BotGiver; + vector _Items; + bool _QualSpec; + bool _Group; + bool _Guild; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + _BotGiver =md.getProperty(prim, "npc_name", true, false); + vector vs; + vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); + for (uint i=0; i args; + if (!vs[i].empty()) + { + explode(vs[i], string(" "), args, false); + if (args.size() != 3 && args.size() != 2) + { + string err = toString("can't find 2 or 3 part ( []) in item line '%s', found %u instead", vs[i].c_str(), args.size()); + throw EParseException(prim, err.c_str()); + } + + if (i == 0) + { + _QualSpec = (args.size() == 3); + } + else if (args.size() == 3 && !_QualSpec) + { + string err = toString("can't mix item with quality and item without quality in item line '%s'", vs[i].c_str()); + throw EParseException(prim, err.c_str()); + } + + TItemDesc item; + item.ItemName = args[0]; + item.ItemQuant = args[1]; + if (_QualSpec) + item.ItemQual = args[2]; + + _Items.push_back(item); + } + } + + string s; + s = md.getProperty(prim, "group", true, false); + _Group = (NLMISC::toLower(s) == "true"); + + _Guild = md.getProperty(prim, "guild", false, true) == "true"; + // Check: if _Guild is true then check if we are in a guild mission + if (_Guild && !md.isGuildMission()) + { + string err = toString("primitive(%s): 'guild' option true 1 for non guild mission.", prim->getName().c_str()); + throw EParseException(prim, err.c_str()); + } + + IStepContent::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + for (uint i=0; i<_Items.size(); ++i) + { + TItemDesc &item = _Items[i]; + + ret += "recv_item : "+item.ItemName+" "+item.ItemQuant; + if (_QualSpec) + ret +=" "+item.ItemQual; + if (!_BotGiver.empty()) + ret += " : "+_BotGiver; + if (_Group) + ret += " : group"; + if (_Guild) + ret += ": guild"; + ret += NL; + } + + return ret; + + } +}; +REGISTER_STEP_CONTENT(CActionRecvItem, "recv_item"); + +// --------------------------------------------------------------------------- +class CActionRecvNamedItem : public IStepContent +{ + vector _Items; + bool _Group; + bool _Guild; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + vector vs; + vs = md.getPropertyArray(prim, "item/quantity", true, false); + for (uint i=0; i args; + if (!vs[i].empty()) + { + explode(vs[i], string(" "), args, false); + if (args.size() != 1 && args.size() != 2) + { + string err = toString("can't find 1 or 2 part ( []) in item line '%s', found %u instead", vs[i].c_str(), args.size()); + throw EParseException(prim, err.c_str()); + } + + TItemDesc item; + item.ItemName = args[0]; + item.ItemQuant = "1"; + if(args.size()>=2 && atoi(args[1].c_str())>0) + item.ItemQuant = args[1]; + + _Items.push_back(item); + } + } + + string s; + s = md.getProperty(prim, "group", true, false); + _Group = (NLMISC::toLower(s) == "true"); + + _Guild = md.getProperty(prim, "guild", false, true) == "true"; + // Check: if _Guild is true then check if we are in a guild mission + if (_Guild && !md.isGuildMission()) + { + string err = toString("primitive(%s): 'guild' option true 1 for non guild mission.", prim->getName().c_str()); + throw EParseException(prim, err.c_str()); + } + + IStepContent::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + for (uint i=0; i<_Items.size(); ++i) + { + TItemDesc &item = _Items[i]; + + ret += "recv_named_item : "+item.ItemName+" "+item.ItemQuant; + if (_Group) + ret += " : group"; + if (_Guild) + ret += ": guild"; + ret += NL; + } + + return ret; + + } +}; +REGISTER_STEP_CONTENT(CActionRecvNamedItem, "recv_named_item"); + +// --------------------------------------------------------------------------- +class CActionDestroyItem : public IStepContent +{ + struct CItemDesc + { + TItemDesc Desc; + bool QuantSpec; + bool QualSpec; + }; + + string _BotDestroyer; + vector _Items; + bool _Guild; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + // get the bot who destroys the item + _BotDestroyer =md.getProperty(prim, "npc_name", true, false); + + // read list of items to destroy + vector vs; + vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); + for (uint i=0; i args; + if (!vs[i].empty()) + { + // parse + explode(vs[i], string(" "), args, false); + if (args.size()<1 || args.size()>3) + { + string err = toString("can't find 1, 2 or 3 part ( [] []) in item line '%s', found %u instead", vs[i].c_str(), args.size()); + throw EParseException(prim, err.c_str()); + } + + // add the item in desc + CItemDesc item; + item.Desc.ItemName = args[0]; + if(args.size()>=2) + { + item.QuantSpec= true; + item.Desc.ItemQuant = args[1]; + } + if(args.size()>=3) + { + item.QualSpec= true; + item.Desc.ItemQual = args[2]; + } + + _Items.push_back(item); + } + } + + _Guild = md.getProperty(prim, "guild", false, true) == "true"; + // Check: if _Guild is true then check if we are in a guild mission + if (_Guild && !md.isGuildMission()) + { + string err = toString("primitive(%s): 'guild' option true 1 for non guild mission.", prim->getName().c_str()); + throw EParseException(prim, err.c_str()); + } + + IStepContent::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + for (uint i=0; i<_Items.size(); ++i) + { + CItemDesc &item = _Items[i]; + + ret += "destroy_item : "+item.Desc.ItemName; + if (item.QuantSpec) + ret +=" "+item.Desc.ItemQuant; + if (item.QualSpec) + ret +=" "+item.Desc.ItemQual; + if (!_BotDestroyer.empty()) + ret += " : "+_BotDestroyer; + if (_Guild) + ret += ": guild"; + ret += NL; + } + + return ret; + + } +}; +REGISTER_STEP_CONTENT(CActionDestroyItem, "destroy_item"); + +// --------------------------------------------------------------------------- +class CActionRecvXp : public IStepContent +{ + string _Skill; + sint32 _Value; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _Skill = md.getProperty(prim, "skill", true, false); + _Value = atoi(md.getProperty(prim, "value", true, false).c_str()); + if(_Skill.empty() || tolower(_Skill[0])!='s' || _Value<=0) + { + string err = toString("Bad skill name or value: '%s' '%d' ", _Skill.c_str(), _Value); + throw EParseException(prim, err.c_str()); + } + } + + string genCode(CMissionData &md) + { + if (!_Skill.empty()) + return toString("recv_xp : %s %d", _Skill.c_str(), _Value) + NL; + else + return string(); + } +}; +REGISTER_STEP_CONTENT(CActionRecvXp, "recv_xp"); + +// --------------------------------------------------------------------------- +class CActionLearnAction : public IStepContent +{ + string _BotGiver; + vector _Actions; + bool _Group; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + _BotGiver = md.getProperty(prim, "npc_name", true, false); + vector vs; + vs = md.getPropertyArray(prim, "actions", true, false); + + for (uint i=0; i _Bricks; + bool _Group; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + _BotGiver = md.getProperty(prim, "npc_name", true, false); + vector vs; + vs = md.getPropertyArray(prim, "bricks", true, false); + + for (uint i=0; i vs; + vs = md.getPropertyArray(prim, "phrase", false, false); + _Phrase.initPhrase(md, prim, vs); + + _ChatMode = md.getProperty(prim, "chat_type", true, false); + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "bot_chat : "+_ChatMode+" : "+_BotName+" : "+_Phrase.genScript(md)+NL; + return ret; + } + + string genPhrase() + { + return _Phrase.genPhrase(); + } +}; +REGISTER_STEP_CONTENT(CActionBotChat, "bot_chat"); + +// --------------------------------------------------------------------------- +class CActionBotEmote : public IStepContent +{ + string _BotName; + string _Emote; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + _BotName = md.getProperty(prim, "npc_name", true, false); + _Emote = md.getProperty(prim, "emote", true, false); + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "bot_emot : "+_BotName+" "+_Emote+NL; + return ret; + } +}; +REGISTER_STEP_CONTENT(CActionBotEmote, "bot_emote"); + +// --------------------------------------------------------------------------- +class CActionAIEvent : public IStepContent +{ + string _GroupName; + string _EventNumber; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + _GroupName = md.getProperty(prim, "group_name", true, false); + _EventNumber = md.getProperty(prim, "event_number", true, false); + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "ai_event : "+_GroupName+"; "+_EventNumber+NL; + return ret; + } +}; +REGISTER_STEP_CONTENT(CActionAIEvent, "ai_event"); + +// --------------------------------------------------------------------------- +class CActionSetTeleport : public CActionBotChat +{ + string _WorldPosition; + bool _Once; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + CActionBotChat::init(md, prim); + + _WorldPosition = md.getProperty(prim, "world_position", true, false); + string s; + prim->getPropertyByName("once", s); + _Once = (NLMISC::toLower(s) == "true"); + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "set_teleport : "+_BotName+" : "+_WorldPosition+" : "; + + if (_Once) + ret += "once : "; + ret += _Phrase.genScript(md) + NL; + return ret; + } +}; +REGISTER_STEP_CONTENT(CActionSetTeleport, "set_teleport"); + +// --------------------------------------------------------------------------- +class CActionTeleport : public IStepContent +{ + string _WorldPosition; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + _WorldPosition = md.getProperty(prim, "world_position", true, false); + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "teleport : "+_WorldPosition+NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CActionTeleport, "teleport"); + +// --------------------------------------------------------------------------- +class CActionSetCult : public IStepContent +{ + string _Cult; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + _Cult = md.getProperty(prim, "cult", true, false); + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "set_cult : " + _Cult + NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CActionSetCult, "set_cult"); + +// --------------------------------------------------------------------------- +class CActionSetCiv : public IStepContent +{ + string _Civ; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + _Civ = md.getProperty(prim, "civ", true, false); + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "set_civ : " + _Civ + NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CActionSetCiv, "set_civ"); + +// --------------------------------------------------------------------------- +class CActionSetGuildCult : public IStepContent +{ + string _Cult; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + _Cult = md.getProperty(prim, "cult", true, false); + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "set_guild_cult : " + _Cult + NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CActionSetGuildCult, "set_guild_cult"); + +// --------------------------------------------------------------------------- +class CActionSetGuildCiv : public IStepContent +{ + string _Civ; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + _Civ = md.getProperty(prim, "civ", true, false); + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "set_guild_civ : " + _Civ + NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CActionSetGuildCiv, "set_guild_civ"); + +// --------------------------------------------------------------------------- +class CActionAddCompass : public IStepContent +{ + string _NpcName; + string _PlaceName; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + _NpcName = md.getProperty(prim, "npc_to_add", true, false); + _PlaceName = md.getProperty(prim, "place_to_add", true, false); + } + + string genCode(CMissionData &md) + { + string ret; + + if (!_NpcName.empty()) + ret = "add_compass_npc : "+_NpcName+NL; + if (!_PlaceName.empty()) + ret += "add_compass_place : "+_PlaceName+NL; + return ret; + } +}; +REGISTER_STEP_CONTENT(CActionAddCompass, "add_compass"); + +// --------------------------------------------------------------------------- +class CActionRemoveCompass : public IStepContent +{ + string _NpcName; + string _PlaceName; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + _NpcName = md.getProperty(prim, "npc_to_remove", true, false); + _PlaceName = md.getProperty(prim, "place_to_remove", true, false); + } + + string genCode(CMissionData &md) + { + string ret; + + if (!_NpcName.empty()) + ret = "remove_compass_npc : "+_NpcName+NL; + if (!_PlaceName.empty()) + ret += "remove_compass_place : "+_PlaceName+NL; + return ret; + } +}; +REGISTER_STEP_CONTENT(CActionRemoveCompass, "remove_compass"); + +// --------------------------------------------------------------------------- +class CActionFail : public IStepContent +{ + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + } + + string genCode(CMissionData &md) + { + return string("fail")+NL; + } +}; +REGISTER_STEP_CONTENT(CActionFail, "fail"); + +// --------------------------------------------------------------------------- +class CActionFailIfSDB : public IStepContent +{ + + string _Condition; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _Condition = md.getProperty(prim, "condition", true, false); + } + + string genCode(CMissionData &md) + { + return string("fail_if_sdb : ")+_Condition+NL; + } +}; +REGISTER_STEP_CONTENT(CActionFailIfSDB, "fail_if_sdb"); + +// --------------------------------------------------------------------------- +class CActionFailMissionCat : public IStepContent +{ + + string _MissionCategory; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _MissionCategory = md.getProperty(prim, "category", true, false); + } + + string genCode(CMissionData &md) + { + return string("fail_mission_cat : ")+_MissionCategory+NL; + } +}; +REGISTER_STEP_CONTENT(CActionFailMissionCat, "fail_mission_cat"); + +// --------------------------------------------------------------------------- +class CActionSystemMsg : public IStepContent +{ + CPhrase _Message; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + vector vs = md.getPropertyArray(prim, "msg_to_display", false, false); + + _Message.initPhrase(md, prim, vs); + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "system_msg : "+_Message.genScript(md)+NL; + return ret; + } + + string genPhrase() + { + return _Message.genPhrase(); + } +}; +REGISTER_STEP_CONTENT(CActionSystemMsg, "system_msg"); + +// --------------------------------------------------------------------------- +class CActionPopupMsg : public IStepContent +{ + CPhrase _Title; + CPhrase _Message; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + vector vst = md.getPropertyArray(prim, "title_to_display", false, false); + vector vsm = md.getPropertyArray(prim, "msg_to_display", false, false); + + _Title.initPhrase(md, prim, vst); + _Message.initPhrase(md, prim, vsm); + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "popup_msg : " + _Title.genScript(md) + " : " + _Message.genScript(md) + NL; + return ret; + } + + string genPhrase() + { + return _Title.genPhrase() + _Message.genPhrase(); + } +}; +REGISTER_STEP_CONTENT(CActionPopupMsg, "popup_msg"); + +// --------------------------------------------------------------------------- +class CActionDeclareWar : public IStepContent +{ + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + } + + string genCode(CMissionData &md) + { + return string("declare_war")+NL; + } +}; +REGISTER_STEP_CONTENT(CActionDeclareWar, "declare_war"); + +// --------------------------------------------------------------------------- +class CActionSetConstrains : public IStepContent +{ + string _Timer; + string _TimePeriod; + string _InsidePlace; + string _InsidePlaceDelay; + string _OutsidePlace; + string _OutsidePlaceDelay; + vector _Wears; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + _Timer = md.getProperty(prim, "timer", true, false); + _TimePeriod = md.getProperty(prim, "time_period", true, false); + _InsidePlace = md.getProperty(prim, "inside_place", true, false); + _InsidePlaceDelay = md.getProperty(prim, "inside_place_delay", true, false); + _OutsidePlace = md.getProperty(prim, "outside_place", true, false); + _OutsidePlaceDelay = md.getProperty(prim, "outside_place_delay", true, false); + _Wears = md.getPropertyArray(prim, "wear", true, false); + } + + string genCode(CMissionData &md) + { + string ret; + + if (!_Timer.empty()) + ret += "timer : "+_Timer+NL; + if (!_TimePeriod.empty()) + { + if ( _TimePeriod == "winter" + || _TimePeriod == "spring" + || _TimePeriod == "summer" + || _TimePeriod == "autumn" + || _TimePeriod == "none") + { + ret += "season : "+_TimePeriod+NL; + } + else + ret += "day_period : "+_TimePeriod+NL; + } + if (!_InsidePlace.empty()) + { + if (_InsidePlace != "none") + { + ret += "inside : "+_InsidePlace; + if (!_InsidePlaceDelay.empty()) + ret += " : "+_InsidePlaceDelay; + } + else + ret += "inside"; + ret += NL; + } + if (!_OutsidePlace.empty()) + { + if (_OutsidePlace != "none") + { + ret += "outside : "+_OutsidePlace; + if (!_OutsidePlaceDelay.empty()) + ret += " : "+_OutsidePlaceDelay; + } + else + ret += "outside"; + ret += NL; + } + if (!_Wears.empty()) + nlwarning("wear constraint not implemented yet"); + return ret; + } +}; +REGISTER_STEP_CONTENT(CActionSetConstrains, "set_constrains"); + +// --------------------------------------------------------------------------- +class CActionSetDesc : public IStepContent +{ + CPhrase _Description; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + + std::vector vs = md.getPropertyArray(prim, "mission_description", false, false); + + _Description.initPhrase(md, prim, vs); + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "set_desc : "+_Description.genScript(md)+NL; + return ret; + } + + string genPhrase() + { + return _Description.genPhrase(); + } + +}; +REGISTER_STEP_CONTENT(CActionSetDesc, "set_desc"); + +// ***************** +// CContentObjective +// ***************** +// base class for step content objectives +// --------------------------------------------------------------------------- +void CContentObjective::init(CMissionData &md, IPrimitive *prim) +{ + IStepContent::init(md, prim); + + _HideObj = md.getProperty(prim, "hide_obj", true, false) == "true"; + _OverloadObj = md.getPropertyArray(prim, "overload_objective", false, false); + _RoleplayObj = md.getPropertyArray(prim, "roleplay_objective", false, false); + uint32 numEntry; + CPhrase::TPredefParams params; + // ask derived class for predefined params + getPredefParam(numEntry, params); + // init the overload phrase + _OverloadPhrase.initPhrase(md, prim, _OverloadObj, numEntry, params); + // init the roleplay phrase + _RoleplayPhrase.initPhrase(md, prim, _RoleplayObj, numEntry, params); + + // check for the 'nb_guild_members_needed' option and see if it's correct for this mission + /*string nbGuildMembersNeeded = md.getProperty(prim, "nb_guild_members_needed", false, true); + if (nbGuildMembersNeeded.empty()) + nbGuildMembersNeeded = "1"; + if (!fromString(nbGuildMembersNeeded.c_str(), _NbGuildMembersNeeded)) + _NbGuildMembersNeeded = 1; + + // Check: + if (!md.isGuildMission() && _NbGuildMembersNeeded != 1) + { + string err = toString("primitive(%s): nb_guild_members_needed != 1 for non guild mission.", prim->getName().c_str()); + throw EParseException(prim, err.c_str()); + }*/ +} + +// --------------------------------------------------------------------------- +string CContentObjective::genCode(CMissionData &md) +{ + string ret; + if (_HideObj) + ret = "hide_obj"+NL; + if (!_OverloadObj.empty()) + { + ret += "set_obj : " + _OverloadPhrase.genScript(md)+NL; + } + if (!_RoleplayObj.empty()) + { + ret += "set_obj_rp : " + _RoleplayPhrase.genScript(md)+NL; + } + return ret; +} + +// --------------------------------------------------------------------------- +/*std::string CContentObjective::genNbGuildMembersNeededOption(CMissionData &md) +{ + string ret = ""; + // If we are in a guild mission we add the 'nb_guild_members_needed' option to the script + if (md.isGuildMission()) + { + ret = ": nb_guild_members_needed "; + ret += toString(_NbGuildMembersNeeded); + } + + return ret; +}*/ + +// --------------------------------------------------------------------------- +string CContentObjective::genPhrase() +{ + if (!_OverloadObj.empty()) + return _OverloadPhrase.genPhrase(); + else + return _RoleplayPhrase.genPhrase(); +} + +// --------------------------------------------------------------------------- +// --------------------------------------------------------------------------- + +struct TKillFaunaInfo +{ + TCompilerVarName SheetName; + TCompilerVarName Quantity; +}; + +struct TKillRaceInfo +{ + TCompilerVarName RaceName; + TCompilerVarName Quantity; +}; + + +class CContentKill : public CContentObjective +{ + vector _KillFaunas; + vector _KillRaces; + TCompilerVarName _KillGroup; + vector _KillNpcs; + TCompilerVarName _KillNpcByNames; + TCompilerVarName _KillNpcByNamesQuantity; + TCompilerVarName _KillFactionName; + TCompilerVarName _KillFactionQuantity; + vector _PredefVarName; + TCompilerVarName _Place; + + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + if (!_KillFaunas.empty()) + { + numEntry = (uint32)_KillFaunas.size(); + predef.resize(numEntry); + for (uint i=0; i<_KillFaunas.size(); ++i) + { + predef[i].resize(2*(i+1)); + for (uint j=0; j vs; + vs = md.getPropertyArray(prim, "fauna/quantity", false, false); + for (uint i=0; i args; + explode(vs[i], string(" "), args, true); + if (args.size() != 2) + { + string err = toString("Syntax error in kill fauna : '%s', need ", vs[i].c_str()); + throw EParseException (prim, err.c_str()); + } + TKillFaunaInfo kfi; + kfi.SheetName.initWithText(toString("c%u", i+1), STRING_MANAGER::creature_model, md, prim, args[0]); + kfi.Quantity.initWithText(toString("q%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); + _KillFaunas.push_back(kfi); + } + + vs = md.getPropertyArray(prim, "race/quantity", false, false); + for (uint i=0; i args; + explode(vs[i], string(" "), args, true); + if (args.size() != 2) + { + string err = toString("Syntax error in kill race : '%s', need ", vs[i].c_str()); + throw EParseException (prim, err.c_str()); + } + TKillRaceInfo kri; + kri.RaceName.initWithText(toString("r%u", i+1), STRING_MANAGER::creature_model, md, prim, args[0]); + kri.Quantity.initWithText(toString("q%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); + _KillRaces.push_back(kri); + } + string s; + //s = md.getProperty(prim, "group", false, true); + vs = md.getPropertyArray(prim, "group", false, false); + if (!vs.empty()) + { + if (vs.size() != 1) + { + string err = "Syntax error in kill group"; + throw EParseException (prim, err.c_str()); + } + + _KillGroup.initWithText("group_name", STRING_MANAGER::bot_name, md, prim, vs[0] ); + + } + + + vs = md.getPropertyArray(prim, "npc", false, false); + for (uint i=0; i args; + explode(s, string(" "), args, true); + if (args.size() != 2) + { + string err = toString("Syntax error in kill npc by name : '%s', need ", s.c_str()); + throw EParseException(prim, err.c_str()); + } + _KillNpcByNames.initWithText("npc", STRING_MANAGER::bot_name, md, prim, args[0]); + _KillNpcByNamesQuantity.initWithText("qt", STRING_MANAGER::integer, md, prim, args[1]); + } + + s = md.getProperty(prim, "faction/quantity", false, false); + if (!s.empty()) + { + vector args; + explode(s, string(" "), args, true); + if (args.size() != 2) + { + string err = toString("Syntax error in kill faction : '%s', need ", s.c_str()); + throw EParseException (prim, err.c_str()); + } + _KillFactionName.initWithText("faction", STRING_MANAGER::faction, md, prim, args[0]); + _KillFactionQuantity.initWithText("qt", STRING_MANAGER::integer, md, prim, args[1]); + } + + bool check = false; + if (!_KillFaunas.empty()) + check = true; + if (!_KillRaces.empty()) + { + if (check) + throw EParseException(prim, "Merging of multiple kill mode is forbidden !"); + check = true; + } + if (!_KillGroup.empty()) + { + if (check) + throw EParseException(prim, "Merging of multiple kill mode is forbidden !"); + + check = true; + } + if (!_KillNpcs.empty()) + { + if (check) + throw EParseException(prim, "Merging of multiple kill mode is forbidden !"); + check = true; + } + if (!_KillNpcByNames._VarValue.empty()) + { + if (check) + throw EParseException(prim, "Merging of multiple kill mode is forbidden !"); + check = true; + } + if (!_KillFactionName.empty()) + { + if (check) + throw EParseException(prim, "Merging of multiple kill mode is forbidden !"); + check = true; + } + + _Place.init("p", STRING_MANAGER::place, md, prim, "place"); + + if (!_Place.empty() && !_KillGroup.empty()) + { + throw EParseException(prim, "Using location with kill group instruction is forbidden!"); + } + // init base class + CContentObjective::init(md, prim); + + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + if (!_KillFaunas.empty()) + { + ret += "kill_fauna : "; + for (uint i=0; i<_KillFaunas.size(); ++i) + { + ret += _KillFaunas[i].SheetName+" "+_KillFaunas[i].Quantity; + if (i < _KillFaunas.size()-1) + ret += "; "; + } + } + else if (!_KillRaces.empty()) + { + ret += "kill_race : "; + for (uint i=0; i<_KillRaces.size(); ++i) + { + ret += _KillRaces[i].RaceName+" "+_KillRaces[i].Quantity; + if (i < _KillRaces.size()-1) + ret += "; "; + } + } + else if (!_KillGroup.empty()) + { + ret += "kill_group : " + _KillGroup; + } + else if (!_KillNpcs.empty()) + { + ret += "kill_npc : "; + for (uint i=0; i<_KillNpcs.size(); ++i) + { + ret += _KillNpcs[i]; + if (i < _KillNpcs.size()-1) + ret += "; "; + } + } + else if (!_KillNpcByNames.empty()) + { + ret += "kill_npc_by_name : "+_KillNpcByNames+" "+_KillNpcByNamesQuantity; + } + else if (!_KillFactionName.empty()) + { + ret += "kill_faction : "+_KillFactionName+" "+_KillFactionQuantity; + } + + if (!_Place.empty()) + ret += " : "+_Place; + + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentKill, "kill"); + +class CContentTalkTo : public CContentObjective +{ + TCompilerVarName _BotName; + CPhrase _Phrase; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + predef.resize(1); + predef[0].resize(1); + predef[0][0] = _BotName; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + + + _BotName.init("npc", STRING_MANAGER::bot, md, prim, "npc_name" ); + + CPhrase::TPredefParams pp(1); + pp[0].push_back(_BotName.getParamInfo()); + + vector vs; + vs = md.getPropertyArray(prim, "phrase", false, false); + _Phrase.initPhrase(md, prim, vs, 0, pp); + +// _Phrase.initPhrase(md, prim, vs); + +// if (_Phrase.asAdditionnalParams()) +// { +// // we need to remove the default 'npc' parameter if add params are found +// CPhrase temp; +// temp.initPhrase(md, prim, vs); +// +// _Phrase = temp; +// } + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "talk_to : "+_BotName; + + if (!_Phrase.isEmpty()) + ret += " : "+_Phrase.genScript(md); + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } + + string genPhrase() + { + string ret; + ret = CContentObjective::genPhrase(); + ret += _Phrase.genPhrase(); + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentTalkTo, "talk_to"); + +class CContentCast : public CContentObjective +{ + vector _Actions; + TCompilerVarName _Place; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + + { + numEntry = (uint32)_Actions.size(); + predef.resize(numEntry); + for (uint i=0; i _Mps; + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = (uint32)_Mps.size(); + predef.resize(numEntry); + for (uint i=0; i vs; + vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); + + for (uint i=0; i args; + explode(vs[i], string(" "), args, true); + if (args.size() != 3) + { + string err = toString("Invalid forage item in '%s', need ", vs[i].c_str()); + throw EParseException(prim, err.c_str()); + } + + TForageInfo fi; + fi.Item.initWithText(toString("i%u", i+1), STRING_MANAGER::item, md, prim, args[0]); + fi.Qt.initWithText(toString("qt%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); + fi.Ql.initWithText(toString("qual%u", i+1), STRING_MANAGER::integer, md, prim, args[2]); + + _Mps.push_back(fi); + } + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "forage : "; + + for (uint i=0; i<_Mps.size(); ++i) + { + ret += _Mps[i].Item+" "+_Mps[i].Qt+" "+_Mps[i].Ql; + if (i < _Mps.size()-1) + ret += "; "; + } + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentForage, "forage"); + +struct TLootInfo +{ + TCompilerVarName Item; + TCompilerVarName Qt; + TCompilerVarName Ql; +}; + +class CContentLoot : public CContentObjective +{ + enum TLootMode + { + lm_unknown, + lm_item, + lm_mp + }; + + TLootMode _Mode; + vector _Items; + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + if (_Mode == lm_item) + { + numEntry = (uint32)_Items.size(); + predef.resize(numEntry); + for (uint i=0; i vs; + vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); + + for (uint i=0; i args; + explode(vs[i], string(" "), args, true); + if (args.size() != 1 && args.size() != 3) + { + string err = toString("Invalid loot item in '%s', need or ", vs[i].c_str()); + throw EParseException(prim, err.c_str()); + } + + if (args.size() == 1) + { + if (_Mode == lm_mp) + throw EParseException(prim, "Can't mix item and mps loot"); + _Mode = lm_item; + } + else if (args.size() == 3) + { + if (_Mode == lm_item) + throw EParseException(prim, "Can't mix item and mps loot"); + _Mode = lm_mp; + } + + TLootInfo li; + li.Item.initWithText(toString("i%u", i+1), STRING_MANAGER::item, md, prim, args[0]); + + if (args.size() > 1) + { + li.Qt.initWithText(toString("qt%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); + + li.Ql.initWithText(toString("qual%u", i+1), STRING_MANAGER::integer, md, prim, args[2]); + + } + _Items.push_back(li); + } + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + if (_Mode == lm_item) + ret += "loot_item : "; + else + ret += "loot_mp : "; + + for (uint i=0; i<_Items.size(); ++i) + { + ret += _Items[i].Item; + if (_Mode == lm_mp) + ret += " "+_Items[i].Qt+" "+_Items[i].Ql; + if (i < _Items.size()-1) + ret += "; "; + } + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentLoot, "loot"); + +struct TCraftInfo +{ + TCompilerVarName Item; + TCompilerVarName Qt; + TCompilerVarName Ql; +}; + +class CContentCraft : public CContentObjective +{ + vector _Items; + + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = (uint32)_Items.size(); + predef.resize(numEntry); + for (uint i=0; i vs; + vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); + + for (uint i=0; i args; + explode(vs[i], string(" "), args, true); + if (args.size() != 3) + { + string err = toString("Invalid craft item in '%s', need ", vs[i].c_str()); + throw EParseException(prim, err.c_str()); + } + + TCraftInfo ci; + ci.Item.initWithText(toString("i%u", i+1), STRING_MANAGER::item, md, prim, args[0]); + ci.Qt.initWithText(toString("qt%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); + ci.Ql.initWithText(toString("qual%u", i+1), STRING_MANAGER::integer, md, prim, args[2]); + _Items.push_back(ci); + } + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "craft : "; + + for (uint i=0; i<_Items.size(); ++i) + { + ret += _Items[i].Item+" "+_Items[i].Qt+" "+_Items[i].Ql; + if (i < _Items.size()-1) + ret += "; "; + } + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentCraft, "craft"); + +class CContentTarget : public CContentObjective +{ + + vector _Npcs; + vector _Faunas; + vector _Races; + TCompilerVarName _Place; + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + // phrase 0 - 1 parameter + // phrase 1 - 2 parameters + // etc ... as many (bots,faunas,race) as specified + + + if (!_Npcs.empty()) + { + numEntry = (uint32)_Npcs.size(); + predef.resize(numEntry); + for (uint i=0; i _Items; + TCompilerVarName _Npc; + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = (uint32)_Items.size(); + predef.resize(numEntry); + for (uint i=0; i vs; + vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); + + for (uint i=0; i args; + explode(vs[i], string(" "), args, true); + if (args.size() != 3) + { + string err = toString("Invalid sell item in '%s', need ", vs[i].c_str()); + throw EParseException(prim, err.c_str()); + } + + TSellInfo si; + si.Item.initWithText(toString("i%u", i+1), STRING_MANAGER::item, md, prim, args[0]); + si.Qt.initWithText(toString("qt%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); + si.Ql.initWithText(toString("qual%u", i+1), STRING_MANAGER::integer, md, prim, args[2]); + _Items.push_back(si); + } + + _Npc.init("npc", STRING_MANAGER::bot, md, prim, "npc_name"); + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "sell : "; + + for (uint i=0; i<_Items.size(); ++i) + { + ret += _Items[i].Item+" "+_Items[i].Qt+" "+_Items[i].Ql; + if (i < _Items.size()-1) + ret += "; "; + }; + if (!_Npc.empty()) + { + ret += " : "+_Npc; + } + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentSell, "sell"); + +struct TBuyInfo +{ + TCompilerVarName Item; + TCompilerVarName Qt; + TCompilerVarName Ql; +}; + +class CContentBuy : public CContentObjective +{ + vector _Items; + TCompilerVarName _Npc; + + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = (uint32)_Items.size(); + predef.resize(numEntry); + for (uint i=0; i vs; + vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); + + for (uint i=0; i args; + explode(vs[i], string(" "), args, true); + if (args.size() != 3) + { + string err = toString("Invalid buy item in '%s', need ", vs[i].c_str()); + throw EParseException(prim, err.c_str()); + } + + TBuyInfo bi; + bi.Item.initWithText(toString("i%u", i+1), STRING_MANAGER::item, md, prim, args[0]); + bi.Qt.initWithText(toString("qt%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); + bi.Ql.initWithText(toString("qual%u", i+1), STRING_MANAGER::integer, md, prim, args[2]); + _Items.push_back(bi); + } + + _Npc.init("npc", STRING_MANAGER::bot, md, prim, "npc_name"); + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "buy : "; + + for (uint i=0; i<_Items.size(); ++i) + { + ret += _Items[i].Item+" "+_Items[i].Qt+" "+_Items[i].Ql; + if (i < _Items.size()-1) + ret += "; "; + }; + if (!_Npc.empty()) + { + ret += " : "+_Npc; + } + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; + +REGISTER_STEP_CONTENT(CContentBuy, "buy"); + +struct TGiveInfo +{ + TCompilerVarName Item; + TCompilerVarName Qt; + TCompilerVarName Ql; +}; + +class CContentGive : public CContentObjective +{ + vector _Items; + TCompilerVarName _Npc; + bool _QualSpec; + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = (uint32)_Items.size(); + predef.resize(numEntry); + for (uint i=0; i vs; + vs = md.getPropertyArray(prim, "item/quantity/quality", true, false); + + for (uint i=0; i args; + explode(vs[i], string(" "), args, true); + if (args.size() != 3 && args.size() != 2) + { + string err = toString("Invalid give item in '%s', need []", vs[i].c_str()); + throw EParseException(prim, err.c_str()); + } + + if (i == 0) + { + _QualSpec = args.size() == 3; + } + else + { + if (_QualSpec && args.size() == 2) + { + string err = toString("Invalid give item in '%s', mixing of item with quality and item without quality is not supported", vs[i].c_str()); + throw EParseException(prim, err.c_str()); + } + } + + TGiveInfo gi; + gi.Item.initWithText(toString("i%u", i+1), STRING_MANAGER::item, md, prim, args[0]); + gi.Qt.initWithText(toString("qt%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); + + if (_QualSpec) + gi.Ql.initWithText(toString("qual%u", i+1), STRING_MANAGER::integer, md, prim, args[2]); + + _Items.push_back(gi); + } + + _Npc.init("npc", STRING_MANAGER::bot, md, prim, "npc_name"); + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "give_item : "; + + for (uint i=0; i<_Items.size(); ++i) + { + ret += _Items[i].Item+" "+_Items[i].Qt; + if (_QualSpec) + ret += " "+_Items[i].Ql; + if (i < _Items.size()-1) + ret += "; "; + }; + ret += " : "+_Npc; + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentGive, "give_item"); + +class CContentGiveMoney : public CContentObjective +{ + TCompilerVarName _Amount; + TCompilerVarName _Npc; + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + predef.resize(1); + predef[0].resize(2); + + predef[0][0] = _Amount; + predef[0][1] = _Npc; + + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + _Amount.init("amount", STRING_MANAGER::integer, md, prim, "amount"); + _Npc.init("npc", STRING_MANAGER::bot, md, prim, "npc_name"); + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "give_money : "+_Amount+" : "+_Npc; + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentGiveMoney, "give_money"); + +class CContentVisit : public CContentObjective +{ + TCompilerVarName _Place; + TCompilerVarName _PlaceVar; + vector _Items; + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + predef.resize(1); + predef[0].resize(1+_Items.size()); + predef[0][0] = _Place; + + for (uint i=0; i<_Items.size(); ++i) + predef[0][i+1] = _Items[i]; + + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + + _Place.init("place", STRING_MANAGER::place, md, prim, "place"); + _Items = TCompilerVarName::getPropertyArrayWithText("i", STRING_MANAGER::item, md, prim, "items_worn" ); + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "visit : "+_Place; + + if (!_Items.empty()) + { + ret += " : "; + for (uint i=0; i<_Items.size(); ++i) + { + ret += _Items[i]; + if (i < _Items.size()-1) + ret += "; "; + } + } + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentVisit, "visit"); + +class CContentEscort : public CContentObjective +{ + string _GroupName; + bool _SaveAll; + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init (CMissionData &md, IPrimitive *prim) + { + _GroupName = md.getProperty(prim, "group_to_escort", true, false); + string s = md.getProperty(prim, "save_all", true, false); + _SaveAll = (NLMISC::toLower(s) == "true"); + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "escort : "+_GroupName; + + if (_SaveAll) + ret += " : save_all"; + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentEscort, "escort"); + +struct TSkillInfo +{ + TCompilerVarName _SkillName; + TCompilerVarName _Level; +}; + +class CContentSkill: public CContentObjective +{ + vector _Skills; + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = (uint32)_Skills.size(); + predef.resize(numEntry); + + for (uint i=0; i vs; + vs = md.getPropertyArray(prim, "skill_name/level", true, false); + + for (uint i=0; i args; + explode(vs[i], string(" "), args, true); + + if (args.size() != 2) + { + string err = toString("Invalid skill in '%s', need ", vs[i].c_str()); + throw EParseException(prim, err.c_str()); + } + + TSkillInfo si; + si._SkillName.initWithText(toString("s%u", i+1), STRING_MANAGER::skill, md, prim, args[0]); + si._Level.initWithText(toString("level%u", i+1), STRING_MANAGER::integer, md, prim, args[1]); + _Skills.push_back(si); + } + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "skill : "; + + for (uint i=0; i<_Skills.size(); ++i) + { + ret += _Skills[i]._SkillName+" "+_Skills[i]._Level; + if (i < _Skills.size()-1) + ret += "; "; + } + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentSkill, "skill"); + +class CContentMission: public CContentObjective +{ + vector _Missions; + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } + +public: + CContentMission(): _Prim(0) {} + + void init(CMissionData &md, IPrimitive *prim) + { + _Missions = md.getPropertyArray(prim, "mission_names", true, false); + _Prim = prim; + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "mission : "; + + for (uint i=0; i<_Missions.size(); ++i) + { + ret += _Missions[i]; + if (i < _Missions.size()-1) + ret += "; "; + + // We check to see if we specified a number after the mission name. If so, we check if it's a guild mission + std::size_t pos = _Missions[i].find_first_of(" \t"); + if (pos != std::string::npos && !md.isGuildMission()) + { + string err = toString("primitive(%s): CContentMission: Number of members needed to complete the mission specified but the mission is not a guild mission.", _Prim->getName().c_str()); + throw EParseException(_Prim, err.c_str()); + } + } + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } + + IPrimitive *_Prim; +}; +REGISTER_STEP_CONTENT(CContentMission, "do_mission"); + +class CContentWaitAIMsg : public CContentObjective +{ + vector _MsgContent; + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } + +public: + void init(CMissionData &md, IPrimitive *prim) + { + _MsgContent = md.getPropertyArray(prim, "msg_content", true, false); + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "wait_msg : "; + + for (uint i=0; i<_MsgContent.size(); ++i) + { + ret += _MsgContent[i]; + if (i < _MsgContent.size()-1) + ret += " "; + } + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentWaitAIMsg, "wait_ai_msg"); + +// *********** +// queue_start +// *********** + +class CContentQueueStart : public CContentObjective +{ + string _StepName; + string _QueueName; + string _Timer; + vector _AIInstances; + vector _GroupsToSpawn; + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } + +public: + void init(CMissionData &md, IPrimitive *prim) + { + _StepName = md.getProperty(prim, "step_name", true, true); + _QueueName = md.getProperty(prim, "queue_name", true, false); + if (_StepName.empty()) + _StepName = "queue_start_" + _QueueName; + + _Timer = md.getProperty(prim, "timer", true, false); + _GroupsToSpawn = md.getPropertyArray(prim, "groups_to_spawn", true, true); + if (_GroupsToSpawn.empty()) + _AIInstances = md.getPropertyArray(prim, "ai_instances", true, true); + else + _AIInstances = md.getPropertyArray(prim, "ai_instances", true, false); + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + uint32 i; + string ret; + ret = CContentObjective::genCode(md); + + ret += "jump_point : " + _StepName + NL; + ret += "queue_start : " + _QueueName + " : " + _Timer + NL; + ret += NL; + + if (!_GroupsToSpawn.empty()) + { + // crash : ai_instance_1 : ai_instance_2 : ... + ret += "crash"; + nlassert(_AIInstances.size() > 0); + for (i = 0; i < _AIInstances.size(); ++i) + ret += " : " + _AIInstances[i]; + ret += NL; + + for (i = 0; i < _GroupsToSpawn.size(); ++i) + ret += "handle_release : " + _GroupsToSpawn[i] + NL; + + ret += "/crash" + NL; + ret += NL; + + ret += "failure" + NL; + for (i = 0; i < _GroupsToSpawn.size(); ++i) + ret += "handle_release : " + _GroupsToSpawn[i] + NL; + ret += "/failure" + NL; + ret += NL; + } + + ret += "player_reconnect" + NL; + for (i = 0; i < _GroupsToSpawn.size(); ++i) + ret += "handle_release : " + _GroupsToSpawn[i] + NL; + ret += "jump : " + _StepName + NL; + ret += "/player_reconnect" + NL; + ret += NL; + + for (i = 0; i < _GroupsToSpawn.size(); ++i) + ret += "handle_create : " + _GroupsToSpawn[i] + NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentQueueStart, "queue_start"); + +// ********* +// queue_end +// ********* + +class CActionQueueEnd : public IStepContent +{ + string _ActionName; + string _QueueName; + // Find the following info in the queue_start node + vector _AIInstances; + vector _GroupsToSpawn; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } +public: + void init(CMissionData &md, IPrimitive *prim) + { + IStepContent::init(md, prim); + _ActionName = md.getProperty(prim, "action_name", true, true); + _QueueName = md.getProperty(prim, "queue_name", true, false); + if (_ActionName.empty()) + _ActionName = "queue_end_" + _QueueName; + + // Search in the queue_start node + IPrimitive *primParent = prim; + while (primParent->getParent() != NULL) + { + string className; + if (primParent->getPropertyByName("class", className)) + if (className == "mission_tree") + break; + primParent = primParent->getParent(); + } + TPrimitiveClassPredicate condClass("queue_start"); + CPrimitiveSet s; + TPrimitiveSet ps; + s.buildSet(primParent, condClass, ps); + + TPrimitivePropertyPredicate condProp("queue_name", _QueueName); + CPrimitiveSetFilter filter; + TPrimitiveSet psFinal; + filter.filterSet(ps, condProp, psFinal); + + if (psFinal.size() == 0) + { + string err = toString("Can't find queue_start for queue_end : '%s'", _QueueName.c_str()); + throw EParseException(prim, err.c_str()); + } + if (psFinal.size() > 1) + { + string err = toString("More than 1 queue_start for queue_end : '%s'", _QueueName.c_str()); + throw EParseException(prim, err.c_str()); + } + + _GroupsToSpawn = md.getPropertyArray(psFinal[0], "groups_to_spawn", true, true); + if (_GroupsToSpawn.empty()) + _AIInstances = md.getPropertyArray(psFinal[0], "ai_instances", true, true); + else + _AIInstances = md.getPropertyArray(psFinal[0], "ai_instances", true, false); + + } + + string genCode(CMissionData &md) + { + uint32 i; + string ret; + + if (_GroupsToSpawn.size() > 0) + { + for (i = 0; i < _GroupsToSpawn.size(); ++i) + ret += "handle_release : " + _GroupsToSpawn[i] + NL; + ret += NL; + } + + if (_AIInstances.size() > 0) + { + ret += "crash"; + for (i = 0; i < _AIInstances.size(); ++i) + ret += " : " + _AIInstances[i]; + ret += NL; + ret += "/crash" + NL; + ret += NL; + } + + ret += "failure" + NL; + ret += "/failure" + NL; + ret += NL; + + ret += "player_reconnect" + NL; + ret += "/player_reconnect" + NL; + ret += NL; + ret += "queue_end : " +_QueueName + NL; + + return ret; + } + +}; +REGISTER_STEP_CONTENT(CActionQueueEnd, "queue_end"); + + +class CContentRingScenario: public CContentObjective +{ + string _ScenarioTag; + + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + } + +public: + void init(CMissionData &md, IPrimitive *prim) + { + _ScenarioTag = md.getProperty(prim, "scenario_tag", true, false); + + CContentObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CContentObjective::genCode(md); + + ret += "ring_scenario : "; + ret += _ScenarioTag; + // Add the 'nb_guild_members_needed' parameter if needed + //ret += CContentObjective::genNbGuildMembersNeededOption(md); + ret += NL; + + return ret; + } +}; +REGISTER_STEP_CONTENT(CContentRingScenario, "ring_scenario"); + diff --git a/code/ryzom/tools/leveldesign/mission_compiler_lib/steps.cpp b/code/ryzom/tools/leveldesign/mission_compiler_lib/steps.cpp index 44e6e96cc..79b7e5095 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_lib/steps.cpp +++ b/code/ryzom/tools/leveldesign/mission_compiler_lib/steps.cpp @@ -1,1402 +1,1402 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "mission_compiler.h" -#include "step.h" -#include "nel/misc/factory.h" -#include - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; - - -// ***** -// IStep -// ***** - -IStep *IStep::createStep(CMissionData &md, IPrimitive *prim) -{ - string *c; - if (!prim->getPropertyByName("class", c)) - throw EParseException(prim, "Can't find property 'class' on primitive"); - - IStep *ret = CFactoryIndirect::instance().getFactory(*c)->createStep(md, prim); - ret->init(md, prim); - - return ret; -}; - -IStep::IStep(CMissionData &md, NLLIGO::IPrimitive *prim) - : _Primitive(prim), - EndOfBranch(false), - JumpPoint(false) -{ - if (prim == NULL) - return; - - prim->getPropertyByName("class", _StepType); - prim->getPropertyByName("name", _StepName); - - // parse the sub prim to create action & objectives; - IPrimitive *child; - // parse the preactions - { - TPrimitiveClassAndNamePredicate pred("actions", "pre_actions"); - child = getPrimitiveChild(prim, pred); - } - - if (child) - { - for (uint i=0; igetNumChildren(); ++i) - { - IPrimitive *subChild; - child->getChild(subChild, i); - if (subChild) - { - // ok, we got one - IStepContent *sc = IStepContent::createStepContent(md, subChild); - if (sc) - _PreActions.push_back(sc); - } - } - } - // parse the objectives - { - TPrimitiveClassAndNamePredicate pred("mission_objectives", "objectives"); - child = getPrimitiveChild(prim, pred); - } - if (child) - { - for (uint i=0; igetNumChildren(); ++i) - { - IPrimitive *subChild; - child->getChild(subChild, i); - if (subChild) - { - // ok, we got one - IStepContent *sc = IStepContent::createStepContent(md, subChild); - if (sc) - _Objectives.push_back(sc); - } - } - } - // parse the post actions - { - TPrimitiveClassAndNamePredicate pred("actions", "post_actions"); - child = getPrimitiveChild(prim, pred); - } - if (child) - { - for (uint i=0; igetNumChildren(); ++i) - { - IPrimitive *subChild; - child->getChild(subChild, i); - if (subChild) - { - // ok, we got one - IStepContent *sc = IStepContent::createStepContent(md, subChild); - if (sc) - _PostActions.push_back(sc); - } - } - } -} - -void IStep::fillStepJump(CMissionData &md, std::set &jumpPoints) -{ - uint i; - // extract step content jump points - for (i=0; i<_PreActions.size(); ++i) - { - _PreActions[i]->fillJump(md, jumpPoints); - } - for (i=0; i<_Objectives.size(); ++i) - { - _Objectives[i]->fillJump(md, jumpPoints); - } - for (i=0; i<_PostActions.size(); ++i) - { - _PostActions[i]->fillJump(md, jumpPoints); - } - - fillJump(md, jumpPoints); - - for (i = 0; i < _SubSteps.size(); ++i) - if (_SubSteps[i] != NULL) - _SubSteps[i]->fillStepJump(md, jumpPoints); -} - - -void IStep::fillJump(CMissionData &md, std::set &jumpPoints) -{ - // jump to the next step - IStep *next = md.getNextStep(this); - - if (!EndOfBranch && next) - { - TJumpInfo ji(next->getStepName()); - jumpPoints.insert(ji); - } - else - { - TJumpInfo ji("__end__"); - jumpPoints.insert(ji); - } -} - -std::string IStep::genCode(CMissionData &md) -{ - string ret; - - ret += genCodePreActions(md); - ret += genCodeObjectives(md); - ret += genCodePostActions(md); - - return ret; -} - -std::string IStep::genCodePreActions(CMissionData &md) -{ - string ret; - // generate code for pre actions - for (uint i=0; i<_PreActions.size(); ++i) - { - ret += _PreActions[i]->genStepContentCode(md); - } - return ret; -} - -std::string IStep::genCodeObjectives(CMissionData &md) -{ - string ret; - // generate code for objectives - for (uint i=0; i<_Objectives.size(); ++i) - { - ret += _Objectives[i]->genStepContentCode(md); - } - return ret; -} - -std::string IStep::genCodePostActions(CMissionData &md) -{ - string ret; - //generate code for post actions - for (uint i=0; i<_PostActions.size(); ++i) - { - ret += _PostActions[i]->genStepContentCode(md); - } - return ret; -} - - -std::string IStep::genPhrase() -{ - string ret; - // generate code for pre actions - for (uint i=0; i<_PreActions.size(); ++i) - { - ret += _PreActions[i]->genStepContentPhrase(); - } - // generate code for objectives - for (uint i=0; i<_Objectives.size(); ++i) - { - ret += _Objectives[i]->genStepContentPhrase(); - } - //generate code for post actions - for (uint i=0; i<_PostActions.size(); ++i) - { - ret += _PostActions[i]->genStepContentPhrase(); - } - //generate code for sub steps - for (uint i=0; i<_SubSteps.size(); ++i) - { - ret += _SubSteps[i]->genPhrase(); - } - - return ret; -} - - -class CStep : public IStep -{ -public: - CStep(CMissionData &md, IPrimitive *prim) - : IStep(md, prim) - { - // nothing special to do - } - -}; -REGISTER_STEP_INDIRECT(CStep, "step"); - -class CStepObjective : public CStep -{ -public: - virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - predef.clear(); - }; - - CStepObjective(CMissionData &md, IPrimitive *prim, const std::string &prefix = "") - : CStep(md, prim), - _HideObj(false), - _Prefix(prefix) - { - } - - void init(CMissionData &md, IPrimitive *prim) - { - _HideObj = md.getProperty(prim, _Prefix + "hide_obj", true, false) == "true"; - _OverloadObj = md.getPropertyArray(prim, _Prefix + "overload_objective", false, false); - _RoleplayObj = md.getPropertyArray(prim, _Prefix + "roleplay_objective", false, false); - uint32 numEntry; - CPhrase::TPredefParams params; - // ask derived class for predefined params - getPredefParam(numEntry, params); - _OverloadPhrase.initPhrase(md, prim, _OverloadObj, numEntry, params); - _RoleplayPhrase.initPhrase(md, prim, _RoleplayObj, numEntry, params); - } - - virtual bool isAction() { return true; } - - string genCode(CMissionData &md) - { - string ret; - if (_HideObj) - ret = "hide_obj" + NL; - if (!_OverloadObj.empty()) - { - ret += "set_obj : " + _OverloadPhrase.genScript(md) + NL; - } - if (!_RoleplayObj.empty()) - { - ret += "set_obj_rp : " + _RoleplayPhrase.genScript(md) + NL; - } - - return ret; - } - - string genPhrase() - { - string ret; - ret += _OverloadPhrase.genPhrase(); - ret += _RoleplayPhrase.genPhrase(); - - ret += IStep::genPhrase(); - - return ret; - } - -protected: - string _Prefix; - bool _HideObj; - vector _OverloadObj; - CPhrase _OverloadPhrase; - vector _RoleplayObj; - CPhrase _RoleplayPhrase; -}; - -class CStepDynChatTalkTo : public CStepObjective -{ -// string _BotNameVar; -// string _BotName; - TCompilerVarName _BotName; - CPhrase _Phrase; - - void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) - { - numEntry = 0; - predef.resize(1); - predef[0].resize(1); - predef[0][0] = _BotName.getParamInfo(); -// if (_BotNameVar.empty()) -// predef[0][0] = CPhrase::TParamInfo("npc", STRING_MANAGER::bot); -// else -// predef[0][0] = CPhrase::TParamInfo(_BotNameVar, STRING_MANAGER::bot); - } -public: - CStepDynChatTalkTo(CMissionData &md, IPrimitive *prim, const std::string &prefix = "") - : CStepObjective(md, prim, prefix) - { - } - - void init(CMissionData &md, IPrimitive *prim) - { - _BotName.init("npc", STRING_MANAGER::bot, md, prim, "npc_name"); -// _BotNameVar = md.getProperty(prim, "npc_name", false, false); - // remove the variable tag if any -// untagVar(_BotNameVar); - -// _BotName = md.getProperty(prim, "npc_name", true, false); - vector vs; - vs = md.getPropertyArray(prim, "talk_to_menu", false, false); - CPhrase::TPredefParams pp(1); - pp[0].push_back(_BotName.getParamInfo()); -// if (_BotNameVar.empty()) -// pp[0].push_back(CPhrase::TParamInfo("npc", STRING_MANAGER::bot)); -// else -// pp[0].push_back(CPhrase::TParamInfo(_BotNameVar, STRING_MANAGER::bot)); - _Phrase.initPhrase(md, prim, vs, 0, pp); - -// _Phrase.initPhrase(md, prim, vs); - -// if (_Phrase.asAdditionnalParams()) -// { -// // we need to remove the default 'npc' parameter if add params are found -// CPhrase temp; -// temp.initPhrase(md, prim, vs); -// -// _Phrase = temp; -// } - CStepObjective::init(md, prim); - } - - string genCode(CMissionData &md) - { - string ret; - ret = CStepObjective::genCode(md); - - ret += "talk_to : "+_BotName._VarValue; - - if (!_Phrase.isEmpty()) - ret += " : "+_Phrase.genScript(md); - ret += NL; - - return ret; - } - - string genPhrase() - { - string ret; - ret = CStepObjective::genPhrase(); - ret += _Phrase.genPhrase(); - - return ret; - } -}; - -class CStepJump : public IStep -{ -public: - CStepJump(CMissionData &md, IPrimitive *prim) - : IStep(md, prim) - { - _StepName = md.getProperty(prim, "target", true, false); - } - - void fillJump(CMissionData &md, set &jumpPoints) - { - jumpPoints.insert(TJumpInfo(_StepName, "", false)); - } - - string genCode(CMissionData &md) - { - string ret; - - ret += "jump : " + _StepName + NL; - - return ret; - } - - bool isAJump() - { - return true; - } - - string _StepName; -}; -REGISTER_STEP_INDIRECT(CStepJump, "jump_to"); - -/// pseudo step used in step parsing -class CStepEnd : public IStep -{ -public: - CStepEnd(CMissionData &md, IPrimitive *prim) - : IStep(md, prim) - { - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "end"+NL; - - return ret; - } - - bool isEnd() { return true; } - -}; -REGISTER_STEP_INDIRECT(CStepEnd, "end"); - -class CStepFailure : public IStep -{ - // Optional jump at end of failure - string _JumpTo; -public: - CStepFailure(CMissionData &md, IPrimitive *prim) - : IStep(md, prim) - { - // parse the sub prim to create action & objectives; - IPrimitive *child; - // parse the pre-actions - { - TPrimitiveClassAndNamePredicate pred("actions", "actions"); - child = getPrimitiveChild(prim, pred); - } - if (child) - { - for (uint i=0; igetNumChildren(); ++i) - { - IPrimitive *subChild; - child->getChild(subChild, i); - if (subChild) - { - // ok, we got one - IStepContent *sc = IStepContent::createStepContent(md, subChild); - if (sc) - _PreActions.push_back(sc); - } - } - } - // look for an optional jump - { - TPrimitiveClassPredicate pred("jump_to"); - child = getPrimitiveChild(prim, pred); - } - if (child) - { - // ok, we have a jump at end of fail step - _JumpTo = md.getProperty(child, "target", true, false); - } - } - - string genCode(CMissionData &md) - { - string ret; - - ret = "failure" + NL; - - string tmp = IStep::genCode(md); - tabulateLine(tmp, 1); - ret += tmp; - - - if (!_JumpTo.empty()) - { - ret += "\tjump : "+_JumpTo + NL; - } - - ret += "/failure"+NL; - - return ret; - } - - void fillJump(CMissionData &md, set &jumpPoints) - { - IStep::fillJump(md, jumpPoints); - if (!_JumpTo.empty()) - jumpPoints.insert(TJumpInfo(_JumpTo)); - } - -}; -REGISTER_STEP_INDIRECT(CStepFailure, "step_failure"); - -class CStepCrash : public IStep -{ - // Optional jump at end of failure - string _JumpTo; - vector _AiInstances; -public: - CStepCrash(CMissionData &md, IPrimitive *prim) - : IStep(md, prim) - { - // parse the sub prim to create action & objectives; - IPrimitive *child; - // parse the pre-actions - { - TPrimitiveClassAndNamePredicate pred("actions", "actions"); - child = getPrimitiveChild(prim, pred); - } - if (child) - { - for (uint i=0; igetNumChildren(); ++i) - { - IPrimitive *subChild; - child->getChild(subChild, i); - if (subChild) - { - // ok, we got one - IStepContent *sc = IStepContent::createStepContent(md, subChild); - if (sc) - _PreActions.push_back(sc); - } - } - } - - // parse ai instance list - vector vs = md.getPropertyArray(prim, "ai_instances", true, false); -/* if (vs.size() == 0) - { - string err = toString("crash block need at least one ai instance !"); - throw EParseException(prim, err.c_str()); - } -*/ - for (uint i=0; i &jumpPoints) - { - IStep::fillJump(md, jumpPoints); - if (!_JumpTo.empty()) - jumpPoints.insert(TJumpInfo(_JumpTo)); - } - -}; -REGISTER_STEP_INDIRECT(CStepCrash, "step_crash"); - -// ///////////////////// // -// STEP PLAYER RECONNECT // -// ///////////////////// // - -// *************************************************************************** -CStepPlayerReconnect::CStepPlayerReconnect(CMissionData &md, IPrimitive *prim) : IStep(md, prim) -{ - // parse the sub prim to create action & objectives; - IPrimitive *child; - - TPrimitiveSet resp; - { - TPrimitivePropertyPredicate pred("step_tag", "true"); - filterPrimitiveChilds(prim, pred, resp); - } - for (uint i=0; igetStepName()) ) - { - // insert a jump point - ret += "jump_point : " + _SubSteps[i]->getStepName() + NL; - } - - ret += _SubSteps[i]->genCode(md); - } - - if (!_JumpTo.empty()) - { - ret += "\tjump : "+_JumpTo + NL; - } - - ret += "/player_reconnect"+NL; - - return ret; -} - -// *************************************************************************** -void CStepPlayerReconnect::fillJump(CMissionData &md, set &jumpPoints) -{ - IStep::fillJump(md, jumpPoints); - if (!_JumpTo.empty()) - jumpPoints.insert(TJumpInfo(_JumpTo)); -} - -REGISTER_STEP_INDIRECT(CStepPlayerReconnect, "step_player_reconnect"); - -// //////////////////////////// // -// END OF STEP PLAYER RECONNECT // -// //////////////////////////// // - -// *************************************************************************** -// get the jump point of a node. NB: if the node is itself a jump, then directly jump to its target -static std::string *getJumpTarget(IPrimitive *child) -{ - if(!child) - return NULL; - - // default: jump to the node - string *s= NULL; - child->getPropertyByName("name", s); - - // if the node is a jump itself - string *className= NULL; - child->getPropertyByName("class", className); - if (className && *className == "jump_to") - { - // generate jump to the step jump target - child->getPropertyByName("target", s); - } - - return s; -} - - -// *************************************************************************** -class CStepDynChat : public IStep -{ -public: - CStepDynChat(CMissionData &md, IPrimitive *prim) - : IStep(md, prim) - { - _BotName = md.getProperty(prim, "npc_name", true, false); - vector temp = md.getPropertyArray(prim, "phrase", false, false); - _Phrase.initPhrase(md, prim, temp); - // talk_to menu - temp = md.getPropertyArray(prim, "talk_to_menu", false, false); -// _TalkToMenu.initPhrase(md, prim, temp); - - _TalkToObjective = NULL; - std::auto_ptr talkToObjective; // next calls could throw exceptions, so take care... - if (!temp.empty()) - { - talkToObjective.reset(new CStepDynChatTalkTo(md, prim, "talk_to_")); - talkToObjective->init(md, prim); - } - - // build the sub branch list - IPrimitive *noResp; - { - TPrimitiveClassPredicate pred("no_answer"); - noResp = getPrimitiveChild(prim, pred); - } - nlassert(noResp); - _SubBranchs.push_back(noResp); - - TPrimitiveSet resp; - { - TPrimitiveClassPredicate pred("dyn_answer"); - filterPrimitiveChilds(prim, pred, resp); - } - _Responses.resize(resp.size()); - for (uint i=0; igetNumChildren() == 0) - throw EParseException(prim, "missing step under 'dyn_answer' node for response"); - - vector temp = md.getPropertyArray(resp[i], "phrase_answer", false, false); - _Responses[i].initPhrase(md, resp[i], temp); - } - _TalkToObjective = talkToObjective.release(); // commit result - } - ~CStepDynChat() - { - delete _TalkToObjective; - } - - TPrimitiveSet getSubBranchs() - { - TPrimitiveSet vStepsToReturn; - for (uint i = 0; i < _SubBranchs.size(); ++i) - { - TPrimitiveSet childs; - { - TPrimitivePropertyPredicate pred("step_tag", "true"); - filterPrimitiveChilds(_SubBranchs[i], pred, childs); - } - for (uint j = 0; j < childs.size(); ++j) - vStepsToReturn.push_back(childs[j]); - } - return vStepsToReturn; - } - - void fillJump(CMissionData &md, set &jumpPoints) - { - for (uint i=0; i<_SubBranchs.size(); ++i) - { - string *s; - IPrimitive *firstStep; - if (!_SubBranchs[i]->getChild(firstStep, 0)) - throw EParseException(_Primitive, toString("Can't find child in %uth sub branch", i+1).c_str()); - - bool ret = firstStep->getPropertyByName("name", s); - if (!ret) - throw EParseException(_Primitive, toString("Can't find property 'name' in %uth sub branch", i+1).c_str()); - - string label; - _SubBranchs[i]->getPropertyByName("name", label); - jumpPoints.insert(TJumpInfo(*s, label)); - } - } - - string genCode(CMissionData &md) - { - string ret; - - // if there's a talk_to menu, add it -// if (!_TalkToMenu.isEmpty()) - if (_TalkToObjective != NULL) - { - ret += _TalkToObjective->genCode(md); -// ret += "talk_to : "+_BotName; -// ret += " : " + _TalkToMenu.genScript(md); -// ret += NL; - } - - - ret += "dyn_chat : " + _BotName + " : " + _Phrase.genScript(md); - - for (uint i=1; i<_SubBranchs.size(); ++i) - { - IPrimitive *child; - _SubBranchs[i]->getChild(child, 0); - - // get the jump target - string *s= getJumpTarget(child); - - ret += " : " + *s + " " + _Responses[i-1].genScript(md); - } - - ret += NL; - - return ret; - } - - string genPhrase() - { - string ret; /* = CStepObjective::genPhrase();*/ - -// if (!_TalkToMenu.isEmpty()) - if (_TalkToObjective != NULL) - { - ret += _TalkToObjective->genPhrase(); -// ret += _TalkToMenu.genPhrase(); - } - - ret += _Phrase.genPhrase(); - - for (uint i=0; i<_Responses.size(); ++i) - { - ret += _Responses[i].genPhrase(); - } - return ret; - } - - /// the list of sub branch for the dyn chat. - TPrimitiveSet _SubBranchs; - // phrase for the main text - CPhrase _Phrase; - // list of phrase for each response - vector _Responses; - - string _BotName; - - // 'talk_to' part -// CPhrase _TalkToMenu; - CStepDynChatTalkTo *_TalkToObjective; - -}; -REGISTER_STEP_INDIRECT(CStepDynChat, "step_dyn_chat"); - -class CLinearDynChat : public IStep -{ - enum TLinearMode - { - mode_fail, - mode_retry, - mode_continue, -// mode_skipable - }; - - TLinearMode _Mode; - string _BotName; - CPhrase _Phrase; - CPhrase _PhraseYes; - - -public: - - - CLinearDynChat(CMissionData &md, IPrimitive *prim) - : IStep(md, prim) - { - _BotName = md.getProperty(prim, "npc_name", true, false); - vector temp = md.getPropertyArray(prim, "phrase", false, false); - _Phrase.initPhrase(md, prim, temp); - - // set the linear mode - string className; - prim->getPropertyByName("class", className); - - if (className == "linear_dyn_chat_fail") - _Mode = mode_fail; - else if (className == "linear_dyn_chat_retry") - _Mode = mode_retry; - else if (className == "linear_dyn_chat_continue") - _Mode = mode_continue; - else - { - string err = toString("Unknow class '%s' for dyn chat !", className.c_str()); - throw EParseException(prim, err.c_str()); - } - - // read the response phrase - vector phraseYes; - phraseYes = md.getPropertyArray(prim, "phrase_yes", false, false); - _PhraseYes.initPhrase(md, prim, phraseYes); - } - - string genCode(CMissionData &md) - { - string ret; - - switch (_Mode) - { - case mode_fail: - ret = "dyn_chat : "+_BotName+" : "+_Phrase.genScript(md)+" : "+_StepName+"_resp "+_PhraseYes.genScript(md)+NL; - ret += "fail"+NL; - ret += "jump_point : " +_StepName+"_resp"+NL; - break; - case mode_retry: - ret += "jump_point : " +_StepName+"_retry"+NL; - ret += "dyn_chat : "+_BotName+" : "+_Phrase.genScript(md)+" : "+_StepName+"_resp "+_PhraseYes.genScript(md)+NL; - ret += "jump : "+_StepName+"_retry"+NL; - ret += "jump_point : " +_StepName+"_resp"+NL; - break; - case mode_continue: - ret = "dyn_chat : "+_BotName+" : "+_Phrase.genScript(md)+" : "+_StepName+"_resp "+_PhraseYes.genScript(md)+NL; - ret += "jump_point : " +_StepName+"_resp"+NL; - break; - } - - return ret; - } - - string genPhrase() - { - string ret; -// ret = CStepObjective::genPhrase(); - ret += _Phrase.genPhrase(); - ret += _PhraseYes.genPhrase(); - - return ret; - } - -}; -typedef CLinearDynChat TLinearDynChatFail; -REGISTER_STEP_INDIRECT(TLinearDynChatFail, "linear_dyn_chat_fail"); -typedef CLinearDynChat TLinearDynChatRetry; -REGISTER_STEP_INDIRECT(TLinearDynChatRetry, "linear_dyn_chat_retry"); -typedef CLinearDynChat TLinearDynChatContinue; -REGISTER_STEP_INDIRECT(TLinearDynChatContinue, "linear_dyn_chat_continue"); - -// /////// // -// STEP IF // -// /////// // - -CStepIf::CStepIf(CMissionData &md, IPrimitive *prim) : IStep(md, prim) -{ - if (prim->getNumChildren() != 2) - throw EParseException(prim, toString("step_if need two child primitive for 'not_ok' and 'ok' clause, found %u child", prim->getNumChildren()).c_str()); - - IPrimitive *notOk = const_cast(prim->getPrimitive("result_no")); - //prim->getChild(notOk, 0); - IPrimitive *ok = const_cast(prim->getPrimitive("result_yes")); - //prim->getChild(ok, 1); - - if (notOk == NULL) - throw EParseException(prim, "Can't find 'not ok' step branch"); - if (ok == NULL) - throw EParseException(prim, "Can't find 'ok' step branch"); - - string name; - notOk->getPropertyByName("class", name); - if (name != "result_no") - throw EParseException(prim, toString("first child must be of class 'result_no', found '%s' instead", name.c_str()).c_str()); - ok->getPropertyByName("class", name); - if (name != "result_yes") - throw EParseException(prim, toString("second child must be of class 'result_yes', found '%s' instead", name.c_str()).c_str()); - - // push in order : not ok, then ok - _SubBranchs.push_back(notOk); - _SubBranchs.push_back(ok); - - - string s = md.getProperty(prim, "condition_type", true, false); - if (s == "test_missions_done") - _IfType = it_mission_done; - else if (s == "test_skills_level") - _IfType = it_skills; - else if (s == "test_bricks_known") - _IfType = it_bricks; - else if (s == "test_sdb") - _IfType = it_sdb; - else if (s == "test_race") - _IfType = it_race; - else if (s == "test_cult") - _IfType = it_cult; - else if (s == "test_civ") - _IfType = it_civ; - else if (s == "test_faction_point") - _IfType = it_faction_point; - else if (s == "test_guild_civ") - _IfType = it_guild_civ; - else if (s == "test_guild_cult") - _IfType = it_guild_cult; - else if (s == "test_guild_fame") - _IfType = it_guild_fame; - else if (s == "test_no_trial") - _IfType = it_no_trial; - else if (s == "test_item_in_inv") - _IfType = it_item_in_inv; - else - throw EParseException(prim, "Unknow test type !"); - - _IfParams = md.getPropertyArray(prim, "test_parameters", true, false); -} - -TPrimitiveSet CStepIf::getSubBranchs() -{ - TPrimitiveSet vStepsToReturn; - for (uint i = 0; i < _SubBranchs.size(); ++i) - { - TPrimitiveSet childs; - { - TPrimitivePropertyPredicate pred("step_tag", "true"); - filterPrimitiveChilds(_SubBranchs[i], pred, childs); - } - for (uint j = 0; j < childs.size(); ++j) - vStepsToReturn.push_back(childs[j]); - } - return vStepsToReturn; -} - -void CStepIf::fillJump(CMissionData &md, set &jumpPoints) -{ - /*string *s; - TPrimitiveSet childs; - bool ret; - - filterPrimitiveChilds(_SubBranchs[1], TPrimitivePropertyPredicate("step_tag", "true"), childs); - if (!childs.empty()) - { - ret = childs[0]->getPropertyByName("name", s); - if (!ret) - throw EParseException(childs[0], "Can't find property 'name' in first step of 'ok' sub branch"); - - jumpPoints.insert(TJumpInfo(*s, "yes")); - } - - // insert link to 'no' step - childs.clear(); - filterPrimitiveChilds(_SubBranchs[0], TPrimitivePropertyPredicate("step_tag", "true"), childs); - if (!childs.empty()) - { - ret = childs[0]->getPropertyByName("name", s); - if (!ret) - throw EParseException(childs[0], "Can't find property 'name' in first step of 'not ok' sub branch"); - - jumpPoints.insert(TJumpInfo(*s, "no")); - }*/ -} - -string CStepIf::genCode(CMissionData &md) -{ - string ret; - - uint32 i; - - TPrimitiveSet childs; - vector yesSteps; - vector noSteps; - - // Get the 'yes branch' jump point - { - TPrimitivePropertyPredicate pred("step_tag", "true"); - filterPrimitiveChilds(_SubBranchs[1], pred, childs); - } - if (!childs.empty()) - { - for (i = 0; i < _SubSteps.size(); ++i) - if (std::find(childs.begin(), childs.end(), _SubSteps[i]->getPrimitive()) != childs.end()) - yesSteps.push_back(_SubSteps[i]); - - if (yesSteps.empty()) - { - string err = toString("In step '%s', can't find sub step in 'yes' sub branch", getStepName().c_str()); - throw EParseException(_SubBranchs[1]->getParent(), err.c_str()); - } - } - - // Get the 'no branch' jump point - childs.clear(); - { - TPrimitivePropertyPredicate pred("step_tag", "true"); - filterPrimitiveChilds(_SubBranchs[0], pred, childs); - } - if (!childs.empty()) - { - for (i = 0; i < _SubSteps.size(); ++i) - if (std::find(childs.begin(), childs.end(), _SubSteps[i]->getPrimitive()) != childs.end()) - noSteps.push_back(_SubSteps[i]); - - if (noSteps.empty()) - { - string err = toString("In step '%s', can't find sub step in 'no' sub branch", getStepName().c_str()); - throw EParseException(_SubBranchs[0]->getParent(), err.c_str()); - } - } - - if ((yesSteps.empty()) && (noSteps.empty())) - { - string err = toString("In step '%s', no yes-branch and no no-branch", getStepName().c_str()); - throw EParseException(_SubBranchs[0]->getParent(), err.c_str()); - } - - string jumpToYes; - if (!yesSteps.empty()) - jumpToYes = yesSteps[0]->getStepName(); - else - jumpToYes = getStepName() + "_endif"; - - - // type of IF: - switch(_IfType) - { - case it_mission_done: - if (_IfParams.empty()) - throw EParseException(_Primitive, "if_mission_done need at least one mission to test"); - for (uint i=0; i<_IfParams.size(); ++i) - ret += "if_mission_done : " + _IfParams[i] + " : " + jumpToYes + NL; - break; - case it_skills: - if (_IfParams.empty()) - throw EParseException(_Primitive, "if_skills need at least one to test"); - ret = "if_skills : "; - for (uint i=0; i<_IfParams.size(); ++i) - { - ret += _IfParams[i]; - if (i < _IfParams.size()-1) - ret += "; "; - } - ret += " : " + jumpToYes + NL; - break; - case it_bricks: - if (_IfParams.empty()) - throw EParseException(_Primitive, "if_bricks need at least one sbrick to test"); - ret = "if_bricks : "; - for (uint i=0; i<_IfParams.size(); ++i) - { - ret += _IfParams[i]; - if (i < _IfParams.size()-1) - ret += "; "; - } - ret += " : " + jumpToYes + NL; - break; - case it_sdb: - if (_IfParams.empty()) - throw EParseException(_Primitive, "if_sdb need an expression to test"); - ret = "if_sdb : "; - for (uint i=0; i<_IfParams.size(); ++i) - { - ret += _IfParams[i]; - if (i < _IfParams.size()-1) - ret += " "; - } - ret += " : " + jumpToYes + NL; - break; - case it_race: - if (_IfParams.empty()) - throw EParseException(_Primitive, "if_race need an expression to test"); - ret = "if_race : "; - for (uint i=0; i<_IfParams.size(); ++i) - { - ret += _IfParams[i]; - if (i < _IfParams.size()-1) - ret += " "; - } - ret += " : " + jumpToYes + NL; - break; - case it_cult: - if (_IfParams.empty()) - throw EParseException(_Primitive, "if_cult need an expression to test"); - ret = "if_cult : "; - for (uint i=0; i<_IfParams.size(); ++i) - { - ret += _IfParams[i]; - if (i < _IfParams.size()-1) - ret += " "; - } - ret += " : " + jumpToYes + NL; - break; - case it_civ: - if (_IfParams.empty()) - throw EParseException(_Primitive, "if_civ need an expression to test"); - ret = "if_civ : "; - for (uint i=0; i<_IfParams.size(); ++i) - { - ret += _IfParams[i]; - if (i < _IfParams.size()-1) - ret += " "; - } - ret += " : " + jumpToYes + NL; - break; - case it_faction_point: - if (_IfParams.empty()) - throw EParseException(_Primitive, "if_faction_point need an expression to test"); - ret = "if_faction_point : "; - for (uint i=0; i<_IfParams.size(); ++i) - { - ret += _IfParams[i]; - if (i < _IfParams.size()-1) - ret += " "; - } - ret += " : " + jumpToYes + NL; - break; - case it_guild_civ: - if (_IfParams.empty()) - throw EParseException(_Primitive, "it_guild_civ need an expression to test"); - ret = "if_guild_civ : "; - for (uint i=0; i<_IfParams.size(); ++i) - { - ret += _IfParams[i]; - if (i < _IfParams.size()-1) - ret += " "; - } - ret += " : " + jumpToYes + NL; - break; - case it_guild_cult: - if (_IfParams.empty()) - throw EParseException(_Primitive, "it_guild_cult need an expression to test"); - ret = "if_guild_cult : "; - for (uint i=0; i<_IfParams.size(); ++i) - { - ret += _IfParams[i]; - if (i < _IfParams.size()-1) - ret += " "; - } - ret += " : " + jumpToYes + NL; - break; - case it_guild_fame: - if (_IfParams.empty()) - throw EParseException(_Primitive, "it_guild_fame need an expression to test"); - ret = "if_guild_fame : "; - for (uint i=0; i<_IfParams.size(); ++i) - { - ret += _IfParams[i]; - if (i < _IfParams.size()-1) - ret += " "; - } - ret += " : " + jumpToYes + NL; - break; - case it_no_trial: - ret = "if_no_trial : " + jumpToYes + NL; - break; - case it_item_in_inv: - if (_IfParams.empty()) - throw EParseException(_Primitive, "if_item_in_inv need at least one mission to test"); - for (uint i=0; i<_IfParams.size(); ++i) - ret += "if_item_in_inv : " + _IfParams[i] + " : " + jumpToYes + NL; - break; - } - - // Generate the 'no branch' - - if (!noSteps.empty()) - { - ret += "# no: " + noSteps[0]->getStepName() + NL; - for (uint i = 0; i < noSteps.size(); ++i) - { - if ( md.isThereAJumpTo(noSteps[i]->getStepName()) ) - { - // insert a jump point - ret += "jump_point : " + noSteps[i]->getStepName() + NL; - } - - ret += noSteps[i]->genCode(md); - } - } - - // Generate the 'yes branch' - - if (!yesSteps.empty()) - { - ret += "jump : " + getStepName() + "_endif" + NL; - ret += "# yes: " + yesSteps[0]->getStepName() + NL; - - for (uint i = 0; i < yesSteps.size(); ++i) - { - if ((i == 0) || md.isThereAJumpTo(yesSteps[i]->getStepName()) ) - { - // insert a jump point - ret += "jump_point : " + yesSteps[i]->getStepName() + NL; - } - - ret += yesSteps[i]->genCode(md); - } - } - - // Generate ending jump point - - ret += "jump_point : " + getStepName() + "_endif" + NL; - - return ret; -} - -REGISTER_STEP_INDIRECT(CStepIf, "step_if"); - -// ////////////// // -// END OF STEP IF // -// ////////////// // - -class CStepOOO : public CStepObjective -{ -public: - CStepOOO(CMissionData &md, IPrimitive *prim) - : CStepObjective(md, prim) - { - } - - - string genCode(CMissionData &md) - { - string ret; - - ret += CStepObjective::genCode(md); - - ret += IStep::genCodePreActions(md); - - ret += "ooo" + NL; - - string tmp = IStep::genCodeObjectives(md); - tabulateLine(tmp, 1); - ret += tmp; - - ret += "/ooo"+NL; - - ret += genCodePostActions(md); - - return ret; - } - -}; -REGISTER_STEP_INDIRECT(CStepOOO, "step_ooo"); - -class CStepAny : public CStepObjective -{ -public: - CStepAny(CMissionData &md, IPrimitive *prim) - : CStepObjective(md, prim) - { - } - - string genCode(CMissionData &md) - { - string ret; - - ret += CStepObjective::genCode(md); - - ret += IStep::genCodePreActions(md); - - ret += "any" + NL; - - string tmp = IStep::genCodeObjectives(md); - tabulateLine(tmp, 1); - - ret += tmp; - - ret += "/any"+NL; - - ret += genCodePostActions(md); - - return ret; - } - -}; -REGISTER_STEP_INDIRECT(CStepAny, "step_any"); - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "mission_compiler.h" +#include "step.h" +#include "nel/misc/factory.h" +#include + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; + + +// ***** +// IStep +// ***** + +IStep *IStep::createStep(CMissionData &md, IPrimitive *prim) +{ + string *c; + if (!prim->getPropertyByName("class", c)) + throw EParseException(prim, "Can't find property 'class' on primitive"); + + IStep *ret = CFactoryIndirect::instance().getFactory(*c)->createStep(md, prim); + ret->init(md, prim); + + return ret; +}; + +IStep::IStep(CMissionData &md, NLLIGO::IPrimitive *prim) + : _Primitive(prim), + EndOfBranch(false), + JumpPoint(false) +{ + if (prim == NULL) + return; + + prim->getPropertyByName("class", _StepType); + prim->getPropertyByName("name", _StepName); + + // parse the sub prim to create action & objectives; + IPrimitive *child; + // parse the preactions + { + TPrimitiveClassAndNamePredicate pred("actions", "pre_actions"); + child = getPrimitiveChild(prim, pred); + } + + if (child) + { + for (uint i=0; igetNumChildren(); ++i) + { + IPrimitive *subChild; + child->getChild(subChild, i); + if (subChild) + { + // ok, we got one + IStepContent *sc = IStepContent::createStepContent(md, subChild); + if (sc) + _PreActions.push_back(sc); + } + } + } + // parse the objectives + { + TPrimitiveClassAndNamePredicate pred("mission_objectives", "objectives"); + child = getPrimitiveChild(prim, pred); + } + if (child) + { + for (uint i=0; igetNumChildren(); ++i) + { + IPrimitive *subChild; + child->getChild(subChild, i); + if (subChild) + { + // ok, we got one + IStepContent *sc = IStepContent::createStepContent(md, subChild); + if (sc) + _Objectives.push_back(sc); + } + } + } + // parse the post actions + { + TPrimitiveClassAndNamePredicate pred("actions", "post_actions"); + child = getPrimitiveChild(prim, pred); + } + if (child) + { + for (uint i=0; igetNumChildren(); ++i) + { + IPrimitive *subChild; + child->getChild(subChild, i); + if (subChild) + { + // ok, we got one + IStepContent *sc = IStepContent::createStepContent(md, subChild); + if (sc) + _PostActions.push_back(sc); + } + } + } +} + +void IStep::fillStepJump(CMissionData &md, std::set &jumpPoints) +{ + uint i; + // extract step content jump points + for (i=0; i<_PreActions.size(); ++i) + { + _PreActions[i]->fillJump(md, jumpPoints); + } + for (i=0; i<_Objectives.size(); ++i) + { + _Objectives[i]->fillJump(md, jumpPoints); + } + for (i=0; i<_PostActions.size(); ++i) + { + _PostActions[i]->fillJump(md, jumpPoints); + } + + fillJump(md, jumpPoints); + + for (i = 0; i < _SubSteps.size(); ++i) + if (_SubSteps[i] != NULL) + _SubSteps[i]->fillStepJump(md, jumpPoints); +} + + +void IStep::fillJump(CMissionData &md, std::set &jumpPoints) +{ + // jump to the next step + IStep *next = md.getNextStep(this); + + if (!EndOfBranch && next) + { + TJumpInfo ji(next->getStepName()); + jumpPoints.insert(ji); + } + else + { + TJumpInfo ji("__end__"); + jumpPoints.insert(ji); + } +} + +std::string IStep::genCode(CMissionData &md) +{ + string ret; + + ret += genCodePreActions(md); + ret += genCodeObjectives(md); + ret += genCodePostActions(md); + + return ret; +} + +std::string IStep::genCodePreActions(CMissionData &md) +{ + string ret; + // generate code for pre actions + for (uint i=0; i<_PreActions.size(); ++i) + { + ret += _PreActions[i]->genStepContentCode(md); + } + return ret; +} + +std::string IStep::genCodeObjectives(CMissionData &md) +{ + string ret; + // generate code for objectives + for (uint i=0; i<_Objectives.size(); ++i) + { + ret += _Objectives[i]->genStepContentCode(md); + } + return ret; +} + +std::string IStep::genCodePostActions(CMissionData &md) +{ + string ret; + //generate code for post actions + for (uint i=0; i<_PostActions.size(); ++i) + { + ret += _PostActions[i]->genStepContentCode(md); + } + return ret; +} + + +std::string IStep::genPhrase() +{ + string ret; + // generate code for pre actions + for (uint i=0; i<_PreActions.size(); ++i) + { + ret += _PreActions[i]->genStepContentPhrase(); + } + // generate code for objectives + for (uint i=0; i<_Objectives.size(); ++i) + { + ret += _Objectives[i]->genStepContentPhrase(); + } + //generate code for post actions + for (uint i=0; i<_PostActions.size(); ++i) + { + ret += _PostActions[i]->genStepContentPhrase(); + } + //generate code for sub steps + for (uint i=0; i<_SubSteps.size(); ++i) + { + ret += _SubSteps[i]->genPhrase(); + } + + return ret; +} + + +class CStep : public IStep +{ +public: + CStep(CMissionData &md, IPrimitive *prim) + : IStep(md, prim) + { + // nothing special to do + } + +}; +REGISTER_STEP_INDIRECT(CStep, "step"); + +class CStepObjective : public CStep +{ +public: + virtual void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + predef.clear(); + }; + + CStepObjective(CMissionData &md, IPrimitive *prim, const std::string &prefix = "") + : CStep(md, prim), + _HideObj(false), + _Prefix(prefix) + { + } + + void init(CMissionData &md, IPrimitive *prim) + { + _HideObj = md.getProperty(prim, _Prefix + "hide_obj", true, false) == "true"; + _OverloadObj = md.getPropertyArray(prim, _Prefix + "overload_objective", false, false); + _RoleplayObj = md.getPropertyArray(prim, _Prefix + "roleplay_objective", false, false); + uint32 numEntry; + CPhrase::TPredefParams params; + // ask derived class for predefined params + getPredefParam(numEntry, params); + _OverloadPhrase.initPhrase(md, prim, _OverloadObj, numEntry, params); + _RoleplayPhrase.initPhrase(md, prim, _RoleplayObj, numEntry, params); + } + + virtual bool isAction() { return true; } + + string genCode(CMissionData &md) + { + string ret; + if (_HideObj) + ret = "hide_obj" + NL; + if (!_OverloadObj.empty()) + { + ret += "set_obj : " + _OverloadPhrase.genScript(md) + NL; + } + if (!_RoleplayObj.empty()) + { + ret += "set_obj_rp : " + _RoleplayPhrase.genScript(md) + NL; + } + + return ret; + } + + string genPhrase() + { + string ret; + ret += _OverloadPhrase.genPhrase(); + ret += _RoleplayPhrase.genPhrase(); + + ret += IStep::genPhrase(); + + return ret; + } + +protected: + string _Prefix; + bool _HideObj; + vector _OverloadObj; + CPhrase _OverloadPhrase; + vector _RoleplayObj; + CPhrase _RoleplayPhrase; +}; + +class CStepDynChatTalkTo : public CStepObjective +{ +// string _BotNameVar; +// string _BotName; + TCompilerVarName _BotName; + CPhrase _Phrase; + + void getPredefParam(uint32 &numEntry, CPhrase::TPredefParams &predef) + { + numEntry = 0; + predef.resize(1); + predef[0].resize(1); + predef[0][0] = _BotName.getParamInfo(); +// if (_BotNameVar.empty()) +// predef[0][0] = CPhrase::TParamInfo("npc", STRING_MANAGER::bot); +// else +// predef[0][0] = CPhrase::TParamInfo(_BotNameVar, STRING_MANAGER::bot); + } +public: + CStepDynChatTalkTo(CMissionData &md, IPrimitive *prim, const std::string &prefix = "") + : CStepObjective(md, prim, prefix) + { + } + + void init(CMissionData &md, IPrimitive *prim) + { + _BotName.init("npc", STRING_MANAGER::bot, md, prim, "npc_name"); +// _BotNameVar = md.getProperty(prim, "npc_name", false, false); + // remove the variable tag if any +// untagVar(_BotNameVar); + +// _BotName = md.getProperty(prim, "npc_name", true, false); + vector vs; + vs = md.getPropertyArray(prim, "talk_to_menu", false, false); + CPhrase::TPredefParams pp(1); + pp[0].push_back(_BotName.getParamInfo()); +// if (_BotNameVar.empty()) +// pp[0].push_back(CPhrase::TParamInfo("npc", STRING_MANAGER::bot)); +// else +// pp[0].push_back(CPhrase::TParamInfo(_BotNameVar, STRING_MANAGER::bot)); + _Phrase.initPhrase(md, prim, vs, 0, pp); + +// _Phrase.initPhrase(md, prim, vs); + +// if (_Phrase.asAdditionnalParams()) +// { +// // we need to remove the default 'npc' parameter if add params are found +// CPhrase temp; +// temp.initPhrase(md, prim, vs); +// +// _Phrase = temp; +// } + CStepObjective::init(md, prim); + } + + string genCode(CMissionData &md) + { + string ret; + ret = CStepObjective::genCode(md); + + ret += "talk_to : "+_BotName._VarValue; + + if (!_Phrase.isEmpty()) + ret += " : "+_Phrase.genScript(md); + ret += NL; + + return ret; + } + + string genPhrase() + { + string ret; + ret = CStepObjective::genPhrase(); + ret += _Phrase.genPhrase(); + + return ret; + } +}; + +class CStepJump : public IStep +{ +public: + CStepJump(CMissionData &md, IPrimitive *prim) + : IStep(md, prim) + { + _StepName = md.getProperty(prim, "target", true, false); + } + + void fillJump(CMissionData &md, set &jumpPoints) + { + jumpPoints.insert(TJumpInfo(_StepName, "", false)); + } + + string genCode(CMissionData &md) + { + string ret; + + ret += "jump : " + _StepName + NL; + + return ret; + } + + bool isAJump() + { + return true; + } + + string _StepName; +}; +REGISTER_STEP_INDIRECT(CStepJump, "jump_to"); + +/// pseudo step used in step parsing +class CStepEnd : public IStep +{ +public: + CStepEnd(CMissionData &md, IPrimitive *prim) + : IStep(md, prim) + { + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "end"+NL; + + return ret; + } + + bool isEnd() { return true; } + +}; +REGISTER_STEP_INDIRECT(CStepEnd, "end"); + +class CStepFailure : public IStep +{ + // Optional jump at end of failure + string _JumpTo; +public: + CStepFailure(CMissionData &md, IPrimitive *prim) + : IStep(md, prim) + { + // parse the sub prim to create action & objectives; + IPrimitive *child; + // parse the pre-actions + { + TPrimitiveClassAndNamePredicate pred("actions", "actions"); + child = getPrimitiveChild(prim, pred); + } + if (child) + { + for (uint i=0; igetNumChildren(); ++i) + { + IPrimitive *subChild; + child->getChild(subChild, i); + if (subChild) + { + // ok, we got one + IStepContent *sc = IStepContent::createStepContent(md, subChild); + if (sc) + _PreActions.push_back(sc); + } + } + } + // look for an optional jump + { + TPrimitiveClassPredicate pred("jump_to"); + child = getPrimitiveChild(prim, pred); + } + if (child) + { + // ok, we have a jump at end of fail step + _JumpTo = md.getProperty(child, "target", true, false); + } + } + + string genCode(CMissionData &md) + { + string ret; + + ret = "failure" + NL; + + string tmp = IStep::genCode(md); + tabulateLine(tmp, 1); + ret += tmp; + + + if (!_JumpTo.empty()) + { + ret += "\tjump : "+_JumpTo + NL; + } + + ret += "/failure"+NL; + + return ret; + } + + void fillJump(CMissionData &md, set &jumpPoints) + { + IStep::fillJump(md, jumpPoints); + if (!_JumpTo.empty()) + jumpPoints.insert(TJumpInfo(_JumpTo)); + } + +}; +REGISTER_STEP_INDIRECT(CStepFailure, "step_failure"); + +class CStepCrash : public IStep +{ + // Optional jump at end of failure + string _JumpTo; + vector _AiInstances; +public: + CStepCrash(CMissionData &md, IPrimitive *prim) + : IStep(md, prim) + { + // parse the sub prim to create action & objectives; + IPrimitive *child; + // parse the pre-actions + { + TPrimitiveClassAndNamePredicate pred("actions", "actions"); + child = getPrimitiveChild(prim, pred); + } + if (child) + { + for (uint i=0; igetNumChildren(); ++i) + { + IPrimitive *subChild; + child->getChild(subChild, i); + if (subChild) + { + // ok, we got one + IStepContent *sc = IStepContent::createStepContent(md, subChild); + if (sc) + _PreActions.push_back(sc); + } + } + } + + // parse ai instance list + vector vs = md.getPropertyArray(prim, "ai_instances", true, false); +/* if (vs.size() == 0) + { + string err = toString("crash block need at least one ai instance !"); + throw EParseException(prim, err.c_str()); + } +*/ + for (uint i=0; i &jumpPoints) + { + IStep::fillJump(md, jumpPoints); + if (!_JumpTo.empty()) + jumpPoints.insert(TJumpInfo(_JumpTo)); + } + +}; +REGISTER_STEP_INDIRECT(CStepCrash, "step_crash"); + +// ///////////////////// // +// STEP PLAYER RECONNECT // +// ///////////////////// // + +// *************************************************************************** +CStepPlayerReconnect::CStepPlayerReconnect(CMissionData &md, IPrimitive *prim) : IStep(md, prim) +{ + // parse the sub prim to create action & objectives; + IPrimitive *child; + + TPrimitiveSet resp; + { + TPrimitivePropertyPredicate pred("step_tag", "true"); + filterPrimitiveChilds(prim, pred, resp); + } + for (uint i=0; igetStepName()) ) + { + // insert a jump point + ret += "jump_point : " + _SubSteps[i]->getStepName() + NL; + } + + ret += _SubSteps[i]->genCode(md); + } + + if (!_JumpTo.empty()) + { + ret += "\tjump : "+_JumpTo + NL; + } + + ret += "/player_reconnect"+NL; + + return ret; +} + +// *************************************************************************** +void CStepPlayerReconnect::fillJump(CMissionData &md, set &jumpPoints) +{ + IStep::fillJump(md, jumpPoints); + if (!_JumpTo.empty()) + jumpPoints.insert(TJumpInfo(_JumpTo)); +} + +REGISTER_STEP_INDIRECT(CStepPlayerReconnect, "step_player_reconnect"); + +// //////////////////////////// // +// END OF STEP PLAYER RECONNECT // +// //////////////////////////// // + +// *************************************************************************** +// get the jump point of a node. NB: if the node is itself a jump, then directly jump to its target +static std::string *getJumpTarget(IPrimitive *child) +{ + if(!child) + return NULL; + + // default: jump to the node + string *s= NULL; + child->getPropertyByName("name", s); + + // if the node is a jump itself + string *className= NULL; + child->getPropertyByName("class", className); + if (className && *className == "jump_to") + { + // generate jump to the step jump target + child->getPropertyByName("target", s); + } + + return s; +} + + +// *************************************************************************** +class CStepDynChat : public IStep +{ +public: + CStepDynChat(CMissionData &md, IPrimitive *prim) + : IStep(md, prim) + { + _BotName = md.getProperty(prim, "npc_name", true, false); + vector temp = md.getPropertyArray(prim, "phrase", false, false); + _Phrase.initPhrase(md, prim, temp); + // talk_to menu + temp = md.getPropertyArray(prim, "talk_to_menu", false, false); +// _TalkToMenu.initPhrase(md, prim, temp); + + _TalkToObjective = NULL; + std::auto_ptr talkToObjective; // next calls could throw exceptions, so take care... + if (!temp.empty()) + { + talkToObjective.reset(new CStepDynChatTalkTo(md, prim, "talk_to_")); + talkToObjective->init(md, prim); + } + + // build the sub branch list + IPrimitive *noResp; + { + TPrimitiveClassPredicate pred("no_answer"); + noResp = getPrimitiveChild(prim, pred); + } + nlassert(noResp); + _SubBranchs.push_back(noResp); + + TPrimitiveSet resp; + { + TPrimitiveClassPredicate pred("dyn_answer"); + filterPrimitiveChilds(prim, pred, resp); + } + _Responses.resize(resp.size()); + for (uint i=0; igetNumChildren() == 0) + throw EParseException(prim, "missing step under 'dyn_answer' node for response"); + + vector temp = md.getPropertyArray(resp[i], "phrase_answer", false, false); + _Responses[i].initPhrase(md, resp[i], temp); + } + _TalkToObjective = talkToObjective.release(); // commit result + } + ~CStepDynChat() + { + delete _TalkToObjective; + } + + TPrimitiveSet getSubBranchs() + { + TPrimitiveSet vStepsToReturn; + for (uint i = 0; i < _SubBranchs.size(); ++i) + { + TPrimitiveSet childs; + { + TPrimitivePropertyPredicate pred("step_tag", "true"); + filterPrimitiveChilds(_SubBranchs[i], pred, childs); + } + for (uint j = 0; j < childs.size(); ++j) + vStepsToReturn.push_back(childs[j]); + } + return vStepsToReturn; + } + + void fillJump(CMissionData &md, set &jumpPoints) + { + for (uint i=0; i<_SubBranchs.size(); ++i) + { + string *s; + IPrimitive *firstStep; + if (!_SubBranchs[i]->getChild(firstStep, 0)) + throw EParseException(_Primitive, toString("Can't find child in %uth sub branch", i+1).c_str()); + + bool ret = firstStep->getPropertyByName("name", s); + if (!ret) + throw EParseException(_Primitive, toString("Can't find property 'name' in %uth sub branch", i+1).c_str()); + + string label; + _SubBranchs[i]->getPropertyByName("name", label); + jumpPoints.insert(TJumpInfo(*s, label)); + } + } + + string genCode(CMissionData &md) + { + string ret; + + // if there's a talk_to menu, add it +// if (!_TalkToMenu.isEmpty()) + if (_TalkToObjective != NULL) + { + ret += _TalkToObjective->genCode(md); +// ret += "talk_to : "+_BotName; +// ret += " : " + _TalkToMenu.genScript(md); +// ret += NL; + } + + + ret += "dyn_chat : " + _BotName + " : " + _Phrase.genScript(md); + + for (uint i=1; i<_SubBranchs.size(); ++i) + { + IPrimitive *child; + _SubBranchs[i]->getChild(child, 0); + + // get the jump target + string *s= getJumpTarget(child); + + ret += " : " + *s + " " + _Responses[i-1].genScript(md); + } + + ret += NL; + + return ret; + } + + string genPhrase() + { + string ret; /* = CStepObjective::genPhrase();*/ + +// if (!_TalkToMenu.isEmpty()) + if (_TalkToObjective != NULL) + { + ret += _TalkToObjective->genPhrase(); +// ret += _TalkToMenu.genPhrase(); + } + + ret += _Phrase.genPhrase(); + + for (uint i=0; i<_Responses.size(); ++i) + { + ret += _Responses[i].genPhrase(); + } + return ret; + } + + /// the list of sub branch for the dyn chat. + TPrimitiveSet _SubBranchs; + // phrase for the main text + CPhrase _Phrase; + // list of phrase for each response + vector _Responses; + + string _BotName; + + // 'talk_to' part +// CPhrase _TalkToMenu; + CStepDynChatTalkTo *_TalkToObjective; + +}; +REGISTER_STEP_INDIRECT(CStepDynChat, "step_dyn_chat"); + +class CLinearDynChat : public IStep +{ + enum TLinearMode + { + mode_fail, + mode_retry, + mode_continue, +// mode_skipable + }; + + TLinearMode _Mode; + string _BotName; + CPhrase _Phrase; + CPhrase _PhraseYes; + + +public: + + + CLinearDynChat(CMissionData &md, IPrimitive *prim) + : IStep(md, prim) + { + _BotName = md.getProperty(prim, "npc_name", true, false); + vector temp = md.getPropertyArray(prim, "phrase", false, false); + _Phrase.initPhrase(md, prim, temp); + + // set the linear mode + string className; + prim->getPropertyByName("class", className); + + if (className == "linear_dyn_chat_fail") + _Mode = mode_fail; + else if (className == "linear_dyn_chat_retry") + _Mode = mode_retry; + else if (className == "linear_dyn_chat_continue") + _Mode = mode_continue; + else + { + string err = toString("Unknow class '%s' for dyn chat !", className.c_str()); + throw EParseException(prim, err.c_str()); + } + + // read the response phrase + vector phraseYes; + phraseYes = md.getPropertyArray(prim, "phrase_yes", false, false); + _PhraseYes.initPhrase(md, prim, phraseYes); + } + + string genCode(CMissionData &md) + { + string ret; + + switch (_Mode) + { + case mode_fail: + ret = "dyn_chat : "+_BotName+" : "+_Phrase.genScript(md)+" : "+_StepName+"_resp "+_PhraseYes.genScript(md)+NL; + ret += "fail"+NL; + ret += "jump_point : " +_StepName+"_resp"+NL; + break; + case mode_retry: + ret += "jump_point : " +_StepName+"_retry"+NL; + ret += "dyn_chat : "+_BotName+" : "+_Phrase.genScript(md)+" : "+_StepName+"_resp "+_PhraseYes.genScript(md)+NL; + ret += "jump : "+_StepName+"_retry"+NL; + ret += "jump_point : " +_StepName+"_resp"+NL; + break; + case mode_continue: + ret = "dyn_chat : "+_BotName+" : "+_Phrase.genScript(md)+" : "+_StepName+"_resp "+_PhraseYes.genScript(md)+NL; + ret += "jump_point : " +_StepName+"_resp"+NL; + break; + } + + return ret; + } + + string genPhrase() + { + string ret; +// ret = CStepObjective::genPhrase(); + ret += _Phrase.genPhrase(); + ret += _PhraseYes.genPhrase(); + + return ret; + } + +}; +typedef CLinearDynChat TLinearDynChatFail; +REGISTER_STEP_INDIRECT(TLinearDynChatFail, "linear_dyn_chat_fail"); +typedef CLinearDynChat TLinearDynChatRetry; +REGISTER_STEP_INDIRECT(TLinearDynChatRetry, "linear_dyn_chat_retry"); +typedef CLinearDynChat TLinearDynChatContinue; +REGISTER_STEP_INDIRECT(TLinearDynChatContinue, "linear_dyn_chat_continue"); + +// /////// // +// STEP IF // +// /////// // + +CStepIf::CStepIf(CMissionData &md, IPrimitive *prim) : IStep(md, prim) +{ + if (prim->getNumChildren() != 2) + throw EParseException(prim, toString("step_if need two child primitive for 'not_ok' and 'ok' clause, found %u child", prim->getNumChildren()).c_str()); + + IPrimitive *notOk = const_cast(prim->getPrimitive("result_no")); + //prim->getChild(notOk, 0); + IPrimitive *ok = const_cast(prim->getPrimitive("result_yes")); + //prim->getChild(ok, 1); + + if (notOk == NULL) + throw EParseException(prim, "Can't find 'not ok' step branch"); + if (ok == NULL) + throw EParseException(prim, "Can't find 'ok' step branch"); + + string name; + notOk->getPropertyByName("class", name); + if (name != "result_no") + throw EParseException(prim, toString("first child must be of class 'result_no', found '%s' instead", name.c_str()).c_str()); + ok->getPropertyByName("class", name); + if (name != "result_yes") + throw EParseException(prim, toString("second child must be of class 'result_yes', found '%s' instead", name.c_str()).c_str()); + + // push in order : not ok, then ok + _SubBranchs.push_back(notOk); + _SubBranchs.push_back(ok); + + + string s = md.getProperty(prim, "condition_type", true, false); + if (s == "test_missions_done") + _IfType = it_mission_done; + else if (s == "test_skills_level") + _IfType = it_skills; + else if (s == "test_bricks_known") + _IfType = it_bricks; + else if (s == "test_sdb") + _IfType = it_sdb; + else if (s == "test_race") + _IfType = it_race; + else if (s == "test_cult") + _IfType = it_cult; + else if (s == "test_civ") + _IfType = it_civ; + else if (s == "test_faction_point") + _IfType = it_faction_point; + else if (s == "test_guild_civ") + _IfType = it_guild_civ; + else if (s == "test_guild_cult") + _IfType = it_guild_cult; + else if (s == "test_guild_fame") + _IfType = it_guild_fame; + else if (s == "test_no_trial") + _IfType = it_no_trial; + else if (s == "test_item_in_inv") + _IfType = it_item_in_inv; + else + throw EParseException(prim, "Unknow test type !"); + + _IfParams = md.getPropertyArray(prim, "test_parameters", true, false); +} + +TPrimitiveSet CStepIf::getSubBranchs() +{ + TPrimitiveSet vStepsToReturn; + for (uint i = 0; i < _SubBranchs.size(); ++i) + { + TPrimitiveSet childs; + { + TPrimitivePropertyPredicate pred("step_tag", "true"); + filterPrimitiveChilds(_SubBranchs[i], pred, childs); + } + for (uint j = 0; j < childs.size(); ++j) + vStepsToReturn.push_back(childs[j]); + } + return vStepsToReturn; +} + +void CStepIf::fillJump(CMissionData &md, set &jumpPoints) +{ + /*string *s; + TPrimitiveSet childs; + bool ret; + + filterPrimitiveChilds(_SubBranchs[1], TPrimitivePropertyPredicate("step_tag", "true"), childs); + if (!childs.empty()) + { + ret = childs[0]->getPropertyByName("name", s); + if (!ret) + throw EParseException(childs[0], "Can't find property 'name' in first step of 'ok' sub branch"); + + jumpPoints.insert(TJumpInfo(*s, "yes")); + } + + // insert link to 'no' step + childs.clear(); + filterPrimitiveChilds(_SubBranchs[0], TPrimitivePropertyPredicate("step_tag", "true"), childs); + if (!childs.empty()) + { + ret = childs[0]->getPropertyByName("name", s); + if (!ret) + throw EParseException(childs[0], "Can't find property 'name' in first step of 'not ok' sub branch"); + + jumpPoints.insert(TJumpInfo(*s, "no")); + }*/ +} + +string CStepIf::genCode(CMissionData &md) +{ + string ret; + + uint32 i; + + TPrimitiveSet childs; + vector yesSteps; + vector noSteps; + + // Get the 'yes branch' jump point + { + TPrimitivePropertyPredicate pred("step_tag", "true"); + filterPrimitiveChilds(_SubBranchs[1], pred, childs); + } + if (!childs.empty()) + { + for (i = 0; i < _SubSteps.size(); ++i) + if (std::find(childs.begin(), childs.end(), _SubSteps[i]->getPrimitive()) != childs.end()) + yesSteps.push_back(_SubSteps[i]); + + if (yesSteps.empty()) + { + string err = toString("In step '%s', can't find sub step in 'yes' sub branch", getStepName().c_str()); + throw EParseException(_SubBranchs[1]->getParent(), err.c_str()); + } + } + + // Get the 'no branch' jump point + childs.clear(); + { + TPrimitivePropertyPredicate pred("step_tag", "true"); + filterPrimitiveChilds(_SubBranchs[0], pred, childs); + } + if (!childs.empty()) + { + for (i = 0; i < _SubSteps.size(); ++i) + if (std::find(childs.begin(), childs.end(), _SubSteps[i]->getPrimitive()) != childs.end()) + noSteps.push_back(_SubSteps[i]); + + if (noSteps.empty()) + { + string err = toString("In step '%s', can't find sub step in 'no' sub branch", getStepName().c_str()); + throw EParseException(_SubBranchs[0]->getParent(), err.c_str()); + } + } + + if ((yesSteps.empty()) && (noSteps.empty())) + { + string err = toString("In step '%s', no yes-branch and no no-branch", getStepName().c_str()); + throw EParseException(_SubBranchs[0]->getParent(), err.c_str()); + } + + string jumpToYes; + if (!yesSteps.empty()) + jumpToYes = yesSteps[0]->getStepName(); + else + jumpToYes = getStepName() + "_endif"; + + + // type of IF: + switch(_IfType) + { + case it_mission_done: + if (_IfParams.empty()) + throw EParseException(_Primitive, "if_mission_done need at least one mission to test"); + for (uint i=0; i<_IfParams.size(); ++i) + ret += "if_mission_done : " + _IfParams[i] + " : " + jumpToYes + NL; + break; + case it_skills: + if (_IfParams.empty()) + throw EParseException(_Primitive, "if_skills need at least one to test"); + ret = "if_skills : "; + for (uint i=0; i<_IfParams.size(); ++i) + { + ret += _IfParams[i]; + if (i < _IfParams.size()-1) + ret += "; "; + } + ret += " : " + jumpToYes + NL; + break; + case it_bricks: + if (_IfParams.empty()) + throw EParseException(_Primitive, "if_bricks need at least one sbrick to test"); + ret = "if_bricks : "; + for (uint i=0; i<_IfParams.size(); ++i) + { + ret += _IfParams[i]; + if (i < _IfParams.size()-1) + ret += "; "; + } + ret += " : " + jumpToYes + NL; + break; + case it_sdb: + if (_IfParams.empty()) + throw EParseException(_Primitive, "if_sdb need an expression to test"); + ret = "if_sdb : "; + for (uint i=0; i<_IfParams.size(); ++i) + { + ret += _IfParams[i]; + if (i < _IfParams.size()-1) + ret += " "; + } + ret += " : " + jumpToYes + NL; + break; + case it_race: + if (_IfParams.empty()) + throw EParseException(_Primitive, "if_race need an expression to test"); + ret = "if_race : "; + for (uint i=0; i<_IfParams.size(); ++i) + { + ret += _IfParams[i]; + if (i < _IfParams.size()-1) + ret += " "; + } + ret += " : " + jumpToYes + NL; + break; + case it_cult: + if (_IfParams.empty()) + throw EParseException(_Primitive, "if_cult need an expression to test"); + ret = "if_cult : "; + for (uint i=0; i<_IfParams.size(); ++i) + { + ret += _IfParams[i]; + if (i < _IfParams.size()-1) + ret += " "; + } + ret += " : " + jumpToYes + NL; + break; + case it_civ: + if (_IfParams.empty()) + throw EParseException(_Primitive, "if_civ need an expression to test"); + ret = "if_civ : "; + for (uint i=0; i<_IfParams.size(); ++i) + { + ret += _IfParams[i]; + if (i < _IfParams.size()-1) + ret += " "; + } + ret += " : " + jumpToYes + NL; + break; + case it_faction_point: + if (_IfParams.empty()) + throw EParseException(_Primitive, "if_faction_point need an expression to test"); + ret = "if_faction_point : "; + for (uint i=0; i<_IfParams.size(); ++i) + { + ret += _IfParams[i]; + if (i < _IfParams.size()-1) + ret += " "; + } + ret += " : " + jumpToYes + NL; + break; + case it_guild_civ: + if (_IfParams.empty()) + throw EParseException(_Primitive, "it_guild_civ need an expression to test"); + ret = "if_guild_civ : "; + for (uint i=0; i<_IfParams.size(); ++i) + { + ret += _IfParams[i]; + if (i < _IfParams.size()-1) + ret += " "; + } + ret += " : " + jumpToYes + NL; + break; + case it_guild_cult: + if (_IfParams.empty()) + throw EParseException(_Primitive, "it_guild_cult need an expression to test"); + ret = "if_guild_cult : "; + for (uint i=0; i<_IfParams.size(); ++i) + { + ret += _IfParams[i]; + if (i < _IfParams.size()-1) + ret += " "; + } + ret += " : " + jumpToYes + NL; + break; + case it_guild_fame: + if (_IfParams.empty()) + throw EParseException(_Primitive, "it_guild_fame need an expression to test"); + ret = "if_guild_fame : "; + for (uint i=0; i<_IfParams.size(); ++i) + { + ret += _IfParams[i]; + if (i < _IfParams.size()-1) + ret += " "; + } + ret += " : " + jumpToYes + NL; + break; + case it_no_trial: + ret = "if_no_trial : " + jumpToYes + NL; + break; + case it_item_in_inv: + if (_IfParams.empty()) + throw EParseException(_Primitive, "if_item_in_inv need at least one mission to test"); + for (uint i=0; i<_IfParams.size(); ++i) + ret += "if_item_in_inv : " + _IfParams[i] + " : " + jumpToYes + NL; + break; + } + + // Generate the 'no branch' + + if (!noSteps.empty()) + { + ret += "# no: " + noSteps[0]->getStepName() + NL; + for (uint i = 0; i < noSteps.size(); ++i) + { + if ( md.isThereAJumpTo(noSteps[i]->getStepName()) ) + { + // insert a jump point + ret += "jump_point : " + noSteps[i]->getStepName() + NL; + } + + ret += noSteps[i]->genCode(md); + } + } + + // Generate the 'yes branch' + + if (!yesSteps.empty()) + { + ret += "jump : " + getStepName() + "_endif" + NL; + ret += "# yes: " + yesSteps[0]->getStepName() + NL; + + for (uint i = 0; i < yesSteps.size(); ++i) + { + if ((i == 0) || md.isThereAJumpTo(yesSteps[i]->getStepName()) ) + { + // insert a jump point + ret += "jump_point : " + yesSteps[i]->getStepName() + NL; + } + + ret += yesSteps[i]->genCode(md); + } + } + + // Generate ending jump point + + ret += "jump_point : " + getStepName() + "_endif" + NL; + + return ret; +} + +REGISTER_STEP_INDIRECT(CStepIf, "step_if"); + +// ////////////// // +// END OF STEP IF // +// ////////////// // + +class CStepOOO : public CStepObjective +{ +public: + CStepOOO(CMissionData &md, IPrimitive *prim) + : CStepObjective(md, prim) + { + } + + + string genCode(CMissionData &md) + { + string ret; + + ret += CStepObjective::genCode(md); + + ret += IStep::genCodePreActions(md); + + ret += "ooo" + NL; + + string tmp = IStep::genCodeObjectives(md); + tabulateLine(tmp, 1); + ret += tmp; + + ret += "/ooo"+NL; + + ret += genCodePostActions(md); + + return ret; + } + +}; +REGISTER_STEP_INDIRECT(CStepOOO, "step_ooo"); + +class CStepAny : public CStepObjective +{ +public: + CStepAny(CMissionData &md, IPrimitive *prim) + : CStepObjective(md, prim) + { + } + + string genCode(CMissionData &md) + { + string ret; + + ret += CStepObjective::genCode(md); + + ret += IStep::genCodePreActions(md); + + ret += "any" + NL; + + string tmp = IStep::genCodeObjectives(md); + tabulateLine(tmp, 1); + + ret += tmp; + + ret += "/any"+NL; + + ret += genCodePostActions(md); + + return ret; + } + +}; +REGISTER_STEP_INDIRECT(CStepAny, "step_any"); + diff --git a/code/ryzom/tools/leveldesign/mission_compiler_lib/variables.cpp b/code/ryzom/tools/leveldesign/mission_compiler_lib/variables.cpp index d4e1e4598..853d487ba 100644 --- a/code/ryzom/tools/leveldesign/mission_compiler_lib/variables.cpp +++ b/code/ryzom/tools/leveldesign/mission_compiler_lib/variables.cpp @@ -1,707 +1,707 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "mission_compiler.h" - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; - - -class IVarFactory -{ -public: - virtual IVar *createVar(CMissionData &md, IPrimitive *prim) = 0; - -}; - -template -class CVarFactory : public IVarFactory -{ - IVar *createVar(CMissionData &md, IPrimitive *prim) - { - return new VarClass(md, prim); - } -}; - -#define REGISTER_VAR_INDIRECT(varClass, key) typedef CVarFactory TVarFactory##varClass; \ - NLMISC_REGISTER_OBJECT_INDIRECT(IVarFactory, TVarFactory##varClass, string, string(key)); - - -//#define REGISTER_VARIABLE(className, varName) NLMISC_REGISTER_OBJECT(IVar, className, std::string, string(varName)); - -/* Class for npc variable */ -class CVarNpc : public IVar -{ -public: - CVarNpc(CMissionData &md, IPrimitive *prim) - : IVar(vt_npc, prim) - { - _NpcLabel = getPrimProperty(prim, "npc_name"); - _NpcFunction = getPrimProperty(prim, "npc_function"); - if (!_NpcFunction.empty()) - { - _NpcFunction = "$"+_NpcFunction+"$"; - } - - IVar *nameVar = CFactoryIndirect::instance().getFactory("var_npc_name")->createVar(md, prim); - md.addVariable(prim, nameVar); - } - - const std::string getNpcLabel() - { - return _NpcLabel; - } - const std::string getNpcFunction() - { - return _NpcFunction; - } - const std::string getNpcFullName() - { - return _NpcLabel+_NpcFunction; - } - - string evalVar(const string &subPart) - { - if (subPart == "fullname") - return getNpcFullName(); - else if (subPart == "function") - return _NpcFunction; - else if (subPart == "") - return _NpcLabel; - - throw EParseException(NULL, toString("var_npc don't have a subpart '%s'", subPart.c_str()).c_str()); - } - - STRING_MANAGER::TParamType getStringManagerType() - { - return STRING_MANAGER::bot; - } - - string genDecl(CMissionData &md) - { - return "decl : bot : "+evalVar("")+NL; - } -private: - string _NpcLabel; - string _NpcFunction; -}; - -REGISTER_VAR_INDIRECT(CVarNpc, "var_npc"); - -/** Var for npc name (aka bot_name) - * This class is implicitly instancied by - * CVarNpc. - */ -class CVarNpcName : public IVar -{ -public: - CVarNpcName(CMissionData &md, IPrimitive *prim) - : IVar(vt_npc, prim) - { - // Change the var name - _VarName += "_name"; - _NpcLabel = getPrimProperty(prim, "npc_name"); - _NpcFunction = getPrimProperty(prim, "npc_function"); - if (!_NpcFunction.empty()) - { - _NpcFunction = "$"+_NpcFunction+"$"; - } - } - - const std::string getNpcLabel() - { - return _NpcLabel; - } - const std::string getNpcFunction() - { - return _NpcFunction; - } - const std::string getNpcFullName() - { - return _NpcLabel+_NpcFunction; - } - - string evalVar(const string &subPart) - { - if (subPart == "") - return string("\"")+_NpcLabel+"\""; - - throw EParseException(NULL, toString("var_npc_name don't have a subpart '%s'", subPart.c_str()).c_str()); - } - - STRING_MANAGER::TParamType getStringManagerType() - { - return STRING_MANAGER::bot_name; - } - - string genDecl(CMissionData &md) - { - return string(); - } - -private: - string _NpcLabel; - string _NpcFunction; -}; -REGISTER_VAR_INDIRECT(CVarNpcName, "var_npc_name"); - -/* Class for npc variable */ -class CVarGroup : public IVar -{ -public: - CVarGroup(CMissionData &md, IPrimitive *prim) - : IVar(vt_npc, prim) - { - _GroupName = getPrimProperty(prim, "group_name"); - } - - string evalVar(const string &subPart) - { - if (subPart.empty()) - return _GroupName; - else if (subPart == "quoted") - return string("\"")+_GroupName+"\""; - else - nlassert(false); - return ""; - } - - STRING_MANAGER::TParamType getStringManagerType() - { - return STRING_MANAGER::bot_name; - } - - string genDecl(CMissionData &md) - { -// return "decl : bot : "+evalVar("no_quote")+NL; - return "decl : bot : "+evalVar("")+NL; - } -private: - string _GroupName; -}; - -REGISTER_VAR_INDIRECT(CVarGroup, "var_group"); -//NLMISC_REGISTER_OBJECT(IVar, CVarGroup, std::string, string("var_group")); - - -/* Class for item */ -class CVarItem : public IVar -{ -public: - CVarItem(CMissionData &md, IPrimitive *prim) - : IVar(vt_item, prim) - { - _ItemSheet = getPrimProperty(prim, "item_sheet"); - } - - const std::string getItemSheet() - { - return _ItemSheet; - } - - string evalVar(const string &subPart) - { - nlassert(subPart.empty()); - return _ItemSheet; - } - - STRING_MANAGER::TParamType getStringManagerType() - { - return STRING_MANAGER::item; - } - - string genDecl(CMissionData &md) - { - return "decl : item : "+evalVar("")+NL; - } -private: - string _ItemSheet; -}; - -REGISTER_VAR_INDIRECT(CVarItem, "var_item"); -//NLMISC_REGISTER_OBJECT(IVar, CVarItem, std::string, string("var_item")); - - -/* Class for race */ -class CVarRace : public IVar -{ -public: - CVarRace(CMissionData &md, IPrimitive *prim) - : IVar(vt_item, prim) - { - _Race = getPrimProperty(prim, "race"); - } - - string evalVar(const string &subPart) - { - nlassert(subPart.empty()); - return _Race; - } - - STRING_MANAGER::TParamType getStringManagerType() - { - return STRING_MANAGER::race; - } - - string genDecl(CMissionData &md) - { - return "decl : race : "+evalVar("")+NL; - } -private: - string _Race; -}; - -REGISTER_VAR_INDIRECT(CVarRace, "var_race"); - -/* Class for sphrase */ -class CVarSPhrase : public IVar -{ -public: - CVarSPhrase(CMissionData &md, IPrimitive *prim) - : IVar(vt_item, prim) - { - _SPhrase = getPrimProperty(prim, "sphrase_sheet"); - } - - string evalVar(const string &subPart) - { - nlassert(subPart.empty()); - return _SPhrase; - } - - STRING_MANAGER::TParamType getStringManagerType() - { - return STRING_MANAGER::sphrase; - } - - string genDecl(CMissionData &md) - { - return "decl : sphrase : "+evalVar("")+NL; - } -private: - string _SPhrase; -}; - -REGISTER_VAR_INDIRECT(CVarSPhrase, "var_sphrase"); - -/* Class for sbrick */ -class CVarSBrick : public IVar -{ -public: - CVarSBrick(CMissionData &md, IPrimitive *prim) - : IVar(vt_item, prim) - { - _SBrick = getPrimProperty(prim, "sbrick_sheet"); - } - - string evalVar(const string &subPart) - { - nlassert(subPart.empty()); - return _SBrick; - } - - STRING_MANAGER::TParamType getStringManagerType() - { - return STRING_MANAGER::sbrick; - } - - string genDecl(CMissionData &md) - { - return "decl : sbrick : "+evalVar("")+NL; - } -private: - string _SBrick; -}; - -REGISTER_VAR_INDIRECT(CVarSBrick, "var_sbrick"); - - -/* for special item */ -char *SpecialItemProp[] = -{ - "Durability", - "Weight", - "SapLoad", - "Dmg", - "Speed", - "Range", - "DodgeModifier", - "ParryModifier", - "AdversaryDodgeModifier", - "AdversaryParryModifier", - "ProtectionFactor", - "MaxSlashingProtection", - "MaxBluntProtection", - "MaxPiercingProtection", - "HpBuff", - "SapBuff", - "StaBuff", - "FocusBuff" -}; - -struct TItemProperty -{ - string PropName; - string PropValue; -}; - -/* Class for special item */ -class CVarSpecialItem : public IVar -{ -public: - CVarSpecialItem(CMissionData &md, IPrimitive *prim) - : IVar(vt_item, prim) - { - static bool init = false; - static set propertyNames; - - if (!init) - { - for (uint i=0; i vs; - vs = getPrimPropertyArray(prim, "properties/values"); - // parse the strings vector - for (uint i=0; i parts; - explode(vs[i], string(" "), parts, true); - if (!parts.empty() && parts.size() != 2) - { - string s = toString("Invalid special item property at line %u", i+1); - throw EParseException(prim, s.c_str()); - } - - if (parts.size() == 2) - { - TItemProperty ip; - ip.PropName = parts[0]; - ip.PropValue = parts[1]; - - if (propertyNames.find(ip.PropName) == propertyNames.end()) - { - string s = toString("Invalid property name '%s'", ip.PropName.c_str()); - throw EParseException(prim, s.c_str()); - } - - _Properties.push_back(ip); - } - } - _Action = getPrimProperty(prim, "item_action"); - vs.clear(); - vs = getPrimPropertyArray(prim, "phrase_item_name"); - _ItemPhrase.initPhrase(md, prim, vs); - - string s; - s = getPrimProperty(prim, "no_drop"); - _NoDrop = (s == "true"); - } - -// const std::string getItemSheet() -// { -// return _ItemSheet; -// } - - string evalVar(const string &subPart) - { - nlassert(subPart.empty()); - return _VarName; - } - - STRING_MANAGER::TParamType getStringManagerType() - { - return STRING_MANAGER::item; - } - - string genDecl(CMissionData &md) - { - string ret = string("decl_item : ")+_VarName+" : "+_ItemSheet+" : "+_ReqSkill; - if (!_Properties.empty() ||!_Action.empty()) - ret += " : "; - for (uint i=0; i<_Properties.size(); ++i) - { - TItemProperty &ip = _Properties[i]; - ret += ip.PropName+" "+ip.PropValue; - if (i < _Properties.size()-1 || !_Action.empty()) - ret += "; "; - } - - if (!_Action.empty()) - ret += _Action; - - ret += " : "+_ItemPhrase.genScript(md); - - if (_NoDrop) - ret += " : no_drop"; - - ret += NL; - - return ret; - } - - std::string genPhrase() - { - return _ItemPhrase.genPhrase(); - } - - -private: - /// the item sheet used as base for this special item - string _ItemSheet; - /// The skill required to use the item - string _ReqSkill; - /// The list of properties - vector _Properties; - // Optional action (enchantement) - string _Action; - // Name of the item - CPhrase _ItemPhrase; - // No drop flag - bool _NoDrop; - - string _Color; - -}; - -REGISTER_VAR_INDIRECT(CVarSpecialItem, "var_special_item"); -//NLMISC_REGISTER_OBJECT(IVar, CVarSpecialItem, std::string, string("var_special_item")); - -/* Class for place variable */ -class CVarPlace : public IVar -{ -public: - CVarPlace(CMissionData &md, IPrimitive *prim) - : IVar(vt_npc, prim) - { - _PlaceLabel = getPrimProperty(prim, "place_name"); - } - -/* const std::string getPlaceLabel() - { - return _PlaceLabel; - } -*/ - string evalVar(const string &subPart) - { - nlassert(subPart.empty()); - return _PlaceLabel; - } - - STRING_MANAGER::TParamType getStringManagerType() - { - return STRING_MANAGER::place; - } - - string genDecl(CMissionData &md) - { - return "decl : place : "+evalVar("")+NL; - } - -private: - string _PlaceLabel; -}; -REGISTER_VAR_INDIRECT(CVarPlace, "var_place"); -//NLMISC_REGISTER_OBJECT(IVar, CVarPlace, std::string, string("var_place")); - -/* Class for integer variable */ -class CVarInteger : public IVar -{ -public: - CVarInteger(CMissionData &md, IPrimitive *prim) - : IVar(vt_integer, prim) - { - if (prim->checkProperty("value")) - _Value = getPrimProperty(prim, "value"); - else if (prim->checkProperty("quantity")) - _Value = getPrimProperty(prim, "quantity"); - else if (prim->checkProperty("quality")) - _Value = getPrimProperty(prim, "quality"); - else - { - string err = toString("Can't find a valid property for integer variable"); - throw EParseException(prim, err.c_str()); - } - } - - const std::string getIntegerValue() - { - return _Value; - } - - string evalVar(const string &subPart) - { - nlassert(subPart.empty()); - return _Value;; - } - - STRING_MANAGER::TParamType getStringManagerType() - { - return STRING_MANAGER::integer; - } - - string genDecl(CMissionData &md) - { - // nothing to declare for this pseudo var - return string(); - } -private: - string _Value; -}; -REGISTER_VAR_INDIRECT(CVarInteger, "var_integer"); -//NLMISC_REGISTER_OBJECT(IVar, CVarInteger, std::string, string("var_integer")); -typedef CVarInteger CVarQuantity; -REGISTER_VAR_INDIRECT(CVarQuantity, "var_quantity"); -//NLMISC_REGISTER_OBJECT(IVar, CVarQuantity, std::string, string("var_quantity")); -typedef CVarInteger CVarQuality; -REGISTER_VAR_INDIRECT(CVarQuality, "var_quality"); -//NLMISC_REGISTER_OBJECT(IVar, CVarQuality, std::string, string("var_quality")); - - -/* Class for text var */ -class CVarText : public IVar -{ -public: - CVarText(CMissionData &md, IPrimitive *prim) - : IVar(vt_item, prim) - { - _TextValue = getPrimPropertyArray(prim, "text"); - } - - const vector &getText() - { - return _TextValue;; - } - - string evalVar(const string &subPart) - { - nlassert(subPart.empty()); - string t; - return std::accumulate(_TextValue.begin(), _TextValue.end(), string("")); - return t; - } - - STRING_MANAGER::TParamType getStringManagerType() - { - nlassert(false); - return STRING_MANAGER::NB_PARAM_TYPES; - } - - string genDecl(CMissionData &md) - { - // nothing to declare for this one - return string(); - } -private: - vector _TextValue; -}; -REGISTER_VAR_INDIRECT(CVarText, "var_text"); -//NLMISC_REGISTER_OBJECT(IVar, CVarText, std::string, string("var_text")); - -/* Class for creature var */ -class CVarCreature : public IVar -{ -public: - CVarCreature(CMissionData &md, IPrimitive *prim) - : IVar(vt_item, prim) - { - _CreatureSheet = getPrimProperty(prim, "creature_sheet"); - } - - string evalVar(const string &subPart) - { - nlassert(subPart.empty()); - return _CreatureSheet; - } - - STRING_MANAGER::TParamType getStringManagerType() - { -// return STRING_MANAGER::creature; - return STRING_MANAGER::creature_model; - } - - string genDecl(CMissionData &md) - { - // declare a creature sheet -// return "decl : creature : "+_CreatureSheet+NL; - return "decl : creature_model : "+_CreatureSheet+NL; - } -private: - string _CreatureSheet; -}; -REGISTER_VAR_INDIRECT(CVarCreature, "var_creature"); -//NLMISC_REGISTER_OBJECT(IVar, CVarCreature, std::string, string("var_creature")); - -/* Class for faction var */ -class CVarFaction : public IVar -{ -public: - CVarFaction(CMissionData &md, IPrimitive *prim) - : IVar(vt_item, prim) - { - _FactionName = getPrimProperty(prim, "faction_name"); - } - - string evalVar(const string &subPart) - { - nlassert(subPart.empty()); - return _FactionName; - } - - STRING_MANAGER::TParamType getStringManagerType() - { - return STRING_MANAGER::faction; - } - - string genDecl(CMissionData &md) - { - // declare a creature sheet - return "decl : faction : "+_FactionName+NL; - } -private: - string _FactionName; -}; -REGISTER_VAR_INDIRECT(CVarFaction, "var_faction"); -//NLMISC_REGISTER_OBJECT(IVar, CVarFaction, std::string, string("var_faction")); - -// Variable factory. -IVar *IVar::createVar(CMissionData &md, IPrimitive *prim) -{ - string *c; - if (!prim->getPropertyByName("class", c)) - throw EParseException(prim, "Can't find property 'class' on primitive"); - - return CFactoryIndirect::instance().getFactory(*c)->createVar(md, prim); - - return NULL; -}; -//IVar *IVar::createVar(CMissionData &md, IPrimitive *prim) -//{ -// string *className; -// if (!prim->getPropertyByName("class", className)) -// throw EParseException(prim, "Can't find property 'class' in primitive"); -// -// IVar *ret = NLMISC_GET_FACTORY_INDIRECT(IVar, std::string).createObject(md, *className, prim); -// -// return ret; -//} -// +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "mission_compiler.h" + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; + + +class IVarFactory +{ +public: + virtual IVar *createVar(CMissionData &md, IPrimitive *prim) = 0; + +}; + +template +class CVarFactory : public IVarFactory +{ + IVar *createVar(CMissionData &md, IPrimitive *prim) + { + return new VarClass(md, prim); + } +}; + +#define REGISTER_VAR_INDIRECT(varClass, key) typedef CVarFactory TVarFactory##varClass; \ + NLMISC_REGISTER_OBJECT_INDIRECT(IVarFactory, TVarFactory##varClass, string, string(key)); + + +//#define REGISTER_VARIABLE(className, varName) NLMISC_REGISTER_OBJECT(IVar, className, std::string, string(varName)); + +/* Class for npc variable */ +class CVarNpc : public IVar +{ +public: + CVarNpc(CMissionData &md, IPrimitive *prim) + : IVar(vt_npc, prim) + { + _NpcLabel = getPrimProperty(prim, "npc_name"); + _NpcFunction = getPrimProperty(prim, "npc_function"); + if (!_NpcFunction.empty()) + { + _NpcFunction = "$"+_NpcFunction+"$"; + } + + IVar *nameVar = CFactoryIndirect::instance().getFactory("var_npc_name")->createVar(md, prim); + md.addVariable(prim, nameVar); + } + + const std::string getNpcLabel() + { + return _NpcLabel; + } + const std::string getNpcFunction() + { + return _NpcFunction; + } + const std::string getNpcFullName() + { + return _NpcLabel+_NpcFunction; + } + + string evalVar(const string &subPart) + { + if (subPart == "fullname") + return getNpcFullName(); + else if (subPart == "function") + return _NpcFunction; + else if (subPart == "") + return _NpcLabel; + + throw EParseException(NULL, toString("var_npc don't have a subpart '%s'", subPart.c_str()).c_str()); + } + + STRING_MANAGER::TParamType getStringManagerType() + { + return STRING_MANAGER::bot; + } + + string genDecl(CMissionData &md) + { + return "decl : bot : "+evalVar("")+NL; + } +private: + string _NpcLabel; + string _NpcFunction; +}; + +REGISTER_VAR_INDIRECT(CVarNpc, "var_npc"); + +/** Var for npc name (aka bot_name) + * This class is implicitly instancied by + * CVarNpc. + */ +class CVarNpcName : public IVar +{ +public: + CVarNpcName(CMissionData &md, IPrimitive *prim) + : IVar(vt_npc, prim) + { + // Change the var name + _VarName += "_name"; + _NpcLabel = getPrimProperty(prim, "npc_name"); + _NpcFunction = getPrimProperty(prim, "npc_function"); + if (!_NpcFunction.empty()) + { + _NpcFunction = "$"+_NpcFunction+"$"; + } + } + + const std::string getNpcLabel() + { + return _NpcLabel; + } + const std::string getNpcFunction() + { + return _NpcFunction; + } + const std::string getNpcFullName() + { + return _NpcLabel+_NpcFunction; + } + + string evalVar(const string &subPart) + { + if (subPart == "") + return string("\"")+_NpcLabel+"\""; + + throw EParseException(NULL, toString("var_npc_name don't have a subpart '%s'", subPart.c_str()).c_str()); + } + + STRING_MANAGER::TParamType getStringManagerType() + { + return STRING_MANAGER::bot_name; + } + + string genDecl(CMissionData &md) + { + return string(); + } + +private: + string _NpcLabel; + string _NpcFunction; +}; +REGISTER_VAR_INDIRECT(CVarNpcName, "var_npc_name"); + +/* Class for npc variable */ +class CVarGroup : public IVar +{ +public: + CVarGroup(CMissionData &md, IPrimitive *prim) + : IVar(vt_npc, prim) + { + _GroupName = getPrimProperty(prim, "group_name"); + } + + string evalVar(const string &subPart) + { + if (subPart.empty()) + return _GroupName; + else if (subPart == "quoted") + return string("\"")+_GroupName+"\""; + else + nlassert(false); + return ""; + } + + STRING_MANAGER::TParamType getStringManagerType() + { + return STRING_MANAGER::bot_name; + } + + string genDecl(CMissionData &md) + { +// return "decl : bot : "+evalVar("no_quote")+NL; + return "decl : bot : "+evalVar("")+NL; + } +private: + string _GroupName; +}; + +REGISTER_VAR_INDIRECT(CVarGroup, "var_group"); +//NLMISC_REGISTER_OBJECT(IVar, CVarGroup, std::string, string("var_group")); + + +/* Class for item */ +class CVarItem : public IVar +{ +public: + CVarItem(CMissionData &md, IPrimitive *prim) + : IVar(vt_item, prim) + { + _ItemSheet = getPrimProperty(prim, "item_sheet"); + } + + const std::string getItemSheet() + { + return _ItemSheet; + } + + string evalVar(const string &subPart) + { + nlassert(subPart.empty()); + return _ItemSheet; + } + + STRING_MANAGER::TParamType getStringManagerType() + { + return STRING_MANAGER::item; + } + + string genDecl(CMissionData &md) + { + return "decl : item : "+evalVar("")+NL; + } +private: + string _ItemSheet; +}; + +REGISTER_VAR_INDIRECT(CVarItem, "var_item"); +//NLMISC_REGISTER_OBJECT(IVar, CVarItem, std::string, string("var_item")); + + +/* Class for race */ +class CVarRace : public IVar +{ +public: + CVarRace(CMissionData &md, IPrimitive *prim) + : IVar(vt_item, prim) + { + _Race = getPrimProperty(prim, "race"); + } + + string evalVar(const string &subPart) + { + nlassert(subPart.empty()); + return _Race; + } + + STRING_MANAGER::TParamType getStringManagerType() + { + return STRING_MANAGER::race; + } + + string genDecl(CMissionData &md) + { + return "decl : race : "+evalVar("")+NL; + } +private: + string _Race; +}; + +REGISTER_VAR_INDIRECT(CVarRace, "var_race"); + +/* Class for sphrase */ +class CVarSPhrase : public IVar +{ +public: + CVarSPhrase(CMissionData &md, IPrimitive *prim) + : IVar(vt_item, prim) + { + _SPhrase = getPrimProperty(prim, "sphrase_sheet"); + } + + string evalVar(const string &subPart) + { + nlassert(subPart.empty()); + return _SPhrase; + } + + STRING_MANAGER::TParamType getStringManagerType() + { + return STRING_MANAGER::sphrase; + } + + string genDecl(CMissionData &md) + { + return "decl : sphrase : "+evalVar("")+NL; + } +private: + string _SPhrase; +}; + +REGISTER_VAR_INDIRECT(CVarSPhrase, "var_sphrase"); + +/* Class for sbrick */ +class CVarSBrick : public IVar +{ +public: + CVarSBrick(CMissionData &md, IPrimitive *prim) + : IVar(vt_item, prim) + { + _SBrick = getPrimProperty(prim, "sbrick_sheet"); + } + + string evalVar(const string &subPart) + { + nlassert(subPart.empty()); + return _SBrick; + } + + STRING_MANAGER::TParamType getStringManagerType() + { + return STRING_MANAGER::sbrick; + } + + string genDecl(CMissionData &md) + { + return "decl : sbrick : "+evalVar("")+NL; + } +private: + string _SBrick; +}; + +REGISTER_VAR_INDIRECT(CVarSBrick, "var_sbrick"); + + +/* for special item */ +char *SpecialItemProp[] = +{ + "Durability", + "Weight", + "SapLoad", + "Dmg", + "Speed", + "Range", + "DodgeModifier", + "ParryModifier", + "AdversaryDodgeModifier", + "AdversaryParryModifier", + "ProtectionFactor", + "MaxSlashingProtection", + "MaxBluntProtection", + "MaxPiercingProtection", + "HpBuff", + "SapBuff", + "StaBuff", + "FocusBuff" +}; + +struct TItemProperty +{ + string PropName; + string PropValue; +}; + +/* Class for special item */ +class CVarSpecialItem : public IVar +{ +public: + CVarSpecialItem(CMissionData &md, IPrimitive *prim) + : IVar(vt_item, prim) + { + static bool init = false; + static set propertyNames; + + if (!init) + { + for (uint i=0; i vs; + vs = getPrimPropertyArray(prim, "properties/values"); + // parse the strings vector + for (uint i=0; i parts; + explode(vs[i], string(" "), parts, true); + if (!parts.empty() && parts.size() != 2) + { + string s = toString("Invalid special item property at line %u", i+1); + throw EParseException(prim, s.c_str()); + } + + if (parts.size() == 2) + { + TItemProperty ip; + ip.PropName = parts[0]; + ip.PropValue = parts[1]; + + if (propertyNames.find(ip.PropName) == propertyNames.end()) + { + string s = toString("Invalid property name '%s'", ip.PropName.c_str()); + throw EParseException(prim, s.c_str()); + } + + _Properties.push_back(ip); + } + } + _Action = getPrimProperty(prim, "item_action"); + vs.clear(); + vs = getPrimPropertyArray(prim, "phrase_item_name"); + _ItemPhrase.initPhrase(md, prim, vs); + + string s; + s = getPrimProperty(prim, "no_drop"); + _NoDrop = (s == "true"); + } + +// const std::string getItemSheet() +// { +// return _ItemSheet; +// } + + string evalVar(const string &subPart) + { + nlassert(subPart.empty()); + return _VarName; + } + + STRING_MANAGER::TParamType getStringManagerType() + { + return STRING_MANAGER::item; + } + + string genDecl(CMissionData &md) + { + string ret = string("decl_item : ")+_VarName+" : "+_ItemSheet+" : "+_ReqSkill; + if (!_Properties.empty() ||!_Action.empty()) + ret += " : "; + for (uint i=0; i<_Properties.size(); ++i) + { + TItemProperty &ip = _Properties[i]; + ret += ip.PropName+" "+ip.PropValue; + if (i < _Properties.size()-1 || !_Action.empty()) + ret += "; "; + } + + if (!_Action.empty()) + ret += _Action; + + ret += " : "+_ItemPhrase.genScript(md); + + if (_NoDrop) + ret += " : no_drop"; + + ret += NL; + + return ret; + } + + std::string genPhrase() + { + return _ItemPhrase.genPhrase(); + } + + +private: + /// the item sheet used as base for this special item + string _ItemSheet; + /// The skill required to use the item + string _ReqSkill; + /// The list of properties + vector _Properties; + // Optional action (enchantement) + string _Action; + // Name of the item + CPhrase _ItemPhrase; + // No drop flag + bool _NoDrop; + + string _Color; + +}; + +REGISTER_VAR_INDIRECT(CVarSpecialItem, "var_special_item"); +//NLMISC_REGISTER_OBJECT(IVar, CVarSpecialItem, std::string, string("var_special_item")); + +/* Class for place variable */ +class CVarPlace : public IVar +{ +public: + CVarPlace(CMissionData &md, IPrimitive *prim) + : IVar(vt_npc, prim) + { + _PlaceLabel = getPrimProperty(prim, "place_name"); + } + +/* const std::string getPlaceLabel() + { + return _PlaceLabel; + } +*/ + string evalVar(const string &subPart) + { + nlassert(subPart.empty()); + return _PlaceLabel; + } + + STRING_MANAGER::TParamType getStringManagerType() + { + return STRING_MANAGER::place; + } + + string genDecl(CMissionData &md) + { + return "decl : place : "+evalVar("")+NL; + } + +private: + string _PlaceLabel; +}; +REGISTER_VAR_INDIRECT(CVarPlace, "var_place"); +//NLMISC_REGISTER_OBJECT(IVar, CVarPlace, std::string, string("var_place")); + +/* Class for integer variable */ +class CVarInteger : public IVar +{ +public: + CVarInteger(CMissionData &md, IPrimitive *prim) + : IVar(vt_integer, prim) + { + if (prim->checkProperty("value")) + _Value = getPrimProperty(prim, "value"); + else if (prim->checkProperty("quantity")) + _Value = getPrimProperty(prim, "quantity"); + else if (prim->checkProperty("quality")) + _Value = getPrimProperty(prim, "quality"); + else + { + string err = toString("Can't find a valid property for integer variable"); + throw EParseException(prim, err.c_str()); + } + } + + const std::string getIntegerValue() + { + return _Value; + } + + string evalVar(const string &subPart) + { + nlassert(subPart.empty()); + return _Value;; + } + + STRING_MANAGER::TParamType getStringManagerType() + { + return STRING_MANAGER::integer; + } + + string genDecl(CMissionData &md) + { + // nothing to declare for this pseudo var + return string(); + } +private: + string _Value; +}; +REGISTER_VAR_INDIRECT(CVarInteger, "var_integer"); +//NLMISC_REGISTER_OBJECT(IVar, CVarInteger, std::string, string("var_integer")); +typedef CVarInteger CVarQuantity; +REGISTER_VAR_INDIRECT(CVarQuantity, "var_quantity"); +//NLMISC_REGISTER_OBJECT(IVar, CVarQuantity, std::string, string("var_quantity")); +typedef CVarInteger CVarQuality; +REGISTER_VAR_INDIRECT(CVarQuality, "var_quality"); +//NLMISC_REGISTER_OBJECT(IVar, CVarQuality, std::string, string("var_quality")); + + +/* Class for text var */ +class CVarText : public IVar +{ +public: + CVarText(CMissionData &md, IPrimitive *prim) + : IVar(vt_item, prim) + { + _TextValue = getPrimPropertyArray(prim, "text"); + } + + const vector &getText() + { + return _TextValue;; + } + + string evalVar(const string &subPart) + { + nlassert(subPart.empty()); + string t; + return std::accumulate(_TextValue.begin(), _TextValue.end(), string("")); + return t; + } + + STRING_MANAGER::TParamType getStringManagerType() + { + nlassert(false); + return STRING_MANAGER::NB_PARAM_TYPES; + } + + string genDecl(CMissionData &md) + { + // nothing to declare for this one + return string(); + } +private: + vector _TextValue; +}; +REGISTER_VAR_INDIRECT(CVarText, "var_text"); +//NLMISC_REGISTER_OBJECT(IVar, CVarText, std::string, string("var_text")); + +/* Class for creature var */ +class CVarCreature : public IVar +{ +public: + CVarCreature(CMissionData &md, IPrimitive *prim) + : IVar(vt_item, prim) + { + _CreatureSheet = getPrimProperty(prim, "creature_sheet"); + } + + string evalVar(const string &subPart) + { + nlassert(subPart.empty()); + return _CreatureSheet; + } + + STRING_MANAGER::TParamType getStringManagerType() + { +// return STRING_MANAGER::creature; + return STRING_MANAGER::creature_model; + } + + string genDecl(CMissionData &md) + { + // declare a creature sheet +// return "decl : creature : "+_CreatureSheet+NL; + return "decl : creature_model : "+_CreatureSheet+NL; + } +private: + string _CreatureSheet; +}; +REGISTER_VAR_INDIRECT(CVarCreature, "var_creature"); +//NLMISC_REGISTER_OBJECT(IVar, CVarCreature, std::string, string("var_creature")); + +/* Class for faction var */ +class CVarFaction : public IVar +{ +public: + CVarFaction(CMissionData &md, IPrimitive *prim) + : IVar(vt_item, prim) + { + _FactionName = getPrimProperty(prim, "faction_name"); + } + + string evalVar(const string &subPart) + { + nlassert(subPart.empty()); + return _FactionName; + } + + STRING_MANAGER::TParamType getStringManagerType() + { + return STRING_MANAGER::faction; + } + + string genDecl(CMissionData &md) + { + // declare a creature sheet + return "decl : faction : "+_FactionName+NL; + } +private: + string _FactionName; +}; +REGISTER_VAR_INDIRECT(CVarFaction, "var_faction"); +//NLMISC_REGISTER_OBJECT(IVar, CVarFaction, std::string, string("var_faction")); + +// Variable factory. +IVar *IVar::createVar(CMissionData &md, IPrimitive *prim) +{ + string *c; + if (!prim->getPropertyByName("class", c)) + throw EParseException(prim, "Can't find property 'class' on primitive"); + + return CFactoryIndirect::instance().getFactory(*c)->createVar(md, prim); + + return NULL; +}; +//IVar *IVar::createVar(CMissionData &md, IPrimitive *prim) +//{ +// string *className; +// if (!prim->getPropertyByName("class", className)) +// throw EParseException(prim, "Can't find property 'class' in primitive"); +// +// IVar *ret = NLMISC_GET_FACTORY_INDIRECT(IVar, std::string).createObject(md, *className, prim); +// +// return ret; +//} +// diff --git a/code/ryzom/tools/leveldesign/mp_generator/main.cpp b/code/ryzom/tools/leveldesign/mp_generator/main.cpp index d775f0e06..bcf7fdf52 100644 --- a/code/ryzom/tools/leveldesign/mp_generator/main.cpp +++ b/code/ryzom/tools/leveldesign/mp_generator/main.cpp @@ -1,1581 +1,1581 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "moulinette.h" -#include "utils.h" -#include "nel/misc/algo.h" - -TRMItem currentDocItem; -CRMData SortableData; - - -// Preloaded Files -CSString FamilyTypContent; -CSString GroupTypContent; -CSString WKContent; - - -// Assigne une nouvelle MP à une creature -void AssignerMP( const CSString& creatureName, const CSString& materialName ) -{ - // on regarde si la créature est dégénérée ou non - if ( ( creatureName.c_str()[3] != 'c' ) && ( creatureName.c_str()[3] != 'd' ) - && ( creatureName.c_str()[3] != 'f' ) && ( creatureName.c_str()[3] != 'j' ) - && ( creatureName.c_str()[3] != 'l' ) && ( creatureName.c_str()[3] != 'p' ) ) - { - } - else - { - // lecture du fichier d'assignement - CSString fileName = toString( "%s//_%s_mp.creature", RAW_MATERIAL_ASSIGN.c_str(), creatureName.c_str() ); - CSString data; - - // création si le fichier n'existe pas - if(!CFile::fileExists(fileName)) - { - CSString str; - str = "\r\n"; - str+= "
\r\n"; - str+= " \r\n"; - str+= " \r\n"; - str+= " \r\n"; - str+= " \r\n"; - str+= " \r\n"; - str+= " \r\n"; - str+= " \r\n"; - str+= " \r\n"; - str+= "\r\n"; - str.writeToFile( fileName ); - } - - // lecture - data.readFromFile( fileName ); - - if ( !data.contains( materialName.c_str() ) ) - { - // on recherche le premier numéro de MP non utilisé - CSString str = data; - int nb= 0; - while ( str.contains( "Name=\"MP" ) ) - { - str = str.splitFrom( "Name=\"MP" ); - nb = str.firstWord().atoi(); - } - - // on insère la nouvelle MP - str = " \r\n \r\n \r\n \r\n \r\n", materialName.c_str() ); - - data = data.replace( " \r\n
\r\n", str.c_str() ); - data.writeToFile( fileName ); - } - } -} - - -// enregistrement des differentes -// caractéristiques de chaque craft part -void LoadCraftParts() -{ - CSString data, ligne, info; - data.readFromFile( ITEM_MP_PARAM_DFN ); - int index; - - printf( "-- LOADING CRAFT PARTS --\n" ); - do - { - data = data.splitFrom( "Name=\"" ); - int index; - index = data.c_str()[0] - 'A'; - craftParts[index].Desc = data.splitTo( "\"" ); - - } while ( data.c_str()[0] != 'Z' ); - - if ( ! CFile::fileExists( "rm_item_parts.csv" ) ) - { - nlError( "rm_item_parts.csv not found\n"); - exit( 1 ); - } - - data.readFromFile( "rm_item_parts.csv" ); - - while ( data != "" ) - { - ligne = data.splitTo( "\n", true ); - - // on recherche la ligne correspondant à notre craft part - info = ligne.splitTo( ";", true ); - if ( info != "" ) - { - index = info.c_str()[0] - 'A'; - - for ( int i=0; i<6; i++ ) - ligne.splitTo( ";", true ); - - // parcours des différentes caractèristiques - for ( int i=0; i files; - // on parcours les fichiers dans le repertoire - CPath::getPathContent ( inputSheetPath, true, false, true, files ); - - for (uint32 i=0; i::const_iterator it; - - if ( ! CFile::fileExists( "creature_models.csv" ) ) - { - nlError( "creature_models.csv not found\n"); - exit( 1 ); - } - - data.readFromFile( "creature_models.csv" ); - - while ( data != "" ) - { - ligneN = data.splitTo( "\n", true ); - ligneM = data.splitTo( "\n", true ); - - // on vérifie que la ligne est valide - if ( ligneN.splitTo( ";", true ) != "" ) - { - ligneM.splitTo( ";", true ); - - // on se déplace jusqu'au données - ligneN.splitTo( ";", true ); - ligneM.splitTo( ";", true ); - ligneN.splitTo( ";", true ); - ligneM.splitTo( ";", true ); - - while ( ligneN != "" ) - { - ListeCreatureMP listeCreatureMP; - - if ( ligneN.contains( ";" ) ) - { - code = ligneN.splitTo( ";", true ); - nom = ligneM.splitTo( ";", true ); - } - else - { - code = ligneN.firstWord(); - nom = ligneM.firstWord(); - ligneN = ""; - } - - // pour chaque nouveau nom de créature trouvé, - // on enregistre les items à générer - for ( char eco='a'; eco<='z'; eco++ ) - { - for ( int level=0; level<10; level++ ) - { - for ( int creatureLevel=1; creatureLevel<=8; creatureLevel++ ) - { - CSString fileName = toString( "c%s%c%c%d", code.toLower().c_str(), eco, - 'a' + level, creatureLevel ); - // on recherche si une créature correspond à ces données - it = creatureFiles.find( fileName ); - - if ( it != creatureFiles.end() ) - { - // si oui, on signale que cet item devra être généré - CreatureMPItem* creatureMP = new CreatureMPItem; - creatureMP->creatureLevel = creatureLevel; - creatureMP->eco = eco; - creatureMP->itemLevel = level; - creatureMP->codeCreature = code; - creatureMP->creatureFileName = fileName; - listeCreatureMP.push_back( creatureMP ); - } - } - } - } - - itemsAGenerer[ nom ] = listeCreatureMP; - } - } - } -} - - -// Retourne la qualité maximum pour un level d'item -int GetMaxQuality( int level ) -{ - if ( level == 0 ) - return 50; - - return ( level * 50 ); -} - - -// Retourne l'énergie maximum pour un level d'item -int GetStatEnergy( int level ) -{ - if ( level == 0 ) - return 20; - - return ( 20 + ( level-1 ) * 15 ); -} - - -// Retourne le nom de classe de l'item selon ses caractèristiques -void GetItemClass( int level, bool mission, bool creature, CSString& outClassName ) -{ - static CSString missionClasses[] = { "Plain", "Average", "Prime", "Select", - "Superb", "Magnificient" }; - - static CSString nonMissionClasses[] = { "", "Basic", "Fine", "Choice", - "Excellent", "Supreme" }; - - if ( mission ) - outClassName = missionClasses[ level ]; - else if ( creature ) - outClassName = nonMissionClasses[ level+1 ]; - else - outClassName = nonMissionClasses[ level ]; -} - - -// Retourne la couleur de l'item -void GetItemColor( int color, char eco, int level, CSString& outStr ) -{ - CSString commonColors [4] = { "Beige", "Green", "Turquoise", "Violet" }; - CSString rareColors [2] = { "Red", "Blue" }; - CSString primeRootColors [2] = { "White", "Black" }; - - if ( eco == 'p' ) - outStr = primeRootColors[ color % 2 ]; - else if ( ( eco != 'c' ) && ( level >= 2 ) ) - outStr = rareColors[ color % 2 ]; - else if ( ( eco == 'c' ) && ( level >= 3 ) ) - outStr = rareColors[ color % 2 ]; - else - outStr = commonColors[ color % 4 ]; -} - - -bool endsWith( const CSString& s, const CSString& substring ) -{ - return (s.right( (uint)substring.size() ) == substring); -} - - -// Génére les noms d'un item -void GenerateItemNames( const CSString& nomMP, char eco, int level, bool mission, bool creature, CSString& outStr ) -{ - CSString itemClass, prefix, singularWithNoPrefix; - CSString ia = "a"; - - GetItemClass( level, mission, creature, itemClass ); - currentDocItem.push( DtStatQuality, itemClass ); - - if ( !mission ) - { - if ( ( creature && ( level == 3 ) ) || ( !creature && ( level == 4 ) ) ) - ia = "an"; - } - - singularWithNoPrefix = itemClass + " "; - - // selection de l'eco-systeme - switch ( eco ) - { - case 'c' : - break; - - case 'd' : - singularWithNoPrefix += "Desert "; - break; - - case 'f' : - singularWithNoPrefix += "Forest "; - break; - - case 'j' : - singularWithNoPrefix += "Jungle "; - break; - - case 'l' : - singularWithNoPrefix += "Lake "; - break; - - case 'p' : - singularWithNoPrefix += "Prime Root "; - break; - } - - singularWithNoPrefix += nomMP; - - // Contenant - if ( endsWith( nomMP, "Wood" ) ) - prefix = "Bundle"; - else if ( endsWith( nomMP, "Bark" ) || endsWith( nomMP, "Moss" ) || endsWith( nomMP, "Sawdust" ) || - endsWith( nomMP, "Straw" ) || endsWith( nomMP, "Dust" ) || endsWith( nomMP, "Soil" ) || - endsWith( nomMP, "Cereal" ) ) - prefix = "Handful"; - else if ( endsWith( nomMP, "Resin" ) || endsWith( nomMP, "Wax" ) ) - prefix = "Portion"; - else if ( endsWith( nomMP, "Whiskers" ) || endsWith( nomMP, "Hairs" ) ) - prefix = "Tuft"; - else if ( endsWith( nomMP, "Silk" ) ) - prefix = "Ball"; - else if ( endsWith( nomMP, "Sap" ) || endsWith( nomMP, "Residue" ) || endsWith( nomMP, "Honey" ) || - endsWith( nomMP, "Blood" ) ) - prefix = "Phial"; - else if ( endsWith( nomMP, "Fruit" ) ) - prefix = "Piece"; - else if ( endsWith( nomMP, "Flesh" ) ) - prefix = "Morsel"; - else if ( endsWith( nomMP, "Saliva" ) ) - prefix = "Sample"; - else if ( endsWith( nomMP, "Pollen" ) || endsWith( nomMP, "Fiber" ) || endsWith( nomMP, "Amber" ) || - endsWith( nomMP, "Leather" ) || endsWith( nomMP, "Oil" ) ) - ia = "some"; - else if ( endsWith( nomMP, "Pelvis" ) || endsWith( nomMP, "Eye" ) || endsWith( nomMP, "Spine" ) || - endsWith( nomMP, "Hoof" ) || endsWith( nomMP, "Mandible" ) || endsWith( nomMP, "Claw") || - endsWith( nomMP, "Tail" ) || endsWith( nomMP, "Trunk" ) || endsWith( nomMP, "Shell" ) || - endsWith( nomMP, "Sting" ) || endsWith( nomMP, "Skin" ) || endsWith( nomMP, "Beak" ) || - endsWith( nomMP, "Wing" ) || endsWith( nomMP, "Horn" ) || endsWith( nomMP, "Rostrum" ) || - endsWith( nomMP, "Skull" ) || endsWith( nomMP, "Pistil" ) ) - prefix = "Fragment"; // number-limited creature objects - - if ( ! prefix.empty() ) - { - outStr = prefix + " of " + singularWithNoPrefix; - ia = "a"; - } - else - outStr = singularWithNoPrefix; - - CSString singular = outStr; - currentDocItem.push( DtTitle, outStr ); - - // A, The - outStr += "\t" + ia + "\tthe\t"; - - // Plural - if ( prefix.empty() ) - outStr += singular + "s"; - else - outStr += prefix + "s" + " of " + singularWithNoPrefix; - - outStr += "\t\tthe"; -} - - -// Retourne le numéro de la famille passée en paramètre -int GetNumeroMP( const CSString& nomMP ) -{ - CSString result; - char buffer[100]; - char buffer2[100]; - int res; - - // *** Get the family number, and add it to faimly.typ if not already done - // on recherche si la MP est présente - // dans le fichier item_mp_family.typ - sprintf( buffer, "%s\" Value=\"", nomMP.c_str() ); - result = FamilyTypContent.splitFrom( buffer ); - - // si oui, on retourne son numéro de MP - if ( result != "" ) - res = result.splitTo( "\"" ).atoi(); - else - { - // sinon, on génère un nouveau numéro : - // on recupère le dernier numéro de MP (le max) - result = FamilyTypContent.splitTo( "" ).right(10); - result.splitTo( "\"", true ); - result = result.splitTo( "\"" ); - - // on ajoute 1 pour avoir un numéro non utilisé - res = result.atoi() + 1; - - // on ajoute la nouvelle MP : - // dans le fichier item_mp_family.typ - sprintf( buffer, " \n", nomMP.c_str(), res ); - FamilyTypContent= FamilyTypContent.replace( "", buffer ); - FamilyTypContent.writeToFile( ITEM_MP_FAMILY_TYP ); - } - - // *** Add the text in wk.uxt (if not done) - // Exist in wk.uxt ??? - sprintf( buffer, "mpfam%d\t", res ); - sprintf( buffer2, "mpfam%d ", res ); - // if not found - if ( !WKContent.contains(buffer) && !WKContent.contains(buffer2) ) - { - // add it at end - sprintf( buffer, "mpfam%d\t\t\t[%s]\n\r\nmpgroup0", res, nomMP.c_str() ); - WKContent= WKContent.replace( "\r\nmpgroup0", buffer ); - WKContent.writeToFile( WK_UXT ); - } - - return res; -} - - -// Retourne le numéro du groupe passé en paramètre -int GetNumeroGroupe( const CSString& groupe ) -{ - CSString result; - char buffer[100]; - char buffer2[100]; - int res; - - // *** Get the group number, and add it to group.typ if not already done - // on recherche si le groupe est présent - // dans le fichier item_mp_group.typ - sprintf( buffer, "%s\" Value=\"", groupe.c_str() ); - result = GroupTypContent.splitFrom( buffer ); - - // si oui, on retourne son numéro de groupe - if ( result != "" ) - res = result.splitTo( "\"" ).atoi(); - else - { - // sinon, on génère un nouveau numéro : - // on recupère le dernier numéro de groupe (le max) - result = GroupTypContent.splitTo( "" ).right(10); - result.splitTo( "\"", true ); - result = result.splitTo( "\"" ); - - // on ajoute 1 pour avoir un numéro non utilisé - res = result.atoi() + 1; - - // on ajoute la nouvelle MP : - // dans le fichier item_mp_group.typ - sprintf( buffer, "\n", groupe.c_str(), res ); - GroupTypContent= GroupTypContent.replace( "", buffer ); - GroupTypContent.writeToFile( ITEM_MP_GROUPE_TYP ); - } - - - // *** Add the text in wk.uxt (if not done) - // Exist in wk.uxt ??? - sprintf( buffer, "mpgroup%d\t", res ); - sprintf( buffer2, "mpgroup%d ", res ); - // if not found - if ( !WKContent.contains(buffer) && !WKContent.contains(buffer2) ) - { - // add it at end - sprintf( buffer, "mpgroup%d\t\t\t[%s]\n\r\nmpSource", res, groupe.c_str() ); - WKContent= WKContent.replace( "\r\nmpSource", buffer ); - WKContent.writeToFile( WK_UXT ); - } - - return res; -} - - -// Génère l'item parent pour une MP -void CreateParentSItem( int numMP, - const CSString& nomMP, - const CSString& groupe, - bool dropOrSell, - const CSString& icon, - const CSString& overlay ) -{ - CSString output; - CSString outputFileName; - - // nom du fichier de sortie - outputFileName = toString( "%s_parent\\_m%04d.sitem", MP_DIRECTORY.c_str(), numMP ); - - // entete xml - output = "\n
\n"; - - // basics - output += " \n \n"; - output += " \n"; - else - // sinon, on peut le vendre - output += "true\"/>\n"; - - output += " \n \n"; - - // mp - output += " \n"; - output += " \n \n \n"; - - // 3d - output += " \n"; - - if ( icon != "" ) - { - output += " \n"; - } - - if ( overlay != "" ) - { - output += " \n"; - } - - output += " \n \n"; - - // fin du fichier - output += " \n \n \n \n\n"; - - // écriture finale - output.writeToFile( outputFileName ); - -} - - -// Remplit les différents informations concernant le craft par un item -void FillCraftData( char craft, int eco, int level, bool creature, int bestStat, - int worstStat1, int worstStat2, CSString& outStr ) -{ - CSString data; - char buf[10]; - int index; - static CSString carac[] = { "Durability", "Weight", "SapLoad", "DMG", "Speed", - "Range", "DodgeModifier", "ParryModifier", - "AdversaryDodgeModifier", "AdversaryParryModifier", - "ProtectionFactor", "MaxSlashingProtection", - "MaxBluntProtection", "MaxPiercingProtection", - "ElementalCastingTimeFactor", "ElementalPowerFactor", - "OffensiveAfflictionCastingTimeFactor", - "OffensiveAfflictionPowerFactor", "HealCastingTimeFactor", - "HealPowerFactor", "DefensiveAfflictionCastingTimeFactor", - "DefensiveAfflictionPowerFactor", - "AcidProtection", - "ColdProtection", - "FireProtection", - "RotProtection", - "ShockWaveProtection", - "PoisonProtection", - "ElectricityProtection", - "DesertResistance", - "ForestResistance", - "LacustreResistance", - "JungleResistance", - "PrimaryRootResistance", - }; - nlctassert((sizeof(carac)/sizeof(carac[0]))==NumMPStats); - - static int mediumStatsByStatQuality[] = { 20, 35, 50, 65, 80 }; - int stat, remaining, nbToRaise, ajout; - int stats[NumMPStats]; - - index = craft - 'A'; - - outStr = " \n"; - - nbToRaise = 0; - remaining = 0; - ajout = 0; - - currentDocItem.push( DtCraftSlotName, craftParts[index].Desc.splitFrom( "(" ).splitTo( ")" ) ); - - // enregistrements des stats de chaque - // caractèristique - for ( int i=0; i 100 ) - { - // si une des stats dépasse 100, les autres - // stats sont augmentées - remaining = stat - 100; - stat = 100; - } - } - else if ( ( i == worstStat1 ) || ( i == worstStat2 ) ) - { - stat -= 20; - - // durabilité minimum - if ( ( i == 0 ) && ( stat < 1 ) ) - stat = 1; - } - else - nbToRaise++; - - stats[i] = stat; - } - else - stats[i] = -1; - } - - if ( nbToRaise != 0 ) - ajout = remaining/nbToRaise; - - // ajout des informations pour chaque carac - for ( int i=0; i\n"; - } - } - - // CraftCivSpec en fonction de l'écosystème - outStr += " \n \n"; -} - - -// Création d'une fiche d'item -void CreateSheet( int numMP, const CSString& nomMP, - const CSString& code, char eco, - int level, const MPCraftStats& craftStats, - bool specialItem = false, int variation = 1 ) -{ - CSString output, directory, itemName, craftInfo, color; - CSString outputFileName, ecoStr; - char chaineNum[5]; - bool creature = ( code != "dxa" ) && ( code != "cxx" ) && ( code != "ixx" ); - - // Creation du nom de fichier - sprintf( chaineNum, "%04d", numMP ); - - switch ( eco ) - { - case 'd' : - directory = "desert"; - ecoStr = "Desert"; - break; - - case 'f' : - directory = "forest"; - ecoStr = "Forest"; - break; - - case 'j' : - directory = "jungle"; - ecoStr = "Jungle"; - break; - - case 'l' : - directory = "lacustre"; - ecoStr = "Lacustre"; - break; - - case 'p' : - directory = "prime_roots"; - ecoStr = "PrimeRoots"; - break; - - default : - directory = "common"; - ecoStr = "Common"; - eco = 'c'; - break; - } - - if ( ( eco == 'c' ) && creature && ( craftStats.Craft == "" ) ) - return; - - outputFileName = toString( "m%04d%s%c%c%02d.sitem", numMP, code.c_str(), eco, - 'a' + level, variation ); - - if ( craftStats.Craft == "" ) - { - CSString levelZone = toString( "%c", 'a' + level ); - currentDocItem.push( DtLevelZone, levelZone.toUpper() ); - } - else - currentDocItem.push( DtLevelZone, "-" ); - - // remplissage des informations de la fiche - output = "\n
\n"; - output += " \n \n"; - - // le code est celui d'une créature, on doit donc rajouter le parent - if ( creature ) - { - output += " \n"; - creature = true; - } - - output += " \n"; - - - output += " \n"; - output += " \n"; - if(craftStats.UsedAsCraftRequirement) - output += " \n"; - } - else - { - // on récupère la couleur - GetItemColor( craftStats.color, eco, level, color ); - output += color; - output += "\"/>\n"; - - currentDocItem.push( DtColor, color ); - - // on ajoute les données de craft - output += " \n"; - for ( uint i=0; i\n \n \n \n \n \n \n \n\n"; - - output.writeToFile( toString( "%s%s\\%s", MP_DIRECTORY.c_str(), directory.c_str(), outputFileName.c_str() ) ); - - // Génération des noms - if ( !specialItem ) - { - outputFileName = toString( "m%04d%s%c%c%02d", numMP, code.c_str(), eco, 'a' + level, variation ); - output = outputFileName; - - GenerateItemNames( nomMP, eco, level, ( craftStats.Craft == "" ), creature, itemName ); - output += "\t" + itemName; - itemNames.insert( output ); - } - - currentDocItem.push( DtEcosystem, ecoStr ); - currentDocItem.push( DtName, outputFileName ); - - SortableData.updateItemAppend( currentDocItem, DtName ); - currentDocItem.reset( DtName ); - currentDocItem.reset( DtEcosystem ); - currentDocItem.reset( DtMaxLevel ); - currentDocItem.reset( DtAverageEnergy ); - currentDocItem.reset( DtTitle ); - currentDocItem.reset( DtLevelZone ); - currentDocItem.reset( DtStatQuality ); - currentDocItem.reset( DtCraftSlotName ); - currentDocItem.reset( DtCraftCivSpec ); - currentDocItem.reset( DtColor ); -} - - -// Pour une MP se trouvant dans des déposits, génération de ses items -void GenerateDepositItems( int numMP, const CSString& nomMP, const MPCraftStats& craftStats, const CSString& loc ) -{ - CSString code; - - if ( loc.left(1) == "I" ) - code = "ixx"; - else if ( loc.left(1) == "D" ) - code = "dxa"; - else - code = "cxx"; - - // pas de craft = items de mission - if ( craftStats.Craft == "" ) - { - if ( loc != "G" ) - CreateSheet( numMP, nomMP, code, 'c', 0, craftStats ); - - for ( int i=1; i<6; i++ ) - { - CreateSheet( numMP, nomMP, code, 'c', i, craftStats ); - } - } - else - { - // 2 items dans common - CreateSheet( numMP, nomMP, code, 'c', 1, craftStats ); - CreateSheet( numMP, nomMP, code, 'c', 2, craftStats ); - - // 3 items par zone - for ( int i=0; i<3; i++ ) - { - CreateSheet( numMP, nomMP, code, 'd', 3+i, craftStats ); - CreateSheet( numMP, nomMP, code, 'f', 3+i, craftStats ); - CreateSheet( numMP, nomMP, code, 'j', 3+i, craftStats ); - CreateSheet( numMP, nomMP, code, 'l', 3+i, craftStats ); - CreateSheet( numMP, nomMP, code, 'p', 3+i, craftStats ); - } - } -} - - -// Pour une MP se trouvant sur un créature, génération de ses items -void GenerateCreatureItems( int numMP, CSString& nomMP, const MPCraftStats& craftStats ) -{ - map::const_iterator itLCMP; - int quality; - static int statQuality[] = { 0, 1, 0, 1, 3, 6, 4, 2 }; - - // On obtient la liste des niveau d'item à generer pour la créature - itLCMP = itemsAGenerer.find( nomMP.firstWord() ); - - if ( itLCMP != itemsAGenerer.end() ) - { - ListeCreatureMP::const_iterator itMP = (*itLCMP).second.begin(); - - // pour chaque niveau d'item à générer - while ( itMP != (*itLCMP).second.end() ) - { - // on enregistre ses caractéristiques - char eco = (*itMP)->eco; - int creatureLevel = (*itMP)->creatureLevel; - int itemLevel = (*itMP)->itemLevel; - CSString creatureFileName = "c"; - creatureFileName += (*itMP)->codeCreature.toLower(); - - if ( craftStats.Craft != "" ) - { - quality = statQuality[creatureLevel-1]; - if ( quality != 6 ) - { - if ( quality < 2 ) - { - CreateSheet( numMP, nomMP, creatureFileName, 'c', quality, craftStats ); - - AssignerMP( (*itMP)->creatureFileName, - toString( "m%04d%s%c%c01.sitem", numMP, creatureFileName.c_str(), 'c', 'a' + quality ) ); - } - else - { - CreateSheet( numMP, nomMP, creatureFileName, eco, quality, craftStats ); - - AssignerMP( (*itMP)->creatureFileName, - toString( "m%04d%s%c%c01.sitem", numMP, creatureFileName.c_str(), eco, 'a' + quality ) ); - } - - currentDocItem.push( DtCreature, (*itMP)->creatureFileName ); - } - } - else - { - // pas de MP de mission pour les boss - if ( creatureLevel < 5 ) - { - CreateSheet( numMP, nomMP, creatureFileName, eco, itemLevel, craftStats ); - - AssignerMP( (*itMP)->creatureFileName, - toString( "m%04d%s%c%c01.sitem", numMP, creatureFileName.c_str(), eco, 'a' + itemLevel ) ); - - currentDocItem.push( DtCreature, (*itMP)->creatureFileName ); - } - } - - itMP++; - } - } -} - - -// Génération d'un item spécial -void GenerateSpecialItem( int numMP, const CSString& nomMP, const MPCraftStats& craftStats, - const CSString& loc,CSString& itemData, int variation ) -{ - CSString info, code, name; - info = itemData.splitTo( "/", true ).toLower(); - - if ( loc.left(1) == "I" ) - code = "ixx"; - else if ( loc.left(1) == "D" ) - code = "dxa"; - else - code = "cxx"; - - CreateSheet( numMP, nomMP, code, info.c_str()[0], info.c_str()[1]-'a', craftStats, true, variation ); - - name = toString( "m%04d%s%s%02d\t", numMP, code.c_str(), info.c_str(), variation ); - name += itemData.splitTo( "/", true ); // singulier - name += "\t"; - name += itemData.splitTo( "/", true ); // article indéfini - name += "\t"; - name += itemData.splitTo( "/", true ); // article défini - name += "\t"; - name += itemData.splitTo( "/", true ); // pluriel - name += "\t\t"; - name += itemData.splitTo( "/", true ); // article pluriel - - itemNames.insert( name ); -} - - -// Special Attrib parsing. craftStats must be good for extraInfo init -void parseSpecialAttributes(const CSString &specialAttributes, MPCraftStats &craftStats, CExtraInfo &extraInfo) -{ - // evaluate DropOrSell according to CraftStats: can DropOrSell if it is a MP Craft - extraInfo.DropOrSell= craftStats.Craft != ""; - - // parse attributes - vector strArray; - splitString(specialAttributes, "-", strArray); - for(uint i=0;i=(sint)MPFamilies.size()) - MPFamilies.resize(numMP+1); - MPFamilies[numMP].Name= nomMP; - MPFamilies[numMP].Icon= icon; - - - // MP trouvées dans les déposits ou dans la goo - if ( loc.left(1) != "C" ) - { - if ( !specialOnly ) - { - // Génération des items - GenerateDepositItems( numMP, nomMP, craftStats, loc ); - } - - // on enregistre les items se trouvant dans les deposits - if ( loc.left(1) == "D" ) - { - CSString output; - output.writeToFile( toString( "%s%s_%d.mp", DEPOSIT_MPS.c_str(), nomMP.toLower().replace( " ", "_" ).c_str(), numMP ) ); - } - - overlay = nomMP.firstWord().toUpper().left(6); - } - // MP trouvées sur les creature - else - { - GenerateCreatureItems( numMP, nomMP, craftStats ); - } - - - // items spéciaux - CSString codeSpecial, nouveauCode; - int variation = 1; - CSortedStringSet::const_iterator it = specialNames.begin(); - - while ( it != specialNames.end() ) - { - CSString name = (*it); - - nouveauCode = name.left(2).toLower(); - - if ( nouveauCode == codeSpecial ) - variation++; - else - variation = 1; - - GenerateSpecialItem( numMP, nomMP, craftStats, loc, name, variation ); - codeSpecial = nouveauCode; - it++; - } - - - // Création de la fiche parente pour la MP - CreateParentSItem( numMP, nomMP, groupe, extraInfo.DropOrSell, icon, overlay ); - - currentDocItem.reset( DtRMFamily ); - currentDocItem.reset( DtGroup ); - currentDocItem.reset( DtProp ); - currentDocItem.reset( DtCreature ); -} - - -// Génération du Primitive Necklace (objet particulier) -void CreatePrimitiveNecklace() -{ - CSString output; - - output = "\n"; - output += "
\n"; - output += " \n"; - output += " \n"; - output += " \n \n"; - output += " \n"; - output += " \n"; - output += " \n"; - output += " \n \n \n \n"; - output += " \n \n\n"; - output.writeToFile( toString( "%scommon\\m0696ixxcc01.sitem", MP_DIRECTORY.c_str() ) ); - - itemNames.insert( "m0696ixxcc01 Primitive Necklace a the Primitive Necklaces the" ); - -} - - -// Enregistre les différents noms -void ItemNamesSave() -{ - printf( "-- SAVING ITEM NAMES --\n"); - CSString data, output; - - FILE* file; - file = fopen( ITEM_WORDS_WK.c_str(), "rb" ); - - char c; - fread( &c, 1, 1, file ); - while ( !feof( file ) ) - { - data += toString( "%c", c ); - fread( &c, 1, 1, file ); - } - - fclose( file ); - - data.splitTo( "i", true ); - output = "i"; - output += data.splitTo( "prospector", true ); - - CSortedStringSet::const_iterator it = itemNames.begin(); - - while ( it != itemNames.end() ) - { - if ( !output.contains( (*it).left(5).c_str() ) ) - { - output += (*it); - output += "\r\n"; - } - it++; - } - - output += "p"; - - output += data; - - output.writeToFile( ITEM_WORDS_WK.c_str() ); -} - - -// Charge les différentes Customized Properties -// définies dans raw_material_generation.cfg -void LoadCustomizedProperties() -{ - CSString data, name, prop, val; - - printf( "-- REGISTERING CUSTOMIZED PROPERTIES --\n" ); - - data.readFromFile( "raw_material_generation.cfg" ); - data = data.splitFrom( "{\r\n\t" ); - CPath::addSearchPath( MP_DIRECTORY, true, false ); - - while ( data.contains( "};" ) ) - { - name = data.splitTo( ",", true ).replace( "\"", "" ); - prop = data.splitTo( ",", true ).replace( "\"", "" ).replace( " ", "" ); - - val = data.splitTo( ",", true ).replace( "\"", "" ).replace( " ", "" ); - if ( val.contains( "\r\n" ) ) - val = val.splitTo( "\r\n", true ); - - TRMItem item; - item.push( DtName, name ); - item.push( DtCustomizedProperties, prop ); - SortableData.updateItemAppend( item, DtName ); - - data.splitTo( "\t", true ); - - CSString fileName, str, output; - fileName = CPath::lookup( name, false, false, true ); - - // on vérifie que le fichier concerné existe - if ( fileName != "" ) - { - CSString zone = prop.splitTo( ".", true ); - str.readFromFile( fileName ); - - if ( !str.contains( zone.c_str() ) ) - { - output = "\n \n \n ", prop.c_str(), val.c_str() ); - - // on vérifie que la propriétés n'a pas déjà été insérée - if ( !str.contains( output.c_str() ) ) - { - str = str.replace( "", output.c_str() ); - str.writeToFile( fileName ); - } - } - else - { - output = toString( " \n", zone.c_str() ); - output += toString( " \n", prop.c_str(), val.c_str() ); - - // on vérifie que la propriétés n'a pas déjà été insérée - if ( !str.contains( toString( "%s\" Value=\"%s\"/>\n", prop.c_str(), val.c_str() ).c_str() ) ) - { - str = str.replace( toString( " \n", zone.c_str() ).c_str(), output.c_str() ); - str.writeToFile( fileName ); - } - } - } - } -} - -// Generate _ic_families.forage_source() -void SaveFamiliesForageSource() -{ - CSString output; - - printf( "-- GROUP ICONS FOR _ic_groups.forage_source --\n"); - - output = "\n"; - output+= "
\n"; - output+= " \n"; - output+= " \n"; - - for ( uint i=0; i!=MPFamilies.size(); ++i ) - { - output+= toString(" \n", MPFamilies[i].Icon.c_str()); - } - - output+= " \n"; - output+= " \n"; - output+= " \n"; - output+= " \n"; - output+= " \n"; - output+= " \n"; - output+= " \n"; - output+= "\n"; - - output.writeToFile( IC_FAMILIES_FORAGE_SOURCE.c_str() ); -} - - -// Génère la documentation -void GenerateDoc() -{ - CProducedDocHtml MainDoc; - CFile::createDirectory("doc"); - MainDoc.open( "doc\\rm.html", "Raw materials by generation order", true ); - MainDoc.write( "\n" ); - MainDoc.write( "" ); - for ( uint32 c=0; c!=DtNbCols; ++c ) - { - MainDoc.write( "" ); - } - MainDoc.write( "" ); - for ( CRMData::CItems::const_iterator isd=SortableData.items().begin(); isd!=SortableData.items().end(); ++isd ) - { - MainDoc.write( (*isd).toHTMLRow() ); - } - MainDoc.write( "
" + string(DataColStr[c]) + "
\n" ); - - // Produce alt docs - CProducedDocHtml AltDocs[DtNbCols]; - for ( uint32 c=0; c!=DtNbCols; ++c ) - { - AltDocs[c].open( "doc\\rm_" + string(DataColStr[c]) + ".html", "Raw materials by " + string(DataColStr[c]), true ); - AltDocs[c].write( "
\n" ); - AltDocs[c].write( "" ); - for ( uint32 cc=0; cc!=DtNbCols; ++cc ) - if ( cc == c ) - AltDocs[c].write( "" ); - else - AltDocs[c].write( "" ); - AltDocs[c].write( "" ); - string previousKey = "[NO PREVIOUS]"; // not a blank string, because it may be a valid value - string previousName = ""; - for ( CRMData::CLookup::const_iterator isd=SortableData.lookup( c ).begin(); isd!=SortableData.lookup( c ).end(); ++isd ) - { - const TRMItem& item = SortableData.getRow( (*isd).second ); - AltDocs[c].write( item.toHTMLRow( c, (*isd).first, previousKey, DtName, previousName ) ); - - previousKey = (*isd).first; - previousName = item.Fields[DtName][0]; - } - AltDocs[c].write( "
" + string(DataColStr[cc]) + "" + string(DataColStr[cc]) + "
\n" ); - AltDocs[c].save(); - } -} - - -// Initialise les repertoires à partir de raw_material_generation.cfg -void SetupDirectories() -{ - CSString data; - - if ( ! CFile::fileExists( "raw_material_generation.cfg" ) ) - { - nlError( "raw_material_generation.cfg not found\n"); - exit( 1 ); - } - - data.readFromFile( "raw_material_generation.cfg" ); - - LEVEL_DESIGN_PATH = data.splitFrom( "LevelDesignPath = \"").splitTo( "\"" ); - TRANSLATION_PATH = data.splitFrom( "TranslationPath = \"" ).splitTo( "\"" ); - - printf( "Level Design Path : %s\nTranslation Path : %s\n\n", LEVEL_DESIGN_PATH.c_str(), TRANSLATION_PATH.c_str() ); - - ITEM_MP_FAMILY_TYP = LEVEL_DESIGN_PATH + "leveldesign\\DFN\\game_elem\\_item\\item_mp_family.typ"; - ITEM_MP_GROUPE_TYP = LEVEL_DESIGN_PATH + "leveldesign\\DFN\\game_elem\\_item\\item_mp_group.typ"; - ITEM_MP_PARAM_DFN = LEVEL_DESIGN_PATH + "leveldesign\\DFN\\game_elem\\_item\\_item_mp_param.dfn"; - MP_DIRECTORY = LEVEL_DESIGN_PATH + "leveldesign\\game_element\\sitem\\raw_material\\"; - DEPOSIT_MPS = LEVEL_DESIGN_PATH + "leveldesign\\game_element\\deposit_system\\mps\\"; - - RAW_MATERIAL_ASSIGN = LEVEL_DESIGN_PATH + "leveldesign\\Game_elem\\Creature\\raw_material_assignment\\"; - - IC_FAMILIES_FORAGE_SOURCE = LEVEL_DESIGN_PATH + "leveldesign\\game_element\\forage_source\\_ic_families.forage_source"; - - WK_UXT = TRANSLATION_PATH + "work\\wk.uxt"; - ITEM_WORDS_WK = TRANSLATION_PATH + "work\\item_words_wk.txt"; -} - - -// Parcours les différentes familles de MP pour effectuer -// les traitements nécessaires -void LoadFamillesMP() -{ - printf( "-- LOADING RAW MATERIAL FAMILIES --\n" ); - - // Preload wk.uxt, item_mp_family.typ, and item_mp_group.typ (avoid to reload them each time) - FamilyTypContent.readFromFile( ITEM_MP_FAMILY_TYP ); - GroupTypContent.readFromFile( ITEM_MP_GROUPE_TYP ); - WKContent.readFromFile( WK_UXT ); - - // avoid huge resize of vector - MPFamilies.reserve(1000); - - CSString fileData, ligne; - - if ( ! CFile::fileExists( "rm_fam_prop.csv" ) ) - { - nlError( "rm_fam_prop.csv not found\n"); - exit( 1 ); - } - - - fileData.readFromFile( "rm_fam_prop.csv" ); - - ligne = fileData.splitTo( "\n", true ); - - while ( ligne != "" ) - { - NewMP( ligne ); - ligne = fileData.splitTo( "\n", true ); - } - - // le Primitive Necklace n'étant pas spécifié dans la liste des MP - // on le rajoute à la main - CreatePrimitiveNecklace(); -} - - -// Programme principal -int main( int argc, char* argv[] ) -{ - new CApplicationContext; - SortableData.init( true ); - - SetupDirectories(); - - LoadCraftParts(); - - LoadCreatureFiles(); - - InitCreatureMP(); - - LoadFamillesMP(); - - ItemNamesSave(); - - LoadCustomizedProperties(); - - SaveFamiliesForageSource(); - - printf( "-- GENERATING DOCUMENTATION --\n" ); - try - { - GenerateDoc(); - } - catch(const Exception &e) - { - nlwarning(e.what()); - nlwarning("HTML Doc generation failed\n"); - } - - printf( "-- DONE --\n" ); - - return 0; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "moulinette.h" +#include "utils.h" +#include "nel/misc/algo.h" + +TRMItem currentDocItem; +CRMData SortableData; + + +// Preloaded Files +CSString FamilyTypContent; +CSString GroupTypContent; +CSString WKContent; + + +// Assigne une nouvelle MP à une creature +void AssignerMP( const CSString& creatureName, const CSString& materialName ) +{ + // on regarde si la créature est dégénérée ou non + if ( ( creatureName.c_str()[3] != 'c' ) && ( creatureName.c_str()[3] != 'd' ) + && ( creatureName.c_str()[3] != 'f' ) && ( creatureName.c_str()[3] != 'j' ) + && ( creatureName.c_str()[3] != 'l' ) && ( creatureName.c_str()[3] != 'p' ) ) + { + } + else + { + // lecture du fichier d'assignement + CSString fileName = toString( "%s//_%s_mp.creature", RAW_MATERIAL_ASSIGN.c_str(), creatureName.c_str() ); + CSString data; + + // création si le fichier n'existe pas + if(!CFile::fileExists(fileName)) + { + CSString str; + str = "\r\n"; + str+= "
\r\n"; + str+= " \r\n"; + str+= " \r\n"; + str+= " \r\n"; + str+= " \r\n"; + str+= " \r\n"; + str+= " \r\n"; + str+= " \r\n"; + str+= " \r\n"; + str+= "\r\n"; + str.writeToFile( fileName ); + } + + // lecture + data.readFromFile( fileName ); + + if ( !data.contains( materialName.c_str() ) ) + { + // on recherche le premier numéro de MP non utilisé + CSString str = data; + int nb= 0; + while ( str.contains( "Name=\"MP" ) ) + { + str = str.splitFrom( "Name=\"MP" ); + nb = str.firstWord().atoi(); + } + + // on insère la nouvelle MP + str = " \r\n \r\n \r\n \r\n \r\n", materialName.c_str() ); + + data = data.replace( " \r\n \r\n", str.c_str() ); + data.writeToFile( fileName ); + } + } +} + + +// enregistrement des differentes +// caractéristiques de chaque craft part +void LoadCraftParts() +{ + CSString data, ligne, info; + data.readFromFile( ITEM_MP_PARAM_DFN ); + int index; + + printf( "-- LOADING CRAFT PARTS --\n" ); + do + { + data = data.splitFrom( "Name=\"" ); + int index; + index = data.c_str()[0] - 'A'; + craftParts[index].Desc = data.splitTo( "\"" ); + + } while ( data.c_str()[0] != 'Z' ); + + if ( ! CFile::fileExists( "rm_item_parts.csv" ) ) + { + nlError( "rm_item_parts.csv not found\n"); + exit( 1 ); + } + + data.readFromFile( "rm_item_parts.csv" ); + + while ( data != "" ) + { + ligne = data.splitTo( "\n", true ); + + // on recherche la ligne correspondant à notre craft part + info = ligne.splitTo( ";", true ); + if ( info != "" ) + { + index = info.c_str()[0] - 'A'; + + for ( int i=0; i<6; i++ ) + ligne.splitTo( ";", true ); + + // parcours des différentes caractèristiques + for ( int i=0; i files; + // on parcours les fichiers dans le repertoire + CPath::getPathContent ( inputSheetPath, true, false, true, files ); + + for (uint32 i=0; i::const_iterator it; + + if ( ! CFile::fileExists( "creature_models.csv" ) ) + { + nlError( "creature_models.csv not found\n"); + exit( 1 ); + } + + data.readFromFile( "creature_models.csv" ); + + while ( data != "" ) + { + ligneN = data.splitTo( "\n", true ); + ligneM = data.splitTo( "\n", true ); + + // on vérifie que la ligne est valide + if ( ligneN.splitTo( ";", true ) != "" ) + { + ligneM.splitTo( ";", true ); + + // on se déplace jusqu'au données + ligneN.splitTo( ";", true ); + ligneM.splitTo( ";", true ); + ligneN.splitTo( ";", true ); + ligneM.splitTo( ";", true ); + + while ( ligneN != "" ) + { + ListeCreatureMP listeCreatureMP; + + if ( ligneN.contains( ";" ) ) + { + code = ligneN.splitTo( ";", true ); + nom = ligneM.splitTo( ";", true ); + } + else + { + code = ligneN.firstWord(); + nom = ligneM.firstWord(); + ligneN = ""; + } + + // pour chaque nouveau nom de créature trouvé, + // on enregistre les items à générer + for ( char eco='a'; eco<='z'; eco++ ) + { + for ( int level=0; level<10; level++ ) + { + for ( int creatureLevel=1; creatureLevel<=8; creatureLevel++ ) + { + CSString fileName = toString( "c%s%c%c%d", code.toLower().c_str(), eco, + 'a' + level, creatureLevel ); + // on recherche si une créature correspond à ces données + it = creatureFiles.find( fileName ); + + if ( it != creatureFiles.end() ) + { + // si oui, on signale que cet item devra être généré + CreatureMPItem* creatureMP = new CreatureMPItem; + creatureMP->creatureLevel = creatureLevel; + creatureMP->eco = eco; + creatureMP->itemLevel = level; + creatureMP->codeCreature = code; + creatureMP->creatureFileName = fileName; + listeCreatureMP.push_back( creatureMP ); + } + } + } + } + + itemsAGenerer[ nom ] = listeCreatureMP; + } + } + } +} + + +// Retourne la qualité maximum pour un level d'item +int GetMaxQuality( int level ) +{ + if ( level == 0 ) + return 50; + + return ( level * 50 ); +} + + +// Retourne l'énergie maximum pour un level d'item +int GetStatEnergy( int level ) +{ + if ( level == 0 ) + return 20; + + return ( 20 + ( level-1 ) * 15 ); +} + + +// Retourne le nom de classe de l'item selon ses caractèristiques +void GetItemClass( int level, bool mission, bool creature, CSString& outClassName ) +{ + static CSString missionClasses[] = { "Plain", "Average", "Prime", "Select", + "Superb", "Magnificient" }; + + static CSString nonMissionClasses[] = { "", "Basic", "Fine", "Choice", + "Excellent", "Supreme" }; + + if ( mission ) + outClassName = missionClasses[ level ]; + else if ( creature ) + outClassName = nonMissionClasses[ level+1 ]; + else + outClassName = nonMissionClasses[ level ]; +} + + +// Retourne la couleur de l'item +void GetItemColor( int color, char eco, int level, CSString& outStr ) +{ + CSString commonColors [4] = { "Beige", "Green", "Turquoise", "Violet" }; + CSString rareColors [2] = { "Red", "Blue" }; + CSString primeRootColors [2] = { "White", "Black" }; + + if ( eco == 'p' ) + outStr = primeRootColors[ color % 2 ]; + else if ( ( eco != 'c' ) && ( level >= 2 ) ) + outStr = rareColors[ color % 2 ]; + else if ( ( eco == 'c' ) && ( level >= 3 ) ) + outStr = rareColors[ color % 2 ]; + else + outStr = commonColors[ color % 4 ]; +} + + +bool endsWith( const CSString& s, const CSString& substring ) +{ + return (s.right( (uint)substring.size() ) == substring); +} + + +// Génére les noms d'un item +void GenerateItemNames( const CSString& nomMP, char eco, int level, bool mission, bool creature, CSString& outStr ) +{ + CSString itemClass, prefix, singularWithNoPrefix; + CSString ia = "a"; + + GetItemClass( level, mission, creature, itemClass ); + currentDocItem.push( DtStatQuality, itemClass ); + + if ( !mission ) + { + if ( ( creature && ( level == 3 ) ) || ( !creature && ( level == 4 ) ) ) + ia = "an"; + } + + singularWithNoPrefix = itemClass + " "; + + // selection de l'eco-systeme + switch ( eco ) + { + case 'c' : + break; + + case 'd' : + singularWithNoPrefix += "Desert "; + break; + + case 'f' : + singularWithNoPrefix += "Forest "; + break; + + case 'j' : + singularWithNoPrefix += "Jungle "; + break; + + case 'l' : + singularWithNoPrefix += "Lake "; + break; + + case 'p' : + singularWithNoPrefix += "Prime Root "; + break; + } + + singularWithNoPrefix += nomMP; + + // Contenant + if ( endsWith( nomMP, "Wood" ) ) + prefix = "Bundle"; + else if ( endsWith( nomMP, "Bark" ) || endsWith( nomMP, "Moss" ) || endsWith( nomMP, "Sawdust" ) || + endsWith( nomMP, "Straw" ) || endsWith( nomMP, "Dust" ) || endsWith( nomMP, "Soil" ) || + endsWith( nomMP, "Cereal" ) ) + prefix = "Handful"; + else if ( endsWith( nomMP, "Resin" ) || endsWith( nomMP, "Wax" ) ) + prefix = "Portion"; + else if ( endsWith( nomMP, "Whiskers" ) || endsWith( nomMP, "Hairs" ) ) + prefix = "Tuft"; + else if ( endsWith( nomMP, "Silk" ) ) + prefix = "Ball"; + else if ( endsWith( nomMP, "Sap" ) || endsWith( nomMP, "Residue" ) || endsWith( nomMP, "Honey" ) || + endsWith( nomMP, "Blood" ) ) + prefix = "Phial"; + else if ( endsWith( nomMP, "Fruit" ) ) + prefix = "Piece"; + else if ( endsWith( nomMP, "Flesh" ) ) + prefix = "Morsel"; + else if ( endsWith( nomMP, "Saliva" ) ) + prefix = "Sample"; + else if ( endsWith( nomMP, "Pollen" ) || endsWith( nomMP, "Fiber" ) || endsWith( nomMP, "Amber" ) || + endsWith( nomMP, "Leather" ) || endsWith( nomMP, "Oil" ) ) + ia = "some"; + else if ( endsWith( nomMP, "Pelvis" ) || endsWith( nomMP, "Eye" ) || endsWith( nomMP, "Spine" ) || + endsWith( nomMP, "Hoof" ) || endsWith( nomMP, "Mandible" ) || endsWith( nomMP, "Claw") || + endsWith( nomMP, "Tail" ) || endsWith( nomMP, "Trunk" ) || endsWith( nomMP, "Shell" ) || + endsWith( nomMP, "Sting" ) || endsWith( nomMP, "Skin" ) || endsWith( nomMP, "Beak" ) || + endsWith( nomMP, "Wing" ) || endsWith( nomMP, "Horn" ) || endsWith( nomMP, "Rostrum" ) || + endsWith( nomMP, "Skull" ) || endsWith( nomMP, "Pistil" ) ) + prefix = "Fragment"; // number-limited creature objects + + if ( ! prefix.empty() ) + { + outStr = prefix + " of " + singularWithNoPrefix; + ia = "a"; + } + else + outStr = singularWithNoPrefix; + + CSString singular = outStr; + currentDocItem.push( DtTitle, outStr ); + + // A, The + outStr += "\t" + ia + "\tthe\t"; + + // Plural + if ( prefix.empty() ) + outStr += singular + "s"; + else + outStr += prefix + "s" + " of " + singularWithNoPrefix; + + outStr += "\t\tthe"; +} + + +// Retourne le numéro de la famille passée en paramètre +int GetNumeroMP( const CSString& nomMP ) +{ + CSString result; + char buffer[100]; + char buffer2[100]; + int res; + + // *** Get the family number, and add it to faimly.typ if not already done + // on recherche si la MP est présente + // dans le fichier item_mp_family.typ + sprintf( buffer, "%s\" Value=\"", nomMP.c_str() ); + result = FamilyTypContent.splitFrom( buffer ); + + // si oui, on retourne son numéro de MP + if ( result != "" ) + res = result.splitTo( "\"" ).atoi(); + else + { + // sinon, on génère un nouveau numéro : + // on recupère le dernier numéro de MP (le max) + result = FamilyTypContent.splitTo( "" ).right(10); + result.splitTo( "\"", true ); + result = result.splitTo( "\"" ); + + // on ajoute 1 pour avoir un numéro non utilisé + res = result.atoi() + 1; + + // on ajoute la nouvelle MP : + // dans le fichier item_mp_family.typ + sprintf( buffer, " \n", nomMP.c_str(), res ); + FamilyTypContent= FamilyTypContent.replace( "", buffer ); + FamilyTypContent.writeToFile( ITEM_MP_FAMILY_TYP ); + } + + // *** Add the text in wk.uxt (if not done) + // Exist in wk.uxt ??? + sprintf( buffer, "mpfam%d\t", res ); + sprintf( buffer2, "mpfam%d ", res ); + // if not found + if ( !WKContent.contains(buffer) && !WKContent.contains(buffer2) ) + { + // add it at end + sprintf( buffer, "mpfam%d\t\t\t[%s]\n\r\nmpgroup0", res, nomMP.c_str() ); + WKContent= WKContent.replace( "\r\nmpgroup0", buffer ); + WKContent.writeToFile( WK_UXT ); + } + + return res; +} + + +// Retourne le numéro du groupe passé en paramètre +int GetNumeroGroupe( const CSString& groupe ) +{ + CSString result; + char buffer[100]; + char buffer2[100]; + int res; + + // *** Get the group number, and add it to group.typ if not already done + // on recherche si le groupe est présent + // dans le fichier item_mp_group.typ + sprintf( buffer, "%s\" Value=\"", groupe.c_str() ); + result = GroupTypContent.splitFrom( buffer ); + + // si oui, on retourne son numéro de groupe + if ( result != "" ) + res = result.splitTo( "\"" ).atoi(); + else + { + // sinon, on génère un nouveau numéro : + // on recupère le dernier numéro de groupe (le max) + result = GroupTypContent.splitTo( "" ).right(10); + result.splitTo( "\"", true ); + result = result.splitTo( "\"" ); + + // on ajoute 1 pour avoir un numéro non utilisé + res = result.atoi() + 1; + + // on ajoute la nouvelle MP : + // dans le fichier item_mp_group.typ + sprintf( buffer, "\n", groupe.c_str(), res ); + GroupTypContent= GroupTypContent.replace( "", buffer ); + GroupTypContent.writeToFile( ITEM_MP_GROUPE_TYP ); + } + + + // *** Add the text in wk.uxt (if not done) + // Exist in wk.uxt ??? + sprintf( buffer, "mpgroup%d\t", res ); + sprintf( buffer2, "mpgroup%d ", res ); + // if not found + if ( !WKContent.contains(buffer) && !WKContent.contains(buffer2) ) + { + // add it at end + sprintf( buffer, "mpgroup%d\t\t\t[%s]\n\r\nmpSource", res, groupe.c_str() ); + WKContent= WKContent.replace( "\r\nmpSource", buffer ); + WKContent.writeToFile( WK_UXT ); + } + + return res; +} + + +// Génère l'item parent pour une MP +void CreateParentSItem( int numMP, + const CSString& nomMP, + const CSString& groupe, + bool dropOrSell, + const CSString& icon, + const CSString& overlay ) +{ + CSString output; + CSString outputFileName; + + // nom du fichier de sortie + outputFileName = toString( "%s_parent\\_m%04d.sitem", MP_DIRECTORY.c_str(), numMP ); + + // entete xml + output = "\n
\n"; + + // basics + output += " \n \n"; + output += " \n"; + else + // sinon, on peut le vendre + output += "true\"/>\n"; + + output += " \n \n"; + + // mp + output += " \n"; + output += " \n \n \n"; + + // 3d + output += " \n"; + + if ( icon != "" ) + { + output += " \n"; + } + + if ( overlay != "" ) + { + output += " \n"; + } + + output += " \n \n"; + + // fin du fichier + output += " \n \n \n \n\n"; + + // écriture finale + output.writeToFile( outputFileName ); + +} + + +// Remplit les différents informations concernant le craft par un item +void FillCraftData( char craft, int eco, int level, bool creature, int bestStat, + int worstStat1, int worstStat2, CSString& outStr ) +{ + CSString data; + char buf[10]; + int index; + static CSString carac[] = { "Durability", "Weight", "SapLoad", "DMG", "Speed", + "Range", "DodgeModifier", "ParryModifier", + "AdversaryDodgeModifier", "AdversaryParryModifier", + "ProtectionFactor", "MaxSlashingProtection", + "MaxBluntProtection", "MaxPiercingProtection", + "ElementalCastingTimeFactor", "ElementalPowerFactor", + "OffensiveAfflictionCastingTimeFactor", + "OffensiveAfflictionPowerFactor", "HealCastingTimeFactor", + "HealPowerFactor", "DefensiveAfflictionCastingTimeFactor", + "DefensiveAfflictionPowerFactor", + "AcidProtection", + "ColdProtection", + "FireProtection", + "RotProtection", + "ShockWaveProtection", + "PoisonProtection", + "ElectricityProtection", + "DesertResistance", + "ForestResistance", + "LacustreResistance", + "JungleResistance", + "PrimaryRootResistance", + }; + nlctassert((sizeof(carac)/sizeof(carac[0]))==NumMPStats); + + static int mediumStatsByStatQuality[] = { 20, 35, 50, 65, 80 }; + int stat, remaining, nbToRaise, ajout; + int stats[NumMPStats]; + + index = craft - 'A'; + + outStr = " \n"; + + nbToRaise = 0; + remaining = 0; + ajout = 0; + + currentDocItem.push( DtCraftSlotName, craftParts[index].Desc.splitFrom( "(" ).splitTo( ")" ) ); + + // enregistrements des stats de chaque + // caractèristique + for ( int i=0; i 100 ) + { + // si une des stats dépasse 100, les autres + // stats sont augmentées + remaining = stat - 100; + stat = 100; + } + } + else if ( ( i == worstStat1 ) || ( i == worstStat2 ) ) + { + stat -= 20; + + // durabilité minimum + if ( ( i == 0 ) && ( stat < 1 ) ) + stat = 1; + } + else + nbToRaise++; + + stats[i] = stat; + } + else + stats[i] = -1; + } + + if ( nbToRaise != 0 ) + ajout = remaining/nbToRaise; + + // ajout des informations pour chaque carac + for ( int i=0; i\n"; + } + } + + // CraftCivSpec en fonction de l'écosystème + outStr += " \n \n"; +} + + +// Création d'une fiche d'item +void CreateSheet( int numMP, const CSString& nomMP, + const CSString& code, char eco, + int level, const MPCraftStats& craftStats, + bool specialItem = false, int variation = 1 ) +{ + CSString output, directory, itemName, craftInfo, color; + CSString outputFileName, ecoStr; + char chaineNum[5]; + bool creature = ( code != "dxa" ) && ( code != "cxx" ) && ( code != "ixx" ); + + // Creation du nom de fichier + sprintf( chaineNum, "%04d", numMP ); + + switch ( eco ) + { + case 'd' : + directory = "desert"; + ecoStr = "Desert"; + break; + + case 'f' : + directory = "forest"; + ecoStr = "Forest"; + break; + + case 'j' : + directory = "jungle"; + ecoStr = "Jungle"; + break; + + case 'l' : + directory = "lacustre"; + ecoStr = "Lacustre"; + break; + + case 'p' : + directory = "prime_roots"; + ecoStr = "PrimeRoots"; + break; + + default : + directory = "common"; + ecoStr = "Common"; + eco = 'c'; + break; + } + + if ( ( eco == 'c' ) && creature && ( craftStats.Craft == "" ) ) + return; + + outputFileName = toString( "m%04d%s%c%c%02d.sitem", numMP, code.c_str(), eco, + 'a' + level, variation ); + + if ( craftStats.Craft == "" ) + { + CSString levelZone = toString( "%c", 'a' + level ); + currentDocItem.push( DtLevelZone, levelZone.toUpper() ); + } + else + currentDocItem.push( DtLevelZone, "-" ); + + // remplissage des informations de la fiche + output = "\n
\n"; + output += " \n \n"; + + // le code est celui d'une créature, on doit donc rajouter le parent + if ( creature ) + { + output += " \n"; + creature = true; + } + + output += " \n"; + + + output += " \n"; + output += " \n"; + if(craftStats.UsedAsCraftRequirement) + output += " \n"; + } + else + { + // on récupère la couleur + GetItemColor( craftStats.color, eco, level, color ); + output += color; + output += "\"/>\n"; + + currentDocItem.push( DtColor, color ); + + // on ajoute les données de craft + output += " \n"; + for ( uint i=0; i\n \n \n \n \n \n \n \n\n"; + + output.writeToFile( toString( "%s%s\\%s", MP_DIRECTORY.c_str(), directory.c_str(), outputFileName.c_str() ) ); + + // Génération des noms + if ( !specialItem ) + { + outputFileName = toString( "m%04d%s%c%c%02d", numMP, code.c_str(), eco, 'a' + level, variation ); + output = outputFileName; + + GenerateItemNames( nomMP, eco, level, ( craftStats.Craft == "" ), creature, itemName ); + output += "\t" + itemName; + itemNames.insert( output ); + } + + currentDocItem.push( DtEcosystem, ecoStr ); + currentDocItem.push( DtName, outputFileName ); + + SortableData.updateItemAppend( currentDocItem, DtName ); + currentDocItem.reset( DtName ); + currentDocItem.reset( DtEcosystem ); + currentDocItem.reset( DtMaxLevel ); + currentDocItem.reset( DtAverageEnergy ); + currentDocItem.reset( DtTitle ); + currentDocItem.reset( DtLevelZone ); + currentDocItem.reset( DtStatQuality ); + currentDocItem.reset( DtCraftSlotName ); + currentDocItem.reset( DtCraftCivSpec ); + currentDocItem.reset( DtColor ); +} + + +// Pour une MP se trouvant dans des déposits, génération de ses items +void GenerateDepositItems( int numMP, const CSString& nomMP, const MPCraftStats& craftStats, const CSString& loc ) +{ + CSString code; + + if ( loc.left(1) == "I" ) + code = "ixx"; + else if ( loc.left(1) == "D" ) + code = "dxa"; + else + code = "cxx"; + + // pas de craft = items de mission + if ( craftStats.Craft == "" ) + { + if ( loc != "G" ) + CreateSheet( numMP, nomMP, code, 'c', 0, craftStats ); + + for ( int i=1; i<6; i++ ) + { + CreateSheet( numMP, nomMP, code, 'c', i, craftStats ); + } + } + else + { + // 2 items dans common + CreateSheet( numMP, nomMP, code, 'c', 1, craftStats ); + CreateSheet( numMP, nomMP, code, 'c', 2, craftStats ); + + // 3 items par zone + for ( int i=0; i<3; i++ ) + { + CreateSheet( numMP, nomMP, code, 'd', 3+i, craftStats ); + CreateSheet( numMP, nomMP, code, 'f', 3+i, craftStats ); + CreateSheet( numMP, nomMP, code, 'j', 3+i, craftStats ); + CreateSheet( numMP, nomMP, code, 'l', 3+i, craftStats ); + CreateSheet( numMP, nomMP, code, 'p', 3+i, craftStats ); + } + } +} + + +// Pour une MP se trouvant sur un créature, génération de ses items +void GenerateCreatureItems( int numMP, CSString& nomMP, const MPCraftStats& craftStats ) +{ + map::const_iterator itLCMP; + int quality; + static int statQuality[] = { 0, 1, 0, 1, 3, 6, 4, 2 }; + + // On obtient la liste des niveau d'item à generer pour la créature + itLCMP = itemsAGenerer.find( nomMP.firstWord() ); + + if ( itLCMP != itemsAGenerer.end() ) + { + ListeCreatureMP::const_iterator itMP = (*itLCMP).second.begin(); + + // pour chaque niveau d'item à générer + while ( itMP != (*itLCMP).second.end() ) + { + // on enregistre ses caractéristiques + char eco = (*itMP)->eco; + int creatureLevel = (*itMP)->creatureLevel; + int itemLevel = (*itMP)->itemLevel; + CSString creatureFileName = "c"; + creatureFileName += (*itMP)->codeCreature.toLower(); + + if ( craftStats.Craft != "" ) + { + quality = statQuality[creatureLevel-1]; + if ( quality != 6 ) + { + if ( quality < 2 ) + { + CreateSheet( numMP, nomMP, creatureFileName, 'c', quality, craftStats ); + + AssignerMP( (*itMP)->creatureFileName, + toString( "m%04d%s%c%c01.sitem", numMP, creatureFileName.c_str(), 'c', 'a' + quality ) ); + } + else + { + CreateSheet( numMP, nomMP, creatureFileName, eco, quality, craftStats ); + + AssignerMP( (*itMP)->creatureFileName, + toString( "m%04d%s%c%c01.sitem", numMP, creatureFileName.c_str(), eco, 'a' + quality ) ); + } + + currentDocItem.push( DtCreature, (*itMP)->creatureFileName ); + } + } + else + { + // pas de MP de mission pour les boss + if ( creatureLevel < 5 ) + { + CreateSheet( numMP, nomMP, creatureFileName, eco, itemLevel, craftStats ); + + AssignerMP( (*itMP)->creatureFileName, + toString( "m%04d%s%c%c01.sitem", numMP, creatureFileName.c_str(), eco, 'a' + itemLevel ) ); + + currentDocItem.push( DtCreature, (*itMP)->creatureFileName ); + } + } + + itMP++; + } + } +} + + +// Génération d'un item spécial +void GenerateSpecialItem( int numMP, const CSString& nomMP, const MPCraftStats& craftStats, + const CSString& loc,CSString& itemData, int variation ) +{ + CSString info, code, name; + info = itemData.splitTo( "/", true ).toLower(); + + if ( loc.left(1) == "I" ) + code = "ixx"; + else if ( loc.left(1) == "D" ) + code = "dxa"; + else + code = "cxx"; + + CreateSheet( numMP, nomMP, code, info.c_str()[0], info.c_str()[1]-'a', craftStats, true, variation ); + + name = toString( "m%04d%s%s%02d\t", numMP, code.c_str(), info.c_str(), variation ); + name += itemData.splitTo( "/", true ); // singulier + name += "\t"; + name += itemData.splitTo( "/", true ); // article indéfini + name += "\t"; + name += itemData.splitTo( "/", true ); // article défini + name += "\t"; + name += itemData.splitTo( "/", true ); // pluriel + name += "\t\t"; + name += itemData.splitTo( "/", true ); // article pluriel + + itemNames.insert( name ); +} + + +// Special Attrib parsing. craftStats must be good for extraInfo init +void parseSpecialAttributes(const CSString &specialAttributes, MPCraftStats &craftStats, CExtraInfo &extraInfo) +{ + // evaluate DropOrSell according to CraftStats: can DropOrSell if it is a MP Craft + extraInfo.DropOrSell= craftStats.Craft != ""; + + // parse attributes + vector strArray; + splitString(specialAttributes, "-", strArray); + for(uint i=0;i=(sint)MPFamilies.size()) + MPFamilies.resize(numMP+1); + MPFamilies[numMP].Name= nomMP; + MPFamilies[numMP].Icon= icon; + + + // MP trouvées dans les déposits ou dans la goo + if ( loc.left(1) != "C" ) + { + if ( !specialOnly ) + { + // Génération des items + GenerateDepositItems( numMP, nomMP, craftStats, loc ); + } + + // on enregistre les items se trouvant dans les deposits + if ( loc.left(1) == "D" ) + { + CSString output; + output.writeToFile( toString( "%s%s_%d.mp", DEPOSIT_MPS.c_str(), nomMP.toLower().replace( " ", "_" ).c_str(), numMP ) ); + } + + overlay = nomMP.firstWord().toUpper().left(6); + } + // MP trouvées sur les creature + else + { + GenerateCreatureItems( numMP, nomMP, craftStats ); + } + + + // items spéciaux + CSString codeSpecial, nouveauCode; + int variation = 1; + CSortedStringSet::const_iterator it = specialNames.begin(); + + while ( it != specialNames.end() ) + { + CSString name = (*it); + + nouveauCode = name.left(2).toLower(); + + if ( nouveauCode == codeSpecial ) + variation++; + else + variation = 1; + + GenerateSpecialItem( numMP, nomMP, craftStats, loc, name, variation ); + codeSpecial = nouveauCode; + it++; + } + + + // Création de la fiche parente pour la MP + CreateParentSItem( numMP, nomMP, groupe, extraInfo.DropOrSell, icon, overlay ); + + currentDocItem.reset( DtRMFamily ); + currentDocItem.reset( DtGroup ); + currentDocItem.reset( DtProp ); + currentDocItem.reset( DtCreature ); +} + + +// Génération du Primitive Necklace (objet particulier) +void CreatePrimitiveNecklace() +{ + CSString output; + + output = "\n"; + output += "
\n"; + output += " \n"; + output += " \n"; + output += " \n \n"; + output += " \n"; + output += " \n"; + output += " \n"; + output += " \n \n \n \n"; + output += " \n \n\n"; + output.writeToFile( toString( "%scommon\\m0696ixxcc01.sitem", MP_DIRECTORY.c_str() ) ); + + itemNames.insert( "m0696ixxcc01 Primitive Necklace a the Primitive Necklaces the" ); + +} + + +// Enregistre les différents noms +void ItemNamesSave() +{ + printf( "-- SAVING ITEM NAMES --\n"); + CSString data, output; + + FILE* file; + file = fopen( ITEM_WORDS_WK.c_str(), "rb" ); + + char c; + fread( &c, 1, 1, file ); + while ( !feof( file ) ) + { + data += toString( "%c", c ); + fread( &c, 1, 1, file ); + } + + fclose( file ); + + data.splitTo( "i", true ); + output = "i"; + output += data.splitTo( "prospector", true ); + + CSortedStringSet::const_iterator it = itemNames.begin(); + + while ( it != itemNames.end() ) + { + if ( !output.contains( (*it).left(5).c_str() ) ) + { + output += (*it); + output += "\r\n"; + } + it++; + } + + output += "p"; + + output += data; + + output.writeToFile( ITEM_WORDS_WK.c_str() ); +} + + +// Charge les différentes Customized Properties +// définies dans raw_material_generation.cfg +void LoadCustomizedProperties() +{ + CSString data, name, prop, val; + + printf( "-- REGISTERING CUSTOMIZED PROPERTIES --\n" ); + + data.readFromFile( "raw_material_generation.cfg" ); + data = data.splitFrom( "{\r\n\t" ); + CPath::addSearchPath( MP_DIRECTORY, true, false ); + + while ( data.contains( "};" ) ) + { + name = data.splitTo( ",", true ).replace( "\"", "" ); + prop = data.splitTo( ",", true ).replace( "\"", "" ).replace( " ", "" ); + + val = data.splitTo( ",", true ).replace( "\"", "" ).replace( " ", "" ); + if ( val.contains( "\r\n" ) ) + val = val.splitTo( "\r\n", true ); + + TRMItem item; + item.push( DtName, name ); + item.push( DtCustomizedProperties, prop ); + SortableData.updateItemAppend( item, DtName ); + + data.splitTo( "\t", true ); + + CSString fileName, str, output; + fileName = CPath::lookup( name, false, false, true ); + + // on vérifie que le fichier concerné existe + if ( fileName != "" ) + { + CSString zone = prop.splitTo( ".", true ); + str.readFromFile( fileName ); + + if ( !str.contains( zone.c_str() ) ) + { + output = "\n \n \n ", prop.c_str(), val.c_str() ); + + // on vérifie que la propriétés n'a pas déjà été insérée + if ( !str.contains( output.c_str() ) ) + { + str = str.replace( "", output.c_str() ); + str.writeToFile( fileName ); + } + } + else + { + output = toString( " \n", zone.c_str() ); + output += toString( " \n", prop.c_str(), val.c_str() ); + + // on vérifie que la propriétés n'a pas déjà été insérée + if ( !str.contains( toString( "%s\" Value=\"%s\"/>\n", prop.c_str(), val.c_str() ).c_str() ) ) + { + str = str.replace( toString( " \n", zone.c_str() ).c_str(), output.c_str() ); + str.writeToFile( fileName ); + } + } + } + } +} + +// Generate _ic_families.forage_source() +void SaveFamiliesForageSource() +{ + CSString output; + + printf( "-- GROUP ICONS FOR _ic_groups.forage_source --\n"); + + output = "\n"; + output+= "
\n"; + output+= " \n"; + output+= " \n"; + + for ( uint i=0; i!=MPFamilies.size(); ++i ) + { + output+= toString(" \n", MPFamilies[i].Icon.c_str()); + } + + output+= " \n"; + output+= " \n"; + output+= " \n"; + output+= " \n"; + output+= " \n"; + output+= " \n"; + output+= " \n"; + output+= "\n"; + + output.writeToFile( IC_FAMILIES_FORAGE_SOURCE.c_str() ); +} + + +// Génère la documentation +void GenerateDoc() +{ + CProducedDocHtml MainDoc; + CFile::createDirectory("doc"); + MainDoc.open( "doc\\rm.html", "Raw materials by generation order", true ); + MainDoc.write( "
\n" ); + MainDoc.write( "" ); + for ( uint32 c=0; c!=DtNbCols; ++c ) + { + MainDoc.write( "" ); + } + MainDoc.write( "" ); + for ( CRMData::CItems::const_iterator isd=SortableData.items().begin(); isd!=SortableData.items().end(); ++isd ) + { + MainDoc.write( (*isd).toHTMLRow() ); + } + MainDoc.write( "
" + string(DataColStr[c]) + "
\n" ); + + // Produce alt docs + CProducedDocHtml AltDocs[DtNbCols]; + for ( uint32 c=0; c!=DtNbCols; ++c ) + { + AltDocs[c].open( "doc\\rm_" + string(DataColStr[c]) + ".html", "Raw materials by " + string(DataColStr[c]), true ); + AltDocs[c].write( "
\n" ); + AltDocs[c].write( "" ); + for ( uint32 cc=0; cc!=DtNbCols; ++cc ) + if ( cc == c ) + AltDocs[c].write( "" ); + else + AltDocs[c].write( "" ); + AltDocs[c].write( "" ); + string previousKey = "[NO PREVIOUS]"; // not a blank string, because it may be a valid value + string previousName = ""; + for ( CRMData::CLookup::const_iterator isd=SortableData.lookup( c ).begin(); isd!=SortableData.lookup( c ).end(); ++isd ) + { + const TRMItem& item = SortableData.getRow( (*isd).second ); + AltDocs[c].write( item.toHTMLRow( c, (*isd).first, previousKey, DtName, previousName ) ); + + previousKey = (*isd).first; + previousName = item.Fields[DtName][0]; + } + AltDocs[c].write( "
" + string(DataColStr[cc]) + "" + string(DataColStr[cc]) + "
\n" ); + AltDocs[c].save(); + } +} + + +// Initialise les repertoires à partir de raw_material_generation.cfg +void SetupDirectories() +{ + CSString data; + + if ( ! CFile::fileExists( "raw_material_generation.cfg" ) ) + { + nlError( "raw_material_generation.cfg not found\n"); + exit( 1 ); + } + + data.readFromFile( "raw_material_generation.cfg" ); + + LEVEL_DESIGN_PATH = data.splitFrom( "LevelDesignPath = \"").splitTo( "\"" ); + TRANSLATION_PATH = data.splitFrom( "TranslationPath = \"" ).splitTo( "\"" ); + + printf( "Level Design Path : %s\nTranslation Path : %s\n\n", LEVEL_DESIGN_PATH.c_str(), TRANSLATION_PATH.c_str() ); + + ITEM_MP_FAMILY_TYP = LEVEL_DESIGN_PATH + "leveldesign\\DFN\\game_elem\\_item\\item_mp_family.typ"; + ITEM_MP_GROUPE_TYP = LEVEL_DESIGN_PATH + "leveldesign\\DFN\\game_elem\\_item\\item_mp_group.typ"; + ITEM_MP_PARAM_DFN = LEVEL_DESIGN_PATH + "leveldesign\\DFN\\game_elem\\_item\\_item_mp_param.dfn"; + MP_DIRECTORY = LEVEL_DESIGN_PATH + "leveldesign\\game_element\\sitem\\raw_material\\"; + DEPOSIT_MPS = LEVEL_DESIGN_PATH + "leveldesign\\game_element\\deposit_system\\mps\\"; + + RAW_MATERIAL_ASSIGN = LEVEL_DESIGN_PATH + "leveldesign\\Game_elem\\Creature\\raw_material_assignment\\"; + + IC_FAMILIES_FORAGE_SOURCE = LEVEL_DESIGN_PATH + "leveldesign\\game_element\\forage_source\\_ic_families.forage_source"; + + WK_UXT = TRANSLATION_PATH + "work\\wk.uxt"; + ITEM_WORDS_WK = TRANSLATION_PATH + "work\\item_words_wk.txt"; +} + + +// Parcours les différentes familles de MP pour effectuer +// les traitements nécessaires +void LoadFamillesMP() +{ + printf( "-- LOADING RAW MATERIAL FAMILIES --\n" ); + + // Preload wk.uxt, item_mp_family.typ, and item_mp_group.typ (avoid to reload them each time) + FamilyTypContent.readFromFile( ITEM_MP_FAMILY_TYP ); + GroupTypContent.readFromFile( ITEM_MP_GROUPE_TYP ); + WKContent.readFromFile( WK_UXT ); + + // avoid huge resize of vector + MPFamilies.reserve(1000); + + CSString fileData, ligne; + + if ( ! CFile::fileExists( "rm_fam_prop.csv" ) ) + { + nlError( "rm_fam_prop.csv not found\n"); + exit( 1 ); + } + + + fileData.readFromFile( "rm_fam_prop.csv" ); + + ligne = fileData.splitTo( "\n", true ); + + while ( ligne != "" ) + { + NewMP( ligne ); + ligne = fileData.splitTo( "\n", true ); + } + + // le Primitive Necklace n'étant pas spécifié dans la liste des MP + // on le rajoute à la main + CreatePrimitiveNecklace(); +} + + +// Programme principal +int main( int argc, char* argv[] ) +{ + new CApplicationContext; + SortableData.init( true ); + + SetupDirectories(); + + LoadCraftParts(); + + LoadCreatureFiles(); + + InitCreatureMP(); + + LoadFamillesMP(); + + ItemNamesSave(); + + LoadCustomizedProperties(); + + SaveFamiliesForageSource(); + + printf( "-- GENERATING DOCUMENTATION --\n" ); + try + { + GenerateDoc(); + } + catch(const Exception &e) + { + nlwarning(e.what()); + nlwarning("HTML Doc generation failed\n"); + } + + printf( "-- DONE --\n" ); + + return 0; +} diff --git a/code/ryzom/tools/leveldesign/mp_generator/moulinette.h b/code/ryzom/tools/leveldesign/mp_generator/moulinette.h index 5598bcb40..7c6eae753 100644 --- a/code/ryzom/tools/leveldesign/mp_generator/moulinette.h +++ b/code/ryzom/tools/leveldesign/mp_generator/moulinette.h @@ -1,154 +1,154 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef MOULINETTE_H_ -#define MOULINETTE_H_ - - -////////////////////////////////// -// INCLUDE FILES // -////////////////////////////////// -#include -#include -#include "nel/misc/path.h" -#include - -////////////////////////////////// -// USED NAMESPACES // -////////////////////////////////// -using namespace NLMISC; -using namespace std; - - -////////////////////////////////// -// DATA STRUCTURES // -////////////////////////////////// - -enum -{ - NumMPStats= 34, - NumMPCraftParts= 26, // Warning: changing this value won't be sufficient. - // You'll have to look deeper into code -}; - -// Contient la description d'une Craft Part -// ainsi que les différentes caracteristiques -// qu'elle concerne -struct CraftPart -{ - CSString Desc; - bool Carac[NumMPStats]; -}; - -// Caractéristiques d'une MP relatives au craft -struct MPCraftStats -{ - CSString Craft; - bool UsedAsCraftRequirement; - int bestStatA; - int worstStatA1; - int worstStatA2; - int bestStatB; - int worstStatB1; - int worstStatB2; - int color; - - MPCraftStats() - { - UsedAsCraftRequirement= false; - } -}; - -// Permet de trier des chaines de caractères -struct ItemSort : public std::less -{ - bool operator()( const NLMISC::CSString& x, const NLMISC::CSString& y ) const - { - return x.icompare( y ); - } -}; -typedef set CSortedStringSet; - -// Decrit un des items générés -// pour une MP de créature -struct CreatureMPItem -{ - char eco; - int itemLevel; - int creatureLevel; - CSString codeCreature; - CSortedStringSet generatedItems; - CSString creatureFileName; -}; -typedef list ListeCreatureMP; - -// Misc Info on a MP family -class CExtraInfo -{ -public: - bool DropOrSell; - - CExtraInfo() - { - DropOrSell= false; - } -}; - -////////////////////////////////// -// VARIABLES GLOBALES // -////////////////////////////////// - -// Liste des différentes Craft parts -CraftPart craftParts[NumMPCraftParts]; - -// Liste des fichiers .creature -map creatureFiles; - -// noms générés pour chaque item -CSortedStringSet itemNames; - -// Liste des items à generer -// pour chaque code de créature -map itemsAGenerer; - -// MP Family list -class CMPFamily -{ -public: - // Name of the family - CSString Name; - // Icon - CSString Icon; -}; -std::vector MPFamilies; - - -// chemin des différents repertoires -CSString LEVEL_DESIGN_PATH; -CSString TRANSLATION_PATH; - -CSString ITEM_MP_FAMILY_TYP; -CSString ITEM_MP_GROUPE_TYP; -CSString ITEM_MP_PARAM_DFN; -CSString MP_DIRECTORY; -CSString DEPOSIT_MPS; -CSString RAW_MATERIAL_ASSIGN; -CSString IC_FAMILIES_FORAGE_SOURCE; - -CSString WK_UXT; -CSString ITEM_WORDS_WK; - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef MOULINETTE_H_ +#define MOULINETTE_H_ + + +////////////////////////////////// +// INCLUDE FILES // +////////////////////////////////// +#include +#include +#include "nel/misc/path.h" +#include + +////////////////////////////////// +// USED NAMESPACES // +////////////////////////////////// +using namespace NLMISC; +using namespace std; + + +////////////////////////////////// +// DATA STRUCTURES // +////////////////////////////////// + +enum +{ + NumMPStats= 34, + NumMPCraftParts= 26, // Warning: changing this value won't be sufficient. + // You'll have to look deeper into code +}; + +// Contient la description d'une Craft Part +// ainsi que les différentes caracteristiques +// qu'elle concerne +struct CraftPart +{ + CSString Desc; + bool Carac[NumMPStats]; +}; + +// Caractéristiques d'une MP relatives au craft +struct MPCraftStats +{ + CSString Craft; + bool UsedAsCraftRequirement; + int bestStatA; + int worstStatA1; + int worstStatA2; + int bestStatB; + int worstStatB1; + int worstStatB2; + int color; + + MPCraftStats() + { + UsedAsCraftRequirement= false; + } +}; + +// Permet de trier des chaines de caractères +struct ItemSort : public std::less +{ + bool operator()( const NLMISC::CSString& x, const NLMISC::CSString& y ) const + { + return x.icompare( y ); + } +}; +typedef set CSortedStringSet; + +// Decrit un des items générés +// pour une MP de créature +struct CreatureMPItem +{ + char eco; + int itemLevel; + int creatureLevel; + CSString codeCreature; + CSortedStringSet generatedItems; + CSString creatureFileName; +}; +typedef list ListeCreatureMP; + +// Misc Info on a MP family +class CExtraInfo +{ +public: + bool DropOrSell; + + CExtraInfo() + { + DropOrSell= false; + } +}; + +////////////////////////////////// +// VARIABLES GLOBALES // +////////////////////////////////// + +// Liste des différentes Craft parts +CraftPart craftParts[NumMPCraftParts]; + +// Liste des fichiers .creature +map creatureFiles; + +// noms générés pour chaque item +CSortedStringSet itemNames; + +// Liste des items à generer +// pour chaque code de créature +map itemsAGenerer; + +// MP Family list +class CMPFamily +{ +public: + // Name of the family + CSString Name; + // Icon + CSString Icon; +}; +std::vector MPFamilies; + + +// chemin des différents repertoires +CSString LEVEL_DESIGN_PATH; +CSString TRANSLATION_PATH; + +CSString ITEM_MP_FAMILY_TYP; +CSString ITEM_MP_GROUPE_TYP; +CSString ITEM_MP_PARAM_DFN; +CSString MP_DIRECTORY; +CSString DEPOSIT_MPS; +CSString RAW_MATERIAL_ASSIGN; +CSString IC_FAMILIES_FORAGE_SOURCE; + +CSString WK_UXT; +CSString ITEM_WORDS_WK; + #endif \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/mp_generator/utils.h b/code/ryzom/tools/leveldesign/mp_generator/utils.h index 12f395203..6804a5bc7 100644 --- a/code/ryzom/tools/leveldesign/mp_generator/utils.h +++ b/code/ryzom/tools/leveldesign/mp_generator/utils.h @@ -1,330 +1,330 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef UTILS_H_ -#define UTILS_H_ - - -// DtName must be the 1st one -enum TDataCol { DtName, DtTitle, DtRMFamily, DtGroup, DtEcosystem, DtLevelZone, DtStatQuality, DtProp, DtCreature, DtCreaTitle, DtCraftSlotName, DtCraftCivSpec, DtColor, DtAverageEnergy, DtMaxLevel, DtCustomizedProperties, DtNbCols }; -const char *DataColStr [DtNbCols] = { "Code", "Name", "Family", "Group", "Ecosystem", "LevelZone", "Stat Quality", "Properties", "Creature sheets", "Creatures", "Item parts", "Craft civ spec", "Color", "Average energy", "Max level", "Customized" }; - - - -/* - * Multi-indexed array. - * NC is the number of columns. - */ -template -class CSortableData -{ -public: - - /// A row is made of fields, usually 1 per column but there may be more than one (each one is a key) - struct TSortableItem - { - std::vector Fields [NC]; - - /// - void push( uint32 column, const std::string& f, bool allowDuplicates=false ) - { - if ( (allowDuplicates) || (find( Fields[column].begin(), Fields[column].end(), f ) == Fields[column].end()) ) - Fields[column].push_back( f ); - } - - /// - void reset( uint32 column ) - { - Fields[ column ].clear(); - } - - /** - * Display the item as a row of a HTML table. - * If (key!=previousKey) and (name==previousName), the row will not be displayed entirely to save space - * - * \param keyColumn If not ~0, column used for sorting => this column displays only the field matching the key - * \param key The key used for sorting (see keyColumn) - * \param previousKey Previous key - * \param nameColumn If not ~0, column used for the unique name (column must have exaclty one element) - * \param previousName Previous name - */ - std::string toHTMLRow( uint32 keyColumn=~0, const string& key=string(), const string& previousKey=string(), - uint32 nameColumn=~0, const string& previousName=string() ) const - { - std::string s = ""; - bool lightMode = (nameColumn == ~0) ? false : ((key != previousKey) && (Fields[nameColumn][0] == previousName)); - for ( uint32 c=0; c!=NC; ++c ) - { - s += ""; - } - s += "\n"; - return s; - } - - - /// - std::string toCSVLine( char columnSeparator=',', string internalSeparator=" - ", uint32 keyColumn=~0, const string& key=string(), const string& previousKey=string(), - uint32 nameColumn=~0, const string& previousName=string() ) const - { - std::string s; - bool lightMode = (nameColumn == ~0) ? false : ((key != previousKey) && (Fields[nameColumn][0] == previousName)); - for ( uint32 c=0; c!=NC; ++c ) - { - if ( c == keyColumn ) - s += key; // key should be a substr of columnToString( c ) - else - { - if ( lightMode ) - s += "\""; - else - s += columnToString( c, internalSeparator ); - } - s += columnSeparator; - } - s += "\n"; - return s; - } - - /// - std::string columnToString( uint32 column, const std::string& internalSeparator=", " ) const - { - std::string s; - std::vector::const_iterator ivs; - for ( ivs=Fields[column].begin(); ivs!=Fields[column].end(); ++ivs ) - { - if ( ivs!=Fields[column].begin() ) - s += internalSeparator; - s += (*ivs); - } - return s; - } - }; - - typedef std::multimap< std::string, uint32 > CLookup; // key to index (not pt because reallocation invalidates pointers) - typedef std::vector< TSortableItem > CItems; - - /// Init - void init( bool enabled ) - { - _Enabled = enabled; - } - - /// Add a row - void addItem( const TSortableItem& item ) - { - if ( ! _Enabled ) - return; - - _Items.push_back( item ); - for ( uint32 c=0; c!=NC; ++c ) - { - for ( std::vector::const_iterator ik=item.Fields[c].begin(); ik!=item.Fields[c].end(); ++ik ) - { - _Indices[c].insert( make_pair( *ik, (uint32)_Items.size()-1 ) ); - } - } - } - - /** - * Update a row (found by the first column, which must have exactly one element). - * Returns true if it existed before, false if it's being created. - * If it existed before: - * - Does not remove elements that already exist and are not in the new item - * - Adds the new elements found in the new item at the specified columns, and updates lookup map - */ - bool updateItemAppend( const TSortableItem& item, uint32 column ) - { - if ( ! _Enabled ) - return true; // quiet - - uint32 nameColumn = 0; - CLookup::iterator ilk = _Indices[nameColumn].find( item.Fields[nameColumn][0] ); - if ( ilk != _Indices[nameColumn].end() ) - { - uint32& index = (*ilk).second; - - // Update map for the specified column - // and update item column - for ( std::vector::const_iterator ivs=item.Fields[column].begin(); ivs!=item.Fields[column].end(); ++ivs ) - { - ilk = _Indices[column].find( *ivs ); - if ( (ilk == _Indices[column].end()) || ( getRow( (*ilk).second ).Fields[nameColumn][0] != item.Fields[nameColumn][0]) ) - { - _Indices[column].insert( make_pair( *ivs, index ) ); - _Items[index].Fields[column].push_back( *ivs ); - } - } - - return true; - } - else - { - addItem( item ); - return false; - } - } - - /** - * Update a row (found by the first column, which must have exactly one element). - * Returns true if it existed before, false if it's being created. - * If it existed before: - * - Does not update lookup maps or item for columns that were already present. - * - Adds entries in lookup maps and updates item for new columns (fields that were empty). - */ - /*bool updateItemAppend( const TSortableItem& item ) - { - if ( ! _Enabled ) - return true; // quiet - - CLookup::iterator ilk = _Indices[0].find( item.Fields[0][0] ); - if ( ilk != _Indices[0].end() ) - { - uint32& index = (*ilk).second; - - for ( uint32 c=1; c!=NC; ++c ) - { - // Update maps for previously empty columns - if ( _Items[index].Fields[c].empty() ) - { - for ( std::vector::iterator ivs=item.Fields[c].begin(); ivs!=item.Fields[c].end(); ++ivs ) - _Indices[c].insert( make_pair( *ivs, index ) ); - } - - // Update item column - _Items[index].Fields[c] = item.Fields[c]; - } - - return true; - } - else - { - addItem( item ); - return false; - } - }*/ - - /// Find or browse by key - CLookup& lookup( uint32 column ) - { - return _Indices[column]; - } - - /// Browse by adding order - CItems& items() - { - return _Items; - } - - /// Get a row by index - TSortableItem& getRow( uint32 index ) - { - return _Items[index]; - } - -private: - - CLookup _Indices [NC]; - - CItems _Items; - - bool _Enabled; -}; - - -typedef CSortableData CRMData; -typedef CRMData::TSortableItem TRMItem; - - -/** - * - */ -class CProducedDocHtml -{ -public: - - /// - CProducedDocHtml() : _File(NULL), _Enabled(false) {} - - /// - void open( const std::string& filename, const std::string& title, bool enableFlag ) - { - _Enabled = enableFlag; - if ( ! _Enabled ) - return; - - _File = fopen( filename.c_str(), "wt" ); - if(!_File) - { - throw Exception("Could not open html: %s", filename.c_str()); - } - fprintf( _File, ("\n\n" + title + "\n\n").c_str() ); - } - - /// - void write( const std::string& htmlCode ) - { - if ( ! _Enabled ) - return; - - fprintf( _File, htmlCode.c_str() ); - } - - /// - void writeln( const std::string& htmlCode ) - { - write( htmlCode + "\n" ); - } - - /// - void writebln( const std::string& htmlCode ) - { - write( htmlCode + "
\n" ); - } - - /// - void writepln( const std::string& htmlCode ) - { - write( "

" + htmlCode + "

\n" ); - } - - /// - void save() - { - if ( ! _Enabled ) - return; - - fprintf( _File, "\n" ); - fclose( _File ); - } - -private: - - FILE *_File; - bool _Enabled; -}; - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef UTILS_H_ +#define UTILS_H_ + + +// DtName must be the 1st one +enum TDataCol { DtName, DtTitle, DtRMFamily, DtGroup, DtEcosystem, DtLevelZone, DtStatQuality, DtProp, DtCreature, DtCreaTitle, DtCraftSlotName, DtCraftCivSpec, DtColor, DtAverageEnergy, DtMaxLevel, DtCustomizedProperties, DtNbCols }; +const char *DataColStr [DtNbCols] = { "Code", "Name", "Family", "Group", "Ecosystem", "LevelZone", "Stat Quality", "Properties", "Creature sheets", "Creatures", "Item parts", "Craft civ spec", "Color", "Average energy", "Max level", "Customized" }; + + + +/* + * Multi-indexed array. + * NC is the number of columns. + */ +template +class CSortableData +{ +public: + + /// A row is made of fields, usually 1 per column but there may be more than one (each one is a key) + struct TSortableItem + { + std::vector Fields [NC]; + + /// + void push( uint32 column, const std::string& f, bool allowDuplicates=false ) + { + if ( (allowDuplicates) || (find( Fields[column].begin(), Fields[column].end(), f ) == Fields[column].end()) ) + Fields[column].push_back( f ); + } + + /// + void reset( uint32 column ) + { + Fields[ column ].clear(); + } + + /** + * Display the item as a row of a HTML table. + * If (key!=previousKey) and (name==previousName), the row will not be displayed entirely to save space + * + * \param keyColumn If not ~0, column used for sorting => this column displays only the field matching the key + * \param key The key used for sorting (see keyColumn) + * \param previousKey Previous key + * \param nameColumn If not ~0, column used for the unique name (column must have exaclty one element) + * \param previousName Previous name + */ + std::string toHTMLRow( uint32 keyColumn=~0, const string& key=string(), const string& previousKey=string(), + uint32 nameColumn=~0, const string& previousName=string() ) const + { + std::string s = "
"; + bool lightMode = (nameColumn == ~0) ? false : ((key != previousKey) && (Fields[nameColumn][0] == previousName)); + for ( uint32 c=0; c!=NC; ++c ) + { + s += ""; + } + s += "\n"; + return s; + } + + + /// + std::string toCSVLine( char columnSeparator=',', string internalSeparator=" - ", uint32 keyColumn=~0, const string& key=string(), const string& previousKey=string(), + uint32 nameColumn=~0, const string& previousName=string() ) const + { + std::string s; + bool lightMode = (nameColumn == ~0) ? false : ((key != previousKey) && (Fields[nameColumn][0] == previousName)); + for ( uint32 c=0; c!=NC; ++c ) + { + if ( c == keyColumn ) + s += key; // key should be a substr of columnToString( c ) + else + { + if ( lightMode ) + s += "\""; + else + s += columnToString( c, internalSeparator ); + } + s += columnSeparator; + } + s += "\n"; + return s; + } + + /// + std::string columnToString( uint32 column, const std::string& internalSeparator=", " ) const + { + std::string s; + std::vector::const_iterator ivs; + for ( ivs=Fields[column].begin(); ivs!=Fields[column].end(); ++ivs ) + { + if ( ivs!=Fields[column].begin() ) + s += internalSeparator; + s += (*ivs); + } + return s; + } + }; + + typedef std::multimap< std::string, uint32 > CLookup; // key to index (not pt because reallocation invalidates pointers) + typedef std::vector< TSortableItem > CItems; + + /// Init + void init( bool enabled ) + { + _Enabled = enabled; + } + + /// Add a row + void addItem( const TSortableItem& item ) + { + if ( ! _Enabled ) + return; + + _Items.push_back( item ); + for ( uint32 c=0; c!=NC; ++c ) + { + for ( std::vector::const_iterator ik=item.Fields[c].begin(); ik!=item.Fields[c].end(); ++ik ) + { + _Indices[c].insert( make_pair( *ik, (uint32)_Items.size()-1 ) ); + } + } + } + + /** + * Update a row (found by the first column, which must have exactly one element). + * Returns true if it existed before, false if it's being created. + * If it existed before: + * - Does not remove elements that already exist and are not in the new item + * - Adds the new elements found in the new item at the specified columns, and updates lookup map + */ + bool updateItemAppend( const TSortableItem& item, uint32 column ) + { + if ( ! _Enabled ) + return true; // quiet + + uint32 nameColumn = 0; + CLookup::iterator ilk = _Indices[nameColumn].find( item.Fields[nameColumn][0] ); + if ( ilk != _Indices[nameColumn].end() ) + { + uint32& index = (*ilk).second; + + // Update map for the specified column + // and update item column + for ( std::vector::const_iterator ivs=item.Fields[column].begin(); ivs!=item.Fields[column].end(); ++ivs ) + { + ilk = _Indices[column].find( *ivs ); + if ( (ilk == _Indices[column].end()) || ( getRow( (*ilk).second ).Fields[nameColumn][0] != item.Fields[nameColumn][0]) ) + { + _Indices[column].insert( make_pair( *ivs, index ) ); + _Items[index].Fields[column].push_back( *ivs ); + } + } + + return true; + } + else + { + addItem( item ); + return false; + } + } + + /** + * Update a row (found by the first column, which must have exactly one element). + * Returns true if it existed before, false if it's being created. + * If it existed before: + * - Does not update lookup maps or item for columns that were already present. + * - Adds entries in lookup maps and updates item for new columns (fields that were empty). + */ + /*bool updateItemAppend( const TSortableItem& item ) + { + if ( ! _Enabled ) + return true; // quiet + + CLookup::iterator ilk = _Indices[0].find( item.Fields[0][0] ); + if ( ilk != _Indices[0].end() ) + { + uint32& index = (*ilk).second; + + for ( uint32 c=1; c!=NC; ++c ) + { + // Update maps for previously empty columns + if ( _Items[index].Fields[c].empty() ) + { + for ( std::vector::iterator ivs=item.Fields[c].begin(); ivs!=item.Fields[c].end(); ++ivs ) + _Indices[c].insert( make_pair( *ivs, index ) ); + } + + // Update item column + _Items[index].Fields[c] = item.Fields[c]; + } + + return true; + } + else + { + addItem( item ); + return false; + } + }*/ + + /// Find or browse by key + CLookup& lookup( uint32 column ) + { + return _Indices[column]; + } + + /// Browse by adding order + CItems& items() + { + return _Items; + } + + /// Get a row by index + TSortableItem& getRow( uint32 index ) + { + return _Items[index]; + } + +private: + + CLookup _Indices [NC]; + + CItems _Items; + + bool _Enabled; +}; + + +typedef CSortableData CRMData; +typedef CRMData::TSortableItem TRMItem; + + +/** + * + */ +class CProducedDocHtml +{ +public: + + /// + CProducedDocHtml() : _File(NULL), _Enabled(false) {} + + /// + void open( const std::string& filename, const std::string& title, bool enableFlag ) + { + _Enabled = enableFlag; + if ( ! _Enabled ) + return; + + _File = fopen( filename.c_str(), "wt" ); + if(!_File) + { + throw Exception("Could not open html: %s", filename.c_str()); + } + fprintf( _File, ("\n\n" + title + "\n\n").c_str() ); + } + + /// + void write( const std::string& htmlCode ) + { + if ( ! _Enabled ) + return; + + fprintf( _File, htmlCode.c_str() ); + } + + /// + void writeln( const std::string& htmlCode ) + { + write( htmlCode + "\n" ); + } + + /// + void writebln( const std::string& htmlCode ) + { + write( htmlCode + "
\n" ); + } + + /// + void writepln( const std::string& htmlCode ) + { + write( "

" + htmlCode + "

\n" ); + } + + /// + void save() + { + if ( ! _Enabled ) + return; + + fprintf( _File, "\n" ); + fclose( _File ); + } + +private: + + FILE *_File; + bool _Enabled; +}; + + #endif \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/named_items_2_csv/named_items_2_csv.cpp b/code/ryzom/tools/leveldesign/named_items_2_csv/named_items_2_csv.cpp index 5dee56474..ca89cae2f 100644 --- a/code/ryzom/tools/leveldesign/named_items_2_csv/named_items_2_csv.cpp +++ b/code/ryzom/tools/leveldesign/named_items_2_csv/named_items_2_csv.cpp @@ -1,562 +1,562 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -/* - author : Fabien Houlmann - houlmann@nevrax.com - date : 13/10/2005 - - named2csv: convert named_items.txt to .csv format and convert it back - to named_items.txt after changes. - - use: named2csv named_items.txt filter.script (to generate a .csv based on filter) - named2csv named_items.txt named_items.csv (to modify .txt with .csv) - - */ - -#include "nel/misc/common.h" -#include "nel/misc/debug.h" -#include "nel/misc/sstring.h" -#include "nel/misc/path.h" -#include "nel/misc/file.h" -#include - -using namespace NLMISC; -using namespace std; - -// function declaration -int verifItemsFile (const char *filename); -int verifCsvFile (const char *filename); -void processItemLine (const string &s); -int getItemsFromFile (const char *filename); -int getFieldsFromFile(const char *filename); -int getNbItemFromFile(const char *filename); -int exportCsv (const char *filename); -int importCsv (const char *filename); -void getItemBounds (const CVectorSString &lines, uint num, uint &a, uint &b); -void updateItemField (CVectorSString &lines, uint itemIndex, uint fieldIndex, uint &a, uint &b); -void addNewItem (CVectorSString &lines, uint itemIndex); -int updateItems (const char *filename); - -// global access -CVectorSString fields; -vector items; - -// check the items file (locSlot and item number coherence) -int verifItemsFile (const char *filename) -{ - FILE *f = fopen(filename, "r"); - if (f == NULL) - nlerror("Can't open file : %s", filename); - - char buffer[1024]; - while (fgets(buffer, 1024, f)) - { - string s(buffer); - - // null or comment - if (s == "" || s.find("//") == 0) - continue; - - if (s.find("_LocSlot") == string::npos) - continue; - - // get item numbers - int n1, n2; - sscanf(buffer, "_Items#%d._LocSlot=%d", &n1, &n2); - - // check - if (n1 != n2) - nlerror("item number (%d) and _LocSlot(%d) don't match !", n1, n2); - } - - fclose(f); - return 0; -} - -// check csv file (locSlot and item number coherence) -int verifCsvFile (const char *filename) -{ - FILE *f = fopen(filename, "r"); - if (f == NULL) - nlerror("Can't open file : %s", filename); - - uint prevId = -1; - char buffer[1024]; - // skip first line - fgets(buffer, 1024, f); - while (fgets(buffer, 1024, f)) - { - uint id = atoi(buffer); - if (id-1 != prevId) - nlerror("item number (%d) and previous item (%d) don't match !", id, prevId); - prevId = id; - } - - fclose(f); - return 0; -} - -// parse a line from source file -void processItemLine(const string &s) -{ - // null or comment - if (s == "" || s.find("//") == 0) - return; - - // other stuff - if (s.find("_Items#") == string::npos) - return; - - // get item number - int n; - sscanf(s.c_str(), "_Items#%d", &n); - - // check fields - for (uint i=0 ; i max) - max = n; - } - - fclose(f); - return max; -} - -// generate .csv file based on actual filled structure -int exportCsv(const char *filename) -{ - nlassert(fields.size() != 0); - - uint i, j; - FILE *f = fopen(filename, "w"); - if (f == NULL) - nlerror("Can't open file : %s", filename); - - // print fields name - for (i=0 ; i items.size()) - items.resize(n+1); - - // add item id - items[n].push_back(val); - - // add others - do - { - val = s.splitTo(';', true); - items[n].push_back(val); - } while (s != ""); - } - - fclose(f); - return 0; -} - -// compute item boundary in the file (min and max lines) -void getItemBounds(const CVectorSString &lines, uint num, uint &a, uint &b) -{ - a = b = 0; - uint i = -1; - bool ok = false; - - while (++i < lines.size() && !ok) - { - if (lines[i] == "" || lines[i].find("//") != string::npos) - continue; - - // get item number - uint n; - if (sscanf(lines[i].c_str(), "_Items#%d", &n) == 0) - continue; - - // find it - if (n == num) - { - // frist line - if (a == 0) - a = b = i+1; - // more line - else - b++; - } - else - { - // end - if (a != 0) - ok = true; - } - } - - // found it ? - if (a != 0) - { - ok = true; - b++; - } -} - -// update an item field with a new value -void updateItemField(CVectorSString &lines, uint itemIndex, uint fieldIndex, uint &a, uint &b) -{ - string field = fields[fieldIndex]; - string val = items[itemIndex][fieldIndex]; - string s = "_Items#"; - s += toString(itemIndex); - s += "."; - s += field; - - // remove jump - val = CSString(val).strtok("\n"); - - uint craftLine = 0; - bool found = false; - uint i = a-1; - - // first pass to check if param have changed - for (i=a ; i= items[itemIndex].size()); - cout << "Updating item " << itemIndex << endl; - - uint a, b; - getItemBounds(lines, itemIndex, a, b); - - // no bound found, it's a new item - if (b == 0) - { - addNewItem(lines, itemIndex); - getItemBounds(lines, itemIndex, a, b); - } - - for (uint fieldIndex=0 ; fieldIndex +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +/* + author : Fabien Houlmann - houlmann@nevrax.com + date : 13/10/2005 + + named2csv: convert named_items.txt to .csv format and convert it back + to named_items.txt after changes. + + use: named2csv named_items.txt filter.script (to generate a .csv based on filter) + named2csv named_items.txt named_items.csv (to modify .txt with .csv) + + */ + +#include "nel/misc/common.h" +#include "nel/misc/debug.h" +#include "nel/misc/sstring.h" +#include "nel/misc/path.h" +#include "nel/misc/file.h" +#include + +using namespace NLMISC; +using namespace std; + +// function declaration +int verifItemsFile (const char *filename); +int verifCsvFile (const char *filename); +void processItemLine (const string &s); +int getItemsFromFile (const char *filename); +int getFieldsFromFile(const char *filename); +int getNbItemFromFile(const char *filename); +int exportCsv (const char *filename); +int importCsv (const char *filename); +void getItemBounds (const CVectorSString &lines, uint num, uint &a, uint &b); +void updateItemField (CVectorSString &lines, uint itemIndex, uint fieldIndex, uint &a, uint &b); +void addNewItem (CVectorSString &lines, uint itemIndex); +int updateItems (const char *filename); + +// global access +CVectorSString fields; +vector items; + +// check the items file (locSlot and item number coherence) +int verifItemsFile (const char *filename) +{ + FILE *f = fopen(filename, "r"); + if (f == NULL) + nlerror("Can't open file : %s", filename); + + char buffer[1024]; + while (fgets(buffer, 1024, f)) + { + string s(buffer); + + // null or comment + if (s == "" || s.find("//") == 0) + continue; + + if (s.find("_LocSlot") == string::npos) + continue; + + // get item numbers + int n1, n2; + sscanf(buffer, "_Items#%d._LocSlot=%d", &n1, &n2); + + // check + if (n1 != n2) + nlerror("item number (%d) and _LocSlot(%d) don't match !", n1, n2); + } + + fclose(f); + return 0; +} + +// check csv file (locSlot and item number coherence) +int verifCsvFile (const char *filename) +{ + FILE *f = fopen(filename, "r"); + if (f == NULL) + nlerror("Can't open file : %s", filename); + + uint prevId = -1; + char buffer[1024]; + // skip first line + fgets(buffer, 1024, f); + while (fgets(buffer, 1024, f)) + { + uint id = atoi(buffer); + if (id-1 != prevId) + nlerror("item number (%d) and previous item (%d) don't match !", id, prevId); + prevId = id; + } + + fclose(f); + return 0; +} + +// parse a line from source file +void processItemLine(const string &s) +{ + // null or comment + if (s == "" || s.find("//") == 0) + return; + + // other stuff + if (s.find("_Items#") == string::npos) + return; + + // get item number + int n; + sscanf(s.c_str(), "_Items#%d", &n); + + // check fields + for (uint i=0 ; i max) + max = n; + } + + fclose(f); + return max; +} + +// generate .csv file based on actual filled structure +int exportCsv(const char *filename) +{ + nlassert(fields.size() != 0); + + uint i, j; + FILE *f = fopen(filename, "w"); + if (f == NULL) + nlerror("Can't open file : %s", filename); + + // print fields name + for (i=0 ; i items.size()) + items.resize(n+1); + + // add item id + items[n].push_back(val); + + // add others + do + { + val = s.splitTo(';', true); + items[n].push_back(val); + } while (s != ""); + } + + fclose(f); + return 0; +} + +// compute item boundary in the file (min and max lines) +void getItemBounds(const CVectorSString &lines, uint num, uint &a, uint &b) +{ + a = b = 0; + uint i = -1; + bool ok = false; + + while (++i < lines.size() && !ok) + { + if (lines[i] == "" || lines[i].find("//") != string::npos) + continue; + + // get item number + uint n; + if (sscanf(lines[i].c_str(), "_Items#%d", &n) == 0) + continue; + + // find it + if (n == num) + { + // frist line + if (a == 0) + a = b = i+1; + // more line + else + b++; + } + else + { + // end + if (a != 0) + ok = true; + } + } + + // found it ? + if (a != 0) + { + ok = true; + b++; + } +} + +// update an item field with a new value +void updateItemField(CVectorSString &lines, uint itemIndex, uint fieldIndex, uint &a, uint &b) +{ + string field = fields[fieldIndex]; + string val = items[itemIndex][fieldIndex]; + string s = "_Items#"; + s += toString(itemIndex); + s += "."; + s += field; + + // remove jump + val = CSString(val).strtok("\n"); + + uint craftLine = 0; + bool found = false; + uint i = a-1; + + // first pass to check if param have changed + for (i=a ; i= items[itemIndex].size()); + cout << "Updating item " << itemIndex << endl; + + uint a, b; + getItemBounds(lines, itemIndex, a, b); + + // no bound found, it's a new item + if (b == 0) + { + addNewItem(lines, itemIndex); + getItemBounds(lines, itemIndex, a, b); + } + + for (uint fieldIndex=0 ; fieldIndex -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include -#include -#include - -#include "nel/misc/config_file.h" -#include "nel/misc/file.h" -#include "nel/misc/i_xml.h" -#include "nel/misc/path.h" -#include "nel/misc/progress_callback.h" - -#include "nel/ligo/primitive.h" -#include "nel/ligo/ligo_config.h" - -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" -#include "nel/georges/u_form_loader.h" - -#include "nel/3d/zone.h" -#include "nel/3d/landscape.h" -#include "nel/3d/scene_group.h" - -#ifdef NL_OS_WINDOWS -#include -#endif // NL_OS_WINDOWS - -// *************************************************************************** - -/* -Documentation - -This tool generates ig from primitive files - - - Load the landscape zone. Load all the *.zonew found in the InLandscapeDir and add them in a landscape - - For each primitive files found in PrimDirs - - Look for points with the "prim" primitive class - - Get the good height on the landscape - - Get the .plant georges file associed with the point - - Add an entry in the good ig file - - Set the shape filename - - Set the plant name - - Set the final position (x and y come from the primitive and z from height test with the landscape, the rotation comes from the primitive) - - Set the ig date - - The date is the most recent date between the .zonew .plant .primitive files associed with the ig. - - Snap to ground only modified or created ig - - Save the modified or created ig files -*/ - -// *************************************************************************** - -using namespace std; -using namespace NLMISC; -using namespace NL3D; -using namespace NLGEORGES; -using namespace NLLIGO; - -// *************************************************************************** -// Utility functions -// *************************************************************************** - -#define SELECTION_EPSILON 0.1f - -#define BAR_LENGTH 21 - -const char *progressbar[BAR_LENGTH]= -{ - "[ ]", - "[. ]", - "[.. ]", - "[... ]", - "[.... ]", - "[..... ]", - "[...... ]", - "[....... ]", - "[........ ]", - "[......... ]", - "[.......... ]", - "[........... ]", - "[............ ]", - "[............. ]", - "[.............. ]", - "[............... ]", - "[................ ]", - "[................. ]", - "[.................. ]", - "[................... ]", - "[....................]" -}; - -// *************************************************************************** - -// Progress bar -class CMyCallback : public IProgressCallback -{ -public: - void progress (float progress) - { - // Delta time, update max all the 300 ms - static sint64 time = CTime::getLocalTime (); - sint64 currentTime = CTime::getLocalTime (); - if ((currentTime - time) > 300) - { - // Crop the progress bar value - progress = getCropedValue (progress); - - // Progress bar - char msg[512]; - uint pgId= (uint)(progress*(float)BAR_LENGTH); - pgId= min(pgId, (uint)(BAR_LENGTH-1)); - sprintf (msg, "\r%s: %s", DisplayString.c_str (), progressbar[pgId]); - uint i; - for (i=(uint)strlen(msg); i<79; i++) - msg[i]=' '; - msg[i]=0; - printf ("%s", msg); - printf ("\r"); - - time = currentTime; - } - } -}; - -// *************************************************************************** - -sint getXFromZoneName (const string &ZoneName) -{ - string xStr, yStr; - uint32 i = 0; - while (ZoneName[i] != '_') - { - yStr += ZoneName[i]; ++i; - if (i == ZoneName.size()) - return -1; - } - ++i; - while (i < ZoneName.size()) - { - xStr += ZoneName[i]; ++i; - } - return ((xStr[0] - 'A')*26 + (xStr[1] - 'A')); -} - -// *************************************************************************** - -bool getZoneCoordByName(const char * name, uint16& x, uint16& y) -{ - uint i; - - std::string zoneName(name); - - // y - std::string::size_type ind1 = zoneName.find("_"); - if(ind1 == std::string::npos) - { - nlwarning("bad file name"); - return false; - } - std::string ystr = zoneName.substr(0,ind1); - for(i=0; idisplayRaw(sText.c_str()); -} - -// *************************************************************************** - -string getPrimitiveName (const IPrimitive &primitive) -{ - string name; - primitive.getPropertyByName ("name", name); - return name; -} - -// *************************************************************************** - -uint16 getZoneId (sint x, sint y) -{ - return (uint16)((((-y)-1)<<8) + x); -} - -// *************************************************************************** - -void getLettersFromNum(uint16 num, std::string& code) -{ - if(num>26*26) - { - nlwarning("zone index too high"); - return; - } - code.resize(0); - uint16 remainder = num%26; - code += 'A' + num/26; - code += 'A' + remainder; -} - -// *************************************************************************** - -void getZoneNameByCoord(sint16 x, sint16 y, std::string& zoneName) -{ - if ((y>0) || (y<-255) || (x<0) || (x>255)) - return; - zoneName = toString(-y) + "_"; - zoneName += ('A' + (x/26)); - zoneName += ('A' + (x%26)); -} - -// *************************************************************************** - -bool triangleIntersect2DGround (const CTriangle &tri, const CVector &pos0) -{ - const CVector &p0= tri.V0; - const CVector &p1= tri.V1; - const CVector &p2= tri.V2; - - // Test if the face enclose the pos in X/Y plane. - // NB: compute and using a BBox to do a rapid test is not a very good idea, since it will - // add an overhead which is NOT negligeable compared to the following test. - float a,b,c; // 2D cartesian coefficients of line in plane X/Y. - // Line p0-p1. - a= -(p1.y-p0.y); - b= (p1.x-p0.x); - c= -(p0.x*a + p0.y*b); - if( (a*pos0.x + b*pos0.y + c) < 0) return false; - // Line p1-p2. - a= -(p2.y-p1.y); - b= (p2.x-p1.x); - c= -(p1.x*a + p1.y*b); - if( (a*pos0.x + b*pos0.y + c) < 0) return false; - // Line p2-p0. - a= -(p0.y-p2.y); - b= (p0.x-p2.x); - c= -(p2.x*a + p2.y*b); - if( (a*pos0.x + b*pos0.y + c) < 0) return false; - - return true; -} - -// *************************************************************************** -// CExportOptions -// *************************************************************************** - -struct CExportOptions -{ - std::string InLandscapeDir; // Directory where to get .zonew files - std::string OutIGDir; // Directory where to put IG - std::string LandBankFile; // The .smallbank file associated with the landscape - std::string LandFarBankFile; // The .farbank file - float CellSize; // Typically 160.0 - std::string LandTileNoiseDir; // Directory where to get displacement map - - std::vector PrimDirs; // Directory to parse for .flora and .prim associated - // This is here we get continent.cfg file - std::string FormDir; // Directory to get georges dfn - - CExportOptions (); - bool loadcf (NLMISC::CConfigFile &cf); -}; - -// *************************************************************************** - -CExportOptions::CExportOptions () -{ - CellSize = 160.0f; -} - -// *************************************************************************** - -bool CExportOptions::loadcf (CConfigFile &cf) -{ - // Out - CConfigFile::CVar &cvOutIGDir = cf.getVar("OutIGDir"); - OutIGDir = cvOutIGDir.asString(); - - // In - CConfigFile::CVar &cvInLandscapeDir = cf.getVar("ZoneWDir"); - InLandscapeDir = cvInLandscapeDir.asString(); - - CConfigFile::CVar &cvLandBankFile = cf.getVar("SmallBank"); - LandBankFile = cvLandBankFile.asString(); - CConfigFile::CVar &cvLandFarBankFile = cf.getVar("FarBank"); - LandFarBankFile = cvLandFarBankFile.asString(); - CConfigFile::CVar &cvLandTileNoiseDir = cf.getVar("DisplaceDir"); - LandTileNoiseDir = cvLandTileNoiseDir.asString(); - - CConfigFile::CVar &cvCellSize = cf.getVar("CellSize"); - CellSize = cvCellSize.asFloat(); - - CConfigFile::CVar &cvPrimDir = cf.getVar("PrimDirs"); - uint i; - PrimDirs.resize (cvPrimDir.size()); - for (i=0; i<(uint)cvPrimDir.size(); i++) - PrimDirs[i] = cvPrimDir.asString(i); - - CConfigFile::CVar &cvFormDir = cf.getVar("FormDir"); - FormDir = cvFormDir.asString(); - - return true; -} - -// *************************************************************************** - -// Array of ig -class CIgContainer -{ -public: - - // An ig - class CIG - { - public: - // Additionnal parameters - class CAdditionnalParam - { - public: - CAdditionnalParam (uint snapLayer, const string &primitiveName, const string &primitiveFile, bool snap) : SnapLayer (snapLayer), PrimitiveName (primitiveName), PrimitiveFile (primitiveFile) - { - Snap = snap; - }; - - // Snap over the landscape - bool Snap; - - // Snap layer - uint SnapLayer; - - // Primitive name - string PrimitiveName; - - // Primitive file - string PrimitiveFile; - }; - - // Default ctor - CIG () - { - Date = 0; - } - - // Update date if new date is more recent - void updateDate (uint32 newDate) - { - if (newDate > Date) - Date = newDate; - } - - // The ig - CInstanceGroup::TInstanceArray Instances; - - // Additionnal information - vector AdditionnalInfo; - - // The ig date - uint32 Date; - }; - - // Init the container - void init (sint minx, sint maxx, sint miny, sint maxy, const char *zoneDir) - { - // Save the values - Minx = minx; - Miny = miny; - Maxx = maxx+1; - Maxy = maxy+1; - Width = maxx - minx + 1; - - // Resize the array - IGS.clear (); - IGS.resize (Width*(maxy-miny+1)); - - // Directory - string dir = CPath::standardizePath (zoneDir, true); - - // For each zone - for (sint y=miny; y<=maxy; y++) - for (sint x=minx; x<=maxx; x++) - { - // The zone name - string zoneFilename; - getZoneNameByCoord ((sint16)x, (sint16)y, zoneFilename); - zoneFilename = dir + zoneFilename + ".zonew"; - - // Get the date - if (CFile::fileExists (zoneFilename)) - get (x, y).Date = CFile::getFileModificationDate (zoneFilename); - } - } - - // Get the ig - CIG &get (sint x, sint y) - { - return IGS[(x-Minx)+(y-Miny)*Width]; - } - - // Size and position - uint Width; - sint Minx; - sint Miny; - sint Maxx; - sint Maxy; - - // The ig vector - vector IGS; -}; - -// *************************************************************************** - -// Array of ig -class CFormContainer -{ -private: - // The map value - struct CValue - { - CValue (CSmartPtr ptr, uint32 date) : Ptr (ptr), Date (date) {}; - - // The form pointer - CSmartPtr Ptr; - - // Its date - uint32 Date; - }; -public: - - // Default ctor - CFormContainer () - { - _FormLoader = UFormLoader::createLoader (); - } - - // Dtor - ~CFormContainer () - { - UFormLoader::releaseLoader (_FormLoader); - } - - // The form container - const UForm *loadForm (const char *formName, uint32 &formDate) - { - // The form - UForm *form = NULL; - formDate = 0; - - // In the map ? - string formShortName = NLMISC::toLower(CFile::getFilename (formName)); - map::iterator ite = _FormMap.find (formShortName); - if (ite == _FormMap.end ()) - { - // Look for this plant file - string path = CPath::lookup (formName, false, false, false); - if (!path.empty ()) - { - // Load it ! - form = _FormLoader->loadForm (path.c_str ()); - if (form) - { - // Get dependencies - set dependencies; - form->getDependencies (dependencies); - - // Get dependencies dates - formDate = 0; - set::const_iterator ite = dependencies.begin (); - while (ite != dependencies.end ()) - { - // Get the path name - string path = CPath::lookup (*ite, false, false, false); - if (!path.empty ()) - { - // Get the file date - uint32 date = CFile::getFileModificationDate (path); - - // Update date - if (date > formDate) - formDate = date; - } - - // Next dependency - ite++; - } - - // Add it - _FormMap.insert (map::value_type (formShortName, CValue (form, formDate))); - } - else - { - // Error in the log - nlwarning ("Error : Can't load the form (%s)", path.c_str ()); - } - } - } - else - { - form = ite->second.Ptr; - formDate = ite->second.Date; - } - - // Return the form or NULL - return form; - } - -private: - - // The form loader - UFormLoader *_FormLoader; - - // The form map - map _FormMap; -}; - -// *************************************************************************** - -void addPointPrimitive (CLandscape &landscape, const char *primFilename, uint32 primFileDate, const IPrimitive &primitive, CIgContainer &igs, - const CExportOptions &options, CFormContainer &formContainer, IProgressCallback &callback) -{ - // Is this primitive a point ? - const CPrimPoint *point = dynamic_cast(&primitive); - if (point) - { - // Get the class name - string className; - if (point->getPropertyByName ("class", className)) - { - // Is it a plant ? - if (className == "prim") - { - // Get its plant name - string plantFilename; - if (point->getPropertyByName ("form", plantFilename)) - { - // Add an extension - if (NLMISC::toLower(CFile::getExtension (plantFilename)) != "plant") - plantFilename += ".plant"; - - // Load this form - uint32 formDate; - const UForm *form = formContainer.loadForm (plantFilename.c_str (), formDate); - if (form) - { - // Get the parameters - string shape; - if (form->getRootNode ().getValueByName (shape, "3D.Shape")) - { - // Get the position - CVector position = point->Point; - - // Get the scale - string scaleText; - float scale = 1; - if (point->getPropertyByName ("scale", scaleText)) - scale = (float) atof (scaleText.c_str ()); - - // Get zone coordinates - sint x = (sint)floor (position.x / options.CellSize); - sint y = (sint)floor (position.y / options.CellSize); - if ( (x >= igs.Minx) && (x < igs.Maxx) && (y >= igs.Miny) && (y < igs.Maxy) ) - { - // Get its layer - string text; - uint layer = 0; - if (point->getPropertyByName ("depth", text)) - { - layer = atoi (text.c_str ()); - } - - // Not snap yet - position.z = 0; - - // Snap flag - bool snap = true; - if (point->getPropertyByName ("snap", text)) - snap = text != "false"; - - // Get height - if (!snap && point->getPropertyByName ("height", text)) - position.z = (float)atof(text.c_str()); - - // *** Add the instance - - // Create it - CInstanceGroup::CInstance instance; - instance.Pos = position; - instance.Rot = CQuat(CVector::K, point->Angle); - instance.Scale = CVector (scale, scale, scale); - instance.nParent = -1; - instance.Name = shape; - instance.InstanceName = NLMISC::toLower(CFile::getFilename (plantFilename)); - - // Get the instance group ref - CIgContainer::CIG &instances = igs.get (x, y); - instances.Instances.push_back (instance); - instances.AdditionnalInfo.push_back (CIgContainer::CIG::CAdditionnalParam (layer, - getPrimitiveName (primitive), primFilename, snap)); - - // Update the date with the primitive filename - instances.updateDate (primFileDate); - - // Update the date with the plant filename - instances.updateDate (formDate); - - // Update the date with the zone filename - string zoneFilename; - getZoneNameByCoord (x, y, zoneFilename); - zoneFilename = CPath::standardizePath (options.InLandscapeDir, true) + zoneFilename + ".zonew"; - // todo hulud needed ? instances.updateDate (zoneFilename); - } - } - else - { - // Error in the log - nlwarning ("Error : Can't get a shape name in the form (%s) for the primitive (%s) in the file (%s)", - plantFilename.c_str (), getPrimitiveName (primitive).c_str (), primFilename); - } - } - else - { - // Error in the log - nlwarning ("Error : can't load the file (%s) used by the primitive (%s) in the file (%s).", plantFilename.c_str (), - getPrimitiveName (primitive).c_str (), primFilename); - } - } - else - { - // Error in the log - nlwarning ("Error : in file (%s), the primitive (%s) has no plant file.", primFilename, getPrimitiveName (primitive).c_str ()); - } - } - } - } - - // Look in children - uint numChildren = primitive.getNumChildren (); - for (uint i=0; iaddNegativeFilter ("addSearchPath"); - - // Register ligo - NLLIGO::Register (); - - if (argc != 2) - { - printf ("Use : prim_export configfile.cfg\n"); - printf ("\nExample of config.cfg\n\n"); - - printf ("\n// Export Options\n"); - printf ("OutIGDir = \"c:/temp/outIG\";\n"); - printf ("ZoneWDir = \"c:/temp/inZoneW\";\n"); - printf ("SmallBank = \"//amiga/3d/database/landscape/_texture_tiles/jungle/jungle.bank\";\n"); - printf ("FarBank = \"//amiga/3d/database/landscape/_texture_tiles/jungle/jungle.farbank\";\n"); - printf ("DisplaceDir = \"//amiga/3d/database/landscape/_texture_tiles/displace\";\n"); - printf ("CellSize = 160.0;\n"); - printf ("PrimDirs = {\"//server/leveldesign/world/fyros\"};\n"); - - return -1; - } - - try - { - // Load the config file - CExportOptions options; - - string sTmp = string("loading cfg file : ") + string(argv[1]) + "\n"; - // outString(sTmp); - { - CConfigFile cf; - cf.load (argv[1]); - if (!options.loadcf(cf)) - { - sTmp = "Error : options not loaded from config file\n"; - outString (sTmp); - return -1; - } - } - - // *** Add pathes in the search path for georges forms - - CPath::addSearchPath (options.FormDir, true, true); - - // Ligo config - CLigoConfig config; - string path = CPath::lookup ("world_editor_classes.xml", false, false, false); - if (path.empty()) - nlwarning ("Error : File world_editor_classes.xml not found"); - else - config.readPrimitiveClass (path.c_str(), false); - - // *** Load the landscape - - // Init the landscape - CLandscape landscape; - landscape.init (); - - // Get file list - vector files; - CPath::getPathContent (options.InLandscapeDir, false, false, true, files); - - // Landscape bounding box - sint minx = 0x7fffffff; - sint miny = 0x7fffffff; - sint maxx = 0x80000000; - sint maxy = 0x80000000; - - // The callback - CMyCallback callback; - - // For each zone files - if (files.empty()) - { - nlwarning ("Error : no zonew files found. Abort."); - } - else - { - uint i; - for (i=0; imaxx) - maxx = x; - if (y>maxy) - maxy = y; - } - else - { - // Error in the log - nlwarning ("Error : can't open the file (%s) for reading", files[i].c_str ()); - } - } - catch(const Exception &e) - { - // Error in the log - nlwarning ("Error loading zone file (%s) : %s", files[i].c_str (), e.what ()); - } - } - } - - // *** Create the igs - CIgContainer igs; - igs.init (minx, maxx, miny, maxy, options.InLandscapeDir.c_str ()); - - // *** Create a form container - CFormContainer formContainer; - - // *** For each primitive files - - // Get the primitive files liste - files.clear (); - for (i=0; igetZoneBB (); - - // The bbox used to select triangles - CAABBox bbox; - CVector &position = instance.Instances[i].Pos; - bbox.setCenter (CVector (position.x + SELECTION_EPSILON, position.y + SELECTION_EPSILON, zoneBBox.getMax ().z + SELECTION_EPSILON)); - bbox.extend (CVector (position.x - SELECTION_EPSILON, position.y - SELECTION_EPSILON, zoneBBox.getMin ().z - SELECTION_EPSILON)); - - // Select some triangles - vector triangles; - landscape.buildTrianglesInBBox (bbox, triangles, 0); - - // Ray trace triangles - set selectedHeight; - uint j; - for (j=0; j= setSize) - { - // Error in the log - nlwarning ("Error : Layer %d used by the primitive (%s) in the file (%s) doesn't exist. Select layer %d instead.", - layer, instance.AdditionnalInfo[i].PrimitiveName.c_str (), - instance.AdditionnalInfo[i].PrimitiveFile.c_str (), setSize-1); - - // New layer - layer = setSize-1; - } - - // Invert the layer number - layer = setSize - layer - 1; - - set::iterator ite = selectedHeight.begin (); - while (ite != selectedHeight.end ()) - { - // Good layer ? - if (currentLayer == layer) - break; - - // Next layer - currentLayer++; - ite++; - } - - // Should be found - nlassert (ite != selectedHeight.end ()); - - // Get the final height - position.z = *ite; - } - else - { - // Error in the log - nlwarning ("Error : No landscape under the primitive (%s) in the file (%s).", - instance.AdditionnalInfo[i].PrimitiveName.c_str (), instance.AdditionnalInfo[i].PrimitiveFile.c_str ()); - } - } - } - } - else - { - // Error in the log - nlwarning ("Error : No landscape for the zone (%s)", CFile::getFilename (igFilename).c_str ()); - } - - // Build an instance group - CInstanceGroup ig; - CVector vGlobalPos = CVector::Null; - vector Portals; - vector Clusters; - ig.build (vGlobalPos, instance.Instances, Portals, Clusters); - - // *** Save the ig file - - try - { - // The file - COFile outFile; - if (outFile.open (igFilename)) - { - ig.serial (outFile); - - // Done - outString ("OK " + CFile::getFilename (igFilename) + " \n"); - } - else - { - // Error in the log - nlwarning ("Error : can't open the file (%s) for writing.", igFilename.c_str ()); - } - } - catch (const Exception &e) - { - // Error in the log - nlwarning ("Error writing the file (%s) : %s", igFilename.c_str (), e.what ()); - } - } - } - else - { - // File exist ? - if (CFile::fileExists (igFilename)) - { - // Done - outString ("REMOVE " + CFile::getFilename (igFilename) + " \n"); - - // Remove it - if (remove (igFilename.c_str ()) != 0) - { - // Error in the log - nlwarning ("Error : Can't remove the file (%s)", igFilename.c_str ()); - } - } - } - } - } - } - } - catch (const Exception &e) - { - string sTmp = string("ERROR : ") + e.what(); - outString (sTmp); - } - - return 1; -} - - - - - - - - -/* - - - - - - - - - - // *** Snap to the ground - - // Get zone coordinates - sint x = (sint)floor (position.x / options.CellSize); - sint y = (sint)floor (position.y / options.CellSize); - -*/ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include +#include + +#include "nel/misc/config_file.h" +#include "nel/misc/file.h" +#include "nel/misc/i_xml.h" +#include "nel/misc/path.h" +#include "nel/misc/progress_callback.h" + +#include "nel/ligo/primitive.h" +#include "nel/ligo/ligo_config.h" + +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" +#include "nel/georges/u_form_loader.h" + +#include "nel/3d/zone.h" +#include "nel/3d/landscape.h" +#include "nel/3d/scene_group.h" + +#ifdef NL_OS_WINDOWS +#include +#endif // NL_OS_WINDOWS + +// *************************************************************************** + +/* +Documentation + +This tool generates ig from primitive files + + - Load the landscape zone. Load all the *.zonew found in the InLandscapeDir and add them in a landscape + - For each primitive files found in PrimDirs + - Look for points with the "prim" primitive class + - Get the good height on the landscape + - Get the .plant georges file associed with the point + - Add an entry in the good ig file + - Set the shape filename + - Set the plant name + - Set the final position (x and y come from the primitive and z from height test with the landscape, the rotation comes from the primitive) + - Set the ig date + - The date is the most recent date between the .zonew .plant .primitive files associed with the ig. + - Snap to ground only modified or created ig + - Save the modified or created ig files +*/ + +// *************************************************************************** + +using namespace std; +using namespace NLMISC; +using namespace NL3D; +using namespace NLGEORGES; +using namespace NLLIGO; + +// *************************************************************************** +// Utility functions +// *************************************************************************** + +#define SELECTION_EPSILON 0.1f + +#define BAR_LENGTH 21 + +const char *progressbar[BAR_LENGTH]= +{ + "[ ]", + "[. ]", + "[.. ]", + "[... ]", + "[.... ]", + "[..... ]", + "[...... ]", + "[....... ]", + "[........ ]", + "[......... ]", + "[.......... ]", + "[........... ]", + "[............ ]", + "[............. ]", + "[.............. ]", + "[............... ]", + "[................ ]", + "[................. ]", + "[.................. ]", + "[................... ]", + "[....................]" +}; + +// *************************************************************************** + +// Progress bar +class CMyCallback : public IProgressCallback +{ +public: + void progress (float progress) + { + // Delta time, update max all the 300 ms + static sint64 time = CTime::getLocalTime (); + sint64 currentTime = CTime::getLocalTime (); + if ((currentTime - time) > 300) + { + // Crop the progress bar value + progress = getCropedValue (progress); + + // Progress bar + char msg[512]; + uint pgId= (uint)(progress*(float)BAR_LENGTH); + pgId= min(pgId, (uint)(BAR_LENGTH-1)); + sprintf (msg, "\r%s: %s", DisplayString.c_str (), progressbar[pgId]); + uint i; + for (i=(uint)strlen(msg); i<79; i++) + msg[i]=' '; + msg[i]=0; + printf ("%s", msg); + printf ("\r"); + + time = currentTime; + } + } +}; + +// *************************************************************************** + +sint getXFromZoneName (const string &ZoneName) +{ + string xStr, yStr; + uint32 i = 0; + while (ZoneName[i] != '_') + { + yStr += ZoneName[i]; ++i; + if (i == ZoneName.size()) + return -1; + } + ++i; + while (i < ZoneName.size()) + { + xStr += ZoneName[i]; ++i; + } + return ((xStr[0] - 'A')*26 + (xStr[1] - 'A')); +} + +// *************************************************************************** + +bool getZoneCoordByName(const char * name, uint16& x, uint16& y) +{ + uint i; + + std::string zoneName(name); + + // y + std::string::size_type ind1 = zoneName.find("_"); + if(ind1 == std::string::npos) + { + nlwarning("bad file name"); + return false; + } + std::string ystr = zoneName.substr(0,ind1); + for(i=0; idisplayRaw(sText.c_str()); +} + +// *************************************************************************** + +string getPrimitiveName (const IPrimitive &primitive) +{ + string name; + primitive.getPropertyByName ("name", name); + return name; +} + +// *************************************************************************** + +uint16 getZoneId (sint x, sint y) +{ + return (uint16)((((-y)-1)<<8) + x); +} + +// *************************************************************************** + +void getLettersFromNum(uint16 num, std::string& code) +{ + if(num>26*26) + { + nlwarning("zone index too high"); + return; + } + code.resize(0); + uint16 remainder = num%26; + code += 'A' + num/26; + code += 'A' + remainder; +} + +// *************************************************************************** + +void getZoneNameByCoord(sint16 x, sint16 y, std::string& zoneName) +{ + if ((y>0) || (y<-255) || (x<0) || (x>255)) + return; + zoneName = toString(-y) + "_"; + zoneName += ('A' + (x/26)); + zoneName += ('A' + (x%26)); +} + +// *************************************************************************** + +bool triangleIntersect2DGround (const CTriangle &tri, const CVector &pos0) +{ + const CVector &p0= tri.V0; + const CVector &p1= tri.V1; + const CVector &p2= tri.V2; + + // Test if the face enclose the pos in X/Y plane. + // NB: compute and using a BBox to do a rapid test is not a very good idea, since it will + // add an overhead which is NOT negligeable compared to the following test. + float a,b,c; // 2D cartesian coefficients of line in plane X/Y. + // Line p0-p1. + a= -(p1.y-p0.y); + b= (p1.x-p0.x); + c= -(p0.x*a + p0.y*b); + if( (a*pos0.x + b*pos0.y + c) < 0) return false; + // Line p1-p2. + a= -(p2.y-p1.y); + b= (p2.x-p1.x); + c= -(p1.x*a + p1.y*b); + if( (a*pos0.x + b*pos0.y + c) < 0) return false; + // Line p2-p0. + a= -(p0.y-p2.y); + b= (p0.x-p2.x); + c= -(p2.x*a + p2.y*b); + if( (a*pos0.x + b*pos0.y + c) < 0) return false; + + return true; +} + +// *************************************************************************** +// CExportOptions +// *************************************************************************** + +struct CExportOptions +{ + std::string InLandscapeDir; // Directory where to get .zonew files + std::string OutIGDir; // Directory where to put IG + std::string LandBankFile; // The .smallbank file associated with the landscape + std::string LandFarBankFile; // The .farbank file + float CellSize; // Typically 160.0 + std::string LandTileNoiseDir; // Directory where to get displacement map + + std::vector PrimDirs; // Directory to parse for .flora and .prim associated + // This is here we get continent.cfg file + std::string FormDir; // Directory to get georges dfn + + CExportOptions (); + bool loadcf (NLMISC::CConfigFile &cf); +}; + +// *************************************************************************** + +CExportOptions::CExportOptions () +{ + CellSize = 160.0f; +} + +// *************************************************************************** + +bool CExportOptions::loadcf (CConfigFile &cf) +{ + // Out + CConfigFile::CVar &cvOutIGDir = cf.getVar("OutIGDir"); + OutIGDir = cvOutIGDir.asString(); + + // In + CConfigFile::CVar &cvInLandscapeDir = cf.getVar("ZoneWDir"); + InLandscapeDir = cvInLandscapeDir.asString(); + + CConfigFile::CVar &cvLandBankFile = cf.getVar("SmallBank"); + LandBankFile = cvLandBankFile.asString(); + CConfigFile::CVar &cvLandFarBankFile = cf.getVar("FarBank"); + LandFarBankFile = cvLandFarBankFile.asString(); + CConfigFile::CVar &cvLandTileNoiseDir = cf.getVar("DisplaceDir"); + LandTileNoiseDir = cvLandTileNoiseDir.asString(); + + CConfigFile::CVar &cvCellSize = cf.getVar("CellSize"); + CellSize = cvCellSize.asFloat(); + + CConfigFile::CVar &cvPrimDir = cf.getVar("PrimDirs"); + uint i; + PrimDirs.resize (cvPrimDir.size()); + for (i=0; i<(uint)cvPrimDir.size(); i++) + PrimDirs[i] = cvPrimDir.asString(i); + + CConfigFile::CVar &cvFormDir = cf.getVar("FormDir"); + FormDir = cvFormDir.asString(); + + return true; +} + +// *************************************************************************** + +// Array of ig +class CIgContainer +{ +public: + + // An ig + class CIG + { + public: + // Additionnal parameters + class CAdditionnalParam + { + public: + CAdditionnalParam (uint snapLayer, const string &primitiveName, const string &primitiveFile, bool snap) : SnapLayer (snapLayer), PrimitiveName (primitiveName), PrimitiveFile (primitiveFile) + { + Snap = snap; + }; + + // Snap over the landscape + bool Snap; + + // Snap layer + uint SnapLayer; + + // Primitive name + string PrimitiveName; + + // Primitive file + string PrimitiveFile; + }; + + // Default ctor + CIG () + { + Date = 0; + } + + // Update date if new date is more recent + void updateDate (uint32 newDate) + { + if (newDate > Date) + Date = newDate; + } + + // The ig + CInstanceGroup::TInstanceArray Instances; + + // Additionnal information + vector AdditionnalInfo; + + // The ig date + uint32 Date; + }; + + // Init the container + void init (sint minx, sint maxx, sint miny, sint maxy, const char *zoneDir) + { + // Save the values + Minx = minx; + Miny = miny; + Maxx = maxx+1; + Maxy = maxy+1; + Width = maxx - minx + 1; + + // Resize the array + IGS.clear (); + IGS.resize (Width*(maxy-miny+1)); + + // Directory + string dir = CPath::standardizePath (zoneDir, true); + + // For each zone + for (sint y=miny; y<=maxy; y++) + for (sint x=minx; x<=maxx; x++) + { + // The zone name + string zoneFilename; + getZoneNameByCoord ((sint16)x, (sint16)y, zoneFilename); + zoneFilename = dir + zoneFilename + ".zonew"; + + // Get the date + if (CFile::fileExists (zoneFilename)) + get (x, y).Date = CFile::getFileModificationDate (zoneFilename); + } + } + + // Get the ig + CIG &get (sint x, sint y) + { + return IGS[(x-Minx)+(y-Miny)*Width]; + } + + // Size and position + uint Width; + sint Minx; + sint Miny; + sint Maxx; + sint Maxy; + + // The ig vector + vector IGS; +}; + +// *************************************************************************** + +// Array of ig +class CFormContainer +{ +private: + // The map value + struct CValue + { + CValue (CSmartPtr ptr, uint32 date) : Ptr (ptr), Date (date) {}; + + // The form pointer + CSmartPtr Ptr; + + // Its date + uint32 Date; + }; +public: + + // Default ctor + CFormContainer () + { + _FormLoader = UFormLoader::createLoader (); + } + + // Dtor + ~CFormContainer () + { + UFormLoader::releaseLoader (_FormLoader); + } + + // The form container + const UForm *loadForm (const char *formName, uint32 &formDate) + { + // The form + UForm *form = NULL; + formDate = 0; + + // In the map ? + string formShortName = NLMISC::toLower(CFile::getFilename (formName)); + map::iterator ite = _FormMap.find (formShortName); + if (ite == _FormMap.end ()) + { + // Look for this plant file + string path = CPath::lookup (formName, false, false, false); + if (!path.empty ()) + { + // Load it ! + form = _FormLoader->loadForm (path.c_str ()); + if (form) + { + // Get dependencies + set dependencies; + form->getDependencies (dependencies); + + // Get dependencies dates + formDate = 0; + set::const_iterator ite = dependencies.begin (); + while (ite != dependencies.end ()) + { + // Get the path name + string path = CPath::lookup (*ite, false, false, false); + if (!path.empty ()) + { + // Get the file date + uint32 date = CFile::getFileModificationDate (path); + + // Update date + if (date > formDate) + formDate = date; + } + + // Next dependency + ite++; + } + + // Add it + _FormMap.insert (map::value_type (formShortName, CValue (form, formDate))); + } + else + { + // Error in the log + nlwarning ("Error : Can't load the form (%s)", path.c_str ()); + } + } + } + else + { + form = ite->second.Ptr; + formDate = ite->second.Date; + } + + // Return the form or NULL + return form; + } + +private: + + // The form loader + UFormLoader *_FormLoader; + + // The form map + map _FormMap; +}; + +// *************************************************************************** + +void addPointPrimitive (CLandscape &landscape, const char *primFilename, uint32 primFileDate, const IPrimitive &primitive, CIgContainer &igs, + const CExportOptions &options, CFormContainer &formContainer, IProgressCallback &callback) +{ + // Is this primitive a point ? + const CPrimPoint *point = dynamic_cast(&primitive); + if (point) + { + // Get the class name + string className; + if (point->getPropertyByName ("class", className)) + { + // Is it a plant ? + if (className == "prim") + { + // Get its plant name + string plantFilename; + if (point->getPropertyByName ("form", plantFilename)) + { + // Add an extension + if (NLMISC::toLower(CFile::getExtension (plantFilename)) != "plant") + plantFilename += ".plant"; + + // Load this form + uint32 formDate; + const UForm *form = formContainer.loadForm (plantFilename.c_str (), formDate); + if (form) + { + // Get the parameters + string shape; + if (form->getRootNode ().getValueByName (shape, "3D.Shape")) + { + // Get the position + CVector position = point->Point; + + // Get the scale + string scaleText; + float scale = 1; + if (point->getPropertyByName ("scale", scaleText)) + scale = (float) atof (scaleText.c_str ()); + + // Get zone coordinates + sint x = (sint)floor (position.x / options.CellSize); + sint y = (sint)floor (position.y / options.CellSize); + if ( (x >= igs.Minx) && (x < igs.Maxx) && (y >= igs.Miny) && (y < igs.Maxy) ) + { + // Get its layer + string text; + uint layer = 0; + if (point->getPropertyByName ("depth", text)) + { + layer = atoi (text.c_str ()); + } + + // Not snap yet + position.z = 0; + + // Snap flag + bool snap = true; + if (point->getPropertyByName ("snap", text)) + snap = text != "false"; + + // Get height + if (!snap && point->getPropertyByName ("height", text)) + position.z = (float)atof(text.c_str()); + + // *** Add the instance + + // Create it + CInstanceGroup::CInstance instance; + instance.Pos = position; + instance.Rot = CQuat(CVector::K, point->Angle); + instance.Scale = CVector (scale, scale, scale); + instance.nParent = -1; + instance.Name = shape; + instance.InstanceName = NLMISC::toLower(CFile::getFilename (plantFilename)); + + // Get the instance group ref + CIgContainer::CIG &instances = igs.get (x, y); + instances.Instances.push_back (instance); + instances.AdditionnalInfo.push_back (CIgContainer::CIG::CAdditionnalParam (layer, + getPrimitiveName (primitive), primFilename, snap)); + + // Update the date with the primitive filename + instances.updateDate (primFileDate); + + // Update the date with the plant filename + instances.updateDate (formDate); + + // Update the date with the zone filename + string zoneFilename; + getZoneNameByCoord (x, y, zoneFilename); + zoneFilename = CPath::standardizePath (options.InLandscapeDir, true) + zoneFilename + ".zonew"; + // todo hulud needed ? instances.updateDate (zoneFilename); + } + } + else + { + // Error in the log + nlwarning ("Error : Can't get a shape name in the form (%s) for the primitive (%s) in the file (%s)", + plantFilename.c_str (), getPrimitiveName (primitive).c_str (), primFilename); + } + } + else + { + // Error in the log + nlwarning ("Error : can't load the file (%s) used by the primitive (%s) in the file (%s).", plantFilename.c_str (), + getPrimitiveName (primitive).c_str (), primFilename); + } + } + else + { + // Error in the log + nlwarning ("Error : in file (%s), the primitive (%s) has no plant file.", primFilename, getPrimitiveName (primitive).c_str ()); + } + } + } + } + + // Look in children + uint numChildren = primitive.getNumChildren (); + for (uint i=0; iaddNegativeFilter ("addSearchPath"); + + // Register ligo + NLLIGO::Register (); + + if (argc != 2) + { + printf ("Use : prim_export configfile.cfg\n"); + printf ("\nExample of config.cfg\n\n"); + + printf ("\n// Export Options\n"); + printf ("OutIGDir = \"c:/temp/outIG\";\n"); + printf ("ZoneWDir = \"c:/temp/inZoneW\";\n"); + printf ("SmallBank = \"//amiga/3d/database/landscape/_texture_tiles/jungle/jungle.bank\";\n"); + printf ("FarBank = \"//amiga/3d/database/landscape/_texture_tiles/jungle/jungle.farbank\";\n"); + printf ("DisplaceDir = \"//amiga/3d/database/landscape/_texture_tiles/displace\";\n"); + printf ("CellSize = 160.0;\n"); + printf ("PrimDirs = {\"//server/leveldesign/world/fyros\"};\n"); + + return -1; + } + + try + { + // Load the config file + CExportOptions options; + + string sTmp = string("loading cfg file : ") + string(argv[1]) + "\n"; + // outString(sTmp); + { + CConfigFile cf; + cf.load (argv[1]); + if (!options.loadcf(cf)) + { + sTmp = "Error : options not loaded from config file\n"; + outString (sTmp); + return -1; + } + } + + // *** Add pathes in the search path for georges forms + + CPath::addSearchPath (options.FormDir, true, true); + + // Ligo config + CLigoConfig config; + string path = CPath::lookup ("world_editor_classes.xml", false, false, false); + if (path.empty()) + nlwarning ("Error : File world_editor_classes.xml not found"); + else + config.readPrimitiveClass (path.c_str(), false); + + // *** Load the landscape + + // Init the landscape + CLandscape landscape; + landscape.init (); + + // Get file list + vector files; + CPath::getPathContent (options.InLandscapeDir, false, false, true, files); + + // Landscape bounding box + sint minx = 0x7fffffff; + sint miny = 0x7fffffff; + sint maxx = 0x80000000; + sint maxy = 0x80000000; + + // The callback + CMyCallback callback; + + // For each zone files + if (files.empty()) + { + nlwarning ("Error : no zonew files found. Abort."); + } + else + { + uint i; + for (i=0; imaxx) + maxx = x; + if (y>maxy) + maxy = y; + } + else + { + // Error in the log + nlwarning ("Error : can't open the file (%s) for reading", files[i].c_str ()); + } + } + catch(const Exception &e) + { + // Error in the log + nlwarning ("Error loading zone file (%s) : %s", files[i].c_str (), e.what ()); + } + } + } + + // *** Create the igs + CIgContainer igs; + igs.init (minx, maxx, miny, maxy, options.InLandscapeDir.c_str ()); + + // *** Create a form container + CFormContainer formContainer; + + // *** For each primitive files + + // Get the primitive files liste + files.clear (); + for (i=0; igetZoneBB (); + + // The bbox used to select triangles + CAABBox bbox; + CVector &position = instance.Instances[i].Pos; + bbox.setCenter (CVector (position.x + SELECTION_EPSILON, position.y + SELECTION_EPSILON, zoneBBox.getMax ().z + SELECTION_EPSILON)); + bbox.extend (CVector (position.x - SELECTION_EPSILON, position.y - SELECTION_EPSILON, zoneBBox.getMin ().z - SELECTION_EPSILON)); + + // Select some triangles + vector triangles; + landscape.buildTrianglesInBBox (bbox, triangles, 0); + + // Ray trace triangles + set selectedHeight; + uint j; + for (j=0; j= setSize) + { + // Error in the log + nlwarning ("Error : Layer %d used by the primitive (%s) in the file (%s) doesn't exist. Select layer %d instead.", + layer, instance.AdditionnalInfo[i].PrimitiveName.c_str (), + instance.AdditionnalInfo[i].PrimitiveFile.c_str (), setSize-1); + + // New layer + layer = setSize-1; + } + + // Invert the layer number + layer = setSize - layer - 1; + + set::iterator ite = selectedHeight.begin (); + while (ite != selectedHeight.end ()) + { + // Good layer ? + if (currentLayer == layer) + break; + + // Next layer + currentLayer++; + ite++; + } + + // Should be found + nlassert (ite != selectedHeight.end ()); + + // Get the final height + position.z = *ite; + } + else + { + // Error in the log + nlwarning ("Error : No landscape under the primitive (%s) in the file (%s).", + instance.AdditionnalInfo[i].PrimitiveName.c_str (), instance.AdditionnalInfo[i].PrimitiveFile.c_str ()); + } + } + } + } + else + { + // Error in the log + nlwarning ("Error : No landscape for the zone (%s)", CFile::getFilename (igFilename).c_str ()); + } + + // Build an instance group + CInstanceGroup ig; + CVector vGlobalPos = CVector::Null; + vector Portals; + vector Clusters; + ig.build (vGlobalPos, instance.Instances, Portals, Clusters); + + // *** Save the ig file + + try + { + // The file + COFile outFile; + if (outFile.open (igFilename)) + { + ig.serial (outFile); + + // Done + outString ("OK " + CFile::getFilename (igFilename) + " \n"); + } + else + { + // Error in the log + nlwarning ("Error : can't open the file (%s) for writing.", igFilename.c_str ()); + } + } + catch (const Exception &e) + { + // Error in the log + nlwarning ("Error writing the file (%s) : %s", igFilename.c_str (), e.what ()); + } + } + } + else + { + // File exist ? + if (CFile::fileExists (igFilename)) + { + // Done + outString ("REMOVE " + CFile::getFilename (igFilename) + " \n"); + + // Remove it + if (remove (igFilename.c_str ()) != 0) + { + // Error in the log + nlwarning ("Error : Can't remove the file (%s)", igFilename.c_str ()); + } + } + } + } + } + } + } + catch (const Exception &e) + { + string sTmp = string("ERROR : ") + e.what(); + outString (sTmp); + } + + return 1; +} + + + + + + + + +/* + + + + + + + + + + // *** Snap to the ground + + // Get zone coordinates + sint x = (sint)floor (position.x / options.CellSize); + sint y = (sint)floor (position.y / options.CellSize); + +*/ diff --git a/code/ryzom/tools/leveldesign/primitive_id_assignator/primitive_id_assignator.cpp b/code/ryzom/tools/leveldesign/primitive_id_assignator/primitive_id_assignator.cpp index 33ee8444e..08c1b255f 100644 --- a/code/ryzom/tools/leveldesign/primitive_id_assignator/primitive_id_assignator.cpp +++ b/code/ryzom/tools/leveldesign/primitive_id_assignator/primitive_id_assignator.cpp @@ -1,158 +1,158 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "nel/misc/types_nl.h" -#include "nel/misc/config_file.h" -#include "nel/misc/path.h" -#include "nel/misc/file.h" - - -using namespace std; -using namespace NLMISC; - -int main(int argc, char *argv[]) -{ - new NLMISC::CApplicationContext; - - CConfigFile cf; - - uint32 firstFreeIndex = 0; - - // load the config file - cf.load("primitive_id_assignator.cfg"); - - // get the list of extension - CConfigFile::CVar &ext = cf.getVar("Extension"); - - // get the list of filter - CConfigFile::CVar &filters = cf.getVar("Filters"); - - // Add the search paths - CConfigFile::CVar &sp = cf.getVar("SearchPath"); - - for (uint i=0; i indexMap; - CConfigFile::CVar &vif = cf.getVar("IndexFile"); - if (!CFile::isExists(vif.asString())) - { - // build a default config file - string fileName = vif.asString(); - FILE *fp = fopen(fileName.c_str(), "wt"); - if (fp == NULL) - { - nlwarning("Can't open file '%s' for writing", - fileName.c_str()); - return -1; - } - fprintf(fp, "Files = {};\n"); - fclose(fp); - - } - indexFile.load(vif.asString()); - - // parse the index file - CConfigFile::CVar &fl = indexFile.getVar("Files"); - for (uint i=0; i<(fl.size())/2; i++) - { - string fileName; - uint32 index; - - fileName = fl.asString(i*2); - index = fl.asInt(i*2+1); - - if (indexMap.find(fileName) != indexMap.end()) - { - nlwarning("Association for file '%s' already exist as index %u, new association with index %u will be lost", - fileName.c_str(), - index, - indexMap[fileName]); - } - else - { - indexMap[fileName] = index; - - if (index >= firstFreeIndex) - firstFreeIndex = index + 1; - } - } - - // scan the search path - for (uint i=0; i files; - CPath::getFileList(ext.asString(i), files); - - for (uint i=0; i::iterator first(indexMap.begin()), last(indexMap.end()); - for (uint i=0; first != last; ++first, ++i) - { - if (i == 0) - fl.forceAsString(first->first); - else - fl.setAsString(first->first, i*2); - fl.setAsString(toString("%u", first->second), i*2+1); - } - - nlinfo("Writing index with %u files indexed", - fl.size()); - - indexFile.save(); - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "nel/misc/types_nl.h" +#include "nel/misc/config_file.h" +#include "nel/misc/path.h" +#include "nel/misc/file.h" + + +using namespace std; +using namespace NLMISC; + +int main(int argc, char *argv[]) +{ + new NLMISC::CApplicationContext; + + CConfigFile cf; + + uint32 firstFreeIndex = 0; + + // load the config file + cf.load("primitive_id_assignator.cfg"); + + // get the list of extension + CConfigFile::CVar &ext = cf.getVar("Extension"); + + // get the list of filter + CConfigFile::CVar &filters = cf.getVar("Filters"); + + // Add the search paths + CConfigFile::CVar &sp = cf.getVar("SearchPath"); + + for (uint i=0; i indexMap; + CConfigFile::CVar &vif = cf.getVar("IndexFile"); + if (!CFile::isExists(vif.asString())) + { + // build a default config file + string fileName = vif.asString(); + FILE *fp = fopen(fileName.c_str(), "wt"); + if (fp == NULL) + { + nlwarning("Can't open file '%s' for writing", + fileName.c_str()); + return -1; + } + fprintf(fp, "Files = {};\n"); + fclose(fp); + + } + indexFile.load(vif.asString()); + + // parse the index file + CConfigFile::CVar &fl = indexFile.getVar("Files"); + for (uint i=0; i<(fl.size())/2; i++) + { + string fileName; + uint32 index; + + fileName = fl.asString(i*2); + index = fl.asInt(i*2+1); + + if (indexMap.find(fileName) != indexMap.end()) + { + nlwarning("Association for file '%s' already exist as index %u, new association with index %u will be lost", + fileName.c_str(), + index, + indexMap[fileName]); + } + else + { + indexMap[fileName] = index; + + if (index >= firstFreeIndex) + firstFreeIndex = index + 1; + } + } + + // scan the search path + for (uint i=0; i files; + CPath::getFileList(ext.asString(i), files); + + for (uint i=0; i::iterator first(indexMap.begin()), last(indexMap.end()); + for (uint i=0; first != last; ++first, ++i) + { + if (i == 0) + fl.forceAsString(first->first); + else + fl.setAsString(first->first, i*2); + fl.setAsString(toString("%u", first->second), i*2+1); + } + + nlinfo("Writing index with %u files indexed", + fl.size()); + + indexFile.save(); + } \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/uni_conv/uni_conv.cpp b/code/ryzom/tools/leveldesign/uni_conv/uni_conv.cpp index fedf44d7a..1bbe82dcc 100644 --- a/code/ryzom/tools/leveldesign/uni_conv/uni_conv.cpp +++ b/code/ryzom/tools/leveldesign/uni_conv/uni_conv.cpp @@ -1,133 +1,133 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include -#include -#include -#include - -using namespace std; -using namespace NLMISC; - -void usage() -{ - printf("uni_conv [option] \n"); - printf("output_mode is one of:\n"); - printf("\t-8 output in UTF-8\n"); - printf("\t-16 output in UTF-16\n"); - printf("\t-a output in ascii, non ascii char are silently removed\n"); - printf("option:\n"); - printf("\t-x minimal support for XML : encode &, < and > in XML chat tag\n"); -} - -int main(int argc, char *argv[]) -{ - new NLMISC::CApplicationContext; - - bool xmlSupport = false; - enum TOutMode {UNDEF, UTF8, UTF16, ASCII}; - CSString inputFile; - CSString outputFile; - TOutMode outMode = UNDEF; - - if (argc < 4) - { - usage(); - return -1; - } - for (int i=1; i': - temp += "<"; - break; - default: - temp += str[i]; - } - } - str = temp; - } - - switch(outMode) - { - case UTF8: - CI18N::writeTextFile(outputFile, str, true); - break; - case UTF16: - CI18N::writeTextFile(outputFile, str, false); - break; - case ASCII: - { - string s = str.toString(); - FILE *fp = fopen(outputFile.c_str(), "wt"); - fwrite(s.data(), s.size(), 1, fp); - fclose(fp); - } - break; - default: - break; - - } -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include +#include +#include +#include + +using namespace std; +using namespace NLMISC; + +void usage() +{ + printf("uni_conv [option] \n"); + printf("output_mode is one of:\n"); + printf("\t-8 output in UTF-8\n"); + printf("\t-16 output in UTF-16\n"); + printf("\t-a output in ascii, non ascii char are silently removed\n"); + printf("option:\n"); + printf("\t-x minimal support for XML : encode &, < and > in XML chat tag\n"); +} + +int main(int argc, char *argv[]) +{ + new NLMISC::CApplicationContext; + + bool xmlSupport = false; + enum TOutMode {UNDEF, UTF8, UTF16, ASCII}; + CSString inputFile; + CSString outputFile; + TOutMode outMode = UNDEF; + + if (argc < 4) + { + usage(); + return -1; + } + for (int i=1; i': + temp += "<"; + break; + default: + temp += str[i]; + } + } + str = temp; + } + + switch(outMode) + { + case UTF8: + CI18N::writeTextFile(outputFile, str, true); + break; + case UTF16: + CI18N::writeTextFile(outputFile, str, false); + break; + case ASCII: + { + string s = str.toString(); + FILE *fp = fopen(outputFile.c_str(), "wt"); + fwrite(s.data(), s.size(), 1, fp); + fclose(fp); + } + break; + default: + break; + + } +} diff --git a/code/ryzom/tools/leveldesign/variable_parser/ReadMe.txt b/code/ryzom/tools/leveldesign/variable_parser/ReadMe.txt index b274cd829..df38a2897 100644 --- a/code/ryzom/tools/leveldesign/variable_parser/ReadMe.txt +++ b/code/ryzom/tools/leveldesign/variable_parser/ReadMe.txt @@ -1,88 +1,88 @@ -======================================================================== - MICROSOFT FOUNDATION CLASS LIBRARY : VariableParser -======================================================================== - - -AppWizard has created this VariableParser application for you. This application -not only demonstrates the basics of using the Microsoft Foundation classes -but is also a starting point for writing your application. - -This file contains a summary of what you will find in each of the files that -make up your VariableParser application. - -VariableParser.dsp - This file (the project file) contains information at the project level and - is used to build a single project or subproject. Other users can share the - project (.dsp) file, but they should export the makefiles locally. - -VariableParser.h - This is the main header file for the application. It includes other - project specific headers (including Resource.h) and declares the - CVariableParserApp application class. - -VariableParser.cpp - This is the main application source file that contains the application - class CVariableParserApp. - -VariableParser.rc - This is a listing of all of the Microsoft Windows resources that the - program uses. It includes the icons, bitmaps, and cursors that are stored - in the RES subdirectory. This file can be directly edited in Microsoft - Visual C++. - -VariableParser.clw - This file contains information used by ClassWizard to edit existing - classes or add new classes. ClassWizard also uses this file to store - information needed to create and edit message maps and dialog data - maps and to create prototype member functions. - -res\VariableParser.ico - This is an icon file, which is used as the application's icon. This - icon is included by the main resource file VariableParser.rc. - -res\VariableParser.rc2 - This file contains resources that are not edited by Microsoft - Visual C++. You should place all resources not editable by - the resource editor in this file. - - - - -///////////////////////////////////////////////////////////////////////////// - -AppWizard creates one dialog class: - -VariableParserDlg.h, VariableParserDlg.cpp - the dialog - These files contain your CVariableParserDlg class. This class defines - the behavior of your application's main dialog. The dialog's - template is in VariableParser.rc, which can be edited in Microsoft - Visual C++. - - -///////////////////////////////////////////////////////////////////////////// -Other standard files: - -StdAfx.h, StdAfx.cpp - These files are used to build a precompiled header (PCH) file - named VariableParser.pch and a precompiled types file named StdAfx.obj. - -Resource.h - This is the standard header file, which defines new resource IDs. - Microsoft Visual C++ reads and updates this file. - -///////////////////////////////////////////////////////////////////////////// -Other notes: - -AppWizard uses "TODO:" to indicate parts of the source code you -should add to or customize. - -If your application uses MFC in a shared DLL, and your application is -in a language other than the operating system's current language, you -will need to copy the corresponding localized resources MFC42XXX.DLL -from the Microsoft Visual C++ CD-ROM onto the system or system32 directory, -and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation. -For example, MFC42DEU.DLL contains resources translated to German.) If you -don't do this, some of the UI elements of your application will remain in the -language of the operating system. - -///////////////////////////////////////////////////////////////////////////// +======================================================================== + MICROSOFT FOUNDATION CLASS LIBRARY : VariableParser +======================================================================== + + +AppWizard has created this VariableParser application for you. This application +not only demonstrates the basics of using the Microsoft Foundation classes +but is also a starting point for writing your application. + +This file contains a summary of what you will find in each of the files that +make up your VariableParser application. + +VariableParser.dsp + This file (the project file) contains information at the project level and + is used to build a single project or subproject. Other users can share the + project (.dsp) file, but they should export the makefiles locally. + +VariableParser.h + This is the main header file for the application. It includes other + project specific headers (including Resource.h) and declares the + CVariableParserApp application class. + +VariableParser.cpp + This is the main application source file that contains the application + class CVariableParserApp. + +VariableParser.rc + This is a listing of all of the Microsoft Windows resources that the + program uses. It includes the icons, bitmaps, and cursors that are stored + in the RES subdirectory. This file can be directly edited in Microsoft + Visual C++. + +VariableParser.clw + This file contains information used by ClassWizard to edit existing + classes or add new classes. ClassWizard also uses this file to store + information needed to create and edit message maps and dialog data + maps and to create prototype member functions. + +res\VariableParser.ico + This is an icon file, which is used as the application's icon. This + icon is included by the main resource file VariableParser.rc. + +res\VariableParser.rc2 + This file contains resources that are not edited by Microsoft + Visual C++. You should place all resources not editable by + the resource editor in this file. + + + + +///////////////////////////////////////////////////////////////////////////// + +AppWizard creates one dialog class: + +VariableParserDlg.h, VariableParserDlg.cpp - the dialog + These files contain your CVariableParserDlg class. This class defines + the behavior of your application's main dialog. The dialog's + template is in VariableParser.rc, which can be edited in Microsoft + Visual C++. + + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named VariableParser.pch and a precompiled types file named StdAfx.obj. + +Resource.h + This is the standard header file, which defines new resource IDs. + Microsoft Visual C++ reads and updates this file. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + +If your application uses MFC in a shared DLL, and your application is +in a language other than the operating system's current language, you +will need to copy the corresponding localized resources MFC42XXX.DLL +from the Microsoft Visual C++ CD-ROM onto the system or system32 directory, +and rename it to be MFCLOC.DLL. ("XXX" stands for the language abbreviation. +For example, MFC42DEU.DLL contains resources translated to German.) If you +don't do this, some of the UI elements of your application will remain in the +language of the operating system. + +///////////////////////////////////////////////////////////////////////////// diff --git a/code/ryzom/tools/leveldesign/variable_parser/StdAfx.cpp b/code/ryzom/tools/leveldesign/variable_parser/StdAfx.cpp index 34c2a0f9b..73ee6f33e 100644 --- a/code/ryzom/tools/leveldesign/variable_parser/StdAfx.cpp +++ b/code/ryzom/tools/leveldesign/variable_parser/StdAfx.cpp @@ -1,24 +1,24 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.cpp : source file that includes just the standard includes -// VariableParser.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.cpp : source file that includes just the standard includes +// VariableParser.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/code/ryzom/tools/leveldesign/variable_parser/StdAfx.h b/code/ryzom/tools/leveldesign/variable_parser/StdAfx.h index 199c84879..b1a840f47 100644 --- a/code/ryzom/tools/leveldesign/variable_parser/StdAfx.h +++ b/code/ryzom/tools/leveldesign/variable_parser/StdAfx.h @@ -1,44 +1,44 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__17D2C6E8_64DB_4922_95A2_E74A8E91D24E__INCLUDED_) -#define AFX_STDAFX_H__17D2C6E8_64DB_4922_95A2_E74A8E91D24E__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#define NOMINMAX - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC Automation classes -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__17D2C6E8_64DB_4922_95A2_E74A8E91D24E__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__17D2C6E8_64DB_4922_95A2_E74A8E91D24E__INCLUDED_) +#define AFX_STDAFX_H__17D2C6E8_64DB_4922_95A2_E74A8E91D24E__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#define NOMINMAX + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__17D2C6E8_64DB_4922_95A2_E74A8E91D24E__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/variable_parser/lua_helper.cpp b/code/ryzom/tools/leveldesign/variable_parser/lua_helper.cpp index a24792c9b..2bb462664 100644 --- a/code/ryzom/tools/leveldesign/variable_parser/lua_helper.cpp +++ b/code/ryzom/tools/leveldesign/variable_parser/lua_helper.cpp @@ -1,726 +1,726 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" - -#include "lua_helper.h" -#include "nel/misc/file.h" -#include "nel/misc/path.h" -//#include "interface_manager.h" - -extern "C" -{ -#include "lualib.h" -} - -// to get rid of you_must_not_use_assert___use_nl_assert___read_debug_h_file messages -#include -#undef assert -#define assert nlassert -#include - -using namespace std; -using namespace NLMISC; - -// *************************************************************************** -const char *CLuaState::_NELSmallScriptTableName= "NELSmallScriptTable"; -uint CLuaStackChecker::_ExceptionContextCounter = 0; - -// *************************************************************************** -void CLuaStackChecker::incrementExceptionContextCounter() -{ - ++ _ExceptionContextCounter; -} - -// *************************************************************************** -void CLuaStackChecker::decrementExceptionContextCounter() -{ - nlassert(_ExceptionContextCounter > 0); - -- _ExceptionContextCounter; -} - - -#ifdef LUA_NEVRAX_VERSION - ILuaIDEInterface *LuaDebuggerIDE = NULL; - static bool LuaDebuggerVisible = false; -#endif - -#ifdef NL_OS_WINDOWS - HMODULE LuaDebuggerModule = 0; -#endif - -void luaDebuggerMainLoop() -{ -#ifdef LUA_NEVRAX_VERSION - if (!LuaDebuggerIDE) return; - if (!LuaDebuggerVisible) - { - LuaDebuggerIDE->showDebugger(true); - LuaDebuggerIDE->expandProjectTree(); - LuaDebuggerIDE->sortFiles(); - LuaDebuggerVisible = true; - } - LuaDebuggerIDE->doMainLoop(); -#endif -} - - - -static std::allocator l_stlAlloc; - - -static void l_free_func(void *block, int oldSize) -{ - l_stlAlloc.deallocate((uint8 *) block, oldSize); -} - -static void *l_realloc_func(void *b, int os, int s) -{ - if (os == s) return b; - void *newB = l_stlAlloc.allocate(s); - memcpy(newB, b, std::min(os, s)); - l_free_func(b, os); - return newB; -} - - - -const int MinGCThreshold = 128; // min value at which garbage collector will be triggered (in kilobytes) -// *************************************************************************** -CLuaState::CLuaState() -{ - _State = NULL; - - #ifdef LUA_NEVRAX_VERSION - _GCThreshold = MinGCThreshold; - #endif - - if (!_State) - { - #ifdef LUA_NEVRAX_VERSION - _State = lua_open(l_realloc_func, l_free_func); - #else - _State = lua_open(); - #endif - nlassert(_State); - } - - // *** Load base libs - { - CLuaStackChecker lsc(this); -#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 - luaL_openlibs(_State); -#else - luaopen_base (_State); - luaopen_table (_State); - luaopen_io (_State); - luaopen_string (_State); - luaopen_math (_State); - luaopen_debug (_State); -#endif - - // open are buggy???? - clear(); - } - - // *** Register basics - CLuaStackChecker lsc(this); - - // do: LUA_REGISTRYINDEX.(lightuserdata*)this.classes= {} - pushLightUserData((void *) this); - newTable(); - push("classes"); - newTable(); // registry class - setTable(-3); - setTable(LUA_REGISTRYINDEX); - - // add pointer from lua state to this CLuaState object - // do: LUA_REGISTRYINDEX.(lightuserdata*)_State= this - pushLightUserData((void *) _State); // NB : as creator of the state, we make the assumption that - // no one will be using this pointer in the registry (cf. ref manual about registry) - pushLightUserData((void *) this); - setTable(LUA_REGISTRYINDEX); - - // Create the Table that contains Function cache for small script execution - push(_NELSmallScriptTableName); // 1:TableName - newTable(); // 1:TableName 2:table - setTable(LUA_REGISTRYINDEX); // ... - _SmallScriptPool= 0; - - // *** luabind init - luabind::open(_State); -} - - -// *************************************************************************** -CLuaStackRestorer::CLuaStackRestorer(CLuaState *state, int finalSize) : _State(state), _FinalSize(finalSize) -{ -} - -// *************************************************************************** -CLuaStackRestorer::~CLuaStackRestorer() -{ - nlassert(_State); - _State->setTop(_FinalSize); -} - -#ifdef NL_OS_WINDOWS - static int NoOpReportHook( int /* reportType */, char * /* message */, int * /* returnValue */ ) - { - return TRUE; - } -#endif - - -// *************************************************************************** -CLuaState::~CLuaState() -{ - nlassert(_State); - - #ifdef LUA_NEVRAX_VERSION - if (!LuaDebuggerIDE) - #else - if (1) - #endif - { - lua_close(_State); - } - else - { - #ifdef LUA_NEVRAX_VERSION - LuaDebuggerIDE->stopDebug(); // this will also close the lua state - LuaDebuggerIDE = NULL; - LuaDebuggerVisible = false; - #ifdef NL_OS_WINDOWS - nlassert(LuaDebuggerModule) - _CrtSetReportHook(NoOpReportHook); // prevent dump of memory leaks at this point - //::FreeLibrary(LuaDebuggerModule); // don't free the library now (seems that it destroy, the main window, causing - // a crash when the app window is destroyed for real... - // -> FreeLibrary will be called when the application is closed - LuaDebuggerModule = 0; - #endif - #endif - } - - // Clear Small Script Cache - _SmallScriptPool= 0; - _SmallScriptCache.clear(); -} - -// *************************************************************************** -CLuaState *CLuaState::fromStatePointer(lua_State *state) -{ - nlassert(state); - int initialStackSize = lua_gettop(state); - lua_checkstack(state, initialStackSize + 2); - lua_pushlightuserdata(state, (void *) state); - lua_gettable(state, LUA_REGISTRYINDEX); - if (!lua_islightuserdata(state, -1)) - { - lua_pop(state, 1); - return NULL; - } - CLuaState *ls = (CLuaState *) lua_touserdata(state, -1); - lua_pop(state, 1); - nlassert(initialStackSize == lua_gettop(state)); - return ls; -} - -// *************************************************************************** -struct CLuaReader -{ - const std::string *Str; - bool Done; -}; - -void CLuaState::loadScript(const std::string &code, const std::string &dbgSrc) -{ - if (code.empty()) return; - struct CHelper - { - static const char *luaChunkReaderFromString(lua_State * /* L */, void *ud, size_t *sz) - { - CLuaReader *rd = (CLuaReader *) ud; - if (!rd->Done) - { - rd->Done = true; - *sz = rd->Str->size(); - return rd->Str->c_str(); - } - else - { - *sz = 0; - return NULL; - } - } - }; - CLuaReader rd; - rd.Str = &code; - rd.Done = false; - - int result = lua_load(_State, CHelper::luaChunkReaderFromString, (void *) &rd, dbgSrc.c_str()); - if (result !=0) - { - // pop the error code - string err= toString(); - pop(); - // throw error - throw ELuaParseError(err); - } -} - -// *************************************************************************** -void CLuaState::executeScriptInternal(const std::string &code, const std::string &dbgSrc, int numRet) -{ - CLuaStackChecker lsc(this, numRet); - - // load the script - loadScript(code, dbgSrc); - - // execute - if (pcall(0, numRet) != 0) - { - // pop the error code - string err= toString(); - pop(); - // throw error - throw ELuaExecuteError(err); - } -} - -// *************************************************************************** -void CLuaState::executeScript(const std::string &code, int numRet) -{ - // run the script, with dbgSrc==script - executeScriptInternal(code, code, numRet); -} - -// *************************************************************************** -bool CLuaState::executeScriptNoThrow(const std::string &code, int numRet) -{ - try - { - executeScript(code, numRet); - } - catch (ELuaError &e) - { - nlwarning(e.what()); - return false; - } - return true; -} - -// *************************************************************************** -bool CLuaState::executeFile(const std::string &pathName) -{ - CIFile inputFile; - if(!inputFile.open(pathName)) - return false; - - #ifdef LUA_NEVRAX_VERSION - if (LuaDebuggerIDE) - { - std::string path = NLMISC::CPath::getCurrentPath() + "/" + pathName.c_str(); - path = CPath::standardizeDosPath(path); - LuaDebuggerIDE->addFile(path.c_str()); - } - #endif - - // load the script text - string script; - /* - while(!inputFile.eof()) - { - char tmpBuff[5000]; - inputFile.getline(tmpBuff, 5000); - script+= tmpBuff; - script+= "\n"; - } - */ - script.resize(NLMISC::CFile::getFileSize(pathName)); - inputFile.serialBuffer((uint8 *) &script[0], (uint)script.size()); - - - // execute the script text, with dbgSrc==filename (use @ for lua internal purpose) - executeScriptInternal(script, string("@") + NLMISC::CFile::getFilename(pathName)); - - return true; -} - -// *************************************************************************** -void CLuaState::executeSmallScript(const std::string &script) -{ - if (script.empty()) return; - // *** if the small script has not already been called before, parse it now - TSmallScriptCache::iterator it= _SmallScriptCache.find(script); - if(it==_SmallScriptCache.end()) - { - CLuaStackChecker lsc(this); - - // add it to a function - loadScript(script, script); - - // Assign the method to the NEL table: NELSmallScriptTable[_SmallScriptPool]= function - push(_NELSmallScriptTableName); // 1:function 2:NelTableName - getTable(LUA_REGISTRYINDEX); // 1:function 2:NelTable - insert(-2); // 1:NelTable 2:function - rawSetI(-2, _SmallScriptPool); // 1:NelTable - pop(); - - // bkup in cache map - it= _SmallScriptCache.insert(make_pair(script, _SmallScriptPool)).first; - - // next allocated - _SmallScriptPool++; - } - - // *** Execute the function associated to the script - CLuaStackChecker lsc(this); - push(_NELSmallScriptTableName); // 1:NelTableName - getTable(LUA_REGISTRYINDEX); // 1:NelTable - // get the function at the given index in the "NELSmallScriptTable" table - rawGetI(-1, it->second); // 1:NelTable 2:function - - // execute - if (pcall(0, 0) != 0) - { - // Stack: 1: NelTable 2:errorcode - // pop the error code, and clear stack - string err= toString(); - pop(); // 1:NelTable - pop(); // .... - // throw error - throw ELuaExecuteError(err); - } - else - { - // Stack: 1:NelTable - pop(); // .... - } -} - -// *************************************************************************** -void CLuaState::registerFunc(const char *name, lua_CFunction function) -{ - lua_register(_State, name, function); -} - -// *************************************************************************** -void CLuaState::pushCClosure(lua_CFunction function, int n) -{ - nlassert(function); - nlassert(getTop() >= n); - lua_pushcclosure(_State, function, n); -} - -// *************************************************************************** -void CLuaState::push(TLuaWrappedFunction function) -{ - struct CForwarder - { - static int callFunc(lua_State *ls) - { - nlassert(ls); - TLuaWrappedFunction func = (TLuaWrappedFunction) lua_touserdata(ls, lua_upvalueindex(1)); - CLuaState *state = (CLuaState *) lua_touserdata(ls, lua_upvalueindex(2)); - nlassert(func); - nlassert(state); - // get real function pointer from the values in the closure - int numResults; - int initialStackSize = state->getTop(); - try - { - // call the actual function - numResults = func(*state); - } - catch(const std::exception &e) - { - // restore stack to its initial size - state->setTop(initialStackSize); - lua_pushstring(ls, e.what()); - // TODO : see if this is safe to call lua error there" ... (it does a long jump) - lua_error(ls); - } - return numResults; - } - }; - pushLightUserData((void *) function); - pushLightUserData((void *) this); - pushCClosure(CForwarder::callFunc, 2); -} - -// *************************************************************************** -// Wrapped function -void CLuaState::registerFunc(const char *name, TLuaWrappedFunction function) -{ - nlassert(function); - CLuaStackChecker lsc(this); - push(name); - push(function); - setTable(LUA_GLOBALSINDEX); -} - - -// *************************************************************************** -bool CLuaState::getTableBooleanValue(const char *name, bool defaultValue) -{ - nlassert(name); - push(name); - getTable(-2); - if (isNil()) - { - pop(); - return defaultValue; - } - bool result = toBoolean(-1); - pop(); - return result; -} - -// *************************************************************************** -double CLuaState::getTableNumberValue(const char *name, double defaultValue) -{ - nlassert(name); - push(name); - getTable(-2); - if (isNil()) - { - pop(); - return defaultValue; - } - double result = toNumber(-1); - pop(); - return result; -} - -// *************************************************************************** -const char *CLuaState::getTableStringValue(const char *name, const char *defaultValue) -{ - nlassert(name); - push(name); - getTable(-2); - if (isNil()) - { - pop(); - return defaultValue; - } - const char *result = toString(-1); - pop(); - return result; -} - -// *************************************************************************** -void CLuaState::getStackContext(string &ret, uint stackLevel) -{ - nlassert(_State); - ret.clear(); - lua_Debug dbg; - if(lua_getstack (_State, stackLevel, &dbg)) - { - if(lua_getinfo(_State, "lS", &dbg)) - { - ret= NLMISC::toString("%s:%d:", dbg.short_src, dbg.currentline); - } - } -} - -// *************************************************************************** -int CLuaState::pcallByName(const char *functionName, int nargs, int nresults, int funcTableIndex /*=LUA_GLOBALSINDEX*/, int errfunc /*= 0*/) -{ - int initialStackSize = getTop(); - nlassert(functionName); - nlassert(isTable(funcTableIndex)); - pushValue(funcTableIndex); - push(functionName); - getTable(-2); - remove(-2); // get rid of the table - nlassert(getTop() >= nargs); // not enough arguments on the stack - // insert function before its arguments - insert(- 1 - nargs); - int result = pcall(nargs, nresults, errfunc); - int currSize = getTop(); - if (result == 0) - { - nlassert(currSize == initialStackSize - nargs + nresults); - } - else - { - // errors, the stack contains a single string - if (errfunc == 0) - { - nlassert(currSize == initialStackSize - nargs + 1); - } - // else if there's an error handler, can't know the size of stack - } - return result; -} - -// *************************************************************************** -void CLuaState::dumpStack() -{ - nlinfo("LUA STACK CONTENT (size = %d)", getTop()); - nlinfo("================="); - CLuaStackChecker lsc(this); - for(int k = 1; k <= getTop(); ++k) - { - pushValue(k); - std::string value = toString(-1) ? toString(-1) : "?"; - nlinfo("Stack entry %d : type = %s, value = %s", k, getTypename(type(-1)), value.c_str()); - pop(); - } -} - -// *************************************************************************** -void CLuaState::getStackAsString(std::string &dest) -{ - dest = NLMISC::toString("Stack size = %d\n", getTop()); - CLuaStackChecker lsc(this); - for(int k = 1; k <= getTop(); ++k) - { - pushValue(k); - std::string value = toString(-1) ? toString(-1) : "?"; - dest += NLMISC::toString("Stack entry %d : type = %s, value = %s\n", k, getTypename(type(-1)), value.c_str()); - pop(); - } -} - -//================================================================================ -CLuaStackChecker::~CLuaStackChecker() -{ - nlassert(_State); - if (!_ExceptionContextCounter) - { - int currSize = _State->getTop(); - if (currSize != _FinalWantedSize) - { - static volatile bool assertWanted = true; - if (assertWanted) - { - nlwarning("Lua stack size error : expected size is %d, current size is %d", _FinalWantedSize, currSize); - _State->dumpStack(); - nlassert(0); - } - } - } - else - { - // this object dtor was called because an exception was thrown, so let the exception - // propagate (the stack must be broken, but because of the exception, not because of code error) - _State->setTop(_FinalWantedSize); - } -} - -// *************************************************************************** -void ELuaWrappedFunctionException::init(CLuaState *ls, const std::string &reason) -{ - // Print first Lua Stack Context -/* - CInterfaceManager *pIM= CInterfaceManager::getInstance(); - if(ls) - { - ls->getStackContext(_Reason, 1); // 1 because 0 is the current C function => return 1 for script called - // enclose with cool colors - pIM->formatLuaStackContext(_Reason); - } -*/ - // Append the reason - _Reason+= reason; -} - -// *************************************************************************** -ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState *luaState) -{ - init(luaState, ""); -} - -// *************************************************************************** -ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState *luaState, const std::string &reason) -{ - init(luaState, reason); -} - -// *************************************************************************** -ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState *luaState, const char *format, ...) -{ - //H_AUTO(Lua_ELuaWrappedFunctionException_ELuaWrappedFunctionException) - std::string reason; - NLMISC_CONVERT_VARGS (reason, format, NLMISC::MaxCStringSize); - init(luaState, reason); -} - -//================================================================================ -void CLuaState::newTable() -{ - nlverify( lua_checkstack(_State, 1) ); - lua_newtable(_State); -} - -//================================================================================ -int CLuaState::getGCCount() -{ - return lua_getgccount(_State); -} - -//================================================================================ -int CLuaState::getGCThreshold() -{ - //H_AUTO(Lua_CLuaState_getGCThreshold) -#ifdef LUA_NEVRAX_VERSION - return _GCThreshold; -#else -# if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 - return lua_gc(_State, LUA_GCCOUNT, 0); -# else - return lua_getgcthreshold(_State); -# endif -#endif -} - -//================================================================================ -void CLuaState::setGCThreshold(int kb) -{ - //H_AUTO(Lua_CLuaState_setGCThreshold) -#ifdef LUA_NEVRAX_VERSION - _GCThreshold = kb; - handleGC(); -#else -# if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 - lua_gc(_State, LUA_GCCOLLECT, kb); -# else - lua_setgcthreshold(_State, kb); -# endif -#endif -} - -//================================================================================ -void CLuaState::handleGC() -{ - //H_AUTO(Lua_CLuaState_handleGC) - #ifdef LUA_NEVRAX_VERSION - // must handle gc manually with the refcounted version - int gcCount = getGCCount(); - if (gcCount >= _GCThreshold) - { - nlwarning("Triggering GC : memory in use = %d kb, current threshold = %d kb", gcCount, _GCThreshold); - lua_setgcthreshold(_State, 0); - gcCount = getGCCount(); - _GCThreshold = std::max(MinGCThreshold, gcCount * 2); - nlwarning("After GC : memory in use = %d kb, threshold = %d kb", gcCount, _GCThreshold); - } - #endif -} - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" + +#include "lua_helper.h" +#include "nel/misc/file.h" +#include "nel/misc/path.h" +//#include "interface_manager.h" + +extern "C" +{ +#include "lualib.h" +} + +// to get rid of you_must_not_use_assert___use_nl_assert___read_debug_h_file messages +#include +#undef assert +#define assert nlassert +#include + +using namespace std; +using namespace NLMISC; + +// *************************************************************************** +const char *CLuaState::_NELSmallScriptTableName= "NELSmallScriptTable"; +uint CLuaStackChecker::_ExceptionContextCounter = 0; + +// *************************************************************************** +void CLuaStackChecker::incrementExceptionContextCounter() +{ + ++ _ExceptionContextCounter; +} + +// *************************************************************************** +void CLuaStackChecker::decrementExceptionContextCounter() +{ + nlassert(_ExceptionContextCounter > 0); + -- _ExceptionContextCounter; +} + + +#ifdef LUA_NEVRAX_VERSION + ILuaIDEInterface *LuaDebuggerIDE = NULL; + static bool LuaDebuggerVisible = false; +#endif + +#ifdef NL_OS_WINDOWS + HMODULE LuaDebuggerModule = 0; +#endif + +void luaDebuggerMainLoop() +{ +#ifdef LUA_NEVRAX_VERSION + if (!LuaDebuggerIDE) return; + if (!LuaDebuggerVisible) + { + LuaDebuggerIDE->showDebugger(true); + LuaDebuggerIDE->expandProjectTree(); + LuaDebuggerIDE->sortFiles(); + LuaDebuggerVisible = true; + } + LuaDebuggerIDE->doMainLoop(); +#endif +} + + + +static std::allocator l_stlAlloc; + + +static void l_free_func(void *block, int oldSize) +{ + l_stlAlloc.deallocate((uint8 *) block, oldSize); +} + +static void *l_realloc_func(void *b, int os, int s) +{ + if (os == s) return b; + void *newB = l_stlAlloc.allocate(s); + memcpy(newB, b, std::min(os, s)); + l_free_func(b, os); + return newB; +} + + + +const int MinGCThreshold = 128; // min value at which garbage collector will be triggered (in kilobytes) +// *************************************************************************** +CLuaState::CLuaState() +{ + _State = NULL; + + #ifdef LUA_NEVRAX_VERSION + _GCThreshold = MinGCThreshold; + #endif + + if (!_State) + { + #ifdef LUA_NEVRAX_VERSION + _State = lua_open(l_realloc_func, l_free_func); + #else + _State = lua_open(); + #endif + nlassert(_State); + } + + // *** Load base libs + { + CLuaStackChecker lsc(this); +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 + luaL_openlibs(_State); +#else + luaopen_base (_State); + luaopen_table (_State); + luaopen_io (_State); + luaopen_string (_State); + luaopen_math (_State); + luaopen_debug (_State); +#endif + + // open are buggy???? + clear(); + } + + // *** Register basics + CLuaStackChecker lsc(this); + + // do: LUA_REGISTRYINDEX.(lightuserdata*)this.classes= {} + pushLightUserData((void *) this); + newTable(); + push("classes"); + newTable(); // registry class + setTable(-3); + setTable(LUA_REGISTRYINDEX); + + // add pointer from lua state to this CLuaState object + // do: LUA_REGISTRYINDEX.(lightuserdata*)_State= this + pushLightUserData((void *) _State); // NB : as creator of the state, we make the assumption that + // no one will be using this pointer in the registry (cf. ref manual about registry) + pushLightUserData((void *) this); + setTable(LUA_REGISTRYINDEX); + + // Create the Table that contains Function cache for small script execution + push(_NELSmallScriptTableName); // 1:TableName + newTable(); // 1:TableName 2:table + setTable(LUA_REGISTRYINDEX); // ... + _SmallScriptPool= 0; + + // *** luabind init + luabind::open(_State); +} + + +// *************************************************************************** +CLuaStackRestorer::CLuaStackRestorer(CLuaState *state, int finalSize) : _State(state), _FinalSize(finalSize) +{ +} + +// *************************************************************************** +CLuaStackRestorer::~CLuaStackRestorer() +{ + nlassert(_State); + _State->setTop(_FinalSize); +} + +#ifdef NL_OS_WINDOWS + static int NoOpReportHook( int /* reportType */, char * /* message */, int * /* returnValue */ ) + { + return TRUE; + } +#endif + + +// *************************************************************************** +CLuaState::~CLuaState() +{ + nlassert(_State); + + #ifdef LUA_NEVRAX_VERSION + if (!LuaDebuggerIDE) + #else + if (1) + #endif + { + lua_close(_State); + } + else + { + #ifdef LUA_NEVRAX_VERSION + LuaDebuggerIDE->stopDebug(); // this will also close the lua state + LuaDebuggerIDE = NULL; + LuaDebuggerVisible = false; + #ifdef NL_OS_WINDOWS + nlassert(LuaDebuggerModule) + _CrtSetReportHook(NoOpReportHook); // prevent dump of memory leaks at this point + //::FreeLibrary(LuaDebuggerModule); // don't free the library now (seems that it destroy, the main window, causing + // a crash when the app window is destroyed for real... + // -> FreeLibrary will be called when the application is closed + LuaDebuggerModule = 0; + #endif + #endif + } + + // Clear Small Script Cache + _SmallScriptPool= 0; + _SmallScriptCache.clear(); +} + +// *************************************************************************** +CLuaState *CLuaState::fromStatePointer(lua_State *state) +{ + nlassert(state); + int initialStackSize = lua_gettop(state); + lua_checkstack(state, initialStackSize + 2); + lua_pushlightuserdata(state, (void *) state); + lua_gettable(state, LUA_REGISTRYINDEX); + if (!lua_islightuserdata(state, -1)) + { + lua_pop(state, 1); + return NULL; + } + CLuaState *ls = (CLuaState *) lua_touserdata(state, -1); + lua_pop(state, 1); + nlassert(initialStackSize == lua_gettop(state)); + return ls; +} + +// *************************************************************************** +struct CLuaReader +{ + const std::string *Str; + bool Done; +}; + +void CLuaState::loadScript(const std::string &code, const std::string &dbgSrc) +{ + if (code.empty()) return; + struct CHelper + { + static const char *luaChunkReaderFromString(lua_State * /* L */, void *ud, size_t *sz) + { + CLuaReader *rd = (CLuaReader *) ud; + if (!rd->Done) + { + rd->Done = true; + *sz = rd->Str->size(); + return rd->Str->c_str(); + } + else + { + *sz = 0; + return NULL; + } + } + }; + CLuaReader rd; + rd.Str = &code; + rd.Done = false; + + int result = lua_load(_State, CHelper::luaChunkReaderFromString, (void *) &rd, dbgSrc.c_str()); + if (result !=0) + { + // pop the error code + string err= toString(); + pop(); + // throw error + throw ELuaParseError(err); + } +} + +// *************************************************************************** +void CLuaState::executeScriptInternal(const std::string &code, const std::string &dbgSrc, int numRet) +{ + CLuaStackChecker lsc(this, numRet); + + // load the script + loadScript(code, dbgSrc); + + // execute + if (pcall(0, numRet) != 0) + { + // pop the error code + string err= toString(); + pop(); + // throw error + throw ELuaExecuteError(err); + } +} + +// *************************************************************************** +void CLuaState::executeScript(const std::string &code, int numRet) +{ + // run the script, with dbgSrc==script + executeScriptInternal(code, code, numRet); +} + +// *************************************************************************** +bool CLuaState::executeScriptNoThrow(const std::string &code, int numRet) +{ + try + { + executeScript(code, numRet); + } + catch (ELuaError &e) + { + nlwarning(e.what()); + return false; + } + return true; +} + +// *************************************************************************** +bool CLuaState::executeFile(const std::string &pathName) +{ + CIFile inputFile; + if(!inputFile.open(pathName)) + return false; + + #ifdef LUA_NEVRAX_VERSION + if (LuaDebuggerIDE) + { + std::string path = NLMISC::CPath::getCurrentPath() + "/" + pathName.c_str(); + path = CPath::standardizeDosPath(path); + LuaDebuggerIDE->addFile(path.c_str()); + } + #endif + + // load the script text + string script; + /* + while(!inputFile.eof()) + { + char tmpBuff[5000]; + inputFile.getline(tmpBuff, 5000); + script+= tmpBuff; + script+= "\n"; + } + */ + script.resize(NLMISC::CFile::getFileSize(pathName)); + inputFile.serialBuffer((uint8 *) &script[0], (uint)script.size()); + + + // execute the script text, with dbgSrc==filename (use @ for lua internal purpose) + executeScriptInternal(script, string("@") + NLMISC::CFile::getFilename(pathName)); + + return true; +} + +// *************************************************************************** +void CLuaState::executeSmallScript(const std::string &script) +{ + if (script.empty()) return; + // *** if the small script has not already been called before, parse it now + TSmallScriptCache::iterator it= _SmallScriptCache.find(script); + if(it==_SmallScriptCache.end()) + { + CLuaStackChecker lsc(this); + + // add it to a function + loadScript(script, script); + + // Assign the method to the NEL table: NELSmallScriptTable[_SmallScriptPool]= function + push(_NELSmallScriptTableName); // 1:function 2:NelTableName + getTable(LUA_REGISTRYINDEX); // 1:function 2:NelTable + insert(-2); // 1:NelTable 2:function + rawSetI(-2, _SmallScriptPool); // 1:NelTable + pop(); + + // bkup in cache map + it= _SmallScriptCache.insert(make_pair(script, _SmallScriptPool)).first; + + // next allocated + _SmallScriptPool++; + } + + // *** Execute the function associated to the script + CLuaStackChecker lsc(this); + push(_NELSmallScriptTableName); // 1:NelTableName + getTable(LUA_REGISTRYINDEX); // 1:NelTable + // get the function at the given index in the "NELSmallScriptTable" table + rawGetI(-1, it->second); // 1:NelTable 2:function + + // execute + if (pcall(0, 0) != 0) + { + // Stack: 1: NelTable 2:errorcode + // pop the error code, and clear stack + string err= toString(); + pop(); // 1:NelTable + pop(); // .... + // throw error + throw ELuaExecuteError(err); + } + else + { + // Stack: 1:NelTable + pop(); // .... + } +} + +// *************************************************************************** +void CLuaState::registerFunc(const char *name, lua_CFunction function) +{ + lua_register(_State, name, function); +} + +// *************************************************************************** +void CLuaState::pushCClosure(lua_CFunction function, int n) +{ + nlassert(function); + nlassert(getTop() >= n); + lua_pushcclosure(_State, function, n); +} + +// *************************************************************************** +void CLuaState::push(TLuaWrappedFunction function) +{ + struct CForwarder + { + static int callFunc(lua_State *ls) + { + nlassert(ls); + TLuaWrappedFunction func = (TLuaWrappedFunction) lua_touserdata(ls, lua_upvalueindex(1)); + CLuaState *state = (CLuaState *) lua_touserdata(ls, lua_upvalueindex(2)); + nlassert(func); + nlassert(state); + // get real function pointer from the values in the closure + int numResults; + int initialStackSize = state->getTop(); + try + { + // call the actual function + numResults = func(*state); + } + catch(const std::exception &e) + { + // restore stack to its initial size + state->setTop(initialStackSize); + lua_pushstring(ls, e.what()); + // TODO : see if this is safe to call lua error there" ... (it does a long jump) + lua_error(ls); + } + return numResults; + } + }; + pushLightUserData((void *) function); + pushLightUserData((void *) this); + pushCClosure(CForwarder::callFunc, 2); +} + +// *************************************************************************** +// Wrapped function +void CLuaState::registerFunc(const char *name, TLuaWrappedFunction function) +{ + nlassert(function); + CLuaStackChecker lsc(this); + push(name); + push(function); + setTable(LUA_GLOBALSINDEX); +} + + +// *************************************************************************** +bool CLuaState::getTableBooleanValue(const char *name, bool defaultValue) +{ + nlassert(name); + push(name); + getTable(-2); + if (isNil()) + { + pop(); + return defaultValue; + } + bool result = toBoolean(-1); + pop(); + return result; +} + +// *************************************************************************** +double CLuaState::getTableNumberValue(const char *name, double defaultValue) +{ + nlassert(name); + push(name); + getTable(-2); + if (isNil()) + { + pop(); + return defaultValue; + } + double result = toNumber(-1); + pop(); + return result; +} + +// *************************************************************************** +const char *CLuaState::getTableStringValue(const char *name, const char *defaultValue) +{ + nlassert(name); + push(name); + getTable(-2); + if (isNil()) + { + pop(); + return defaultValue; + } + const char *result = toString(-1); + pop(); + return result; +} + +// *************************************************************************** +void CLuaState::getStackContext(string &ret, uint stackLevel) +{ + nlassert(_State); + ret.clear(); + lua_Debug dbg; + if(lua_getstack (_State, stackLevel, &dbg)) + { + if(lua_getinfo(_State, "lS", &dbg)) + { + ret= NLMISC::toString("%s:%d:", dbg.short_src, dbg.currentline); + } + } +} + +// *************************************************************************** +int CLuaState::pcallByName(const char *functionName, int nargs, int nresults, int funcTableIndex /*=LUA_GLOBALSINDEX*/, int errfunc /*= 0*/) +{ + int initialStackSize = getTop(); + nlassert(functionName); + nlassert(isTable(funcTableIndex)); + pushValue(funcTableIndex); + push(functionName); + getTable(-2); + remove(-2); // get rid of the table + nlassert(getTop() >= nargs); // not enough arguments on the stack + // insert function before its arguments + insert(- 1 - nargs); + int result = pcall(nargs, nresults, errfunc); + int currSize = getTop(); + if (result == 0) + { + nlassert(currSize == initialStackSize - nargs + nresults); + } + else + { + // errors, the stack contains a single string + if (errfunc == 0) + { + nlassert(currSize == initialStackSize - nargs + 1); + } + // else if there's an error handler, can't know the size of stack + } + return result; +} + +// *************************************************************************** +void CLuaState::dumpStack() +{ + nlinfo("LUA STACK CONTENT (size = %d)", getTop()); + nlinfo("================="); + CLuaStackChecker lsc(this); + for(int k = 1; k <= getTop(); ++k) + { + pushValue(k); + std::string value = toString(-1) ? toString(-1) : "?"; + nlinfo("Stack entry %d : type = %s, value = %s", k, getTypename(type(-1)), value.c_str()); + pop(); + } +} + +// *************************************************************************** +void CLuaState::getStackAsString(std::string &dest) +{ + dest = NLMISC::toString("Stack size = %d\n", getTop()); + CLuaStackChecker lsc(this); + for(int k = 1; k <= getTop(); ++k) + { + pushValue(k); + std::string value = toString(-1) ? toString(-1) : "?"; + dest += NLMISC::toString("Stack entry %d : type = %s, value = %s\n", k, getTypename(type(-1)), value.c_str()); + pop(); + } +} + +//================================================================================ +CLuaStackChecker::~CLuaStackChecker() +{ + nlassert(_State); + if (!_ExceptionContextCounter) + { + int currSize = _State->getTop(); + if (currSize != _FinalWantedSize) + { + static volatile bool assertWanted = true; + if (assertWanted) + { + nlwarning("Lua stack size error : expected size is %d, current size is %d", _FinalWantedSize, currSize); + _State->dumpStack(); + nlassert(0); + } + } + } + else + { + // this object dtor was called because an exception was thrown, so let the exception + // propagate (the stack must be broken, but because of the exception, not because of code error) + _State->setTop(_FinalWantedSize); + } +} + +// *************************************************************************** +void ELuaWrappedFunctionException::init(CLuaState *ls, const std::string &reason) +{ + // Print first Lua Stack Context +/* + CInterfaceManager *pIM= CInterfaceManager::getInstance(); + if(ls) + { + ls->getStackContext(_Reason, 1); // 1 because 0 is the current C function => return 1 for script called + // enclose with cool colors + pIM->formatLuaStackContext(_Reason); + } +*/ + // Append the reason + _Reason+= reason; +} + +// *************************************************************************** +ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState *luaState) +{ + init(luaState, ""); +} + +// *************************************************************************** +ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState *luaState, const std::string &reason) +{ + init(luaState, reason); +} + +// *************************************************************************** +ELuaWrappedFunctionException::ELuaWrappedFunctionException(CLuaState *luaState, const char *format, ...) +{ + //H_AUTO(Lua_ELuaWrappedFunctionException_ELuaWrappedFunctionException) + std::string reason; + NLMISC_CONVERT_VARGS (reason, format, NLMISC::MaxCStringSize); + init(luaState, reason); +} + +//================================================================================ +void CLuaState::newTable() +{ + nlverify( lua_checkstack(_State, 1) ); + lua_newtable(_State); +} + +//================================================================================ +int CLuaState::getGCCount() +{ + return lua_getgccount(_State); +} + +//================================================================================ +int CLuaState::getGCThreshold() +{ + //H_AUTO(Lua_CLuaState_getGCThreshold) +#ifdef LUA_NEVRAX_VERSION + return _GCThreshold; +#else +# if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 + return lua_gc(_State, LUA_GCCOUNT, 0); +# else + return lua_getgcthreshold(_State); +# endif +#endif +} + +//================================================================================ +void CLuaState::setGCThreshold(int kb) +{ + //H_AUTO(Lua_CLuaState_setGCThreshold) +#ifdef LUA_NEVRAX_VERSION + _GCThreshold = kb; + handleGC(); +#else +# if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501 + lua_gc(_State, LUA_GCCOLLECT, kb); +# else + lua_setgcthreshold(_State, kb); +# endif +#endif +} + +//================================================================================ +void CLuaState::handleGC() +{ + //H_AUTO(Lua_CLuaState_handleGC) + #ifdef LUA_NEVRAX_VERSION + // must handle gc manually with the refcounted version + int gcCount = getGCCount(); + if (gcCount >= _GCThreshold) + { + nlwarning("Triggering GC : memory in use = %d kb, current threshold = %d kb", gcCount, _GCThreshold); + lua_setgcthreshold(_State, 0); + gcCount = getGCCount(); + _GCThreshold = std::max(MinGCThreshold, gcCount * 2); + nlwarning("After GC : memory in use = %d kb, threshold = %d kb", gcCount, _GCThreshold); + } + #endif +} + + diff --git a/code/ryzom/tools/leveldesign/variable_parser/lua_helper.h b/code/ryzom/tools/leveldesign/variable_parser/lua_helper.h index 4a7cb0095..3048daaea 100644 --- a/code/ryzom/tools/leveldesign/variable_parser/lua_helper.h +++ b/code/ryzom/tools/leveldesign/variable_parser/lua_helper.h @@ -1,374 +1,374 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef RZ_LUA_HELPER_H -#define RZ_LUA_HELPER_H - - -#include "nel/misc/types_nl.h" -#include "nel/misc/smart_ptr.h" - -extern "C" -{ - #include -} - - -class CLuaState; - -// *************************************************************************** -/** Helper class to see if a stack is restored at its initial size (or with n return results). - * Check that the stack size remains unchanged when the object goes out of scope - */ -class CLuaStackChecker -{ -public: - CLuaStackChecker(CLuaState *state, int numWantedResults = 0); - ~CLuaStackChecker(); - /** Increment exception context counter - * When an exception is thrown, lua stack checker do any assert bu will - * rather restore the lua stack at its original size, and will - * let the exception a chance to propagate - */ - static void incrementExceptionContextCounter(); - static void decrementExceptionContextCounter(); - -private: - CLuaState *_State; - int _FinalWantedSize; - static uint _ExceptionContextCounter; - -}; - -// ************************************************************************** -/** Helper class to restore the lua stack to the desired size when this object goes out of scope - */ -class CLuaStackRestorer -{ -public: - CLuaStackRestorer(CLuaState *state, int finalSize); - ~CLuaStackRestorer(); -private: - int _FinalSize; - CLuaState *_State; -}; - -//////////////// -// EXCEPTIONS // -//////////////// - -class ELuaError : public NLMISC::Exception -{ -public: - ELuaError() { CLuaStackChecker::incrementExceptionContextCounter(); } - virtual ~ELuaError() throw() { CLuaStackChecker::decrementExceptionContextCounter(); } - ELuaError(const std::string &reason) : Exception(reason) { CLuaStackChecker::incrementExceptionContextCounter(); } - // what(), plus append the Reason - virtual std::string luaWhat() const throw() {return NLMISC::toString("LUAError: %s", what());} -}; - -// A parse error occured -class ELuaParseError : public ELuaError -{ -public: - ELuaParseError() {} - ELuaParseError(const std::string &reason) : ELuaError(reason) {} - virtual ~ELuaParseError() throw() { } - // what(), plus append the Reason - virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaParseError: %s", what());} -}; - -/** Exception thrown when something went wrong inside a wrapped function called by lua - */ -class ELuaWrappedFunctionException : public ELuaError -{ -public: - ELuaWrappedFunctionException(CLuaState *luaState); - ELuaWrappedFunctionException(CLuaState *luaState, const std::string &reason); - ELuaWrappedFunctionException(CLuaState *luaState, const char *format, ...); - virtual ~ELuaWrappedFunctionException() throw() { } - virtual const char *what() const throw() {return _Reason.c_str();} -protected: - void init(CLuaState *ls, const std::string &reason); -protected: - std::string _Reason; -}; - -// A execution error occured -class ELuaExecuteError : public ELuaError -{ -public: - ELuaExecuteError() {} - ELuaExecuteError(const std::string &reason) : ELuaError(reason) {} - virtual ~ELuaExecuteError() throw() { } - // what(), plus append the Reason - virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaExecuteError: %s", what());} -}; - -// A bad cast occured when using lua_checkcast -class ELuaBadCast : public ELuaError -{ -public: - ELuaBadCast() {} - ELuaBadCast(const std::string &reason) : ELuaError(reason) {} - // what(), plus append the Reason - virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaBadCast: %s", what());} -}; - -// Error when trying to indexate an object that is not a table -class ELuaNotATable : public ELuaError -{ -public: - ELuaNotATable() {} - ELuaNotATable(const std::string &reason) : ELuaError(reason) {} - // what(), plus append the Reason - virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaNotATable: %s", what());} -}; - - -// *************************************************************************** -// a function to be used with a CLuaState instance -typedef int (* TLuaWrappedFunction) (CLuaState &ls); - - -// *************************************************************************** -/** C++ version of a lua state - */ -class CLuaState : public NLMISC::CRefCount -{ -public: - typedef NLMISC::CRefPtr TRefPtr; - - // Create a new environement - CLuaState(); - ~CLuaState(); - - - /// \name Registering - // @{ - // register a wrapped function - void registerFunc(const char *name, TLuaWrappedFunction function); - // @} - - - /// \name Script execution - // @{ - - /** Parse a script and push as a function in top of the LUA stack - * \throw ELuaParseError - * \param dbgSrc is a string for debug. Should be a filename (preceded with '@'), or a short script. - */ - void loadScript(const std::string &code, const std::string &dbgSrc); - - /** Execute a script from a string, possibly throwing an exception if there's a parse error - * \throw ELuaParseError, ELuaExecuteError - */ - void executeScript(const std::string &code, int numRet = 0); - - /** Execute a script from a string. If an errors occurs it is printed in the log - * \return true if script execution was successful - */ - bool executeScriptNoThrow(const std::string &code, int numRet = 0); - - /** Load a Script from a File (maybe in a BNP), and execute it - * \return false if file not found - * \throw ELuaParseError, ELuaExecuteError - */ - bool executeFile(const std::string &pathName); - - /** execute a very Small Script (a function call for instance) - * It is different from doString() in such there is a cache (where the key is the script itself) - * so that the second time this script is executed, there is no parsing - * Note: I experienced optim with about 10 times faster than a executeScript() on a simple "a= a+1;" script - * \throw ELuaParseError, ELuaExecuteError - */ - void executeSmallScript(const std::string &script); - - // @} - - - /// \name Stack Manipulation - // @{ - // stack manipulation (indices start at 1) - void setTop(int index); // set new size of stack - void clear() { setTop(0); } - int getTop(); - bool empty() { return getTop() == 0; } - void pushValue(int index); // copie nth element of stack to the top of the stack - void remove(int index); // remove nth element of stack - void insert(int index); // insert last element of the stack before the given position - void replace(int index); // replace nth element of the stack with the top of the stack - void pop(int numElem = 1); // remove n elements from the top of the stack - // test the type of an element in the stack - // return one of the following values : - // LUA_TNIL - // LUA_TNUMBER - // LUA_TBOOLEAN - // LUA_TSTRING - // LUA_TTABLE - // LUA_TFUNCTION - // LUA_TUSERDATA - // LUA_TTHREAD - // LUA_TLIGHTUSERDATA - int type(int index = -1); - const char *getTypename(int type); - bool isNil(int index = -1); - bool isBoolean(int index = -1); - bool isNumber(int index = -1); - bool isString(int index = -1); - bool isTable(int index = -1); - bool isFunction(int index = -1); - bool isCFunction(int index = -1); - bool isUserData(int index = -1); - bool isLightUserData(int index = -1); - // converting then getting a value from the stack - bool toBoolean(int index = -1); - lua_Number toNumber(int index = -1); - const char *toString(int index = -1); - void toString(int index, std::string &str); // convert to a std::string, with a NULL check. - size_t strlen(int index = -1); - lua_CFunction toCFunction(int index = -1); - void *toUserData(int index = -1); - const void *toPointer(int index = -1); - /** Helper functions : get value of the wanted type in the top table after conversion - * A default value is used if the stack entry is NULL. - * If conversion fails then an exception is thrown (with optional msg) - */ - bool getTableBooleanValue(const char *name, bool defaultValue= false); - double getTableNumberValue(const char *name, double defaultValue= 0); - const char *getTableStringValue(const char *name, const char *defaultValue= NULL); - // pushing value onto the stack - void push(bool value); - void push(lua_Number value); - void push(const char *str); - void push(const char *str, int length); - void push(const std::string &str); - void pushNil(); - void push(lua_CFunction f); - void push(TLuaWrappedFunction function); - void pushLightUserData(void *); // push a light user data (use newUserData to push a full userdata) - // metatables - bool getMetaTable(int index = -1); - bool setMetaTable(int index = -1); // set the metatable at top of stack to the object at 'index' (usually -2), then pop the metatable - // even if asignment failed - // comparison - bool equal(int index1, int index2); - bool rawEqual(int index1, int index2); - bool lessThan(int index1, int index2); - // concatenation of the n element at the top of the stack (using lua semantic) - void concat(int numElem); - // tables - void newTable(); // create a new table at top of the stack - void getTable(int index); // get value from a table at index 'index' (key is at top) - void rawGet(int index); - void setTable(int index); // set (key, value) from top of the stack into the given table - // both key and value are poped - void rawSet(int index); - bool next(int index); // table traversal - // UserData - void *newUserData(uint size); - // seting value by int index in a table - void rawSetI(int index, int n); - void rawGetI(int index, int n); - /** Calling functions (it's up to the caller to clear the results) - * The function should have been pushed on the stack - */ - void call(int nargs, int nresults); - int pcall(int nargs, int nresults, int errfunc = 0); - /** Helper : Execute a function by name. Lookup for the function is done in the table at the index 'funcTableIndex' - * the behaviour is the same than with call of pcall. - */ - int pcallByName(const char *functionName, int nargs, int nresults, int funcTableIndex = LUA_GLOBALSINDEX, int errfunc = 0); - - // push a C closure (pop n element from the stack and associate with the function) - void pushCClosure(lua_CFunction function, int n); - // @} - - - /// \name Misc - // @{ - /** Retrieve pointer to a CLuaState environment from its lua_State pointer, or NULL - * if there no such environment - */ - static CLuaState *fromStatePointer(lua_State *state); - // Get state pointer. The state should not be closed (this object has ownership) - lua_State *getStatePointer() const {return _State;} - // check that an index is valid when accessing the stack - // an assertion is raised if the index is not valid - void checkIndex(int index); - - // registering C function to use with a lua state pointer - void registerFunc(const char *name, lua_CFunction function); - - // Garbage collector - int getGCCount(); // get memory in use in KB - int getGCThreshold(); // get max memory in KB - void setGCThreshold(int kb); // set max memory in KB (no-op with ref-counted version) - - // handle garbage collector for ref-counted version of lua (no-op with standard version, in which case gc handling is automatic) - void handleGC(); - - /** For Debug: get the Stack context of execution (filename / line) - * \param stackLevel: get the context of execution of the given stackLevel. - * 0 for the current function - * 1 for the function that called 0 - * 2 .... - * NB: if called from a C function called from LUA, remember that stackLevel 0 is the current function. - * Hence if you want to know what LUA context called you, pass stackLevel=1! - * \param ret string cleared if any error, else filled with formated FileName / LineNumber - */ - void getStackContext(std::string &ret, uint stackLevel); - // @} - - // for debug : dump the current content of the stack (no recursion) - void dumpStack(); - static void dumpStack(lua_State *ls); - void getStackAsString(std::string &dest); - - -private: - lua_State *_State; - - // Small Script Cache - uint _SmallScriptPool; - typedef std::map TSmallScriptCache; - TSmallScriptCache _SmallScriptCache; - static const char * _NELSmallScriptTableName; - -private: - // this object isn't intended to be copied - CLuaState(const CLuaState &/* other */):NLMISC::CRefCount() { nlassert(0); } - CLuaState &operator=(const CLuaState &/* other */) { nlassert(0); return *this; } - - void executeScriptInternal(const std::string &code, const std::string &dbgSrc, int numRet = 0); - -}; - - -// Access to lua function -// one should not include lua.h directly because if a debugger is present, lua -// function pointer will be taken from a dynamic library. - - - -//============================================================================================= -// include implementation -#define RZ_INCLUDE_LUA_HELPER_INLINE - #include "lua_helper_inline.h" -#undef RZ_INCLUDE_LUA_HELPER_INLINE - - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef RZ_LUA_HELPER_H +#define RZ_LUA_HELPER_H + + +#include "nel/misc/types_nl.h" +#include "nel/misc/smart_ptr.h" + +extern "C" +{ + #include +} + + +class CLuaState; + +// *************************************************************************** +/** Helper class to see if a stack is restored at its initial size (or with n return results). + * Check that the stack size remains unchanged when the object goes out of scope + */ +class CLuaStackChecker +{ +public: + CLuaStackChecker(CLuaState *state, int numWantedResults = 0); + ~CLuaStackChecker(); + /** Increment exception context counter + * When an exception is thrown, lua stack checker do any assert bu will + * rather restore the lua stack at its original size, and will + * let the exception a chance to propagate + */ + static void incrementExceptionContextCounter(); + static void decrementExceptionContextCounter(); + +private: + CLuaState *_State; + int _FinalWantedSize; + static uint _ExceptionContextCounter; + +}; + +// ************************************************************************** +/** Helper class to restore the lua stack to the desired size when this object goes out of scope + */ +class CLuaStackRestorer +{ +public: + CLuaStackRestorer(CLuaState *state, int finalSize); + ~CLuaStackRestorer(); +private: + int _FinalSize; + CLuaState *_State; +}; + +//////////////// +// EXCEPTIONS // +//////////////// + +class ELuaError : public NLMISC::Exception +{ +public: + ELuaError() { CLuaStackChecker::incrementExceptionContextCounter(); } + virtual ~ELuaError() throw() { CLuaStackChecker::decrementExceptionContextCounter(); } + ELuaError(const std::string &reason) : Exception(reason) { CLuaStackChecker::incrementExceptionContextCounter(); } + // what(), plus append the Reason + virtual std::string luaWhat() const throw() {return NLMISC::toString("LUAError: %s", what());} +}; + +// A parse error occured +class ELuaParseError : public ELuaError +{ +public: + ELuaParseError() {} + ELuaParseError(const std::string &reason) : ELuaError(reason) {} + virtual ~ELuaParseError() throw() { } + // what(), plus append the Reason + virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaParseError: %s", what());} +}; + +/** Exception thrown when something went wrong inside a wrapped function called by lua + */ +class ELuaWrappedFunctionException : public ELuaError +{ +public: + ELuaWrappedFunctionException(CLuaState *luaState); + ELuaWrappedFunctionException(CLuaState *luaState, const std::string &reason); + ELuaWrappedFunctionException(CLuaState *luaState, const char *format, ...); + virtual ~ELuaWrappedFunctionException() throw() { } + virtual const char *what() const throw() {return _Reason.c_str();} +protected: + void init(CLuaState *ls, const std::string &reason); +protected: + std::string _Reason; +}; + +// A execution error occured +class ELuaExecuteError : public ELuaError +{ +public: + ELuaExecuteError() {} + ELuaExecuteError(const std::string &reason) : ELuaError(reason) {} + virtual ~ELuaExecuteError() throw() { } + // what(), plus append the Reason + virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaExecuteError: %s", what());} +}; + +// A bad cast occured when using lua_checkcast +class ELuaBadCast : public ELuaError +{ +public: + ELuaBadCast() {} + ELuaBadCast(const std::string &reason) : ELuaError(reason) {} + // what(), plus append the Reason + virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaBadCast: %s", what());} +}; + +// Error when trying to indexate an object that is not a table +class ELuaNotATable : public ELuaError +{ +public: + ELuaNotATable() {} + ELuaNotATable(const std::string &reason) : ELuaError(reason) {} + // what(), plus append the Reason + virtual std::string luaWhat() const throw() {return NLMISC::toString("ELuaNotATable: %s", what());} +}; + + +// *************************************************************************** +// a function to be used with a CLuaState instance +typedef int (* TLuaWrappedFunction) (CLuaState &ls); + + +// *************************************************************************** +/** C++ version of a lua state + */ +class CLuaState : public NLMISC::CRefCount +{ +public: + typedef NLMISC::CRefPtr TRefPtr; + + // Create a new environement + CLuaState(); + ~CLuaState(); + + + /// \name Registering + // @{ + // register a wrapped function + void registerFunc(const char *name, TLuaWrappedFunction function); + // @} + + + /// \name Script execution + // @{ + + /** Parse a script and push as a function in top of the LUA stack + * \throw ELuaParseError + * \param dbgSrc is a string for debug. Should be a filename (preceded with '@'), or a short script. + */ + void loadScript(const std::string &code, const std::string &dbgSrc); + + /** Execute a script from a string, possibly throwing an exception if there's a parse error + * \throw ELuaParseError, ELuaExecuteError + */ + void executeScript(const std::string &code, int numRet = 0); + + /** Execute a script from a string. If an errors occurs it is printed in the log + * \return true if script execution was successful + */ + bool executeScriptNoThrow(const std::string &code, int numRet = 0); + + /** Load a Script from a File (maybe in a BNP), and execute it + * \return false if file not found + * \throw ELuaParseError, ELuaExecuteError + */ + bool executeFile(const std::string &pathName); + + /** execute a very Small Script (a function call for instance) + * It is different from doString() in such there is a cache (where the key is the script itself) + * so that the second time this script is executed, there is no parsing + * Note: I experienced optim with about 10 times faster than a executeScript() on a simple "a= a+1;" script + * \throw ELuaParseError, ELuaExecuteError + */ + void executeSmallScript(const std::string &script); + + // @} + + + /// \name Stack Manipulation + // @{ + // stack manipulation (indices start at 1) + void setTop(int index); // set new size of stack + void clear() { setTop(0); } + int getTop(); + bool empty() { return getTop() == 0; } + void pushValue(int index); // copie nth element of stack to the top of the stack + void remove(int index); // remove nth element of stack + void insert(int index); // insert last element of the stack before the given position + void replace(int index); // replace nth element of the stack with the top of the stack + void pop(int numElem = 1); // remove n elements from the top of the stack + // test the type of an element in the stack + // return one of the following values : + // LUA_TNIL + // LUA_TNUMBER + // LUA_TBOOLEAN + // LUA_TSTRING + // LUA_TTABLE + // LUA_TFUNCTION + // LUA_TUSERDATA + // LUA_TTHREAD + // LUA_TLIGHTUSERDATA + int type(int index = -1); + const char *getTypename(int type); + bool isNil(int index = -1); + bool isBoolean(int index = -1); + bool isNumber(int index = -1); + bool isString(int index = -1); + bool isTable(int index = -1); + bool isFunction(int index = -1); + bool isCFunction(int index = -1); + bool isUserData(int index = -1); + bool isLightUserData(int index = -1); + // converting then getting a value from the stack + bool toBoolean(int index = -1); + lua_Number toNumber(int index = -1); + const char *toString(int index = -1); + void toString(int index, std::string &str); // convert to a std::string, with a NULL check. + size_t strlen(int index = -1); + lua_CFunction toCFunction(int index = -1); + void *toUserData(int index = -1); + const void *toPointer(int index = -1); + /** Helper functions : get value of the wanted type in the top table after conversion + * A default value is used if the stack entry is NULL. + * If conversion fails then an exception is thrown (with optional msg) + */ + bool getTableBooleanValue(const char *name, bool defaultValue= false); + double getTableNumberValue(const char *name, double defaultValue= 0); + const char *getTableStringValue(const char *name, const char *defaultValue= NULL); + // pushing value onto the stack + void push(bool value); + void push(lua_Number value); + void push(const char *str); + void push(const char *str, int length); + void push(const std::string &str); + void pushNil(); + void push(lua_CFunction f); + void push(TLuaWrappedFunction function); + void pushLightUserData(void *); // push a light user data (use newUserData to push a full userdata) + // metatables + bool getMetaTable(int index = -1); + bool setMetaTable(int index = -1); // set the metatable at top of stack to the object at 'index' (usually -2), then pop the metatable + // even if asignment failed + // comparison + bool equal(int index1, int index2); + bool rawEqual(int index1, int index2); + bool lessThan(int index1, int index2); + // concatenation of the n element at the top of the stack (using lua semantic) + void concat(int numElem); + // tables + void newTable(); // create a new table at top of the stack + void getTable(int index); // get value from a table at index 'index' (key is at top) + void rawGet(int index); + void setTable(int index); // set (key, value) from top of the stack into the given table + // both key and value are poped + void rawSet(int index); + bool next(int index); // table traversal + // UserData + void *newUserData(uint size); + // seting value by int index in a table + void rawSetI(int index, int n); + void rawGetI(int index, int n); + /** Calling functions (it's up to the caller to clear the results) + * The function should have been pushed on the stack + */ + void call(int nargs, int nresults); + int pcall(int nargs, int nresults, int errfunc = 0); + /** Helper : Execute a function by name. Lookup for the function is done in the table at the index 'funcTableIndex' + * the behaviour is the same than with call of pcall. + */ + int pcallByName(const char *functionName, int nargs, int nresults, int funcTableIndex = LUA_GLOBALSINDEX, int errfunc = 0); + + // push a C closure (pop n element from the stack and associate with the function) + void pushCClosure(lua_CFunction function, int n); + // @} + + + /// \name Misc + // @{ + /** Retrieve pointer to a CLuaState environment from its lua_State pointer, or NULL + * if there no such environment + */ + static CLuaState *fromStatePointer(lua_State *state); + // Get state pointer. The state should not be closed (this object has ownership) + lua_State *getStatePointer() const {return _State;} + // check that an index is valid when accessing the stack + // an assertion is raised if the index is not valid + void checkIndex(int index); + + // registering C function to use with a lua state pointer + void registerFunc(const char *name, lua_CFunction function); + + // Garbage collector + int getGCCount(); // get memory in use in KB + int getGCThreshold(); // get max memory in KB + void setGCThreshold(int kb); // set max memory in KB (no-op with ref-counted version) + + // handle garbage collector for ref-counted version of lua (no-op with standard version, in which case gc handling is automatic) + void handleGC(); + + /** For Debug: get the Stack context of execution (filename / line) + * \param stackLevel: get the context of execution of the given stackLevel. + * 0 for the current function + * 1 for the function that called 0 + * 2 .... + * NB: if called from a C function called from LUA, remember that stackLevel 0 is the current function. + * Hence if you want to know what LUA context called you, pass stackLevel=1! + * \param ret string cleared if any error, else filled with formated FileName / LineNumber + */ + void getStackContext(std::string &ret, uint stackLevel); + // @} + + // for debug : dump the current content of the stack (no recursion) + void dumpStack(); + static void dumpStack(lua_State *ls); + void getStackAsString(std::string &dest); + + +private: + lua_State *_State; + + // Small Script Cache + uint _SmallScriptPool; + typedef std::map TSmallScriptCache; + TSmallScriptCache _SmallScriptCache; + static const char * _NELSmallScriptTableName; + +private: + // this object isn't intended to be copied + CLuaState(const CLuaState &/* other */):NLMISC::CRefCount() { nlassert(0); } + CLuaState &operator=(const CLuaState &/* other */) { nlassert(0); return *this; } + + void executeScriptInternal(const std::string &code, const std::string &dbgSrc, int numRet = 0); + +}; + + +// Access to lua function +// one should not include lua.h directly because if a debugger is present, lua +// function pointer will be taken from a dynamic library. + + + +//============================================================================================= +// include implementation +#define RZ_INCLUDE_LUA_HELPER_INLINE + #include "lua_helper_inline.h" +#undef RZ_INCLUDE_LUA_HELPER_INLINE + + +#endif diff --git a/code/ryzom/tools/leveldesign/variable_parser/lua_helper_inline.h b/code/ryzom/tools/leveldesign/variable_parser/lua_helper_inline.h index e3011bd74..94dad901c 100644 --- a/code/ryzom/tools/leveldesign/variable_parser/lua_helper_inline.h +++ b/code/ryzom/tools/leveldesign/variable_parser/lua_helper_inline.h @@ -1,422 +1,422 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef RZ_INCLUDE_LUA_HELPER_INLINE - #error "don't include directly, include lua_helper.h instead" -#endif - - -///////////////////// -// CLuaStackChecker // -////////////////////// - -//================================================================================ -inline CLuaStackChecker::CLuaStackChecker(CLuaState *state, int numWantedResults) -{ - nlassert(state); - _State = state; - _FinalWantedSize = state->getTop() + numWantedResults; -} - - -/////////////// -// CLuaState // -/////////////// - -//================================================================================ -inline void CLuaState::checkIndex(int index) -{ - // NB : more restrictive test that in the documentation there, because - // we don't expose the check stack function - nlassert( (index!=0 && abs(index) <= getTop()) - || index == LUA_REGISTRYINDEX - || index == LUA_GLOBALSINDEX - ); -} - -//================================================================================ -inline int CLuaState::getTop() -{ - return lua_gettop(_State); -} - -//================================================================================ -inline void CLuaState::setTop(int index) -{ - // if index is strictly negative, this is a "pop". ensure that the user don't pop more than allowed - if (index < 0) - { - checkIndex(index); - } - // if index is positive and is more than the current top - else if ( index>getTop() ) - { - // must ensure that we have enough stack space - nlverify( lua_checkstack(_State, index-getTop()) ); - } - - // set top - lua_settop(_State, index); -} - -//================================================================================ -inline void CLuaState::pushValue(int index) -{ - checkIndex(index); - lua_pushvalue(_State, index); -} - -//================================================================================ -inline void CLuaState::remove(int index) -{ - checkIndex(index); - lua_remove(_State, index); -} - -//================================================================================ -inline void CLuaState::insert(int index) -{ - checkIndex(index); - lua_insert(_State, index); -} - -//================================================================================ -inline void CLuaState::replace(int index) -{ - checkIndex(index); - lua_replace(_State, index); -} - -//================================================================================ -inline void CLuaState::pop(int numElem /* = 1 */) -{ - nlassert(numElem <= getTop()); - lua_pop(_State, numElem); -} - -//================================================================================ -inline int CLuaState::type(int index /* = -1 */) -{ - checkIndex(index); - return lua_type(_State, index); -} - -//================================================================================ -inline const char *CLuaState::getTypename(int type) -{ - return lua_typename(_State, type); -} - -//================================================================================ -inline bool CLuaState::isNil(int index) -{ - checkIndex(index); - return lua_isnil(_State, index) != 0; -} - -//================================================================================ -inline bool CLuaState::isBoolean(int index) -{ - checkIndex(index); - return lua_isboolean(_State, index) != 0; -} - -//================================================================================ -inline bool CLuaState::isNumber(int index) -{ - checkIndex(index); - return lua_isnumber(_State, index) != 0; -} - -//================================================================================ -inline bool CLuaState::isString(int index) -{ - checkIndex(index); - return lua_isstring(_State, index) != 0; -} - -//================================================================================ -inline bool CLuaState::isTable(int index) -{ - checkIndex(index); - return lua_istable(_State, index) != 0; -} - -//================================================================================ -inline bool CLuaState::isFunction(int index) -{ - checkIndex(index); - return lua_isfunction(_State, index) != 0; -} - -//================================================================================ -inline bool CLuaState::isCFunction(int index) -{ - checkIndex(index); - return lua_iscfunction(_State, index) != 0; -} - -//================================================================================ -inline bool CLuaState::isUserData(int index) -{ - checkIndex(index); - return lua_isuserdata(_State, index) != 0; -} - -//================================================================================ -inline bool CLuaState::isLightUserData(int index) -{ - checkIndex(index); - return lua_islightuserdata(_State, index) != 0; -} - -//================================================================================ -inline bool CLuaState::toBoolean(int index) -{ - checkIndex(index); - return lua_toboolean(_State, index) != 0; -} - -//================================================================================ -inline lua_Number CLuaState::toNumber(int index) -{ - checkIndex(index); - return lua_tonumber(_State, index); -} - -//================================================================================ -inline const char *CLuaState::toString(int index) -{ - checkIndex(index); - return lua_tostring(_State, index); -} - -//================================================================================ -inline void CLuaState::toString(int index, std::string &str) -{ - checkIndex(index); - const char *pc= lua_tostring(_State, index); - if(pc) - str= pc; - else - str.clear(); -} - -//================================================================================ -inline size_t CLuaState::strlen(int index) -{ - checkIndex(index); - return lua_strlen(_State, index); -} - -//================================================================================ -inline lua_CFunction CLuaState::toCFunction(int index) -{ - checkIndex(index); - return lua_tocfunction(_State, index); -} - -//================================================================================ -inline void *CLuaState::toUserData(int index) -{ - checkIndex(index); - return lua_touserdata(_State, index); -} - -//================================================================================ -inline const void *CLuaState::toPointer(int index) -{ - checkIndex(index); - return lua_topointer(_State, index); -} - - -//================================================================================ -inline void CLuaState::push(bool value) -{ - nlverify( lua_checkstack(_State, 1) ); - lua_pushboolean(_State, (int) value); -} - -//================================================================================ -inline void CLuaState::push(lua_Number value) -{ - nlverify( lua_checkstack(_State, 1) ); - lua_pushnumber(_State, value); -} - -//================================================================================ -inline void CLuaState::push(const char *str) -{ - nlverify( lua_checkstack(_State, 1) ); - lua_pushstring(_State, str); -} - - -//================================================================================ -inline void CLuaState::push(const char *str, int length) -{ - nlverify( lua_checkstack(_State, 1) ); - lua_pushlstring(_State, str, length); -} - -//================================================================================ -inline void CLuaState::push(const std::string &str) -{ - nlverify( lua_checkstack(_State, 1) ); - push(str.c_str()); -} - -//================================================================================ -inline void CLuaState::pushNil() -{ - nlverify( lua_checkstack(_State, 1) ); - lua_pushnil(_State); -} - -//================================================================================ -inline void CLuaState::push(lua_CFunction f) -{ - nlverify( lua_checkstack(_State, 1) ); - lua_pushcfunction(_State, f); -} - -//================================================================================ -inline void CLuaState::pushLightUserData(void *ptr) -{ - nlverify( lua_checkstack(_State, 1) ); - lua_pushlightuserdata(_State, ptr); -} - -//================================================================================ -inline bool CLuaState::equal(int index1, int index2) -{ - checkIndex(index1); - checkIndex(index2); - return lua_equal(_State, index1, index2) != 0; -} - -//================================================================================ -inline bool CLuaState::getMetaTable(int index) -{ - checkIndex(index); - return lua_getmetatable(_State, index) != 0; -} - -//================================================================================ -inline bool CLuaState::setMetaTable(int index) -{ - checkIndex(index); - return lua_setmetatable(_State, index) != 0; -} - -//================================================================================ -inline bool CLuaState::rawEqual(int index1, int index2) -{ - checkIndex(index1); - checkIndex(index2); - return lua_rawequal(_State, index1, index2) != 0; -} - -//================================================================================ -inline bool CLuaState::lessThan(int index1, int index2) -{ - checkIndex(index1); - checkIndex(index2); - return lua_lessthan(_State, index1, index2) != 0; -} - - -//================================================================================ -inline void CLuaState::concat(int numElem) -{ - nlassert(numElem <= getTop()); - lua_concat(_State, numElem); -} - -//================================================================================ -inline void CLuaState::getTable(int index) -{ - checkIndex(index); - nlassert(isTable(index) || isUserData(index)); - lua_gettable(_State, index); -} - -//================================================================================ -inline void CLuaState::rawGet(int index) -{ - checkIndex(index); - lua_rawget(_State, index); -} - -//================================================================================ -inline void CLuaState::setTable(int index) -{ - checkIndex(index); - nlassert(getTop() >= 2); - nlassert(isTable(index)); - lua_settable(_State, index); -} - -//================================================================================ -inline void CLuaState::rawSet(int index) -{ - checkIndex(index); - lua_rawset(_State, index); -} - -//================================================================================ -inline bool CLuaState::next(int index) -{ - //H_AUTO(Lua_CLuaState_next) - checkIndex(index); - return lua_next(_State, index) != 0; -} - -//================================================================================ -inline void CLuaState::rawSetI(int index, int n) -{ - //H_AUTO(Lua_CLuaState_rawSetI) - checkIndex(index); - lua_rawseti(_State, index, n); -} - -//================================================================================ -inline void CLuaState::rawGetI(int index, int n) -{ - checkIndex(index); - lua_rawgeti(_State, index, n); -} - -//================================================================================ -inline void CLuaState::call(int nargs, int nresults) -{ - nlassert(getTop() >= nargs); - lua_call(_State, nargs, nresults); -} - -//================================================================================ -inline int CLuaState::pcall(int nargs, int nresults, int errfunc) -{ - return lua_pcall(_State, nargs, nresults, errfunc); -} - -//================================================================================ -inline void *CLuaState::newUserData(uint size) -{ - nlassert(size>0); - return lua_newuserdata(_State, size); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef RZ_INCLUDE_LUA_HELPER_INLINE + #error "don't include directly, include lua_helper.h instead" +#endif + + +///////////////////// +// CLuaStackChecker // +////////////////////// + +//================================================================================ +inline CLuaStackChecker::CLuaStackChecker(CLuaState *state, int numWantedResults) +{ + nlassert(state); + _State = state; + _FinalWantedSize = state->getTop() + numWantedResults; +} + + +/////////////// +// CLuaState // +/////////////// + +//================================================================================ +inline void CLuaState::checkIndex(int index) +{ + // NB : more restrictive test that in the documentation there, because + // we don't expose the check stack function + nlassert( (index!=0 && abs(index) <= getTop()) + || index == LUA_REGISTRYINDEX + || index == LUA_GLOBALSINDEX + ); +} + +//================================================================================ +inline int CLuaState::getTop() +{ + return lua_gettop(_State); +} + +//================================================================================ +inline void CLuaState::setTop(int index) +{ + // if index is strictly negative, this is a "pop". ensure that the user don't pop more than allowed + if (index < 0) + { + checkIndex(index); + } + // if index is positive and is more than the current top + else if ( index>getTop() ) + { + // must ensure that we have enough stack space + nlverify( lua_checkstack(_State, index-getTop()) ); + } + + // set top + lua_settop(_State, index); +} + +//================================================================================ +inline void CLuaState::pushValue(int index) +{ + checkIndex(index); + lua_pushvalue(_State, index); +} + +//================================================================================ +inline void CLuaState::remove(int index) +{ + checkIndex(index); + lua_remove(_State, index); +} + +//================================================================================ +inline void CLuaState::insert(int index) +{ + checkIndex(index); + lua_insert(_State, index); +} + +//================================================================================ +inline void CLuaState::replace(int index) +{ + checkIndex(index); + lua_replace(_State, index); +} + +//================================================================================ +inline void CLuaState::pop(int numElem /* = 1 */) +{ + nlassert(numElem <= getTop()); + lua_pop(_State, numElem); +} + +//================================================================================ +inline int CLuaState::type(int index /* = -1 */) +{ + checkIndex(index); + return lua_type(_State, index); +} + +//================================================================================ +inline const char *CLuaState::getTypename(int type) +{ + return lua_typename(_State, type); +} + +//================================================================================ +inline bool CLuaState::isNil(int index) +{ + checkIndex(index); + return lua_isnil(_State, index) != 0; +} + +//================================================================================ +inline bool CLuaState::isBoolean(int index) +{ + checkIndex(index); + return lua_isboolean(_State, index) != 0; +} + +//================================================================================ +inline bool CLuaState::isNumber(int index) +{ + checkIndex(index); + return lua_isnumber(_State, index) != 0; +} + +//================================================================================ +inline bool CLuaState::isString(int index) +{ + checkIndex(index); + return lua_isstring(_State, index) != 0; +} + +//================================================================================ +inline bool CLuaState::isTable(int index) +{ + checkIndex(index); + return lua_istable(_State, index) != 0; +} + +//================================================================================ +inline bool CLuaState::isFunction(int index) +{ + checkIndex(index); + return lua_isfunction(_State, index) != 0; +} + +//================================================================================ +inline bool CLuaState::isCFunction(int index) +{ + checkIndex(index); + return lua_iscfunction(_State, index) != 0; +} + +//================================================================================ +inline bool CLuaState::isUserData(int index) +{ + checkIndex(index); + return lua_isuserdata(_State, index) != 0; +} + +//================================================================================ +inline bool CLuaState::isLightUserData(int index) +{ + checkIndex(index); + return lua_islightuserdata(_State, index) != 0; +} + +//================================================================================ +inline bool CLuaState::toBoolean(int index) +{ + checkIndex(index); + return lua_toboolean(_State, index) != 0; +} + +//================================================================================ +inline lua_Number CLuaState::toNumber(int index) +{ + checkIndex(index); + return lua_tonumber(_State, index); +} + +//================================================================================ +inline const char *CLuaState::toString(int index) +{ + checkIndex(index); + return lua_tostring(_State, index); +} + +//================================================================================ +inline void CLuaState::toString(int index, std::string &str) +{ + checkIndex(index); + const char *pc= lua_tostring(_State, index); + if(pc) + str= pc; + else + str.clear(); +} + +//================================================================================ +inline size_t CLuaState::strlen(int index) +{ + checkIndex(index); + return lua_strlen(_State, index); +} + +//================================================================================ +inline lua_CFunction CLuaState::toCFunction(int index) +{ + checkIndex(index); + return lua_tocfunction(_State, index); +} + +//================================================================================ +inline void *CLuaState::toUserData(int index) +{ + checkIndex(index); + return lua_touserdata(_State, index); +} + +//================================================================================ +inline const void *CLuaState::toPointer(int index) +{ + checkIndex(index); + return lua_topointer(_State, index); +} + + +//================================================================================ +inline void CLuaState::push(bool value) +{ + nlverify( lua_checkstack(_State, 1) ); + lua_pushboolean(_State, (int) value); +} + +//================================================================================ +inline void CLuaState::push(lua_Number value) +{ + nlverify( lua_checkstack(_State, 1) ); + lua_pushnumber(_State, value); +} + +//================================================================================ +inline void CLuaState::push(const char *str) +{ + nlverify( lua_checkstack(_State, 1) ); + lua_pushstring(_State, str); +} + + +//================================================================================ +inline void CLuaState::push(const char *str, int length) +{ + nlverify( lua_checkstack(_State, 1) ); + lua_pushlstring(_State, str, length); +} + +//================================================================================ +inline void CLuaState::push(const std::string &str) +{ + nlverify( lua_checkstack(_State, 1) ); + push(str.c_str()); +} + +//================================================================================ +inline void CLuaState::pushNil() +{ + nlverify( lua_checkstack(_State, 1) ); + lua_pushnil(_State); +} + +//================================================================================ +inline void CLuaState::push(lua_CFunction f) +{ + nlverify( lua_checkstack(_State, 1) ); + lua_pushcfunction(_State, f); +} + +//================================================================================ +inline void CLuaState::pushLightUserData(void *ptr) +{ + nlverify( lua_checkstack(_State, 1) ); + lua_pushlightuserdata(_State, ptr); +} + +//================================================================================ +inline bool CLuaState::equal(int index1, int index2) +{ + checkIndex(index1); + checkIndex(index2); + return lua_equal(_State, index1, index2) != 0; +} + +//================================================================================ +inline bool CLuaState::getMetaTable(int index) +{ + checkIndex(index); + return lua_getmetatable(_State, index) != 0; +} + +//================================================================================ +inline bool CLuaState::setMetaTable(int index) +{ + checkIndex(index); + return lua_setmetatable(_State, index) != 0; +} + +//================================================================================ +inline bool CLuaState::rawEqual(int index1, int index2) +{ + checkIndex(index1); + checkIndex(index2); + return lua_rawequal(_State, index1, index2) != 0; +} + +//================================================================================ +inline bool CLuaState::lessThan(int index1, int index2) +{ + checkIndex(index1); + checkIndex(index2); + return lua_lessthan(_State, index1, index2) != 0; +} + + +//================================================================================ +inline void CLuaState::concat(int numElem) +{ + nlassert(numElem <= getTop()); + lua_concat(_State, numElem); +} + +//================================================================================ +inline void CLuaState::getTable(int index) +{ + checkIndex(index); + nlassert(isTable(index) || isUserData(index)); + lua_gettable(_State, index); +} + +//================================================================================ +inline void CLuaState::rawGet(int index) +{ + checkIndex(index); + lua_rawget(_State, index); +} + +//================================================================================ +inline void CLuaState::setTable(int index) +{ + checkIndex(index); + nlassert(getTop() >= 2); + nlassert(isTable(index)); + lua_settable(_State, index); +} + +//================================================================================ +inline void CLuaState::rawSet(int index) +{ + checkIndex(index); + lua_rawset(_State, index); +} + +//================================================================================ +inline bool CLuaState::next(int index) +{ + //H_AUTO(Lua_CLuaState_next) + checkIndex(index); + return lua_next(_State, index) != 0; +} + +//================================================================================ +inline void CLuaState::rawSetI(int index, int n) +{ + //H_AUTO(Lua_CLuaState_rawSetI) + checkIndex(index); + lua_rawseti(_State, index, n); +} + +//================================================================================ +inline void CLuaState::rawGetI(int index, int n) +{ + checkIndex(index); + lua_rawgeti(_State, index, n); +} + +//================================================================================ +inline void CLuaState::call(int nargs, int nresults) +{ + nlassert(getTop() >= nargs); + lua_call(_State, nargs, nresults); +} + +//================================================================================ +inline int CLuaState::pcall(int nargs, int nresults, int errfunc) +{ + return lua_pcall(_State, nargs, nresults, errfunc); +} + +//================================================================================ +inline void *CLuaState::newUserData(uint size) +{ + nlassert(size>0); + return lua_newuserdata(_State, size); +} diff --git a/code/ryzom/tools/leveldesign/variable_parser/resource.h b/code/ryzom/tools/leveldesign/variable_parser/resource.h index 5410565bb..c41671a22 100644 --- a/code/ryzom/tools/leveldesign/variable_parser/resource.h +++ b/code/ryzom/tools/leveldesign/variable_parser/resource.h @@ -1,49 +1,49 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by variable_parser.rc -// -#define IDD_VARIABLEPARSER_DIALOG 102 -#define IDR_MAINFRAME 128 -#define IDC_HDR_FILE 1000 -#define IDC_TMPL_FILE 1001 -#define IDC_FOOT_FILE 1002 -#define IDC_HDR_BROWSE 1003 -#define IDC_TMPL_BROWSE 1004 -#define IDC_FOOT_BROWSE 1005 -#define IDC_GENERATE 1006 -#define IDC_OUTPUT_FILE 1007 -#define IDC_OUTPUT_BROWSE 1008 -#define IDC_GEN_FILE 1009 -#define IDC_GEN_BROWSE 1010 -#define IDC_LUA_FILE 1011 -#define IDC_LUA_BROWSE 1012 -#define IDC_VARDEF 1013 -#define IDC_ADDVARDEF 1014 -#define IDC_REMVARDEF 1015 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 130 -#define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1016 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by variable_parser.rc +// +#define IDD_VARIABLEPARSER_DIALOG 102 +#define IDR_MAINFRAME 128 +#define IDC_HDR_FILE 1000 +#define IDC_TMPL_FILE 1001 +#define IDC_FOOT_FILE 1002 +#define IDC_HDR_BROWSE 1003 +#define IDC_TMPL_BROWSE 1004 +#define IDC_FOOT_BROWSE 1005 +#define IDC_GENERATE 1006 +#define IDC_OUTPUT_FILE 1007 +#define IDC_OUTPUT_BROWSE 1008 +#define IDC_GEN_FILE 1009 +#define IDC_GEN_BROWSE 1010 +#define IDC_LUA_FILE 1011 +#define IDC_LUA_BROWSE 1012 +#define IDC_VARDEF 1013 +#define IDC_ADDVARDEF 1014 +#define IDC_REMVARDEF 1015 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 130 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1016 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/code/ryzom/tools/leveldesign/variable_parser/variable_parser.cpp b/code/ryzom/tools/leveldesign/variable_parser/variable_parser.cpp index 66f50f8d2..405db5e90 100644 --- a/code/ryzom/tools/leveldesign/variable_parser/variable_parser.cpp +++ b/code/ryzom/tools/leveldesign/variable_parser/variable_parser.cpp @@ -1,92 +1,92 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// VariableParser.cpp : Defines the class behaviors for the application. -// - -#include "stdafx.h" -#include "variable_parser.h" -#include "variable_parserDlg.h" - -/*#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif -*/ - - -///////////////////////////////////////////////////////////////////////////// -// CVariableParserApp - -BEGIN_MESSAGE_MAP(CVariableParserApp, CWinApp) - //{{AFX_MSG_MAP(CVariableParserApp) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code! - //}}AFX_MSG - ON_COMMAND(ID_HELP, CWinApp::OnHelp) -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CVariableParserApp construction - -CVariableParserApp::CVariableParserApp() -{ - // TODO: add construction code here, - // Place all significant initialization in InitInstance -} - -///////////////////////////////////////////////////////////////////////////// -// The one and only CVariableParserApp object - -CVariableParserApp theApp; - -///////////////////////////////////////////////////////////////////////////// -// CVariableParserApp initialization - -BOOL CVariableParserApp::InitInstance() -{ - AfxEnableControlContainer(); - - // Standard initialization - // If you are not using these features and wish to reduce the size - // of your final executable, you should remove from the following - // the specific initialization routines you do not need. - -#ifdef _AFXDLL - Enable3dControls(); // Call this when using MFC in a shared DLL -#else - Enable3dControlsStatic(); // Call this when linking to MFC statically -#endif - - CVariableParserDlg dlg; - m_pMainWnd = &dlg; - int nResponse = dlg.DoModal(); - if (nResponse == IDOK) - { - // TODO: Place code here to handle when the dialog is - // dismissed with OK - } - else if (nResponse == IDCANCEL) - { - // TODO: Place code here to handle when the dialog is - // dismissed with Cancel - } - - // Since the dialog has been closed, return FALSE so that we exit the - // application, rather than start the application's message pump. - return FALSE; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// VariableParser.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "variable_parser.h" +#include "variable_parserDlg.h" + +/*#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif +*/ + + +///////////////////////////////////////////////////////////////////////////// +// CVariableParserApp + +BEGIN_MESSAGE_MAP(CVariableParserApp, CWinApp) + //{{AFX_MSG_MAP(CVariableParserApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CVariableParserApp construction + +CVariableParserApp::CVariableParserApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CVariableParserApp object + +CVariableParserApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CVariableParserApp initialization + +BOOL CVariableParserApp::InitInstance() +{ + AfxEnableControlContainer(); + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + CVariableParserDlg dlg; + m_pMainWnd = &dlg; + int nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} diff --git a/code/ryzom/tools/leveldesign/variable_parser/variable_parser.h b/code/ryzom/tools/leveldesign/variable_parser/variable_parser.h index e83a747c1..1d608b291 100644 --- a/code/ryzom/tools/leveldesign/variable_parser/variable_parser.h +++ b/code/ryzom/tools/leveldesign/variable_parser/variable_parser.h @@ -1,65 +1,65 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// VariableParser.h : main header file for the VARIABLEPARSER application -// - -#if !defined(AFX_VARIABLEPARSER_H__8AF5C966_94E0_4F89_AA0E_1DCA9720623A__INCLUDED_) -#define AFX_VARIABLEPARSER_H__8AF5C966_94E0_4F89_AA0E_1DCA9720623A__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including this file for PCH -#endif - -#include "resource.h" // main symbols - -///////////////////////////////////////////////////////////////////////////// -// CVariableParserApp: -// See VariableParser.cpp for the implementation of this class -// - -class CVariableParserApp : public CWinApp -{ -public: - CVariableParserApp(); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CVariableParserApp) - public: - virtual BOOL InitInstance(); - //}}AFX_VIRTUAL - -// Implementation - - //{{AFX_MSG(CVariableParserApp) - // NOTE - the ClassWizard will add and remove member functions here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_VARIABLEPARSER_H__8AF5C966_94E0_4F89_AA0E_1DCA9720623A__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// VariableParser.h : main header file for the VARIABLEPARSER application +// + +#if !defined(AFX_VARIABLEPARSER_H__8AF5C966_94E0_4F89_AA0E_1DCA9720623A__INCLUDED_) +#define AFX_VARIABLEPARSER_H__8AF5C966_94E0_4F89_AA0E_1DCA9720623A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CVariableParserApp: +// See VariableParser.cpp for the implementation of this class +// + +class CVariableParserApp : public CWinApp +{ +public: + CVariableParserApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CVariableParserApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + + //{{AFX_MSG(CVariableParserApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_VARIABLEPARSER_H__8AF5C966_94E0_4F89_AA0E_1DCA9720623A__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/variable_parser/variable_parserDlg.cpp b/code/ryzom/tools/leveldesign/variable_parser/variable_parserDlg.cpp index 1cd92d758..60360d47b 100644 --- a/code/ryzom/tools/leveldesign/variable_parser/variable_parserDlg.cpp +++ b/code/ryzom/tools/leveldesign/variable_parser/variable_parserDlg.cpp @@ -1,500 +1,500 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// VariableParserDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "variable_parser.h" -#include "variable_parserDlg.h" - -/*#ifdef _DEBUG -#define new DEBUG_NEW -#undef THIS_FILE -static char THIS_FILE[] = __FILE__; -#endif*/ - -using namespace NLMISC; -using namespace std; - -///////////////////////////////////////////////////////////////////////////// -// CVariableParserDlg dialog - -CVariableParserDlg::CVariableParserDlg(CWnd* pParent /*=NULL*/) - : CDialog(CVariableParserDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CVariableParserDlg) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT - // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 - m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); -} - -CVariableParserDlg::~CVariableParserDlg() -{ - m_nomVariables.clear(); - for ( uint i=0; iSetWindowText( fileDlg.GetPathName() ); - } -} - - -void CVariableParserDlg::OnTmplBrowse() -{ - CFileDialog fileDlg( TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, "Primitive file (*.primitive)|*.primitive||"); - - if ( fileDlg.DoModal() == IDOK ) - { - GetDlgItem( IDC_TMPL_FILE )->SetWindowText( fileDlg.GetPathName() ); - } -} - - -void CVariableParserDlg::OnFootBrowse() -{ - CFileDialog fileDlg( TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, "Primitive file (*.primitive)|*.primitive||"); - - if ( fileDlg.DoModal() == IDOK ) - { - GetDlgItem( IDC_FOOT_FILE )->SetWindowText( fileDlg.GetPathName() ); - } -} - - -void CVariableParserDlg::OnOutputBrowse() -{ - CFileDialog fileDlg( FALSE, NULL, NULL, OFN_OVERWRITEPROMPT, "Primitive file (*.primitive)|*.primitive||"); - - if ( fileDlg.DoModal() == IDOK ) - { - GetDlgItem( IDC_OUTPUT_FILE )->SetWindowText( fileDlg.GetPathName() ); - } -} - - -void CVariableParserDlg::OnGenBrowse() -{ - CFileDialog fileDlg( TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, "Comma Separated Values (*.csv)|*.csv||"); - - if ( fileDlg.DoModal() == IDOK ) - { - GetDlgItem( IDC_GEN_FILE )->SetWindowText( fileDlg.GetPathName() ); - } -} - -void CVariableParserDlg::OnLUABrowse() -{ - CFileDialog fileDlg( TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, "Lua files (*.lua)|*.lua||"); - - if ( fileDlg.DoModal() == IDOK ) - { - GetDlgItem( IDC_LUA_FILE )->SetWindowText( fileDlg.GetPathName() ); - } -} - -void CleanString( CSString &str ) -{ - int i = (int)str.size(); - bool ok = false; - - while ( !ok && ( i > 0 ) ) - { - char c = str.c_str()[i-1]; - if ( !isalpha(c) && !isdigit(c) && ( c != '_' ) && ( c != ')' ) ) - { - i--; - } - else - ok = true; - } - - str = str.left( i ); -} - -void CVariableParserDlg::ProcessGeneratorFile( const string& generatorFile ) -{ - CSString genData, ligne; - int colonneVar = 0; - - genData.readFromFile( generatorFile ); - - ligne = genData.splitTo( "\n", true ); - - while ( ligne != "" ) - { - CSString var = ligne.splitTo( ";", true ); - CleanString( var ); - - if ( var != "" ) - { - m_nomVariables.push_back( var ) ; - vector vec; - m_variables.push_back( vec ); - } - } - - while ( genData != "" ) - { - ligne = genData.splitTo( "\n", true ); - - if ( ligne != "" ) - { - for ( uint i=0;i= params.capacity() ) - params.push_back( "" ); - - CString str = m_variables[colonne][ligne].c_str(); - params[colonne] = str; - - if ( colonne+1 == m_variables.size() ) - { - ParseTemplate( params ); - } - else - { - BuildParseParameters( params, ligne, colonne+1 ); - } - } - else if ( left == "##" ) - { - params.push_back( "" ); - CString str = m_variables[colonne][0].c_str(); - - for ( uint j=(uint)m_nomVariables.size(); j>0; j-- ) - { - str.Replace( toString( "C%d", j-1 ).c_str(), params[j-1].c_str() ); - } - - try - { - m_luaState.executeScript( str.GetBuffer( str.GetLength() ) ); - } - catch (ELuaError &e) - { - MessageBox( toString( "%s", e.luaWhat().c_str() ).c_str() ); - return; - } - - - m_luaState.push("VAL"); - m_luaState.getTable(LUA_GLOBALSINDEX); - bool ok= false; - sint type= m_luaState.type(); - - if ( type == LUA_TBOOLEAN ) - { - // get and pop - bool val= m_luaState.toBoolean(); - m_luaState.pop(); - // set result - if ( val ) - str = "TRUE"; - else - str = "FALSE"; - ok = true; - } - else if ( type == LUA_TNUMBER ) - { - // get and pop - double val= m_luaState.toNumber(); - m_luaState.pop(); - // set double or integer? - if ( val == floor( val ) ) - str.Format( "%d", sint64( floor( val ) ) ); - else - str.Format( "%.3f", val ); - ok = true; - } - else if ( type == LUA_TSTRING ) - { - // get and pop - std::string val; - m_luaState.toString(-1, val); - m_luaState.pop(); - // set result - str = val.c_str(); - ok = true; - } - - if ( !ok ) - { - MessageBox( toString( "VAL is not defined on column %d", colonne ).c_str() ); - } - else - { - params[colonne] = str; - if ( colonne+1 == m_variables.size() ) - { - ParseTemplate( params ); - } - else - { - BuildParseParameters( params, ligne, colonne+1 ); - } - } - } - else - { - for ( uint i=0; i= params.capacity() ) - params.push_back( "" ); - - CString str; - - str = m_variables[colonne][i].c_str(); - - params[colonne] = str; - - if ( colonne+1 == m_variables.size() ) - { - ParseTemplate( params ); - } - else - { - BuildParseParameters( params, i, colonne+1 ); - } - } - } -} - - -void CVariableParserDlg::ParseTemplate( const ParseParameters& params ) -{ - CString tmp = m_templateText.c_str(); - - for ( uint i=0; i< m_nomVariables.size(); i++ ) - { - CSString toFind; - if ( CSString( m_nomVariables[ i ] ).left(2) == "@@" ) - { - toFind = toString( "%s", m_nomVariables[i].c_str() ); - } - else if ( CSString( m_nomVariables[ i ] ).left(2) == "##" ) - { - toFind = toString( "%s", m_nomVariables[i].c_str() ); - } - else - toFind = toString( "$$%s", m_nomVariables[i].c_str() ); - - tmp.Replace( toFind.c_str(), params[i].c_str() ); - } - - m_outputText += tmp; -} - -void CVariableParserDlg::OnGenerate() -{ - CString error = ""; - - CSString hdr, foot; - CString hdrFilename, templFileName, footFileName, - outputFileName, luaFileName; - - - GetDlgItem( IDC_HDR_FILE )->GetWindowText( hdrFilename ); - if ( hdrFilename == "" ) - error += "Header file name not set.\n"; - - GetDlgItem( IDC_FOOT_FILE )->GetWindowText( footFileName ); - if ( footFileName == "" ) - error += "Foot file name not set.\n"; - - GetDlgItem( IDC_TMPL_FILE )->GetWindowText( templFileName ); - if ( templFileName == "" ) - error += "Template file name not set.\n"; - - if ( m_varDefList.GetCount() == 0 ) - error += "Generator file name not set.\n"; - - GetDlgItem( IDC_OUTPUT_FILE )->GetWindowText( outputFileName ); - if ( outputFileName == "" ) - error += "Output file name not set."; - - if ( error != "" ) - { - MessageBox( error, NULL, MB_OK ); - } - else - { - GetDlgItem( IDC_LUA_FILE )->GetWindowText( luaFileName ); - if ( luaFileName != "" ) - { - m_luaState.executeFile( std::string( luaFileName ) ); - } - - hdr.readFromFile( std::string( hdrFilename ) ); - foot.readFromFile( std::string( footFileName ) ); - m_templateText.readFromFile( std::string( templFileName ) ); - - m_outputText = hdr; - for ( int i=0; i +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// VariableParserDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "variable_parser.h" +#include "variable_parserDlg.h" + +/*#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif*/ + +using namespace NLMISC; +using namespace std; + +///////////////////////////////////////////////////////////////////////////// +// CVariableParserDlg dialog + +CVariableParserDlg::CVariableParserDlg(CWnd* pParent /*=NULL*/) + : CDialog(CVariableParserDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CVariableParserDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +CVariableParserDlg::~CVariableParserDlg() +{ + m_nomVariables.clear(); + for ( uint i=0; iSetWindowText( fileDlg.GetPathName() ); + } +} + + +void CVariableParserDlg::OnTmplBrowse() +{ + CFileDialog fileDlg( TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, "Primitive file (*.primitive)|*.primitive||"); + + if ( fileDlg.DoModal() == IDOK ) + { + GetDlgItem( IDC_TMPL_FILE )->SetWindowText( fileDlg.GetPathName() ); + } +} + + +void CVariableParserDlg::OnFootBrowse() +{ + CFileDialog fileDlg( TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, "Primitive file (*.primitive)|*.primitive||"); + + if ( fileDlg.DoModal() == IDOK ) + { + GetDlgItem( IDC_FOOT_FILE )->SetWindowText( fileDlg.GetPathName() ); + } +} + + +void CVariableParserDlg::OnOutputBrowse() +{ + CFileDialog fileDlg( FALSE, NULL, NULL, OFN_OVERWRITEPROMPT, "Primitive file (*.primitive)|*.primitive||"); + + if ( fileDlg.DoModal() == IDOK ) + { + GetDlgItem( IDC_OUTPUT_FILE )->SetWindowText( fileDlg.GetPathName() ); + } +} + + +void CVariableParserDlg::OnGenBrowse() +{ + CFileDialog fileDlg( TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, "Comma Separated Values (*.csv)|*.csv||"); + + if ( fileDlg.DoModal() == IDOK ) + { + GetDlgItem( IDC_GEN_FILE )->SetWindowText( fileDlg.GetPathName() ); + } +} + +void CVariableParserDlg::OnLUABrowse() +{ + CFileDialog fileDlg( TRUE, NULL, NULL, OFN_OVERWRITEPROMPT, "Lua files (*.lua)|*.lua||"); + + if ( fileDlg.DoModal() == IDOK ) + { + GetDlgItem( IDC_LUA_FILE )->SetWindowText( fileDlg.GetPathName() ); + } +} + +void CleanString( CSString &str ) +{ + int i = (int)str.size(); + bool ok = false; + + while ( !ok && ( i > 0 ) ) + { + char c = str.c_str()[i-1]; + if ( !isalpha(c) && !isdigit(c) && ( c != '_' ) && ( c != ')' ) ) + { + i--; + } + else + ok = true; + } + + str = str.left( i ); +} + +void CVariableParserDlg::ProcessGeneratorFile( const string& generatorFile ) +{ + CSString genData, ligne; + int colonneVar = 0; + + genData.readFromFile( generatorFile ); + + ligne = genData.splitTo( "\n", true ); + + while ( ligne != "" ) + { + CSString var = ligne.splitTo( ";", true ); + CleanString( var ); + + if ( var != "" ) + { + m_nomVariables.push_back( var ) ; + vector vec; + m_variables.push_back( vec ); + } + } + + while ( genData != "" ) + { + ligne = genData.splitTo( "\n", true ); + + if ( ligne != "" ) + { + for ( uint i=0;i= params.capacity() ) + params.push_back( "" ); + + CString str = m_variables[colonne][ligne].c_str(); + params[colonne] = str; + + if ( colonne+1 == m_variables.size() ) + { + ParseTemplate( params ); + } + else + { + BuildParseParameters( params, ligne, colonne+1 ); + } + } + else if ( left == "##" ) + { + params.push_back( "" ); + CString str = m_variables[colonne][0].c_str(); + + for ( uint j=(uint)m_nomVariables.size(); j>0; j-- ) + { + str.Replace( toString( "C%d", j-1 ).c_str(), params[j-1].c_str() ); + } + + try + { + m_luaState.executeScript( str.GetBuffer( str.GetLength() ) ); + } + catch (ELuaError &e) + { + MessageBox( toString( "%s", e.luaWhat().c_str() ).c_str() ); + return; + } + + + m_luaState.push("VAL"); + m_luaState.getTable(LUA_GLOBALSINDEX); + bool ok= false; + sint type= m_luaState.type(); + + if ( type == LUA_TBOOLEAN ) + { + // get and pop + bool val= m_luaState.toBoolean(); + m_luaState.pop(); + // set result + if ( val ) + str = "TRUE"; + else + str = "FALSE"; + ok = true; + } + else if ( type == LUA_TNUMBER ) + { + // get and pop + double val= m_luaState.toNumber(); + m_luaState.pop(); + // set double or integer? + if ( val == floor( val ) ) + str.Format( "%d", sint64( floor( val ) ) ); + else + str.Format( "%.3f", val ); + ok = true; + } + else if ( type == LUA_TSTRING ) + { + // get and pop + std::string val; + m_luaState.toString(-1, val); + m_luaState.pop(); + // set result + str = val.c_str(); + ok = true; + } + + if ( !ok ) + { + MessageBox( toString( "VAL is not defined on column %d", colonne ).c_str() ); + } + else + { + params[colonne] = str; + if ( colonne+1 == m_variables.size() ) + { + ParseTemplate( params ); + } + else + { + BuildParseParameters( params, ligne, colonne+1 ); + } + } + } + else + { + for ( uint i=0; i= params.capacity() ) + params.push_back( "" ); + + CString str; + + str = m_variables[colonne][i].c_str(); + + params[colonne] = str; + + if ( colonne+1 == m_variables.size() ) + { + ParseTemplate( params ); + } + else + { + BuildParseParameters( params, i, colonne+1 ); + } + } + } +} + + +void CVariableParserDlg::ParseTemplate( const ParseParameters& params ) +{ + CString tmp = m_templateText.c_str(); + + for ( uint i=0; i< m_nomVariables.size(); i++ ) + { + CSString toFind; + if ( CSString( m_nomVariables[ i ] ).left(2) == "@@" ) + { + toFind = toString( "%s", m_nomVariables[i].c_str() ); + } + else if ( CSString( m_nomVariables[ i ] ).left(2) == "##" ) + { + toFind = toString( "%s", m_nomVariables[i].c_str() ); + } + else + toFind = toString( "$$%s", m_nomVariables[i].c_str() ); + + tmp.Replace( toFind.c_str(), params[i].c_str() ); + } + + m_outputText += tmp; +} + +void CVariableParserDlg::OnGenerate() +{ + CString error = ""; + + CSString hdr, foot; + CString hdrFilename, templFileName, footFileName, + outputFileName, luaFileName; + + + GetDlgItem( IDC_HDR_FILE )->GetWindowText( hdrFilename ); + if ( hdrFilename == "" ) + error += "Header file name not set.\n"; + + GetDlgItem( IDC_FOOT_FILE )->GetWindowText( footFileName ); + if ( footFileName == "" ) + error += "Foot file name not set.\n"; + + GetDlgItem( IDC_TMPL_FILE )->GetWindowText( templFileName ); + if ( templFileName == "" ) + error += "Template file name not set.\n"; + + if ( m_varDefList.GetCount() == 0 ) + error += "Generator file name not set.\n"; + + GetDlgItem( IDC_OUTPUT_FILE )->GetWindowText( outputFileName ); + if ( outputFileName == "" ) + error += "Output file name not set."; + + if ( error != "" ) + { + MessageBox( error, NULL, MB_OK ); + } + else + { + GetDlgItem( IDC_LUA_FILE )->GetWindowText( luaFileName ); + if ( luaFileName != "" ) + { + m_luaState.executeFile( std::string( luaFileName ) ); + } + + hdr.readFromFile( std::string( hdrFilename ) ); + foot.readFromFile( std::string( footFileName ) ); + m_templateText.readFromFile( std::string( templFileName ) ); + + m_outputText = hdr; + for ( int i=0; i -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// VariableParserDlg.h : header file -// - -#include "nel/misc/sstring.h" -#include "lua_helper.h" - -using namespace NLMISC; -using namespace std; - -#if !defined(AFX_VARIABLEPARSERDLG_H__65EA6C6E_3D9A_4929_944C_28D932505ECC__INCLUDED_) -#define AFX_VARIABLEPARSERDLG_H__65EA6C6E_3D9A_4929_944C_28D932505ECC__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - - - -typedef vector< string > ParseParameters; - - - -///////////////////////////////////////////////////////////////////////////// -// CVariableParserDlg dialog - -class CVariableParserDlg : public CDialog -{ -// Construction -public: - CVariableParserDlg(CWnd* pParent = NULL); // standard constructor - ~CVariableParserDlg(); - -// Dialog Data - //{{AFX_DATA(CVariableParserDlg) - enum { IDD = IDD_VARIABLEPARSER_DIALOG }; - CListBox m_varDefList; - //}}AFX_DATA - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CVariableParserDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - HICON m_hIcon; - - // Generated message map functions - //{{AFX_MSG(CVariableParserDlg) - virtual BOOL OnInitDialog(); - afx_msg void OnPaint(); - afx_msg HCURSOR OnQueryDragIcon(); - afx_msg void OnHdrBrowse(); - afx_msg void OnTmplBrowse(); - afx_msg void OnFootBrowse(); - afx_msg void OnOutputBrowse(); - afx_msg void OnGenerate(); - afx_msg void OnGenBrowse(); - afx_msg void OnLUABrowse(); - afx_msg void OnAddvardef(); - afx_msg void OnRemvardef(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - - - void ProcessGeneratorFile( const string& generatorFile ); - - void ParseTemplate( const ParseParameters& params ); - - void BuildParseParameters( ParseParameters& params, uint ligne, uint colonne ); - - - vector< string > m_nomVariables; - vector< vector< string > > m_variables; - - CSString m_templateText, m_outputText; - - CLuaState m_luaState; -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_VARIABLEPARSERDLG_H__65EA6C6E_3D9A_4929_944C_28D932505ECC__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// VariableParserDlg.h : header file +// + +#include "nel/misc/sstring.h" +#include "lua_helper.h" + +using namespace NLMISC; +using namespace std; + +#if !defined(AFX_VARIABLEPARSERDLG_H__65EA6C6E_3D9A_4929_944C_28D932505ECC__INCLUDED_) +#define AFX_VARIABLEPARSERDLG_H__65EA6C6E_3D9A_4929_944C_28D932505ECC__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + + +typedef vector< string > ParseParameters; + + + +///////////////////////////////////////////////////////////////////////////// +// CVariableParserDlg dialog + +class CVariableParserDlg : public CDialog +{ +// Construction +public: + CVariableParserDlg(CWnd* pParent = NULL); // standard constructor + ~CVariableParserDlg(); + +// Dialog Data + //{{AFX_DATA(CVariableParserDlg) + enum { IDD = IDD_VARIABLEPARSER_DIALOG }; + CListBox m_varDefList; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CVariableParserDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + HICON m_hIcon; + + // Generated message map functions + //{{AFX_MSG(CVariableParserDlg) + virtual BOOL OnInitDialog(); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnHdrBrowse(); + afx_msg void OnTmplBrowse(); + afx_msg void OnFootBrowse(); + afx_msg void OnOutputBrowse(); + afx_msg void OnGenerate(); + afx_msg void OnGenBrowse(); + afx_msg void OnLUABrowse(); + afx_msg void OnAddvardef(); + afx_msg void OnRemvardef(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + + void ProcessGeneratorFile( const string& generatorFile ); + + void ParseTemplate( const ParseParameters& params ); + + void BuildParseParameters( ParseParameters& params, uint ligne, uint colonne ); + + + vector< string > m_nomVariables; + vector< vector< string > > m_variables; + + CSString m_templateText, m_outputText; + + CLuaState m_luaState; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_VARIABLEPARSERDLG_H__65EA6C6E_3D9A_4929_944C_28D932505ECC__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/land_export/main.cpp b/code/ryzom/tools/leveldesign/world_editor/land_export/main.cpp index ab734e969..52c1dddc2 100644 --- a/code/ryzom/tools/leveldesign/world_editor/land_export/main.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/land_export/main.cpp @@ -1,307 +1,307 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include -#include - -#include "nel/misc/config_file.h" -#include "nel/misc/file.h" -#include "nel/misc/i_xml.h" - -#include "../land_export_lib/export.h" -#include "nel/ligo/zone_region.h" - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; - -// --------------------------------------------------------------------------- -// Out a string to the stdout and log.log -void outString (const string &sText) -{ - createDebug (); - InfoLog->displayRaw(sText.c_str()); - //printf ("%s", sText.c_str()); -} - -// --------------------------------------------------------------------------- -class CExportCB : public IExportCB -{ - int _PassProgress; - int _NiouLine; -public: - - bool isCanceled () - { - return false; // Never ending story - } - - // Display callbacks - - void dispPass (const std::string &Text) - { - /* string sTmp = string("PASS : ") + Text + "\n"; - outString (sTmp); */ - _PassProgress = 0; - _NiouLine = 0; - } - - void dispPassProgress (float percentage) - { - if (_PassProgress != (int)(percentage*100.0f)) - { - _PassProgress = (int)(percentage*100.0f); - string sTmp = toString(_PassProgress) + "."; - if ((_NiouLine++) == 20) - { - _NiouLine = 0; - sTmp += "\n"; - } - outString (sTmp); - fflush (stdout); - } - } - - void dispInfo (const std::string &Text) - { - /* string sTmp = string("INFO : ") + Text + "\n"; - outString (sTmp); */ - } - - void dispWarning (const std::string &Text) - { - string sTmp = string("WARNING : ") + Text + "\n"; - outString (sTmp); - } - - void dispError (const std::string &Text) - { - string sTmp = string("ERROR : ") + Text + "\n"; - outString (sTmp); - exit (-1); - } - -}; - -// --------------------------------------------------------------------------- -struct SOptions : public SExportOptions -{ - string ZoneRegionFile; - string FileName; - - CConfigFile cf; - - string getStr (const string &var) - { - string ret; - try - { - CConfigFile::CVar &cvString = cf.getVar (var); - ret = cvString.asString (); - } - catch (const EConfigFile &/*e*/) - { - outString (string("WARNING : variable not found : ") + var + " in " + FileName + "\n"); - } - return ret; - } - - float getFloat (const string &var) - { - float ret = 0.0; - try - { - CConfigFile::CVar &cvString = cf.getVar (var); - ret = cvString.asFloat (); - } - catch (const EConfigFile &/*e*/) - { - outString (string("WARNING : variable not found : ") + var + " in " + FileName + "\n"); - } - return ret; - } - - sint32 getInt (const string &var) - { - sint32 ret = 0; - try - { - CConfigFile::CVar &cvString = cf.getVar (var); - ret = cvString.asInt (); - } - catch (const EConfigFile &/*e*/) - { - outString (string("WARNING : variable not found : ") + var + " in " + FileName + "\n"); - } - return ret; - } - - bool loadFromCfg (const string &filename) - { - FileName = filename; - FILE * f = fopen (filename.c_str(), "rt"); - if (f == NULL) - return false; - else - fclose (f); - - - try - { - cf.load (filename); - this->OutZoneDir = getStr ("OutZoneDir"); - this->OutIGDir = getStr ("OutIGDir"); - this->RefZoneDir = getStr ("RefZoneDir"); - this->RefIGDir = getStr ("RefIGDir"); - this->LigoBankDir = getStr ("LigoBankDir"); - this->TileBankFile = getStr ("TileBankFile"); - this->ColorMapFile = getStr ("ColorMapFile"); - this->HeightMapFile = getStr ("HeightMapFile1"); - this->ZFactor = getFloat ("ZFactor1"); - this->HeightMapFile2 = getStr ("HeightMapFile2"); - this->ZFactor2 = getFloat ("ZFactor2"); - this->Light = (uint8)getInt ("ZoneLight"); - this->CellSize = getFloat ("CellSize"); - this->Threshold = getFloat ("Threshold"); - this->ZoneRegionFile = getStr ("ZoneRegionFile"); - this->ContinentFile = getStr("ContinentFile"); - this->RefCMBDir = getStr("RefCMBDir"); - this->OutCMBDir = getStr("OutCMBDir"); - this->AdditionnalIGInDir = getStr("AdditionnalIGInDir"); - this->AdditionnalIGOutDir = getStr("AdditionnalIGOutDir"); - this->ExportCollisions = getInt("ExportCollisions") != 0; - this->ExportAdditionnalIGs = getInt("ExportAdditionnalIGs") != 0; - this->DFNDir = getStr("DFNDir"); - this->ContinentsDir = getStr("ContinentsDir"); - } - catch (const EConfigFile &e) - { - string sTmp = string("ERROR : Error in config file : ") + e.what() + "\n"; - outString (sTmp); - return false; - } - return true; - } - - bool loadLand (const string &filename) - { - try - { - CIFile fileIn; - if (fileIn.open (filename)) - { - CIXml xml (true); - xml.init (fileIn); - ZoneRegion = new CZoneRegion; - ZoneRegion->serial (xml); - } - else - { - string sTmp = string("Can't open file : ") + filename; - outString (sTmp); - return false; - } - } - catch (const Exception& e) - { - string sTmp = string("Error in land file : ") + e.what(); - outString (sTmp); - return false; - } - return true; - } -}; - -// --------------------------------------------------------------------------- -int main (int argc, char**argv) -{ - new NLMISC::CApplicationContext; - // Filter addSearchPath - NLMISC::createDebug(); - InfoLog->addNegativeFilter ("addSearchPath"); - - // Verify the number of arguments - if (argc != 2) - { - printf ("Use : land_export configfile.cfg\n"); - printf ("\nExample of config.cfg\n\n"); - printf ("// Where to put all .zone generated\n"); - printf ("OutZoneDir = \"\";\n"); - printf ("// Where the reference zones are\n"); - printf ("RefZoneDir = \"\";\n"); - printf ("// Where the reference igs are\n"); - printf ("RefIGDir = \"\";\n"); - printf ("// Where to put all .ig generated\n"); - printf ("OutIGDir = \"\";\n"); - printf ("// Where all .ligozone are (those used by the .land)\n"); - printf ("LigoBankDir = \"\";\n"); - printf ("// The .bank file (used to know if a tile is oriented and the like)\n"); - printf ("TileBankFile = "";\n"); - printf ("// The grayscale tga file (127 is 0, 0 is -127*ZFactor and 255 is 128*ZFactor)\n"); - printf ("HeightMapFile1 = \"\";\n"); - printf ("// The heightmap factor\n"); - printf ("ZFactor1 = 1.0;\n"); - printf ("// The second grayscale tga file\n"); - printf ("HeightMapFile2 = \"\";\n"); - printf ("// The 2nd heightmap factor\n"); - printf ("ZFactor2 = 1.0;\n"); - printf ("// Roughly light the zone (0-none, 1-patch, 2-noise)\n"); - printf ("ZoneLight = 0;\n"); - printf ("// A cellsize (zonesize)\n"); - printf ("CellSize = 0.0;\n"); - printf ("// The .land to compute.\n"); - printf ("ZoneRegionFile = \"\";\n"); - printf ("// 0 if collisions should not be exported.\n"); - printf ("ExportCollisions = 0;\n"); - printf ("// 0 if additionnal igs should not be exported.\n"); - printf ("ExportAdditionnalIGs = 0;\n"); - printf ("// where the collision mesh builds are. They must match a village ig in the .continent that match the .land name.\n"); - printf ("RefCMBDir = \"\";\n"); - printf ("// where the collision mesh builds are put after being translated.\n"); - printf ("OutCMBDir = \"\";\n"); - printf ("// where the additionnal instance groups are. They must match a village ig in the .continent that match the .land name.\n"); - printf ("AdditionnalIGInDir = \"\";\n"); - printf ("// where the additionnal instance groups are put after being translated.\n"); - printf ("AdditionnalIGOutDir = \"\";\n"); - printf ("// where the dfn are located.\n"); - printf ("DFNDir = \"\";\n"); - printf("// the continent containing cmb and igs to export"); - printf ("ContinentFile = \"\";\n"); - printf("// search path for continents"); - printf ("ContinentsDir = \"\";\n"); - - - return -1; - } - - SOptions options; - CExportCB exportCB; - CExport exporter; - - string sTmp = toString("Loading cfg file : ") + argv[1] + "\n"; - outString (sTmp); - if (!options.loadFromCfg (argv[1])) - return -1; - - sTmp = string("Loading land file : ") + options.ZoneRegionFile + "\n"; - outString (sTmp); - if (!options.loadLand (options.ZoneRegionFile)) - return -1; - - exporter.export_ (options, &exportCB); - - return 1; +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include + +#include "nel/misc/config_file.h" +#include "nel/misc/file.h" +#include "nel/misc/i_xml.h" + +#include "../land_export_lib/export.h" +#include "nel/ligo/zone_region.h" + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; + +// --------------------------------------------------------------------------- +// Out a string to the stdout and log.log +void outString (const string &sText) +{ + createDebug (); + InfoLog->displayRaw(sText.c_str()); + //printf ("%s", sText.c_str()); +} + +// --------------------------------------------------------------------------- +class CExportCB : public IExportCB +{ + int _PassProgress; + int _NiouLine; +public: + + bool isCanceled () + { + return false; // Never ending story + } + + // Display callbacks + + void dispPass (const std::string &Text) + { + /* string sTmp = string("PASS : ") + Text + "\n"; + outString (sTmp); */ + _PassProgress = 0; + _NiouLine = 0; + } + + void dispPassProgress (float percentage) + { + if (_PassProgress != (int)(percentage*100.0f)) + { + _PassProgress = (int)(percentage*100.0f); + string sTmp = toString(_PassProgress) + "."; + if ((_NiouLine++) == 20) + { + _NiouLine = 0; + sTmp += "\n"; + } + outString (sTmp); + fflush (stdout); + } + } + + void dispInfo (const std::string &Text) + { + /* string sTmp = string("INFO : ") + Text + "\n"; + outString (sTmp); */ + } + + void dispWarning (const std::string &Text) + { + string sTmp = string("WARNING : ") + Text + "\n"; + outString (sTmp); + } + + void dispError (const std::string &Text) + { + string sTmp = string("ERROR : ") + Text + "\n"; + outString (sTmp); + exit (-1); + } + +}; + +// --------------------------------------------------------------------------- +struct SOptions : public SExportOptions +{ + string ZoneRegionFile; + string FileName; + + CConfigFile cf; + + string getStr (const string &var) + { + string ret; + try + { + CConfigFile::CVar &cvString = cf.getVar (var); + ret = cvString.asString (); + } + catch (const EConfigFile &/*e*/) + { + outString (string("WARNING : variable not found : ") + var + " in " + FileName + "\n"); + } + return ret; + } + + float getFloat (const string &var) + { + float ret = 0.0; + try + { + CConfigFile::CVar &cvString = cf.getVar (var); + ret = cvString.asFloat (); + } + catch (const EConfigFile &/*e*/) + { + outString (string("WARNING : variable not found : ") + var + " in " + FileName + "\n"); + } + return ret; + } + + sint32 getInt (const string &var) + { + sint32 ret = 0; + try + { + CConfigFile::CVar &cvString = cf.getVar (var); + ret = cvString.asInt (); + } + catch (const EConfigFile &/*e*/) + { + outString (string("WARNING : variable not found : ") + var + " in " + FileName + "\n"); + } + return ret; + } + + bool loadFromCfg (const string &filename) + { + FileName = filename; + FILE * f = fopen (filename.c_str(), "rt"); + if (f == NULL) + return false; + else + fclose (f); + + + try + { + cf.load (filename); + this->OutZoneDir = getStr ("OutZoneDir"); + this->OutIGDir = getStr ("OutIGDir"); + this->RefZoneDir = getStr ("RefZoneDir"); + this->RefIGDir = getStr ("RefIGDir"); + this->LigoBankDir = getStr ("LigoBankDir"); + this->TileBankFile = getStr ("TileBankFile"); + this->ColorMapFile = getStr ("ColorMapFile"); + this->HeightMapFile = getStr ("HeightMapFile1"); + this->ZFactor = getFloat ("ZFactor1"); + this->HeightMapFile2 = getStr ("HeightMapFile2"); + this->ZFactor2 = getFloat ("ZFactor2"); + this->Light = (uint8)getInt ("ZoneLight"); + this->CellSize = getFloat ("CellSize"); + this->Threshold = getFloat ("Threshold"); + this->ZoneRegionFile = getStr ("ZoneRegionFile"); + this->ContinentFile = getStr("ContinentFile"); + this->RefCMBDir = getStr("RefCMBDir"); + this->OutCMBDir = getStr("OutCMBDir"); + this->AdditionnalIGInDir = getStr("AdditionnalIGInDir"); + this->AdditionnalIGOutDir = getStr("AdditionnalIGOutDir"); + this->ExportCollisions = getInt("ExportCollisions") != 0; + this->ExportAdditionnalIGs = getInt("ExportAdditionnalIGs") != 0; + this->DFNDir = getStr("DFNDir"); + this->ContinentsDir = getStr("ContinentsDir"); + } + catch (const EConfigFile &e) + { + string sTmp = string("ERROR : Error in config file : ") + e.what() + "\n"; + outString (sTmp); + return false; + } + return true; + } + + bool loadLand (const string &filename) + { + try + { + CIFile fileIn; + if (fileIn.open (filename)) + { + CIXml xml (true); + xml.init (fileIn); + ZoneRegion = new CZoneRegion; + ZoneRegion->serial (xml); + } + else + { + string sTmp = string("Can't open file : ") + filename; + outString (sTmp); + return false; + } + } + catch (const Exception& e) + { + string sTmp = string("Error in land file : ") + e.what(); + outString (sTmp); + return false; + } + return true; + } +}; + +// --------------------------------------------------------------------------- +int main (int argc, char**argv) +{ + new NLMISC::CApplicationContext; + // Filter addSearchPath + NLMISC::createDebug(); + InfoLog->addNegativeFilter ("addSearchPath"); + + // Verify the number of arguments + if (argc != 2) + { + printf ("Use : land_export configfile.cfg\n"); + printf ("\nExample of config.cfg\n\n"); + printf ("// Where to put all .zone generated\n"); + printf ("OutZoneDir = \"\";\n"); + printf ("// Where the reference zones are\n"); + printf ("RefZoneDir = \"\";\n"); + printf ("// Where the reference igs are\n"); + printf ("RefIGDir = \"\";\n"); + printf ("// Where to put all .ig generated\n"); + printf ("OutIGDir = \"\";\n"); + printf ("// Where all .ligozone are (those used by the .land)\n"); + printf ("LigoBankDir = \"\";\n"); + printf ("// The .bank file (used to know if a tile is oriented and the like)\n"); + printf ("TileBankFile = "";\n"); + printf ("// The grayscale tga file (127 is 0, 0 is -127*ZFactor and 255 is 128*ZFactor)\n"); + printf ("HeightMapFile1 = \"\";\n"); + printf ("// The heightmap factor\n"); + printf ("ZFactor1 = 1.0;\n"); + printf ("// The second grayscale tga file\n"); + printf ("HeightMapFile2 = \"\";\n"); + printf ("// The 2nd heightmap factor\n"); + printf ("ZFactor2 = 1.0;\n"); + printf ("// Roughly light the zone (0-none, 1-patch, 2-noise)\n"); + printf ("ZoneLight = 0;\n"); + printf ("// A cellsize (zonesize)\n"); + printf ("CellSize = 0.0;\n"); + printf ("// The .land to compute.\n"); + printf ("ZoneRegionFile = \"\";\n"); + printf ("// 0 if collisions should not be exported.\n"); + printf ("ExportCollisions = 0;\n"); + printf ("// 0 if additionnal igs should not be exported.\n"); + printf ("ExportAdditionnalIGs = 0;\n"); + printf ("// where the collision mesh builds are. They must match a village ig in the .continent that match the .land name.\n"); + printf ("RefCMBDir = \"\";\n"); + printf ("// where the collision mesh builds are put after being translated.\n"); + printf ("OutCMBDir = \"\";\n"); + printf ("// where the additionnal instance groups are. They must match a village ig in the .continent that match the .land name.\n"); + printf ("AdditionnalIGInDir = \"\";\n"); + printf ("// where the additionnal instance groups are put after being translated.\n"); + printf ("AdditionnalIGOutDir = \"\";\n"); + printf ("// where the dfn are located.\n"); + printf ("DFNDir = \"\";\n"); + printf("// the continent containing cmb and igs to export"); + printf ("ContinentFile = \"\";\n"); + printf("// search path for continents"); + printf ("ContinentsDir = \"\";\n"); + + + return -1; + } + + SOptions options; + CExportCB exportCB; + CExport exporter; + + string sTmp = toString("Loading cfg file : ") + argv[1] + "\n"; + outString (sTmp); + if (!options.loadFromCfg (argv[1])) + return -1; + + sTmp = string("Loading land file : ") + options.ZoneRegionFile + "\n"; + outString (sTmp); + if (!options.loadLand (options.ZoneRegionFile)) + return -1; + + exporter.export_ (options, &exportCB); + + return 1; } \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/land_export_lib/export.cpp b/code/ryzom/tools/leveldesign/world_editor/land_export_lib/export.cpp index 00396226b..64e156909 100644 --- a/code/ryzom/tools/leveldesign/world_editor/land_export_lib/export.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/land_export_lib/export.cpp @@ -1,2899 +1,2899 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "export.h" - -#include "nel/misc/file.h" -#include "nel/misc/path.h" -#include "nel/misc/smart_ptr.h" - -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" -#include "nel/georges/u_form_loader.h" -#include "nel/misc/quat.h" - -#include "nel/3d/tile_bank.h" -#include "nel/3d/zone_lighter.h" -#include "nel/3d/zone_symmetrisation.h" -#include "nel/3d/landscape.h" -#include "nel/3d/scene_group.h" - -#include "nel/ligo/zone_region.h" -#include "nel/ligo/zone_bank.h" - -#include "nel/../../src/pacs/collision_mesh_build.h" - - -#include "../../../leveldesign/export/tools.h" - -#include - -#ifdef NL_OS_WINDOWS -# include -#endif // NL_OS_WINDOWS - -using namespace NL3D; -using namespace NLMISC; -using namespace NLLIGO; -using namespace NLGEORGES; -using namespace std; -using namespace NLPACS; - - - - - - - -// --------------------------------------------------------------------------- -// Export options -// --------------------------------------------------------------------------- - -// --------------------------------------------------------------------------- -SExportOptions::SExportOptions () -{ - ZoneRegion = NULL; - CellSize = 160.0f; - Threshold = 1.0f; - ZFactor = 1.0f; - ZFactor2 = 1.0f; - Light = false; - ExportCollisions = false; - ExportAdditionnalIGs = false; -} - -// --------------------------------------------------------------------------- -void SExportOptions::serial (NLMISC::IStream& s) -{ - int version = s.serialVersion (11); - - s.serial (OutZoneDir); - s.serial (RefZoneDir); - - if (version > 0) - s.serial (LigoBankDir); - - if (version > 1) - s.serial (TileBankFile); - - if (version > 2) - s.serial (HeightMapFile); - - if (version > 3) - s.serial (Light); - - if (version > 4) - { - s.serial (ZFactor); - s.serial (HeightMapFile2); - s.serial (ZFactor2); - } - - if (version > 5) - { - s.serial (ZoneMin); - s.serial (ZoneMax); - } - - if (version > 6) - { - s.serial (RefIGDir); - s.serial (OutIGDir); - } - - if (version > 7) - { - s.serial(ExportCollisions); - s.serial(RefCMBDir, OutCMBDir); - s.serial(AdditionnalIGInDir, AdditionnalIGOutDir); - s.serial(ContinentFile); - s.serial(DFNDir); - } - - if (version > 8) - { - s.serial(ExportAdditionnalIGs); - } - - if (version > 9) - { - s.serial(ContinentsDir); - } - - if (version > 10) - { - s.serial (ColorMapFile); - } -} - -// --------------------------------------------------------------------------- -// CExport -// --------------------------------------------------------------------------- - -// --------------------------------------------------------------------------- -CExport::CExport () -{ - _ZeZoneBank = NULL; - _FormLoader = UFormLoader::createLoader (); -} - -// --------------------------------------------------------------------------- -CExport::~CExport () -{ - UFormLoader::releaseLoader (_FormLoader); -} - -// --------------------------------------------------------------------------- -bool CExport::export_ (SExportOptions &options, IExportCB *expCB) -{ - string sCurDir = CTools::pwd(); - - _Options = &options; - _ExportCB = expCB; - - if (_Options->ZoneRegion == NULL) - { - if (_ExportCB != NULL) - _ExportCB->dispError ("No Zone to export"); - return false; - } - - // LOADING - // --- continent form - CPath::addSearchPath(_Options->DFNDir, true, false); - CPath::addSearchPath(_Options->RefCMBDir, true, false); - CPath::addSearchPath(_Options->ContinentsDir, true, false); - CPath::addSearchPath(_Options->AdditionnalIGInDir, true, false); - - // --- ligozone - if (_ExportCB != NULL) - _ExportCB->dispPass ("Loading ligozone bank"); - _ZeZoneBank = new CZoneBank; - string error; - _ZeZoneBank->initFromPath (_Options->LigoBankDir, error); - - // --- tile - if (_ExportCB != NULL) - _ExportCB->dispPass ("Loading tile bank"); - _ZeTileBank = new CTileBank; - try - { - CIFile inFile (_Options->TileBankFile); - _ZeTileBank->serial (inFile); - } - catch (const Exception &) - { - if (_ExportCB != NULL) - _ExportCB->dispError (string("Cant load tile bank : ") + _Options->TileBankFile); - return false; - } - - // --- height map - if (_ExportCB != NULL) - _ExportCB->dispPass ("Loading height map"); - _HeightMap = NULL; - if (_Options->HeightMapFile != "") - { - _HeightMap = new CBitmap; - try - { - CIFile inFile; - if (inFile.open (_Options->HeightMapFile)) - { - _HeightMap->load (inFile); - } - else - { - if (_ExportCB != NULL) - _ExportCB->dispWarning (string("Cant load height map : ") + _Options->HeightMapFile); - delete _HeightMap; - _HeightMap = NULL; - } - } - catch (const Exception &) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning (string("Cant load height map : ") + _Options->HeightMapFile); - delete _HeightMap; - _HeightMap = NULL; - } - } - - // --- height map 2 - if (_ExportCB != NULL) - _ExportCB->dispPass ("Loading height map"); - _HeightMap2 = NULL; - if (_Options->HeightMapFile2 != "") - { - _HeightMap2 = new CBitmap; - try - { - CIFile inFile; - if (inFile.open (_Options->HeightMapFile2)) - { - _HeightMap2->load (inFile); - } - else - { - if (_ExportCB != NULL) - _ExportCB->dispWarning (string("ERROR: Cant load height map : ") + _Options->HeightMapFile2); - delete _HeightMap2; - _HeightMap2 = NULL; - } - } - catch (const Exception &) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning (string("ERROR: Cant load height map : ") + _Options->HeightMapFile2); - delete _HeightMap2; - _HeightMap2 = NULL; - } - } - - // --- color map - if (_ExportCB != NULL) - _ExportCB->dispPass ("Loading color map"); - _ColorMap = NULL; - if (_Options->ColorMapFile != "") - { - _ColorMap = new CBitmap; - try - { - CIFile inFile; - if (inFile.open (_Options->ColorMapFile)) - { - _ColorMap->load (inFile); - } - else - { - if (_ExportCB != NULL) - _ExportCB->dispWarning (string("ERROR: Cant load color map : ") + _Options->ColorMapFile); - delete _ColorMap; - _ColorMap = NULL; - } - } - catch (const Exception &) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning (string("ERROR: Cant load color map : ") + _Options->ColorMapFile); - delete _ColorMap; - _ColorMap = NULL; - } - } - - // **************** - // *EXPORTING CODE* - // **************** - - if (_ExportCB != NULL) - _ExportCB->dispPass ("Exporting"); - - // Clip the min max to the x[0,255],y[0,-255] values - sint32 nMinX = _Options->ZoneRegion->getMinX() < 0 ? 0 : _Options->ZoneRegion->getMinX(); - sint32 nMaxX = _Options->ZoneRegion->getMaxX() > 255 ? 255 : _Options->ZoneRegion->getMaxX(); - sint32 nMinY = _Options->ZoneRegion->getMinY() > 0 ? 0 : _Options->ZoneRegion->getMinY(); - sint32 nMaxY = _Options->ZoneRegion->getMaxY() < -255 ? -255 : _Options->ZoneRegion->getMaxY(); - - - vector allFiles; - - // Delete zones that are not in the bounding square - try - { - // Add zone files - if (_Options->OutZoneDir != "") - NLMISC::CPath::getPathContent(_Options->OutZoneDir, true, false, true, allFiles); - - // Add ig files - vector allOtherFiles; - if (_Options->OutIGDir != "") - NLMISC::CPath::getPathContent(_Options->OutIGDir, true, false, true, allOtherFiles); - allFiles.insert(allFiles.end(), allOtherFiles.begin(), allOtherFiles.end()); - } - catch (const Exception &e) - { - if (_ExportCB != NULL) - _ExportCB->dispError (string("GetPathcontent failed : ") + e.what()); - return false; - } - - // zones - - - - for (uint32 nFile = 0; nFile < allFiles.size(); ++nFile) - { - string fileExt = NLMISC::CFile::getExtension(allFiles[nFile]); - string fileName = NLMISC::CFile::getFilename(allFiles[nFile]); - - if (fileExt != "ig" && fileExt != "zone" && fileExt != "zonel" && fileExt != "zonenh" ) continue; - sint32 x = getXFromZoneName (fileName); - sint32 y = getYFromZoneName (fileName); - if ((x>=0) && (y<=0)) - { - bool bMustDelete = false; - // Valid file - if ((xnMaxX) || (ynMaxY)) - { - bMustDelete = true; - } - else - { - const string &SrcZoneName = _Options->ZoneRegion->getName (x, y); - - if ((SrcZoneName == STRING_OUT_OF_BOUND) || (SrcZoneName == STRING_UNUSED)) - { - bMustDelete = true; - } - } - - if (bMustDelete) - { - if (!CFile::deleteFile (allFiles[nFile])) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning (string("Can't delete ") + fileName); - } - else - { - if (_ExportCB != NULL) - _ExportCB->dispInfo (string("Deleted ") + fileName); - } - } - } - } - - - - CTools::chdir (sCurDir); - - // Get the export limiters if any - _ZoneMinX = nMinX; - _ZoneMinY = nMinY; - _ZoneMaxX = nMaxX; - _ZoneMaxY = nMaxY; - - if ((_Options->ZoneMin != "") && (_Options->ZoneMax != "")) - { - _Options->ZoneMin = strupr (_Options->ZoneMin); - _Options->ZoneMax = strupr (_Options->ZoneMax); - sint32 nNewMinX = getXFromZoneName (_Options->ZoneMin); - sint32 nNewMinY = getYFromZoneName (_Options->ZoneMin); - sint32 nNewMaxX = getXFromZoneName (_Options->ZoneMax); - sint32 nNewMaxY = getYFromZoneName (_Options->ZoneMax); - - if (nNewMinX > nNewMaxX) - swap (nNewMinX, nNewMaxX); - if (nNewMinY > nNewMaxY) - swap (nNewMinY, nNewMaxY); - - if (nNewMinX > nMinX) - nMinX = nNewMinX; - if (nNewMinY > nMinY) - nMinY = nNewMinY; - - if (nNewMaxX < nMaxX) - nMaxX = nNewMaxX; - if (nNewMaxY < nMaxY) - nMaxY = nNewMaxY; - } - - sint32 nTotalFile = (1 + nMaxY - nMinY) * (1 + nMaxX - nMinX); - sint32 nCurrentFile = 0; - - vector ZoneTreated; - ZoneTreated.resize(nTotalFile, false); - - for (sint32 j = nMinY; j <= nMaxY; ++j) - { - for (sint32 i = nMinX; i <= nMaxX; ++i) - if (!ZoneTreated[i-nMinX+(j-nMinY)*(1+nMaxX-nMinX)]) - { - ++nCurrentFile; - if (_ExportCB != NULL) - _ExportCB->dispPassProgress(((float)nCurrentFile)/((float)nTotalFile)); - - const string &SrcZoneName = _Options->ZoneRegion->getName(i,j); - - if ((SrcZoneName == STRING_OUT_OF_BOUND) || - (SrcZoneName == STRING_UNUSED)) - continue; - - treatPattern (i, j, ZoneTreated, nMinX, nMinY, 1+nMaxX-nMinX); - - if ((_ExportCB != NULL) && (_ExportCB->isCanceled())) - break; - } - if ((_ExportCB != NULL) && (_ExportCB->isCanceled())) - break; - } - - exportCMBAndAdditionnalIGs(); - - - - if (_ExportCB != NULL) - _ExportCB->dispPass ("Finished"); - delete _ZeZoneBank; - delete _ZeTileBank; - - return true; -} - -// --------------------------------------------------------------------------- -void CExport::treatPattern (sint32 x, sint32 y, - vector &ZoneTreated, sint32 nMinX, sint32 nMinY, sint32 nStride) -{ - - CZoneRegion *pZR = _Options->ZoneRegion; - const string &rSZone = pZR->getName (x, y); - CZoneBankElement *pZBE = _ZeZoneBank->getElementByZoneName (rSZone); - - if (pZBE == NULL) - return; - - sint32 sizeX = pZBE->getSizeX(), sizeY = pZBE->getSizeY(); - sint32 posX = pZR->getPosX (x, y), posY = pZR->getPosY (x, y); - uint8 rot = pZR->getRot (x, y); - uint8 flip = pZR->getFlip (x, y); - sint32 i, j; - sint32 deltaX, deltaY; - - if (flip == 0) - { - switch (rot) - { - case 0: deltaX = -posX; deltaY = -posY; break; - case 1: deltaX = -(sizeY-1-posY); deltaY = -posX; break; - case 2: deltaX = -(sizeX-1-posX); deltaY = -(sizeY-1-posY); break; - case 3: deltaX = -posY; deltaY = -(sizeX-1-posX); break; - } - } - else - { - switch (rot) - { - case 0: deltaX = -(sizeX-1-posX); deltaY = -posY; break; - case 1: deltaX = -(sizeY-1-posY); deltaY = -(sizeX-1-posX); break; - case 2: deltaX = -posX; deltaY = -(sizeY-1-posY); break; - case 3: deltaX = -posY; deltaY = -posX; break; - } - } - - SPiece sMask; - sMask.Tab.resize (sizeX*sizeY); - for(i = 0; i < sizeX*sizeY; ++i) - sMask.Tab[i] = pZBE->getMask()[i]; - sMask.w = sizeX; - sMask.h = sizeY; - sMask.rotFlip (rot, flip); - - // Check if we have to export the zones - bool bHaveToExportZone = false; - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - // If date of the piece is newer than date of the final zones - string finalZoneName = _Options->OutZoneDir + string("\\") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + string(".zonel"); - if (!CTools::fileExist(finalZoneName)) - { - finalZoneName = _Options->OutZoneDir + string("\\") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + string(".zone"); - if (!CTools::fileExist(finalZoneName)) - { - bHaveToExportZone = true; // A file do not exist -> export it - - if (_ExportCB != NULL) - _ExportCB->dispInfo (string("finalZone do not exist")); - - - continue; - } - } - string refZoneName = _Options->RefZoneDir + string("\\") + rSZone + string(".zone"); - - if (!CTools::fileExist(refZoneName)) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning(string("RefZone do not exist.") + refZoneName); - return; - } - - if (CTools::fileDateCmp(refZoneName, finalZoneName) > 0) - { - bHaveToExportZone = true; - - if (_ExportCB != NULL) - _ExportCB->dispInfo (string("RefZone newer than finalZone.")); - - break; - } - // Or if the date of the cell is newer than the date of the final zone - uint32 cellDateLow = pZR->getDate(x+deltaX+i, y+deltaY+j, 0); - uint32 cellDateHigh = pZR->getDate(x+deltaX+i, y+deltaY+j, 1); - - if (CTools::fileDateCmp(finalZoneName, cellDateLow, cellDateHigh) < 0) - { - bHaveToExportZone = true; - - if (_ExportCB != NULL) - _ExportCB->dispInfo (string("Cell date newer")); - - break; - } - } - - // Check if we have to export the igs - bool bHaveToExportIG = false; - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - // If date of the piece is newer than date of the final zones - string finalIGName = _Options->OutIGDir + string("\\") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + string(".ig"); - if (!CTools::fileExist(finalIGName)) - { - finalIGName = _Options->OutIGDir + string("\\") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + string(".ig"); - if (!CTools::fileExist(finalIGName)) - { - bHaveToExportIG = true; // A file do not exist -> export it - - if (_ExportCB != NULL) - _ExportCB->dispInfo (string("final instance group do not exist")); - - - continue; - } - } - string refIGName = _Options->RefIGDir + string("\\") + rSZone + string(".ig"); - - if (!CTools::fileExist(refIGName)) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning(string("RefIG do not exist.") + refIGName); - continue; - } - - if (CTools::fileDateCmp(refIGName, finalIGName) > 0) - { - bHaveToExportIG = true; - - if (_ExportCB != NULL) - _ExportCB->dispInfo (string("RefIG newer than finalIG.")); - - break; - } - // Or if the date of the cell is newer than the date of the final ig - uint32 cellDateLow = pZR->getDate(x+deltaX+i, y+deltaY+j, 0); - uint32 cellDateHigh = pZR->getDate(x+deltaX+i, y+deltaY+j, 1); - - if (CTools::fileDateCmp(finalIGName, cellDateLow, cellDateHigh) < 0) - { - bHaveToExportIG = true; - - if (_ExportCB != NULL) - _ExportCB->dispInfo (string("Cell date newer")); - - break; - } - } - - - if (bHaveToExportZone == false && bHaveToExportIG == false) - return; - - // Put the big zone at the right position - CZone BigZone; - - - // 1 - Load the zone and IG - string BigZoneFileName; - - if (bHaveToExportZone) - { - try - { - BigZoneFileName = _Options->RefZoneDir + string("\\") + rSZone + string(".zone"); - CIFile inFile ; - if (inFile.open(BigZoneFileName)) - { - BigZone.serial (inFile); - } - else - { - _ExportCB->dispWarning(string("reference zone " + BigZoneFileName + " does not exists, skipping.")); - bHaveToExportZone = false; - } - } - catch (const Exception &e) - { - if (_ExportCB != NULL) - { - _ExportCB->dispWarning (string("Cant load zone : ") + BigZoneFileName); - _ExportCB->dispWarning (string("Reason : ") + e.what()); - } - bHaveToExportZone = false; - } - } - - CInstanceGroup bigIG; - string bigIGFileName; - - if (bHaveToExportIG) - { - try - { - bigIGFileName = _Options->RefIGDir + string("\\") + rSZone + string(".ig"); - CIFile inFile; - if (inFile.open(bigIGFileName)) - { - bigIG.serial (inFile); - } - else - { - // _ExportCB->dispWarning(string("reference ig " + bigIGFileName + " does not exists, skipping.")); - bHaveToExportIG = false; - } - } - catch (const Exception &e) - { - if (_ExportCB != NULL) - { - _ExportCB->dispWarning (string("ERROR: Cant load ig : ") + bigIGFileName); - _ExportCB->dispWarning (string("ERROR: Reason : ") + e.what()); - } - bHaveToExportIG = false; - } - } - - // 1bis - Copy the zone as no heightmap - CZone BigZoneNoHeightmap = BigZone; - - // 2 - Transform zone / ig - // zone - if (bHaveToExportZone) - { - if (flip == 0) - { - switch (rot) - { - case 0: - transformZone (BigZone, x+deltaX, y+deltaY, rot, flip, true); - transformZone (BigZoneNoHeightmap, x+deltaX, y+deltaY, rot, flip, false); - break; - case 1: - transformZone (BigZone, x+deltaX+sizeY, y+deltaY, rot, flip, true); - transformZone (BigZoneNoHeightmap, x+deltaX+sizeY, y+deltaY, rot, flip, false); - break; - case 2: - transformZone (BigZone, x+deltaX+sizeX, y+deltaY+sizeY, rot, flip, true); - transformZone (BigZoneNoHeightmap, x+deltaX+sizeX, y+deltaY+sizeY, rot, flip, false); - break; - case 3: - transformZone (BigZone, x+deltaX, y+deltaY+sizeX, rot, flip, true); - transformZone (BigZoneNoHeightmap, x+deltaX, y+deltaY+sizeX, rot, flip, false); - break; - } - } - else - { - switch (rot) - { - case 0: - transformZone (BigZone, x+deltaX+sizeX, y+deltaY, rot, flip, true); - transformZone (BigZoneNoHeightmap, x+deltaX+sizeX, y+deltaY, rot, flip, false); - break; - case 1: - transformZone (BigZone, x+deltaX+sizeY, y+deltaY+sizeX, rot, flip, true); - transformZone (BigZoneNoHeightmap, x+deltaX+sizeY, y+deltaY+sizeX, rot, flip, false); - break; - case 2: - transformZone (BigZone, x+deltaX, y+deltaY+sizeY, rot, flip, true); - transformZone (BigZoneNoHeightmap, x+deltaX, y+deltaY+sizeY, rot, flip, false); - break; - case 3: - transformZone (BigZone, x+deltaX, y+deltaY, rot, flip, true); - transformZone (BigZoneNoHeightmap, x+deltaX, y+deltaY, rot, flip, false); - break; - } - } - } - - if (bHaveToExportIG) - { - if (flip == 0) - { - switch (rot) - { - case 0: - transformIG (bigIG, x+deltaX, y+deltaY, rot, flip); - break; - case 1: - transformIG (bigIG, x+deltaX+sizeY, y+deltaY, rot, flip); - break; - case 2: - transformIG (bigIG, x+deltaX+sizeX, y+deltaY+sizeY, rot, flip); - break; - case 3: - transformIG (bigIG, x+deltaX, y+deltaY+sizeX, rot, flip); - break; - } - } - else - { - switch (rot) - { - case 0: - transformIG (bigIG, x+deltaX+sizeX, y+deltaY, rot, flip); - break; - case 1: - transformIG (bigIG, x+deltaX+sizeY, y+deltaY+sizeX, rot, flip); - break; - case 2: - transformIG (bigIG, x+deltaX, y+deltaY+sizeY, rot, flip); - break; - case 3: - transformIG (bigIG, x+deltaX, y+deltaY, rot, flip); - break; - } - } - } - - // 3 - Add the global color map - addColorMap (BigZone); - - // 4 - Cut the big zone into a set of unit zones - - // - Build patch informations - - // Retrieve source patches - vector SrcPI; - vector BorderVertices; - BigZone.retrieve (SrcPI, BorderVertices); - vector SrcPINoHeightmap; - vector BorderVerticesNoHeightmap; - BigZoneNoHeightmap.retrieve (SrcPINoHeightmap, BorderVerticesNoHeightmap); - - // Resize bool array - vector PatchTransfered; // Is the patch n is transfered in a zoneUnit ? - PatchTransfered.resize (SrcPI.size(), false); - - // Patch bb - vector bb; - bb.resize (SrcPI.size()); - for (i = 0; i < (sint)SrcPI.size(); ++i) - { - CPatchInfo &rPI = SrcPI[i]; - - bb[i].setCenter (rPI.Patch.Vertices[0]); - - for (j = 0; j < 4; ++j) - bb[i].extend (rPI.Patch.Vertices[j]); - - for (j = 0; j < 4; ++j) - bb[i].extend (rPI.Patch.Interiors[j]); - - for (j = 0; j < 8; ++j) - bb[i].extend (rPI.Patch.Tangents[j]); - } - - bool first = true; - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - CZone UnitZone; - CZone UnitZoneLighted; - CZone UnitZoneNoHeightmap; - - CInstanceGroup unitIG; - - if (bHaveToExportZone) - { - // Put all the patches contained in the square ... in the unit zone - cutZone (BigZone, BigZoneNoHeightmap, UnitZone, UnitZoneNoHeightmap, x+deltaX+i, y+deltaY+j, PatchTransfered, bb, SrcPI, SrcPINoHeightmap, - sMask, BorderVertices, BorderVerticesNoHeightmap, x+deltaX, y+deltaY); - if (_Options->Light > 0) - light (UnitZoneLighted, UnitZone); - else - UnitZoneLighted = UnitZone; - } - - if (bHaveToExportIG) - { - // Put all the instances contained in the square ... in the unit zone - cutIG (bigIG, unitIG, x+deltaX+i, y+deltaY+j, sMask, first, x+deltaX, y+deltaY); - } - - if (bHaveToExportZone) - { - // Save the zone - string DstZoneFileName; - try - { - // Delete the .zone and .zonel file - DstZoneFileName = getZoneNameFromXY(x+deltaX+i, y+deltaY+j); - DstZoneFileName = _Options->OutZoneDir + string("/") + DstZoneFileName; - string sTmp = DstZoneFileName + string(".zone"); - CFile::deleteFile (sTmp); - DstZoneFileName = DstZoneFileName + string(".zonel"); - CFile::deleteFile (DstZoneFileName); - - // Delete the .zonenh file - string DstZoneNoHeightmapFileName = _Options->OutZoneDir + string("/") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + string(".zonenh"); - CFile::deleteFile (DstZoneNoHeightmapFileName); - - COFile outFile (DstZoneFileName); - UnitZoneLighted.serial (outFile); - if (_ExportCB != NULL) - _ExportCB->dispInfo (string("Writing ") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + ".zonel"); - - COFile outFileNH (DstZoneNoHeightmapFileName); - UnitZoneNoHeightmap.serial (outFileNH); - } - catch (const Exception &) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning (string("Cant write ") + DstZoneFileName); - } - } - - if (bHaveToExportIG) - { - // Save the ig - string dstIGFileName; - try - { - dstIGFileName = getZoneNameFromXY(x+deltaX+i, y+deltaY+j); - dstIGFileName = _Options->OutIGDir + string("/") + dstIGFileName + string(".ig"); - CFile::deleteFile (dstIGFileName); - COFile outFile (dstIGFileName); - unitIG.serial(outFile); - if (_ExportCB != NULL) - _ExportCB->dispInfo (string("Writing ") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + ".ig"); - } - catch (const Exception &) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning (string("Cant write ") + dstIGFileName); - } - } - - // Set the zone as unused to not treat it the next time - ZoneTreated[(x+deltaX+i)-nMinX + ((y+deltaY+j)-nMinY) * nStride] = true; - - if ((_ExportCB != NULL) && (_ExportCB->isCanceled())) - return; - - first = false; - } - -} - -// --------------------------------------------------------------------------- -// Tile conversion -int TransitionFlipLR[48] = -{ - 0, // 0 - 4, // 1 - 5, // 2 - 27, // 3 - 1, // 4 - 2, // 5 - 6, // 6 - 34, // 7 - 11, // 8 - 33, // 9 - 31, // 10 - 8, // 11 - 13, // 12 - 12, // 13 - 47, // 14 - 40, // 15 - 39, // 16 - 20, // 17 - 46, // 18 - 45, // 19 - 17, // 20 - 43, // 21 - 42, // 22 - 41, // 23 - 24, // 24 - 28, // 25 - 29, // 26 - 3, // 27 - 25, // 28 - 26, // 29 - 30, // 30 - 10, // 31 - 35, // 32 - 9, // 33 - 7, // 34 - 32, // 35 - 37, // 36 - 36, // 37 - 44, // 38 - 16, // 39 - 15, // 40 - 23, // 41 - 22, // 42 - 21, // 43 - 38, // 44 - 19, // 45 - 18, // 46 - 14 // 47 -}; - -int TransitionFlipUD[48] = -{ - 24, // 0 - 28, // 1 - 29, // 2 - 3, // 3 - 25, // 4 - 26, // 5 - 30, // 6 - 10, // 7 - 35, // 8 - 9, // 9 - 7, // 10 - 32, // 11 - 37, // 12 - 36, // 13 - 23, // 14 - 16, // 15 - 15, // 16 - 44, // 17 - 22, // 18 - 21, // 19 - 38, // 20 - 19, // 21 - 18, // 22 - 14, // 23 - 0, // 24 - 4, // 25 - 5, // 26 - 27, // 27 - 1, // 28 - 2, // 29 - 6, // 30 - 34, // 31 - 11, // 32 - 33, // 33 - 31, // 34 - 8, // 35 - 13, // 36 - 12, // 37 - 20, // 38 - 40, // 39 - 39, // 40 - 47, // 41 - 46, // 42 - 45, // 43 - 17, // 44 - 43, // 45 - 42, // 46 - 41 // 47 -}; - -int TransitionRotCCW[48] = -{ - 27, // 0 - 28, // 1 - 29, // 2 - 0, // 3 - 1, // 4 - 2, // 5 - 33, // 6 - 34, // 7 - 35, // 8 - 6, // 9 - 7, // 10 - 8, // 11 - 39, // 12 - 40, // 13 - 17, // 14 - 12, // 15 - 13, // 16 - 41, // 17 - 45, // 18 - 46, // 19 - 47, // 20 - 18, // 21 - 19, // 22 - 20, // 23 - 3, // 24 - 4, // 25 - 5, // 26 - 24, // 27 - 25, // 28 - 26, // 29 - 9, // 30 - 10, // 31 - 11, // 32 - 30, // 33 - 31, // 34 - 32, // 35 - 15, // 36 - 16, // 37 - 14, // 38 - 36, // 39 - 37, // 40 - 38, // 41 - 21, // 42 - 22, // 43 - 23, // 44 - 42, // 45 - 43, // 46 - 44 // 47 -}; - -// --------------------------------------------------------------------------- -// Come from rpo2nel.cpp -// --------------------------------------------------------------------------- -bool transformTile (const CTileBank &bank, uint &tile, uint &tileRotation, bool symmetry, uint rotate) -{ - // Tile exist ? - if ( (rotate!=0) || symmetry ) - { - if (tile < (uint)bank.getTileCount()) - { - // Get xref - int tileSet; - int number; - CTileBank::TTileType type; - - // Get tile xref - bank.getTileXRef ((int)tile, tileSet, number, type); - - // Transition ? - if (type == CTileBank::transition) - { - // Number should be ok - nlassert (number>=0); - nlassert (numbergetOrientedBorder (CTileSet::left, CTileSet::getEdgeType ((CTileSet::TTransition)number, CTileSet::left)), - pTileSet->getOrientedBorder (CTileSet::bottom, CTileSet::getEdgeType ((CTileSet::TTransition)number, CTileSet::bottom)), - pTileSet->getOrientedBorder (CTileSet::right, CTileSet::getEdgeType ((CTileSet::TTransition)number, CTileSet::right)), - pTileSet->getOrientedBorder (CTileSet::top, CTileSet::getEdgeType ((CTileSet::TTransition)number, CTileSet::top)) - }; - - // Symmetry ? - if (symmetry) - { - CTileSet::TFlagBorder tmp = oriented[(0)&3]; - oriented[(0)&3] = CTileSet::getInvertBorder (oriented[(2)&3]); - oriented[(2)&3] = CTileSet::getInvertBorder (tmp); - oriented[(1)&3] = CTileSet::getInvertBorder (oriented[(1)&3]); - oriented[(3)&3] = CTileSet::getInvertBorder (oriented[(3)&3]); - } - - // Rotation - CTileSet::TFlagBorder edges[4]; - edges[0] = pTileSet->getOrientedBorder (CTileSet::left, oriented[(0 + rotate )&3]); - edges[1] = pTileSet->getOrientedBorder (CTileSet::bottom, oriented[(1 + rotate )&3]); - edges[2] = pTileSet->getOrientedBorder (CTileSet::right, oriented[(2 + rotate )&3]); - edges[3] = pTileSet->getOrientedBorder (CTileSet::top, oriented[(3 + rotate )&3]); - - // Get the good tile number - CTileSet::TTransition transition = pTileSet->getTransitionTile (edges[3], edges[1], edges[0], edges[2]); - nlassert ((CTileSet::TTransition)transition != CTileSet::notfound); - tile = (uint)(pTileSet->getTransition (transition)->getTile ()); - } - - // Transform rotation - if (symmetry) - tileRotation = (4-tileRotation)&3; - tileRotation += rotate; - tileRotation &= 3; - } - else - return false; - } - - // Ok - return true; -} - -// --------------------------------------------------------------------------- -// Come from rpo2nel.cpp -// --------------------------------------------------------------------------- -void transform256Case (const CTileBank &bank, uint &case256, uint tileRotation, bool symmetry, uint rotate) -{ - // Tile exist ? - if ( (rotate!=0) || symmetry ) - { - // Remove its rotation - case256 += tileRotation; - case256 &= 3; - - // Symmetry ? - if (symmetry) - { - // Take the symmetry - uint symArray[4] = {3, 2, 1, 0}; - case256 = symArray[case256]; - } - - // Rotation ? - case256 -= rotate + tileRotation; - case256 &= 3; - } -} - -// --------------------------------------------------------------------------- - -void CExport::addColorMap (CZone &zeZone) -{ - // Colormap available ? - if (_ColorMap) - { - // Conversion nPosX,nPosY to Zone Coordinate ZoneX, ZoneY - vector PatchInfos; - vector BorderVertices; - - // Retrieve the zone - zeZone.retrieve (PatchInfos, BorderVertices); - - // Apply the Colormap to all tile color. - // -------- - uint i; - for (i = 0; i < PatchInfos.size(); ++i) - { - CPatchInfo &rPI = PatchInfos[i]; - - // Get size - uint sizeU = rPI.OrderS+1; - uint sizeV = rPI.OrderT+1; - - // For each color tiles - uint u, v; - for (v = 0; v < sizeV; v++) - for (u = 0; u < sizeU; u++) - { - // Compute the coordinate for this color tile - CVector pos = rPI.Patch.eval ((float)u/(float)(sizeU-1), (float)v/(float)(sizeV-1)); - - // Get the color - CRGBAF colorf = getColor (pos.x, pos.y); - clamp (colorf.R, 0.f, 255.f); - clamp (colorf.G, 0.f, 255.f); - clamp (colorf.B, 0.f, 255.f); - clamp (colorf.A, 0.f, 255.f); - CRGBA color = CRGBA ((uint8)colorf.R, (uint8)colorf.G, (uint8)colorf.B, (uint8)colorf.A); - - // Destination color - uint16 &dest = rPI.TileColors[u+v*(sizeU)].Color565; - - // Original color - CRGBA src; - src.set565 (dest); - - // Blend the original and new color - CRGBA tmp; - tmp.blendFromui (src, color, ((uint)color.A) * 256 / 255); - dest = tmp.get565 (); - } - } - - zeZone.build (zeZone.getZoneId (), PatchInfos, BorderVertices); - } -} - -// --------------------------------------------------------------------------- -void CExport::transformZone (CZone &zeZone, sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip, bool computeHeightmap) -{ - // Conversion nPosX,nPosY to Zone Coordinate ZoneX, ZoneY - uint32 i, j; - vector PatchInfos; - vector BorderVertices; - - sint32 nZoneX = nPosX; - sint32 nZoneY = -1 - nPosY; - uint16 nZoneId = nZoneX+(nZoneY*256); - - zeZone.retrieve (PatchInfos, BorderVertices); - - nlassert (BorderVertices.size() == 0); - - CMatrix Transfo; - Transfo.setRot (CQuat(CVector::K, (float)(nRot * Pi / 2.0f))); - Transfo.setPos (CVector(nPosX*_Options->CellSize, (nPosY)*_Options->CellSize, 0.0f)); - - if (nFlip != 0) - nFlip = 1; - - if (nFlip == 1) - Transfo.scale(CVector(-1.0f, 1.0f, 1.0f)); - - // Transform the Patchs, and apply HeightMap. - //============================= - - - // 0. Transfrom zone indexes - //======================= - { - CMatrix invTransfo = Transfo; - invTransfo.invert (); - - NL3D::CZoneSymmetrisation zoneSymmetry; - if (! CPatchInfo::transform (PatchInfos, zoneSymmetry, *_ZeTileBank, nFlip != 0, nRot, _Options->CellSize, _Options->Threshold, invTransfo) ) - { - std::string name = getZoneNameFromXY (nPosX, nPosY); - - // Can't transform the zone - nlwarning ("ERROR: can't transform zone %s with sym:%d rot:%d", name.c_str (), nFlip, nRot); - } - } - - // 1. Transfom ligo zone in world - //======================= - for (i = 0; i < PatchInfos.size(); ++i) - { - CPatchInfo &rPI = PatchInfos[i]; - - rPI.Patch.applyMatrix (Transfo); - } - - // Bkup the original patchs. - vector oldPatchInfos= PatchInfos; - - // 2. Apply the Heighmap to all vertices/tangents/interiors. - // -------- - for (i = 0; i < PatchInfos.size(); ++i) - { - CPatchInfo &rPI = PatchInfos[i]; - - if (computeHeightmap) - { - // Elevate the vertices. - CVector verticesBeforeHeightMap[4]; - for (j = 0; j < 4; ++j) - { - verticesBeforeHeightMap[j]= rPI.Patch.Vertices[j]; - rPI.Patch.Vertices[j].z += getHeight(rPI.Patch.Vertices[j].x, rPI.Patch.Vertices[j].y); - } - - // Interior and tangent are rotated to follow the heightmap normal, avoiding the "Stair Effect". - // Compute the matrix to apply to interiors and tangents. - CMatrix tgMatrix[4]; - for (j = 0; j < 4; ++j) - { - // compute the normal of the heightmap. - CVector hmapNormal= getHeightNormal(rPI.Patch.Vertices[j].x, rPI.Patch.Vertices[j].y); - - // Compute the rotation which transforms the original normal: (0,0,1), to this normal. - CAngleAxis angleAxis; - angleAxis.Axis= CVector::K ^ hmapNormal; - angleAxis.Angle= (float)asin(angleAxis.Axis.norm()); - angleAxis.Axis.normalize(); - - // build the matrix which transform the old tgt/interior to his newValue: - // newVertexPos+ rotate*(oldTgPos-oldVertexPos) - tgMatrix[j].identity(); - tgMatrix[j].translate(rPI.Patch.Vertices[j]); - tgMatrix[j].setRot( CQuat(angleAxis) ); - tgMatrix[j].translate(-verticesBeforeHeightMap[j]); - } - - // For all interior. - for (j = 0; j < 4; ++j) - rPI.Patch.Interiors[j]= tgMatrix[j] * rPI.Patch.Interiors[j]; - - // when j == 7 or 0 use vertex 0 for delta Z to ensure continuity of normals - // when j == 1 or 2 use vertex 1 - // when j == 3 or 4 use vertex 2 - // when j == 5 or 6 use vertex 3 - for (j = 0; j < 8; ++j) - { - // get the correct vertex - uint vertexId= ((j+1)/2)%4; - // apply the tgMatrix to the tangent - rPI.Patch.Tangents[j]= tgMatrix[vertexId] * rPI.Patch.Tangents[j]; - } - } - - for (j = 0; j < 4; ++j) - rPI.BindEdges[j].ZoneId = nZoneId; - } - - // 3. For all binds, reset the position of near vertices/tangents/interiors. Must do it at last - // -------- - bool bindVertexModified= true; - // Since this is a recursive problem (binded patchs may bind other patchs), do it unitl all vertices no more move :) - while(bindVertexModified) - { - bindVertexModified= false; - for (i = 0; i < PatchInfos.size(); ++i) - { - CPatchInfo &rPI = PatchInfos[i]; - - // For all edges - for (j = 0; j < 4; ++j) - { - uint numBinds= rPI.BindEdges[j].NPatchs; - // If this edge is binded on 2 or 4 patches. - if( numBinds==2 || numBinds==4 ) - { - // compute the 4 or 8 tangents along the edge (in CCW) - CVector subTangents[8]; - computeSubdividedTangents(numBinds, rPI.Patch, j, subTangents); - - - // For all vertex to bind: 1 or 3. - for(uint vb=0; vb PatchInfos; - vector BorderVertices; - - sint32 nZoneX = nPosX; - sint32 nZoneY = -1 - nPosY; - uint16 nZoneId = nZoneX+(nZoneY*256); - - zeZone.retrieve (PatchInfos, BorderVertices); - - nlassert (BorderVertices.size() == 0); - - CMatrix Transfo; - Transfo.setRot (CQuat(CVector::K, (float)(nRot * Pi / 2.0f))); - Transfo.setPos (CVector(nPosX*_Options->CellSize, (nPosY)*_Options->CellSize, 0.0f)); - - if (nFlip != 0) - nFlip = 1; - - if (nFlip == 1) - Transfo.scale(CVector(-1.0f, 1.0f, 1.0f)); - - // Transform the Patchs, and apply HeightMap. - //============================= - - // Bkup the original patchs. - vector oldPatchInfos= PatchInfos; - - - // 1. Apply the Heighmap to all vertices/tangents/interiors. - // -------- - for (i = 0; i < PatchInfos.size(); ++i) - { - CPatchInfo &rPI = PatchInfos[i]; - - rPI.Patch.applyMatrix (Transfo); - - // Elevate the vertices. - CVector verticesBeforeHeightMap[4]; - for (j = 0; j < 4; ++j) - { - verticesBeforeHeightMap[j]= rPI.Patch.Vertices[j]; - rPI.Patch.Vertices[j].z += getHeight(rPI.Patch.Vertices[j].x, rPI.Patch.Vertices[j].y); - } - - // Interior and tangent are rotated to follow the heightmap normal, avoiding the "Stair Effect". - // Compute the matrix to apply to interiors and tangents. - CMatrix tgMatrix[4]; - for (j = 0; j < 4; ++j) - { - // compute the normal of the heightmap. - CVector hmapNormal= getHeightNormal(rPI.Patch.Vertices[j].x, rPI.Patch.Vertices[j].y); - - // Compute the rotation which transforms the original normal: (0,0,1), to this normal. - CAngleAxis angleAxis; - angleAxis.Axis= CVector::K ^ hmapNormal; - angleAxis.Angle= (float)asin(angleAxis.Axis.norm()); - angleAxis.Axis.normalize(); - - // build the matrix which transform the old tgt/interior to his newValue: - // newVertexPos+ rotate*(oldTgPos-oldVertexPos) - tgMatrix[j].identity(); - tgMatrix[j].translate(rPI.Patch.Vertices[j]); - tgMatrix[j].setRot( CQuat(angleAxis) ); - tgMatrix[j].translate(-verticesBeforeHeightMap[j]); - } - - // For all interior. - for (j = 0; j < 4; ++j) - rPI.Patch.Interiors[j]= tgMatrix[j] * rPI.Patch.Interiors[j]; - - // when j == 7 or 0 use vertex 0 for delta Z to ensure continuity of normals - // when j == 1 or 2 use vertex 1 - // when j == 3 or 4 use vertex 2 - // when j == 5 or 6 use vertex 3 - for (j = 0; j < 8; ++j) - { - // get the correct vertex - uint vertexId= ((j+1)/2)%4; - // apply the tgMatrix to the tangent - rPI.Patch.Tangents[j]= tgMatrix[vertexId] * rPI.Patch.Tangents[j]; - } - - for (j = 0; j < 4; ++j) - rPI.BindEdges[j].ZoneId = nZoneId; - } - - - // 2. For all binds, reset the position of near vertices/tangents/interiors. Must do it at last - // -------- - bool bindVertexModified= true; - // Since this is a recursive problem (binded patchs may bind other patchs), do it unitl all vertices no more move :) - while(bindVertexModified) - { - bindVertexModified= false; - for (i = 0; i < PatchInfos.size(); ++i) - { - CPatchInfo &rPI = PatchInfos[i]; - - // For all edges - for (j = 0; j < 4; ++j) - { - uint numBinds= rPI.BindEdges[j].NPatchs; - // If this edge is binded on 2 or 4 patches. - if( numBinds==2 || numBinds==4 ) - { - // compute the 4 or 8 tangents along the edge (in CCW) - CVector subTangents[8]; - computeSubdividedTangents(numBinds, rPI.Patch, j, subTangents); - - - // For all vertex to bind: 1 or 3. - for(uint vb=0; vb D - swap(rPI.Patch.Vertices[1], rPI.Patch.Vertices[2]); // B <-> C - - swap(rPI.Patch.Tangents[0], rPI.Patch.Tangents[5]); // ab <-> dc - swap(rPI.Patch.Tangents[1], rPI.Patch.Tangents[4]); // ba <-> cd - swap(rPI.Patch.Tangents[2], rPI.Patch.Tangents[3]); // bc <-> cb - swap(rPI.Patch.Tangents[7], rPI.Patch.Tangents[6]); // ad <-> da - - swap(rPI.Patch.Interiors[0], rPI.Patch.Interiors[3]); // ia <-> id - swap(rPI.Patch.Interiors[1], rPI.Patch.Interiors[2]); // ib <-> ic - - // Flip the base vertice - swap(rPI.BaseVertices[0], rPI.BaseVertices[3]); - swap(rPI.BaseVertices[1], rPI.BaseVertices[2]); - - // Flip bind edge only AB and CD - swap(rPI.BindEdges[0], rPI.BindEdges[2]); - - // Flip bind edge content only if multiple bind - for (j = 0; j < 4; j++) - { - if (rPI.BindEdges[j].NPatchs == 2) - { - swap (rPI.BindEdges[j].Next[0], rPI.BindEdges[j].Next[1]); - swap (rPI.BindEdges[j].Edge[0], rPI.BindEdges[j].Edge[1]); - } - if (rPI.BindEdges[j].NPatchs == 4) - { - swap (rPI.BindEdges[j].Next[0], rPI.BindEdges[j].Next[3]); - swap (rPI.BindEdges[j].Next[1], rPI.BindEdges[j].Next[2]); - - swap (rPI.BindEdges[j].Edge[0], rPI.BindEdges[j].Edge[3]); - swap (rPI.BindEdges[j].Edge[1], rPI.BindEdges[j].Edge[2]); - } - } - - for (j = 0; j < 4; ++j) - { - uint32 nNbPatch = rPI.BindEdges[j].NPatchs == 5 ? 1 : rPI.BindEdges[j].NPatchs; - for (k = 0; k < nNbPatch; ++k) - { - if (rPI.BindEdges[j].Edge[k] == 0) - rPI.BindEdges[j].Edge[k] = 2; - else if (rPI.BindEdges[j].Edge[k] == 2) - rPI.BindEdges[j].Edge[k] = 0; - } - } - - // Tile switching - for (j = 0; j < (uint32)(rPI.OrderS/2); ++j) - { - for (k = 0; k < rPI.OrderT; ++k) - { - swap(rPI.Tiles[j+k*rPI.OrderS], rPI.Tiles[(rPI.OrderS-1-j)+k*rPI.OrderS]); - } - } - - for (j = 0; j < (uint32)((rPI.OrderS+1)/2); ++j) - { - for (k = 0; k < (uint32)(rPI.OrderT+1); ++k) - { - swap(rPI.TileColors [j+k*(rPI.OrderS+1)], rPI.TileColors[(rPI.OrderS-j)+k*(rPI.OrderS+1)]); - } - } - } - - // Extra code for Rotating the zone. - //============================= - - // Rotate all tile elements in CW (because zones are turned in CCW) - // If zone flipped rotate tile elements by 180° - set allnames; // Debug - for (i = 0; i < PatchInfos.size(); ++i) - { - CPatchInfo &rPI = PatchInfos[i]; - - for (j = 0; j < rPI.Tiles.size(); ++j) - { - - int tileID, tileSet; - unsigned int tileIDun; - CTileBank::TTileType type; - CTileSet *pTS; - unsigned int nbOfRot; - - // Is the tile is painted ? - if (rPI.Tiles[j].Tile[0] == 65535) - continue; - - // Rotate Tiles - // Invert rotation effect on transition - for (pass = 0; pass < 3; ++pass) - { - if (rPI.Tiles[j].Tile[pass] == NL_TILE_ELM_LAYER_EMPTY) - break; - uint8 ori = rPI.Tiles[j].getTileOrient (pass); - - // Invert rotation effect on transition - _ZeTileBank->getTileXRef(rPI.Tiles[j].Tile[pass], tileSet, tileID, type); - pTS = _ZeTileBank->getTileSet (tileSet); - tileIDun = rPI.Tiles[j].Tile[pass]; - nbOfRot = rPI.Tiles[j].getTileOrient (pass); - if (!pTS->getOriented()) - { - transformTile (*_ZeTileBank, tileIDun, nbOfRot, (nFlip == 1), (4-nRot)%4); - } - else - { - transformTile (*_ZeTileBank, tileIDun, nbOfRot, (nFlip == 1), 0); - } - rPI.Tiles[j].Tile[pass] = tileIDun; - // Rotate tile - rPI.Tiles[j].setTileOrient (pass, nbOfRot); - } - - bool is256x256; - uint8 uvOff; - rPI.Tiles[j].getTile256Info (is256x256, uvOff); - if (is256x256) - { - unsigned int unCase = uvOff; - transform256Case (*_ZeTileBank, unCase, 0, (nFlip == 1), (4-nRot)%4); - rPI.Tiles[j].setTile256Info (true, unCase); - } - } - } - - zeZone.build (nZoneId, PatchInfos, BorderVertices); -}*/ - -/* -CLandscape gLand; -bool gLandInited = false; -*/ - - -// --------------------------------------------------------------------------- -void CExport::buildTransfo(sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip, CMatrix &posTransfo, CQuat &rotTransfo) -{ - // we don't use a single matrix because we don't want to apply a mirror on meshs - rotTransfo = CQuat(CVector::K, (float)(nRot * Pi / 2.0f)); - - posTransfo.setRot(rotTransfo); - posTransfo.setPos(CVector(nPosX * _Options->CellSize, (nPosY) * _Options->CellSize, 0.0f)); - if (nFlip == 1) - posTransfo.scale(CVector(-1.0f, 1.0f, 1.0f)); -} - -// --------------------------------------------------------------------------- -void CExport::transformIG (CInstanceGroup &ig, sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip) -{ - uint k; - CQuat rotTransfo; - CMatrix transformation; - - buildTransfo(nPosX, nPosY, nRot, nFlip, transformation, rotTransfo); - - /////////////// - // instances // - /////////////// - - for (k = 0; k < ig.getNumInstance(); ++k) - { - /* CInstanceGroup::CInstance &igi = ig.getInstance(k); - igi.Pos = transformation * igi.Pos; - igi.Rot = rotTransfo * igi.Rot; */ - - // add height map influence - //igi.Pos.z += getHeight(igi.Pos.x, igi.Pos.y); - - // Instance - CInstanceGroup::CInstance &igi = ig.getInstance(k); - - // Get the previous instance matrix - CMatrix previousMt; - previousMt.identity (); - previousMt.setRot(igi.Rot); - previousMt.setPos(igi.Pos); - previousMt.scale(igi.Scale); - - // Compose the matrix - previousMt = transformation * previousMt; - - // Extract the rotation and pos - igi.Rot = previousMt.getRot (); - igi.Pos = previousMt.getPos (); - - // Extract the scale - CMatrix scaleMatrix; - scaleMatrix.identity (); - scaleMatrix.setRot (igi.Rot); - scaleMatrix.invert (); - scaleMatrix = scaleMatrix * previousMt; - igi.Scale.set (scaleMatrix.getI ().x, scaleMatrix.getJ ().y, scaleMatrix.getK ().z); - } - - ////////////////// - // point lights // - ////////////////// - - for (k = 0; k < ig.getNumPointLights(); ++k) - { - CPointLightNamed &plm = ig.getPointLightNamed(k); - plm.setPosition(transformation * plm.getPosition()); - - // add height map influence - // plm.setPosition(plm.getPosition() + CVector::K * getHeight(plm.getPosition().x, plm.getPosition().y)); - } - -} - - -// --------------------------------------------------------------------------- -void CExport::transformCMB (NLPACS::CCollisionMeshBuild &cmb,sint32 nPosX,sint32 nPosY,uint8 nRot,uint8 nFlip) -{ - CQuat rotTransfo; - CMatrix posTransfo; - buildTransfo(nPosX, nPosY, nRot, nFlip, posTransfo, rotTransfo); - for(std::vector::iterator it = cmb.Vertices.begin(); it != cmb.Vertices.end(); ++it) - { - *it = posTransfo * *it; - } -} - -// --------------------------------------------------------------------------- -void CExport::cutZone (NL3D::CZone &bigZone, NL3D::CZone &bigZoneNoHeightmap, NL3D::CZone &unitZone, NL3D::CZone &unitZoneNoHeightmap, - sint32 nPosX, sint32 nPosY, vector &PatchTransfered, const vector &bb, vector &SrcPI, - vector &SrcPINoHeightmap, SPiece &sMask, vector &BorderVertices, - vector &BorderVerticesNoHeightmap, sint32 baseX, sint32 baseY) -{ - string DstZoneFileName = getZoneNameFromXY (nPosX, nPosY); - - uint32 i, j, k, l, m; - vector DstPI; - vector DstPINoHeightmap; - - sint32 nZoneX = nPosX; - sint32 nZoneY = -1 - nPosY; - uint16 nZoneId = nZoneX+(nZoneY*256); - - float rMinX = nPosX * _Options->CellSize; - float rMaxX = (1+nPosX) * _Options->CellSize; - float rMinY = nPosY * _Options->CellSize; - float rMaxY = (1+nPosY) * _Options->CellSize; - - map OldToNewPatchId; // Used to convert old patch id to new patch id - - for (i = 0; i < SrcPI.size(); ++i) - if (!PatchTransfered[i]) // If patch not already transfered in a zone unit - { - CPatchInfo &rPI = SrcPI[i]; - CPatchInfo &rPINoHeightmap = SrcPINoHeightmap[i]; - - // Is the Patch contained in the current mask ? Center of bbox tested - if ((bb[i].getCenter().x >= rMinX)&&(bb[i].getCenter().x <= rMaxX)&& - (bb[i].getCenter().y >= rMinY)&&(bb[i].getCenter().y <= rMaxY)) - { - for (j = 0; j < 4; ++j) - { - rPI.BindEdges[j].ZoneId = nZoneId; - rPINoHeightmap.BindEdges[j].ZoneId = nZoneId; - } - - PatchTransfered[i] = true; - DstPI.push_back (rPI); - DstPINoHeightmap.push_back (rPINoHeightmap); - OldToNewPatchId.insert (pair(i, (int)DstPI.size()-1)); - } - } - - // Look for patches out of the mask attached to a patch in this zone - bool foundOne; - do - { - foundOne = false; - for (i = 0; i < SrcPI.size(); ++i) - { - // Not yet transfered ? - if (!PatchTransfered[i]) // If patch not already transfered in a zone unit - { - // Get the center of the zone - sint x = (sint)(floor(bb[i].getCenter().x / _Options->CellSize)) - baseX; - sint y = (sint)(floor(bb[i].getCenter().y / _Options->CellSize)) - baseY; - - // Not in the mask ? - bool inTheMask = (x>=0) && (x<(sint)sMask.w) && (y>=0) && (y<(sint)sMask.h); - if (!inTheMask || !sMask.Tab[x+y*sMask.w]) - { - // Attached to a patch in this zone ? - CPatchInfo &rPI = SrcPI[i]; - CPatchInfo &rPINoHeightmap = SrcPINoHeightmap[i]; - for (j = 0; j < 4; ++j) - { - // Binded ? - if (rPI.BindEdges[j].NPatchs) - { - // Number of others - uint otherCount = rPI.BindEdges[j].NPatchs; - if (rPI.BindEdges[j].NPatchs == 5) - otherCount = 1; - - // For each other patch - for (k=0; k(i, (int)DstPI.size()-1)); - foundOne = true; - break; - } - } - if (k(next, (int)DstPI.size()-1)); - PatchTransfered[next] = true; - } - } - - if ((DstPI[i].BindEdges[j].NPatchs == 2) || (DstPI[i].BindEdges[j].NPatchs == 4)) - { - for (k = 0; k < DstPI[i].BindEdges[j].NPatchs; ++k) - { - uint next = DstPI[i].BindEdges[j].Next[k]; - if (!PatchTransfered[next]) - { - CPatchInfo &rPITmp = SrcPI[next]; - CPatchInfo &rPITmpNoHeightmap = SrcPINoHeightmap[next]; - for (m = 0; m < 4; ++m) - { - rPITmp.BindEdges[m].ZoneId = nZoneId; - rPITmpNoHeightmap.BindEdges[m].ZoneId = nZoneId; - } - DstPI.push_back (rPITmp); - DstPINoHeightmap.push_back (rPITmpNoHeightmap); - OldToNewPatchId.insert (pair(next, (int)DstPI.size()-1)); - PatchTransfered[next] = true; - } - } - } - } - } - - // Do it until no more patch added - if (nPreviousDstPISize == DstPI.size()) - break; - nPreviousDstPISize = (uint32)DstPI.size(); - } - - for (i = 0; i < DstPI.size(); ++i) - { - CPatchInfo &rPI = DstPI[i]; - CPatchInfo &rPINoHeightmap = DstPINoHeightmap[i]; - for (j = 0; j < 4; ++j) - { - if ((rPI.BindEdges[j].NPatchs == 1) || (rPI.BindEdges[j].NPatchs == 5)) - { - map::iterator it = OldToNewPatchId.find (rPI.BindEdges[j].Next[0]); - if (it == OldToNewPatchId.end()) - { - if (rPI.BindEdges[j].NPatchs == 5) - { - if (_ExportCB != NULL) - _ExportCB->dispError (string("Continuity problem in zone ") + DstZoneFileName); - } - else - { - rPI.BindEdges[j].NPatchs = 0; - rPINoHeightmap.BindEdges[j].NPatchs = 0; - } - } - else - { - rPI.BindEdges[j].Next[0] = it->second; - rPINoHeightmap.BindEdges[j].Next[0] = it->second; - } - } - - if ((rPI.BindEdges[j].NPatchs == 2) || (rPI.BindEdges[j].NPatchs == 4)) - { - for (k = 0; k < rPI.BindEdges[j].NPatchs; ++k) - { - map::iterator it = OldToNewPatchId.find (rPI.BindEdges[j].Next[k]); - if (it == OldToNewPatchId.end()) - { - if (_ExportCB != NULL) - _ExportCB->dispError (string("Continuity problem in zone ") + DstZoneFileName); - } - else - { - rPI.BindEdges[j].Next[k] = it->second; - rPINoHeightmap.BindEdges[j].Next[k] = it->second; - } - } - } - } - } - - unitZone.build (nZoneId, DstPI, BorderVertices); - unitZoneNoHeightmap.build (nZoneId, DstPINoHeightmap, BorderVerticesNoHeightmap); -/* { // Debug - if (!gLandInited) - { - gLand.init(); - gLandInited = true; - } - - gLand.addZone(unitZone); - gLand.checkBinds(); - }*/ -} - - -// --------------------------------------------------------------------------- -void CExport::cutIG(CInstanceGroup &bigIG, CInstanceGroup &unitIG, sint32 nPosX, sint32 nPosY, SPiece &sMask, bool first, sint32 baseX, sint32 baseY) -{ - uint k; - string DstZoneFileName = getZoneNameFromXY (nPosX, nPosY); - - float rMinX = nPosX * _Options->CellSize; - float rMaxX = (1+nPosX) * _Options->CellSize; - float rMinY = nPosY * _Options->CellSize; - float rMaxY = (1+nPosY) * _Options->CellSize; - - CInstanceGroup::TInstanceArray instances; - std::vector portals; - std::vector clusters; - std::vector pointLightList; - - bool realTimeSuncontribution = bigIG.getRealTimeSunContribution(); - - /////////////// - // instances // - /////////////// - for (k = 0; k < bigIG.getNumInstance(); ++k) - { - CInstanceGroup::CInstance &igi = bigIG.getInstance(k); - const CVector &pos = igi.Pos; - if (pos.x >= rMinX && pos.x < rMaxX && pos.y >= rMinY && pos.y < rMaxY) - { - instances.push_back(igi); - } - - // First zone ? - if (first) - { - // Out of the mask ? - sint x = (sint)(floor(pos.x / _Options->CellSize)) - baseX; - sint y = (sint)(floor(pos.y / _Options->CellSize)) - baseY; - - // Not in the mask ? - bool inTheMask = (x>=0) && (x<(sint)sMask.w) && (y>=0) && (y<(sint)sMask.h); - if (!inTheMask || !sMask.Tab[x+y*sMask.w]) - { - instances.push_back(igi); - } - } - } - - //////////// - // lights // - //////////// - - const std::vector &lights = bigIG.getPointLightList(); - for (k = 0; k < lights.size(); ++k) - { - const CVector &pos = lights[k].getPosition(); - if (pos.x >= rMinX && pos.x < rMaxX && pos.y >= rMinY && pos.y < rMaxY) - { - pointLightList.push_back(lights[k]); - } - - // First zone ? - if (first) - { - // Out of the mask ? - sint x = (sint)(floor(pos.x / _Options->CellSize)) - baseX; - sint y = (sint)(floor(pos.y / _Options->CellSize)) - baseY; - - // Not in the mask ? - bool inTheMask = (x>=0) && (x<(sint)sMask.w) && (y>=0) && (y<(sint)sMask.h); - if (!inTheMask || !sMask.Tab[x+y*sMask.w]) - { - pointLightList.push_back(lights[k]); - } - } - } - - // build the resulting ig - unitIG.build(bigIG.getGlobalPos(), instances, portals, clusters, pointLightList); - unitIG.enableRealTimeSunContribution(realTimeSuncontribution); - -} - - -// --------------------------------------------------------------------------- -float CExport::getHeight (float x, float y) -{ - float deltaZ = 0.0f, deltaZ2 = 0.0f; - CRGBAF color; - sint32 SizeX = _ZoneMaxX - _ZoneMinX + 1; - sint32 SizeY = _ZoneMaxY - _ZoneMinY + 1; - - clamp (x, _Options->CellSize*_ZoneMinX, _Options->CellSize*(_ZoneMaxX+1)); - clamp (y, _Options->CellSize*_ZoneMinY, _Options->CellSize*(_ZoneMaxY+1)); - - if (_HeightMap != NULL) - { - color = _HeightMap->getColor ( (x-_Options->CellSize*_ZoneMinX)/(_Options->CellSize*SizeX), - 1.0f - ((y-_Options->CellSize*_ZoneMinY)/(_Options->CellSize*SizeY))); - color *= 255; - deltaZ = color.A; - deltaZ = deltaZ - 127.0f; // Median intensity is 127 - deltaZ *= _Options->ZFactor; - } - - if (_HeightMap2 != NULL) - { - color = _HeightMap2->getColor ( (x-_Options->CellSize*_ZoneMinX)/(_Options->CellSize*SizeX), - 1.0f - ((y-_Options->CellSize*_ZoneMinY)/(_Options->CellSize*SizeY))); - color *= 255; - deltaZ2 = color.A; - deltaZ2 = deltaZ2 - 127.0f; // Median intensity is 127 - deltaZ2 *= _Options->ZFactor2; - } - - return (deltaZ + deltaZ2); -} - -// --------------------------------------------------------------------------- -CRGBAF CExport::getColor (float x, float y) -{ - CRGBAF color = CRGBA::Black; - sint32 SizeX = _ZoneMaxX - _ZoneMinX + 1; - sint32 SizeY = _ZoneMaxY - _ZoneMinY + 1; - - clamp (x, _Options->CellSize*_ZoneMinX, _Options->CellSize*(_ZoneMaxX+1)); - clamp (y, _Options->CellSize*_ZoneMinY, _Options->CellSize*(_ZoneMaxY+1)); - - if (_ColorMap != NULL) - { - color = _ColorMap->getColor ( (x-_Options->CellSize*_ZoneMinX)/(_Options->CellSize*SizeX), - 1.0f - ((y-_Options->CellSize*_ZoneMinY)/(_Options->CellSize*SizeY))); - color *= 255; - } - - return color; -} - -// --------------------------------------------------------------------------- -void CExport::light (NL3D::CZone &zoneOut, NL3D::CZone &zoneIn) -{ - // Same as zone_lighter stand-alone exe - // ------------------------------------ - /* CZoneLighter zl; - CLandscape land; - CZoneLighter::CLightDesc ld; - vector obstacle; - vector listzone; - - ld.SkyContribution = false; - ld.Oversampling = CZoneLighter::CLightDesc::NoOverSampling; - ld.Shadow = false; - ld.Softshadow = false; - ld.NumCPU = 1; - ld.GridSize = 2; - - try - { - zl.init (); - land.init (); - land.TileBank = *_ZeTileBank; - land.initTileBanks(); - land.addZone (zoneIn); - - listzone.push_back(zoneIn.getZoneId()); - - zl.light (land, zoneOut, zoneIn.getZoneId(), ld, obstacle, listzone); - } - catch (const Exception &e) - { - if (_ExportCB != NULL) - _ExportCB->dispError (e.what()); - }*/ - - // Quickest version without noise - // ------------------------------ - - CLandscape land; - - land.init (); - land.TileBank = *_ZeTileBank; - land.initTileBanks(); - land.addZone (zoneIn); - - - vector vPI; - vector vBV; - uint32 i, j, k, m; - float s, t, val; - CVector n, l = CVector (1.0f, 1.0f, -1.0f); - vector vertices; - CVector v[4]; - - l.normalize(); - - CZone *dyn = land.getZone(zoneIn.getZoneId()); - uint32 numPatch = dyn->getNumPatchs(); - - zoneIn.retrieve (vPI, vBV); - - if (_Options->Light == 2) // Noise ? - for (i = 0; i < numPatch; ++i) - { - const CPatch *pCP = const_cast(dyn)->getPatch (i); - - CPatchInfo &rPI = vPI[i]; - vertices.resize((rPI.OrderT*4+1)*(rPI.OrderS*4+1)); - - for (k = 0; k < (uint32)(rPI.OrderT*4+1); ++k) - for (j = 0; j < (uint32)(rPI.OrderS*4+1); ++j) - { - s = (((float)j) / (rPI.OrderS*4)); - t = (((float)k) / (rPI.OrderT*4)); - vertices[j+k*(rPI.OrderS*4+1)] = pCP->computeVertex(s, t); - } - - for (k = 0; k < (uint32)(rPI.OrderT*4); ++k) - for (j = 0; j < (uint32)(rPI.OrderS*4); ++j) - { - v[0] = vertices[(j+0)+(k+0)*(rPI.OrderS*4+1)]; - v[1] = vertices[(j+1)+(k+0)*(rPI.OrderS*4+1)]; - v[2] = vertices[(j+1)+(k+1)*(rPI.OrderS*4+1)]; - v[3] = vertices[(j+0)+(k+1)*(rPI.OrderS*4+1)]; - - val = 0.0f; - for (m = 0; m < 4; ++m) - { - n = (v[(m+0)%4]-v[(m+2)%4])^(v[(m+0)%4]-v[(m+1)%4]); - n.normalize(); - val += 255.0f*(1.0f-n*l)/2.0f; - } - val = val / 4.0f; - clamp (val, 0.0f, 255.0f); - rPI.Lumels[j+k*rPI.OrderS*4] = (uint8)(val); - } - } - else // No noise - for (i = 0; i < numPatch; ++i) - { - const CPatch *pCP = const_cast(dyn)->getPatch (i); - CBezierPatch *pBP = pCP->unpackIntoCache(); - - CPatchInfo &rPI = vPI[i]; - - for (k = 0; k < (uint32)(rPI.OrderT*4); ++k) - for (j = 0; j < (uint32)(rPI.OrderS*4); ++j) - { - s = ((0.5f+(float)j) / (rPI.OrderS*4)); - t = ((0.5f+(float)k) / (rPI.OrderT*4)); - n = pBP->evalNormal (s, t); - val = 255.0f*(1.0f-n*l)/2.0f; - clamp (val, 0.0f, 255.0f); - rPI.Lumels[j+k*rPI.OrderS*4] = (uint8)(val); - } - } - - zoneOut.build (zoneIn.getZoneId(), vPI, vBV); -} - -// --------------------------------------------------------------------------- -string CExport::getZoneNameFromXY (sint32 x, sint32 y) -{ - string tmp; - - if ((y>0) || (y<-255) || (x<0) || (x>255)) - return "NOT VALID"; - tmp = toString(-y) + "_"; - tmp += ('A' + (x/26)); - tmp += ('A' + (x%26)); - return tmp; -} - -// --------------------------------------------------------------------------- -sint32 CExport::getXFromZoneName (const string &ZoneName) -{ - string xStr, yStr; - uint32 i = 0; - while (ZoneName[i] != '_') - { - yStr += ZoneName[i]; ++i; - if (i == ZoneName.size()) - return -1; - } - ++i; - while (i < ZoneName.size()) - { - xStr += ZoneName[i]; ++i; - } - return ((xStr[0] - 'A')*26 + (xStr[1] - 'A')); -} - -// --------------------------------------------------------------------------- -sint32 CExport::getYFromZoneName (const string &ZoneName) -{ - string xStr, yStr; - uint32 i = 0; - while (ZoneName[i] != '_') - { - yStr += ZoneName[i]; ++i; - if (i == ZoneName.size()) - return 1; - } - ++i; - while (i < ZoneName.size()) - { - xStr += ZoneName[i]; ++i; - } - return -atoi(yStr.c_str()); -} - -// --------------------------------------------------------------------------- -void CExport::transformCMB (const std::string &name, const NLMISC::CMatrix &transfo, bool verbose) const -{ - if (name.empty()) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Can't load cmb : the name is empty"); - return; - } - std::string cmbNoExtension = CFile::getFilenameWithoutExtension(name); - std::string cmbName = CPath::lookup(cmbNoExtension + ".cmb" , false, false, false); - if (cmbName.empty()) - { - if ((_ExportCB != NULL) && verbose) - _ExportCB->dispWarning("Can't find " + cmbNoExtension + ".cmb"); - return; - } - CIFile inStream; - if (inStream.open(cmbName)) - { - try - { - CCollisionMeshBuild cmb; - cmb.serial(inStream); - // translate and save - cmb.transform (transfo); - COFile outStream; - std::string outFileName = _Options->OutCMBDir +"/" + cmbNoExtension + ".cmb"; - if (!outStream.open(outFileName)) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Couldn't open " + outFileName + "for writing, not exporting"); - } - else - { - try - { - cmb.serial(outStream); - outStream.close(); - } - catch (const EStream &e) - { - outStream.close(); - if (_ExportCB != NULL) - { - _ExportCB->dispWarning("Error while writing " + outFileName); - _ExportCB->dispWarning(e.what()); - } - } - } - inStream.close(); - } - catch (const EStream &e) - { - inStream.close(); - if (_ExportCB != NULL) - { - _ExportCB->dispWarning("Error while reading " + cmbName); - _ExportCB->dispWarning(e.what()); - } - } - } - else - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Unable to open " + cmbName); - } -} - -// --------------------------------------------------------------------------- -void CExport::transformAdditionnalIG (const std::string &name, const NLMISC::CMatrix &transfo, const NLMISC::CQuat &rotTransfo) const -{ - if (name.empty()) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Can't load cmb : the name is empty"); - return; - } - std::string igNoExtension = CFile::getFilenameWithoutExtension(name); - std::string igName = CPath::lookup(igNoExtension + ".ig" , false, false, false); - if (igName.empty()) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Can't find " + igNoExtension + ".cmb"); - return; - } - CIFile inStream; - if (inStream.open(igName)) - { - try - { - CInstanceGroup ig, igOut; - ig.serial(inStream); - - CVector globalPos; - CInstanceGroup::TInstanceArray IA; - std::vector Clusters; - std::vector Portals; - std::vector PLN; - - ig.retrieve(globalPos, IA, Clusters, Portals, PLN); - bool realTimeSuncontribution = ig.getRealTimeSunContribution(); - - uint k; - // elevate instance - for(k = 0; k < IA.size(); ++k) - { - IA[k].Pos = transfo * IA[k].Pos; - IA[k].Rot = rotTransfo * IA[k].Rot; - } - // lights - for(k = 0; k < PLN.size(); ++k) - { - PLN[k].setPosition(transfo * PLN[k].getPosition()); - } - // portals - std::vector portal; - for(k = 0; k < Portals.size(); ++k) - { - Portals[k].getPoly(portal); - for(uint l = 0; l < portal.size(); ++l) - { - portal[l] = transfo * portal[l]; - } - Portals[k].setPoly(portal); - } - - // clusters - for(k = 0; k < Clusters.size(); ++k) - { - Clusters[k].applyMatrix (transfo); - } - - - - igOut.build(globalPos, IA, Clusters, Portals, PLN); - igOut.enableRealTimeSunContribution(realTimeSuncontribution); - - COFile outStream; - std::string outFileName = _Options->AdditionnalIGOutDir +"/" + igNoExtension + ".ig"; - if (!outStream.open(outFileName)) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Couldn't open " + outFileName + "for writing, not exporting"); - } - else - { - try - { - igOut.serial(outStream); - outStream.close(); - } - catch (const EStream &e) - { - outStream.close(); - if (_ExportCB != NULL) - { - _ExportCB->dispWarning("Error while writing " + outFileName); - _ExportCB->dispWarning(e.what()); - } - } - } - inStream.close(); - } - catch (const EStream &e) - { - inStream.close(); - if (_ExportCB != NULL) - { - _ExportCB->dispWarning("Error while reading " + igName); - _ExportCB->dispWarning(e.what()); - } - } - } - else - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Unable to open " + igName); - } -} - -// --------------------------------------------------------------------------- -void CExport::exportCMBAndAdditionnalIGs() -{ - if (!_Options->ExportCollisions && !_Options->ExportCollisions) return; - CSmartPtr continent = loadContinent(_Options->ContinentFile); - if (!continent) return; - - NLGEORGES::UFormElm *villages; - if (!continent->getRootNode ().getNodeByName (&villages, "Villages") || !villages) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Cant find villages in a continent form"); - return; - } - - uint size; - nlverify (villages->getArraySize (size)); - - for(uint k = 0; k < size; ++k) - { - NLGEORGES::UFormElm *village; - if (!villages->getArrayNode (&village, k) || !village) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Cant get a village "); - continue; - } - - // get position of village - float altitude; - if (!village->getValueByName (altitude, "Altitude")) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Cant get a village position"); - continue; - } - - // get rotation of village - sint32 rotation; - if (!village->getValueByName (rotation, "Rotation")) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Cant get a village rotation"); - continue; - } - - // get width and height of village - uint32 width; - if (!village->getValueByName (width, "Width")) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Cant get a village width"); - continue; - } - - // get width and height of village - uint32 height; - if (!village->getValueByName (height, "Height")) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Cant get a village height"); - continue; - } - - // get position of village - std::string zoneName; - if (!village->getValueByName (zoneName, "Zone")) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Cant get a village name"); - continue; - } - - zoneName = strupr(zoneName); - // - sint32 x = CExport::getXFromZoneName(zoneName), y = CExport::getYFromZoneName(zoneName); - CVector pos(160.f * x, 160.f * y, altitude + getHeight(160.f * x, 160.f * y)); - - // *** Build the transformation - CMatrix transfo; - CQuat rotTransfo; - rotTransfo.identity (); - transfo.identity (); - - // Rotation - float angle = (float)rotation * (float)Pi / 2.f; - transfo.rotateZ (angle); - rotTransfo = CQuat (CVector::K, angle); - - // Add translation - switch (rotation&3) - { - case 0: - transfo.setPos (pos); - break; - case 1: - transfo.setPos (pos+CVector (160.f * height, 0, 0)); - break; - case 2: - transfo.setPos (pos+CVector (160.f * width, 160.f * height, 0)); - break; - case 3: - transfo.setPos (pos+CVector (0, 160.f * width, 0)); - break; - } - - // process ig / cmb of the village - NLGEORGES::UFormElm *igNamesItem; - if (!village->getNodeByName (&igNamesItem, "IgList") || !igNamesItem) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Cant get village ig list"); - continue; - } - - uint sizeIg; - nlverify (igNamesItem->getArraySize (sizeIg)); - - std::string igName; - - // For each children - for(uint k = 0; k < sizeIg; ++k) - { - // Get the aray element - const NLGEORGES::UFormElm *currIg; - if (igNamesItem->getArrayNode (&currIg, k) && currIg) - { - const NLGEORGES::UFormElm *igNameItem; - if (!currIg->getNodeByName (&igNameItem, "IgName") || !igNameItem) - { - nlwarning("Unable to get village name from a form"); - continue; - } - - if (igNameItem->getValue (igName)) - { - if (_Options->ExportCollisions) - { - transformCMB (igName, transfo, true); - - // Try to export alternative cmb like ig#0.cmb, ig#1.cmb, ig#2.cmb ... ig#9.cmb - std::string cmbNoExtension = CFile::getFilenameWithoutExtension(igName) + "#"; - uint alt; - for (alt=0; alt<10; alt++) - transformCMB (cmbNoExtension+toString (alt), transfo, false); - } - if (_Options->ExportAdditionnalIGs) transformAdditionnalIG (igName, transfo, rotTransfo); - } - else - { - nlwarning("Unable to get village name from a form"); - } - } - } - - } - return; -} - - -// --------------------------------------------------------------------------- -NLGEORGES::UForm* CExport::loadContinent(const std::string &name) const -{ - if (!NLMISC::CFile::fileExists(name)) - { - if (_ExportCB != NULL) - _ExportCB->dispWarning("Can't find " + name); - return NULL; - } - - UForm *form; - if (!(form = _FormLoader->loadForm (name.c_str ()))) - { - if (_ExportCB != NULL) - { - _ExportCB->dispWarning("Unable to load continent form : " + name); - } - return NULL; - } - - return form; -} - - - -// *************************************************************************** -void CExport::computeSubdividedTangents(uint numBinds, const NL3D::CBezierPatch &patch, uint edge, NLMISC::CVector subTangents[8]) -{ - // Subdivide the Bezier patch to get the correct tangents to apply to neighbors - CBezierPatch subPatchs1_2[2]; - CBezierPatch subPatchs1_4[4]; - - // subdivide on s if edge is horizontal - bool subDivideOnS= (edge&1)==1; - - // Subdivide one time. - if(subDivideOnS) patch.subdivideS(subPatchs1_2[0], subPatchs1_2[1]); - else patch.subdivideT(subPatchs1_2[0], subPatchs1_2[1]); - - // Subdivide again for bind 1/4. - if(numBinds==4) - { - if(subDivideOnS) - { - subPatchs1_2[0].subdivideS(subPatchs1_4[0], subPatchs1_4[1]); - subPatchs1_2[1].subdivideS(subPatchs1_4[2], subPatchs1_4[3]); - } - else - { - subPatchs1_2[0].subdivideT(subPatchs1_4[0], subPatchs1_4[1]); - subPatchs1_2[1].subdivideT(subPatchs1_4[2], subPatchs1_4[3]); - } - } - - // Now, fill the tangents according to edge. - bool invertPaSrc= edge>=2; - // Bind 1/2 case. - if(numBinds==2) - { - // 4 tangents to fill. - for(uint i=0;i<4;i++) - { - // get patch id from 0 to 1. - uint paSrcId= i/2; - // invert if edge is 2 or 3 - if(invertPaSrc) paSrcId= 1-paSrcId; - // get tg id in this patch. - uint tgSrcId= (i&1) + edge*2; - // fill result. - subTangents[i]= subPatchs1_2[paSrcId].Tangents[tgSrcId]; - } - } - // Bind 1/4 case. - else - { - // 8 tangents to fill. - for(uint i=0;i<8;i++) - { - // get patch id from 0 to 3. - uint paSrcId= i/2; - // invert if edge is 2 or 3 - if(invertPaSrc) paSrcId= 3-paSrcId; - // get tg id in this patch. - uint tgSrcId= (i&1) + edge*2; - // fill result. - subTangents[i]= subPatchs1_4[paSrcId].Tangents[tgSrcId]; - } - } -} - - -// *************************************************************************** -bool CExport::applyVertexBind(NL3D::CPatchInfo &pa, NL3D::CPatchInfo &oldPa, uint edgeToModify, bool startEdge, - const NLMISC::CMatrix &oldTgSpace, const NLMISC::CMatrix &newTgSpace, - const NLMISC::CVector &bindedPos, const NLMISC::CVector &bindedTangent ) -{ - // Get the vertex to modify according to edge/startEdge - uint vertexToModify= edgeToModify + (startEdge?0:1); - vertexToModify&=3; - - // If already moved, no-op - if(pa.Patch.Vertices[vertexToModify]==bindedPos) - return false; - else - { - // Change the vertex - pa.Patch.Vertices[vertexToModify]= bindedPos; - - // change the tangent, according to startEdge - pa.Patch.Tangents[edgeToModify*2 + (startEdge?0:1) ]= bindedTangent; - - // Must change the tangent which is on the other side of the vertex: - uint tgToModify= 8 + edgeToModify*2 + (startEdge?-1:+2); - tgToModify&=7; - /* To keep the same continuity aspect around the vertex, we compute the original tangent in a - special space: the Binded Patch Tangent Space. Once we have the original tangent in the original patch TgSpace, - we reapply it in the transformed patch TgSpace, to get the transformed tangent - */ - pa.Patch.Tangents[tgToModify]= newTgSpace * ( oldTgSpace.inverted() * oldPa.Patch.Tangents[tgToModify] ); - - - // Do the same to the associated interior. - pa.Patch.Interiors[vertexToModify]= newTgSpace * ( oldTgSpace.inverted() * oldPa.Patch.Interiors[vertexToModify] ); - - - // modified - return true; - } -} - - -// *************************************************************************** -NLMISC::CVector CExport::getHeightNormal (float x, float y) -{ - sint32 SizeX = _ZoneMaxX - _ZoneMinX + 1; - sint32 SizeY = _ZoneMaxY - _ZoneMinY + 1; - sint32 bmpW, bmpH; - - - // get width/height of the bitmap - if (_HeightMap != NULL) - { - bmpW= _HeightMap->getWidth(); - bmpH= _HeightMap->getHeight(); - } - else if (_HeightMap2 != NULL) - { - bmpW= _HeightMap2->getWidth(); - bmpH= _HeightMap2->getHeight(); - } - else - { - // no heightmap: unmodified normal - return CVector::K; - } - - - // compute a good delta to compute tangents of the heightmap: 1/10 of a pixel, avoiding precision problem. - float dx= ((_Options->CellSize*SizeX)/bmpW)/10; // eg: 160m/20pixels/10= 0.8 - float dy= ((_Options->CellSize*SizeY)/bmpH)/10; - - // compute tangent around the position. - float hc= getHeight(x,y); - float hx= getHeight(x+dx,y); - float hy= getHeight(x,y+dy); - CVector ds(dx,0,hx-hc); - CVector dt(0,dy,hy-hc); - - // compute the heightmap normal with the tangents - return (ds^dt).normed(); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "export.h" + +#include "nel/misc/file.h" +#include "nel/misc/path.h" +#include "nel/misc/smart_ptr.h" + +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" +#include "nel/georges/u_form_loader.h" +#include "nel/misc/quat.h" + +#include "nel/3d/tile_bank.h" +#include "nel/3d/zone_lighter.h" +#include "nel/3d/zone_symmetrisation.h" +#include "nel/3d/landscape.h" +#include "nel/3d/scene_group.h" + +#include "nel/ligo/zone_region.h" +#include "nel/ligo/zone_bank.h" + +#include "nel/../../src/pacs/collision_mesh_build.h" + + +#include "../../../leveldesign/export/tools.h" + +#include + +#ifdef NL_OS_WINDOWS +# include +#endif // NL_OS_WINDOWS + +using namespace NL3D; +using namespace NLMISC; +using namespace NLLIGO; +using namespace NLGEORGES; +using namespace std; +using namespace NLPACS; + + + + + + + +// --------------------------------------------------------------------------- +// Export options +// --------------------------------------------------------------------------- + +// --------------------------------------------------------------------------- +SExportOptions::SExportOptions () +{ + ZoneRegion = NULL; + CellSize = 160.0f; + Threshold = 1.0f; + ZFactor = 1.0f; + ZFactor2 = 1.0f; + Light = false; + ExportCollisions = false; + ExportAdditionnalIGs = false; +} + +// --------------------------------------------------------------------------- +void SExportOptions::serial (NLMISC::IStream& s) +{ + int version = s.serialVersion (11); + + s.serial (OutZoneDir); + s.serial (RefZoneDir); + + if (version > 0) + s.serial (LigoBankDir); + + if (version > 1) + s.serial (TileBankFile); + + if (version > 2) + s.serial (HeightMapFile); + + if (version > 3) + s.serial (Light); + + if (version > 4) + { + s.serial (ZFactor); + s.serial (HeightMapFile2); + s.serial (ZFactor2); + } + + if (version > 5) + { + s.serial (ZoneMin); + s.serial (ZoneMax); + } + + if (version > 6) + { + s.serial (RefIGDir); + s.serial (OutIGDir); + } + + if (version > 7) + { + s.serial(ExportCollisions); + s.serial(RefCMBDir, OutCMBDir); + s.serial(AdditionnalIGInDir, AdditionnalIGOutDir); + s.serial(ContinentFile); + s.serial(DFNDir); + } + + if (version > 8) + { + s.serial(ExportAdditionnalIGs); + } + + if (version > 9) + { + s.serial(ContinentsDir); + } + + if (version > 10) + { + s.serial (ColorMapFile); + } +} + +// --------------------------------------------------------------------------- +// CExport +// --------------------------------------------------------------------------- + +// --------------------------------------------------------------------------- +CExport::CExport () +{ + _ZeZoneBank = NULL; + _FormLoader = UFormLoader::createLoader (); +} + +// --------------------------------------------------------------------------- +CExport::~CExport () +{ + UFormLoader::releaseLoader (_FormLoader); +} + +// --------------------------------------------------------------------------- +bool CExport::export_ (SExportOptions &options, IExportCB *expCB) +{ + string sCurDir = CTools::pwd(); + + _Options = &options; + _ExportCB = expCB; + + if (_Options->ZoneRegion == NULL) + { + if (_ExportCB != NULL) + _ExportCB->dispError ("No Zone to export"); + return false; + } + + // LOADING + // --- continent form + CPath::addSearchPath(_Options->DFNDir, true, false); + CPath::addSearchPath(_Options->RefCMBDir, true, false); + CPath::addSearchPath(_Options->ContinentsDir, true, false); + CPath::addSearchPath(_Options->AdditionnalIGInDir, true, false); + + // --- ligozone + if (_ExportCB != NULL) + _ExportCB->dispPass ("Loading ligozone bank"); + _ZeZoneBank = new CZoneBank; + string error; + _ZeZoneBank->initFromPath (_Options->LigoBankDir, error); + + // --- tile + if (_ExportCB != NULL) + _ExportCB->dispPass ("Loading tile bank"); + _ZeTileBank = new CTileBank; + try + { + CIFile inFile (_Options->TileBankFile); + _ZeTileBank->serial (inFile); + } + catch (const Exception &) + { + if (_ExportCB != NULL) + _ExportCB->dispError (string("Cant load tile bank : ") + _Options->TileBankFile); + return false; + } + + // --- height map + if (_ExportCB != NULL) + _ExportCB->dispPass ("Loading height map"); + _HeightMap = NULL; + if (_Options->HeightMapFile != "") + { + _HeightMap = new CBitmap; + try + { + CIFile inFile; + if (inFile.open (_Options->HeightMapFile)) + { + _HeightMap->load (inFile); + } + else + { + if (_ExportCB != NULL) + _ExportCB->dispWarning (string("Cant load height map : ") + _Options->HeightMapFile); + delete _HeightMap; + _HeightMap = NULL; + } + } + catch (const Exception &) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning (string("Cant load height map : ") + _Options->HeightMapFile); + delete _HeightMap; + _HeightMap = NULL; + } + } + + // --- height map 2 + if (_ExportCB != NULL) + _ExportCB->dispPass ("Loading height map"); + _HeightMap2 = NULL; + if (_Options->HeightMapFile2 != "") + { + _HeightMap2 = new CBitmap; + try + { + CIFile inFile; + if (inFile.open (_Options->HeightMapFile2)) + { + _HeightMap2->load (inFile); + } + else + { + if (_ExportCB != NULL) + _ExportCB->dispWarning (string("ERROR: Cant load height map : ") + _Options->HeightMapFile2); + delete _HeightMap2; + _HeightMap2 = NULL; + } + } + catch (const Exception &) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning (string("ERROR: Cant load height map : ") + _Options->HeightMapFile2); + delete _HeightMap2; + _HeightMap2 = NULL; + } + } + + // --- color map + if (_ExportCB != NULL) + _ExportCB->dispPass ("Loading color map"); + _ColorMap = NULL; + if (_Options->ColorMapFile != "") + { + _ColorMap = new CBitmap; + try + { + CIFile inFile; + if (inFile.open (_Options->ColorMapFile)) + { + _ColorMap->load (inFile); + } + else + { + if (_ExportCB != NULL) + _ExportCB->dispWarning (string("ERROR: Cant load color map : ") + _Options->ColorMapFile); + delete _ColorMap; + _ColorMap = NULL; + } + } + catch (const Exception &) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning (string("ERROR: Cant load color map : ") + _Options->ColorMapFile); + delete _ColorMap; + _ColorMap = NULL; + } + } + + // **************** + // *EXPORTING CODE* + // **************** + + if (_ExportCB != NULL) + _ExportCB->dispPass ("Exporting"); + + // Clip the min max to the x[0,255],y[0,-255] values + sint32 nMinX = _Options->ZoneRegion->getMinX() < 0 ? 0 : _Options->ZoneRegion->getMinX(); + sint32 nMaxX = _Options->ZoneRegion->getMaxX() > 255 ? 255 : _Options->ZoneRegion->getMaxX(); + sint32 nMinY = _Options->ZoneRegion->getMinY() > 0 ? 0 : _Options->ZoneRegion->getMinY(); + sint32 nMaxY = _Options->ZoneRegion->getMaxY() < -255 ? -255 : _Options->ZoneRegion->getMaxY(); + + + vector allFiles; + + // Delete zones that are not in the bounding square + try + { + // Add zone files + if (_Options->OutZoneDir != "") + NLMISC::CPath::getPathContent(_Options->OutZoneDir, true, false, true, allFiles); + + // Add ig files + vector allOtherFiles; + if (_Options->OutIGDir != "") + NLMISC::CPath::getPathContent(_Options->OutIGDir, true, false, true, allOtherFiles); + allFiles.insert(allFiles.end(), allOtherFiles.begin(), allOtherFiles.end()); + } + catch (const Exception &e) + { + if (_ExportCB != NULL) + _ExportCB->dispError (string("GetPathcontent failed : ") + e.what()); + return false; + } + + // zones + + + + for (uint32 nFile = 0; nFile < allFiles.size(); ++nFile) + { + string fileExt = NLMISC::CFile::getExtension(allFiles[nFile]); + string fileName = NLMISC::CFile::getFilename(allFiles[nFile]); + + if (fileExt != "ig" && fileExt != "zone" && fileExt != "zonel" && fileExt != "zonenh" ) continue; + sint32 x = getXFromZoneName (fileName); + sint32 y = getYFromZoneName (fileName); + if ((x>=0) && (y<=0)) + { + bool bMustDelete = false; + // Valid file + if ((xnMaxX) || (ynMaxY)) + { + bMustDelete = true; + } + else + { + const string &SrcZoneName = _Options->ZoneRegion->getName (x, y); + + if ((SrcZoneName == STRING_OUT_OF_BOUND) || (SrcZoneName == STRING_UNUSED)) + { + bMustDelete = true; + } + } + + if (bMustDelete) + { + if (!CFile::deleteFile (allFiles[nFile])) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning (string("Can't delete ") + fileName); + } + else + { + if (_ExportCB != NULL) + _ExportCB->dispInfo (string("Deleted ") + fileName); + } + } + } + } + + + + CTools::chdir (sCurDir); + + // Get the export limiters if any + _ZoneMinX = nMinX; + _ZoneMinY = nMinY; + _ZoneMaxX = nMaxX; + _ZoneMaxY = nMaxY; + + if ((_Options->ZoneMin != "") && (_Options->ZoneMax != "")) + { + _Options->ZoneMin = strupr (_Options->ZoneMin); + _Options->ZoneMax = strupr (_Options->ZoneMax); + sint32 nNewMinX = getXFromZoneName (_Options->ZoneMin); + sint32 nNewMinY = getYFromZoneName (_Options->ZoneMin); + sint32 nNewMaxX = getXFromZoneName (_Options->ZoneMax); + sint32 nNewMaxY = getYFromZoneName (_Options->ZoneMax); + + if (nNewMinX > nNewMaxX) + swap (nNewMinX, nNewMaxX); + if (nNewMinY > nNewMaxY) + swap (nNewMinY, nNewMaxY); + + if (nNewMinX > nMinX) + nMinX = nNewMinX; + if (nNewMinY > nMinY) + nMinY = nNewMinY; + + if (nNewMaxX < nMaxX) + nMaxX = nNewMaxX; + if (nNewMaxY < nMaxY) + nMaxY = nNewMaxY; + } + + sint32 nTotalFile = (1 + nMaxY - nMinY) * (1 + nMaxX - nMinX); + sint32 nCurrentFile = 0; + + vector ZoneTreated; + ZoneTreated.resize(nTotalFile, false); + + for (sint32 j = nMinY; j <= nMaxY; ++j) + { + for (sint32 i = nMinX; i <= nMaxX; ++i) + if (!ZoneTreated[i-nMinX+(j-nMinY)*(1+nMaxX-nMinX)]) + { + ++nCurrentFile; + if (_ExportCB != NULL) + _ExportCB->dispPassProgress(((float)nCurrentFile)/((float)nTotalFile)); + + const string &SrcZoneName = _Options->ZoneRegion->getName(i,j); + + if ((SrcZoneName == STRING_OUT_OF_BOUND) || + (SrcZoneName == STRING_UNUSED)) + continue; + + treatPattern (i, j, ZoneTreated, nMinX, nMinY, 1+nMaxX-nMinX); + + if ((_ExportCB != NULL) && (_ExportCB->isCanceled())) + break; + } + if ((_ExportCB != NULL) && (_ExportCB->isCanceled())) + break; + } + + exportCMBAndAdditionnalIGs(); + + + + if (_ExportCB != NULL) + _ExportCB->dispPass ("Finished"); + delete _ZeZoneBank; + delete _ZeTileBank; + + return true; +} + +// --------------------------------------------------------------------------- +void CExport::treatPattern (sint32 x, sint32 y, + vector &ZoneTreated, sint32 nMinX, sint32 nMinY, sint32 nStride) +{ + + CZoneRegion *pZR = _Options->ZoneRegion; + const string &rSZone = pZR->getName (x, y); + CZoneBankElement *pZBE = _ZeZoneBank->getElementByZoneName (rSZone); + + if (pZBE == NULL) + return; + + sint32 sizeX = pZBE->getSizeX(), sizeY = pZBE->getSizeY(); + sint32 posX = pZR->getPosX (x, y), posY = pZR->getPosY (x, y); + uint8 rot = pZR->getRot (x, y); + uint8 flip = pZR->getFlip (x, y); + sint32 i, j; + sint32 deltaX, deltaY; + + if (flip == 0) + { + switch (rot) + { + case 0: deltaX = -posX; deltaY = -posY; break; + case 1: deltaX = -(sizeY-1-posY); deltaY = -posX; break; + case 2: deltaX = -(sizeX-1-posX); deltaY = -(sizeY-1-posY); break; + case 3: deltaX = -posY; deltaY = -(sizeX-1-posX); break; + } + } + else + { + switch (rot) + { + case 0: deltaX = -(sizeX-1-posX); deltaY = -posY; break; + case 1: deltaX = -(sizeY-1-posY); deltaY = -(sizeX-1-posX); break; + case 2: deltaX = -posX; deltaY = -(sizeY-1-posY); break; + case 3: deltaX = -posY; deltaY = -posX; break; + } + } + + SPiece sMask; + sMask.Tab.resize (sizeX*sizeY); + for(i = 0; i < sizeX*sizeY; ++i) + sMask.Tab[i] = pZBE->getMask()[i]; + sMask.w = sizeX; + sMask.h = sizeY; + sMask.rotFlip (rot, flip); + + // Check if we have to export the zones + bool bHaveToExportZone = false; + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + // If date of the piece is newer than date of the final zones + string finalZoneName = _Options->OutZoneDir + string("\\") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + string(".zonel"); + if (!CTools::fileExist(finalZoneName)) + { + finalZoneName = _Options->OutZoneDir + string("\\") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + string(".zone"); + if (!CTools::fileExist(finalZoneName)) + { + bHaveToExportZone = true; // A file do not exist -> export it + + if (_ExportCB != NULL) + _ExportCB->dispInfo (string("finalZone do not exist")); + + + continue; + } + } + string refZoneName = _Options->RefZoneDir + string("\\") + rSZone + string(".zone"); + + if (!CTools::fileExist(refZoneName)) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning(string("RefZone do not exist.") + refZoneName); + return; + } + + if (CTools::fileDateCmp(refZoneName, finalZoneName) > 0) + { + bHaveToExportZone = true; + + if (_ExportCB != NULL) + _ExportCB->dispInfo (string("RefZone newer than finalZone.")); + + break; + } + // Or if the date of the cell is newer than the date of the final zone + uint32 cellDateLow = pZR->getDate(x+deltaX+i, y+deltaY+j, 0); + uint32 cellDateHigh = pZR->getDate(x+deltaX+i, y+deltaY+j, 1); + + if (CTools::fileDateCmp(finalZoneName, cellDateLow, cellDateHigh) < 0) + { + bHaveToExportZone = true; + + if (_ExportCB != NULL) + _ExportCB->dispInfo (string("Cell date newer")); + + break; + } + } + + // Check if we have to export the igs + bool bHaveToExportIG = false; + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + // If date of the piece is newer than date of the final zones + string finalIGName = _Options->OutIGDir + string("\\") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + string(".ig"); + if (!CTools::fileExist(finalIGName)) + { + finalIGName = _Options->OutIGDir + string("\\") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + string(".ig"); + if (!CTools::fileExist(finalIGName)) + { + bHaveToExportIG = true; // A file do not exist -> export it + + if (_ExportCB != NULL) + _ExportCB->dispInfo (string("final instance group do not exist")); + + + continue; + } + } + string refIGName = _Options->RefIGDir + string("\\") + rSZone + string(".ig"); + + if (!CTools::fileExist(refIGName)) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning(string("RefIG do not exist.") + refIGName); + continue; + } + + if (CTools::fileDateCmp(refIGName, finalIGName) > 0) + { + bHaveToExportIG = true; + + if (_ExportCB != NULL) + _ExportCB->dispInfo (string("RefIG newer than finalIG.")); + + break; + } + // Or if the date of the cell is newer than the date of the final ig + uint32 cellDateLow = pZR->getDate(x+deltaX+i, y+deltaY+j, 0); + uint32 cellDateHigh = pZR->getDate(x+deltaX+i, y+deltaY+j, 1); + + if (CTools::fileDateCmp(finalIGName, cellDateLow, cellDateHigh) < 0) + { + bHaveToExportIG = true; + + if (_ExportCB != NULL) + _ExportCB->dispInfo (string("Cell date newer")); + + break; + } + } + + + if (bHaveToExportZone == false && bHaveToExportIG == false) + return; + + // Put the big zone at the right position + CZone BigZone; + + + // 1 - Load the zone and IG + string BigZoneFileName; + + if (bHaveToExportZone) + { + try + { + BigZoneFileName = _Options->RefZoneDir + string("\\") + rSZone + string(".zone"); + CIFile inFile ; + if (inFile.open(BigZoneFileName)) + { + BigZone.serial (inFile); + } + else + { + _ExportCB->dispWarning(string("reference zone " + BigZoneFileName + " does not exists, skipping.")); + bHaveToExportZone = false; + } + } + catch (const Exception &e) + { + if (_ExportCB != NULL) + { + _ExportCB->dispWarning (string("Cant load zone : ") + BigZoneFileName); + _ExportCB->dispWarning (string("Reason : ") + e.what()); + } + bHaveToExportZone = false; + } + } + + CInstanceGroup bigIG; + string bigIGFileName; + + if (bHaveToExportIG) + { + try + { + bigIGFileName = _Options->RefIGDir + string("\\") + rSZone + string(".ig"); + CIFile inFile; + if (inFile.open(bigIGFileName)) + { + bigIG.serial (inFile); + } + else + { + // _ExportCB->dispWarning(string("reference ig " + bigIGFileName + " does not exists, skipping.")); + bHaveToExportIG = false; + } + } + catch (const Exception &e) + { + if (_ExportCB != NULL) + { + _ExportCB->dispWarning (string("ERROR: Cant load ig : ") + bigIGFileName); + _ExportCB->dispWarning (string("ERROR: Reason : ") + e.what()); + } + bHaveToExportIG = false; + } + } + + // 1bis - Copy the zone as no heightmap + CZone BigZoneNoHeightmap = BigZone; + + // 2 - Transform zone / ig + // zone + if (bHaveToExportZone) + { + if (flip == 0) + { + switch (rot) + { + case 0: + transformZone (BigZone, x+deltaX, y+deltaY, rot, flip, true); + transformZone (BigZoneNoHeightmap, x+deltaX, y+deltaY, rot, flip, false); + break; + case 1: + transformZone (BigZone, x+deltaX+sizeY, y+deltaY, rot, flip, true); + transformZone (BigZoneNoHeightmap, x+deltaX+sizeY, y+deltaY, rot, flip, false); + break; + case 2: + transformZone (BigZone, x+deltaX+sizeX, y+deltaY+sizeY, rot, flip, true); + transformZone (BigZoneNoHeightmap, x+deltaX+sizeX, y+deltaY+sizeY, rot, flip, false); + break; + case 3: + transformZone (BigZone, x+deltaX, y+deltaY+sizeX, rot, flip, true); + transformZone (BigZoneNoHeightmap, x+deltaX, y+deltaY+sizeX, rot, flip, false); + break; + } + } + else + { + switch (rot) + { + case 0: + transformZone (BigZone, x+deltaX+sizeX, y+deltaY, rot, flip, true); + transformZone (BigZoneNoHeightmap, x+deltaX+sizeX, y+deltaY, rot, flip, false); + break; + case 1: + transformZone (BigZone, x+deltaX+sizeY, y+deltaY+sizeX, rot, flip, true); + transformZone (BigZoneNoHeightmap, x+deltaX+sizeY, y+deltaY+sizeX, rot, flip, false); + break; + case 2: + transformZone (BigZone, x+deltaX, y+deltaY+sizeY, rot, flip, true); + transformZone (BigZoneNoHeightmap, x+deltaX, y+deltaY+sizeY, rot, flip, false); + break; + case 3: + transformZone (BigZone, x+deltaX, y+deltaY, rot, flip, true); + transformZone (BigZoneNoHeightmap, x+deltaX, y+deltaY, rot, flip, false); + break; + } + } + } + + if (bHaveToExportIG) + { + if (flip == 0) + { + switch (rot) + { + case 0: + transformIG (bigIG, x+deltaX, y+deltaY, rot, flip); + break; + case 1: + transformIG (bigIG, x+deltaX+sizeY, y+deltaY, rot, flip); + break; + case 2: + transformIG (bigIG, x+deltaX+sizeX, y+deltaY+sizeY, rot, flip); + break; + case 3: + transformIG (bigIG, x+deltaX, y+deltaY+sizeX, rot, flip); + break; + } + } + else + { + switch (rot) + { + case 0: + transformIG (bigIG, x+deltaX+sizeX, y+deltaY, rot, flip); + break; + case 1: + transformIG (bigIG, x+deltaX+sizeY, y+deltaY+sizeX, rot, flip); + break; + case 2: + transformIG (bigIG, x+deltaX, y+deltaY+sizeY, rot, flip); + break; + case 3: + transformIG (bigIG, x+deltaX, y+deltaY, rot, flip); + break; + } + } + } + + // 3 - Add the global color map + addColorMap (BigZone); + + // 4 - Cut the big zone into a set of unit zones + + // - Build patch informations + + // Retrieve source patches + vector SrcPI; + vector BorderVertices; + BigZone.retrieve (SrcPI, BorderVertices); + vector SrcPINoHeightmap; + vector BorderVerticesNoHeightmap; + BigZoneNoHeightmap.retrieve (SrcPINoHeightmap, BorderVerticesNoHeightmap); + + // Resize bool array + vector PatchTransfered; // Is the patch n is transfered in a zoneUnit ? + PatchTransfered.resize (SrcPI.size(), false); + + // Patch bb + vector bb; + bb.resize (SrcPI.size()); + for (i = 0; i < (sint)SrcPI.size(); ++i) + { + CPatchInfo &rPI = SrcPI[i]; + + bb[i].setCenter (rPI.Patch.Vertices[0]); + + for (j = 0; j < 4; ++j) + bb[i].extend (rPI.Patch.Vertices[j]); + + for (j = 0; j < 4; ++j) + bb[i].extend (rPI.Patch.Interiors[j]); + + for (j = 0; j < 8; ++j) + bb[i].extend (rPI.Patch.Tangents[j]); + } + + bool first = true; + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + CZone UnitZone; + CZone UnitZoneLighted; + CZone UnitZoneNoHeightmap; + + CInstanceGroup unitIG; + + if (bHaveToExportZone) + { + // Put all the patches contained in the square ... in the unit zone + cutZone (BigZone, BigZoneNoHeightmap, UnitZone, UnitZoneNoHeightmap, x+deltaX+i, y+deltaY+j, PatchTransfered, bb, SrcPI, SrcPINoHeightmap, + sMask, BorderVertices, BorderVerticesNoHeightmap, x+deltaX, y+deltaY); + if (_Options->Light > 0) + light (UnitZoneLighted, UnitZone); + else + UnitZoneLighted = UnitZone; + } + + if (bHaveToExportIG) + { + // Put all the instances contained in the square ... in the unit zone + cutIG (bigIG, unitIG, x+deltaX+i, y+deltaY+j, sMask, first, x+deltaX, y+deltaY); + } + + if (bHaveToExportZone) + { + // Save the zone + string DstZoneFileName; + try + { + // Delete the .zone and .zonel file + DstZoneFileName = getZoneNameFromXY(x+deltaX+i, y+deltaY+j); + DstZoneFileName = _Options->OutZoneDir + string("/") + DstZoneFileName; + string sTmp = DstZoneFileName + string(".zone"); + CFile::deleteFile (sTmp); + DstZoneFileName = DstZoneFileName + string(".zonel"); + CFile::deleteFile (DstZoneFileName); + + // Delete the .zonenh file + string DstZoneNoHeightmapFileName = _Options->OutZoneDir + string("/") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + string(".zonenh"); + CFile::deleteFile (DstZoneNoHeightmapFileName); + + COFile outFile (DstZoneFileName); + UnitZoneLighted.serial (outFile); + if (_ExportCB != NULL) + _ExportCB->dispInfo (string("Writing ") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + ".zonel"); + + COFile outFileNH (DstZoneNoHeightmapFileName); + UnitZoneNoHeightmap.serial (outFileNH); + } + catch (const Exception &) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning (string("Cant write ") + DstZoneFileName); + } + } + + if (bHaveToExportIG) + { + // Save the ig + string dstIGFileName; + try + { + dstIGFileName = getZoneNameFromXY(x+deltaX+i, y+deltaY+j); + dstIGFileName = _Options->OutIGDir + string("/") + dstIGFileName + string(".ig"); + CFile::deleteFile (dstIGFileName); + COFile outFile (dstIGFileName); + unitIG.serial(outFile); + if (_ExportCB != NULL) + _ExportCB->dispInfo (string("Writing ") + getZoneNameFromXY(x+deltaX+i, y+deltaY+j) + ".ig"); + } + catch (const Exception &) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning (string("Cant write ") + dstIGFileName); + } + } + + // Set the zone as unused to not treat it the next time + ZoneTreated[(x+deltaX+i)-nMinX + ((y+deltaY+j)-nMinY) * nStride] = true; + + if ((_ExportCB != NULL) && (_ExportCB->isCanceled())) + return; + + first = false; + } + +} + +// --------------------------------------------------------------------------- +// Tile conversion +int TransitionFlipLR[48] = +{ + 0, // 0 + 4, // 1 + 5, // 2 + 27, // 3 + 1, // 4 + 2, // 5 + 6, // 6 + 34, // 7 + 11, // 8 + 33, // 9 + 31, // 10 + 8, // 11 + 13, // 12 + 12, // 13 + 47, // 14 + 40, // 15 + 39, // 16 + 20, // 17 + 46, // 18 + 45, // 19 + 17, // 20 + 43, // 21 + 42, // 22 + 41, // 23 + 24, // 24 + 28, // 25 + 29, // 26 + 3, // 27 + 25, // 28 + 26, // 29 + 30, // 30 + 10, // 31 + 35, // 32 + 9, // 33 + 7, // 34 + 32, // 35 + 37, // 36 + 36, // 37 + 44, // 38 + 16, // 39 + 15, // 40 + 23, // 41 + 22, // 42 + 21, // 43 + 38, // 44 + 19, // 45 + 18, // 46 + 14 // 47 +}; + +int TransitionFlipUD[48] = +{ + 24, // 0 + 28, // 1 + 29, // 2 + 3, // 3 + 25, // 4 + 26, // 5 + 30, // 6 + 10, // 7 + 35, // 8 + 9, // 9 + 7, // 10 + 32, // 11 + 37, // 12 + 36, // 13 + 23, // 14 + 16, // 15 + 15, // 16 + 44, // 17 + 22, // 18 + 21, // 19 + 38, // 20 + 19, // 21 + 18, // 22 + 14, // 23 + 0, // 24 + 4, // 25 + 5, // 26 + 27, // 27 + 1, // 28 + 2, // 29 + 6, // 30 + 34, // 31 + 11, // 32 + 33, // 33 + 31, // 34 + 8, // 35 + 13, // 36 + 12, // 37 + 20, // 38 + 40, // 39 + 39, // 40 + 47, // 41 + 46, // 42 + 45, // 43 + 17, // 44 + 43, // 45 + 42, // 46 + 41 // 47 +}; + +int TransitionRotCCW[48] = +{ + 27, // 0 + 28, // 1 + 29, // 2 + 0, // 3 + 1, // 4 + 2, // 5 + 33, // 6 + 34, // 7 + 35, // 8 + 6, // 9 + 7, // 10 + 8, // 11 + 39, // 12 + 40, // 13 + 17, // 14 + 12, // 15 + 13, // 16 + 41, // 17 + 45, // 18 + 46, // 19 + 47, // 20 + 18, // 21 + 19, // 22 + 20, // 23 + 3, // 24 + 4, // 25 + 5, // 26 + 24, // 27 + 25, // 28 + 26, // 29 + 9, // 30 + 10, // 31 + 11, // 32 + 30, // 33 + 31, // 34 + 32, // 35 + 15, // 36 + 16, // 37 + 14, // 38 + 36, // 39 + 37, // 40 + 38, // 41 + 21, // 42 + 22, // 43 + 23, // 44 + 42, // 45 + 43, // 46 + 44 // 47 +}; + +// --------------------------------------------------------------------------- +// Come from rpo2nel.cpp +// --------------------------------------------------------------------------- +bool transformTile (const CTileBank &bank, uint &tile, uint &tileRotation, bool symmetry, uint rotate) +{ + // Tile exist ? + if ( (rotate!=0) || symmetry ) + { + if (tile < (uint)bank.getTileCount()) + { + // Get xref + int tileSet; + int number; + CTileBank::TTileType type; + + // Get tile xref + bank.getTileXRef ((int)tile, tileSet, number, type); + + // Transition ? + if (type == CTileBank::transition) + { + // Number should be ok + nlassert (number>=0); + nlassert (numbergetOrientedBorder (CTileSet::left, CTileSet::getEdgeType ((CTileSet::TTransition)number, CTileSet::left)), + pTileSet->getOrientedBorder (CTileSet::bottom, CTileSet::getEdgeType ((CTileSet::TTransition)number, CTileSet::bottom)), + pTileSet->getOrientedBorder (CTileSet::right, CTileSet::getEdgeType ((CTileSet::TTransition)number, CTileSet::right)), + pTileSet->getOrientedBorder (CTileSet::top, CTileSet::getEdgeType ((CTileSet::TTransition)number, CTileSet::top)) + }; + + // Symmetry ? + if (symmetry) + { + CTileSet::TFlagBorder tmp = oriented[(0)&3]; + oriented[(0)&3] = CTileSet::getInvertBorder (oriented[(2)&3]); + oriented[(2)&3] = CTileSet::getInvertBorder (tmp); + oriented[(1)&3] = CTileSet::getInvertBorder (oriented[(1)&3]); + oriented[(3)&3] = CTileSet::getInvertBorder (oriented[(3)&3]); + } + + // Rotation + CTileSet::TFlagBorder edges[4]; + edges[0] = pTileSet->getOrientedBorder (CTileSet::left, oriented[(0 + rotate )&3]); + edges[1] = pTileSet->getOrientedBorder (CTileSet::bottom, oriented[(1 + rotate )&3]); + edges[2] = pTileSet->getOrientedBorder (CTileSet::right, oriented[(2 + rotate )&3]); + edges[3] = pTileSet->getOrientedBorder (CTileSet::top, oriented[(3 + rotate )&3]); + + // Get the good tile number + CTileSet::TTransition transition = pTileSet->getTransitionTile (edges[3], edges[1], edges[0], edges[2]); + nlassert ((CTileSet::TTransition)transition != CTileSet::notfound); + tile = (uint)(pTileSet->getTransition (transition)->getTile ()); + } + + // Transform rotation + if (symmetry) + tileRotation = (4-tileRotation)&3; + tileRotation += rotate; + tileRotation &= 3; + } + else + return false; + } + + // Ok + return true; +} + +// --------------------------------------------------------------------------- +// Come from rpo2nel.cpp +// --------------------------------------------------------------------------- +void transform256Case (const CTileBank &bank, uint &case256, uint tileRotation, bool symmetry, uint rotate) +{ + // Tile exist ? + if ( (rotate!=0) || symmetry ) + { + // Remove its rotation + case256 += tileRotation; + case256 &= 3; + + // Symmetry ? + if (symmetry) + { + // Take the symmetry + uint symArray[4] = {3, 2, 1, 0}; + case256 = symArray[case256]; + } + + // Rotation ? + case256 -= rotate + tileRotation; + case256 &= 3; + } +} + +// --------------------------------------------------------------------------- + +void CExport::addColorMap (CZone &zeZone) +{ + // Colormap available ? + if (_ColorMap) + { + // Conversion nPosX,nPosY to Zone Coordinate ZoneX, ZoneY + vector PatchInfos; + vector BorderVertices; + + // Retrieve the zone + zeZone.retrieve (PatchInfos, BorderVertices); + + // Apply the Colormap to all tile color. + // -------- + uint i; + for (i = 0; i < PatchInfos.size(); ++i) + { + CPatchInfo &rPI = PatchInfos[i]; + + // Get size + uint sizeU = rPI.OrderS+1; + uint sizeV = rPI.OrderT+1; + + // For each color tiles + uint u, v; + for (v = 0; v < sizeV; v++) + for (u = 0; u < sizeU; u++) + { + // Compute the coordinate for this color tile + CVector pos = rPI.Patch.eval ((float)u/(float)(sizeU-1), (float)v/(float)(sizeV-1)); + + // Get the color + CRGBAF colorf = getColor (pos.x, pos.y); + clamp (colorf.R, 0.f, 255.f); + clamp (colorf.G, 0.f, 255.f); + clamp (colorf.B, 0.f, 255.f); + clamp (colorf.A, 0.f, 255.f); + CRGBA color = CRGBA ((uint8)colorf.R, (uint8)colorf.G, (uint8)colorf.B, (uint8)colorf.A); + + // Destination color + uint16 &dest = rPI.TileColors[u+v*(sizeU)].Color565; + + // Original color + CRGBA src; + src.set565 (dest); + + // Blend the original and new color + CRGBA tmp; + tmp.blendFromui (src, color, ((uint)color.A) * 256 / 255); + dest = tmp.get565 (); + } + } + + zeZone.build (zeZone.getZoneId (), PatchInfos, BorderVertices); + } +} + +// --------------------------------------------------------------------------- +void CExport::transformZone (CZone &zeZone, sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip, bool computeHeightmap) +{ + // Conversion nPosX,nPosY to Zone Coordinate ZoneX, ZoneY + uint32 i, j; + vector PatchInfos; + vector BorderVertices; + + sint32 nZoneX = nPosX; + sint32 nZoneY = -1 - nPosY; + uint16 nZoneId = nZoneX+(nZoneY*256); + + zeZone.retrieve (PatchInfos, BorderVertices); + + nlassert (BorderVertices.size() == 0); + + CMatrix Transfo; + Transfo.setRot (CQuat(CVector::K, (float)(nRot * Pi / 2.0f))); + Transfo.setPos (CVector(nPosX*_Options->CellSize, (nPosY)*_Options->CellSize, 0.0f)); + + if (nFlip != 0) + nFlip = 1; + + if (nFlip == 1) + Transfo.scale(CVector(-1.0f, 1.0f, 1.0f)); + + // Transform the Patchs, and apply HeightMap. + //============================= + + + // 0. Transfrom zone indexes + //======================= + { + CMatrix invTransfo = Transfo; + invTransfo.invert (); + + NL3D::CZoneSymmetrisation zoneSymmetry; + if (! CPatchInfo::transform (PatchInfos, zoneSymmetry, *_ZeTileBank, nFlip != 0, nRot, _Options->CellSize, _Options->Threshold, invTransfo) ) + { + std::string name = getZoneNameFromXY (nPosX, nPosY); + + // Can't transform the zone + nlwarning ("ERROR: can't transform zone %s with sym:%d rot:%d", name.c_str (), nFlip, nRot); + } + } + + // 1. Transfom ligo zone in world + //======================= + for (i = 0; i < PatchInfos.size(); ++i) + { + CPatchInfo &rPI = PatchInfos[i]; + + rPI.Patch.applyMatrix (Transfo); + } + + // Bkup the original patchs. + vector oldPatchInfos= PatchInfos; + + // 2. Apply the Heighmap to all vertices/tangents/interiors. + // -------- + for (i = 0; i < PatchInfos.size(); ++i) + { + CPatchInfo &rPI = PatchInfos[i]; + + if (computeHeightmap) + { + // Elevate the vertices. + CVector verticesBeforeHeightMap[4]; + for (j = 0; j < 4; ++j) + { + verticesBeforeHeightMap[j]= rPI.Patch.Vertices[j]; + rPI.Patch.Vertices[j].z += getHeight(rPI.Patch.Vertices[j].x, rPI.Patch.Vertices[j].y); + } + + // Interior and tangent are rotated to follow the heightmap normal, avoiding the "Stair Effect". + // Compute the matrix to apply to interiors and tangents. + CMatrix tgMatrix[4]; + for (j = 0; j < 4; ++j) + { + // compute the normal of the heightmap. + CVector hmapNormal= getHeightNormal(rPI.Patch.Vertices[j].x, rPI.Patch.Vertices[j].y); + + // Compute the rotation which transforms the original normal: (0,0,1), to this normal. + CAngleAxis angleAxis; + angleAxis.Axis= CVector::K ^ hmapNormal; + angleAxis.Angle= (float)asin(angleAxis.Axis.norm()); + angleAxis.Axis.normalize(); + + // build the matrix which transform the old tgt/interior to his newValue: + // newVertexPos+ rotate*(oldTgPos-oldVertexPos) + tgMatrix[j].identity(); + tgMatrix[j].translate(rPI.Patch.Vertices[j]); + tgMatrix[j].setRot( CQuat(angleAxis) ); + tgMatrix[j].translate(-verticesBeforeHeightMap[j]); + } + + // For all interior. + for (j = 0; j < 4; ++j) + rPI.Patch.Interiors[j]= tgMatrix[j] * rPI.Patch.Interiors[j]; + + // when j == 7 or 0 use vertex 0 for delta Z to ensure continuity of normals + // when j == 1 or 2 use vertex 1 + // when j == 3 or 4 use vertex 2 + // when j == 5 or 6 use vertex 3 + for (j = 0; j < 8; ++j) + { + // get the correct vertex + uint vertexId= ((j+1)/2)%4; + // apply the tgMatrix to the tangent + rPI.Patch.Tangents[j]= tgMatrix[vertexId] * rPI.Patch.Tangents[j]; + } + } + + for (j = 0; j < 4; ++j) + rPI.BindEdges[j].ZoneId = nZoneId; + } + + // 3. For all binds, reset the position of near vertices/tangents/interiors. Must do it at last + // -------- + bool bindVertexModified= true; + // Since this is a recursive problem (binded patchs may bind other patchs), do it unitl all vertices no more move :) + while(bindVertexModified) + { + bindVertexModified= false; + for (i = 0; i < PatchInfos.size(); ++i) + { + CPatchInfo &rPI = PatchInfos[i]; + + // For all edges + for (j = 0; j < 4; ++j) + { + uint numBinds= rPI.BindEdges[j].NPatchs; + // If this edge is binded on 2 or 4 patches. + if( numBinds==2 || numBinds==4 ) + { + // compute the 4 or 8 tangents along the edge (in CCW) + CVector subTangents[8]; + computeSubdividedTangents(numBinds, rPI.Patch, j, subTangents); + + + // For all vertex to bind: 1 or 3. + for(uint vb=0; vb PatchInfos; + vector BorderVertices; + + sint32 nZoneX = nPosX; + sint32 nZoneY = -1 - nPosY; + uint16 nZoneId = nZoneX+(nZoneY*256); + + zeZone.retrieve (PatchInfos, BorderVertices); + + nlassert (BorderVertices.size() == 0); + + CMatrix Transfo; + Transfo.setRot (CQuat(CVector::K, (float)(nRot * Pi / 2.0f))); + Transfo.setPos (CVector(nPosX*_Options->CellSize, (nPosY)*_Options->CellSize, 0.0f)); + + if (nFlip != 0) + nFlip = 1; + + if (nFlip == 1) + Transfo.scale(CVector(-1.0f, 1.0f, 1.0f)); + + // Transform the Patchs, and apply HeightMap. + //============================= + + // Bkup the original patchs. + vector oldPatchInfos= PatchInfos; + + + // 1. Apply the Heighmap to all vertices/tangents/interiors. + // -------- + for (i = 0; i < PatchInfos.size(); ++i) + { + CPatchInfo &rPI = PatchInfos[i]; + + rPI.Patch.applyMatrix (Transfo); + + // Elevate the vertices. + CVector verticesBeforeHeightMap[4]; + for (j = 0; j < 4; ++j) + { + verticesBeforeHeightMap[j]= rPI.Patch.Vertices[j]; + rPI.Patch.Vertices[j].z += getHeight(rPI.Patch.Vertices[j].x, rPI.Patch.Vertices[j].y); + } + + // Interior and tangent are rotated to follow the heightmap normal, avoiding the "Stair Effect". + // Compute the matrix to apply to interiors and tangents. + CMatrix tgMatrix[4]; + for (j = 0; j < 4; ++j) + { + // compute the normal of the heightmap. + CVector hmapNormal= getHeightNormal(rPI.Patch.Vertices[j].x, rPI.Patch.Vertices[j].y); + + // Compute the rotation which transforms the original normal: (0,0,1), to this normal. + CAngleAxis angleAxis; + angleAxis.Axis= CVector::K ^ hmapNormal; + angleAxis.Angle= (float)asin(angleAxis.Axis.norm()); + angleAxis.Axis.normalize(); + + // build the matrix which transform the old tgt/interior to his newValue: + // newVertexPos+ rotate*(oldTgPos-oldVertexPos) + tgMatrix[j].identity(); + tgMatrix[j].translate(rPI.Patch.Vertices[j]); + tgMatrix[j].setRot( CQuat(angleAxis) ); + tgMatrix[j].translate(-verticesBeforeHeightMap[j]); + } + + // For all interior. + for (j = 0; j < 4; ++j) + rPI.Patch.Interiors[j]= tgMatrix[j] * rPI.Patch.Interiors[j]; + + // when j == 7 or 0 use vertex 0 for delta Z to ensure continuity of normals + // when j == 1 or 2 use vertex 1 + // when j == 3 or 4 use vertex 2 + // when j == 5 or 6 use vertex 3 + for (j = 0; j < 8; ++j) + { + // get the correct vertex + uint vertexId= ((j+1)/2)%4; + // apply the tgMatrix to the tangent + rPI.Patch.Tangents[j]= tgMatrix[vertexId] * rPI.Patch.Tangents[j]; + } + + for (j = 0; j < 4; ++j) + rPI.BindEdges[j].ZoneId = nZoneId; + } + + + // 2. For all binds, reset the position of near vertices/tangents/interiors. Must do it at last + // -------- + bool bindVertexModified= true; + // Since this is a recursive problem (binded patchs may bind other patchs), do it unitl all vertices no more move :) + while(bindVertexModified) + { + bindVertexModified= false; + for (i = 0; i < PatchInfos.size(); ++i) + { + CPatchInfo &rPI = PatchInfos[i]; + + // For all edges + for (j = 0; j < 4; ++j) + { + uint numBinds= rPI.BindEdges[j].NPatchs; + // If this edge is binded on 2 or 4 patches. + if( numBinds==2 || numBinds==4 ) + { + // compute the 4 or 8 tangents along the edge (in CCW) + CVector subTangents[8]; + computeSubdividedTangents(numBinds, rPI.Patch, j, subTangents); + + + // For all vertex to bind: 1 or 3. + for(uint vb=0; vb D + swap(rPI.Patch.Vertices[1], rPI.Patch.Vertices[2]); // B <-> C + + swap(rPI.Patch.Tangents[0], rPI.Patch.Tangents[5]); // ab <-> dc + swap(rPI.Patch.Tangents[1], rPI.Patch.Tangents[4]); // ba <-> cd + swap(rPI.Patch.Tangents[2], rPI.Patch.Tangents[3]); // bc <-> cb + swap(rPI.Patch.Tangents[7], rPI.Patch.Tangents[6]); // ad <-> da + + swap(rPI.Patch.Interiors[0], rPI.Patch.Interiors[3]); // ia <-> id + swap(rPI.Patch.Interiors[1], rPI.Patch.Interiors[2]); // ib <-> ic + + // Flip the base vertice + swap(rPI.BaseVertices[0], rPI.BaseVertices[3]); + swap(rPI.BaseVertices[1], rPI.BaseVertices[2]); + + // Flip bind edge only AB and CD + swap(rPI.BindEdges[0], rPI.BindEdges[2]); + + // Flip bind edge content only if multiple bind + for (j = 0; j < 4; j++) + { + if (rPI.BindEdges[j].NPatchs == 2) + { + swap (rPI.BindEdges[j].Next[0], rPI.BindEdges[j].Next[1]); + swap (rPI.BindEdges[j].Edge[0], rPI.BindEdges[j].Edge[1]); + } + if (rPI.BindEdges[j].NPatchs == 4) + { + swap (rPI.BindEdges[j].Next[0], rPI.BindEdges[j].Next[3]); + swap (rPI.BindEdges[j].Next[1], rPI.BindEdges[j].Next[2]); + + swap (rPI.BindEdges[j].Edge[0], rPI.BindEdges[j].Edge[3]); + swap (rPI.BindEdges[j].Edge[1], rPI.BindEdges[j].Edge[2]); + } + } + + for (j = 0; j < 4; ++j) + { + uint32 nNbPatch = rPI.BindEdges[j].NPatchs == 5 ? 1 : rPI.BindEdges[j].NPatchs; + for (k = 0; k < nNbPatch; ++k) + { + if (rPI.BindEdges[j].Edge[k] == 0) + rPI.BindEdges[j].Edge[k] = 2; + else if (rPI.BindEdges[j].Edge[k] == 2) + rPI.BindEdges[j].Edge[k] = 0; + } + } + + // Tile switching + for (j = 0; j < (uint32)(rPI.OrderS/2); ++j) + { + for (k = 0; k < rPI.OrderT; ++k) + { + swap(rPI.Tiles[j+k*rPI.OrderS], rPI.Tiles[(rPI.OrderS-1-j)+k*rPI.OrderS]); + } + } + + for (j = 0; j < (uint32)((rPI.OrderS+1)/2); ++j) + { + for (k = 0; k < (uint32)(rPI.OrderT+1); ++k) + { + swap(rPI.TileColors [j+k*(rPI.OrderS+1)], rPI.TileColors[(rPI.OrderS-j)+k*(rPI.OrderS+1)]); + } + } + } + + // Extra code for Rotating the zone. + //============================= + + // Rotate all tile elements in CW (because zones are turned in CCW) + // If zone flipped rotate tile elements by 180° + set allnames; // Debug + for (i = 0; i < PatchInfos.size(); ++i) + { + CPatchInfo &rPI = PatchInfos[i]; + + for (j = 0; j < rPI.Tiles.size(); ++j) + { + + int tileID, tileSet; + unsigned int tileIDun; + CTileBank::TTileType type; + CTileSet *pTS; + unsigned int nbOfRot; + + // Is the tile is painted ? + if (rPI.Tiles[j].Tile[0] == 65535) + continue; + + // Rotate Tiles + // Invert rotation effect on transition + for (pass = 0; pass < 3; ++pass) + { + if (rPI.Tiles[j].Tile[pass] == NL_TILE_ELM_LAYER_EMPTY) + break; + uint8 ori = rPI.Tiles[j].getTileOrient (pass); + + // Invert rotation effect on transition + _ZeTileBank->getTileXRef(rPI.Tiles[j].Tile[pass], tileSet, tileID, type); + pTS = _ZeTileBank->getTileSet (tileSet); + tileIDun = rPI.Tiles[j].Tile[pass]; + nbOfRot = rPI.Tiles[j].getTileOrient (pass); + if (!pTS->getOriented()) + { + transformTile (*_ZeTileBank, tileIDun, nbOfRot, (nFlip == 1), (4-nRot)%4); + } + else + { + transformTile (*_ZeTileBank, tileIDun, nbOfRot, (nFlip == 1), 0); + } + rPI.Tiles[j].Tile[pass] = tileIDun; + // Rotate tile + rPI.Tiles[j].setTileOrient (pass, nbOfRot); + } + + bool is256x256; + uint8 uvOff; + rPI.Tiles[j].getTile256Info (is256x256, uvOff); + if (is256x256) + { + unsigned int unCase = uvOff; + transform256Case (*_ZeTileBank, unCase, 0, (nFlip == 1), (4-nRot)%4); + rPI.Tiles[j].setTile256Info (true, unCase); + } + } + } + + zeZone.build (nZoneId, PatchInfos, BorderVertices); +}*/ + +/* +CLandscape gLand; +bool gLandInited = false; +*/ + + +// --------------------------------------------------------------------------- +void CExport::buildTransfo(sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip, CMatrix &posTransfo, CQuat &rotTransfo) +{ + // we don't use a single matrix because we don't want to apply a mirror on meshs + rotTransfo = CQuat(CVector::K, (float)(nRot * Pi / 2.0f)); + + posTransfo.setRot(rotTransfo); + posTransfo.setPos(CVector(nPosX * _Options->CellSize, (nPosY) * _Options->CellSize, 0.0f)); + if (nFlip == 1) + posTransfo.scale(CVector(-1.0f, 1.0f, 1.0f)); +} + +// --------------------------------------------------------------------------- +void CExport::transformIG (CInstanceGroup &ig, sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip) +{ + uint k; + CQuat rotTransfo; + CMatrix transformation; + + buildTransfo(nPosX, nPosY, nRot, nFlip, transformation, rotTransfo); + + /////////////// + // instances // + /////////////// + + for (k = 0; k < ig.getNumInstance(); ++k) + { + /* CInstanceGroup::CInstance &igi = ig.getInstance(k); + igi.Pos = transformation * igi.Pos; + igi.Rot = rotTransfo * igi.Rot; */ + + // add height map influence + //igi.Pos.z += getHeight(igi.Pos.x, igi.Pos.y); + + // Instance + CInstanceGroup::CInstance &igi = ig.getInstance(k); + + // Get the previous instance matrix + CMatrix previousMt; + previousMt.identity (); + previousMt.setRot(igi.Rot); + previousMt.setPos(igi.Pos); + previousMt.scale(igi.Scale); + + // Compose the matrix + previousMt = transformation * previousMt; + + // Extract the rotation and pos + igi.Rot = previousMt.getRot (); + igi.Pos = previousMt.getPos (); + + // Extract the scale + CMatrix scaleMatrix; + scaleMatrix.identity (); + scaleMatrix.setRot (igi.Rot); + scaleMatrix.invert (); + scaleMatrix = scaleMatrix * previousMt; + igi.Scale.set (scaleMatrix.getI ().x, scaleMatrix.getJ ().y, scaleMatrix.getK ().z); + } + + ////////////////// + // point lights // + ////////////////// + + for (k = 0; k < ig.getNumPointLights(); ++k) + { + CPointLightNamed &plm = ig.getPointLightNamed(k); + plm.setPosition(transformation * plm.getPosition()); + + // add height map influence + // plm.setPosition(plm.getPosition() + CVector::K * getHeight(plm.getPosition().x, plm.getPosition().y)); + } + +} + + +// --------------------------------------------------------------------------- +void CExport::transformCMB (NLPACS::CCollisionMeshBuild &cmb,sint32 nPosX,sint32 nPosY,uint8 nRot,uint8 nFlip) +{ + CQuat rotTransfo; + CMatrix posTransfo; + buildTransfo(nPosX, nPosY, nRot, nFlip, posTransfo, rotTransfo); + for(std::vector::iterator it = cmb.Vertices.begin(); it != cmb.Vertices.end(); ++it) + { + *it = posTransfo * *it; + } +} + +// --------------------------------------------------------------------------- +void CExport::cutZone (NL3D::CZone &bigZone, NL3D::CZone &bigZoneNoHeightmap, NL3D::CZone &unitZone, NL3D::CZone &unitZoneNoHeightmap, + sint32 nPosX, sint32 nPosY, vector &PatchTransfered, const vector &bb, vector &SrcPI, + vector &SrcPINoHeightmap, SPiece &sMask, vector &BorderVertices, + vector &BorderVerticesNoHeightmap, sint32 baseX, sint32 baseY) +{ + string DstZoneFileName = getZoneNameFromXY (nPosX, nPosY); + + uint32 i, j, k, l, m; + vector DstPI; + vector DstPINoHeightmap; + + sint32 nZoneX = nPosX; + sint32 nZoneY = -1 - nPosY; + uint16 nZoneId = nZoneX+(nZoneY*256); + + float rMinX = nPosX * _Options->CellSize; + float rMaxX = (1+nPosX) * _Options->CellSize; + float rMinY = nPosY * _Options->CellSize; + float rMaxY = (1+nPosY) * _Options->CellSize; + + map OldToNewPatchId; // Used to convert old patch id to new patch id + + for (i = 0; i < SrcPI.size(); ++i) + if (!PatchTransfered[i]) // If patch not already transfered in a zone unit + { + CPatchInfo &rPI = SrcPI[i]; + CPatchInfo &rPINoHeightmap = SrcPINoHeightmap[i]; + + // Is the Patch contained in the current mask ? Center of bbox tested + if ((bb[i].getCenter().x >= rMinX)&&(bb[i].getCenter().x <= rMaxX)&& + (bb[i].getCenter().y >= rMinY)&&(bb[i].getCenter().y <= rMaxY)) + { + for (j = 0; j < 4; ++j) + { + rPI.BindEdges[j].ZoneId = nZoneId; + rPINoHeightmap.BindEdges[j].ZoneId = nZoneId; + } + + PatchTransfered[i] = true; + DstPI.push_back (rPI); + DstPINoHeightmap.push_back (rPINoHeightmap); + OldToNewPatchId.insert (pair(i, (int)DstPI.size()-1)); + } + } + + // Look for patches out of the mask attached to a patch in this zone + bool foundOne; + do + { + foundOne = false; + for (i = 0; i < SrcPI.size(); ++i) + { + // Not yet transfered ? + if (!PatchTransfered[i]) // If patch not already transfered in a zone unit + { + // Get the center of the zone + sint x = (sint)(floor(bb[i].getCenter().x / _Options->CellSize)) - baseX; + sint y = (sint)(floor(bb[i].getCenter().y / _Options->CellSize)) - baseY; + + // Not in the mask ? + bool inTheMask = (x>=0) && (x<(sint)sMask.w) && (y>=0) && (y<(sint)sMask.h); + if (!inTheMask || !sMask.Tab[x+y*sMask.w]) + { + // Attached to a patch in this zone ? + CPatchInfo &rPI = SrcPI[i]; + CPatchInfo &rPINoHeightmap = SrcPINoHeightmap[i]; + for (j = 0; j < 4; ++j) + { + // Binded ? + if (rPI.BindEdges[j].NPatchs) + { + // Number of others + uint otherCount = rPI.BindEdges[j].NPatchs; + if (rPI.BindEdges[j].NPatchs == 5) + otherCount = 1; + + // For each other patch + for (k=0; k(i, (int)DstPI.size()-1)); + foundOne = true; + break; + } + } + if (k(next, (int)DstPI.size()-1)); + PatchTransfered[next] = true; + } + } + + if ((DstPI[i].BindEdges[j].NPatchs == 2) || (DstPI[i].BindEdges[j].NPatchs == 4)) + { + for (k = 0; k < DstPI[i].BindEdges[j].NPatchs; ++k) + { + uint next = DstPI[i].BindEdges[j].Next[k]; + if (!PatchTransfered[next]) + { + CPatchInfo &rPITmp = SrcPI[next]; + CPatchInfo &rPITmpNoHeightmap = SrcPINoHeightmap[next]; + for (m = 0; m < 4; ++m) + { + rPITmp.BindEdges[m].ZoneId = nZoneId; + rPITmpNoHeightmap.BindEdges[m].ZoneId = nZoneId; + } + DstPI.push_back (rPITmp); + DstPINoHeightmap.push_back (rPITmpNoHeightmap); + OldToNewPatchId.insert (pair(next, (int)DstPI.size()-1)); + PatchTransfered[next] = true; + } + } + } + } + } + + // Do it until no more patch added + if (nPreviousDstPISize == DstPI.size()) + break; + nPreviousDstPISize = (uint32)DstPI.size(); + } + + for (i = 0; i < DstPI.size(); ++i) + { + CPatchInfo &rPI = DstPI[i]; + CPatchInfo &rPINoHeightmap = DstPINoHeightmap[i]; + for (j = 0; j < 4; ++j) + { + if ((rPI.BindEdges[j].NPatchs == 1) || (rPI.BindEdges[j].NPatchs == 5)) + { + map::iterator it = OldToNewPatchId.find (rPI.BindEdges[j].Next[0]); + if (it == OldToNewPatchId.end()) + { + if (rPI.BindEdges[j].NPatchs == 5) + { + if (_ExportCB != NULL) + _ExportCB->dispError (string("Continuity problem in zone ") + DstZoneFileName); + } + else + { + rPI.BindEdges[j].NPatchs = 0; + rPINoHeightmap.BindEdges[j].NPatchs = 0; + } + } + else + { + rPI.BindEdges[j].Next[0] = it->second; + rPINoHeightmap.BindEdges[j].Next[0] = it->second; + } + } + + if ((rPI.BindEdges[j].NPatchs == 2) || (rPI.BindEdges[j].NPatchs == 4)) + { + for (k = 0; k < rPI.BindEdges[j].NPatchs; ++k) + { + map::iterator it = OldToNewPatchId.find (rPI.BindEdges[j].Next[k]); + if (it == OldToNewPatchId.end()) + { + if (_ExportCB != NULL) + _ExportCB->dispError (string("Continuity problem in zone ") + DstZoneFileName); + } + else + { + rPI.BindEdges[j].Next[k] = it->second; + rPINoHeightmap.BindEdges[j].Next[k] = it->second; + } + } + } + } + } + + unitZone.build (nZoneId, DstPI, BorderVertices); + unitZoneNoHeightmap.build (nZoneId, DstPINoHeightmap, BorderVerticesNoHeightmap); +/* { // Debug + if (!gLandInited) + { + gLand.init(); + gLandInited = true; + } + + gLand.addZone(unitZone); + gLand.checkBinds(); + }*/ +} + + +// --------------------------------------------------------------------------- +void CExport::cutIG(CInstanceGroup &bigIG, CInstanceGroup &unitIG, sint32 nPosX, sint32 nPosY, SPiece &sMask, bool first, sint32 baseX, sint32 baseY) +{ + uint k; + string DstZoneFileName = getZoneNameFromXY (nPosX, nPosY); + + float rMinX = nPosX * _Options->CellSize; + float rMaxX = (1+nPosX) * _Options->CellSize; + float rMinY = nPosY * _Options->CellSize; + float rMaxY = (1+nPosY) * _Options->CellSize; + + CInstanceGroup::TInstanceArray instances; + std::vector portals; + std::vector clusters; + std::vector pointLightList; + + bool realTimeSuncontribution = bigIG.getRealTimeSunContribution(); + + /////////////// + // instances // + /////////////// + for (k = 0; k < bigIG.getNumInstance(); ++k) + { + CInstanceGroup::CInstance &igi = bigIG.getInstance(k); + const CVector &pos = igi.Pos; + if (pos.x >= rMinX && pos.x < rMaxX && pos.y >= rMinY && pos.y < rMaxY) + { + instances.push_back(igi); + } + + // First zone ? + if (first) + { + // Out of the mask ? + sint x = (sint)(floor(pos.x / _Options->CellSize)) - baseX; + sint y = (sint)(floor(pos.y / _Options->CellSize)) - baseY; + + // Not in the mask ? + bool inTheMask = (x>=0) && (x<(sint)sMask.w) && (y>=0) && (y<(sint)sMask.h); + if (!inTheMask || !sMask.Tab[x+y*sMask.w]) + { + instances.push_back(igi); + } + } + } + + //////////// + // lights // + //////////// + + const std::vector &lights = bigIG.getPointLightList(); + for (k = 0; k < lights.size(); ++k) + { + const CVector &pos = lights[k].getPosition(); + if (pos.x >= rMinX && pos.x < rMaxX && pos.y >= rMinY && pos.y < rMaxY) + { + pointLightList.push_back(lights[k]); + } + + // First zone ? + if (first) + { + // Out of the mask ? + sint x = (sint)(floor(pos.x / _Options->CellSize)) - baseX; + sint y = (sint)(floor(pos.y / _Options->CellSize)) - baseY; + + // Not in the mask ? + bool inTheMask = (x>=0) && (x<(sint)sMask.w) && (y>=0) && (y<(sint)sMask.h); + if (!inTheMask || !sMask.Tab[x+y*sMask.w]) + { + pointLightList.push_back(lights[k]); + } + } + } + + // build the resulting ig + unitIG.build(bigIG.getGlobalPos(), instances, portals, clusters, pointLightList); + unitIG.enableRealTimeSunContribution(realTimeSuncontribution); + +} + + +// --------------------------------------------------------------------------- +float CExport::getHeight (float x, float y) +{ + float deltaZ = 0.0f, deltaZ2 = 0.0f; + CRGBAF color; + sint32 SizeX = _ZoneMaxX - _ZoneMinX + 1; + sint32 SizeY = _ZoneMaxY - _ZoneMinY + 1; + + clamp (x, _Options->CellSize*_ZoneMinX, _Options->CellSize*(_ZoneMaxX+1)); + clamp (y, _Options->CellSize*_ZoneMinY, _Options->CellSize*(_ZoneMaxY+1)); + + if (_HeightMap != NULL) + { + color = _HeightMap->getColor ( (x-_Options->CellSize*_ZoneMinX)/(_Options->CellSize*SizeX), + 1.0f - ((y-_Options->CellSize*_ZoneMinY)/(_Options->CellSize*SizeY))); + color *= 255; + deltaZ = color.A; + deltaZ = deltaZ - 127.0f; // Median intensity is 127 + deltaZ *= _Options->ZFactor; + } + + if (_HeightMap2 != NULL) + { + color = _HeightMap2->getColor ( (x-_Options->CellSize*_ZoneMinX)/(_Options->CellSize*SizeX), + 1.0f - ((y-_Options->CellSize*_ZoneMinY)/(_Options->CellSize*SizeY))); + color *= 255; + deltaZ2 = color.A; + deltaZ2 = deltaZ2 - 127.0f; // Median intensity is 127 + deltaZ2 *= _Options->ZFactor2; + } + + return (deltaZ + deltaZ2); +} + +// --------------------------------------------------------------------------- +CRGBAF CExport::getColor (float x, float y) +{ + CRGBAF color = CRGBA::Black; + sint32 SizeX = _ZoneMaxX - _ZoneMinX + 1; + sint32 SizeY = _ZoneMaxY - _ZoneMinY + 1; + + clamp (x, _Options->CellSize*_ZoneMinX, _Options->CellSize*(_ZoneMaxX+1)); + clamp (y, _Options->CellSize*_ZoneMinY, _Options->CellSize*(_ZoneMaxY+1)); + + if (_ColorMap != NULL) + { + color = _ColorMap->getColor ( (x-_Options->CellSize*_ZoneMinX)/(_Options->CellSize*SizeX), + 1.0f - ((y-_Options->CellSize*_ZoneMinY)/(_Options->CellSize*SizeY))); + color *= 255; + } + + return color; +} + +// --------------------------------------------------------------------------- +void CExport::light (NL3D::CZone &zoneOut, NL3D::CZone &zoneIn) +{ + // Same as zone_lighter stand-alone exe + // ------------------------------------ + /* CZoneLighter zl; + CLandscape land; + CZoneLighter::CLightDesc ld; + vector obstacle; + vector listzone; + + ld.SkyContribution = false; + ld.Oversampling = CZoneLighter::CLightDesc::NoOverSampling; + ld.Shadow = false; + ld.Softshadow = false; + ld.NumCPU = 1; + ld.GridSize = 2; + + try + { + zl.init (); + land.init (); + land.TileBank = *_ZeTileBank; + land.initTileBanks(); + land.addZone (zoneIn); + + listzone.push_back(zoneIn.getZoneId()); + + zl.light (land, zoneOut, zoneIn.getZoneId(), ld, obstacle, listzone); + } + catch (const Exception &e) + { + if (_ExportCB != NULL) + _ExportCB->dispError (e.what()); + }*/ + + // Quickest version without noise + // ------------------------------ + + CLandscape land; + + land.init (); + land.TileBank = *_ZeTileBank; + land.initTileBanks(); + land.addZone (zoneIn); + + + vector vPI; + vector vBV; + uint32 i, j, k, m; + float s, t, val; + CVector n, l = CVector (1.0f, 1.0f, -1.0f); + vector vertices; + CVector v[4]; + + l.normalize(); + + CZone *dyn = land.getZone(zoneIn.getZoneId()); + uint32 numPatch = dyn->getNumPatchs(); + + zoneIn.retrieve (vPI, vBV); + + if (_Options->Light == 2) // Noise ? + for (i = 0; i < numPatch; ++i) + { + const CPatch *pCP = const_cast(dyn)->getPatch (i); + + CPatchInfo &rPI = vPI[i]; + vertices.resize((rPI.OrderT*4+1)*(rPI.OrderS*4+1)); + + for (k = 0; k < (uint32)(rPI.OrderT*4+1); ++k) + for (j = 0; j < (uint32)(rPI.OrderS*4+1); ++j) + { + s = (((float)j) / (rPI.OrderS*4)); + t = (((float)k) / (rPI.OrderT*4)); + vertices[j+k*(rPI.OrderS*4+1)] = pCP->computeVertex(s, t); + } + + for (k = 0; k < (uint32)(rPI.OrderT*4); ++k) + for (j = 0; j < (uint32)(rPI.OrderS*4); ++j) + { + v[0] = vertices[(j+0)+(k+0)*(rPI.OrderS*4+1)]; + v[1] = vertices[(j+1)+(k+0)*(rPI.OrderS*4+1)]; + v[2] = vertices[(j+1)+(k+1)*(rPI.OrderS*4+1)]; + v[3] = vertices[(j+0)+(k+1)*(rPI.OrderS*4+1)]; + + val = 0.0f; + for (m = 0; m < 4; ++m) + { + n = (v[(m+0)%4]-v[(m+2)%4])^(v[(m+0)%4]-v[(m+1)%4]); + n.normalize(); + val += 255.0f*(1.0f-n*l)/2.0f; + } + val = val / 4.0f; + clamp (val, 0.0f, 255.0f); + rPI.Lumels[j+k*rPI.OrderS*4] = (uint8)(val); + } + } + else // No noise + for (i = 0; i < numPatch; ++i) + { + const CPatch *pCP = const_cast(dyn)->getPatch (i); + CBezierPatch *pBP = pCP->unpackIntoCache(); + + CPatchInfo &rPI = vPI[i]; + + for (k = 0; k < (uint32)(rPI.OrderT*4); ++k) + for (j = 0; j < (uint32)(rPI.OrderS*4); ++j) + { + s = ((0.5f+(float)j) / (rPI.OrderS*4)); + t = ((0.5f+(float)k) / (rPI.OrderT*4)); + n = pBP->evalNormal (s, t); + val = 255.0f*(1.0f-n*l)/2.0f; + clamp (val, 0.0f, 255.0f); + rPI.Lumels[j+k*rPI.OrderS*4] = (uint8)(val); + } + } + + zoneOut.build (zoneIn.getZoneId(), vPI, vBV); +} + +// --------------------------------------------------------------------------- +string CExport::getZoneNameFromXY (sint32 x, sint32 y) +{ + string tmp; + + if ((y>0) || (y<-255) || (x<0) || (x>255)) + return "NOT VALID"; + tmp = toString(-y) + "_"; + tmp += ('A' + (x/26)); + tmp += ('A' + (x%26)); + return tmp; +} + +// --------------------------------------------------------------------------- +sint32 CExport::getXFromZoneName (const string &ZoneName) +{ + string xStr, yStr; + uint32 i = 0; + while (ZoneName[i] != '_') + { + yStr += ZoneName[i]; ++i; + if (i == ZoneName.size()) + return -1; + } + ++i; + while (i < ZoneName.size()) + { + xStr += ZoneName[i]; ++i; + } + return ((xStr[0] - 'A')*26 + (xStr[1] - 'A')); +} + +// --------------------------------------------------------------------------- +sint32 CExport::getYFromZoneName (const string &ZoneName) +{ + string xStr, yStr; + uint32 i = 0; + while (ZoneName[i] != '_') + { + yStr += ZoneName[i]; ++i; + if (i == ZoneName.size()) + return 1; + } + ++i; + while (i < ZoneName.size()) + { + xStr += ZoneName[i]; ++i; + } + return -atoi(yStr.c_str()); +} + +// --------------------------------------------------------------------------- +void CExport::transformCMB (const std::string &name, const NLMISC::CMatrix &transfo, bool verbose) const +{ + if (name.empty()) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Can't load cmb : the name is empty"); + return; + } + std::string cmbNoExtension = CFile::getFilenameWithoutExtension(name); + std::string cmbName = CPath::lookup(cmbNoExtension + ".cmb" , false, false, false); + if (cmbName.empty()) + { + if ((_ExportCB != NULL) && verbose) + _ExportCB->dispWarning("Can't find " + cmbNoExtension + ".cmb"); + return; + } + CIFile inStream; + if (inStream.open(cmbName)) + { + try + { + CCollisionMeshBuild cmb; + cmb.serial(inStream); + // translate and save + cmb.transform (transfo); + COFile outStream; + std::string outFileName = _Options->OutCMBDir +"/" + cmbNoExtension + ".cmb"; + if (!outStream.open(outFileName)) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Couldn't open " + outFileName + "for writing, not exporting"); + } + else + { + try + { + cmb.serial(outStream); + outStream.close(); + } + catch (const EStream &e) + { + outStream.close(); + if (_ExportCB != NULL) + { + _ExportCB->dispWarning("Error while writing " + outFileName); + _ExportCB->dispWarning(e.what()); + } + } + } + inStream.close(); + } + catch (const EStream &e) + { + inStream.close(); + if (_ExportCB != NULL) + { + _ExportCB->dispWarning("Error while reading " + cmbName); + _ExportCB->dispWarning(e.what()); + } + } + } + else + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Unable to open " + cmbName); + } +} + +// --------------------------------------------------------------------------- +void CExport::transformAdditionnalIG (const std::string &name, const NLMISC::CMatrix &transfo, const NLMISC::CQuat &rotTransfo) const +{ + if (name.empty()) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Can't load cmb : the name is empty"); + return; + } + std::string igNoExtension = CFile::getFilenameWithoutExtension(name); + std::string igName = CPath::lookup(igNoExtension + ".ig" , false, false, false); + if (igName.empty()) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Can't find " + igNoExtension + ".cmb"); + return; + } + CIFile inStream; + if (inStream.open(igName)) + { + try + { + CInstanceGroup ig, igOut; + ig.serial(inStream); + + CVector globalPos; + CInstanceGroup::TInstanceArray IA; + std::vector Clusters; + std::vector Portals; + std::vector PLN; + + ig.retrieve(globalPos, IA, Clusters, Portals, PLN); + bool realTimeSuncontribution = ig.getRealTimeSunContribution(); + + uint k; + // elevate instance + for(k = 0; k < IA.size(); ++k) + { + IA[k].Pos = transfo * IA[k].Pos; + IA[k].Rot = rotTransfo * IA[k].Rot; + } + // lights + for(k = 0; k < PLN.size(); ++k) + { + PLN[k].setPosition(transfo * PLN[k].getPosition()); + } + // portals + std::vector portal; + for(k = 0; k < Portals.size(); ++k) + { + Portals[k].getPoly(portal); + for(uint l = 0; l < portal.size(); ++l) + { + portal[l] = transfo * portal[l]; + } + Portals[k].setPoly(portal); + } + + // clusters + for(k = 0; k < Clusters.size(); ++k) + { + Clusters[k].applyMatrix (transfo); + } + + + + igOut.build(globalPos, IA, Clusters, Portals, PLN); + igOut.enableRealTimeSunContribution(realTimeSuncontribution); + + COFile outStream; + std::string outFileName = _Options->AdditionnalIGOutDir +"/" + igNoExtension + ".ig"; + if (!outStream.open(outFileName)) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Couldn't open " + outFileName + "for writing, not exporting"); + } + else + { + try + { + igOut.serial(outStream); + outStream.close(); + } + catch (const EStream &e) + { + outStream.close(); + if (_ExportCB != NULL) + { + _ExportCB->dispWarning("Error while writing " + outFileName); + _ExportCB->dispWarning(e.what()); + } + } + } + inStream.close(); + } + catch (const EStream &e) + { + inStream.close(); + if (_ExportCB != NULL) + { + _ExportCB->dispWarning("Error while reading " + igName); + _ExportCB->dispWarning(e.what()); + } + } + } + else + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Unable to open " + igName); + } +} + +// --------------------------------------------------------------------------- +void CExport::exportCMBAndAdditionnalIGs() +{ + if (!_Options->ExportCollisions && !_Options->ExportCollisions) return; + CSmartPtr continent = loadContinent(_Options->ContinentFile); + if (!continent) return; + + NLGEORGES::UFormElm *villages; + if (!continent->getRootNode ().getNodeByName (&villages, "Villages") || !villages) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Cant find villages in a continent form"); + return; + } + + uint size; + nlverify (villages->getArraySize (size)); + + for(uint k = 0; k < size; ++k) + { + NLGEORGES::UFormElm *village; + if (!villages->getArrayNode (&village, k) || !village) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Cant get a village "); + continue; + } + + // get position of village + float altitude; + if (!village->getValueByName (altitude, "Altitude")) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Cant get a village position"); + continue; + } + + // get rotation of village + sint32 rotation; + if (!village->getValueByName (rotation, "Rotation")) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Cant get a village rotation"); + continue; + } + + // get width and height of village + uint32 width; + if (!village->getValueByName (width, "Width")) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Cant get a village width"); + continue; + } + + // get width and height of village + uint32 height; + if (!village->getValueByName (height, "Height")) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Cant get a village height"); + continue; + } + + // get position of village + std::string zoneName; + if (!village->getValueByName (zoneName, "Zone")) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Cant get a village name"); + continue; + } + + zoneName = strupr(zoneName); + // + sint32 x = CExport::getXFromZoneName(zoneName), y = CExport::getYFromZoneName(zoneName); + CVector pos(160.f * x, 160.f * y, altitude + getHeight(160.f * x, 160.f * y)); + + // *** Build the transformation + CMatrix transfo; + CQuat rotTransfo; + rotTransfo.identity (); + transfo.identity (); + + // Rotation + float angle = (float)rotation * (float)Pi / 2.f; + transfo.rotateZ (angle); + rotTransfo = CQuat (CVector::K, angle); + + // Add translation + switch (rotation&3) + { + case 0: + transfo.setPos (pos); + break; + case 1: + transfo.setPos (pos+CVector (160.f * height, 0, 0)); + break; + case 2: + transfo.setPos (pos+CVector (160.f * width, 160.f * height, 0)); + break; + case 3: + transfo.setPos (pos+CVector (0, 160.f * width, 0)); + break; + } + + // process ig / cmb of the village + NLGEORGES::UFormElm *igNamesItem; + if (!village->getNodeByName (&igNamesItem, "IgList") || !igNamesItem) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Cant get village ig list"); + continue; + } + + uint sizeIg; + nlverify (igNamesItem->getArraySize (sizeIg)); + + std::string igName; + + // For each children + for(uint k = 0; k < sizeIg; ++k) + { + // Get the aray element + const NLGEORGES::UFormElm *currIg; + if (igNamesItem->getArrayNode (&currIg, k) && currIg) + { + const NLGEORGES::UFormElm *igNameItem; + if (!currIg->getNodeByName (&igNameItem, "IgName") || !igNameItem) + { + nlwarning("Unable to get village name from a form"); + continue; + } + + if (igNameItem->getValue (igName)) + { + if (_Options->ExportCollisions) + { + transformCMB (igName, transfo, true); + + // Try to export alternative cmb like ig#0.cmb, ig#1.cmb, ig#2.cmb ... ig#9.cmb + std::string cmbNoExtension = CFile::getFilenameWithoutExtension(igName) + "#"; + uint alt; + for (alt=0; alt<10; alt++) + transformCMB (cmbNoExtension+toString (alt), transfo, false); + } + if (_Options->ExportAdditionnalIGs) transformAdditionnalIG (igName, transfo, rotTransfo); + } + else + { + nlwarning("Unable to get village name from a form"); + } + } + } + + } + return; +} + + +// --------------------------------------------------------------------------- +NLGEORGES::UForm* CExport::loadContinent(const std::string &name) const +{ + if (!NLMISC::CFile::fileExists(name)) + { + if (_ExportCB != NULL) + _ExportCB->dispWarning("Can't find " + name); + return NULL; + } + + UForm *form; + if (!(form = _FormLoader->loadForm (name.c_str ()))) + { + if (_ExportCB != NULL) + { + _ExportCB->dispWarning("Unable to load continent form : " + name); + } + return NULL; + } + + return form; +} + + + +// *************************************************************************** +void CExport::computeSubdividedTangents(uint numBinds, const NL3D::CBezierPatch &patch, uint edge, NLMISC::CVector subTangents[8]) +{ + // Subdivide the Bezier patch to get the correct tangents to apply to neighbors + CBezierPatch subPatchs1_2[2]; + CBezierPatch subPatchs1_4[4]; + + // subdivide on s if edge is horizontal + bool subDivideOnS= (edge&1)==1; + + // Subdivide one time. + if(subDivideOnS) patch.subdivideS(subPatchs1_2[0], subPatchs1_2[1]); + else patch.subdivideT(subPatchs1_2[0], subPatchs1_2[1]); + + // Subdivide again for bind 1/4. + if(numBinds==4) + { + if(subDivideOnS) + { + subPatchs1_2[0].subdivideS(subPatchs1_4[0], subPatchs1_4[1]); + subPatchs1_2[1].subdivideS(subPatchs1_4[2], subPatchs1_4[3]); + } + else + { + subPatchs1_2[0].subdivideT(subPatchs1_4[0], subPatchs1_4[1]); + subPatchs1_2[1].subdivideT(subPatchs1_4[2], subPatchs1_4[3]); + } + } + + // Now, fill the tangents according to edge. + bool invertPaSrc= edge>=2; + // Bind 1/2 case. + if(numBinds==2) + { + // 4 tangents to fill. + for(uint i=0;i<4;i++) + { + // get patch id from 0 to 1. + uint paSrcId= i/2; + // invert if edge is 2 or 3 + if(invertPaSrc) paSrcId= 1-paSrcId; + // get tg id in this patch. + uint tgSrcId= (i&1) + edge*2; + // fill result. + subTangents[i]= subPatchs1_2[paSrcId].Tangents[tgSrcId]; + } + } + // Bind 1/4 case. + else + { + // 8 tangents to fill. + for(uint i=0;i<8;i++) + { + // get patch id from 0 to 3. + uint paSrcId= i/2; + // invert if edge is 2 or 3 + if(invertPaSrc) paSrcId= 3-paSrcId; + // get tg id in this patch. + uint tgSrcId= (i&1) + edge*2; + // fill result. + subTangents[i]= subPatchs1_4[paSrcId].Tangents[tgSrcId]; + } + } +} + + +// *************************************************************************** +bool CExport::applyVertexBind(NL3D::CPatchInfo &pa, NL3D::CPatchInfo &oldPa, uint edgeToModify, bool startEdge, + const NLMISC::CMatrix &oldTgSpace, const NLMISC::CMatrix &newTgSpace, + const NLMISC::CVector &bindedPos, const NLMISC::CVector &bindedTangent ) +{ + // Get the vertex to modify according to edge/startEdge + uint vertexToModify= edgeToModify + (startEdge?0:1); + vertexToModify&=3; + + // If already moved, no-op + if(pa.Patch.Vertices[vertexToModify]==bindedPos) + return false; + else + { + // Change the vertex + pa.Patch.Vertices[vertexToModify]= bindedPos; + + // change the tangent, according to startEdge + pa.Patch.Tangents[edgeToModify*2 + (startEdge?0:1) ]= bindedTangent; + + // Must change the tangent which is on the other side of the vertex: + uint tgToModify= 8 + edgeToModify*2 + (startEdge?-1:+2); + tgToModify&=7; + /* To keep the same continuity aspect around the vertex, we compute the original tangent in a + special space: the Binded Patch Tangent Space. Once we have the original tangent in the original patch TgSpace, + we reapply it in the transformed patch TgSpace, to get the transformed tangent + */ + pa.Patch.Tangents[tgToModify]= newTgSpace * ( oldTgSpace.inverted() * oldPa.Patch.Tangents[tgToModify] ); + + + // Do the same to the associated interior. + pa.Patch.Interiors[vertexToModify]= newTgSpace * ( oldTgSpace.inverted() * oldPa.Patch.Interiors[vertexToModify] ); + + + // modified + return true; + } +} + + +// *************************************************************************** +NLMISC::CVector CExport::getHeightNormal (float x, float y) +{ + sint32 SizeX = _ZoneMaxX - _ZoneMinX + 1; + sint32 SizeY = _ZoneMaxY - _ZoneMinY + 1; + sint32 bmpW, bmpH; + + + // get width/height of the bitmap + if (_HeightMap != NULL) + { + bmpW= _HeightMap->getWidth(); + bmpH= _HeightMap->getHeight(); + } + else if (_HeightMap2 != NULL) + { + bmpW= _HeightMap2->getWidth(); + bmpH= _HeightMap2->getHeight(); + } + else + { + // no heightmap: unmodified normal + return CVector::K; + } + + + // compute a good delta to compute tangents of the heightmap: 1/10 of a pixel, avoiding precision problem. + float dx= ((_Options->CellSize*SizeX)/bmpW)/10; // eg: 160m/20pixels/10= 0.8 + float dy= ((_Options->CellSize*SizeY)/bmpH)/10; + + // compute tangent around the position. + float hc= getHeight(x,y); + float hx= getHeight(x+dx,y); + float hy= getHeight(x,y+dy); + CVector ds(dx,0,hx-hc); + CVector dt(0,dy,hy-hc); + + // compute the heightmap normal with the tangents + return (ds^dt).normed(); +} diff --git a/code/ryzom/tools/leveldesign/world_editor/land_export_lib/export.h b/code/ryzom/tools/leveldesign/world_editor/land_export_lib/export.h index 011505afd..e77406e39 100644 --- a/code/ryzom/tools/leveldesign/world_editor/land_export_lib/export.h +++ b/code/ryzom/tools/leveldesign/world_editor/land_export_lib/export.h @@ -1,223 +1,223 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef WE_EXPORT_H -#define WE_EXPORT_H - -// --------------------------------------------------------------------------- - - -#include -#include -#include "nel/misc/types_nl.h" -#include "nel/misc/rgba.h" -#include "nel/misc/aabbox.h" -#include "nel/3d/zone.h" - -// --------------------------------------------------------------------------- - -namespace NLMISC -{ - class IStream; - class CBitmap; - class CMatrix; - class CQuat; - class CVector; -} - -namespace NL3D -{ - class CZone; - struct CPatchInfo; - class CBezierPatch; - class CTileBank; - class CInstanceGroup; -} - -namespace NLLIGO -{ - class CZoneRegion; - class CZoneBank; - struct SPiece; -} - -namespace NLPACS -{ - class CCollisionMeshBuild ; -} - - -namespace NLGEORGES -{ - class UForm; - class UFormLoader; -} - - -// --------------------------------------------------------------------------- -// Export options -// --------------------------------------------------------------------------- -struct SExportOptions -{ - // Options saved - std::string OutZoneDir; - std::string OutIGDir; - std::string RefZoneDir; - std::string RefIGDir; - bool ExportCollisions; - bool ExportAdditionnalIGs; - std::string RefCMBDir; - std::string OutCMBDir; - std::string DFNDir; - std::string AdditionnalIGInDir; // villages.. - std::string AdditionnalIGOutDir; - - std::string ContinentFile; - std::string ContinentsDir; - - std::string LigoBankDir; - std::string TileBankFile; - - // The colormap file name - std::string ColorMapFile; - - std::string HeightMapFile; - float ZFactor; - std::string HeightMapFile2; - float ZFactor2; - - uint8 Light; // Roughly light the zone (0-none, 1-patch, 2-noise) - - std::string ZoneMin; - std::string ZoneMax; - - - - // Options not saved - NLLIGO::CZoneRegion *ZoneRegion; // The region to make - float CellSize; - float Threshold; - - // ======================================================================= - - SExportOptions (); - void serial (NLMISC::IStream& s); -}; - -// --------------------------------------------------------------------------- -// Export callback -// --------------------------------------------------------------------------- -// The user of CExport can be informed of what's happen in the export process with -// this class and can cancel the process by returning true in the isCanceled method. -class IExportCB -{ -public: - virtual bool isCanceled () = 0; // Tell the exporter if it must end as quick as possible - // Display callbacks - virtual void dispPass (const std::string &Text) = 0; // Pass (generate land, vegetable, etc...) - virtual void dispPassProgress (float percentage) = 0; // [ 0.0 , 1.0 ] - virtual void dispInfo (const std::string &Text) = 0; // Verbose - virtual void dispWarning (const std::string &Text) = 0; // Error but not critical - virtual void dispError (const std::string &Text) = 0; // Should block (misfunction) -}; - -// --------------------------------------------------------------------------- - -class CExport -{ - -public: - - CExport (); - ~CExport (); - - // EXPORT : - bool export_ (SExportOptions &options, IExportCB *expCB = NULL); - - static std::string getZoneNameFromXY (sint32 x, sint32 y); - static sint32 getXFromZoneName (const std::string &ZoneName); - static sint32 getYFromZoneName (const std::string &ZoneName); - -private: - SExportOptions *_Options; - IExportCB *_ExportCB; - NLLIGO::CZoneBank *_ZeZoneBank; - - NL3D::CTileBank *_ZeTileBank; - NLMISC::CBitmap *_HeightMap; - NLMISC::CBitmap *_HeightMap2; - sint32 _ZoneMinX, _ZoneMinY, _ZoneMaxX, _ZoneMaxY; - - // The colormap - NLMISC::CBitmap *_ColorMap; - - - NLGEORGES::UFormLoader *_FormLoader; -private: - /// export all cmb (directory is given in the options) - void exportCMBs(); - void exportAdditionnalIGs(); - void treatPattern (sint32 nPosX, sint32 nPosY, - std::vector &ZoneTreated, sint32 nMinX, sint32 nMinY, sint32 nStride); - /// build a non mirroring transfo (for mesh, collision mesh builds) - void buildTransfo(sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip, NLMISC::CMatrix &posTransfo, NLMISC::CQuat &rotTranfo); - void transformZone (NL3D::CZone &zeZone, sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip, bool computeHeightmap); - void transformIG (NL3D::CInstanceGroup &ig, sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip); - void transformCMB(NLPACS::CCollisionMeshBuild &cmb, sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip); - - /* - Add the Colormap to the user color of the zone - Performs USERCOLOR = USERCOLOR * (1-colormap.A) + colormap.RGB * colormap.A - */ - void addColorMap (NL3D::CZone &zeZone); - - - void cutZone (NL3D::CZone &bigZone, NL3D::CZone &bigZoneNoHeightmap, NL3D::CZone &unitZone, NL3D::CZone &unitZoneNoHeightmap, - sint32 nPosX, sint32 nPosY, std::vector &PatchTransfered, const std::vector &bb, std::vector &SrcPI, - std::vector &SrcPINoHeightmap, NLLIGO::SPiece &sMask, std::vector &BorderVertices, - std::vector &BorderVerticesNoHeightmap, sint32 baseX, sint32 baseY); - - void cutIG (NL3D::CInstanceGroup &bigIG, NL3D::CInstanceGroup &unitIG, sint32 nPosX, sint32 nPosY, NLLIGO::SPiece &sMask, bool first, - sint32 baseX, sint32 baseY); - - float getHeight (float x, float y); - - // Get a filtred RGBA color from _ColorMap - NLMISC::CRGBAF getColor (float x, float y); - - // return the normalized height normal. - NLMISC::CVector getHeightNormal (float x, float y); - - void light (NL3D::CZone &zoneOut, NL3D::CZone &zoneIn); - - NLGEORGES::UForm *loadContinent(const std::string &name) const; - void transformCMB (const std::string &cmbName, const NLMISC::CMatrix &transfo, bool verbose) const; - void transformAdditionnalIG (const std::string &igName, const NLMISC::CMatrix &transfo, const NLMISC::CQuat &rotTransfo) const; - void exportCMBAndAdditionnalIGs(); - - - // used by transformZone. compute sub tangents along an edge - void computeSubdividedTangents(uint numBinds, const NL3D::CBezierPatch &patch, uint edge, NLMISC::CVector subTangents[8]); - - // used by transformZone. return false if the vertex was same, and nop in this case. Else change the vertex, - // and move related tangent/interiors too - bool applyVertexBind(NL3D::CPatchInfo &pa, NL3D::CPatchInfo &oldPa, uint edgeToModify, bool startEdge, - const NLMISC::CMatrix &oldTgSpace, const NLMISC::CMatrix &newTgSpace, - const NLMISC::CVector &bindedPos, const NLMISC::CVector &bindedTangent ); - -}; - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef WE_EXPORT_H +#define WE_EXPORT_H + +// --------------------------------------------------------------------------- + + +#include +#include +#include "nel/misc/types_nl.h" +#include "nel/misc/rgba.h" +#include "nel/misc/aabbox.h" +#include "nel/3d/zone.h" + +// --------------------------------------------------------------------------- + +namespace NLMISC +{ + class IStream; + class CBitmap; + class CMatrix; + class CQuat; + class CVector; +} + +namespace NL3D +{ + class CZone; + struct CPatchInfo; + class CBezierPatch; + class CTileBank; + class CInstanceGroup; +} + +namespace NLLIGO +{ + class CZoneRegion; + class CZoneBank; + struct SPiece; +} + +namespace NLPACS +{ + class CCollisionMeshBuild ; +} + + +namespace NLGEORGES +{ + class UForm; + class UFormLoader; +} + + +// --------------------------------------------------------------------------- +// Export options +// --------------------------------------------------------------------------- +struct SExportOptions +{ + // Options saved + std::string OutZoneDir; + std::string OutIGDir; + std::string RefZoneDir; + std::string RefIGDir; + bool ExportCollisions; + bool ExportAdditionnalIGs; + std::string RefCMBDir; + std::string OutCMBDir; + std::string DFNDir; + std::string AdditionnalIGInDir; // villages.. + std::string AdditionnalIGOutDir; + + std::string ContinentFile; + std::string ContinentsDir; + + std::string LigoBankDir; + std::string TileBankFile; + + // The colormap file name + std::string ColorMapFile; + + std::string HeightMapFile; + float ZFactor; + std::string HeightMapFile2; + float ZFactor2; + + uint8 Light; // Roughly light the zone (0-none, 1-patch, 2-noise) + + std::string ZoneMin; + std::string ZoneMax; + + + + // Options not saved + NLLIGO::CZoneRegion *ZoneRegion; // The region to make + float CellSize; + float Threshold; + + // ======================================================================= + + SExportOptions (); + void serial (NLMISC::IStream& s); +}; + +// --------------------------------------------------------------------------- +// Export callback +// --------------------------------------------------------------------------- +// The user of CExport can be informed of what's happen in the export process with +// this class and can cancel the process by returning true in the isCanceled method. +class IExportCB +{ +public: + virtual bool isCanceled () = 0; // Tell the exporter if it must end as quick as possible + // Display callbacks + virtual void dispPass (const std::string &Text) = 0; // Pass (generate land, vegetable, etc...) + virtual void dispPassProgress (float percentage) = 0; // [ 0.0 , 1.0 ] + virtual void dispInfo (const std::string &Text) = 0; // Verbose + virtual void dispWarning (const std::string &Text) = 0; // Error but not critical + virtual void dispError (const std::string &Text) = 0; // Should block (misfunction) +}; + +// --------------------------------------------------------------------------- + +class CExport +{ + +public: + + CExport (); + ~CExport (); + + // EXPORT : + bool export_ (SExportOptions &options, IExportCB *expCB = NULL); + + static std::string getZoneNameFromXY (sint32 x, sint32 y); + static sint32 getXFromZoneName (const std::string &ZoneName); + static sint32 getYFromZoneName (const std::string &ZoneName); + +private: + SExportOptions *_Options; + IExportCB *_ExportCB; + NLLIGO::CZoneBank *_ZeZoneBank; + + NL3D::CTileBank *_ZeTileBank; + NLMISC::CBitmap *_HeightMap; + NLMISC::CBitmap *_HeightMap2; + sint32 _ZoneMinX, _ZoneMinY, _ZoneMaxX, _ZoneMaxY; + + // The colormap + NLMISC::CBitmap *_ColorMap; + + + NLGEORGES::UFormLoader *_FormLoader; +private: + /// export all cmb (directory is given in the options) + void exportCMBs(); + void exportAdditionnalIGs(); + void treatPattern (sint32 nPosX, sint32 nPosY, + std::vector &ZoneTreated, sint32 nMinX, sint32 nMinY, sint32 nStride); + /// build a non mirroring transfo (for mesh, collision mesh builds) + void buildTransfo(sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip, NLMISC::CMatrix &posTransfo, NLMISC::CQuat &rotTranfo); + void transformZone (NL3D::CZone &zeZone, sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip, bool computeHeightmap); + void transformIG (NL3D::CInstanceGroup &ig, sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip); + void transformCMB(NLPACS::CCollisionMeshBuild &cmb, sint32 nPosX, sint32 nPosY, uint8 nRot, uint8 nFlip); + + /* + Add the Colormap to the user color of the zone + Performs USERCOLOR = USERCOLOR * (1-colormap.A) + colormap.RGB * colormap.A + */ + void addColorMap (NL3D::CZone &zeZone); + + + void cutZone (NL3D::CZone &bigZone, NL3D::CZone &bigZoneNoHeightmap, NL3D::CZone &unitZone, NL3D::CZone &unitZoneNoHeightmap, + sint32 nPosX, sint32 nPosY, std::vector &PatchTransfered, const std::vector &bb, std::vector &SrcPI, + std::vector &SrcPINoHeightmap, NLLIGO::SPiece &sMask, std::vector &BorderVertices, + std::vector &BorderVerticesNoHeightmap, sint32 baseX, sint32 baseY); + + void cutIG (NL3D::CInstanceGroup &bigIG, NL3D::CInstanceGroup &unitIG, sint32 nPosX, sint32 nPosY, NLLIGO::SPiece &sMask, bool first, + sint32 baseX, sint32 baseY); + + float getHeight (float x, float y); + + // Get a filtred RGBA color from _ColorMap + NLMISC::CRGBAF getColor (float x, float y); + + // return the normalized height normal. + NLMISC::CVector getHeightNormal (float x, float y); + + void light (NL3D::CZone &zoneOut, NL3D::CZone &zoneIn); + + NLGEORGES::UForm *loadContinent(const std::string &name) const; + void transformCMB (const std::string &cmbName, const NLMISC::CMatrix &transfo, bool verbose) const; + void transformAdditionnalIG (const std::string &igName, const NLMISC::CMatrix &transfo, const NLMISC::CQuat &rotTransfo) const; + void exportCMBAndAdditionnalIGs(); + + + // used by transformZone. compute sub tangents along an edge + void computeSubdividedTangents(uint numBinds, const NL3D::CBezierPatch &patch, uint edge, NLMISC::CVector subTangents[8]); + + // used by transformZone. return false if the vertex was same, and nop in this case. Else change the vertex, + // and move related tangent/interiors too + bool applyVertexBind(NL3D::CPatchInfo &pa, NL3D::CPatchInfo &oldPa, uint edgeToModify, bool startEdge, + const NLMISC::CMatrix &oldTgSpace, const NLMISC::CMatrix &newTgSpace, + const NLMISC::CVector &bindedPos, const NLMISC::CVector &bindedTangent ); + +}; + #endif // WE_EXPORT_H \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/ligoscape.txt b/code/ryzom/tools/leveldesign/world_editor/ligoscape.txt index 5ff700815..a706381c2 100644 --- a/code/ryzom/tools/leveldesign/world_editor/ligoscape.txt +++ b/code/ryzom/tools/leveldesign/world_editor/ligoscape.txt @@ -1,43 +1,43 @@ -INTRODUCTION: -------------- - -Ligoscape is a landscape generation method based on the NeL landscape technology. - -PROJECT STRUCTURE: ------------------- - -The project is composed of : - -* Static Library * - This lib contains the shared code used by the plugin, the WorldEditor and the exporter. - It contains the main export code from 3dsmax to ligo and ligo to NeL. - -* 3dsmax Plugin * - This plugin is used to check, debug and export ligo data from max to WorldEditor - -* WorldEditor * - This tools is used to paint the landscape with base zone - The tool is in 2 part a DLL and a EXE because it is used in stand-alone mode and in - integrated mode (inside the Master Tool). It can be used to export (ligo to NeL). - -* Exporter * - This is just a little program in command line to export data from Ligo to Nel. - It is used in the build_game_data process. - -PROJECT DEPENDENCIES: ---------------------- - -// "ProjectA <- ProjectB" is for "ProjectA needs ProjectB" - -ligoscape_lib <- nel_3d -ligoscape_lib <- nel_misc - -ligoscape_plugin_max <- ligoscape_lib -ligoscape_plugin_max <- nel_patch_lib - -WorldEditor <- ligoscape_lib -WorldEditor <- nel_3d -WorldEditor <- nel_misc -WorldEditor <- nel_driver_opengl - +INTRODUCTION: +------------- + +Ligoscape is a landscape generation method based on the NeL landscape technology. + +PROJECT STRUCTURE: +------------------ + +The project is composed of : + +* Static Library * + This lib contains the shared code used by the plugin, the WorldEditor and the exporter. + It contains the main export code from 3dsmax to ligo and ligo to NeL. + +* 3dsmax Plugin * + This plugin is used to check, debug and export ligo data from max to WorldEditor + +* WorldEditor * + This tools is used to paint the landscape with base zone + The tool is in 2 part a DLL and a EXE because it is used in stand-alone mode and in + integrated mode (inside the Master Tool). It can be used to export (ligo to NeL). + +* Exporter * + This is just a little program in command line to export data from Ligo to Nel. + It is used in the build_game_data process. + +PROJECT DEPENDENCIES: +--------------------- + +// "ProjectA <- ProjectB" is for "ProjectA needs ProjectB" + +ligoscape_lib <- nel_3d +ligoscape_lib <- nel_misc + +ligoscape_plugin_max <- ligoscape_lib +ligoscape_plugin_max <- nel_patch_lib + +WorldEditor <- ligoscape_lib +WorldEditor <- nel_3d +WorldEditor <- nel_misc +WorldEditor <- nel_driver_opengl + WorldEditor_Exe <- WorldEditor \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/action.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/action.cpp index 71265a528..0baa3deb2 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/action.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/action.cpp @@ -1,2901 +1,2901 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" - -#include "action.h" -#include "world_editor.h" -#include "main_frm.h" -#include "world_editor_doc.h" -#include "editor_primitive.h" -#include "nel/sound/background_sound_manager.h" - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; - -// *************************************************************************** - -CActionLigoTile::CActionLigoTile (const CLigoData &data, const CDatabaseLocator &locator) -{ - // Backup new data - _New = data; - - // Backup old data - CWorldEditorDoc *doc = getDocument (); - doc->getLigoData (_Old, locator); - - // Backup locator - _Locator = locator; -} - -// *************************************************************************** - -void CActionLigoTile::undo () -{ - set (_Old); - invalidateLeftView (); - CWorldEditorDoc *doc = getDocument (); - doc->modifyDatabase (_Locator.getDatabaseIndex ()); -} - -// *************************************************************************** - -bool CActionLigoTile::redo () -{ - set (_New); - invalidateLeftView (); - CWorldEditorDoc *doc = getDocument (); - doc->modifyDatabase (_Locator.getDatabaseIndex ()); - return true; -} - -// *************************************************************************** - -void CActionLigoTile::set (const CLigoData &data) -{ - CWorldEditorDoc *doc = getDocument (); - NLLIGO::CZoneRegion ®ion = doc->_DataHierarchy[_Locator.getDatabaseIndex ()].ZoneRegion; - nlassert ((_Locator.XSubPrim >= region.getMinX ()) && (_Locator.XSubPrim <= region.getMaxX ()) && (_Locator.Y >= region.getMinY ()) && (_Locator.Y <= region.getMaxY ())); - - region.setPosX (_Locator.XSubPrim, _Locator.Y, data.PosX); - region.setPosY (_Locator.XSubPrim, _Locator.Y, data.PosY); - region.setName (_Locator.XSubPrim, _Locator.Y, data.ZoneName); - region.setRot (_Locator.XSubPrim, _Locator.Y, data.Rot); - region.setFlip (_Locator.XSubPrim, _Locator.Y, data.Flip); - region.setSharingMatNames (_Locator.XSubPrim, _Locator.Y, 0, data.SharingMatNames[0]); - region.setSharingMatNames (_Locator.XSubPrim, _Locator.Y, 1, data.SharingMatNames[1]); - region.setSharingMatNames (_Locator.XSubPrim, _Locator.Y, 2, data.SharingMatNames[2]); - region.setSharingMatNames (_Locator.XSubPrim, _Locator.Y, 3, data.SharingMatNames[3]); - region.setSharingCutEdges (_Locator.XSubPrim, _Locator.Y, 0, data.SharingCutEdges[0]); - region.setSharingCutEdges (_Locator.XSubPrim, _Locator.Y, 1, data.SharingCutEdges[1]); - region.setSharingCutEdges (_Locator.XSubPrim, _Locator.Y, 2, data.SharingCutEdges[2]); - region.setSharingCutEdges (_Locator.XSubPrim, _Locator.Y, 3, data.SharingCutEdges[3]); -} - -// *************************************************************************** - -CActionLigoMove::CActionLigoMove (uint index, sint32 deltaX, sint32 deltaY) -{ - _Index = index; - _DeltaX = deltaX; - _DeltaY = deltaY; -} - -// *************************************************************************** - -void CActionLigoMove::undo () -{ - CWorldEditorDoc *doc = getDocument (); - NLLIGO::CZoneRegion ®ion = doc->_DataHierarchy[_Index].ZoneRegion; - region.setMaxX (region.getMaxX () - _DeltaX); - region.setMinX (region.getMinX () - _DeltaX); - region.setMaxY (region.getMaxY () - _DeltaY); - region.setMinY (region.getMinY () - _DeltaY); - doc->modifyDatabase (_Index); -} - -// *************************************************************************** - -bool CActionLigoMove::redo () -{ - CWorldEditorDoc *doc = getDocument (); - NLLIGO::CZoneRegion ®ion = doc->_DataHierarchy[_Index].ZoneRegion; - region.setMaxX (region.getMaxX () + _DeltaX); - region.setMinX (region.getMinX () + _DeltaX); - region.setMaxY (region.getMaxY () + _DeltaY); - region.setMinY (region.getMinY () + _DeltaY); - doc->modifyDatabase (_Index); - return true; -} - -// *************************************************************************** - -CActionLigoResize::CActionLigoResize (uint index, sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY) -{ - _Index = index; - _NewMinX = newMinX; - _NewMaxX = newMaxX; - _NewMinY = newMinY; - _NewMaxY = newMaxY; - - // Backup old region zone - CWorldEditorDoc *doc = getDocument (); - _Old = doc->_DataHierarchy[_Index].ZoneRegion; -} - -// *************************************************************************** - -void CActionLigoResize::undo () -{ - // Restaure old region zone - CWorldEditorDoc *doc = getDocument (); - doc->_DataHierarchy[_Index].ZoneRegion = _Old; - doc->modifyDatabase (_Index); -} - -// *************************************************************************** - -bool CActionLigoResize::redo () -{ - // Get the zone region - CWorldEditorDoc *doc = getDocument (); - NLLIGO::CZoneRegion ®ion = doc->_DataHierarchy[_Index].ZoneRegion; - - sint32 i, j; - vector newZones; - newZones.resize ((1+_NewMaxX-_NewMinX)*(1+_NewMaxY-_NewMinY)); - - sint32 newStride = 1+_NewMaxX-_NewMinX; - sint32 Stride = 1+region.getMaxX ()-region.getMinX (); - - for (j = _NewMinY; j <= _NewMaxY; ++j) - for (i = _NewMinX; i <= _NewMaxX; ++i) - { - // Ref on the new value - CLigoData &data = newZones[(i-_NewMinX)+(j-_NewMinY)*newStride]; - - // In the old array ? - if ((i >= region.getMinX ())&&(i <= region.getMaxX ())&&(j >= region.getMinY ())&&(j <= region.getMaxY ())) - { - // Backup values - data.PosX = region.getPosX (i, j); - data.PosY = region.getPosY (i, j); - data.ZoneName = region.getName (i, j); - data.Rot = region.getRot (i, j); - data.Flip = region.getFlip (i, j); - data.SharingMatNames[0] = region.getSharingMatNames (i, j, 0); - data.SharingMatNames[1] = region.getSharingMatNames (i, j, 1); - data.SharingMatNames[2] = region.getSharingMatNames (i, j, 2); - data.SharingMatNames[3] = region.getSharingMatNames (i, j, 3); - data.SharingCutEdges[0] = region.getSharingCutEdges (i, j, 0); - data.SharingCutEdges[1] = region.getSharingCutEdges (i, j, 1); - data.SharingCutEdges[2] = region.getSharingCutEdges (i, j, 2); - data.SharingCutEdges[3] = region.getSharingCutEdges (i, j, 3); - } - else - { - // By default - data.PosX = 0; - data.PosY = 0; - data.ZoneName = ""; - data.Rot = 0; - data.Flip = 0; - data.SharingMatNames[0] = ""; - data.SharingMatNames[1] = ""; - data.SharingMatNames[2] = ""; - data.SharingMatNames[3] = ""; - data.SharingCutEdges[0] = 0; - data.SharingCutEdges[1] = 0; - data.SharingCutEdges[2] = 0; - data.SharingCutEdges[3] = 0; - } - } - region.resize (_NewMinX, _NewMaxX, _NewMinY, _NewMaxY); - - for (j = _NewMinY; j <= _NewMaxY; ++j) - for (i = _NewMinX; i <= _NewMaxX; ++i) - { - // Ref on the new value - const CLigoData &data = newZones[(i-_NewMinX)+(j-_NewMinY)*newStride]; - - region.setName (i, j, data.ZoneName); - region.setPosX (i, j, data.PosX); - region.setPosY (i, j, data.PosY); - region.setRot (i, j, data.Rot); - region.setFlip (i, j, data.Flip); - uint k; - for (k=0; k<4; k++) - { - region.setSharingMatNames (i, j, k, data.SharingMatNames[k]); - region.setSharingCutEdges (i, j, k, data.SharingCutEdges[k]); - } - } - - doc->modifyDatabase (_Index); - return true; -} - -// *************************************************************************** -// CActionImportPrimitive -// *************************************************************************** - -CActionImportPrimitive::CActionImportPrimitive (const char *oldPrimFile) -{ - _Filename = oldPrimFile; - _FirstLoad = true; -} - -// *************************************************************************** - -void CActionImportPrimitive::undo () -{ - // Check we have a primitive - CWorldEditorDoc *doc = getDocument (); - nlassert (doc->_DataHierarchy.size () > 0); - - // Remove back primitive - doc->_DataHierarchy.resize (doc->_DataHierarchy.size ()-1); - doc->_DataHierarchy.recomputePointerArray (); - - // Invalidate tools - getMainFrame ()->invalidateTools (); - InvalidateAllPrimitives (); - - // Modify files - doc->modifyProject (); -} - -// *************************************************************************** - -bool CActionImportPrimitive::redo () -{ - CWorldEditorDoc *doc = getDocument (); - - // First redo ? - if (_FirstLoad) - { - // Load the old primitive - try - { - // The file - CIFile fileIn; - if (fileIn.open (_Filename)) - { - // The region to load - NLLIGO::CPrimRegion region; - - // Load it - CIXml input; - input.init (fileIn); - region.serial (input); - - // Convert it - NLLIGO::CPrimitives Primitives; - Primitives.convert (region); - - if (_Filename.find("audio") != std::string::npos) - { - // import audio prim - - // Create an audio node - IPrimitive *audio = new CPrimNodeEditor; - std::string audioName = region.Name; - audioName = audioName.substr(0, audioName.find(".prim")); - audio->addPropertyByName ("name", new CPropertyString (audioName.c_str())); - audio->addPropertyByName ("class", new CPropertyString ("audio")); - - // Insert the audio node - _Primitive.RootNode->insertChild (audio); - - IPrimitive *sounds = new CPrimNodeEditor; - sounds->addPropertyByName ("name", new CPropertyString ("sounds")); - sounds->addPropertyByName ("class", new CPropertyString ("sounds")); - - // Insert the soundnode - audio->insertChild (sounds); - - IPrimitive *soundBanks = new CPrimNodeEditor; - soundBanks->addPropertyByName ("name", new CPropertyString ("sample_banks")); - soundBanks->addPropertyByName ("class", new CPropertyString ("sample_banks")); - - // Insert the soundnode - audio->insertChild (soundBanks); - - IPrimitive *envFx = new CPrimNodeEditor; - envFx->addPropertyByName ("name", new CPropertyString ("env_fx")); - envFx->addPropertyByName ("class", new CPropertyString ("env_fx")); - - // Insert the soundnode - audio->insertChild (envFx); - - // layer count count - uint count = Primitives.RootNode->getNumChildren (); - - for (uint i=0; igetChild (layer, i)); - - // Get the name - string layerName; - layer->getPropertyByName ("name", layerName); - - // Create a sound_folder node - IPrimitive *soundFolder = new CPrimNodeEditor; - soundFolder->addPropertyByName ("name", new CPropertyString (layerName.c_str ())); - soundFolder->addPropertyByName ("class", new CPropertyString ("sound_folder")); - - // Insert the sound folder node - sounds->insertChild (soundFolder); - - // sound count - uint soundCount = layer->getNumChildren (); - - // Make sounds - for (uint j=0; jgetChild (prim, j)); - - // Get the name - string rawName; - prim->getPropertyByName ("name", rawName); - string name; - uint layerId = 0; - - // extract the sound name and, optinaly, the layer id - uint n = std::count(rawName.begin(), rawName.end(), '-'); - std::vector splited; - - NLMISC::explode(rawName, string("-"), splited); - - if (n == 2) - { - // no layer spec - name = splited[1]; - } - else if (n==3) - { - // layer is specified - name = splited[2]; - layerId = 'a' - splited[1][0]; - clamp(layerId, 0u, NLSOUND::BACKGROUND_LAYER-1); - } - else - { - nlwarning("sound %s have a bad format. Ignoring", rawName.c_str()); - // skip this one - continue; - } - - char layerString[1024]; - sprintf(layerString, "layer_%u", layerId); - - // Path ? - const CPrimPathEditor *path = dynamic_cast (prim); - if (path) - { - // Copy the node - CPrimPathEditor *newPrim = new CPrimPathEditor; - *newPrim = *path; - newPrim->addPropertyByName ("class", new CPropertyString ("sound_path")); - newPrim->removePropertyByName("name"); - newPrim->addPropertyByName ("name", new CPropertyString (name.c_str())); - newPrim->addPropertyByName ("layer", new CPropertyString (layerString)); - - // Add the primitive - soundFolder->insertChild (newPrim); - } - else - { - // Zone ? - const CPrimZoneEditor *zone = dynamic_cast (prim); - if (zone) - { - // Copy the node - CPrimZoneEditor *newPrim = new CPrimZoneEditor; - *newPrim = *zone; - newPrim->addPropertyByName ("class", new CPropertyString ("sound_zone")); - newPrim->removePropertyByName("name"); - newPrim->addPropertyByName ("name", new CPropertyString (name.c_str())); - newPrim->addPropertyByName ("layer", new CPropertyString (layerString)); - - // Add the primitive - soundFolder->insertChild (newPrim); - } - else - { - // point ? - const CPrimPointEditor *point = dynamic_cast (prim); - if (zone) - { - // Copy the node - CPrimPointEditor *newPrim = new CPrimPointEditor; - *newPrim = *point; - newPrim->addPropertyByName ("class", new CPropertyString ("sound_point")); - newPrim->removePropertyByName("name"); - newPrim->addPropertyByName ("name", new CPropertyString (name.c_str())); - newPrim->addPropertyByName ("layer", new CPropertyString (layerString)); - - // Add the primitive - soundFolder->insertChild (newPrim); - } - } - } - } - } - } - else - { - // import flora prim - - // Flora count - uint count = Primitives.RootNode->getNumChildren (); - - // Make flora - for (uint i=0; igetChild (layer, i)); - - // Get the name - string layerName; - layer->getPropertyByName ("name", layerName); - - // Create a flora node - IPrimitive *flora = new CPrimNodeEditor; - flora->addPropertyByName ("name", new CPropertyString (layerName.c_str ())); - flora->addPropertyByName ("class", new CPropertyString ("flora")); - - // Insert the flora node - _Primitive.RootNode->insertChild (flora); - - // Flora count - uint floraCount = layer->getNumChildren (); - - // Make flora - for (uint j=0; jgetChild (prim, j)); - - // Get the name - string name; - prim->getPropertyByName ("name", name); - - // Path ? - const CPrimPathEditor *path = dynamic_cast (prim); - if (path) - { - // Copy the node - CPrimPathEditor *newPrim = new CPrimPathEditor; - *newPrim = *path; - newPrim->addPropertyByName ("class", new CPropertyString ("flora_path")); - - // Add the primitive - flora->insertChild (newPrim); - } - else - { - // Zone ? - const CPrimZoneEditor *zone = dynamic_cast (prim); - if (zone) - { - // Copy the node - CPrimZoneEditor *newPrim = new CPrimZoneEditor; - *newPrim = *zone; - newPrim->addPropertyByName ("class", new CPropertyString ("flora_zone")); - - // Add the primitive - flora->insertChild (newPrim); - } - } - } - } - } - - _FirstLoad = false; - } - else - { - theApp.errorMessage ("Can't open the file (%s) for reading.", _Filename.c_str ()); - return false; - } - } - catch (Exception& e) - { - theApp.errorMessage ("Error reading the file (%s) : (%s).", _Filename.c_str (), e.what ()); - return false; - } - } - - // Push back the primitive - doc->_DataHierarchy.push_back (CWorldEditorDoc::CDatabaseElement (CWorldEditorDoc::CDatabaseElement::Primitive)); - doc->_DataHierarchy.recomputePointerArray (); - doc->_DataHierarchy.back ().Primitives = _Primitive; - - // Update default values - doc->updateDefaultValues (doc->_DataHierarchy.size ()-1); - - // Invalidate tools - getMainFrame ()->invalidateTools (); - InvalidateAllPrimitives (); - - // Modify files - doc->modifyProject (); - - return true; -} - -// *************************************************************************** -// CActionLoadPrimitive -// *************************************************************************** - -CActionLoadPrimitive::CActionLoadPrimitive (const char *oldPrimFile) -{ - _Filename = oldPrimFile; - _FirstLoad = true; -} - -// *************************************************************************** - -void CActionLoadPrimitive::undo () -{ - // Check we have a primitive - CWorldEditorDoc *doc = getDocument (); - nlassert (doc->_DataHierarchy.size () > 0); - - // Remove back primitive - doc->_DataHierarchy.resize (doc->_DataHierarchy.size ()-1); - doc->_DataHierarchy.recomputePointerArray (); - InvalidateAllPrimitives (); - - // Invalidate tools - getMainFrame ()->invalidateTools (); - - // Modify files - doc->modifyProject (); -} - -// *************************************************************************** - -bool CActionLoadPrimitive::redo () -{ - CWorldEditorDoc *doc = getDocument (); - // First redo ? - if (_FirstLoad) - { - // Load the old primitive - try - { - // The file - CIFile fileIn; - if (fileIn.open (_Filename)) - { - // Load it - CIXml input; - input.init (fileIn); - - // Set the primitive context - CPrimitiveContext::instance().CurrentPrimitive = &_Primitive; - // Convert it - _Primitive.read (input.getRootNode (), _Filename.c_str (), theApp.Config); - - // cleanup context - CPrimitiveContext::instance().CurrentPrimitive = NULL; - - _FirstLoad = false; - } - else - { - theApp.errorMessage ("Can't open the file (%s) for reading.", _Filename.c_str ()); - return false; - } - } - catch (Exception& e) - { - theApp.errorMessage ("Error reading the file (%s) : (%s).", _Filename.c_str (), e.what ()); - return false; - } - } - - // Push back the primitive - doc->_DataHierarchy.push_back (CWorldEditorDoc::CDatabaseElement (CWorldEditorDoc::CDatabaseElement::Primitive)); - doc->_DataHierarchy.recomputePointerArray (); - doc->_DataHierarchy.back ().Primitives = _Primitive; - doc->_DataHierarchy.back ().Filename = _Filename; - doc->_DataHierarchy.back ().LastModifedTime = NLMISC::CFile::getFileModificationDate (_Filename); - - // Update default values - doc->updateDefaultValues (doc->_DataHierarchy.size ()-1); - - // Auto generate missing id - doc->resetUniqueID(*(doc->_DataHierarchy.back().Primitives.RootNode), true); - - // Invalidate tools - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); - - // Modify files - doc->modifyProject (); - - return true; -} - -// *************************************************************************** -// CActionNewPrimitive -// *************************************************************************** - -CActionNewPrimitive::CActionNewPrimitive () -{ -} - -// *************************************************************************** - -void CActionNewPrimitive::undo () -{ - CWorldEditorDoc *doc = getDocument (); - // Check we have a primitive - nlassert (doc->_DataHierarchy.size () > 0); - - // Remove back primitive - doc->_DataHierarchy.resize (doc->_DataHierarchy.size ()-1); - doc->_DataHierarchy.recomputePointerArray (); - - // Invalidate tools - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); - - // Modify files - doc->modifyProject (); -} - -// *************************************************************************** - -bool CActionNewPrimitive::redo () -{ - CWorldEditorDoc *doc = getDocument (); - // Push back the primitive - doc->_DataHierarchy.push_back (CWorldEditorDoc::CDatabaseElement (CWorldEditorDoc::CDatabaseElement::Primitive)); - doc->_DataHierarchy.recomputePointerArray (); - - // Invalidate tools - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); - - // Modify files - uint index = doc->_DataHierarchy.size ()-1; - doc->modifyProject (); - doc->modifyDatabase (index); - - return true; -} - -// *************************************************************************** -// CActionClearPrimitives -// *************************************************************************** - -CActionClearPrimitives::CActionClearPrimitives () -{ - // Copy the primitives - CWorldEditorDoc *doc = getDocument (); - _Primitives = doc->_DataHierarchy; -} - -// *************************************************************************** - -void CActionClearPrimitives::undo () -{ - CWorldEditorDoc *doc = getDocument (); - // Remove all the primitives - doc->_DataHierarchy = _Primitives; - - // Invalidate - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); - - // Modify files - doc->modifyProject (); -} - -// *************************************************************************** - -bool CActionClearPrimitives::redo () -{ - CWorldEditorDoc *doc = getDocument (); - // Remove all the primitives - doc->_DataHierarchy.clear (); - doc->_DataHierarchy.recomputePointerArray (); - - // Invalidate - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); - - // Modify files - doc->modifyProject (); - - return true; -} - -// *************************************************************************** -// CActionUnselectAll -// *************************************************************************** - -CActionUnselectAll::CActionUnselectAll () -{ - CWorldEditorDoc *doc = getDocument (); - doc->modifyPropertyDlg(); - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Primitive ? - if (locator.Primitive) - { - // Add this locator - _SelectedPrimitives.push_back (locator); - } - - ite++; - } -} - -// *************************************************************************** - -void CActionUnselectAll::undo () -{ - CWorldEditorDoc *doc = getDocument (); - for (uint i=0; i<_SelectedPrimitives.size (); i++) - { - // Get the locator pointer - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _SelectedPrimitives[i]); - - // Select the primitive - if (!getPrimitiveEditor(locator.Primitive)->getSelected()) -// if (const_cast(locator.Primitive)->addPropertyByName ("selected", new CPropertyString ())) - { - getPrimitiveEditor(locator.Primitive)->setSelected(true); - InvalidatePrimitive (locator, SelectionState); - invalidateLeftView (); - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - } - } -} - -// *************************************************************************** - -bool CActionUnselectAll::redo () -{ - CWorldEditorDoc *doc = getDocument (); - bool modified = false; - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Primitive ? - if (locator.Primitive) - { - // Remove selected flag - if (getPrimitiveEditor(locator.Primitive)->getSelected()) -// if (const_cast(locator.Primitive)->removePropertyByName ("selected")) - { - getPrimitiveEditor(locator.Primitive)->setSelected(false); - //modified = true; - InvalidatePrimitive (locator, SelectionState); - invalidateLeftView (); - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - } - } - - ite++; - } - - return modified; -} - -// *************************************************************************** -// CActionSelectAll -// *************************************************************************** - -CActionSelectAll::CActionSelectAll () -{ - CWorldEditorDoc *doc = getDocument (); - doc->modifyPropertyDlg(); - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Primitive ? - if (locator.Primitive) - { - // Add this locator - _SelectedPrimitives.push_back (locator); - } - - ite++; - } -} - -// *************************************************************************** - -void CActionSelectAll::undo () -{ - CWorldEditorDoc *doc = getDocument (); - CDatabaseLocatorPointer locator; - doc->getFirstLocator (locator); - do - { - // Primitive ? - if (locator.Primitive) - { - // Remove selected flag - if (getPrimitiveEditor(locator.Primitive)->getSelected()) -// if (const_cast(locator.Primitive)->removePropertyByName ("selected")) - { - getPrimitiveEditor(locator.Primitive)->setSelected(false); - InvalidatePrimitive (locator, SelectionState); - invalidateLeftView (); - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - } - } - } - while (locator.next ()); - - for (uint i=0; i<_SelectedPrimitives.size (); i++) - { - // Get the locator pointer - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _SelectedPrimitives[i]); - - // Select the primitive - if (!getPrimitiveEditor(locator.Primitive)->getSelected()) -// if (const_cast(locator.Primitive)->addPropertyByName ("selected", new CPropertyString ())) - { - getPrimitiveEditor(locator.Primitive)->setSelected(false); - InvalidatePrimitive (locator, SelectionState); - invalidateLeftView (); - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - } - } -} - -// *************************************************************************** - -bool CActionSelectAll::redo () -{ - bool modified = false; - CWorldEditorDoc *doc = getDocument (); - CDatabaseLocatorPointer locator; - doc->getFirstLocator (locator); - do - { - // Primitive ? - if (locator.Primitive) - { - // Remove selected flag - if (!getPrimitiveEditor(locator.Primitive)->getSelected()) -// if (const_cast(locator.Primitive)->addPropertyByName ("selected", new CPropertyString ())) - { - getPrimitiveEditor(locator.Primitive)->setSelected(true); - // modified = true; - InvalidatePrimitive (locator, SelectionState); - invalidateLeftView (); - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - } - } - } - while (locator.next ()); - - return modified; -} - -// *************************************************************************** -// CActionSelect -// *************************************************************************** - -CActionSelect::CActionSelect (const CDatabaseLocator &locator) -{ - getDocument()->modifyPropertyDlg(); - _Locator = locator; -} - -// *************************************************************************** - -void CActionSelect::undo () -{ - CWorldEditorDoc *doc = getDocument (); - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - if (locator.Primitive) - { - // Select it -// nlverify (const_cast(locator.Primitive)->removePropertyByName ("selected")); - getPrimitiveEditor(locator.Primitive)->setSelected(false); - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate selection - InvalidatePrimitive (locator, SelectionState); - invalidateLeftView (); - } -} - -// *************************************************************************** - -bool CActionSelect::redo () -{ - CWorldEditorDoc *doc = getDocument (); - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - if (locator.Primitive) - { - // Select it - if (!getPrimitiveEditor(locator.Primitive)->getSelected()) -// if (const_cast(locator.Primitive)->addPropertyByName ("selected", new CPropertyString ())) - { - getPrimitiveEditor(locator.Primitive)->setSelected(true); - // Invalidate selection - InvalidatePrimitive (locator, SelectionState); - invalidateLeftView (); - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - - // return true; - } - } - return false; -} - -// *************************************************************************** -// CActionUnselect -// *************************************************************************** - -CActionUnselect::CActionUnselect (const CDatabaseLocator &locator) -{ - getDocument()->modifyPropertyDlg(); - _Locator = locator; -} - -// *************************************************************************** - -void CActionUnselect::undo () -{ - CWorldEditorDoc *doc = getDocument (); - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - if (locator.Primitive) - { - // Select it -// nlverify (const_cast(locator.Primitive)->addPropertyByName ("selected", new CPropertyString ())); - getPrimitiveEditor(locator.Primitive)->setSelected(true); - - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate selection - InvalidatePrimitive (locator, SelectionState); - invalidateLeftView (); - } -} - -// *************************************************************************** - -bool CActionUnselect::redo () -{ - CWorldEditorDoc *doc = getDocument (); - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - if (locator.Primitive) - { - // Select it - if (getPrimitiveEditor(locator.Primitive)->getSelected()) -// if (const_cast(locator.Primitive)->removePropertyByName ("selected")) - { - getPrimitiveEditor(locator.Primitive)->setSelected(false); - // Invalidate selection - InvalidatePrimitive (locator, SelectionState); - invalidateLeftView (); - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - - return true; - } - } - return false; -} - -// *************************************************************************** - -// *************************************************************************** -// CActionUnselectAllSub -// *************************************************************************** - -CActionUnselectAllSub::CActionUnselectAllSub () -{ - CWorldEditorDoc *doc = getDocument (); - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Primitive ? - if (locator.Primitive) - { - // Selected ? -// IProperty *prop; - if (getPrimitiveEditor(locator.Primitive)->getSelected()) -// if (locator.Primitive->getPropertyByName ("selected", prop)) - { - // Scan its subvertex - uint numVert = locator.Primitive->getNumVector (); - if (numVert) - { - const CPrimVector *vectors = locator.Primitive->getPrimVector (); - for (uint vert=0; vertgetLocator (locator, subLocator); - - // Select its subvertex - nlassert ((uint)subLocator.XSubPrim < locator.Primitive->getNumVector ()); - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - if (vectors[subLocator.XSubPrim].Selected == false) - { - vectors[subLocator.XSubPrim].Selected = true; - modified = true; - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - } - } - - // Invalidate selection - if (modified) - invalidateLeftView (); -} - -// *************************************************************************** - -bool CActionUnselectAllSub::redo () -{ - CWorldEditorDoc *doc = getDocument (); - bool modified = false; - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Primitive ? - if (locator.Primitive) - { - // Selected ? -// IProperty *prop; - if (getPrimitiveEditor(locator.Primitive)->getSelected()) -// if (locator.Primitive->getPropertyByName ("selected", prop)) - { - // Scan its subvertex - uint numVert = locator.Primitive->getNumVector (); - if (numVert) - { - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - for (uint vert=0; vertmodifyDatabase (locator.getDatabaseIndex ()); - } - } - } - } - } - - ite++; - } - - // Invalidate selection - if (modified) - invalidateLeftView (); - - return modified; -} - -// *************************************************************************** -// CActionSelectAllSub -// *************************************************************************** - -CActionSelectAllSub::CActionSelectAllSub () -{ - CWorldEditorDoc *doc = getDocument (); - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Primitive ? - if (locator.Primitive) - { - // Selected ? -// IProperty *prop; - if (getPrimitiveEditor(locator.Primitive)->getSelected()) -// if (locator.Primitive->getPropertyByName ("selected", prop)) - { - // Scan its subvertex - uint numVert = locator.Primitive->getNumVector (); - if (numVert) - { - const CPrimVector *vectors = locator.Primitive->getPrimVector (); - for (uint vert=0; vertgetLocator (locator, subLocator); - - // Select its subvertex - nlassert ((uint)subLocator.XSubPrim < locator.Primitive->getNumVector ()); - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - if (vectors[subLocator.XSubPrim].Selected) - { - vectors[subLocator.XSubPrim].Selected = false; - modified = true; - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - } - } - - // Invalidate selection - if (modified) - invalidateLeftView (); -} - -// *************************************************************************** - -bool CActionSelectAllSub::redo () -{ - CWorldEditorDoc *doc = getDocument (); - bool modified = false; - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Primitive ? - if (locator.Primitive) - { - // Selected ? -// IProperty *prop; - if (getPrimitiveEditor(locator.Primitive)->getSelected()) -// if (locator.Primitive->getPropertyByName ("selected", prop)) - { - // Scan its subvertex - uint numVert = locator.Primitive->getNumVector (); - if (numVert) - { - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - for (uint vert=0; vertmodifyDatabase (locator.getDatabaseIndex ()); - } - } - } - } - } - - ite++; - } - - // Invalidate selection - if (modified) - invalidateLeftView (); - - return modified; -} - -// *************************************************************************** -// CActionSelectSub -// *************************************************************************** - -CActionSelectSub::CActionSelectSub (const CDatabaseLocator &locator) -{ - _Locator = locator; -} - -// *************************************************************************** - -void CActionSelectSub::undo () -{ - CWorldEditorDoc *doc = getDocument (); - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - if (locator.Primitive) - { - // Select its subvertex - nlassert ((uint)_Locator.XSubPrim < locator.Primitive->getNumVector ()); - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - nlassert (vectors[_Locator.XSubPrim].Selected); - vectors[_Locator.XSubPrim].Selected = false; - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate selection - invalidateLeftView (); - } -} - -// *************************************************************************** - -bool CActionSelectSub::redo () -{ - CWorldEditorDoc *doc = getDocument (); - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - if (locator.Primitive) - { - // Select its subvertex - nlassert ((uint)_Locator.XSubPrim < locator.Primitive->getNumVector ()); - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - if (!vectors[_Locator.XSubPrim].Selected) - { - vectors[_Locator.XSubPrim].Selected = true; - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate selection - invalidateLeftView (); - return true; - } - } - return false; -} - -// *************************************************************************** -// CActionUnselectSub -// *************************************************************************** - -CActionUnselectSub::CActionUnselectSub (const CDatabaseLocator &locator) -{ - _Locator = locator; -} - -// *************************************************************************** - -void CActionUnselectSub::undo () -{ - CWorldEditorDoc *doc = getDocument (); - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - if (locator.Primitive) - { - // Select its subvertex - nlassert ((uint)_Locator.XSubPrim < locator.Primitive->getNumVector ()); - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - nlassert (!vectors[_Locator.XSubPrim].Selected); - vectors[_Locator.XSubPrim].Selected = true; - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate selection - invalidateLeftView (); - } -} - -// *************************************************************************** - -bool CActionUnselectSub::redo () -{ - CWorldEditorDoc *doc = getDocument (); - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - if (locator.Primitive) - { - // Select its subvertex - nlassert ((uint)_Locator.XSubPrim < locator.Primitive->getNumVector ()); - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - if (vectors[_Locator.XSubPrim].Selected) - { - vectors[_Locator.XSubPrim].Selected = false; - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate selection - invalidateLeftView (); - return true; - } - } - return false; -} - -// *************************************************************************** -// CActionMove -// *************************************************************************** - -CActionMove::CActionMove (bool subSelection) -{ - CWorldEditorDoc *doc = getDocument (); - // Sub selection ? - _SubSelection = subSelection; - - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Primitive ? - if (locator.Primitive) - { - // Shown ? -// IProperty *prop; - if (isPrimitiveVisible (locator.Primitive)) -// if (!locator.Primitive->getPropertyByName ("hidden", prop)) - { - // Scan its subvertex - uint numVert = locator.Primitive->getNumVector (); - if (numVert) - { - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - for (uint vert=0; vertgetLocator (locator, entry.Locator); - - // Select its subvertex - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - vectors[entry.Locator.XSubPrim].CVector::operator= (entry.OldPosition); - - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate quad grid - InvalidatePrimitive (locator, QuadTree); - } - - // Invalidate selection - invalidateLeftView (); -} - -// *************************************************************************** - -bool CActionMove::redo () -{ - if (_Translation.isNull ()) - return false; - - CWorldEditorDoc *doc = getDocument (); - for (uint i=0; i<_Entities.size (); i++) - { - // Get the locator pointer - CUndoEntry &entry = _Entities[i]; - CDatabaseLocatorPointer locator; - doc->getLocator (locator, entry.Locator); - - // Select its subvertex - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - vectors[entry.Locator.XSubPrim].CVector::operator= (entry.OldPosition); - vectors[entry.Locator.XSubPrim].CVector::operator+= (_Translation); - - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate quad grid - InvalidatePrimitive (locator, QuadTree); - } - - // Invalidate selection - invalidateLeftView (); - - return true; -} - -// *************************************************************************** - -bool CActionMove::getText (string &result) -{ - result = toString ("Move %.2f, %.2f", _Translation.x, _Translation.y); - return true; -} - -// *************************************************************************** -// CActionRotate -// *************************************************************************** - -CActionRotate::CActionRotate (bool subSelection, const CVector &pivot) -{ - CWorldEditorDoc *doc = getDocument (); - // Sub selection ? - _SubSelection = subSelection; - - // Pivot ? - Pivot = pivot; - - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Primitive ? - if (locator.Primitive) - { - // Shown ? -// IProperty *prop; - if (isPrimitiveVisible (locator.Primitive)) -// if (!locator.Primitive->getPropertyByName ("hidden", prop)) - { - // Scan its subvertex - uint numVert = locator.Primitive->getNumVector (); - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - const CPrimPointEditor *pointPrim = dynamic_cast (locator.Primitive); - for (uint vert=0; vertAngle:0)); - - // Set the sub index - _Entities.back ().Locator.XSubPrim = vert; - } - } - } - } - - ite++; - } - _Rotate = false; - _Turn = false; -} - -// *************************************************************************** - -void CActionRotate::setAngle (float angle, bool rotate, bool turn) -{ - _Angle = angle; - _Rotate = rotate; - _Turn = turn; -} - -// *************************************************************************** - -void CActionRotate::undo () -{ - CWorldEditorDoc *doc = getDocument (); - for (uint i=0; i<_Entities.size (); i++) - { - // Get the locator pointer - CUndoEntry &entry = _Entities[i]; - CDatabaseLocatorPointer locator; - doc->getLocator (locator, entry.Locator); - - // Select its subvertex - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - vectors[entry.Locator.XSubPrim].CVector::operator= (entry.OldPosition); - - // Restaure the turn - if (entry.PointPrimitive) - { - CPrimPointEditor *primPoint = safe_cast (const_cast (locator.Primitive)); - primPoint->Angle = entry.PointPrimitiveAngle; - } - - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate quad grid - InvalidatePrimitive (locator, QuadTree); - } - - // Invalidate selection - invalidateLeftView (); -} - -// *************************************************************************** - -bool CActionRotate::redo () -{ - if (_Angle == 0 || (!_Turn && !_Rotate)) - return false; - - CWorldEditorDoc *doc = getDocument (); - for (uint i=0; i<_Entities.size (); i++) - { - // Get the locator pointer - CUndoEntry &entry = _Entities[i]; - CDatabaseLocatorPointer locator; - doc->getLocator (locator, entry.Locator); - - // Select its subvertex - bool modified = false; - if (_Rotate) - { - // Select its subvertex - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - vectors[entry.Locator.XSubPrim].CVector::operator= (entry.OldPosition); - - // Transform point - transformVector (vectors[entry.Locator.XSubPrim], _Angle, Pivot); - modified = true; - } - - // Transform point - if (_Turn && entry.PointPrimitive) - { - // Select its subvertex - CPrimPointEditor *primPoint = safe_cast (const_cast (locator.Primitive)); - primPoint->Angle = entry.PointPrimitiveAngle; - primPoint->Angle += _Angle; - modified = true; - } - - if (modified) - { - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate quad grid - InvalidatePrimitive (locator, QuadTree); - } - } - - // Invalidate selection - invalidateLeftView (); - - return true; -} - -// *************************************************************************** - -bool CActionRotate::getText (string &result) -{ - result = toString ("Rotate %.2f degrees", 180*_Angle/Pi); - return true; -} - -// *************************************************************************** - -bool CActionRotate::getHelp (string &result) -{ - result = "Turn with CTRL"; - return _Rotate; -} - -// *************************************************************************** -// CActionScale -// *************************************************************************** - -CActionScale::CActionScale (bool subSelection, const CVector &pivot) -{ - CWorldEditorDoc *doc = getDocument (); - // Sub selection ? - _SubSelection = subSelection; - - // Pivot - Pivot = pivot; - - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Primitive ? - if (locator.Primitive) - { - // Shown ? -// IProperty *prop; - if (isPrimitiveVisible (locator.Primitive)) -// if (!locator.Primitive->getPropertyByName ("hidden", prop)) - { - // Scan its subvertex - uint numVert = locator.Primitive->getNumVector (); - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - - // Radius - string radius; - const bool hasRadius = locator.Primitive->getPropertyByName ("radius", radius); - - for (uint vert=0; vertgetLocator (locator, entry.Locator); - - // Select its subvertex - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - vectors[entry.Locator.XSubPrim].CVector::operator= (entry.OldPosition); - - // Does it have radius ? - if (entry.HasRadius) - { - const_cast (locator.Primitive)->removePropertyByName ("radius"); - const_cast (locator.Primitive)->addPropertyByName ("radius", new CPropertyString (toString (entry.Radius).c_str())); - } - - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate quad grid - InvalidatePrimitive (locator, QuadTree); - } - - // Invalidate selection - invalidateLeftView (); -} - -// *************************************************************************** - -bool CActionScale::redo () -{ - if ((_Factor == 1.f) || (!_Scale && !_Radius)) - return false; - - CWorldEditorDoc *doc = getDocument (); - for (uint i=0; i<_Entities.size (); i++) - { - // Get the locator pointer - CUndoEntry &entry = _Entities[i]; - CDatabaseLocatorPointer locator; - doc->getLocator (locator, entry.Locator); - - bool modified = false; - - if (_Scale) - { - // Select its subvertex - CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); - vectors[entry.Locator.XSubPrim].CVector::operator= (entry.OldPosition); - vectors[entry.Locator.XSubPrim].CVector::operator-= (Pivot); - vectors[entry.Locator.XSubPrim].CVector::operator*= (_Factor); - vectors[entry.Locator.XSubPrim].CVector::operator+= (Pivot); - modified = true; - } - - if (_Radius) - { - const_cast (locator.Primitive)->removePropertyByName ("radius"); - const_cast (locator.Primitive)->addPropertyByName ("radius", new CPropertyString (toString (entry.Radius*_Factor).c_str())); - modified = true; - } - - if (modified) - { - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate quad grid - InvalidatePrimitive (locator, QuadTree); - } - } - - // Invalidate selection - invalidateLeftView (); - - return true; -} - -// *************************************************************************** - -bool CActionScale::getText (string &result) -{ - result = toString ("Scale %.2f%%", _Factor*100); - return true; -} - -// *************************************************************************** - -bool CActionScale::getHelp (string &result) -{ - result = "Radius with CTRL"; - return _Scale; -} - -// *************************************************************************** -// CActionAddVertex -// *************************************************************************** - -CActionAddVertex::CActionAddVertex (const CDatabaseLocator &locator, const CVector &newVertex) -{ - // Save the locator - _Locator = locator; - _NewVertex = newVertex; -} - -// *************************************************************************** - -void CActionAddVertex::undo () -{ - CWorldEditorDoc *doc = getDocument (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Is a path or a zone ? - std::vector *primVector = NULL; - CPrimPathEditor *path = dynamic_cast (const_cast (locator.Primitive)); - if (path) - primVector = &path->VPoints; - else - { - CPrimZoneEditor *zone = dynamic_cast (const_cast (locator.Primitive)); - if (zone) - primVector = &zone->VPoints; - } - - // Found ? - nlverify (primVector); - - // Delete the vertex - primVector->erase (primVector->begin ()+(_Locator.XSubPrim+1)); - - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate quad grid - InvalidatePrimitive (locator, QuadTree); -} - -// *************************************************************************** - -bool CActionAddVertex::redo () -{ - CWorldEditorDoc *doc = getDocument (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Is a path or a zone ? - std::vector *primVector = NULL; - CPrimPathEditor *path = dynamic_cast (const_cast (locator.Primitive)); - if (path) - primVector = &path->VPoints; - else - { - CPrimZoneEditor *zone = dynamic_cast (const_cast (locator.Primitive)); - if (zone) - primVector = &zone->VPoints; - } - - // Found ? - nlverify (primVector); - - // Insert a vertex - primVector->insert (primVector->begin ()+(_Locator.XSubPrim+1), CPrimVector()); - - // Initialise it - (*primVector)[_Locator.XSubPrim+1].CVector::operator= (_NewVertex); - - // Not selected - (*primVector)[_Locator.XSubPrim+1].Selected = false; - - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate quad grid - InvalidatePrimitive (locator, QuadTree); - - return true; -} - -// *************************************************************************** -// CActionDeleteSub -// *************************************************************************** - -CActionDeleteSub::CActionDeleteSub (const CDatabaseLocatorPointer &locator) -{ - // Save the locator - _Locator = locator; - - // Is a path or a zone ? - std::vector *primVector = NULL; - CPrimPathEditor *path = dynamic_cast (const_cast (locator.Primitive)); - if (path) - primVector = &path->VPoints; - else - { - CPrimZoneEditor *zone = dynamic_cast (const_cast (locator.Primitive)); - if (zone) - primVector = &zone->VPoints; - } - - // Found ? - nlverify (primVector); - - // Delete the vertex - _OldVertex = (*primVector)[_Locator.XSubPrim]; -} - -// *************************************************************************** - -void CActionDeleteSub::undo () -{ - CWorldEditorDoc *doc = getDocument (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Is a path or a zone ? - std::vector *primVector = NULL; - CPrimPathEditor *path = dynamic_cast (const_cast (locator.Primitive)); - if (path) - primVector = &path->VPoints; - else - { - CPrimZoneEditor *zone = dynamic_cast (const_cast (locator.Primitive)); - if (zone) - primVector = &zone->VPoints; - } - - // Found ? - nlverify (primVector); - - // Insert a vertex - primVector->insert (primVector->begin ()+_Locator.XSubPrim, CPrimVector()); - - // Initialise it - (*primVector)[_Locator.XSubPrim] = (_OldVertex); - - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate left view - invalidateLeftView (); - - // Invalidate quad grid - InvalidatePrimitive (locator, QuadTree); -} - -// *************************************************************************** - -bool CActionDeleteSub::redo () -{ - CWorldEditorDoc *doc = getDocument (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Is a path or a zone ? - std::vector *primVector = NULL; - CPrimPathEditor *path = dynamic_cast (const_cast (locator.Primitive)); - if (path) - primVector = &path->VPoints; - else - { - CPrimZoneEditor *zone = dynamic_cast (const_cast (locator.Primitive)); - if (zone) - primVector = &zone->VPoints; - } - - // Found ? - nlverify (primVector); - - // Delete the vertex - primVector->erase (primVector->begin ()+_Locator.XSubPrim); - - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate left view - invalidateLeftView (); - - // Invalidate quad grid - InvalidatePrimitive (locator, QuadTree); - - return true; -} - -// *************************************************************************** -// CActionDelete -// *************************************************************************** - -CActionDelete::CActionDelete (const CDatabaseLocatorPointer &locator) -{ - // Save the locator - _Locator = locator; - - // Copy the primitive - _OldPrimitive = locator.Primitive->copy (); -} - -// *************************************************************************** - -CActionDelete::~CActionDelete () -{ - delete _OldPrimitive; -} - -// *************************************************************************** - -void CActionDelete::undo () -{ - CWorldEditorDoc *doc = getDocument (); - - // Copy the primtive - IPrimitive *copy = _OldPrimitive->copy (); - - // Insert it - doc->insertPrimitive (_Locator, copy); - - // Modify files - doc->modifyDatabase (_Locator.getDatabaseIndex ()); - - // Invalidate left view - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Invalidate quad grid - InvalidatePrimitiveRec (locator, QuadTree|LogicTreeStruct|SelectionState); -} - -// *************************************************************************** - -bool CActionDelete::redo () -{ - CWorldEditorDoc *doc = getDocument (); - - doc->deletePrimitive (_Locator); - - // Modify files - doc->modifyDatabase (_Locator.getDatabaseIndex ()); - - // Invalidate left view - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Invalidate quad grid - // Will be removed from the quad grid by the IPrimitiveEditor destructor - - return true; -} - -// *************************************************************************** -// CActionSetPrimitivePropertyString -// *************************************************************************** - -CActionSetPrimitivePropertyString::CActionSetPrimitivePropertyString (const CDatabaseLocatorPointer &locator, const char *propertyName, const char *newValue, bool _default) -{ - _PropertyName = propertyName; - _PropertyNewValue = newValue; - _PropertyNewValueDefault = _default; - _Locator = locator; - - // Backup old value - const IProperty *prop; - _OldExist = locator.Primitive->getPropertyByName (propertyName, prop); - - if (_OldExist) - { - // Dynamic cast - const CPropertyString *propString = dynamic_cast (prop); - nlassert (propString); - _PropertyOldValue = propString->String; - _PropertyOldValueDefault = propString->Default; - } -} - -// *************************************************************************** - -void CActionSetPrimitivePropertyString::undo () -{ - CWorldEditorDoc *doc = getDocument (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Remove the old property - const_cast (locator.Primitive)->removePropertyByName (_PropertyName.c_str ()); - - // Add the old property - if (_OldExist) - const_cast (locator.Primitive)->addPropertyByName (_PropertyName.c_str (), new CPropertyString (_PropertyOldValue.c_str (), _PropertyOldValueDefault)); - - // Invalidate tools - getMainFrame ()->invalidateToolsParam (); - InvalidatePrimitive (locator, LogicTreeParam); - - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate right view - invalidateLeftView (); -} - -// *************************************************************************** - -bool CActionSetPrimitivePropertyString::redo () -{ - CWorldEditorDoc *doc = getDocument (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Remove the old property - const_cast (locator.Primitive)->removePropertyByName (_PropertyName.c_str ()); - - // Add the new property - const_cast (locator.Primitive)->addPropertyByName (_PropertyName.c_str (), new CPropertyString (_PropertyNewValue.c_str (), _PropertyNewValueDefault)); - - // Invalidate tools - getMainFrame ()->invalidateToolsParam (); - InvalidatePrimitive (locator, LogicTreeParam); - - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate right view - invalidateLeftView (); - - return true; -} - -// *************************************************************************** -// CActionSetPrimitivePropertyStringArray -// *************************************************************************** - -CActionSetPrimitivePropertyStringArray::CActionSetPrimitivePropertyStringArray (const CDatabaseLocatorPointer &locator, const char *propertyName, const std::vector &newValue, bool _default) -{ - _PropertyName = propertyName; - _PropertyNewValue = newValue; - _Locator = locator; - _PropertyNewValueDefault = _default; - - // Backup old value - const IProperty *prop; - _OldExist = locator.Primitive->getPropertyByName (propertyName, prop); - - if (_OldExist) - { - // Dynamic cast - const CPropertyStringArray *propStringArray = dynamic_cast (prop); - nlassert (propStringArray); - _PropertyOldValue = propStringArray->StringArray; - _PropertyOldValueDefault = propStringArray->Default; - } -} - -// *************************************************************************** - -void CActionSetPrimitivePropertyStringArray::undo () -{ - CWorldEditorDoc *doc = getDocument (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Remove the old property - const_cast (locator.Primitive)->removePropertyByName (_PropertyName.c_str ()); - - // Add the old property - if (_OldExist) - const_cast (locator.Primitive)->addPropertyByName (_PropertyName.c_str (), new CPropertyStringArray (_PropertyOldValue, _PropertyOldValueDefault)); - - // Invalidate tools - getMainFrame ()->invalidateToolsParam (); - - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); -} - -// *************************************************************************** - -bool CActionSetPrimitivePropertyStringArray::redo () -{ - CWorldEditorDoc *doc = getDocument (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Remove the old property - const_cast (locator.Primitive)->removePropertyByName (_PropertyName.c_str ()); - - // Add the new property - const_cast (locator.Primitive)->addPropertyByName (_PropertyName.c_str (), new CPropertyStringArray (_PropertyNewValue, _PropertyNewValueDefault)); - - // Invalidate tools - getMainFrame ()->invalidateToolsParam (); - - // Modify files - doc->modifyDatabase (locator.getDatabaseIndex ()); - - return true; -} - -// *************************************************************************** -// CActionAddPrimitiveByClass -// *************************************************************************** - -CActionAddPrimitiveByClass::CActionAddPrimitiveByClass (const CDatabaseLocator &locator, const char *className, - const NLMISC::CVector &initPos, float deltaPos, - const std::vector initParameters) -{ - _Locator = locator; - _ClassName = className; - _OldPrimitive = NULL; - _InitPos = initPos; - _DeltaPos = deltaPos; - _InitParameters = initParameters; -} - -// *************************************************************************** - -void CActionAddPrimitiveByClass::undo () -{ - CWorldEditorDoc *doc = getDocument (); - - // Delete the primitive - doc->deletePrimitive (_Locator); - - // Invalidate left view - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Modify files - doc->modifyDatabase (_Locator.getDatabaseIndex ()); - - // Invalidate quad grid - // Will be removed from the quad grid by the IPrimitiveEditor destructor -} - -// *************************************************************************** - -bool CActionAddPrimitiveByClass::redo () -{ - CWorldEditorDoc *doc = getDocument (); - - // First time ? - if (_OldPrimitive == NULL) - { - - // Get the primitive - CDatabaseLocator _parent = _Locator; - _parent.getParent (); - CDatabaseLocatorPointer parent; - doc->getLocator (parent, _parent); - - // Get the class primitive - IPrimitive *primitive = const_cast (doc->createPrimitive (_Locator, _ClassName.c_str (), "", _InitPos, _DeltaPos, _InitParameters)); - // IPrimitive *primitive = const_cast (doc->createPrimitive (_Locator, _ClassName.c_str (), (_ClassName+"_"+toString (parent.Primitive->getNumChildren ())).c_str (), _InitPos, _DeltaPos, _InitParameters)); - if (primitive != NULL) - { - // Invalidate left view - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Modify files - doc->modifyDatabase (_Locator.getDatabaseIndex ()); - - // Final name - string name; - if (!primitive->getPropertyByName ("name", name) || name.empty()) - { - string newValue = _ClassName+"_"+toString (parent.Primitive->getNumChildren ()); - if (!newValue.empty()) - doc->addModification (new CActionSetPrimitivePropertyString (locator, "name", newValue.c_str (), false)); - } - - // Backup it - _OldPrimitive = locator.Primitive->copy (); - - // Invalidate quad grid - InvalidatePrimitiveRec (locator, QuadTree|LogicTreeStruct|SelectionState); - return true; - } - } - else - { - // Make a copy - IPrimitive *copy = _OldPrimitive->copy (); - // Second time, restaure backuped primitive - doc->insertPrimitive (_Locator, copy); - - // Modify files - doc->modifyDatabase (_Locator.getDatabaseIndex ()); - - // Invalidate left view - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Invalidate quad grid - InvalidatePrimitiveRec (locator, QuadTree|LogicTreeStruct|SelectionState); - - return true; - } - - return false; -} - -// *************************************************************************** -// CActionAddLandscape -// *************************************************************************** - -CActionAddLandscape::CActionAddLandscape (const char *filename) -{ - _FirstTime = true; - _Filename = filename; -} - -// *************************************************************************** - -void CActionAddLandscape::undo () -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Remove last landscape - doc->_DataHierarchy.resize (doc->_DataHierarchy.size ()-1); - doc->_DataHierarchy.recomputePointerArray (); - - // Modify files - doc->modifyProject (); - - // Invalidate all - invalidateLeftView (); - getMainFrame ()->invalidateLandscape (); - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); -} - -// *************************************************************************** - -bool CActionAddLandscape::redo () -{ - // Disable events - CNoInteraction nointeraction; - - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Result - bool result = true; - - if (_FirstTime) - { - // Load the file - getMainFrame ()->launchLoadingDialog (string("loading land ") + _Filename); - - try - { - // Open it - CIFile fileIn; - if (fileIn.open (_Filename)) - { - CIXml xml(true); - xml.init (fileIn); - _NewRegion.serial (xml); - } - else - { - getMainFrame ()->terminateLoadingDialog (); - theApp.errorMessage ("Can't open file %s for reading", _Filename.c_str ()); - result = false; - } - } - catch (Exception& e) - { - getMainFrame ()->terminateLoadingDialog (); - theApp.errorMessage ("Error reading file %s : %s", _Filename.c_str (), e.what ()); - result = false; - } - - // Done - getMainFrame ()->terminateLoadingDialog (); - _FirstTime = false; - } - - if (result) - { - // Push the landscape - doc->_DataHierarchy.push_back (CWorldEditorDoc::CDatabaseElement (CWorldEditorDoc::CDatabaseElement::Landscape)); - doc->_DataHierarchy.recomputePointerArray (); - doc->_DataHierarchy.back ().ZoneRegion = _NewRegion; - doc->_DataHierarchy.back ().Filename = _Filename; - doc->_DataHierarchy.back ().LastModifedTime = NLMISC::CFile::getFileModificationDate (_Filename); - - // Init the landscape manager - getMainFrame ()->invalidateLandscape (); - - // Invalidate pointers - InvalidateAllPrimitives (); - - // Modify files - doc->modifyProject (); - - // Invalidate all - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - } - - return result; -} - -// *************************************************************************** -// CActionNewPrimitive -// *************************************************************************** - -CActionNewLandscape::CActionNewLandscape () -{ -} - -// *************************************************************************** - -void CActionNewLandscape::undo () -{ - CWorldEditorDoc *doc = getDocument (); - // Check we have a primitive - nlassert (doc->_DataHierarchy.size () > 0); - - // Remove back primitive - doc->_DataHierarchy.resize (doc->_DataHierarchy.size ()-1); - doc->_DataHierarchy.recomputePointerArray (); - - // Invalidate tools - getMainFrame ()->invalidateLandscape (); - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); - - // Modify files - doc->modifyProject (); -} - -// *************************************************************************** - -bool CActionNewLandscape::redo () -{ - CWorldEditorDoc *doc = getDocument (); - // Push back the primitive - doc->_DataHierarchy.push_back (CWorldEditorDoc::CDatabaseElement (CWorldEditorDoc::CDatabaseElement::Landscape)); - doc->_DataHierarchy.recomputePointerArray (); - - // Invalidate tools - getMainFrame ()->invalidateLandscape (); - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); - - // Modify files - uint index = doc->_DataHierarchy.size ()-1; - doc->modifyProject (); - doc->modifyDatabase (index); - - return true; -} - -// *************************************************************************** - -CActionDeleteDatabaseElement::CActionDeleteDatabaseElement (uint prim) -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Backup the primitive - _Index = prim; - _Primitive = new CWorldEditorDoc::CDatabaseElement (doc->_DataHierarchy[_Index]); -} - -// *************************************************************************** - -CActionDeleteDatabaseElement::~CActionDeleteDatabaseElement () -{ - if (_Primitive) - delete _Primitive; -} - -// *************************************************************************** - -void CActionDeleteDatabaseElement::undo () -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Insert the primitive - std::list::iterator ite = doc->_DataHierarchy.begin(); - for (uint i=0; i<_Index; i++) - ite++; - doc->_DataHierarchy.insert (ite, *_Primitive); - doc->_DataHierarchy.recomputePointerArray (); - - // Is a landscape ? - if (doc->isLandscape (_Index)) - getMainFrame ()->invalidateLandscape (); - - // Modify files - doc->modifyProject (); - - // Invalidate all - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); -} - -// *************************************************************************** - -bool CActionDeleteDatabaseElement::redo () -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Is a landscape ? - if (doc->isLandscape (_Index)) - getMainFrame ()->invalidateLandscape (); - - // Delete the primitive - std::list::iterator ite = doc->_DataHierarchy.begin(); - for (uint i=0; i<_Index; i++) - ite++; - doc->_DataHierarchy.erase (ite); - doc->_DataHierarchy.recomputePointerArray (); - - // Modify files - doc->modifyProject (); - - // Invalidate all - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); - - return true; -} - -// *************************************************************************** -// CActionXChgDatabaseElement -// *************************************************************************** - -CActionXChgDatabaseElement::CActionXChgDatabaseElement (uint prim) -{ - // Backup the primitive - _Index = prim; -} - -// *************************************************************************** - -CActionXChgDatabaseElement::~CActionXChgDatabaseElement () -{ -} - -// *************************************************************************** - -void CActionXChgDatabaseElement::undo () -{ - // Same than redo - redo (); -} - -// *************************************************************************** - -bool CActionXChgDatabaseElement::redo () -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - nlassert (_Index+1 < doc->getNumDatabaseElement ()); - - // Is a landscape ? - if (doc->isLandscape (_Index) || doc->isLandscape (_Index+1)) - getMainFrame ()->invalidateLandscape (); - - // Delete the primitive - uint i; - std::list::iterator ite0 = doc->_DataHierarchy.begin(); - for (i=0; i<_Index; i++) - ite0++; - std::list::iterator ite1 = ite0; - ite1++; - doc->_DataHierarchy.splice (ite0, doc->_DataHierarchy, ite1); - doc->_DataHierarchy.recomputePointerArray (); - - // Modify files - doc->modifyProject (); - - // Invalidate all - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); - - return true; -} - -// *************************************************************************** -// CActionAddPrimitive -// *************************************************************************** - -CActionAddPrimitive::CActionAddPrimitive (const NLLIGO::IPrimitive &primitiveToAdd, const CDatabaseLocator &locator) -{ - _Primitive = primitiveToAdd.copy (); - _Locator = locator; -} - -// *************************************************************************** - -CActionAddPrimitive::CActionAddPrimitive (NLLIGO::IPrimitive *primitiveToAdd, const CDatabaseLocator &locator) -{ - _Primitive = primitiveToAdd; - _Locator = locator; - _FirstTime = true; -} - -// *************************************************************************** - -CActionAddPrimitive::~CActionAddPrimitive () -{ - delete _Primitive; -} - -// *************************************************************************** - -void CActionAddPrimitive::undo () -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Add the primitive - doc->deletePrimitive (_Locator); - - // Modify files - doc->modifyDatabase (_Locator.getDatabaseIndex ()); - - // Invalidate all - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Invalidate quad grid - // Will be removed from the quad grid by the IPrimitiveEditor destructor -} - -// *************************************************************************** - -bool CActionAddPrimitive::redo () -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Make a copy - IPrimitive *copy = _Primitive->copy (); - - // Add the primitive - doc->insertPrimitive (_Locator, copy); - - // Modify files - doc->modifyDatabase (_Locator.getDatabaseIndex ()); - - // Update unique ID - if (_FirstTime) - doc->resetUniqueID (*copy); - - // Invalidate all - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Invalidate quad grid - InvalidatePrimitiveRec (locator, QuadTree|LogicTreeStruct|SelectionState); - - _FirstTime = false; - - // Done - return true; -} - - -// *************************************************************************** -// CActionShowHide -// *************************************************************************** - -CActionShowHide::CActionShowHide (const CDatabaseLocatorPointer &locator, bool show) -{ - _Show = show; - _Locator = locator; -} - -// *************************************************************************** - -void CActionShowHide::undo () -{ - CWorldEditorDoc *doc = getDocument (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Show it ? - if (_Show) - { - // Add the property - getPrimitiveEditor(locator.Primitive)->setHidden(true); - -// nlverify (const_cast(locator.Primitive)->addPropertyByName ("hidden", new CPropertyString (""))); - } - else - { - // Remove the property - getPrimitiveEditor(locator.Primitive)->setHidden(false); -// const IProperty *property; -// nlassert (locator.Primitive->getPropertyByName ("hidden", property)); -// const_cast(locator.Primitive)->removePropertyByName ("hidden"); - } - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate all - invalidateLeftView (); - getMainFrame ()->invalidateToolsParam (); - InvalidatePrimitive (locator, LogicTreeParam); -} - -// *************************************************************************** - -bool CActionShowHide::redo () -{ - CWorldEditorDoc *doc = getDocument (); - - // Get the primitive - CDatabaseLocatorPointer locator; - doc->getLocator (locator, _Locator); - - // Show it ? - if (_Show) - { - // Remove the property - getPrimitiveEditor(locator.Primitive)->setHidden(false); -// const IProperty *property; -// if (!locator.Primitive->getPropertyByName ("hidden", property)) -// // Does not exist -// return false; -// -// // Show it -// nlverify (const_cast(locator.Primitive)->removePropertyByName ("hidden")); - } - else - { - // Add the property - getPrimitiveEditor(locator.Primitive)->setHidden(true); -// const IProperty *property; -// if (locator.Primitive->getPropertyByName ("hidden", property)) -// // Already exist -// return false; -// -// // Add the property -// nlverify (const_cast(locator.Primitive)->addPropertyByName ("hidden", new CPropertyString (""))); - } - - // Modify files - // doc->modifyDatabase (locator.getDatabaseIndex ()); - - // Invalidate all - invalidateLeftView (); - getMainFrame ()->invalidateToolsParam (); - InvalidatePrimitive (locator, LogicTreeParam); - - return true; -} - -// *************************************************************************** +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" + +#include "action.h" +#include "world_editor.h" +#include "main_frm.h" +#include "world_editor_doc.h" +#include "editor_primitive.h" +#include "nel/sound/background_sound_manager.h" + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; + +// *************************************************************************** + +CActionLigoTile::CActionLigoTile (const CLigoData &data, const CDatabaseLocator &locator) +{ + // Backup new data + _New = data; + + // Backup old data + CWorldEditorDoc *doc = getDocument (); + doc->getLigoData (_Old, locator); + + // Backup locator + _Locator = locator; +} + +// *************************************************************************** + +void CActionLigoTile::undo () +{ + set (_Old); + invalidateLeftView (); + CWorldEditorDoc *doc = getDocument (); + doc->modifyDatabase (_Locator.getDatabaseIndex ()); +} + +// *************************************************************************** + +bool CActionLigoTile::redo () +{ + set (_New); + invalidateLeftView (); + CWorldEditorDoc *doc = getDocument (); + doc->modifyDatabase (_Locator.getDatabaseIndex ()); + return true; +} + +// *************************************************************************** + +void CActionLigoTile::set (const CLigoData &data) +{ + CWorldEditorDoc *doc = getDocument (); + NLLIGO::CZoneRegion ®ion = doc->_DataHierarchy[_Locator.getDatabaseIndex ()].ZoneRegion; + nlassert ((_Locator.XSubPrim >= region.getMinX ()) && (_Locator.XSubPrim <= region.getMaxX ()) && (_Locator.Y >= region.getMinY ()) && (_Locator.Y <= region.getMaxY ())); + + region.setPosX (_Locator.XSubPrim, _Locator.Y, data.PosX); + region.setPosY (_Locator.XSubPrim, _Locator.Y, data.PosY); + region.setName (_Locator.XSubPrim, _Locator.Y, data.ZoneName); + region.setRot (_Locator.XSubPrim, _Locator.Y, data.Rot); + region.setFlip (_Locator.XSubPrim, _Locator.Y, data.Flip); + region.setSharingMatNames (_Locator.XSubPrim, _Locator.Y, 0, data.SharingMatNames[0]); + region.setSharingMatNames (_Locator.XSubPrim, _Locator.Y, 1, data.SharingMatNames[1]); + region.setSharingMatNames (_Locator.XSubPrim, _Locator.Y, 2, data.SharingMatNames[2]); + region.setSharingMatNames (_Locator.XSubPrim, _Locator.Y, 3, data.SharingMatNames[3]); + region.setSharingCutEdges (_Locator.XSubPrim, _Locator.Y, 0, data.SharingCutEdges[0]); + region.setSharingCutEdges (_Locator.XSubPrim, _Locator.Y, 1, data.SharingCutEdges[1]); + region.setSharingCutEdges (_Locator.XSubPrim, _Locator.Y, 2, data.SharingCutEdges[2]); + region.setSharingCutEdges (_Locator.XSubPrim, _Locator.Y, 3, data.SharingCutEdges[3]); +} + +// *************************************************************************** + +CActionLigoMove::CActionLigoMove (uint index, sint32 deltaX, sint32 deltaY) +{ + _Index = index; + _DeltaX = deltaX; + _DeltaY = deltaY; +} + +// *************************************************************************** + +void CActionLigoMove::undo () +{ + CWorldEditorDoc *doc = getDocument (); + NLLIGO::CZoneRegion ®ion = doc->_DataHierarchy[_Index].ZoneRegion; + region.setMaxX (region.getMaxX () - _DeltaX); + region.setMinX (region.getMinX () - _DeltaX); + region.setMaxY (region.getMaxY () - _DeltaY); + region.setMinY (region.getMinY () - _DeltaY); + doc->modifyDatabase (_Index); +} + +// *************************************************************************** + +bool CActionLigoMove::redo () +{ + CWorldEditorDoc *doc = getDocument (); + NLLIGO::CZoneRegion ®ion = doc->_DataHierarchy[_Index].ZoneRegion; + region.setMaxX (region.getMaxX () + _DeltaX); + region.setMinX (region.getMinX () + _DeltaX); + region.setMaxY (region.getMaxY () + _DeltaY); + region.setMinY (region.getMinY () + _DeltaY); + doc->modifyDatabase (_Index); + return true; +} + +// *************************************************************************** + +CActionLigoResize::CActionLigoResize (uint index, sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY) +{ + _Index = index; + _NewMinX = newMinX; + _NewMaxX = newMaxX; + _NewMinY = newMinY; + _NewMaxY = newMaxY; + + // Backup old region zone + CWorldEditorDoc *doc = getDocument (); + _Old = doc->_DataHierarchy[_Index].ZoneRegion; +} + +// *************************************************************************** + +void CActionLigoResize::undo () +{ + // Restaure old region zone + CWorldEditorDoc *doc = getDocument (); + doc->_DataHierarchy[_Index].ZoneRegion = _Old; + doc->modifyDatabase (_Index); +} + +// *************************************************************************** + +bool CActionLigoResize::redo () +{ + // Get the zone region + CWorldEditorDoc *doc = getDocument (); + NLLIGO::CZoneRegion ®ion = doc->_DataHierarchy[_Index].ZoneRegion; + + sint32 i, j; + vector newZones; + newZones.resize ((1+_NewMaxX-_NewMinX)*(1+_NewMaxY-_NewMinY)); + + sint32 newStride = 1+_NewMaxX-_NewMinX; + sint32 Stride = 1+region.getMaxX ()-region.getMinX (); + + for (j = _NewMinY; j <= _NewMaxY; ++j) + for (i = _NewMinX; i <= _NewMaxX; ++i) + { + // Ref on the new value + CLigoData &data = newZones[(i-_NewMinX)+(j-_NewMinY)*newStride]; + + // In the old array ? + if ((i >= region.getMinX ())&&(i <= region.getMaxX ())&&(j >= region.getMinY ())&&(j <= region.getMaxY ())) + { + // Backup values + data.PosX = region.getPosX (i, j); + data.PosY = region.getPosY (i, j); + data.ZoneName = region.getName (i, j); + data.Rot = region.getRot (i, j); + data.Flip = region.getFlip (i, j); + data.SharingMatNames[0] = region.getSharingMatNames (i, j, 0); + data.SharingMatNames[1] = region.getSharingMatNames (i, j, 1); + data.SharingMatNames[2] = region.getSharingMatNames (i, j, 2); + data.SharingMatNames[3] = region.getSharingMatNames (i, j, 3); + data.SharingCutEdges[0] = region.getSharingCutEdges (i, j, 0); + data.SharingCutEdges[1] = region.getSharingCutEdges (i, j, 1); + data.SharingCutEdges[2] = region.getSharingCutEdges (i, j, 2); + data.SharingCutEdges[3] = region.getSharingCutEdges (i, j, 3); + } + else + { + // By default + data.PosX = 0; + data.PosY = 0; + data.ZoneName = ""; + data.Rot = 0; + data.Flip = 0; + data.SharingMatNames[0] = ""; + data.SharingMatNames[1] = ""; + data.SharingMatNames[2] = ""; + data.SharingMatNames[3] = ""; + data.SharingCutEdges[0] = 0; + data.SharingCutEdges[1] = 0; + data.SharingCutEdges[2] = 0; + data.SharingCutEdges[3] = 0; + } + } + region.resize (_NewMinX, _NewMaxX, _NewMinY, _NewMaxY); + + for (j = _NewMinY; j <= _NewMaxY; ++j) + for (i = _NewMinX; i <= _NewMaxX; ++i) + { + // Ref on the new value + const CLigoData &data = newZones[(i-_NewMinX)+(j-_NewMinY)*newStride]; + + region.setName (i, j, data.ZoneName); + region.setPosX (i, j, data.PosX); + region.setPosY (i, j, data.PosY); + region.setRot (i, j, data.Rot); + region.setFlip (i, j, data.Flip); + uint k; + for (k=0; k<4; k++) + { + region.setSharingMatNames (i, j, k, data.SharingMatNames[k]); + region.setSharingCutEdges (i, j, k, data.SharingCutEdges[k]); + } + } + + doc->modifyDatabase (_Index); + return true; +} + +// *************************************************************************** +// CActionImportPrimitive +// *************************************************************************** + +CActionImportPrimitive::CActionImportPrimitive (const char *oldPrimFile) +{ + _Filename = oldPrimFile; + _FirstLoad = true; +} + +// *************************************************************************** + +void CActionImportPrimitive::undo () +{ + // Check we have a primitive + CWorldEditorDoc *doc = getDocument (); + nlassert (doc->_DataHierarchy.size () > 0); + + // Remove back primitive + doc->_DataHierarchy.resize (doc->_DataHierarchy.size ()-1); + doc->_DataHierarchy.recomputePointerArray (); + + // Invalidate tools + getMainFrame ()->invalidateTools (); + InvalidateAllPrimitives (); + + // Modify files + doc->modifyProject (); +} + +// *************************************************************************** + +bool CActionImportPrimitive::redo () +{ + CWorldEditorDoc *doc = getDocument (); + + // First redo ? + if (_FirstLoad) + { + // Load the old primitive + try + { + // The file + CIFile fileIn; + if (fileIn.open (_Filename)) + { + // The region to load + NLLIGO::CPrimRegion region; + + // Load it + CIXml input; + input.init (fileIn); + region.serial (input); + + // Convert it + NLLIGO::CPrimitives Primitives; + Primitives.convert (region); + + if (_Filename.find("audio") != std::string::npos) + { + // import audio prim + + // Create an audio node + IPrimitive *audio = new CPrimNodeEditor; + std::string audioName = region.Name; + audioName = audioName.substr(0, audioName.find(".prim")); + audio->addPropertyByName ("name", new CPropertyString (audioName.c_str())); + audio->addPropertyByName ("class", new CPropertyString ("audio")); + + // Insert the audio node + _Primitive.RootNode->insertChild (audio); + + IPrimitive *sounds = new CPrimNodeEditor; + sounds->addPropertyByName ("name", new CPropertyString ("sounds")); + sounds->addPropertyByName ("class", new CPropertyString ("sounds")); + + // Insert the soundnode + audio->insertChild (sounds); + + IPrimitive *soundBanks = new CPrimNodeEditor; + soundBanks->addPropertyByName ("name", new CPropertyString ("sample_banks")); + soundBanks->addPropertyByName ("class", new CPropertyString ("sample_banks")); + + // Insert the soundnode + audio->insertChild (soundBanks); + + IPrimitive *envFx = new CPrimNodeEditor; + envFx->addPropertyByName ("name", new CPropertyString ("env_fx")); + envFx->addPropertyByName ("class", new CPropertyString ("env_fx")); + + // Insert the soundnode + audio->insertChild (envFx); + + // layer count count + uint count = Primitives.RootNode->getNumChildren (); + + for (uint i=0; igetChild (layer, i)); + + // Get the name + string layerName; + layer->getPropertyByName ("name", layerName); + + // Create a sound_folder node + IPrimitive *soundFolder = new CPrimNodeEditor; + soundFolder->addPropertyByName ("name", new CPropertyString (layerName.c_str ())); + soundFolder->addPropertyByName ("class", new CPropertyString ("sound_folder")); + + // Insert the sound folder node + sounds->insertChild (soundFolder); + + // sound count + uint soundCount = layer->getNumChildren (); + + // Make sounds + for (uint j=0; jgetChild (prim, j)); + + // Get the name + string rawName; + prim->getPropertyByName ("name", rawName); + string name; + uint layerId = 0; + + // extract the sound name and, optinaly, the layer id + uint n = std::count(rawName.begin(), rawName.end(), '-'); + std::vector splited; + + NLMISC::explode(rawName, string("-"), splited); + + if (n == 2) + { + // no layer spec + name = splited[1]; + } + else if (n==3) + { + // layer is specified + name = splited[2]; + layerId = 'a' - splited[1][0]; + clamp(layerId, 0u, NLSOUND::BACKGROUND_LAYER-1); + } + else + { + nlwarning("sound %s have a bad format. Ignoring", rawName.c_str()); + // skip this one + continue; + } + + char layerString[1024]; + sprintf(layerString, "layer_%u", layerId); + + // Path ? + const CPrimPathEditor *path = dynamic_cast (prim); + if (path) + { + // Copy the node + CPrimPathEditor *newPrim = new CPrimPathEditor; + *newPrim = *path; + newPrim->addPropertyByName ("class", new CPropertyString ("sound_path")); + newPrim->removePropertyByName("name"); + newPrim->addPropertyByName ("name", new CPropertyString (name.c_str())); + newPrim->addPropertyByName ("layer", new CPropertyString (layerString)); + + // Add the primitive + soundFolder->insertChild (newPrim); + } + else + { + // Zone ? + const CPrimZoneEditor *zone = dynamic_cast (prim); + if (zone) + { + // Copy the node + CPrimZoneEditor *newPrim = new CPrimZoneEditor; + *newPrim = *zone; + newPrim->addPropertyByName ("class", new CPropertyString ("sound_zone")); + newPrim->removePropertyByName("name"); + newPrim->addPropertyByName ("name", new CPropertyString (name.c_str())); + newPrim->addPropertyByName ("layer", new CPropertyString (layerString)); + + // Add the primitive + soundFolder->insertChild (newPrim); + } + else + { + // point ? + const CPrimPointEditor *point = dynamic_cast (prim); + if (zone) + { + // Copy the node + CPrimPointEditor *newPrim = new CPrimPointEditor; + *newPrim = *point; + newPrim->addPropertyByName ("class", new CPropertyString ("sound_point")); + newPrim->removePropertyByName("name"); + newPrim->addPropertyByName ("name", new CPropertyString (name.c_str())); + newPrim->addPropertyByName ("layer", new CPropertyString (layerString)); + + // Add the primitive + soundFolder->insertChild (newPrim); + } + } + } + } + } + } + else + { + // import flora prim + + // Flora count + uint count = Primitives.RootNode->getNumChildren (); + + // Make flora + for (uint i=0; igetChild (layer, i)); + + // Get the name + string layerName; + layer->getPropertyByName ("name", layerName); + + // Create a flora node + IPrimitive *flora = new CPrimNodeEditor; + flora->addPropertyByName ("name", new CPropertyString (layerName.c_str ())); + flora->addPropertyByName ("class", new CPropertyString ("flora")); + + // Insert the flora node + _Primitive.RootNode->insertChild (flora); + + // Flora count + uint floraCount = layer->getNumChildren (); + + // Make flora + for (uint j=0; jgetChild (prim, j)); + + // Get the name + string name; + prim->getPropertyByName ("name", name); + + // Path ? + const CPrimPathEditor *path = dynamic_cast (prim); + if (path) + { + // Copy the node + CPrimPathEditor *newPrim = new CPrimPathEditor; + *newPrim = *path; + newPrim->addPropertyByName ("class", new CPropertyString ("flora_path")); + + // Add the primitive + flora->insertChild (newPrim); + } + else + { + // Zone ? + const CPrimZoneEditor *zone = dynamic_cast (prim); + if (zone) + { + // Copy the node + CPrimZoneEditor *newPrim = new CPrimZoneEditor; + *newPrim = *zone; + newPrim->addPropertyByName ("class", new CPropertyString ("flora_zone")); + + // Add the primitive + flora->insertChild (newPrim); + } + } + } + } + } + + _FirstLoad = false; + } + else + { + theApp.errorMessage ("Can't open the file (%s) for reading.", _Filename.c_str ()); + return false; + } + } + catch (Exception& e) + { + theApp.errorMessage ("Error reading the file (%s) : (%s).", _Filename.c_str (), e.what ()); + return false; + } + } + + // Push back the primitive + doc->_DataHierarchy.push_back (CWorldEditorDoc::CDatabaseElement (CWorldEditorDoc::CDatabaseElement::Primitive)); + doc->_DataHierarchy.recomputePointerArray (); + doc->_DataHierarchy.back ().Primitives = _Primitive; + + // Update default values + doc->updateDefaultValues (doc->_DataHierarchy.size ()-1); + + // Invalidate tools + getMainFrame ()->invalidateTools (); + InvalidateAllPrimitives (); + + // Modify files + doc->modifyProject (); + + return true; +} + +// *************************************************************************** +// CActionLoadPrimitive +// *************************************************************************** + +CActionLoadPrimitive::CActionLoadPrimitive (const char *oldPrimFile) +{ + _Filename = oldPrimFile; + _FirstLoad = true; +} + +// *************************************************************************** + +void CActionLoadPrimitive::undo () +{ + // Check we have a primitive + CWorldEditorDoc *doc = getDocument (); + nlassert (doc->_DataHierarchy.size () > 0); + + // Remove back primitive + doc->_DataHierarchy.resize (doc->_DataHierarchy.size ()-1); + doc->_DataHierarchy.recomputePointerArray (); + InvalidateAllPrimitives (); + + // Invalidate tools + getMainFrame ()->invalidateTools (); + + // Modify files + doc->modifyProject (); +} + +// *************************************************************************** + +bool CActionLoadPrimitive::redo () +{ + CWorldEditorDoc *doc = getDocument (); + // First redo ? + if (_FirstLoad) + { + // Load the old primitive + try + { + // The file + CIFile fileIn; + if (fileIn.open (_Filename)) + { + // Load it + CIXml input; + input.init (fileIn); + + // Set the primitive context + CPrimitiveContext::instance().CurrentPrimitive = &_Primitive; + // Convert it + _Primitive.read (input.getRootNode (), _Filename.c_str (), theApp.Config); + + // cleanup context + CPrimitiveContext::instance().CurrentPrimitive = NULL; + + _FirstLoad = false; + } + else + { + theApp.errorMessage ("Can't open the file (%s) for reading.", _Filename.c_str ()); + return false; + } + } + catch (Exception& e) + { + theApp.errorMessage ("Error reading the file (%s) : (%s).", _Filename.c_str (), e.what ()); + return false; + } + } + + // Push back the primitive + doc->_DataHierarchy.push_back (CWorldEditorDoc::CDatabaseElement (CWorldEditorDoc::CDatabaseElement::Primitive)); + doc->_DataHierarchy.recomputePointerArray (); + doc->_DataHierarchy.back ().Primitives = _Primitive; + doc->_DataHierarchy.back ().Filename = _Filename; + doc->_DataHierarchy.back ().LastModifedTime = NLMISC::CFile::getFileModificationDate (_Filename); + + // Update default values + doc->updateDefaultValues (doc->_DataHierarchy.size ()-1); + + // Auto generate missing id + doc->resetUniqueID(*(doc->_DataHierarchy.back().Primitives.RootNode), true); + + // Invalidate tools + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); + + // Modify files + doc->modifyProject (); + + return true; +} + +// *************************************************************************** +// CActionNewPrimitive +// *************************************************************************** + +CActionNewPrimitive::CActionNewPrimitive () +{ +} + +// *************************************************************************** + +void CActionNewPrimitive::undo () +{ + CWorldEditorDoc *doc = getDocument (); + // Check we have a primitive + nlassert (doc->_DataHierarchy.size () > 0); + + // Remove back primitive + doc->_DataHierarchy.resize (doc->_DataHierarchy.size ()-1); + doc->_DataHierarchy.recomputePointerArray (); + + // Invalidate tools + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); + + // Modify files + doc->modifyProject (); +} + +// *************************************************************************** + +bool CActionNewPrimitive::redo () +{ + CWorldEditorDoc *doc = getDocument (); + // Push back the primitive + doc->_DataHierarchy.push_back (CWorldEditorDoc::CDatabaseElement (CWorldEditorDoc::CDatabaseElement::Primitive)); + doc->_DataHierarchy.recomputePointerArray (); + + // Invalidate tools + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); + + // Modify files + uint index = doc->_DataHierarchy.size ()-1; + doc->modifyProject (); + doc->modifyDatabase (index); + + return true; +} + +// *************************************************************************** +// CActionClearPrimitives +// *************************************************************************** + +CActionClearPrimitives::CActionClearPrimitives () +{ + // Copy the primitives + CWorldEditorDoc *doc = getDocument (); + _Primitives = doc->_DataHierarchy; +} + +// *************************************************************************** + +void CActionClearPrimitives::undo () +{ + CWorldEditorDoc *doc = getDocument (); + // Remove all the primitives + doc->_DataHierarchy = _Primitives; + + // Invalidate + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); + + // Modify files + doc->modifyProject (); +} + +// *************************************************************************** + +bool CActionClearPrimitives::redo () +{ + CWorldEditorDoc *doc = getDocument (); + // Remove all the primitives + doc->_DataHierarchy.clear (); + doc->_DataHierarchy.recomputePointerArray (); + + // Invalidate + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); + + // Modify files + doc->modifyProject (); + + return true; +} + +// *************************************************************************** +// CActionUnselectAll +// *************************************************************************** + +CActionUnselectAll::CActionUnselectAll () +{ + CWorldEditorDoc *doc = getDocument (); + doc->modifyPropertyDlg(); + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Primitive ? + if (locator.Primitive) + { + // Add this locator + _SelectedPrimitives.push_back (locator); + } + + ite++; + } +} + +// *************************************************************************** + +void CActionUnselectAll::undo () +{ + CWorldEditorDoc *doc = getDocument (); + for (uint i=0; i<_SelectedPrimitives.size (); i++) + { + // Get the locator pointer + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _SelectedPrimitives[i]); + + // Select the primitive + if (!getPrimitiveEditor(locator.Primitive)->getSelected()) +// if (const_cast(locator.Primitive)->addPropertyByName ("selected", new CPropertyString ())) + { + getPrimitiveEditor(locator.Primitive)->setSelected(true); + InvalidatePrimitive (locator, SelectionState); + invalidateLeftView (); + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + } + } +} + +// *************************************************************************** + +bool CActionUnselectAll::redo () +{ + CWorldEditorDoc *doc = getDocument (); + bool modified = false; + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Primitive ? + if (locator.Primitive) + { + // Remove selected flag + if (getPrimitiveEditor(locator.Primitive)->getSelected()) +// if (const_cast(locator.Primitive)->removePropertyByName ("selected")) + { + getPrimitiveEditor(locator.Primitive)->setSelected(false); + //modified = true; + InvalidatePrimitive (locator, SelectionState); + invalidateLeftView (); + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + } + } + + ite++; + } + + return modified; +} + +// *************************************************************************** +// CActionSelectAll +// *************************************************************************** + +CActionSelectAll::CActionSelectAll () +{ + CWorldEditorDoc *doc = getDocument (); + doc->modifyPropertyDlg(); + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Primitive ? + if (locator.Primitive) + { + // Add this locator + _SelectedPrimitives.push_back (locator); + } + + ite++; + } +} + +// *************************************************************************** + +void CActionSelectAll::undo () +{ + CWorldEditorDoc *doc = getDocument (); + CDatabaseLocatorPointer locator; + doc->getFirstLocator (locator); + do + { + // Primitive ? + if (locator.Primitive) + { + // Remove selected flag + if (getPrimitiveEditor(locator.Primitive)->getSelected()) +// if (const_cast(locator.Primitive)->removePropertyByName ("selected")) + { + getPrimitiveEditor(locator.Primitive)->setSelected(false); + InvalidatePrimitive (locator, SelectionState); + invalidateLeftView (); + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + } + } + } + while (locator.next ()); + + for (uint i=0; i<_SelectedPrimitives.size (); i++) + { + // Get the locator pointer + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _SelectedPrimitives[i]); + + // Select the primitive + if (!getPrimitiveEditor(locator.Primitive)->getSelected()) +// if (const_cast(locator.Primitive)->addPropertyByName ("selected", new CPropertyString ())) + { + getPrimitiveEditor(locator.Primitive)->setSelected(false); + InvalidatePrimitive (locator, SelectionState); + invalidateLeftView (); + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + } + } +} + +// *************************************************************************** + +bool CActionSelectAll::redo () +{ + bool modified = false; + CWorldEditorDoc *doc = getDocument (); + CDatabaseLocatorPointer locator; + doc->getFirstLocator (locator); + do + { + // Primitive ? + if (locator.Primitive) + { + // Remove selected flag + if (!getPrimitiveEditor(locator.Primitive)->getSelected()) +// if (const_cast(locator.Primitive)->addPropertyByName ("selected", new CPropertyString ())) + { + getPrimitiveEditor(locator.Primitive)->setSelected(true); + // modified = true; + InvalidatePrimitive (locator, SelectionState); + invalidateLeftView (); + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + } + } + } + while (locator.next ()); + + return modified; +} + +// *************************************************************************** +// CActionSelect +// *************************************************************************** + +CActionSelect::CActionSelect (const CDatabaseLocator &locator) +{ + getDocument()->modifyPropertyDlg(); + _Locator = locator; +} + +// *************************************************************************** + +void CActionSelect::undo () +{ + CWorldEditorDoc *doc = getDocument (); + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + if (locator.Primitive) + { + // Select it +// nlverify (const_cast(locator.Primitive)->removePropertyByName ("selected")); + getPrimitiveEditor(locator.Primitive)->setSelected(false); + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate selection + InvalidatePrimitive (locator, SelectionState); + invalidateLeftView (); + } +} + +// *************************************************************************** + +bool CActionSelect::redo () +{ + CWorldEditorDoc *doc = getDocument (); + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + if (locator.Primitive) + { + // Select it + if (!getPrimitiveEditor(locator.Primitive)->getSelected()) +// if (const_cast(locator.Primitive)->addPropertyByName ("selected", new CPropertyString ())) + { + getPrimitiveEditor(locator.Primitive)->setSelected(true); + // Invalidate selection + InvalidatePrimitive (locator, SelectionState); + invalidateLeftView (); + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + + // return true; + } + } + return false; +} + +// *************************************************************************** +// CActionUnselect +// *************************************************************************** + +CActionUnselect::CActionUnselect (const CDatabaseLocator &locator) +{ + getDocument()->modifyPropertyDlg(); + _Locator = locator; +} + +// *************************************************************************** + +void CActionUnselect::undo () +{ + CWorldEditorDoc *doc = getDocument (); + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + if (locator.Primitive) + { + // Select it +// nlverify (const_cast(locator.Primitive)->addPropertyByName ("selected", new CPropertyString ())); + getPrimitiveEditor(locator.Primitive)->setSelected(true); + + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate selection + InvalidatePrimitive (locator, SelectionState); + invalidateLeftView (); + } +} + +// *************************************************************************** + +bool CActionUnselect::redo () +{ + CWorldEditorDoc *doc = getDocument (); + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + if (locator.Primitive) + { + // Select it + if (getPrimitiveEditor(locator.Primitive)->getSelected()) +// if (const_cast(locator.Primitive)->removePropertyByName ("selected")) + { + getPrimitiveEditor(locator.Primitive)->setSelected(false); + // Invalidate selection + InvalidatePrimitive (locator, SelectionState); + invalidateLeftView (); + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + + return true; + } + } + return false; +} + +// *************************************************************************** + +// *************************************************************************** +// CActionUnselectAllSub +// *************************************************************************** + +CActionUnselectAllSub::CActionUnselectAllSub () +{ + CWorldEditorDoc *doc = getDocument (); + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Primitive ? + if (locator.Primitive) + { + // Selected ? +// IProperty *prop; + if (getPrimitiveEditor(locator.Primitive)->getSelected()) +// if (locator.Primitive->getPropertyByName ("selected", prop)) + { + // Scan its subvertex + uint numVert = locator.Primitive->getNumVector (); + if (numVert) + { + const CPrimVector *vectors = locator.Primitive->getPrimVector (); + for (uint vert=0; vertgetLocator (locator, subLocator); + + // Select its subvertex + nlassert ((uint)subLocator.XSubPrim < locator.Primitive->getNumVector ()); + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + if (vectors[subLocator.XSubPrim].Selected == false) + { + vectors[subLocator.XSubPrim].Selected = true; + modified = true; + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + } + } + + // Invalidate selection + if (modified) + invalidateLeftView (); +} + +// *************************************************************************** + +bool CActionUnselectAllSub::redo () +{ + CWorldEditorDoc *doc = getDocument (); + bool modified = false; + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Primitive ? + if (locator.Primitive) + { + // Selected ? +// IProperty *prop; + if (getPrimitiveEditor(locator.Primitive)->getSelected()) +// if (locator.Primitive->getPropertyByName ("selected", prop)) + { + // Scan its subvertex + uint numVert = locator.Primitive->getNumVector (); + if (numVert) + { + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + for (uint vert=0; vertmodifyDatabase (locator.getDatabaseIndex ()); + } + } + } + } + } + + ite++; + } + + // Invalidate selection + if (modified) + invalidateLeftView (); + + return modified; +} + +// *************************************************************************** +// CActionSelectAllSub +// *************************************************************************** + +CActionSelectAllSub::CActionSelectAllSub () +{ + CWorldEditorDoc *doc = getDocument (); + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Primitive ? + if (locator.Primitive) + { + // Selected ? +// IProperty *prop; + if (getPrimitiveEditor(locator.Primitive)->getSelected()) +// if (locator.Primitive->getPropertyByName ("selected", prop)) + { + // Scan its subvertex + uint numVert = locator.Primitive->getNumVector (); + if (numVert) + { + const CPrimVector *vectors = locator.Primitive->getPrimVector (); + for (uint vert=0; vertgetLocator (locator, subLocator); + + // Select its subvertex + nlassert ((uint)subLocator.XSubPrim < locator.Primitive->getNumVector ()); + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + if (vectors[subLocator.XSubPrim].Selected) + { + vectors[subLocator.XSubPrim].Selected = false; + modified = true; + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + } + } + + // Invalidate selection + if (modified) + invalidateLeftView (); +} + +// *************************************************************************** + +bool CActionSelectAllSub::redo () +{ + CWorldEditorDoc *doc = getDocument (); + bool modified = false; + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Primitive ? + if (locator.Primitive) + { + // Selected ? +// IProperty *prop; + if (getPrimitiveEditor(locator.Primitive)->getSelected()) +// if (locator.Primitive->getPropertyByName ("selected", prop)) + { + // Scan its subvertex + uint numVert = locator.Primitive->getNumVector (); + if (numVert) + { + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + for (uint vert=0; vertmodifyDatabase (locator.getDatabaseIndex ()); + } + } + } + } + } + + ite++; + } + + // Invalidate selection + if (modified) + invalidateLeftView (); + + return modified; +} + +// *************************************************************************** +// CActionSelectSub +// *************************************************************************** + +CActionSelectSub::CActionSelectSub (const CDatabaseLocator &locator) +{ + _Locator = locator; +} + +// *************************************************************************** + +void CActionSelectSub::undo () +{ + CWorldEditorDoc *doc = getDocument (); + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + if (locator.Primitive) + { + // Select its subvertex + nlassert ((uint)_Locator.XSubPrim < locator.Primitive->getNumVector ()); + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + nlassert (vectors[_Locator.XSubPrim].Selected); + vectors[_Locator.XSubPrim].Selected = false; + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate selection + invalidateLeftView (); + } +} + +// *************************************************************************** + +bool CActionSelectSub::redo () +{ + CWorldEditorDoc *doc = getDocument (); + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + if (locator.Primitive) + { + // Select its subvertex + nlassert ((uint)_Locator.XSubPrim < locator.Primitive->getNumVector ()); + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + if (!vectors[_Locator.XSubPrim].Selected) + { + vectors[_Locator.XSubPrim].Selected = true; + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate selection + invalidateLeftView (); + return true; + } + } + return false; +} + +// *************************************************************************** +// CActionUnselectSub +// *************************************************************************** + +CActionUnselectSub::CActionUnselectSub (const CDatabaseLocator &locator) +{ + _Locator = locator; +} + +// *************************************************************************** + +void CActionUnselectSub::undo () +{ + CWorldEditorDoc *doc = getDocument (); + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + if (locator.Primitive) + { + // Select its subvertex + nlassert ((uint)_Locator.XSubPrim < locator.Primitive->getNumVector ()); + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + nlassert (!vectors[_Locator.XSubPrim].Selected); + vectors[_Locator.XSubPrim].Selected = true; + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate selection + invalidateLeftView (); + } +} + +// *************************************************************************** + +bool CActionUnselectSub::redo () +{ + CWorldEditorDoc *doc = getDocument (); + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + if (locator.Primitive) + { + // Select its subvertex + nlassert ((uint)_Locator.XSubPrim < locator.Primitive->getNumVector ()); + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + if (vectors[_Locator.XSubPrim].Selected) + { + vectors[_Locator.XSubPrim].Selected = false; + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate selection + invalidateLeftView (); + return true; + } + } + return false; +} + +// *************************************************************************** +// CActionMove +// *************************************************************************** + +CActionMove::CActionMove (bool subSelection) +{ + CWorldEditorDoc *doc = getDocument (); + // Sub selection ? + _SubSelection = subSelection; + + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Primitive ? + if (locator.Primitive) + { + // Shown ? +// IProperty *prop; + if (isPrimitiveVisible (locator.Primitive)) +// if (!locator.Primitive->getPropertyByName ("hidden", prop)) + { + // Scan its subvertex + uint numVert = locator.Primitive->getNumVector (); + if (numVert) + { + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + for (uint vert=0; vertgetLocator (locator, entry.Locator); + + // Select its subvertex + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + vectors[entry.Locator.XSubPrim].CVector::operator= (entry.OldPosition); + + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate quad grid + InvalidatePrimitive (locator, QuadTree); + } + + // Invalidate selection + invalidateLeftView (); +} + +// *************************************************************************** + +bool CActionMove::redo () +{ + if (_Translation.isNull ()) + return false; + + CWorldEditorDoc *doc = getDocument (); + for (uint i=0; i<_Entities.size (); i++) + { + // Get the locator pointer + CUndoEntry &entry = _Entities[i]; + CDatabaseLocatorPointer locator; + doc->getLocator (locator, entry.Locator); + + // Select its subvertex + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + vectors[entry.Locator.XSubPrim].CVector::operator= (entry.OldPosition); + vectors[entry.Locator.XSubPrim].CVector::operator+= (_Translation); + + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate quad grid + InvalidatePrimitive (locator, QuadTree); + } + + // Invalidate selection + invalidateLeftView (); + + return true; +} + +// *************************************************************************** + +bool CActionMove::getText (string &result) +{ + result = toString ("Move %.2f, %.2f", _Translation.x, _Translation.y); + return true; +} + +// *************************************************************************** +// CActionRotate +// *************************************************************************** + +CActionRotate::CActionRotate (bool subSelection, const CVector &pivot) +{ + CWorldEditorDoc *doc = getDocument (); + // Sub selection ? + _SubSelection = subSelection; + + // Pivot ? + Pivot = pivot; + + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Primitive ? + if (locator.Primitive) + { + // Shown ? +// IProperty *prop; + if (isPrimitiveVisible (locator.Primitive)) +// if (!locator.Primitive->getPropertyByName ("hidden", prop)) + { + // Scan its subvertex + uint numVert = locator.Primitive->getNumVector (); + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + const CPrimPointEditor *pointPrim = dynamic_cast (locator.Primitive); + for (uint vert=0; vertAngle:0)); + + // Set the sub index + _Entities.back ().Locator.XSubPrim = vert; + } + } + } + } + + ite++; + } + _Rotate = false; + _Turn = false; +} + +// *************************************************************************** + +void CActionRotate::setAngle (float angle, bool rotate, bool turn) +{ + _Angle = angle; + _Rotate = rotate; + _Turn = turn; +} + +// *************************************************************************** + +void CActionRotate::undo () +{ + CWorldEditorDoc *doc = getDocument (); + for (uint i=0; i<_Entities.size (); i++) + { + // Get the locator pointer + CUndoEntry &entry = _Entities[i]; + CDatabaseLocatorPointer locator; + doc->getLocator (locator, entry.Locator); + + // Select its subvertex + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + vectors[entry.Locator.XSubPrim].CVector::operator= (entry.OldPosition); + + // Restaure the turn + if (entry.PointPrimitive) + { + CPrimPointEditor *primPoint = safe_cast (const_cast (locator.Primitive)); + primPoint->Angle = entry.PointPrimitiveAngle; + } + + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate quad grid + InvalidatePrimitive (locator, QuadTree); + } + + // Invalidate selection + invalidateLeftView (); +} + +// *************************************************************************** + +bool CActionRotate::redo () +{ + if (_Angle == 0 || (!_Turn && !_Rotate)) + return false; + + CWorldEditorDoc *doc = getDocument (); + for (uint i=0; i<_Entities.size (); i++) + { + // Get the locator pointer + CUndoEntry &entry = _Entities[i]; + CDatabaseLocatorPointer locator; + doc->getLocator (locator, entry.Locator); + + // Select its subvertex + bool modified = false; + if (_Rotate) + { + // Select its subvertex + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + vectors[entry.Locator.XSubPrim].CVector::operator= (entry.OldPosition); + + // Transform point + transformVector (vectors[entry.Locator.XSubPrim], _Angle, Pivot); + modified = true; + } + + // Transform point + if (_Turn && entry.PointPrimitive) + { + // Select its subvertex + CPrimPointEditor *primPoint = safe_cast (const_cast (locator.Primitive)); + primPoint->Angle = entry.PointPrimitiveAngle; + primPoint->Angle += _Angle; + modified = true; + } + + if (modified) + { + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate quad grid + InvalidatePrimitive (locator, QuadTree); + } + } + + // Invalidate selection + invalidateLeftView (); + + return true; +} + +// *************************************************************************** + +bool CActionRotate::getText (string &result) +{ + result = toString ("Rotate %.2f degrees", 180*_Angle/Pi); + return true; +} + +// *************************************************************************** + +bool CActionRotate::getHelp (string &result) +{ + result = "Turn with CTRL"; + return _Rotate; +} + +// *************************************************************************** +// CActionScale +// *************************************************************************** + +CActionScale::CActionScale (bool subSelection, const CVector &pivot) +{ + CWorldEditorDoc *doc = getDocument (); + // Sub selection ? + _SubSelection = subSelection; + + // Pivot + Pivot = pivot; + + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Primitive ? + if (locator.Primitive) + { + // Shown ? +// IProperty *prop; + if (isPrimitiveVisible (locator.Primitive)) +// if (!locator.Primitive->getPropertyByName ("hidden", prop)) + { + // Scan its subvertex + uint numVert = locator.Primitive->getNumVector (); + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + + // Radius + string radius; + const bool hasRadius = locator.Primitive->getPropertyByName ("radius", radius); + + for (uint vert=0; vertgetLocator (locator, entry.Locator); + + // Select its subvertex + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + vectors[entry.Locator.XSubPrim].CVector::operator= (entry.OldPosition); + + // Does it have radius ? + if (entry.HasRadius) + { + const_cast (locator.Primitive)->removePropertyByName ("radius"); + const_cast (locator.Primitive)->addPropertyByName ("radius", new CPropertyString (toString (entry.Radius).c_str())); + } + + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate quad grid + InvalidatePrimitive (locator, QuadTree); + } + + // Invalidate selection + invalidateLeftView (); +} + +// *************************************************************************** + +bool CActionScale::redo () +{ + if ((_Factor == 1.f) || (!_Scale && !_Radius)) + return false; + + CWorldEditorDoc *doc = getDocument (); + for (uint i=0; i<_Entities.size (); i++) + { + // Get the locator pointer + CUndoEntry &entry = _Entities[i]; + CDatabaseLocatorPointer locator; + doc->getLocator (locator, entry.Locator); + + bool modified = false; + + if (_Scale) + { + // Select its subvertex + CPrimVector *vectors = const_cast (locator.Primitive->getPrimVector ()); + vectors[entry.Locator.XSubPrim].CVector::operator= (entry.OldPosition); + vectors[entry.Locator.XSubPrim].CVector::operator-= (Pivot); + vectors[entry.Locator.XSubPrim].CVector::operator*= (_Factor); + vectors[entry.Locator.XSubPrim].CVector::operator+= (Pivot); + modified = true; + } + + if (_Radius) + { + const_cast (locator.Primitive)->removePropertyByName ("radius"); + const_cast (locator.Primitive)->addPropertyByName ("radius", new CPropertyString (toString (entry.Radius*_Factor).c_str())); + modified = true; + } + + if (modified) + { + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate quad grid + InvalidatePrimitive (locator, QuadTree); + } + } + + // Invalidate selection + invalidateLeftView (); + + return true; +} + +// *************************************************************************** + +bool CActionScale::getText (string &result) +{ + result = toString ("Scale %.2f%%", _Factor*100); + return true; +} + +// *************************************************************************** + +bool CActionScale::getHelp (string &result) +{ + result = "Radius with CTRL"; + return _Scale; +} + +// *************************************************************************** +// CActionAddVertex +// *************************************************************************** + +CActionAddVertex::CActionAddVertex (const CDatabaseLocator &locator, const CVector &newVertex) +{ + // Save the locator + _Locator = locator; + _NewVertex = newVertex; +} + +// *************************************************************************** + +void CActionAddVertex::undo () +{ + CWorldEditorDoc *doc = getDocument (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Is a path or a zone ? + std::vector *primVector = NULL; + CPrimPathEditor *path = dynamic_cast (const_cast (locator.Primitive)); + if (path) + primVector = &path->VPoints; + else + { + CPrimZoneEditor *zone = dynamic_cast (const_cast (locator.Primitive)); + if (zone) + primVector = &zone->VPoints; + } + + // Found ? + nlverify (primVector); + + // Delete the vertex + primVector->erase (primVector->begin ()+(_Locator.XSubPrim+1)); + + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate quad grid + InvalidatePrimitive (locator, QuadTree); +} + +// *************************************************************************** + +bool CActionAddVertex::redo () +{ + CWorldEditorDoc *doc = getDocument (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Is a path or a zone ? + std::vector *primVector = NULL; + CPrimPathEditor *path = dynamic_cast (const_cast (locator.Primitive)); + if (path) + primVector = &path->VPoints; + else + { + CPrimZoneEditor *zone = dynamic_cast (const_cast (locator.Primitive)); + if (zone) + primVector = &zone->VPoints; + } + + // Found ? + nlverify (primVector); + + // Insert a vertex + primVector->insert (primVector->begin ()+(_Locator.XSubPrim+1), CPrimVector()); + + // Initialise it + (*primVector)[_Locator.XSubPrim+1].CVector::operator= (_NewVertex); + + // Not selected + (*primVector)[_Locator.XSubPrim+1].Selected = false; + + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate quad grid + InvalidatePrimitive (locator, QuadTree); + + return true; +} + +// *************************************************************************** +// CActionDeleteSub +// *************************************************************************** + +CActionDeleteSub::CActionDeleteSub (const CDatabaseLocatorPointer &locator) +{ + // Save the locator + _Locator = locator; + + // Is a path or a zone ? + std::vector *primVector = NULL; + CPrimPathEditor *path = dynamic_cast (const_cast (locator.Primitive)); + if (path) + primVector = &path->VPoints; + else + { + CPrimZoneEditor *zone = dynamic_cast (const_cast (locator.Primitive)); + if (zone) + primVector = &zone->VPoints; + } + + // Found ? + nlverify (primVector); + + // Delete the vertex + _OldVertex = (*primVector)[_Locator.XSubPrim]; +} + +// *************************************************************************** + +void CActionDeleteSub::undo () +{ + CWorldEditorDoc *doc = getDocument (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Is a path or a zone ? + std::vector *primVector = NULL; + CPrimPathEditor *path = dynamic_cast (const_cast (locator.Primitive)); + if (path) + primVector = &path->VPoints; + else + { + CPrimZoneEditor *zone = dynamic_cast (const_cast (locator.Primitive)); + if (zone) + primVector = &zone->VPoints; + } + + // Found ? + nlverify (primVector); + + // Insert a vertex + primVector->insert (primVector->begin ()+_Locator.XSubPrim, CPrimVector()); + + // Initialise it + (*primVector)[_Locator.XSubPrim] = (_OldVertex); + + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate left view + invalidateLeftView (); + + // Invalidate quad grid + InvalidatePrimitive (locator, QuadTree); +} + +// *************************************************************************** + +bool CActionDeleteSub::redo () +{ + CWorldEditorDoc *doc = getDocument (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Is a path or a zone ? + std::vector *primVector = NULL; + CPrimPathEditor *path = dynamic_cast (const_cast (locator.Primitive)); + if (path) + primVector = &path->VPoints; + else + { + CPrimZoneEditor *zone = dynamic_cast (const_cast (locator.Primitive)); + if (zone) + primVector = &zone->VPoints; + } + + // Found ? + nlverify (primVector); + + // Delete the vertex + primVector->erase (primVector->begin ()+_Locator.XSubPrim); + + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate left view + invalidateLeftView (); + + // Invalidate quad grid + InvalidatePrimitive (locator, QuadTree); + + return true; +} + +// *************************************************************************** +// CActionDelete +// *************************************************************************** + +CActionDelete::CActionDelete (const CDatabaseLocatorPointer &locator) +{ + // Save the locator + _Locator = locator; + + // Copy the primitive + _OldPrimitive = locator.Primitive->copy (); +} + +// *************************************************************************** + +CActionDelete::~CActionDelete () +{ + delete _OldPrimitive; +} + +// *************************************************************************** + +void CActionDelete::undo () +{ + CWorldEditorDoc *doc = getDocument (); + + // Copy the primtive + IPrimitive *copy = _OldPrimitive->copy (); + + // Insert it + doc->insertPrimitive (_Locator, copy); + + // Modify files + doc->modifyDatabase (_Locator.getDatabaseIndex ()); + + // Invalidate left view + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Invalidate quad grid + InvalidatePrimitiveRec (locator, QuadTree|LogicTreeStruct|SelectionState); +} + +// *************************************************************************** + +bool CActionDelete::redo () +{ + CWorldEditorDoc *doc = getDocument (); + + doc->deletePrimitive (_Locator); + + // Modify files + doc->modifyDatabase (_Locator.getDatabaseIndex ()); + + // Invalidate left view + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Invalidate quad grid + // Will be removed from the quad grid by the IPrimitiveEditor destructor + + return true; +} + +// *************************************************************************** +// CActionSetPrimitivePropertyString +// *************************************************************************** + +CActionSetPrimitivePropertyString::CActionSetPrimitivePropertyString (const CDatabaseLocatorPointer &locator, const char *propertyName, const char *newValue, bool _default) +{ + _PropertyName = propertyName; + _PropertyNewValue = newValue; + _PropertyNewValueDefault = _default; + _Locator = locator; + + // Backup old value + const IProperty *prop; + _OldExist = locator.Primitive->getPropertyByName (propertyName, prop); + + if (_OldExist) + { + // Dynamic cast + const CPropertyString *propString = dynamic_cast (prop); + nlassert (propString); + _PropertyOldValue = propString->String; + _PropertyOldValueDefault = propString->Default; + } +} + +// *************************************************************************** + +void CActionSetPrimitivePropertyString::undo () +{ + CWorldEditorDoc *doc = getDocument (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Remove the old property + const_cast (locator.Primitive)->removePropertyByName (_PropertyName.c_str ()); + + // Add the old property + if (_OldExist) + const_cast (locator.Primitive)->addPropertyByName (_PropertyName.c_str (), new CPropertyString (_PropertyOldValue.c_str (), _PropertyOldValueDefault)); + + // Invalidate tools + getMainFrame ()->invalidateToolsParam (); + InvalidatePrimitive (locator, LogicTreeParam); + + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate right view + invalidateLeftView (); +} + +// *************************************************************************** + +bool CActionSetPrimitivePropertyString::redo () +{ + CWorldEditorDoc *doc = getDocument (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Remove the old property + const_cast (locator.Primitive)->removePropertyByName (_PropertyName.c_str ()); + + // Add the new property + const_cast (locator.Primitive)->addPropertyByName (_PropertyName.c_str (), new CPropertyString (_PropertyNewValue.c_str (), _PropertyNewValueDefault)); + + // Invalidate tools + getMainFrame ()->invalidateToolsParam (); + InvalidatePrimitive (locator, LogicTreeParam); + + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate right view + invalidateLeftView (); + + return true; +} + +// *************************************************************************** +// CActionSetPrimitivePropertyStringArray +// *************************************************************************** + +CActionSetPrimitivePropertyStringArray::CActionSetPrimitivePropertyStringArray (const CDatabaseLocatorPointer &locator, const char *propertyName, const std::vector &newValue, bool _default) +{ + _PropertyName = propertyName; + _PropertyNewValue = newValue; + _Locator = locator; + _PropertyNewValueDefault = _default; + + // Backup old value + const IProperty *prop; + _OldExist = locator.Primitive->getPropertyByName (propertyName, prop); + + if (_OldExist) + { + // Dynamic cast + const CPropertyStringArray *propStringArray = dynamic_cast (prop); + nlassert (propStringArray); + _PropertyOldValue = propStringArray->StringArray; + _PropertyOldValueDefault = propStringArray->Default; + } +} + +// *************************************************************************** + +void CActionSetPrimitivePropertyStringArray::undo () +{ + CWorldEditorDoc *doc = getDocument (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Remove the old property + const_cast (locator.Primitive)->removePropertyByName (_PropertyName.c_str ()); + + // Add the old property + if (_OldExist) + const_cast (locator.Primitive)->addPropertyByName (_PropertyName.c_str (), new CPropertyStringArray (_PropertyOldValue, _PropertyOldValueDefault)); + + // Invalidate tools + getMainFrame ()->invalidateToolsParam (); + + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); +} + +// *************************************************************************** + +bool CActionSetPrimitivePropertyStringArray::redo () +{ + CWorldEditorDoc *doc = getDocument (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Remove the old property + const_cast (locator.Primitive)->removePropertyByName (_PropertyName.c_str ()); + + // Add the new property + const_cast (locator.Primitive)->addPropertyByName (_PropertyName.c_str (), new CPropertyStringArray (_PropertyNewValue, _PropertyNewValueDefault)); + + // Invalidate tools + getMainFrame ()->invalidateToolsParam (); + + // Modify files + doc->modifyDatabase (locator.getDatabaseIndex ()); + + return true; +} + +// *************************************************************************** +// CActionAddPrimitiveByClass +// *************************************************************************** + +CActionAddPrimitiveByClass::CActionAddPrimitiveByClass (const CDatabaseLocator &locator, const char *className, + const NLMISC::CVector &initPos, float deltaPos, + const std::vector initParameters) +{ + _Locator = locator; + _ClassName = className; + _OldPrimitive = NULL; + _InitPos = initPos; + _DeltaPos = deltaPos; + _InitParameters = initParameters; +} + +// *************************************************************************** + +void CActionAddPrimitiveByClass::undo () +{ + CWorldEditorDoc *doc = getDocument (); + + // Delete the primitive + doc->deletePrimitive (_Locator); + + // Invalidate left view + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Modify files + doc->modifyDatabase (_Locator.getDatabaseIndex ()); + + // Invalidate quad grid + // Will be removed from the quad grid by the IPrimitiveEditor destructor +} + +// *************************************************************************** + +bool CActionAddPrimitiveByClass::redo () +{ + CWorldEditorDoc *doc = getDocument (); + + // First time ? + if (_OldPrimitive == NULL) + { + + // Get the primitive + CDatabaseLocator _parent = _Locator; + _parent.getParent (); + CDatabaseLocatorPointer parent; + doc->getLocator (parent, _parent); + + // Get the class primitive + IPrimitive *primitive = const_cast (doc->createPrimitive (_Locator, _ClassName.c_str (), "", _InitPos, _DeltaPos, _InitParameters)); + // IPrimitive *primitive = const_cast (doc->createPrimitive (_Locator, _ClassName.c_str (), (_ClassName+"_"+toString (parent.Primitive->getNumChildren ())).c_str (), _InitPos, _DeltaPos, _InitParameters)); + if (primitive != NULL) + { + // Invalidate left view + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Modify files + doc->modifyDatabase (_Locator.getDatabaseIndex ()); + + // Final name + string name; + if (!primitive->getPropertyByName ("name", name) || name.empty()) + { + string newValue = _ClassName+"_"+toString (parent.Primitive->getNumChildren ()); + if (!newValue.empty()) + doc->addModification (new CActionSetPrimitivePropertyString (locator, "name", newValue.c_str (), false)); + } + + // Backup it + _OldPrimitive = locator.Primitive->copy (); + + // Invalidate quad grid + InvalidatePrimitiveRec (locator, QuadTree|LogicTreeStruct|SelectionState); + return true; + } + } + else + { + // Make a copy + IPrimitive *copy = _OldPrimitive->copy (); + // Second time, restaure backuped primitive + doc->insertPrimitive (_Locator, copy); + + // Modify files + doc->modifyDatabase (_Locator.getDatabaseIndex ()); + + // Invalidate left view + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Invalidate quad grid + InvalidatePrimitiveRec (locator, QuadTree|LogicTreeStruct|SelectionState); + + return true; + } + + return false; +} + +// *************************************************************************** +// CActionAddLandscape +// *************************************************************************** + +CActionAddLandscape::CActionAddLandscape (const char *filename) +{ + _FirstTime = true; + _Filename = filename; +} + +// *************************************************************************** + +void CActionAddLandscape::undo () +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Remove last landscape + doc->_DataHierarchy.resize (doc->_DataHierarchy.size ()-1); + doc->_DataHierarchy.recomputePointerArray (); + + // Modify files + doc->modifyProject (); + + // Invalidate all + invalidateLeftView (); + getMainFrame ()->invalidateLandscape (); + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); +} + +// *************************************************************************** + +bool CActionAddLandscape::redo () +{ + // Disable events + CNoInteraction nointeraction; + + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Result + bool result = true; + + if (_FirstTime) + { + // Load the file + getMainFrame ()->launchLoadingDialog (string("loading land ") + _Filename); + + try + { + // Open it + CIFile fileIn; + if (fileIn.open (_Filename)) + { + CIXml xml(true); + xml.init (fileIn); + _NewRegion.serial (xml); + } + else + { + getMainFrame ()->terminateLoadingDialog (); + theApp.errorMessage ("Can't open file %s for reading", _Filename.c_str ()); + result = false; + } + } + catch (Exception& e) + { + getMainFrame ()->terminateLoadingDialog (); + theApp.errorMessage ("Error reading file %s : %s", _Filename.c_str (), e.what ()); + result = false; + } + + // Done + getMainFrame ()->terminateLoadingDialog (); + _FirstTime = false; + } + + if (result) + { + // Push the landscape + doc->_DataHierarchy.push_back (CWorldEditorDoc::CDatabaseElement (CWorldEditorDoc::CDatabaseElement::Landscape)); + doc->_DataHierarchy.recomputePointerArray (); + doc->_DataHierarchy.back ().ZoneRegion = _NewRegion; + doc->_DataHierarchy.back ().Filename = _Filename; + doc->_DataHierarchy.back ().LastModifedTime = NLMISC::CFile::getFileModificationDate (_Filename); + + // Init the landscape manager + getMainFrame ()->invalidateLandscape (); + + // Invalidate pointers + InvalidateAllPrimitives (); + + // Modify files + doc->modifyProject (); + + // Invalidate all + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + } + + return result; +} + +// *************************************************************************** +// CActionNewPrimitive +// *************************************************************************** + +CActionNewLandscape::CActionNewLandscape () +{ +} + +// *************************************************************************** + +void CActionNewLandscape::undo () +{ + CWorldEditorDoc *doc = getDocument (); + // Check we have a primitive + nlassert (doc->_DataHierarchy.size () > 0); + + // Remove back primitive + doc->_DataHierarchy.resize (doc->_DataHierarchy.size ()-1); + doc->_DataHierarchy.recomputePointerArray (); + + // Invalidate tools + getMainFrame ()->invalidateLandscape (); + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); + + // Modify files + doc->modifyProject (); +} + +// *************************************************************************** + +bool CActionNewLandscape::redo () +{ + CWorldEditorDoc *doc = getDocument (); + // Push back the primitive + doc->_DataHierarchy.push_back (CWorldEditorDoc::CDatabaseElement (CWorldEditorDoc::CDatabaseElement::Landscape)); + doc->_DataHierarchy.recomputePointerArray (); + + // Invalidate tools + getMainFrame ()->invalidateLandscape (); + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); + + // Modify files + uint index = doc->_DataHierarchy.size ()-1; + doc->modifyProject (); + doc->modifyDatabase (index); + + return true; +} + +// *************************************************************************** + +CActionDeleteDatabaseElement::CActionDeleteDatabaseElement (uint prim) +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Backup the primitive + _Index = prim; + _Primitive = new CWorldEditorDoc::CDatabaseElement (doc->_DataHierarchy[_Index]); +} + +// *************************************************************************** + +CActionDeleteDatabaseElement::~CActionDeleteDatabaseElement () +{ + if (_Primitive) + delete _Primitive; +} + +// *************************************************************************** + +void CActionDeleteDatabaseElement::undo () +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Insert the primitive + std::list::iterator ite = doc->_DataHierarchy.begin(); + for (uint i=0; i<_Index; i++) + ite++; + doc->_DataHierarchy.insert (ite, *_Primitive); + doc->_DataHierarchy.recomputePointerArray (); + + // Is a landscape ? + if (doc->isLandscape (_Index)) + getMainFrame ()->invalidateLandscape (); + + // Modify files + doc->modifyProject (); + + // Invalidate all + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); +} + +// *************************************************************************** + +bool CActionDeleteDatabaseElement::redo () +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Is a landscape ? + if (doc->isLandscape (_Index)) + getMainFrame ()->invalidateLandscape (); + + // Delete the primitive + std::list::iterator ite = doc->_DataHierarchy.begin(); + for (uint i=0; i<_Index; i++) + ite++; + doc->_DataHierarchy.erase (ite); + doc->_DataHierarchy.recomputePointerArray (); + + // Modify files + doc->modifyProject (); + + // Invalidate all + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); + + return true; +} + +// *************************************************************************** +// CActionXChgDatabaseElement +// *************************************************************************** + +CActionXChgDatabaseElement::CActionXChgDatabaseElement (uint prim) +{ + // Backup the primitive + _Index = prim; +} + +// *************************************************************************** + +CActionXChgDatabaseElement::~CActionXChgDatabaseElement () +{ +} + +// *************************************************************************** + +void CActionXChgDatabaseElement::undo () +{ + // Same than redo + redo (); +} + +// *************************************************************************** + +bool CActionXChgDatabaseElement::redo () +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + nlassert (_Index+1 < doc->getNumDatabaseElement ()); + + // Is a landscape ? + if (doc->isLandscape (_Index) || doc->isLandscape (_Index+1)) + getMainFrame ()->invalidateLandscape (); + + // Delete the primitive + uint i; + std::list::iterator ite0 = doc->_DataHierarchy.begin(); + for (i=0; i<_Index; i++) + ite0++; + std::list::iterator ite1 = ite0; + ite1++; + doc->_DataHierarchy.splice (ite0, doc->_DataHierarchy, ite1); + doc->_DataHierarchy.recomputePointerArray (); + + // Modify files + doc->modifyProject (); + + // Invalidate all + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); + + return true; +} + +// *************************************************************************** +// CActionAddPrimitive +// *************************************************************************** + +CActionAddPrimitive::CActionAddPrimitive (const NLLIGO::IPrimitive &primitiveToAdd, const CDatabaseLocator &locator) +{ + _Primitive = primitiveToAdd.copy (); + _Locator = locator; +} + +// *************************************************************************** + +CActionAddPrimitive::CActionAddPrimitive (NLLIGO::IPrimitive *primitiveToAdd, const CDatabaseLocator &locator) +{ + _Primitive = primitiveToAdd; + _Locator = locator; + _FirstTime = true; +} + +// *************************************************************************** + +CActionAddPrimitive::~CActionAddPrimitive () +{ + delete _Primitive; +} + +// *************************************************************************** + +void CActionAddPrimitive::undo () +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Add the primitive + doc->deletePrimitive (_Locator); + + // Modify files + doc->modifyDatabase (_Locator.getDatabaseIndex ()); + + // Invalidate all + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Invalidate quad grid + // Will be removed from the quad grid by the IPrimitiveEditor destructor +} + +// *************************************************************************** + +bool CActionAddPrimitive::redo () +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Make a copy + IPrimitive *copy = _Primitive->copy (); + + // Add the primitive + doc->insertPrimitive (_Locator, copy); + + // Modify files + doc->modifyDatabase (_Locator.getDatabaseIndex ()); + + // Update unique ID + if (_FirstTime) + doc->resetUniqueID (*copy); + + // Invalidate all + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Invalidate quad grid + InvalidatePrimitiveRec (locator, QuadTree|LogicTreeStruct|SelectionState); + + _FirstTime = false; + + // Done + return true; +} + + +// *************************************************************************** +// CActionShowHide +// *************************************************************************** + +CActionShowHide::CActionShowHide (const CDatabaseLocatorPointer &locator, bool show) +{ + _Show = show; + _Locator = locator; +} + +// *************************************************************************** + +void CActionShowHide::undo () +{ + CWorldEditorDoc *doc = getDocument (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Show it ? + if (_Show) + { + // Add the property + getPrimitiveEditor(locator.Primitive)->setHidden(true); + +// nlverify (const_cast(locator.Primitive)->addPropertyByName ("hidden", new CPropertyString (""))); + } + else + { + // Remove the property + getPrimitiveEditor(locator.Primitive)->setHidden(false); +// const IProperty *property; +// nlassert (locator.Primitive->getPropertyByName ("hidden", property)); +// const_cast(locator.Primitive)->removePropertyByName ("hidden"); + } + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate all + invalidateLeftView (); + getMainFrame ()->invalidateToolsParam (); + InvalidatePrimitive (locator, LogicTreeParam); +} + +// *************************************************************************** + +bool CActionShowHide::redo () +{ + CWorldEditorDoc *doc = getDocument (); + + // Get the primitive + CDatabaseLocatorPointer locator; + doc->getLocator (locator, _Locator); + + // Show it ? + if (_Show) + { + // Remove the property + getPrimitiveEditor(locator.Primitive)->setHidden(false); +// const IProperty *property; +// if (!locator.Primitive->getPropertyByName ("hidden", property)) +// // Does not exist +// return false; +// +// // Show it +// nlverify (const_cast(locator.Primitive)->removePropertyByName ("hidden")); + } + else + { + // Add the property + getPrimitiveEditor(locator.Primitive)->setHidden(true); +// const IProperty *property; +// if (locator.Primitive->getPropertyByName ("hidden", property)) +// // Already exist +// return false; +// +// // Add the property +// nlverify (const_cast(locator.Primitive)->addPropertyByName ("hidden", new CPropertyString (""))); + } + + // Modify files + // doc->modifyDatabase (locator.getDatabaseIndex ()); + + // Invalidate all + invalidateLeftView (); + getMainFrame ()->invalidateToolsParam (); + InvalidatePrimitive (locator, LogicTreeParam); + + return true; +} + +// *************************************************************************** diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/action.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/action.h index 9145f4af4..2e5fdb9a9 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/action.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/action.h @@ -1,732 +1,732 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_ACTION_H -#define NL_ACTION_H - -#include "world_editor_doc.h" - - -/** - * Basic editing action - * - * \author Cyril 'Hulud' Corvazier - * \author Nevrax France - * \date 2002 - */ -class IAction -{ -public: - - // Virtual destructor - virtual ~IAction () {} - - // Do / undo - virtual void undo () = 0; - virtual bool redo () = 0; - - // Used to deferentiate selection from real action on the doc - virtual bool isAffectingContent() {return true;} -}; - -// An intermediate base class for selection or hide/show action -class CActionSelectionBase : public IAction -{ - bool isAffectingContent() { return false;} -}; - - -// Add a landscape -class CActionAddLandscape : public IAction -{ -public: - // Landscape name - CActionAddLandscape (const char *name); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - std::string _Filename; - bool _FirstTime; - NLLIGO::CZoneRegion _NewRegion; -}; - -// New landscape document -class CActionNewLandscape : public IAction -{ -public: - - // Constructor - CActionNewLandscape (); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); -}; - -// Modify the landscape -class CActionLigoTile : public IAction -{ -public: - - // Constructor - CActionLigoTile (const CLigoData &data, const CDatabaseLocator &locator); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - void set (const CLigoData &data); - - CDatabaseLocator _Locator; - CLigoData _Old; - CLigoData _New; -}; - -// Move the landscape -class CActionLigoMove : public IAction -{ -public: - - // Constructor - CActionLigoMove (uint index, sint32 deltaX, sint32 deltaY); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - uint _Index; - sint32 _DeltaX; - sint32 _DeltaY; -}; - -// Modify the landscape -class CActionLigoResize : public IAction -{ -public: - - // Constructor - CActionLigoResize (uint index, sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - uint _Index; - sint32 _NewMinX; - sint32 _NewMaxX; - sint32 _NewMinY; - sint32 _NewMaxY; - NLLIGO::CZoneRegion _Old; -}; - -// Import the landscape -class CActionImportPrimitive : public IAction -{ -public: - - // Constructor - CActionImportPrimitive (const char *oldPrimFile); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - bool _FirstLoad; - std::string _Filename; - NLLIGO::CPrimitives _Primitive; -}; - -// Import the landscape -class CActionLoadPrimitive : public IAction -{ -public: - - // Constructor - CActionLoadPrimitive (const char *oldPrimFile); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - bool _FirstLoad; - std::string _Filename; - NLLIGO::CPrimitives _Primitive; -}; - -// New primitive document -class CActionNewPrimitive : public IAction -{ -public: - - // Constructor - CActionNewPrimitive (); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); -}; - -// Clear primitives -class CActionClearPrimitives : public IAction -{ -public: - - // Constructor - CActionClearPrimitives (); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - CWorldEditorDoc::CDatabaseList _Primitives; -}; - -// Delete a primitive -class CActionDeleteDatabaseElement : public IAction -{ -public: - - // Constructor - CActionDeleteDatabaseElement (uint prim); - ~CActionDeleteDatabaseElement (); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - uint _Index; - CWorldEditorDoc::CDatabaseElement *_Primitive; -}; - -// XChg the database element with the next one -class CActionXChgDatabaseElement : public IAction -{ -public: - - // Constructor - CActionXChgDatabaseElement (uint prim); - ~CActionXChgDatabaseElement (); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - uint _Index; -}; - -// Unselect all -class CActionUnselectAll : public CActionSelectionBase -{ -public: - - // Constructor - CActionUnselectAll (); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - std::vector _SelectedPrimitives; -}; - -// Select all -class CActionSelectAll : public CActionSelectionBase -{ -public: - - // Constructor - CActionSelectAll (); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - std::vector _SelectedPrimitives; -}; - -// Unselect -class CActionUnselect : public CActionSelectionBase -{ -public: - - // Constructor - CActionUnselect (const CDatabaseLocator &locator); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - CDatabaseLocator _Locator; -}; - -// Select -class CActionSelect : public CActionSelectionBase -{ -public: - - // Constructor - CActionSelect (const CDatabaseLocator &locator); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - CDatabaseLocator _Locator; -}; - -// Unselect all sub primitive -class CActionUnselectAllSub : public CActionSelectionBase -{ -public: - - // Constructor - CActionUnselectAllSub (); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - std::vector _SelectedPrimitives; -}; - -// Select all sub primitive -class CActionSelectAllSub : public CActionSelectionBase -{ -public: - - // Constructor - CActionSelectAllSub (); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - std::vector _SelectedPrimitives; -}; - -// Unselect sub primitive -class CActionUnselectSub : public CActionSelectionBase -{ -public: - - // Constructor - CActionUnselectSub (const CDatabaseLocator &locator); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - CDatabaseLocator _Locator; -}; - -// Select sub primitive -class CActionSelectSub : public CActionSelectionBase -{ -public: - - // Constructor - CActionSelectSub (const CDatabaseLocator &locator); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - CDatabaseLocator _Locator; -}; - -// Interactife action -class IActionInteractive : public IAction -{ -public: - virtual bool getText (std::string &result) { return false; } - virtual bool getHelp (std::string &result) { return false; } -}; - -// Move selection action -class CActionMove : public IActionInteractive -{ -public: - - CActionMove (bool subSelection); - - // Init after - void setTranslation (const NLMISC::CVector &translation); - - // From IAction - virtual void undo (); - virtual bool redo (); - - // From IActionInteractive - virtual bool getText (std::string &result); - -private: - - // Undo entry - class CUndoEntry - { - public: - CUndoEntry (const CDatabaseLocator &locator, const NLMISC::CVector &oldPosition) - { - Locator = locator; - OldPosition = oldPosition; - } - - // The locator - CDatabaseLocator Locator; - - // The old position - NLMISC::CVector OldPosition; - }; - - // Vector of primitive to modify - std::vector _Entities; - - // The translation - NLMISC::CVector _Translation; - - // Sub selection ? - bool _SubSelection; -}; - -// Rotate selection action -class CActionRotate : public IActionInteractive -{ -public: - - CActionRotate (bool subSelection, const NLMISC::CVector &pivot); - - // Init after - void setAngle(float angle, bool rotate, bool turn); - - // From IAction - virtual void undo (); - virtual bool redo (); - - // From IActionInteractive - virtual bool getHelp (std::string &result); - virtual bool getText (std::string &result); - -private: - - // Undo entry - class CUndoEntry - { - public: - CUndoEntry (const CDatabaseLocator &locator, const NLMISC::CVector &oldPosition, bool pointPrimitive, float pointPrimitiveAngle) - { - Locator = locator; - OldPosition = oldPosition; - PointPrimitive = pointPrimitive; - PointPrimitiveAngle = pointPrimitiveAngle; - } - - // The locator - CDatabaseLocator Locator; - - // The old position - NLMISC::CVector OldPosition; - - // Is it a point primitive - bool PointPrimitive; - - // Is it a point primitive - float PointPrimitiveAngle; - }; - - // Vector of primitive to modify - std::vector _Entities; - - // The translation - float _Angle; - - // Sub selection ? - bool _SubSelection; - - // Rotate or turn ? - bool _Rotate:1; - bool _Turn:1; - - // Pivot - NLMISC::CVector Pivot; -}; - -// Scale selection action -class CActionScale : public IActionInteractive -{ -public: - - CActionScale (bool subSelection, const NLMISC::CVector &pivot); - - // Init after - void setScale (float factor, bool scale, bool radius); - - // From IAction - virtual void undo (); - virtual bool redo (); - - // From IActionInteractive - virtual bool getHelp (std::string &result); - virtual bool getText (std::string &result); - -private: - - // Undo entry - class CUndoEntry - { - public: - CUndoEntry (const CDatabaseLocator &locator, const NLMISC::CVector &oldPosition, bool hasRadius, float radius) - { - Locator = locator; - OldPosition = oldPosition; - HasRadius = hasRadius; - Radius = radius; - } - - // The locator - CDatabaseLocator Locator; - - // The old position - NLMISC::CVector OldPosition; - - // Does it have a radius - bool HasRadius; - float Radius; - }; - - // Vector of primitive to modify - std::vector _Entities; - - // The translation - float _Factor; - bool _Scale:1; - bool _Radius:1; - - // Sub selection ? - bool _SubSelection; - - // Pivot - NLMISC::CVector Pivot; -}; - -// Select -class CActionAddVertex : public IActionInteractive -{ -public: - - // Constructor - CActionAddVertex (const CDatabaseLocator &locator, const NLMISC::CVector &newVertex); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - CDatabaseLocator _Locator; - NLMISC::CVector _NewVertex; -}; - -// Delete a vertex -class CActionDeleteSub : public IAction -{ -public: - - // Constructor - CActionDeleteSub (const CDatabaseLocatorPointer &locator); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - CDatabaseLocator _Locator; - NLLIGO::CPrimVector _OldVertex; -}; - -// Delete a primitive -class CActionDelete : public IAction -{ -public: - - // Constructor - CActionDelete (const CDatabaseLocatorPointer &locator); - ~CActionDelete (); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - CDatabaseLocator _Locator; - NLLIGO::IPrimitive *_OldPrimitive; -}; - -// Add a primitive by class -class CActionAddPrimitiveByClass : public IAction -{ -public: - - // Constructor - CActionAddPrimitiveByClass (const CDatabaseLocator &locator, const char *className, const NLMISC::CVector &initPos, float deltaPos, - const std::vector initParameters); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - NLMISC::CVector _InitPos; - float _DeltaPos; - NLLIGO::IPrimitive *_OldPrimitive; - std::string _ClassName; - CDatabaseLocator _Locator; - std::vector _InitParameters; -}; - -// Change primitive property -class CActionSetPrimitivePropertyString : public IAction -{ -public: - - // Constructor - CActionSetPrimitivePropertyString (const CDatabaseLocatorPointer &locator, const char *propertyName, const char *newValue, bool _default); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - bool _OldExist; - std::string _PropertyName; - std::string _PropertyOldValue; - bool _PropertyOldValueDefault; - std::string _PropertyNewValue; - bool _PropertyNewValueDefault; - CDatabaseLocator _Locator; -}; - -// Change primitive property -class CActionSetPrimitivePropertyStringArray : public IAction -{ -public: - - // Constructor - CActionSetPrimitivePropertyStringArray (const CDatabaseLocatorPointer &locator, const char *propertyName, const std::vector &newValue, bool _default); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - bool _OldExist; - std::string _PropertyName; - std::vector _PropertyOldValue; - bool _PropertyOldValueDefault; - std::vector _PropertyNewValue; - bool _PropertyNewValueDefault; - CDatabaseLocator _Locator; -}; - -// Change primitive property -class CActionAddPrimitive : public IAction -{ -public: - - // Constructor, will copy the primitive - CActionAddPrimitive (const NLLIGO::IPrimitive &primitiveToAdd, const CDatabaseLocator &locator); - - // Constructor, will keep the primitive allocated with new - CActionAddPrimitive (NLLIGO::IPrimitive *primitiveToAdd, const CDatabaseLocator &locator); - - // Destructor - ~CActionAddPrimitive (); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - bool _FirstTime; - NLLIGO::IPrimitive *_Primitive; - CDatabaseLocator _Locator; -}; - - -// Show / hide a primitive -class CActionShowHide : public CActionSelectionBase -{ -public: - CActionShowHide (const CDatabaseLocatorPointer &locator, bool show); - -private: - - // From IAction - virtual void undo (); - virtual bool redo (); - - bool _Show; - CDatabaseLocator _Locator; -}; - -#endif // NL_ACTION_H - -/* End of action.h */ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef NL_ACTION_H +#define NL_ACTION_H + +#include "world_editor_doc.h" + + +/** + * Basic editing action + * + * \author Cyril 'Hulud' Corvazier + * \author Nevrax France + * \date 2002 + */ +class IAction +{ +public: + + // Virtual destructor + virtual ~IAction () {} + + // Do / undo + virtual void undo () = 0; + virtual bool redo () = 0; + + // Used to deferentiate selection from real action on the doc + virtual bool isAffectingContent() {return true;} +}; + +// An intermediate base class for selection or hide/show action +class CActionSelectionBase : public IAction +{ + bool isAffectingContent() { return false;} +}; + + +// Add a landscape +class CActionAddLandscape : public IAction +{ +public: + // Landscape name + CActionAddLandscape (const char *name); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + std::string _Filename; + bool _FirstTime; + NLLIGO::CZoneRegion _NewRegion; +}; + +// New landscape document +class CActionNewLandscape : public IAction +{ +public: + + // Constructor + CActionNewLandscape (); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); +}; + +// Modify the landscape +class CActionLigoTile : public IAction +{ +public: + + // Constructor + CActionLigoTile (const CLigoData &data, const CDatabaseLocator &locator); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + void set (const CLigoData &data); + + CDatabaseLocator _Locator; + CLigoData _Old; + CLigoData _New; +}; + +// Move the landscape +class CActionLigoMove : public IAction +{ +public: + + // Constructor + CActionLigoMove (uint index, sint32 deltaX, sint32 deltaY); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + uint _Index; + sint32 _DeltaX; + sint32 _DeltaY; +}; + +// Modify the landscape +class CActionLigoResize : public IAction +{ +public: + + // Constructor + CActionLigoResize (uint index, sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + uint _Index; + sint32 _NewMinX; + sint32 _NewMaxX; + sint32 _NewMinY; + sint32 _NewMaxY; + NLLIGO::CZoneRegion _Old; +}; + +// Import the landscape +class CActionImportPrimitive : public IAction +{ +public: + + // Constructor + CActionImportPrimitive (const char *oldPrimFile); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + bool _FirstLoad; + std::string _Filename; + NLLIGO::CPrimitives _Primitive; +}; + +// Import the landscape +class CActionLoadPrimitive : public IAction +{ +public: + + // Constructor + CActionLoadPrimitive (const char *oldPrimFile); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + bool _FirstLoad; + std::string _Filename; + NLLIGO::CPrimitives _Primitive; +}; + +// New primitive document +class CActionNewPrimitive : public IAction +{ +public: + + // Constructor + CActionNewPrimitive (); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); +}; + +// Clear primitives +class CActionClearPrimitives : public IAction +{ +public: + + // Constructor + CActionClearPrimitives (); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + CWorldEditorDoc::CDatabaseList _Primitives; +}; + +// Delete a primitive +class CActionDeleteDatabaseElement : public IAction +{ +public: + + // Constructor + CActionDeleteDatabaseElement (uint prim); + ~CActionDeleteDatabaseElement (); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + uint _Index; + CWorldEditorDoc::CDatabaseElement *_Primitive; +}; + +// XChg the database element with the next one +class CActionXChgDatabaseElement : public IAction +{ +public: + + // Constructor + CActionXChgDatabaseElement (uint prim); + ~CActionXChgDatabaseElement (); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + uint _Index; +}; + +// Unselect all +class CActionUnselectAll : public CActionSelectionBase +{ +public: + + // Constructor + CActionUnselectAll (); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + std::vector _SelectedPrimitives; +}; + +// Select all +class CActionSelectAll : public CActionSelectionBase +{ +public: + + // Constructor + CActionSelectAll (); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + std::vector _SelectedPrimitives; +}; + +// Unselect +class CActionUnselect : public CActionSelectionBase +{ +public: + + // Constructor + CActionUnselect (const CDatabaseLocator &locator); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + CDatabaseLocator _Locator; +}; + +// Select +class CActionSelect : public CActionSelectionBase +{ +public: + + // Constructor + CActionSelect (const CDatabaseLocator &locator); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + CDatabaseLocator _Locator; +}; + +// Unselect all sub primitive +class CActionUnselectAllSub : public CActionSelectionBase +{ +public: + + // Constructor + CActionUnselectAllSub (); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + std::vector _SelectedPrimitives; +}; + +// Select all sub primitive +class CActionSelectAllSub : public CActionSelectionBase +{ +public: + + // Constructor + CActionSelectAllSub (); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + std::vector _SelectedPrimitives; +}; + +// Unselect sub primitive +class CActionUnselectSub : public CActionSelectionBase +{ +public: + + // Constructor + CActionUnselectSub (const CDatabaseLocator &locator); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + CDatabaseLocator _Locator; +}; + +// Select sub primitive +class CActionSelectSub : public CActionSelectionBase +{ +public: + + // Constructor + CActionSelectSub (const CDatabaseLocator &locator); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + CDatabaseLocator _Locator; +}; + +// Interactife action +class IActionInteractive : public IAction +{ +public: + virtual bool getText (std::string &result) { return false; } + virtual bool getHelp (std::string &result) { return false; } +}; + +// Move selection action +class CActionMove : public IActionInteractive +{ +public: + + CActionMove (bool subSelection); + + // Init after + void setTranslation (const NLMISC::CVector &translation); + + // From IAction + virtual void undo (); + virtual bool redo (); + + // From IActionInteractive + virtual bool getText (std::string &result); + +private: + + // Undo entry + class CUndoEntry + { + public: + CUndoEntry (const CDatabaseLocator &locator, const NLMISC::CVector &oldPosition) + { + Locator = locator; + OldPosition = oldPosition; + } + + // The locator + CDatabaseLocator Locator; + + // The old position + NLMISC::CVector OldPosition; + }; + + // Vector of primitive to modify + std::vector _Entities; + + // The translation + NLMISC::CVector _Translation; + + // Sub selection ? + bool _SubSelection; +}; + +// Rotate selection action +class CActionRotate : public IActionInteractive +{ +public: + + CActionRotate (bool subSelection, const NLMISC::CVector &pivot); + + // Init after + void setAngle(float angle, bool rotate, bool turn); + + // From IAction + virtual void undo (); + virtual bool redo (); + + // From IActionInteractive + virtual bool getHelp (std::string &result); + virtual bool getText (std::string &result); + +private: + + // Undo entry + class CUndoEntry + { + public: + CUndoEntry (const CDatabaseLocator &locator, const NLMISC::CVector &oldPosition, bool pointPrimitive, float pointPrimitiveAngle) + { + Locator = locator; + OldPosition = oldPosition; + PointPrimitive = pointPrimitive; + PointPrimitiveAngle = pointPrimitiveAngle; + } + + // The locator + CDatabaseLocator Locator; + + // The old position + NLMISC::CVector OldPosition; + + // Is it a point primitive + bool PointPrimitive; + + // Is it a point primitive + float PointPrimitiveAngle; + }; + + // Vector of primitive to modify + std::vector _Entities; + + // The translation + float _Angle; + + // Sub selection ? + bool _SubSelection; + + // Rotate or turn ? + bool _Rotate:1; + bool _Turn:1; + + // Pivot + NLMISC::CVector Pivot; +}; + +// Scale selection action +class CActionScale : public IActionInteractive +{ +public: + + CActionScale (bool subSelection, const NLMISC::CVector &pivot); + + // Init after + void setScale (float factor, bool scale, bool radius); + + // From IAction + virtual void undo (); + virtual bool redo (); + + // From IActionInteractive + virtual bool getHelp (std::string &result); + virtual bool getText (std::string &result); + +private: + + // Undo entry + class CUndoEntry + { + public: + CUndoEntry (const CDatabaseLocator &locator, const NLMISC::CVector &oldPosition, bool hasRadius, float radius) + { + Locator = locator; + OldPosition = oldPosition; + HasRadius = hasRadius; + Radius = radius; + } + + // The locator + CDatabaseLocator Locator; + + // The old position + NLMISC::CVector OldPosition; + + // Does it have a radius + bool HasRadius; + float Radius; + }; + + // Vector of primitive to modify + std::vector _Entities; + + // The translation + float _Factor; + bool _Scale:1; + bool _Radius:1; + + // Sub selection ? + bool _SubSelection; + + // Pivot + NLMISC::CVector Pivot; +}; + +// Select +class CActionAddVertex : public IActionInteractive +{ +public: + + // Constructor + CActionAddVertex (const CDatabaseLocator &locator, const NLMISC::CVector &newVertex); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + CDatabaseLocator _Locator; + NLMISC::CVector _NewVertex; +}; + +// Delete a vertex +class CActionDeleteSub : public IAction +{ +public: + + // Constructor + CActionDeleteSub (const CDatabaseLocatorPointer &locator); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + CDatabaseLocator _Locator; + NLLIGO::CPrimVector _OldVertex; +}; + +// Delete a primitive +class CActionDelete : public IAction +{ +public: + + // Constructor + CActionDelete (const CDatabaseLocatorPointer &locator); + ~CActionDelete (); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + CDatabaseLocator _Locator; + NLLIGO::IPrimitive *_OldPrimitive; +}; + +// Add a primitive by class +class CActionAddPrimitiveByClass : public IAction +{ +public: + + // Constructor + CActionAddPrimitiveByClass (const CDatabaseLocator &locator, const char *className, const NLMISC::CVector &initPos, float deltaPos, + const std::vector initParameters); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + NLMISC::CVector _InitPos; + float _DeltaPos; + NLLIGO::IPrimitive *_OldPrimitive; + std::string _ClassName; + CDatabaseLocator _Locator; + std::vector _InitParameters; +}; + +// Change primitive property +class CActionSetPrimitivePropertyString : public IAction +{ +public: + + // Constructor + CActionSetPrimitivePropertyString (const CDatabaseLocatorPointer &locator, const char *propertyName, const char *newValue, bool _default); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + bool _OldExist; + std::string _PropertyName; + std::string _PropertyOldValue; + bool _PropertyOldValueDefault; + std::string _PropertyNewValue; + bool _PropertyNewValueDefault; + CDatabaseLocator _Locator; +}; + +// Change primitive property +class CActionSetPrimitivePropertyStringArray : public IAction +{ +public: + + // Constructor + CActionSetPrimitivePropertyStringArray (const CDatabaseLocatorPointer &locator, const char *propertyName, const std::vector &newValue, bool _default); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + bool _OldExist; + std::string _PropertyName; + std::vector _PropertyOldValue; + bool _PropertyOldValueDefault; + std::vector _PropertyNewValue; + bool _PropertyNewValueDefault; + CDatabaseLocator _Locator; +}; + +// Change primitive property +class CActionAddPrimitive : public IAction +{ +public: + + // Constructor, will copy the primitive + CActionAddPrimitive (const NLLIGO::IPrimitive &primitiveToAdd, const CDatabaseLocator &locator); + + // Constructor, will keep the primitive allocated with new + CActionAddPrimitive (NLLIGO::IPrimitive *primitiveToAdd, const CDatabaseLocator &locator); + + // Destructor + ~CActionAddPrimitive (); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + bool _FirstTime; + NLLIGO::IPrimitive *_Primitive; + CDatabaseLocator _Locator; +}; + + +// Show / hide a primitive +class CActionShowHide : public CActionSelectionBase +{ +public: + CActionShowHide (const CDatabaseLocatorPointer &locator, bool show); + +private: + + // From IAction + virtual void undo (); + virtual bool redo (); + + bool _Show; + CDatabaseLocator _Locator; +}; + +#endif // NL_ACTION_H + +/* End of action.h */ diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_logic.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_logic.cpp index f5efa3231..018466169 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_logic.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_logic.cpp @@ -1,1521 +1,1521 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" - -#include "world_editor_doc.h" -#include "display.h" - -using namespace NLLIGO; -using namespace NLMISC; -using namespace NL3D; -using namespace std; - -// *************************************************************************** -// SPrimBuild -// *************************************************************************** - -// --------------------------------------------------------------------------- - -// *************************************************************************** -// CBuilderLogic -// *************************************************************************** - -// --------------------------------------------------------------------------- -CBuilderLogic::CBuilderLogic() -: _LogicCallback(0) -{ - _ItemSelected = NULL; - _RegionSelected = -1; - _ToolsLogic = NULL; - _Display = NULL; -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::setDisplay (CDisplay *pDisp) -{ - _Display = pDisp; -} - - -void CBuilderLogic::notify() -{ - if (_LogicCallback) - { - CWorldEditorDoc *doc = getDocument (); - uint primCount = doc->getNumDatabaseElement (); - for (uint i=0; ionLogicChanged (i); - } - } -} - -void CBuilderLogic::setLogicCallback(ILogicCallback *logicCallback) -{ - _LogicCallback = logicCallback; -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::setToolsLogic (CToolsLogic *pTool) -{ - _ToolsLogic = pTool; -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::uninit() -{ - _Display = NULL; -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::updateToolsLogic () -{ - notify(); - // Regenerate the toolsLogic with the data in the region - if (_ToolsLogic == NULL) - return; - - _ToolsLogic->reset(); - uint32 i, j; - sint32 tempItem = -1; - for (j = 0; j < getDocument ()->getNumDatabaseElement (); ++j) - { - const CPrimRegion &rRegion = getDocument ()->getPrimRegion (j); - sint32 nReg = j; - - map mapGroups; - map::iterator itGroups; - - // Create Regions - nReg = _ToolsLogic->createNewRegion (rRegion.Name); - - // Create Groups - for (i = 0; i < rRegion.VPoints.size(); ++i) - { - itGroups = mapGroups.find(rRegion.VPoints[i].LayerName); - if (itGroups == mapGroups.end()) - { - uint32 nGroup = _ToolsLogic->createNewGroup (j, rRegion.VPoints[i].LayerName); - mapGroups.insert (make_pair(rRegion.VPoints[i].LayerName, nGroup)); - } - } - for (i = 0; i < rRegion.VPaths.size(); ++i) - { - itGroups = mapGroups.find(rRegion.VPaths[i].LayerName); - if (itGroups == mapGroups.end()) - { - uint32 nGroup = _ToolsLogic->createNewGroup (j, rRegion.VPaths[i].LayerName); - mapGroups.insert (make_pair(rRegion.VPaths[i].LayerName, nGroup)); - } - } - for (i = 0; i < rRegion.VZones.size(); ++i) - { - itGroups = mapGroups.find(rRegion.VZones[i].LayerName); - if (itGroups == mapGroups.end()) - { - uint32 nGroup = _ToolsLogic->createNewGroup (j, rRegion.VZones[i].LayerName); - mapGroups.insert (make_pair(rRegion.VZones[i].LayerName, nGroup)); - } - } - - for (i = 0; i < rRegion.VPoints.size(); ++i) - { - HTREEITEM newItem = (HTREEITEM)tempItem; - tempItem--; - itGroups = mapGroups.find(rRegion.VPoints[i].LayerName); - if (itGroups != mapGroups.end()) - if (rRegion.VPoints[i].Name != "-- Delete Me --") - { - newItem = _ToolsLogic->addPoint (nReg, itGroups->second, rRegion.VPoints[i].Name.c_str(), rRegion.VHidePoints[i]); - } - } - - for (i = 0; i < rRegion.VPaths.size(); ++i) - { - HTREEITEM newItem = (HTREEITEM)tempItem; - tempItem--; - itGroups = mapGroups.find(rRegion.VPaths[i].LayerName); - if (itGroups != mapGroups.end()) - if (rRegion.VPaths[i].Name != "-- Delete Me --") - { - newItem = _ToolsLogic->addPath (nReg, itGroups->second, rRegion.VPaths[i].Name.c_str(), rRegion.VHidePaths[i]); - } - } - - for (i = 0; i < rRegion.VZones.size(); ++i) - { - HTREEITEM newItem = (HTREEITEM)tempItem; - tempItem--; - itGroups = mapGroups.find(rRegion.VZones[i].LayerName); - if (itGroups != mapGroups.end()) - if (rRegion.VZones[i].Name != "-- Delete Me --") - { - newItem = _ToolsLogic->addZone (nReg, itGroups->second, rRegion.VZones[i].Name.c_str(), rRegion.VHideZones[i]); - } - } - } - - - _VerticesSelected.resize (0); -} - -// --------------------------------------------------------------------------- -const string &CBuilderLogic::getZoneRegionName (uint32 nPos) -{ - return _PRegions[nPos]->Name; -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::move (const string ®Name, float x, float y) -{ - uint32 i, j, k; - - for (i = 0; i < _PRegions.size(); ++i) - if (_PRegions[i]->Name == regName) - { - _MustAskSaves[i] = true; - for (j = 0; j < _PRegions[i]->VPoints.size(); ++j) - { - _PRegions[i]->VPoints[j].Point.x += x; - _PRegions[i]->VPoints[j].Point.y += y; - } - - for (j = 0; j < _PRegions[i]->VPaths.size(); ++j) - { - for (k = 0; k < _PRegions[i]->VPaths[j].VPoints.size(); ++k) - { - _PRegions[i]->VPaths[j].VPoints[k].x += x; - _PRegions[i]->VPaths[j].VPoints[k].y += y; - } - } - - for (j = 0; j < _PRegions[i]->VZones.size(); ++j) - { - for (k = 0; k < _PRegions[i]->VZones[j].VPoints.size(); ++k) - { - _PRegions[i]->VZones[j].VPoints[k].x += x; - _PRegions[i]->VZones[j].VPoints[k].y += y; - } - } - notify(); - return; - } -} - -// --------------------------------------------------------------------------- - -void CBuilderLogic::insertPoint (uint32 pos, HTREEITEM item, const char *Name, const char *LayerName) -{ - - CPrimPointEditor pp; - pp.LayerName = LayerName; - pp.Name = Name; - pp.Point = CVector(0.0f, 0.0f, 0.0f); - _PRegions[pos]->VPoints.push_back (pp); - _PRegions[pos]->VHidePoints.push_back (false); - SPrimBuild pB; - pB.Type = 0; // Point - pB.Pos = _PRegions[pos]->VPoints.size()-1; - pB.PRegion = _PRegions[pos]; - _Primitives.insert (map::value_type(item, pB)); - _MustAskSaves[pos] = true; - - notify(); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::insertPath (uint32 pos, HTREEITEM item, const char *Name, const char *LayerName) -{ - - CPrimPathEditor pp; - pp.LayerName = LayerName; - pp.Name = Name; - _PRegions[pos]->VPaths.push_back (pp); - _PRegions[pos]->VHidePaths.push_back (false); - SPrimBuild pB; - pB.Type = 1; // Path - pB.Pos = _PRegions[pos]->VPaths.size()-1; - pB.PRegion = _PRegions[pos]; - _Primitives.insert (map::value_type(item, pB)); - _MustAskSaves[pos] = true; - - notify(); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::insertZone (uint32 pos, HTREEITEM item, const char *Name, const char *LayerName) -{ - CPrimZoneEditor pz; - pz.LayerName = LayerName; - pz.Name = Name; - _PRegions[pos]->VZones.push_back (pz); - _PRegions[pos]->VHideZones.push_back (false); - SPrimBuild pB; - pB.Type = 2; // Zone - pB.Pos = _PRegions[pos]->VZones.size()-1; - pB.PRegion = _PRegions[pos]; - _Primitives.insert (map::value_type(item, pB)); - _MustAskSaves[pos] = true; - - notify(); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::del (HTREEITEM item) -{ - map::iterator it = _Primitives.find (item); - - if (it != _Primitives.end()) - { - SPrimBuild &rPB = it->second; - CPrimRegion &PRegion = *rPB.PRegion; - // Delete the entry in the document - - - // Delete in the region - switch (rPB.Type) - { - case 0: - { - PRegion.VPoints.erase (PRegion.VPoints.begin()+rPB.Pos); - PRegion.VHidePoints.erase (PRegion.VHidePoints.begin()+rPB.Pos); - } - break; - case 1: - { - PRegion.VPaths.erase (PRegion.VPaths.begin()+rPB.Pos); - PRegion.VHidePaths.erase (PRegion.VHidePaths.begin()+rPB.Pos); - } - break; - case 2: - PRegion.VZones.erase (PRegion.VZones.begin()+rPB.Pos); - PRegion.VHideZones.erase (PRegion.VHideZones.begin()+rPB.Pos); - break; - } - // Update position - map::iterator it2 = _Primitives.begin (); - while (it2 != _Primitives.end()) - { - SPrimBuild &rPB2 = it2->second; - - if ((rPB2.PRegion == rPB.PRegion)&&(rPB2.Type == rPB.Type)) - if (rPB2.Pos > rPB.Pos) - rPB2.Pos -= 1; - - ++it2; - } - // Delete the entry in the map - _Primitives.erase (it); - - for (uint32 z = 0; z < _PRegions.size(); ++z) - if (_PRegions[z] == &PRegion) - { - _MustAskSaves[z] = true; - break; - } - } - notify(); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::primHide (HTREEITEM item) -{ - map::iterator it = _Primitives.find (item); - if (it != _Primitives.end()) - { - SPrimBuild &rPB = it->second; - rPB.hidden = true; - if (rPB.Type == 0) // Points - { - rPB.PRegion->VHidePoints[rPB.Pos] = true; - } - else if (rPB.Type == 1) // Paths - { - rPB.PRegion->VHidePaths[rPB.Pos] = true; - } - else if (rPB.Type == 2) /// Zones - { - rPB.PRegion->VHideZones[rPB.Pos] = true; - } - } -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::primUnhide (HTREEITEM item) -{ - map::iterator it = _Primitives.find (item); - if (it != _Primitives.end()) - { - SPrimBuild &rPB = it->second; - rPB.hidden = false; - if (rPB.Type == 0) // Points - { - rPB.PRegion->VHidePoints[rPB.Pos] = false; - } - else if (rPB.Type == 1) // Paths - { - rPB.PRegion->VHidePaths[rPB.Pos] = false; - } - else if (rPB.Type == 2) /// Zones - { - rPB.PRegion->VHideZones[rPB.Pos] = false; - } - } -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::hideAll (uint32 nPos, sint32 nID, bool bHide) -{ - map::iterator it = _Primitives.begin (); - while (it != _Primitives.end()) - { - SPrimBuild &rPB = it->second; - - if (rPB.PRegion == _PRegions[nPos]) - { - if (rPB.Type == nID) - { - rPB.hidden = bHide; - if (rPB.Type == 0) // Points - { - rPB.PRegion->VHidePoints[rPB.Pos] = bHide; - } - else if (rPB.Type == 1) // Paths - { - rPB.PRegion->VHidePaths[rPB.Pos] = bHide; - } - else if (rPB.Type == 2) /// Zones - { - rPB.PRegion->VHideZones[rPB.Pos] = bHide; - } - } - } - - ++it; - } -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::regionSetName (uint32 nPos, HTREEITEM item, const string &sRegionName) -{ - CPrimRegion &rPR = *_PRegions[nPos]; - rPR.Name = sRegionName; - notify(); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::regionCreateGroup (uint32 nPos, HTREEITEM newItem, const string &sGroupName) -{ - insertPoint (nPos, (HTREEITEM)-1, "-- Delete Me --", sGroupName.c_str()); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::regionDeleteGroup (uint32 nPos, const std::string &sGroupName) -{ - sint32 i, j; - for (i = 0; i < (sint32)_PRegions[nPos]->VPoints.size(); ++i) - { - if (_PRegions[nPos]->VPoints[i].LayerName == sGroupName) - { - for (j = i+1; j < (sint32)_PRegions[nPos]->VPoints.size(); ++j) - _PRegions[nPos]->VPoints[j-1] = _PRegions[nPos]->VPoints[j]; - _PRegions[nPos]->VPoints.resize (_PRegions[nPos]->VPoints.size()-1); - i = -1; - } - } - notify(); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::regionHideAll (uint32 nPos, bool bHide) -{ - map::iterator it = _Primitives.begin (); - while (it != _Primitives.end()) - { - SPrimBuild &rPB = it->second; - - if (rPB.PRegion == _PRegions[nPos]) - rPB.hidden = bHide; - - ++it; - } -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::regionHideType (uint32 nPos, const string &Type, bool bHide) -{ - map::iterator it = _Primitives.begin (); - while (it != _Primitives.end()) - { - SPrimBuild &rPB = it->second; - - if (rPB.PRegion == _PRegions[nPos]) - { - string Name, Tmp; - switch (rPB.Type) - { - case 0: Name = _PRegions[nPos]->VPoints[rPB.Pos].Name; break; - case 1: Name = _PRegions[nPos]->VPaths[rPB.Pos].Name; break; - case 2: Name = _PRegions[nPos]->VZones[rPB.Pos].Name; break; - } - - uint32 i = 0; - while (Name[i] != '-') ++i; - i++; - while ((Name[i] != '-') && (i < Name.size())) - { - Tmp += Name[i]; - ++i; - } - if (Tmp == Type) - rPB.hidden = bHide; - } - - ++it; - } -} - -// --------------------------------------------------------------------------- -int CBuilderLogic::getMaxPostfix (const char *prefix) -{ - int nTmp; - int nZeMax = -1; - int nPFLen = strlen(prefix); - - map::iterator it = _Primitives.begin (); - while (it != _Primitives.end()) - { - SPrimBuild &rPB = it->second; - nTmp = 0; - switch (rPB.Type) - { - case 0: // Point - if (strncmp(prefix, rPB.PRegion->VPoints[rPB.Pos].Name.c_str(), nPFLen) == 0) - { - CPrimPointEditor &rP = rPB.PRegion->VPoints[rPB.Pos]; - if ((rP.Name[nPFLen+0] >= '0') && (rP.Name[nPFLen+0] <= '9') && - (rP.Name[nPFLen+1] >= '0') && (rP.Name[nPFLen+1] <= '9') && - (rP.Name[nPFLen+2] >= '0') && (rP.Name[nPFLen+2] <= '9')) - { - nTmp = (rP.Name[nPFLen+0] - '0')*100; - nTmp += (rP.Name[nPFLen+1] - '0')*10; - nTmp += (rP.Name[nPFLen+2] - '0')*1; - } - } - break; - case 1: // Path - if (strncmp(prefix, rPB.PRegion->VPaths[rPB.Pos].Name.c_str(), nPFLen) == 0) - { - CPrimPathEditor &rP = rPB.PRegion->VPaths[rPB.Pos]; - if ((rP.Name[nPFLen+0] >= '0') && (rP.Name[nPFLen+0] <= '9') && - (rP.Name[nPFLen+1] >= '0') && (rP.Name[nPFLen+1] <= '9') && - (rP.Name[nPFLen+2] >= '0') && (rP.Name[nPFLen+2] <= '9')) - { - nTmp = (rP.Name[nPFLen+0] - '0')*100; - nTmp += (rP.Name[nPFLen+1] - '0')*10; - nTmp += (rP.Name[nPFLen+2] - '0')*1; - } - } - break; - case 2: // Zone - if (strncmp(prefix, rPB.PRegion->VZones[rPB.Pos].Name.c_str(), nPFLen) == 0) - { - CPrimZoneEditor &rP = rPB.PRegion->VZones[rPB.Pos]; - if ((rP.Name[nPFLen+0] >= '0') && (rP.Name[nPFLen+0] <= '9') && - (rP.Name[nPFLen+1] >= '0') && (rP.Name[nPFLen+1] <= '9') && - (rP.Name[nPFLen+2] >= '0') && (rP.Name[nPFLen+2] <= '9')) - { - nTmp = (rP.Name[nPFLen+0] - '0')*100; - nTmp += (rP.Name[nPFLen+1] - '0')*10; - nTmp += (rP.Name[nPFLen+2] - '0')*1; - } - } - break; - } - - if (nZeMax < nTmp) - nZeMax = nTmp; - - ++it; - } - - return nZeMax; -} - -// --------------------------------------------------------------------------- -bool CBuilderLogic::isAlreadyExisting (const char *sPrimitiveName) -{ - map::iterator it = _Primitives.begin (); - while (it != _Primitives.end()) - { - SPrimBuild &rPB = it->second; - - switch (rPB.Type) - { - case 0: // Point - if (strcmp(sPrimitiveName, rPB.PRegion->VPoints[rPB.Pos].Name.c_str()) == 0) - return true; - break; - case 1: // Path - if (strcmp(sPrimitiveName, rPB.PRegion->VPaths[rPB.Pos].Name.c_str()) == 0) - return true; - break; - case 2: // Zone - if (strcmp(sPrimitiveName, rPB.PRegion->VZones[rPB.Pos].Name.c_str()) == 0) - return true; - break; - default: - break; - } - ++it; - } - return false; -} - -// --------------------------------------------------------------------------- -const char* CBuilderLogic::getName (HTREEITEM item) -{ - map::iterator it = _Primitives.find (item); - if (it == _Primitives.end()) - return NULL; - else - { - SPrimBuild &rPB = it->second; - CPrimRegion &PRegion = *rPB.PRegion; - - switch (rPB.Type) - { - case 0: - return PRegion.VPoints[rPB.Pos].Name.c_str(); - break; - case 1: - return PRegion.VPaths[rPB.Pos].Name.c_str(); - break; - case 2: - return PRegion.VZones[rPB.Pos].Name.c_str(); - break; - } - return NULL; - } -} - -// --------------------------------------------------------------------------- -const char* CBuilderLogic::getLayerName (HTREEITEM item) -{ - map::iterator it = _Primitives.find (item); - if (it == _Primitives.end()) - return NULL; - else - { - SPrimBuild &rPB = it->second; - CPrimRegion &PRegion = *rPB.PRegion; - - switch (rPB.Type) - { - case 0: - return PRegion.VPoints[rPB.Pos].LayerName.c_str(); - break; - case 1: - return PRegion.VPaths[rPB.Pos].LayerName.c_str(); - break; - case 2: - return PRegion.VZones[rPB.Pos].LayerName.c_str(); - break; - } - return NULL; - } -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::getAllPrimZoneNames (vector &allNames) -{ - allNames.clear (); - for (uint32 i = 0; i < _PRegions.size(); ++i) - for (uint32 j = 0; j < _PRegions[i]->VZones.size(); ++j) - allNames.push_back (_PRegions[i]->VZones[j].Name); -} - - -// --------------------------------------------------------------------------- -bool CBuilderLogic::isHidden (HTREEITEM item) -{ - map::iterator it = _Primitives.find (item); - if (it == _Primitives.end()) - { - return true; - } - else - { - SPrimBuild &rPB = it->second; - return rPB.hidden; - } -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::setName (HTREEITEM item, const char* pStr) -{ - map::iterator it = _Primitives.find (item); - if (it == _Primitives.end()) - return; - else - { - SPrimBuild &rPB = it->second; - CPrimRegion &PRegion = *rPB.PRegion; - - switch (rPB.Type) - { - case 0: - PRegion.VPoints[rPB.Pos].Name = pStr; - break; - case 1: - PRegion.VPaths[rPB.Pos].Name = pStr; - break; - case 2: - PRegion.VZones[rPB.Pos].Name = pStr; - break; - } - - for (uint32 z = 0; z < _PRegions.size(); ++z) - if (_PRegions[z] == &PRegion) - { - _MustAskSaves[z] = true; - break; - } - - } - notify(); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::setLayerName (HTREEITEM item, const char* pStr) -{ - map::iterator it = _Primitives.find (item); - if (it == _Primitives.end()) - return; - else - { - SPrimBuild &rPB = it->second; - CPrimRegion &PRegion = *rPB.PRegion; - - switch (rPB.Type) - { - case 0: - PRegion.VPoints[rPB.Pos].LayerName = pStr; - break; - case 1: - PRegion.VPaths[rPB.Pos].LayerName = pStr; - break; - case 2: - PRegion.VZones[rPB.Pos].LayerName = pStr; - break; - } - - for (uint32 z = 0; z < _PRegions.size(); ++z) - if (_PRegions[z] == &PRegion) - { - _MustAskSaves[z] = true; - break; - } - } - notify(); -} - -// --------------------------------------------------------------------------- -HTREEITEM CBuilderLogic::getSelPB () -{ - return _ItemSelected; -} - -// --------------------------------------------------------------------------- -std::string CBuilderLogic::getSelPBName () -{ - map::iterator it = _Primitives.find (_ItemSelected); - if (it != _Primitives.end()) - { - SPrimBuild &rPB = it->second; - CPrimRegion &PRegion = *rPB.PRegion; - - switch (rPB.Type) - { - case 0: return PRegion.VPoints[rPB.Pos].Name; - case 1: return PRegion.VPaths[rPB.Pos].Name; - case 2: return PRegion.VZones[rPB.Pos].Name; - } - } - - return ""; -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::setSelPB (HTREEITEM item) -{ - _VerticesSelected.clear (); - _ItemSelected = NULL; - map::iterator it = _Primitives.find (item); - if (it != _Primitives.end()) - { - _ItemSelected = item; - _ItemSelectedName = getName(_ItemSelected); - _ToolsLogic->GetTreeCtrl()->Select(item, TVGN_CARET); - } -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::createVertexOnSelPB (CVector &v, sint32 atPos) -{ - map::iterator it = _Primitives.find (_ItemSelected); - if (it == _Primitives.end()) - return; - SPrimBuild &rPB = it->second; - CPrimRegion &PRegion = *rPB.PRegion; - - switch (rPB.Type) - { - case 0: - if (!rPB.Created) - { - PRegion.VPoints[rPB.Pos].Point = v; - rPB.Created = true; - } - break; - case 1: - if (!rPB.Created) - { - rPB.Created = true; - } - if (atPos != -1) - { - PRegion.VPaths[rPB.Pos].VPoints.insert (PRegion.VPaths[rPB.Pos].VPoints.begin()+atPos, v); - } - else - { - PRegion.VPaths[rPB.Pos].VPoints.push_back(v); - } - break; - case 2: - if (!rPB.Created) - { - rPB.Created = true; - } - if (atPos != -1) - { - PRegion.VZones[rPB.Pos].VPoints.insert (PRegion.VZones[rPB.Pos].VPoints.begin()+atPos, v); - } - else - { - PRegion.VZones[rPB.Pos].VPoints.push_back(v); - } - break; - } - for (uint32 z = 0; z < _PRegions.size(); ++z) - if (_PRegions[z] == &PRegion) - { - _MustAskSaves[z] = true; - break; - } - - notify(); -} - -// --------------------------------------------------------------------------- -bool CBuilderLogic::selectVerticesOnSelPB (CVector &selMin, CVector &selMax) -{ - _VerticesSelected.clear (); - map::iterator it = _Primitives.find (_ItemSelected); - if (it == _Primitives.end()) - return false; - - SPrimBuild &rPB = it->second; - CPrimRegion &PRegion = *rPB.PRegion; - - if (!rPB.Created) - return false; - - CPrimVector *pV = NULL; - uint32 nNbV = 0; - switch (rPB.Type) - { - case 0: - nNbV = 1; - pV = &(PRegion.VPoints[rPB.Pos].Point); - break; - case 1: - nNbV = PRegion.VPaths[rPB.Pos].VPoints.size(); - pV = &(PRegion.VPaths[rPB.Pos].VPoints[0]); - break; - case 2: - nNbV = PRegion.VZones[rPB.Pos].VPoints.size(); - pV = &(PRegion.VZones[rPB.Pos].VPoints[0]); - break; - } - float selMinX = min(selMin.x, selMax.x); - float selMinY = min(selMin.y, selMax.y); - float selMaxX = max(selMin.x, selMax.x); - float selMaxY = max(selMin.y, selMax.y); - - for (uint32 i = 0; i < nNbV; ++i) - { - if ((pV[i].x > selMinX) && (pV[i].x < selMaxX) && - (pV[i].y > selMinY) && (pV[i].y < selMaxY)) - { - _VerticesSelected.push_back (i); - } - } - if (_VerticesSelected.size() == 0) - return false; - return true; -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::createIsoVertexOnSelVertexOnSelPB () -{ - if ((_VerticesSelected.size() <= 1) || (_ItemSelected == NULL)) - return; - map::iterator it = _Primitives.find (_ItemSelected); - if (it == _Primitives.end()) - return; - SPrimBuild &rPB = it->second; - CPrimRegion &PRegion = *rPB.PRegion; - CVector v(0.0f, 0.0f, 0.0f); - - sint minvs = 30000; - for (uint32 i = 0; i < _VerticesSelected.size(); ++i) - { - switch (rPB.Type) - { - case 0: - v += PRegion.VPoints[rPB.Pos].Point; - break; - case 1: - v += PRegion.VPaths[rPB.Pos].VPoints[_VerticesSelected[i]]; - break; - case 2: - v += PRegion.VZones[rPB.Pos].VPoints[_VerticesSelected[i]]; - break; - } - if (_VerticesSelected[i] < minvs) - minvs = _VerticesSelected[i]; - } - v /= (float)_VerticesSelected.size(); - - if (rPB.Type == 2) - { - CPrimZoneEditor &pz = PRegion.VZones[rPB.Pos]; - if (((_VerticesSelected[0] == 0) && (_VerticesSelected[1] == ((sint32)pz.VPoints.size()-1))) || - ((_VerticesSelected[0] == ((sint32)pz.VPoints.size()-1)) && (_VerticesSelected[1] == 0))) - { - createVertexOnSelPB (v, 0); - } - else - { - createVertexOnSelPB (v, minvs+1); - } - } - else - { - createVertexOnSelPB (v, minvs+1); - } -} - -// --------------------------------------------------------------------------- -bool CBuilderLogic::isSelection() -{ - return (_VerticesSelected.size() > 0); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::setSelVerticesOnSelPB (NLMISC::CVector &v) -{ - if ((_VerticesSelected.size() == 0) || (_ItemSelected == NULL)) - return; - map::iterator it = _Primitives.find (_ItemSelected); - if (it == _Primitives.end()) - return; - SPrimBuild &rPB = it->second; - CPrimRegion &PRegion = *rPB.PRegion; - - for (uint32 i = 0; i < _VerticesSelected.size(); ++i) - { - switch (rPB.Type) - { - case 0: - PRegion.VPoints[rPB.Pos].Point += v; - break; - case 1: - PRegion.VPaths[rPB.Pos].VPoints[_VerticesSelected[i]] += v; - break; - case 2: - PRegion.VZones[rPB.Pos].VPoints[_VerticesSelected[i]] += v; - break; - } - } - - for (uint32 z = 0; z < _PRegions.size(); ++z) - if (_PRegions[z] == &PRegion) - { - _MustAskSaves[z] = true; - break; - } - notify(); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::delSelVerticesOnSelPB () -{ - if ((_VerticesSelected.size() == 0) || (_ItemSelected == NULL)) - return; - map::iterator it = _Primitives.find (_ItemSelected); - if (it == _Primitives.end()) - return; - SPrimBuild &rPB = it->second; - CPrimRegion &PRegion = *rPB.PRegion; - - uint32 i; - for (uint32 k = 0; k < _VerticesSelected.size(); ++k) - { - int VertexSelected = _VerticesSelected[k]; - switch (rPB.Type) - { - case 0: - rPB.Created = false; - break; - case 1: - if (PRegion.VPaths[rPB.Pos].VPoints.size() == 1) - rPB.Created = false; - - for (i = VertexSelected+1; i < PRegion.VPaths[rPB.Pos].VPoints.size(); ++i) - PRegion.VPaths[rPB.Pos].VPoints[i-1] = PRegion.VPaths[rPB.Pos].VPoints[i]; - PRegion.VPaths[rPB.Pos].VPoints.resize (PRegion.VPaths[rPB.Pos].VPoints.size()-1); - break; - case 2: - if (PRegion.VZones[rPB.Pos].VPoints.size() == 1) - rPB.Created = false; - - for (i = VertexSelected+1; i < PRegion.VZones[rPB.Pos].VPoints.size(); ++i) - PRegion.VZones[rPB.Pos].VPoints[i-1] = PRegion.VZones[rPB.Pos].VPoints[i]; - PRegion.VZones[rPB.Pos].VPoints.resize (PRegion.VZones[rPB.Pos].VPoints.size()-1); - break; - } - } - - for (uint32 z = 0; z < _PRegions.size(); ++z) - if (_PRegions[z] == &PRegion) - { - _MustAskSaves[z] = true; - break; - } - - notify(); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::stackSelPB () -{ - map::iterator it = _Primitives.find (_ItemSelected); - if (it == _Primitives.end()) - return; - SPrimBuild &rPB = it->second; - CPrimRegion &PRegion = *rPB.PRegion; -} - -// --------------------------------------------------------------------------- -string CBuilderLogic::getZonesNameAt (CVector &v) -{ - string ret; - for (uint32 i = 0; i < _PRegions.size(); ++i) - { - for (uint32 j = 0; j < _PRegions[i]->VZones.size(); ++j) - { - CPrimZoneEditor *pz = &_PRegions[i]->VZones[j]; - - // Find if the patat is visible - bool bHidden = true; - map::iterator it = _Primitives.begin (); - while (it != _Primitives.end()) - { - if ((it->second.Type == 2) && ((sint32)j == it->second.Pos)) - { - if (it->second.hidden) - bHidden = true; - else - bHidden = false; - break; - } - ++it; - } - - if ((!bHidden) && (pz->contains(v))) - { - if (ret.size() == 0) - { - ret += pz->Name; - } - else - { - ret += ", " + pz->Name; - } - } - } - } - return ret; -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::selectZoneAt (NLMISC::CVector &v) -{ - vector zonelist; - uint32 i, j; - - for (i = 0; i < _PRegions.size(); ++i) - { - for (j = 0; j < _PRegions[i]->VZones.size(); ++j) - { - CPrimZoneEditor *pz = &_PRegions[i]->VZones[j]; - // Find if the patat is visible - bool bHidden = true; - map::iterator it = _Primitives.begin (); - while (it != _Primitives.end()) - { - if ((it->second.Type == 2) && ((sint32)j == it->second.Pos)) - { - if (it->second.hidden) - bHidden = true; - else - bHidden = false; - break; - } - ++it; - } - - if ((!bHidden) && (pz->contains(v))) - { - zonelist.push_back (pz->Name); - } - } - } - - if (zonelist.size() == 0) - return; - - string sSelPB = getSelPBName(); - for (i = 0; i < zonelist.size(); ++i) - { - if (zonelist[i] == sSelPB) - break; - } - - if (i == zonelist.size()) - i = 0; - else - i = (i+1)%zonelist.size(); - sSelPB = zonelist[i]; - - map::iterator it = _Primitives.begin (); - while (it != _Primitives.end()) - { - if (sSelPB == getName(it->first)) - { - setSelPB (it->first); - break; - } - ++it; - } -} - -// --------------------------------------------------------------------------- -CRGBA CBuilderLogic::findColor(const string &Name) // region-type-001 -{ - // Get the type from the name - string sType; - uint32 i = 0; - while (i < Name.size()) - { - if (Name[i]=='-') break; - ++i; - } - if (i == Name.size()) - return CRGBA (255, 255, 255, 255); - ++i; - while (i < Name.size()) - { - if (Name[i]=='-') break; - sType += Name[i]; - ++i; - } - if (i == Name.size()) - return CRGBA (255, 255, 255, 255); - - vector &rTypes = _Display->_MainFrame->_Environnement.Types; - for (i = 0; i < rTypes.size(); ++i) - if (sType == rTypes[i].Name) - return rTypes[i].Color; - - return CRGBA (255, 255, 255, 255); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::render (CVector &viewMin, CVector &viewMax) -{ - if (DontUse3D) - return; - // Accelerate rendering with vertex buffer - CVertexBuffer VB; - CPrimitiveBlock PB; - CVertexBuffer VBL; - CPrimitiveBlock PBL; - CMaterial Mat; - - CRGBA colSel = CRGBA(255, 0, 0, 192); - - Mat.initUnlit (); - Mat.setSrcBlend(CMaterial::srcalpha); - Mat.setDstBlend(CMaterial::invsrcalpha); - Mat.setBlend (true); - Mat.setColor (CRGBA(255, 255, 255, 192)); - VB.setVertexFormat (CVertexBuffer::PositionFlag|CVertexBuffer::PrimaryColorFlag); - VBL.setVertexFormat (CVertexBuffer::PositionFlag|CVertexBuffer::PrimaryColorFlag); - - // Parse the map - map::iterator it = _Primitives.begin(); - while (it != _Primitives.end()) - { - HTREEITEM curItem = it->first; - SPrimBuild &curPB = it->second; - CPrimRegion &PRegion = *curPB.PRegion; - - CRGBA col; - uint32 i; - - // If not created do not display or hidden - if ((!curPB.Created)||(curPB.hidden)) - { - ++it; - continue; - } - - CPrimVector *pVec = NULL; - uint32 nNbVec = 0; - - // Clip - - if (curPB.Type == 0) // Point - { - col = findColor (PRegion.VPoints[curPB.Pos].Name); - pVec = &PRegion.VPoints[curPB.Pos].Point; - nNbVec = 1; - } - - if (curPB.Type == 1) // Path - { - col = findColor (PRegion.VPaths[curPB.Pos].Name); - nNbVec = PRegion.VPaths[curPB.Pos].VPoints.size(); - if (nNbVec > 0) - pVec = &PRegion.VPaths[curPB.Pos].VPoints[0]; - } - - if (curPB.Type == 2) // Zone - { - col = findColor (PRegion.VZones[curPB.Pos].Name); - nNbVec = PRegion.VZones[curPB.Pos].VPoints.size(); - if (nNbVec > 0) - pVec = &PRegion.VZones[curPB.Pos].VPoints[0]; - } - - col.A = 192; - - if (nNbVec == 0) - { - ++it; - continue; - } - - if (clip(pVec, nNbVec, viewMin, viewMax)) - { - ++it; - continue; - } - - - // Draw all interiors - - if (curPB.Type == 2) // For Zones - { - vector vRef; - uint32 nStart, VBStart = VB.getNumVertices(), PBStart = PB.getNumTri(); - vRef.resize(nNbVec); - for(i = 0; i < vRef.size(); ++i) - vRef[i] = i; - - nStart = 0; - while (vRef.size() > 2) - { - // Is triangle (nStart, nStart+1, nStart+2) back face ? - sint32 nP1 = vRef[nStart]; - sint32 nP2 = vRef[(nStart+1)%vRef.size()]; - sint32 nP3 = vRef[(nStart+2)%vRef.size()]; - CVector pos1 = pVec[nP1]; - CVector pos2 = pVec[nP2]; - CVector pos3 = pVec[nP3]; - if (((pos2.x-pos1.x) * (pos3.y-pos1.y) - (pos2.y-pos1.y) * (pos3.x-pos1.x)) < 0.0f) - { - // Yes -> next triangle - nStart++; - //nlassert(nStart != vRef.size()); - if (nStart == vRef.size()) - { - VB.setNumVertices (VBStart); - PB.setNumTri(PBStart); - break; - } - continue; - } - // Is triangle (nStart, nStart+1, nStart+2) contains the other point ? - bool bInside = false; - for (i = 0; i < vRef.size(); ++i) - { - if ((vRef[i] != nP1) && (vRef[i] != nP2) && (vRef[i] != nP3)) - { - if (isInTriangleOrEdge( pVec[vRef[i]].x, pVec[vRef[i]].y, - pos1.x, pos1.y, - pos2.x, pos2.y, - pos3.x, pos3.y )) - { - bInside = true; - break; - } - } - } - if (bInside) - { - // Yes -> next triangle - nStart++; - //nlassert(nStart != vRef.size()); - if (nStart == vRef.size()) - { - VB.setNumVertices (VBStart); - PB.setNumTri(PBStart); - break; - } - continue; - } - - // Draw the triangle - convertToScreen (&pos1, 1, viewMin, viewMax); - convertToScreen (&pos2, 1, viewMin, viewMax); - convertToScreen (&pos3, 1, viewMin, viewMax); - if (curItem == _ItemSelected) - renderDrawTriangle(pos1, pos2, pos3, colSel, &VB, &PB); - else - renderDrawTriangle(pos1, pos2, pos3, col, &VB, &PB); - - // Erase the point in the middle - for (i = 1+((nStart+1)%vRef.size()); i < vRef.size(); ++i) - vRef[i-1] = vRef[i]; - vRef.resize (vRef.size()-1); - nStart = 0; - } - } - - // Draw all lines - - if ((curPB.Type == 1) || (curPB.Type == 2)) // For Pathes and Zones - { - uint32 nNbLineToDraw = (curPB.Type == 2)?(nNbVec):(nNbVec-1); - if ((nNbLineToDraw == 1)&&(curPB.Type == 2)) - nNbLineToDraw = 0; - for (i = 0; i < nNbLineToDraw; ++i) - { - CVector pos = pVec[i]; - CVector pos2 = pVec[(i+1)%(nNbVec)]; - - convertToScreen (&pos, 1, viewMin, viewMax); - convertToScreen (&pos2, 1, viewMin, viewMax); - if (curItem == _ItemSelected) - renderDrawLine (pos, pos2, colSel, &VBL, &PBL); - else - renderDrawLine (pos, pos2, col, &VBL, &PBL); - } - } - - // Draw all points - bool bDrawPoints = true; - - if (curPB.Type == 2) // Zone - if (curItem != _ItemSelected) - bDrawPoints = false; // Do not draw the points on zone other than selected one - - if (bDrawPoints) - for (i = 0; i < nNbVec; ++i) // For Points, Pathes and Zones - { - CVector pos = pVec[i]; - convertToScreen (&pos, 1, viewMin, viewMax); - if (curItem == _ItemSelected) - { - bool bFound = false; - for (uint32 k = 0; k < _VerticesSelected.size(); ++k) - if (_VerticesSelected[k] == (sint32)i) - { - bFound = true; - break; - } - if (bFound) - renderDrawPoint (pos, colSel, &VBL, &PBL); - else - renderDrawPoint (pos, col, &VBL, &PBL); - } - else - { - renderDrawPoint (pos, col, &VBL, &PBL); - } - } - - ++it; - } - - // Flush the Vertex Buffer - - CMatrix mtx; - mtx.identity(); - CNELU::Driver->setupViewport (CViewport()); - CNELU::Driver->setupViewMatrix (mtx); - CNELU::Driver->setupModelMatrix (mtx); - CNELU::Driver->setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false); - CNELU::Driver->activeVertexBuffer(VB); - CNELU::Driver->render(PB, Mat); - CNELU::Driver->activeVertexBuffer(VBL); - CNELU::Driver->render(PBL, Mat); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::renderDrawPoint (CVector &pos, CRGBA &col, CVertexBuffer *pVB, CPrimitiveBlock *pPB) -{ - if (DontUse3D) - return; - - if (pVB == NULL) - { - CDRU::drawLine (pos.x-0.01f, pos.y, pos.x+0.01f, pos.y, *CNELU::Driver, col); - CDRU::drawLine (pos.x, pos.y-0.01f, pos.x, pos.y+0.01f, *CNELU::Driver, col); - } - else - { - sint32 nVBPos = pVB->getNumVertices(); - pVB->setNumVertices (nVBPos+4); - pVB->setVertexCoord (nVBPos+0, pos.x-0.01f, pos.z, pos.y); - pVB->setVertexCoord (nVBPos+1, pos.x+0.01f, pos.z, pos.y); - pVB->setVertexCoord (nVBPos+2, pos.x, pos.z, pos.y-0.01f); - pVB->setVertexCoord (nVBPos+3, pos.x, pos.z, pos.y+0.01f); - pVB->setColor (nVBPos+0, col); - pVB->setColor (nVBPos+1, col); - pVB->setColor (nVBPos+2, col); - pVB->setColor (nVBPos+3, col); - sint32 nPBPos = pPB->getNumLine(); - pPB->setNumLine (nPBPos+2); - pPB->setLine (nPBPos+0, nVBPos+0, nVBPos+1); - pPB->setLine (nPBPos+1, nVBPos+2, nVBPos+3); - } -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::renderDrawLine (CVector &pos, CVector &pos2, CRGBA &col, CVertexBuffer *pVB, CPrimitiveBlock *pPB) -{ - sint32 nVBPos = pVB->getNumVertices(); - pVB->setNumVertices (nVBPos+2); - pVB->setVertexCoord (nVBPos+0, pos.x, pos.z, pos.y); - pVB->setVertexCoord (nVBPos+1, pos2.x, pos2.z, pos2.y); - pVB->setColor (nVBPos+0, col); - pVB->setColor (nVBPos+1, col); - sint32 nPBPos = pPB->getNumLine(); - pPB->setNumLine (nPBPos+1); - pPB->setLine (nPBPos+0, nVBPos+0, nVBPos+1); -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::renderDrawTriangle (CVector &pos, CVector &pos2, CVector &pos3, CRGBA &col, CVertexBuffer *pVB, CPrimitiveBlock *pPB) -{ - sint32 nVBPos = pVB->getNumVertices(); - pVB->setNumVertices (nVBPos+3); - pVB->setVertexCoord (nVBPos+0, pos.x, pos.z, pos.y); - pVB->setVertexCoord (nVBPos+1, pos2.x, pos2.z, pos2.y); - pVB->setVertexCoord (nVBPos+2, pos3.x, pos3.z, pos3.y); - pVB->setColor (nVBPos+0, col); - pVB->setColor (nVBPos+1, col); - pVB->setColor (nVBPos+2, col); - sint32 nPBPos = pPB->getNumTri(); - pPB->setNumTri (nPBPos+1); - pPB->setTri (nPBPos+0, nVBPos+0, nVBPos+1, nVBPos+2); -} - -// --------------------------------------------------------------------------- -bool CBuilderLogic::clip (CPrimVector *pVec, uint32 nNbVec, CVector &viewMin, CVector &viewMax) -{ - uint32 i; - for (i = 0; i < nNbVec; ++i) - if (pVec[i].x > viewMin.x) - break; - if (i == nNbVec) - return true; // Entirely clipped - - for (i = 0; i < nNbVec; ++i) - if (pVec[i].x < viewMax.x) - break; - if (i == nNbVec) - return true; - - for (i = 0; i < nNbVec; ++i) - if (pVec[i].y > viewMin.y) - break; - if (i == nNbVec) - return true; - - for (i = 0; i < nNbVec; ++i) - if (pVec[i].y < viewMax.y) - break; - if (i == nNbVec) - return true; - return false; // Not entirely clipped -} - -// --------------------------------------------------------------------------- -void CBuilderLogic::convertToScreen (CVector* pVec, sint nNbVec, CVector &viewMin, CVector &viewMax) -{ - for (sint i = 0; i < nNbVec; ++i) - { - pVec[i].x = (pVec[i].x-viewMin.x)/(viewMax.x-viewMin.x); - pVec[i].y = (pVec[i].y-viewMin.y)/(viewMax.y-viewMin.y); - pVec[i].z = 0.0f; - } -} - -// --------------------------------------------------------------------------- -bool CBuilderLogic::isInTriangleOrEdge( double x, double y, - double xt1, double yt1, - double xt2, double yt2, - double xt3, double yt3 ) -{ - // Test vector T1X and T1T2 - double sign1 = ((xt2-xt1)*(y-yt1) - (yt2-yt1)*(x-xt1)); - // Test vector T2X and T2T3 - double sign2 = ((xt3-xt2)*(y-yt2) - (yt3-yt2)*(x-xt2)); - // Test vector T3X and T3T1 - double sign3 = ((xt1-xt3)*(y-yt3) - (yt1-yt3)*(x-xt3)); - if( (sign1 <= 0.0)&&(sign2 <= 0.0)&&(sign3 <= 0.0) ) - return true; - if( (sign1 >= 0.0)&&(sign2 >= 0.0)&&(sign3 >= 0.0) ) - return true; - return false; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" + +#include "world_editor_doc.h" +#include "display.h" + +using namespace NLLIGO; +using namespace NLMISC; +using namespace NL3D; +using namespace std; + +// *************************************************************************** +// SPrimBuild +// *************************************************************************** + +// --------------------------------------------------------------------------- + +// *************************************************************************** +// CBuilderLogic +// *************************************************************************** + +// --------------------------------------------------------------------------- +CBuilderLogic::CBuilderLogic() +: _LogicCallback(0) +{ + _ItemSelected = NULL; + _RegionSelected = -1; + _ToolsLogic = NULL; + _Display = NULL; +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::setDisplay (CDisplay *pDisp) +{ + _Display = pDisp; +} + + +void CBuilderLogic::notify() +{ + if (_LogicCallback) + { + CWorldEditorDoc *doc = getDocument (); + uint primCount = doc->getNumDatabaseElement (); + for (uint i=0; ionLogicChanged (i); + } + } +} + +void CBuilderLogic::setLogicCallback(ILogicCallback *logicCallback) +{ + _LogicCallback = logicCallback; +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::setToolsLogic (CToolsLogic *pTool) +{ + _ToolsLogic = pTool; +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::uninit() +{ + _Display = NULL; +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::updateToolsLogic () +{ + notify(); + // Regenerate the toolsLogic with the data in the region + if (_ToolsLogic == NULL) + return; + + _ToolsLogic->reset(); + uint32 i, j; + sint32 tempItem = -1; + for (j = 0; j < getDocument ()->getNumDatabaseElement (); ++j) + { + const CPrimRegion &rRegion = getDocument ()->getPrimRegion (j); + sint32 nReg = j; + + map mapGroups; + map::iterator itGroups; + + // Create Regions + nReg = _ToolsLogic->createNewRegion (rRegion.Name); + + // Create Groups + for (i = 0; i < rRegion.VPoints.size(); ++i) + { + itGroups = mapGroups.find(rRegion.VPoints[i].LayerName); + if (itGroups == mapGroups.end()) + { + uint32 nGroup = _ToolsLogic->createNewGroup (j, rRegion.VPoints[i].LayerName); + mapGroups.insert (make_pair(rRegion.VPoints[i].LayerName, nGroup)); + } + } + for (i = 0; i < rRegion.VPaths.size(); ++i) + { + itGroups = mapGroups.find(rRegion.VPaths[i].LayerName); + if (itGroups == mapGroups.end()) + { + uint32 nGroup = _ToolsLogic->createNewGroup (j, rRegion.VPaths[i].LayerName); + mapGroups.insert (make_pair(rRegion.VPaths[i].LayerName, nGroup)); + } + } + for (i = 0; i < rRegion.VZones.size(); ++i) + { + itGroups = mapGroups.find(rRegion.VZones[i].LayerName); + if (itGroups == mapGroups.end()) + { + uint32 nGroup = _ToolsLogic->createNewGroup (j, rRegion.VZones[i].LayerName); + mapGroups.insert (make_pair(rRegion.VZones[i].LayerName, nGroup)); + } + } + + for (i = 0; i < rRegion.VPoints.size(); ++i) + { + HTREEITEM newItem = (HTREEITEM)tempItem; + tempItem--; + itGroups = mapGroups.find(rRegion.VPoints[i].LayerName); + if (itGroups != mapGroups.end()) + if (rRegion.VPoints[i].Name != "-- Delete Me --") + { + newItem = _ToolsLogic->addPoint (nReg, itGroups->second, rRegion.VPoints[i].Name.c_str(), rRegion.VHidePoints[i]); + } + } + + for (i = 0; i < rRegion.VPaths.size(); ++i) + { + HTREEITEM newItem = (HTREEITEM)tempItem; + tempItem--; + itGroups = mapGroups.find(rRegion.VPaths[i].LayerName); + if (itGroups != mapGroups.end()) + if (rRegion.VPaths[i].Name != "-- Delete Me --") + { + newItem = _ToolsLogic->addPath (nReg, itGroups->second, rRegion.VPaths[i].Name.c_str(), rRegion.VHidePaths[i]); + } + } + + for (i = 0; i < rRegion.VZones.size(); ++i) + { + HTREEITEM newItem = (HTREEITEM)tempItem; + tempItem--; + itGroups = mapGroups.find(rRegion.VZones[i].LayerName); + if (itGroups != mapGroups.end()) + if (rRegion.VZones[i].Name != "-- Delete Me --") + { + newItem = _ToolsLogic->addZone (nReg, itGroups->second, rRegion.VZones[i].Name.c_str(), rRegion.VHideZones[i]); + } + } + } + + + _VerticesSelected.resize (0); +} + +// --------------------------------------------------------------------------- +const string &CBuilderLogic::getZoneRegionName (uint32 nPos) +{ + return _PRegions[nPos]->Name; +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::move (const string ®Name, float x, float y) +{ + uint32 i, j, k; + + for (i = 0; i < _PRegions.size(); ++i) + if (_PRegions[i]->Name == regName) + { + _MustAskSaves[i] = true; + for (j = 0; j < _PRegions[i]->VPoints.size(); ++j) + { + _PRegions[i]->VPoints[j].Point.x += x; + _PRegions[i]->VPoints[j].Point.y += y; + } + + for (j = 0; j < _PRegions[i]->VPaths.size(); ++j) + { + for (k = 0; k < _PRegions[i]->VPaths[j].VPoints.size(); ++k) + { + _PRegions[i]->VPaths[j].VPoints[k].x += x; + _PRegions[i]->VPaths[j].VPoints[k].y += y; + } + } + + for (j = 0; j < _PRegions[i]->VZones.size(); ++j) + { + for (k = 0; k < _PRegions[i]->VZones[j].VPoints.size(); ++k) + { + _PRegions[i]->VZones[j].VPoints[k].x += x; + _PRegions[i]->VZones[j].VPoints[k].y += y; + } + } + notify(); + return; + } +} + +// --------------------------------------------------------------------------- + +void CBuilderLogic::insertPoint (uint32 pos, HTREEITEM item, const char *Name, const char *LayerName) +{ + + CPrimPointEditor pp; + pp.LayerName = LayerName; + pp.Name = Name; + pp.Point = CVector(0.0f, 0.0f, 0.0f); + _PRegions[pos]->VPoints.push_back (pp); + _PRegions[pos]->VHidePoints.push_back (false); + SPrimBuild pB; + pB.Type = 0; // Point + pB.Pos = _PRegions[pos]->VPoints.size()-1; + pB.PRegion = _PRegions[pos]; + _Primitives.insert (map::value_type(item, pB)); + _MustAskSaves[pos] = true; + + notify(); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::insertPath (uint32 pos, HTREEITEM item, const char *Name, const char *LayerName) +{ + + CPrimPathEditor pp; + pp.LayerName = LayerName; + pp.Name = Name; + _PRegions[pos]->VPaths.push_back (pp); + _PRegions[pos]->VHidePaths.push_back (false); + SPrimBuild pB; + pB.Type = 1; // Path + pB.Pos = _PRegions[pos]->VPaths.size()-1; + pB.PRegion = _PRegions[pos]; + _Primitives.insert (map::value_type(item, pB)); + _MustAskSaves[pos] = true; + + notify(); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::insertZone (uint32 pos, HTREEITEM item, const char *Name, const char *LayerName) +{ + CPrimZoneEditor pz; + pz.LayerName = LayerName; + pz.Name = Name; + _PRegions[pos]->VZones.push_back (pz); + _PRegions[pos]->VHideZones.push_back (false); + SPrimBuild pB; + pB.Type = 2; // Zone + pB.Pos = _PRegions[pos]->VZones.size()-1; + pB.PRegion = _PRegions[pos]; + _Primitives.insert (map::value_type(item, pB)); + _MustAskSaves[pos] = true; + + notify(); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::del (HTREEITEM item) +{ + map::iterator it = _Primitives.find (item); + + if (it != _Primitives.end()) + { + SPrimBuild &rPB = it->second; + CPrimRegion &PRegion = *rPB.PRegion; + // Delete the entry in the document + + + // Delete in the region + switch (rPB.Type) + { + case 0: + { + PRegion.VPoints.erase (PRegion.VPoints.begin()+rPB.Pos); + PRegion.VHidePoints.erase (PRegion.VHidePoints.begin()+rPB.Pos); + } + break; + case 1: + { + PRegion.VPaths.erase (PRegion.VPaths.begin()+rPB.Pos); + PRegion.VHidePaths.erase (PRegion.VHidePaths.begin()+rPB.Pos); + } + break; + case 2: + PRegion.VZones.erase (PRegion.VZones.begin()+rPB.Pos); + PRegion.VHideZones.erase (PRegion.VHideZones.begin()+rPB.Pos); + break; + } + // Update position + map::iterator it2 = _Primitives.begin (); + while (it2 != _Primitives.end()) + { + SPrimBuild &rPB2 = it2->second; + + if ((rPB2.PRegion == rPB.PRegion)&&(rPB2.Type == rPB.Type)) + if (rPB2.Pos > rPB.Pos) + rPB2.Pos -= 1; + + ++it2; + } + // Delete the entry in the map + _Primitives.erase (it); + + for (uint32 z = 0; z < _PRegions.size(); ++z) + if (_PRegions[z] == &PRegion) + { + _MustAskSaves[z] = true; + break; + } + } + notify(); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::primHide (HTREEITEM item) +{ + map::iterator it = _Primitives.find (item); + if (it != _Primitives.end()) + { + SPrimBuild &rPB = it->second; + rPB.hidden = true; + if (rPB.Type == 0) // Points + { + rPB.PRegion->VHidePoints[rPB.Pos] = true; + } + else if (rPB.Type == 1) // Paths + { + rPB.PRegion->VHidePaths[rPB.Pos] = true; + } + else if (rPB.Type == 2) /// Zones + { + rPB.PRegion->VHideZones[rPB.Pos] = true; + } + } +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::primUnhide (HTREEITEM item) +{ + map::iterator it = _Primitives.find (item); + if (it != _Primitives.end()) + { + SPrimBuild &rPB = it->second; + rPB.hidden = false; + if (rPB.Type == 0) // Points + { + rPB.PRegion->VHidePoints[rPB.Pos] = false; + } + else if (rPB.Type == 1) // Paths + { + rPB.PRegion->VHidePaths[rPB.Pos] = false; + } + else if (rPB.Type == 2) /// Zones + { + rPB.PRegion->VHideZones[rPB.Pos] = false; + } + } +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::hideAll (uint32 nPos, sint32 nID, bool bHide) +{ + map::iterator it = _Primitives.begin (); + while (it != _Primitives.end()) + { + SPrimBuild &rPB = it->second; + + if (rPB.PRegion == _PRegions[nPos]) + { + if (rPB.Type == nID) + { + rPB.hidden = bHide; + if (rPB.Type == 0) // Points + { + rPB.PRegion->VHidePoints[rPB.Pos] = bHide; + } + else if (rPB.Type == 1) // Paths + { + rPB.PRegion->VHidePaths[rPB.Pos] = bHide; + } + else if (rPB.Type == 2) /// Zones + { + rPB.PRegion->VHideZones[rPB.Pos] = bHide; + } + } + } + + ++it; + } +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::regionSetName (uint32 nPos, HTREEITEM item, const string &sRegionName) +{ + CPrimRegion &rPR = *_PRegions[nPos]; + rPR.Name = sRegionName; + notify(); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::regionCreateGroup (uint32 nPos, HTREEITEM newItem, const string &sGroupName) +{ + insertPoint (nPos, (HTREEITEM)-1, "-- Delete Me --", sGroupName.c_str()); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::regionDeleteGroup (uint32 nPos, const std::string &sGroupName) +{ + sint32 i, j; + for (i = 0; i < (sint32)_PRegions[nPos]->VPoints.size(); ++i) + { + if (_PRegions[nPos]->VPoints[i].LayerName == sGroupName) + { + for (j = i+1; j < (sint32)_PRegions[nPos]->VPoints.size(); ++j) + _PRegions[nPos]->VPoints[j-1] = _PRegions[nPos]->VPoints[j]; + _PRegions[nPos]->VPoints.resize (_PRegions[nPos]->VPoints.size()-1); + i = -1; + } + } + notify(); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::regionHideAll (uint32 nPos, bool bHide) +{ + map::iterator it = _Primitives.begin (); + while (it != _Primitives.end()) + { + SPrimBuild &rPB = it->second; + + if (rPB.PRegion == _PRegions[nPos]) + rPB.hidden = bHide; + + ++it; + } +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::regionHideType (uint32 nPos, const string &Type, bool bHide) +{ + map::iterator it = _Primitives.begin (); + while (it != _Primitives.end()) + { + SPrimBuild &rPB = it->second; + + if (rPB.PRegion == _PRegions[nPos]) + { + string Name, Tmp; + switch (rPB.Type) + { + case 0: Name = _PRegions[nPos]->VPoints[rPB.Pos].Name; break; + case 1: Name = _PRegions[nPos]->VPaths[rPB.Pos].Name; break; + case 2: Name = _PRegions[nPos]->VZones[rPB.Pos].Name; break; + } + + uint32 i = 0; + while (Name[i] != '-') ++i; + i++; + while ((Name[i] != '-') && (i < Name.size())) + { + Tmp += Name[i]; + ++i; + } + if (Tmp == Type) + rPB.hidden = bHide; + } + + ++it; + } +} + +// --------------------------------------------------------------------------- +int CBuilderLogic::getMaxPostfix (const char *prefix) +{ + int nTmp; + int nZeMax = -1; + int nPFLen = strlen(prefix); + + map::iterator it = _Primitives.begin (); + while (it != _Primitives.end()) + { + SPrimBuild &rPB = it->second; + nTmp = 0; + switch (rPB.Type) + { + case 0: // Point + if (strncmp(prefix, rPB.PRegion->VPoints[rPB.Pos].Name.c_str(), nPFLen) == 0) + { + CPrimPointEditor &rP = rPB.PRegion->VPoints[rPB.Pos]; + if ((rP.Name[nPFLen+0] >= '0') && (rP.Name[nPFLen+0] <= '9') && + (rP.Name[nPFLen+1] >= '0') && (rP.Name[nPFLen+1] <= '9') && + (rP.Name[nPFLen+2] >= '0') && (rP.Name[nPFLen+2] <= '9')) + { + nTmp = (rP.Name[nPFLen+0] - '0')*100; + nTmp += (rP.Name[nPFLen+1] - '0')*10; + nTmp += (rP.Name[nPFLen+2] - '0')*1; + } + } + break; + case 1: // Path + if (strncmp(prefix, rPB.PRegion->VPaths[rPB.Pos].Name.c_str(), nPFLen) == 0) + { + CPrimPathEditor &rP = rPB.PRegion->VPaths[rPB.Pos]; + if ((rP.Name[nPFLen+0] >= '0') && (rP.Name[nPFLen+0] <= '9') && + (rP.Name[nPFLen+1] >= '0') && (rP.Name[nPFLen+1] <= '9') && + (rP.Name[nPFLen+2] >= '0') && (rP.Name[nPFLen+2] <= '9')) + { + nTmp = (rP.Name[nPFLen+0] - '0')*100; + nTmp += (rP.Name[nPFLen+1] - '0')*10; + nTmp += (rP.Name[nPFLen+2] - '0')*1; + } + } + break; + case 2: // Zone + if (strncmp(prefix, rPB.PRegion->VZones[rPB.Pos].Name.c_str(), nPFLen) == 0) + { + CPrimZoneEditor &rP = rPB.PRegion->VZones[rPB.Pos]; + if ((rP.Name[nPFLen+0] >= '0') && (rP.Name[nPFLen+0] <= '9') && + (rP.Name[nPFLen+1] >= '0') && (rP.Name[nPFLen+1] <= '9') && + (rP.Name[nPFLen+2] >= '0') && (rP.Name[nPFLen+2] <= '9')) + { + nTmp = (rP.Name[nPFLen+0] - '0')*100; + nTmp += (rP.Name[nPFLen+1] - '0')*10; + nTmp += (rP.Name[nPFLen+2] - '0')*1; + } + } + break; + } + + if (nZeMax < nTmp) + nZeMax = nTmp; + + ++it; + } + + return nZeMax; +} + +// --------------------------------------------------------------------------- +bool CBuilderLogic::isAlreadyExisting (const char *sPrimitiveName) +{ + map::iterator it = _Primitives.begin (); + while (it != _Primitives.end()) + { + SPrimBuild &rPB = it->second; + + switch (rPB.Type) + { + case 0: // Point + if (strcmp(sPrimitiveName, rPB.PRegion->VPoints[rPB.Pos].Name.c_str()) == 0) + return true; + break; + case 1: // Path + if (strcmp(sPrimitiveName, rPB.PRegion->VPaths[rPB.Pos].Name.c_str()) == 0) + return true; + break; + case 2: // Zone + if (strcmp(sPrimitiveName, rPB.PRegion->VZones[rPB.Pos].Name.c_str()) == 0) + return true; + break; + default: + break; + } + ++it; + } + return false; +} + +// --------------------------------------------------------------------------- +const char* CBuilderLogic::getName (HTREEITEM item) +{ + map::iterator it = _Primitives.find (item); + if (it == _Primitives.end()) + return NULL; + else + { + SPrimBuild &rPB = it->second; + CPrimRegion &PRegion = *rPB.PRegion; + + switch (rPB.Type) + { + case 0: + return PRegion.VPoints[rPB.Pos].Name.c_str(); + break; + case 1: + return PRegion.VPaths[rPB.Pos].Name.c_str(); + break; + case 2: + return PRegion.VZones[rPB.Pos].Name.c_str(); + break; + } + return NULL; + } +} + +// --------------------------------------------------------------------------- +const char* CBuilderLogic::getLayerName (HTREEITEM item) +{ + map::iterator it = _Primitives.find (item); + if (it == _Primitives.end()) + return NULL; + else + { + SPrimBuild &rPB = it->second; + CPrimRegion &PRegion = *rPB.PRegion; + + switch (rPB.Type) + { + case 0: + return PRegion.VPoints[rPB.Pos].LayerName.c_str(); + break; + case 1: + return PRegion.VPaths[rPB.Pos].LayerName.c_str(); + break; + case 2: + return PRegion.VZones[rPB.Pos].LayerName.c_str(); + break; + } + return NULL; + } +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::getAllPrimZoneNames (vector &allNames) +{ + allNames.clear (); + for (uint32 i = 0; i < _PRegions.size(); ++i) + for (uint32 j = 0; j < _PRegions[i]->VZones.size(); ++j) + allNames.push_back (_PRegions[i]->VZones[j].Name); +} + + +// --------------------------------------------------------------------------- +bool CBuilderLogic::isHidden (HTREEITEM item) +{ + map::iterator it = _Primitives.find (item); + if (it == _Primitives.end()) + { + return true; + } + else + { + SPrimBuild &rPB = it->second; + return rPB.hidden; + } +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::setName (HTREEITEM item, const char* pStr) +{ + map::iterator it = _Primitives.find (item); + if (it == _Primitives.end()) + return; + else + { + SPrimBuild &rPB = it->second; + CPrimRegion &PRegion = *rPB.PRegion; + + switch (rPB.Type) + { + case 0: + PRegion.VPoints[rPB.Pos].Name = pStr; + break; + case 1: + PRegion.VPaths[rPB.Pos].Name = pStr; + break; + case 2: + PRegion.VZones[rPB.Pos].Name = pStr; + break; + } + + for (uint32 z = 0; z < _PRegions.size(); ++z) + if (_PRegions[z] == &PRegion) + { + _MustAskSaves[z] = true; + break; + } + + } + notify(); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::setLayerName (HTREEITEM item, const char* pStr) +{ + map::iterator it = _Primitives.find (item); + if (it == _Primitives.end()) + return; + else + { + SPrimBuild &rPB = it->second; + CPrimRegion &PRegion = *rPB.PRegion; + + switch (rPB.Type) + { + case 0: + PRegion.VPoints[rPB.Pos].LayerName = pStr; + break; + case 1: + PRegion.VPaths[rPB.Pos].LayerName = pStr; + break; + case 2: + PRegion.VZones[rPB.Pos].LayerName = pStr; + break; + } + + for (uint32 z = 0; z < _PRegions.size(); ++z) + if (_PRegions[z] == &PRegion) + { + _MustAskSaves[z] = true; + break; + } + } + notify(); +} + +// --------------------------------------------------------------------------- +HTREEITEM CBuilderLogic::getSelPB () +{ + return _ItemSelected; +} + +// --------------------------------------------------------------------------- +std::string CBuilderLogic::getSelPBName () +{ + map::iterator it = _Primitives.find (_ItemSelected); + if (it != _Primitives.end()) + { + SPrimBuild &rPB = it->second; + CPrimRegion &PRegion = *rPB.PRegion; + + switch (rPB.Type) + { + case 0: return PRegion.VPoints[rPB.Pos].Name; + case 1: return PRegion.VPaths[rPB.Pos].Name; + case 2: return PRegion.VZones[rPB.Pos].Name; + } + } + + return ""; +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::setSelPB (HTREEITEM item) +{ + _VerticesSelected.clear (); + _ItemSelected = NULL; + map::iterator it = _Primitives.find (item); + if (it != _Primitives.end()) + { + _ItemSelected = item; + _ItemSelectedName = getName(_ItemSelected); + _ToolsLogic->GetTreeCtrl()->Select(item, TVGN_CARET); + } +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::createVertexOnSelPB (CVector &v, sint32 atPos) +{ + map::iterator it = _Primitives.find (_ItemSelected); + if (it == _Primitives.end()) + return; + SPrimBuild &rPB = it->second; + CPrimRegion &PRegion = *rPB.PRegion; + + switch (rPB.Type) + { + case 0: + if (!rPB.Created) + { + PRegion.VPoints[rPB.Pos].Point = v; + rPB.Created = true; + } + break; + case 1: + if (!rPB.Created) + { + rPB.Created = true; + } + if (atPos != -1) + { + PRegion.VPaths[rPB.Pos].VPoints.insert (PRegion.VPaths[rPB.Pos].VPoints.begin()+atPos, v); + } + else + { + PRegion.VPaths[rPB.Pos].VPoints.push_back(v); + } + break; + case 2: + if (!rPB.Created) + { + rPB.Created = true; + } + if (atPos != -1) + { + PRegion.VZones[rPB.Pos].VPoints.insert (PRegion.VZones[rPB.Pos].VPoints.begin()+atPos, v); + } + else + { + PRegion.VZones[rPB.Pos].VPoints.push_back(v); + } + break; + } + for (uint32 z = 0; z < _PRegions.size(); ++z) + if (_PRegions[z] == &PRegion) + { + _MustAskSaves[z] = true; + break; + } + + notify(); +} + +// --------------------------------------------------------------------------- +bool CBuilderLogic::selectVerticesOnSelPB (CVector &selMin, CVector &selMax) +{ + _VerticesSelected.clear (); + map::iterator it = _Primitives.find (_ItemSelected); + if (it == _Primitives.end()) + return false; + + SPrimBuild &rPB = it->second; + CPrimRegion &PRegion = *rPB.PRegion; + + if (!rPB.Created) + return false; + + CPrimVector *pV = NULL; + uint32 nNbV = 0; + switch (rPB.Type) + { + case 0: + nNbV = 1; + pV = &(PRegion.VPoints[rPB.Pos].Point); + break; + case 1: + nNbV = PRegion.VPaths[rPB.Pos].VPoints.size(); + pV = &(PRegion.VPaths[rPB.Pos].VPoints[0]); + break; + case 2: + nNbV = PRegion.VZones[rPB.Pos].VPoints.size(); + pV = &(PRegion.VZones[rPB.Pos].VPoints[0]); + break; + } + float selMinX = min(selMin.x, selMax.x); + float selMinY = min(selMin.y, selMax.y); + float selMaxX = max(selMin.x, selMax.x); + float selMaxY = max(selMin.y, selMax.y); + + for (uint32 i = 0; i < nNbV; ++i) + { + if ((pV[i].x > selMinX) && (pV[i].x < selMaxX) && + (pV[i].y > selMinY) && (pV[i].y < selMaxY)) + { + _VerticesSelected.push_back (i); + } + } + if (_VerticesSelected.size() == 0) + return false; + return true; +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::createIsoVertexOnSelVertexOnSelPB () +{ + if ((_VerticesSelected.size() <= 1) || (_ItemSelected == NULL)) + return; + map::iterator it = _Primitives.find (_ItemSelected); + if (it == _Primitives.end()) + return; + SPrimBuild &rPB = it->second; + CPrimRegion &PRegion = *rPB.PRegion; + CVector v(0.0f, 0.0f, 0.0f); + + sint minvs = 30000; + for (uint32 i = 0; i < _VerticesSelected.size(); ++i) + { + switch (rPB.Type) + { + case 0: + v += PRegion.VPoints[rPB.Pos].Point; + break; + case 1: + v += PRegion.VPaths[rPB.Pos].VPoints[_VerticesSelected[i]]; + break; + case 2: + v += PRegion.VZones[rPB.Pos].VPoints[_VerticesSelected[i]]; + break; + } + if (_VerticesSelected[i] < minvs) + minvs = _VerticesSelected[i]; + } + v /= (float)_VerticesSelected.size(); + + if (rPB.Type == 2) + { + CPrimZoneEditor &pz = PRegion.VZones[rPB.Pos]; + if (((_VerticesSelected[0] == 0) && (_VerticesSelected[1] == ((sint32)pz.VPoints.size()-1))) || + ((_VerticesSelected[0] == ((sint32)pz.VPoints.size()-1)) && (_VerticesSelected[1] == 0))) + { + createVertexOnSelPB (v, 0); + } + else + { + createVertexOnSelPB (v, minvs+1); + } + } + else + { + createVertexOnSelPB (v, minvs+1); + } +} + +// --------------------------------------------------------------------------- +bool CBuilderLogic::isSelection() +{ + return (_VerticesSelected.size() > 0); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::setSelVerticesOnSelPB (NLMISC::CVector &v) +{ + if ((_VerticesSelected.size() == 0) || (_ItemSelected == NULL)) + return; + map::iterator it = _Primitives.find (_ItemSelected); + if (it == _Primitives.end()) + return; + SPrimBuild &rPB = it->second; + CPrimRegion &PRegion = *rPB.PRegion; + + for (uint32 i = 0; i < _VerticesSelected.size(); ++i) + { + switch (rPB.Type) + { + case 0: + PRegion.VPoints[rPB.Pos].Point += v; + break; + case 1: + PRegion.VPaths[rPB.Pos].VPoints[_VerticesSelected[i]] += v; + break; + case 2: + PRegion.VZones[rPB.Pos].VPoints[_VerticesSelected[i]] += v; + break; + } + } + + for (uint32 z = 0; z < _PRegions.size(); ++z) + if (_PRegions[z] == &PRegion) + { + _MustAskSaves[z] = true; + break; + } + notify(); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::delSelVerticesOnSelPB () +{ + if ((_VerticesSelected.size() == 0) || (_ItemSelected == NULL)) + return; + map::iterator it = _Primitives.find (_ItemSelected); + if (it == _Primitives.end()) + return; + SPrimBuild &rPB = it->second; + CPrimRegion &PRegion = *rPB.PRegion; + + uint32 i; + for (uint32 k = 0; k < _VerticesSelected.size(); ++k) + { + int VertexSelected = _VerticesSelected[k]; + switch (rPB.Type) + { + case 0: + rPB.Created = false; + break; + case 1: + if (PRegion.VPaths[rPB.Pos].VPoints.size() == 1) + rPB.Created = false; + + for (i = VertexSelected+1; i < PRegion.VPaths[rPB.Pos].VPoints.size(); ++i) + PRegion.VPaths[rPB.Pos].VPoints[i-1] = PRegion.VPaths[rPB.Pos].VPoints[i]; + PRegion.VPaths[rPB.Pos].VPoints.resize (PRegion.VPaths[rPB.Pos].VPoints.size()-1); + break; + case 2: + if (PRegion.VZones[rPB.Pos].VPoints.size() == 1) + rPB.Created = false; + + for (i = VertexSelected+1; i < PRegion.VZones[rPB.Pos].VPoints.size(); ++i) + PRegion.VZones[rPB.Pos].VPoints[i-1] = PRegion.VZones[rPB.Pos].VPoints[i]; + PRegion.VZones[rPB.Pos].VPoints.resize (PRegion.VZones[rPB.Pos].VPoints.size()-1); + break; + } + } + + for (uint32 z = 0; z < _PRegions.size(); ++z) + if (_PRegions[z] == &PRegion) + { + _MustAskSaves[z] = true; + break; + } + + notify(); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::stackSelPB () +{ + map::iterator it = _Primitives.find (_ItemSelected); + if (it == _Primitives.end()) + return; + SPrimBuild &rPB = it->second; + CPrimRegion &PRegion = *rPB.PRegion; +} + +// --------------------------------------------------------------------------- +string CBuilderLogic::getZonesNameAt (CVector &v) +{ + string ret; + for (uint32 i = 0; i < _PRegions.size(); ++i) + { + for (uint32 j = 0; j < _PRegions[i]->VZones.size(); ++j) + { + CPrimZoneEditor *pz = &_PRegions[i]->VZones[j]; + + // Find if the patat is visible + bool bHidden = true; + map::iterator it = _Primitives.begin (); + while (it != _Primitives.end()) + { + if ((it->second.Type == 2) && ((sint32)j == it->second.Pos)) + { + if (it->second.hidden) + bHidden = true; + else + bHidden = false; + break; + } + ++it; + } + + if ((!bHidden) && (pz->contains(v))) + { + if (ret.size() == 0) + { + ret += pz->Name; + } + else + { + ret += ", " + pz->Name; + } + } + } + } + return ret; +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::selectZoneAt (NLMISC::CVector &v) +{ + vector zonelist; + uint32 i, j; + + for (i = 0; i < _PRegions.size(); ++i) + { + for (j = 0; j < _PRegions[i]->VZones.size(); ++j) + { + CPrimZoneEditor *pz = &_PRegions[i]->VZones[j]; + // Find if the patat is visible + bool bHidden = true; + map::iterator it = _Primitives.begin (); + while (it != _Primitives.end()) + { + if ((it->second.Type == 2) && ((sint32)j == it->second.Pos)) + { + if (it->second.hidden) + bHidden = true; + else + bHidden = false; + break; + } + ++it; + } + + if ((!bHidden) && (pz->contains(v))) + { + zonelist.push_back (pz->Name); + } + } + } + + if (zonelist.size() == 0) + return; + + string sSelPB = getSelPBName(); + for (i = 0; i < zonelist.size(); ++i) + { + if (zonelist[i] == sSelPB) + break; + } + + if (i == zonelist.size()) + i = 0; + else + i = (i+1)%zonelist.size(); + sSelPB = zonelist[i]; + + map::iterator it = _Primitives.begin (); + while (it != _Primitives.end()) + { + if (sSelPB == getName(it->first)) + { + setSelPB (it->first); + break; + } + ++it; + } +} + +// --------------------------------------------------------------------------- +CRGBA CBuilderLogic::findColor(const string &Name) // region-type-001 +{ + // Get the type from the name + string sType; + uint32 i = 0; + while (i < Name.size()) + { + if (Name[i]=='-') break; + ++i; + } + if (i == Name.size()) + return CRGBA (255, 255, 255, 255); + ++i; + while (i < Name.size()) + { + if (Name[i]=='-') break; + sType += Name[i]; + ++i; + } + if (i == Name.size()) + return CRGBA (255, 255, 255, 255); + + vector &rTypes = _Display->_MainFrame->_Environnement.Types; + for (i = 0; i < rTypes.size(); ++i) + if (sType == rTypes[i].Name) + return rTypes[i].Color; + + return CRGBA (255, 255, 255, 255); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::render (CVector &viewMin, CVector &viewMax) +{ + if (DontUse3D) + return; + // Accelerate rendering with vertex buffer + CVertexBuffer VB; + CPrimitiveBlock PB; + CVertexBuffer VBL; + CPrimitiveBlock PBL; + CMaterial Mat; + + CRGBA colSel = CRGBA(255, 0, 0, 192); + + Mat.initUnlit (); + Mat.setSrcBlend(CMaterial::srcalpha); + Mat.setDstBlend(CMaterial::invsrcalpha); + Mat.setBlend (true); + Mat.setColor (CRGBA(255, 255, 255, 192)); + VB.setVertexFormat (CVertexBuffer::PositionFlag|CVertexBuffer::PrimaryColorFlag); + VBL.setVertexFormat (CVertexBuffer::PositionFlag|CVertexBuffer::PrimaryColorFlag); + + // Parse the map + map::iterator it = _Primitives.begin(); + while (it != _Primitives.end()) + { + HTREEITEM curItem = it->first; + SPrimBuild &curPB = it->second; + CPrimRegion &PRegion = *curPB.PRegion; + + CRGBA col; + uint32 i; + + // If not created do not display or hidden + if ((!curPB.Created)||(curPB.hidden)) + { + ++it; + continue; + } + + CPrimVector *pVec = NULL; + uint32 nNbVec = 0; + + // Clip + + if (curPB.Type == 0) // Point + { + col = findColor (PRegion.VPoints[curPB.Pos].Name); + pVec = &PRegion.VPoints[curPB.Pos].Point; + nNbVec = 1; + } + + if (curPB.Type == 1) // Path + { + col = findColor (PRegion.VPaths[curPB.Pos].Name); + nNbVec = PRegion.VPaths[curPB.Pos].VPoints.size(); + if (nNbVec > 0) + pVec = &PRegion.VPaths[curPB.Pos].VPoints[0]; + } + + if (curPB.Type == 2) // Zone + { + col = findColor (PRegion.VZones[curPB.Pos].Name); + nNbVec = PRegion.VZones[curPB.Pos].VPoints.size(); + if (nNbVec > 0) + pVec = &PRegion.VZones[curPB.Pos].VPoints[0]; + } + + col.A = 192; + + if (nNbVec == 0) + { + ++it; + continue; + } + + if (clip(pVec, nNbVec, viewMin, viewMax)) + { + ++it; + continue; + } + + + // Draw all interiors + + if (curPB.Type == 2) // For Zones + { + vector vRef; + uint32 nStart, VBStart = VB.getNumVertices(), PBStart = PB.getNumTri(); + vRef.resize(nNbVec); + for(i = 0; i < vRef.size(); ++i) + vRef[i] = i; + + nStart = 0; + while (vRef.size() > 2) + { + // Is triangle (nStart, nStart+1, nStart+2) back face ? + sint32 nP1 = vRef[nStart]; + sint32 nP2 = vRef[(nStart+1)%vRef.size()]; + sint32 nP3 = vRef[(nStart+2)%vRef.size()]; + CVector pos1 = pVec[nP1]; + CVector pos2 = pVec[nP2]; + CVector pos3 = pVec[nP3]; + if (((pos2.x-pos1.x) * (pos3.y-pos1.y) - (pos2.y-pos1.y) * (pos3.x-pos1.x)) < 0.0f) + { + // Yes -> next triangle + nStart++; + //nlassert(nStart != vRef.size()); + if (nStart == vRef.size()) + { + VB.setNumVertices (VBStart); + PB.setNumTri(PBStart); + break; + } + continue; + } + // Is triangle (nStart, nStart+1, nStart+2) contains the other point ? + bool bInside = false; + for (i = 0; i < vRef.size(); ++i) + { + if ((vRef[i] != nP1) && (vRef[i] != nP2) && (vRef[i] != nP3)) + { + if (isInTriangleOrEdge( pVec[vRef[i]].x, pVec[vRef[i]].y, + pos1.x, pos1.y, + pos2.x, pos2.y, + pos3.x, pos3.y )) + { + bInside = true; + break; + } + } + } + if (bInside) + { + // Yes -> next triangle + nStart++; + //nlassert(nStart != vRef.size()); + if (nStart == vRef.size()) + { + VB.setNumVertices (VBStart); + PB.setNumTri(PBStart); + break; + } + continue; + } + + // Draw the triangle + convertToScreen (&pos1, 1, viewMin, viewMax); + convertToScreen (&pos2, 1, viewMin, viewMax); + convertToScreen (&pos3, 1, viewMin, viewMax); + if (curItem == _ItemSelected) + renderDrawTriangle(pos1, pos2, pos3, colSel, &VB, &PB); + else + renderDrawTriangle(pos1, pos2, pos3, col, &VB, &PB); + + // Erase the point in the middle + for (i = 1+((nStart+1)%vRef.size()); i < vRef.size(); ++i) + vRef[i-1] = vRef[i]; + vRef.resize (vRef.size()-1); + nStart = 0; + } + } + + // Draw all lines + + if ((curPB.Type == 1) || (curPB.Type == 2)) // For Pathes and Zones + { + uint32 nNbLineToDraw = (curPB.Type == 2)?(nNbVec):(nNbVec-1); + if ((nNbLineToDraw == 1)&&(curPB.Type == 2)) + nNbLineToDraw = 0; + for (i = 0; i < nNbLineToDraw; ++i) + { + CVector pos = pVec[i]; + CVector pos2 = pVec[(i+1)%(nNbVec)]; + + convertToScreen (&pos, 1, viewMin, viewMax); + convertToScreen (&pos2, 1, viewMin, viewMax); + if (curItem == _ItemSelected) + renderDrawLine (pos, pos2, colSel, &VBL, &PBL); + else + renderDrawLine (pos, pos2, col, &VBL, &PBL); + } + } + + // Draw all points + bool bDrawPoints = true; + + if (curPB.Type == 2) // Zone + if (curItem != _ItemSelected) + bDrawPoints = false; // Do not draw the points on zone other than selected one + + if (bDrawPoints) + for (i = 0; i < nNbVec; ++i) // For Points, Pathes and Zones + { + CVector pos = pVec[i]; + convertToScreen (&pos, 1, viewMin, viewMax); + if (curItem == _ItemSelected) + { + bool bFound = false; + for (uint32 k = 0; k < _VerticesSelected.size(); ++k) + if (_VerticesSelected[k] == (sint32)i) + { + bFound = true; + break; + } + if (bFound) + renderDrawPoint (pos, colSel, &VBL, &PBL); + else + renderDrawPoint (pos, col, &VBL, &PBL); + } + else + { + renderDrawPoint (pos, col, &VBL, &PBL); + } + } + + ++it; + } + + // Flush the Vertex Buffer + + CMatrix mtx; + mtx.identity(); + CNELU::Driver->setupViewport (CViewport()); + CNELU::Driver->setupViewMatrix (mtx); + CNELU::Driver->setupModelMatrix (mtx); + CNELU::Driver->setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false); + CNELU::Driver->activeVertexBuffer(VB); + CNELU::Driver->render(PB, Mat); + CNELU::Driver->activeVertexBuffer(VBL); + CNELU::Driver->render(PBL, Mat); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::renderDrawPoint (CVector &pos, CRGBA &col, CVertexBuffer *pVB, CPrimitiveBlock *pPB) +{ + if (DontUse3D) + return; + + if (pVB == NULL) + { + CDRU::drawLine (pos.x-0.01f, pos.y, pos.x+0.01f, pos.y, *CNELU::Driver, col); + CDRU::drawLine (pos.x, pos.y-0.01f, pos.x, pos.y+0.01f, *CNELU::Driver, col); + } + else + { + sint32 nVBPos = pVB->getNumVertices(); + pVB->setNumVertices (nVBPos+4); + pVB->setVertexCoord (nVBPos+0, pos.x-0.01f, pos.z, pos.y); + pVB->setVertexCoord (nVBPos+1, pos.x+0.01f, pos.z, pos.y); + pVB->setVertexCoord (nVBPos+2, pos.x, pos.z, pos.y-0.01f); + pVB->setVertexCoord (nVBPos+3, pos.x, pos.z, pos.y+0.01f); + pVB->setColor (nVBPos+0, col); + pVB->setColor (nVBPos+1, col); + pVB->setColor (nVBPos+2, col); + pVB->setColor (nVBPos+3, col); + sint32 nPBPos = pPB->getNumLine(); + pPB->setNumLine (nPBPos+2); + pPB->setLine (nPBPos+0, nVBPos+0, nVBPos+1); + pPB->setLine (nPBPos+1, nVBPos+2, nVBPos+3); + } +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::renderDrawLine (CVector &pos, CVector &pos2, CRGBA &col, CVertexBuffer *pVB, CPrimitiveBlock *pPB) +{ + sint32 nVBPos = pVB->getNumVertices(); + pVB->setNumVertices (nVBPos+2); + pVB->setVertexCoord (nVBPos+0, pos.x, pos.z, pos.y); + pVB->setVertexCoord (nVBPos+1, pos2.x, pos2.z, pos2.y); + pVB->setColor (nVBPos+0, col); + pVB->setColor (nVBPos+1, col); + sint32 nPBPos = pPB->getNumLine(); + pPB->setNumLine (nPBPos+1); + pPB->setLine (nPBPos+0, nVBPos+0, nVBPos+1); +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::renderDrawTriangle (CVector &pos, CVector &pos2, CVector &pos3, CRGBA &col, CVertexBuffer *pVB, CPrimitiveBlock *pPB) +{ + sint32 nVBPos = pVB->getNumVertices(); + pVB->setNumVertices (nVBPos+3); + pVB->setVertexCoord (nVBPos+0, pos.x, pos.z, pos.y); + pVB->setVertexCoord (nVBPos+1, pos2.x, pos2.z, pos2.y); + pVB->setVertexCoord (nVBPos+2, pos3.x, pos3.z, pos3.y); + pVB->setColor (nVBPos+0, col); + pVB->setColor (nVBPos+1, col); + pVB->setColor (nVBPos+2, col); + sint32 nPBPos = pPB->getNumTri(); + pPB->setNumTri (nPBPos+1); + pPB->setTri (nPBPos+0, nVBPos+0, nVBPos+1, nVBPos+2); +} + +// --------------------------------------------------------------------------- +bool CBuilderLogic::clip (CPrimVector *pVec, uint32 nNbVec, CVector &viewMin, CVector &viewMax) +{ + uint32 i; + for (i = 0; i < nNbVec; ++i) + if (pVec[i].x > viewMin.x) + break; + if (i == nNbVec) + return true; // Entirely clipped + + for (i = 0; i < nNbVec; ++i) + if (pVec[i].x < viewMax.x) + break; + if (i == nNbVec) + return true; + + for (i = 0; i < nNbVec; ++i) + if (pVec[i].y > viewMin.y) + break; + if (i == nNbVec) + return true; + + for (i = 0; i < nNbVec; ++i) + if (pVec[i].y < viewMax.y) + break; + if (i == nNbVec) + return true; + return false; // Not entirely clipped +} + +// --------------------------------------------------------------------------- +void CBuilderLogic::convertToScreen (CVector* pVec, sint nNbVec, CVector &viewMin, CVector &viewMax) +{ + for (sint i = 0; i < nNbVec; ++i) + { + pVec[i].x = (pVec[i].x-viewMin.x)/(viewMax.x-viewMin.x); + pVec[i].y = (pVec[i].y-viewMin.y)/(viewMax.y-viewMin.y); + pVec[i].z = 0.0f; + } +} + +// --------------------------------------------------------------------------- +bool CBuilderLogic::isInTriangleOrEdge( double x, double y, + double xt1, double yt1, + double xt2, double yt2, + double xt3, double yt3 ) +{ + // Test vector T1X and T1T2 + double sign1 = ((xt2-xt1)*(y-yt1) - (yt2-yt1)*(x-xt1)); + // Test vector T2X and T2T3 + double sign2 = ((xt3-xt2)*(y-yt2) - (yt3-yt2)*(x-xt2)); + // Test vector T3X and T3T1 + double sign3 = ((xt1-xt3)*(y-yt3) - (yt1-yt3)*(x-xt3)); + if( (sign1 <= 0.0)&&(sign2 <= 0.0)&&(sign3 <= 0.0) ) + return true; + if( (sign1 >= 0.0)&&(sign2 >= 0.0)&&(sign3 >= 0.0) ) + return true; + return false; +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_logic.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_logic.h index 5f95efd38..2272fb3d0 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_logic.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_logic.h @@ -1,138 +1,138 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// This class is interface between all that is displayed in -// display/tools view and the game core - -#ifndef BUILDERLOGIC_H -#define BUILDERLOGIC_H - -// *************************************************************************** - -#include - -// *************************************************************************** - -class CDisplay; -class CToolsLogic; - -namespace NL3D -{ - class CVertexBuffer; - class CPrimitiveBlock; -} - -// *************************************************************************** - -class CBuilderLogic -{ -public: - - /// Callback class for logic dependent object. - class ILogicCallback - { - public: - virtual void onLogicChanged(uint prim) =0; - }; - -private: - - std::vector _MustAskSaves; - sint32 _RegionSelected; - - // Selection - HTREEITEM _ItemSelected; - std::string _ItemSelectedName; - std::vector _VerticesSelected; - NLMISC::CRGBA _SelectionCol; - - CDisplay *_Display; - CToolsLogic *_ToolsLogic; - - ILogicCallback *_LogicCallback; - -public: - - CBuilderLogic(); - void setLogicCallback(ILogicCallback *logicCallback); - - void setDisplay (CDisplay *pDisp); - void setToolsLogic (CToolsLogic *pTool); - void uninit (); - void updateToolsLogic (); - void newZone (); - void move (const std::string &name, float x, float y); - - void insertPoint (uint32 nPos, HTREEITEM item, const char *Name, const char *LayerName); - void insertPath (uint32 nPos, HTREEITEM item, const char *Name, const char *LayerName); - void insertZone (uint32 nPos, HTREEITEM item, const char *Name, const char *LayerName); - void del (HTREEITEM item); - void primHide (HTREEITEM item); - void primUnhide (HTREEITEM item); - void hideAll (uint32 nPos, sint32 nID, bool bHide); - void regionSetName (uint32 nPos, HTREEITEM item, const std::string &sRegionName); - void regionCreateGroup (uint32 nPos, HTREEITEM item, const std::string &sGroupName); - void regionDeleteGroup (uint32 nPos, const std::string &sGroupName); - void regionHideAll (uint32 nPos, bool bHide); // (bHide == false) -> unhide - void regionHideType (uint32 nPos, const std::string &Type, bool bHide); // (bHide == false) -> unhide - int getMaxPostfix (const char *prefix); - bool isAlreadyExisting (const char *sPrimitiveName); - - const char* getName (HTREEITEM item); - const char* getLayerName (HTREEITEM item); - void getAllPrimZoneNames (std::vector &allNames); - bool isHidden (HTREEITEM item); - void setName (HTREEITEM item, const char *pStr); - void setLayerName (HTREEITEM item, const char *pStr); - - // Operation on Selected PrimBuild - HTREEITEM getSelPB (); - std::string getSelPBName (); - void setSelPB (HTREEITEM item); - void createVertexOnSelPB (NLMISC::CVector &v, sint32 atPos = -1); - bool selectVerticesOnSelPB (NLMISC::CVector &selMin, NLMISC::CVector &selMax); - void createIsoVertexOnSelVertexOnSelPB (); - bool isSelection(); - void setSelVerticesOnSelPB (NLMISC::CVector &v); - void delSelVerticesOnSelPB (); - void stackSelPB (); - - std::string getZonesNameAt (NLMISC::CVector &v); - void selectZoneAt (NLMISC::CVector &v); - - void render (NLMISC::CVector &viewMin, NLMISC::CVector &viewMax); - -private: - - void notify(); - - // Help for rendering - bool isInTriangleOrEdge( double x, double y, - double xt1, double yt1, - double xt2, double yt2, - double xt3, double yt3 ); - void convertToScreen (NLMISC::CVector* pVec, sint nNbVec, NLMISC::CVector &viewMin, NLMISC::CVector &viewMax); - bool clip (NLMISC::CPrimVector *pVec, uint32 nNbVec, NLMISC::CVector &viewMin, NLMISC::CVector &viewMax); - void renderDrawPoint (NLMISC::CVector &pos, NLMISC::CRGBA &col, NL3D::CVertexBuffer *pVB, NL3D::CPrimitiveBlock *pPB); - void renderDrawLine (NLMISC::CVector &pos, NLMISC::CVector &pos2, NLMISC::CRGBA &col, NL3D::CVertexBuffer *pVB, NL3D::CPrimitiveBlock *pPB); - void renderDrawTriangle (NLMISC::CVector &pos, NLMISC::CVector &pos2, NLMISC::CVector &pos3, NLMISC::CRGBA &col, NL3D::CVertexBuffer *pVB, NL3D::CPrimitiveBlock *pPB); - NLMISC::CRGBA findColor(const std::string &LayerName); - -}; - -// *************************************************************************** - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// This class is interface between all that is displayed in +// display/tools view and the game core + +#ifndef BUILDERLOGIC_H +#define BUILDERLOGIC_H + +// *************************************************************************** + +#include + +// *************************************************************************** + +class CDisplay; +class CToolsLogic; + +namespace NL3D +{ + class CVertexBuffer; + class CPrimitiveBlock; +} + +// *************************************************************************** + +class CBuilderLogic +{ +public: + + /// Callback class for logic dependent object. + class ILogicCallback + { + public: + virtual void onLogicChanged(uint prim) =0; + }; + +private: + + std::vector _MustAskSaves; + sint32 _RegionSelected; + + // Selection + HTREEITEM _ItemSelected; + std::string _ItemSelectedName; + std::vector _VerticesSelected; + NLMISC::CRGBA _SelectionCol; + + CDisplay *_Display; + CToolsLogic *_ToolsLogic; + + ILogicCallback *_LogicCallback; + +public: + + CBuilderLogic(); + void setLogicCallback(ILogicCallback *logicCallback); + + void setDisplay (CDisplay *pDisp); + void setToolsLogic (CToolsLogic *pTool); + void uninit (); + void updateToolsLogic (); + void newZone (); + void move (const std::string &name, float x, float y); + + void insertPoint (uint32 nPos, HTREEITEM item, const char *Name, const char *LayerName); + void insertPath (uint32 nPos, HTREEITEM item, const char *Name, const char *LayerName); + void insertZone (uint32 nPos, HTREEITEM item, const char *Name, const char *LayerName); + void del (HTREEITEM item); + void primHide (HTREEITEM item); + void primUnhide (HTREEITEM item); + void hideAll (uint32 nPos, sint32 nID, bool bHide); + void regionSetName (uint32 nPos, HTREEITEM item, const std::string &sRegionName); + void regionCreateGroup (uint32 nPos, HTREEITEM item, const std::string &sGroupName); + void regionDeleteGroup (uint32 nPos, const std::string &sGroupName); + void regionHideAll (uint32 nPos, bool bHide); // (bHide == false) -> unhide + void regionHideType (uint32 nPos, const std::string &Type, bool bHide); // (bHide == false) -> unhide + int getMaxPostfix (const char *prefix); + bool isAlreadyExisting (const char *sPrimitiveName); + + const char* getName (HTREEITEM item); + const char* getLayerName (HTREEITEM item); + void getAllPrimZoneNames (std::vector &allNames); + bool isHidden (HTREEITEM item); + void setName (HTREEITEM item, const char *pStr); + void setLayerName (HTREEITEM item, const char *pStr); + + // Operation on Selected PrimBuild + HTREEITEM getSelPB (); + std::string getSelPBName (); + void setSelPB (HTREEITEM item); + void createVertexOnSelPB (NLMISC::CVector &v, sint32 atPos = -1); + bool selectVerticesOnSelPB (NLMISC::CVector &selMin, NLMISC::CVector &selMax); + void createIsoVertexOnSelVertexOnSelPB (); + bool isSelection(); + void setSelVerticesOnSelPB (NLMISC::CVector &v); + void delSelVerticesOnSelPB (); + void stackSelPB (); + + std::string getZonesNameAt (NLMISC::CVector &v); + void selectZoneAt (NLMISC::CVector &v); + + void render (NLMISC::CVector &viewMin, NLMISC::CVector &viewMax); + +private: + + void notify(); + + // Help for rendering + bool isInTriangleOrEdge( double x, double y, + double xt1, double yt1, + double xt2, double yt2, + double xt3, double yt3 ); + void convertToScreen (NLMISC::CVector* pVec, sint nNbVec, NLMISC::CVector &viewMin, NLMISC::CVector &viewMax); + bool clip (NLMISC::CPrimVector *pVec, uint32 nNbVec, NLMISC::CVector &viewMin, NLMISC::CVector &viewMax); + void renderDrawPoint (NLMISC::CVector &pos, NLMISC::CRGBA &col, NL3D::CVertexBuffer *pVB, NL3D::CPrimitiveBlock *pPB); + void renderDrawLine (NLMISC::CVector &pos, NLMISC::CVector &pos2, NLMISC::CRGBA &col, NL3D::CVertexBuffer *pVB, NL3D::CPrimitiveBlock *pPB); + void renderDrawTriangle (NLMISC::CVector &pos, NLMISC::CVector &pos2, NLMISC::CVector &pos3, NLMISC::CRGBA &col, NL3D::CVertexBuffer *pVB, NL3D::CPrimitiveBlock *pPB); + NLMISC::CRGBA findColor(const std::string &LayerName); + +}; + +// *************************************************************************** + #endif // BUILDERLOGIC_H \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone.cpp index e6c27a1a7..99d8bb881 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone.cpp @@ -1,1751 +1,1751 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" -#include "nel/misc/object_vector.h" -#include "nel/misc/path.h" - -#include "world_editor.h" -#include "world_editor_doc.h" -#include "builder_zone.h" -#include "main_frm.h" -#include "display.h" -#include "tools_zone.h" - -extern bool DontUse3D; - -using namespace std; -using namespace NLLIGO; - -// Because we cant use the namespace NLMISC or NL3D in global due to some collision (CBitmap,...) -using NLMISC::CIFile; -using NLMISC::Exception; -using NLMISC::CVector; -using NLMISC::CUV; -using NLMISC::CMatrix; -using NLMISC::CSmartPtr; -using NLMISC::CIFile; -using NLMISC::COFile; - -using NL3D::ITexture; -using NL3D::CTextureMem; -using NL3D::CTextureFile; -using NL3D::CVertexBuffer; -using NL3D::CIndexBuffer; -using NL3D::CMaterial; -using NL3D::CViewport; -using NL3D::CNELU; -using NL3D::CVertexBufferReadWrite; -using NL3D::CIndexBufferReadWrite; - -// *************************************************************************** -// CDataBase::SCacheTexture -// *************************************************************************** - -// --------------------------------------------------------------------------- -CDataBase::SCacheTexture::SCacheTexture() -{ - Enabled = false; - Texture = NULL; -} - -// --------------------------------------------------------------------------- -bool CDataBase::SCacheTexture::isFull() -{ - if (!Enabled) - return false; - for (uint32 i = 0; i < FreePlace.size(); ++i) - if (FreePlace[i]) - return false; - return true; -} - -// *************************************************************************** -// CDataBase -// *************************************************************************** - -// --------------------------------------------------------------------------- -CDataBase::CDataBase (uint bitmapSize) -{ - _RefCacheTextureSizeX = _RefCacheTextureSizeY = 1024; // Size of the texture cache - _RefSizeX = _RefSizeY = bitmapSize; // Size of a zone in pixel - _RefCacheTextureNbEltX = _RefCacheTextureSizeX / _RefSizeX; - _RefCacheTextureNbEltY = _RefCacheTextureSizeY / _RefSizeY; - for (uint32 i = 0; i < 64; ++i) - _CacheTexture[i].Enabled = false; -} - -// --------------------------------------------------------------------------- -CDataBase::~CDataBase () -{ - reset (); -} - -// --------------------------------------------------------------------------- -void CDataBase::reset () -{ - for (uint32 i = 0; i < 64; ++i) - { - _CacheTexture[i].Enabled = false; - _CacheTexture[i].Texture = NULL; // Because its a smart ptr - _CacheTexture[i].PtrMem.resize (0); - _CacheTexture[i].FreePlace.resize(0); - } - - map::iterator it = _ZoneDBmap.begin (); - while (it != _ZoneDBmap.end()) - { - string sName = it->first; - SElement &rElt = it->second; - delete rElt.WinBitmap; - rElt.WinBitmap = NULL; - ++it; - } - _ZoneDBmap.clear (); - _UnusedTexture = NULL; -} - -// --------------------------------------------------------------------------- -bool CDataBase::initFromPath (const string &Path) -{ - return false; -} - -// --------------------------------------------------------------------------- -bool CDataBase::init (const string &Path, CZoneBank &zb) -{ - string sDirBackup = NLMISC::CPath::getCurrentPath(); - - // "Path" can be relative to the doc path so we have to be first in the doc path - string s2 = NLMISC::CFile::getPath ((LPCTSTR)getMainFrame()->getDocument()->GetPathName()); - NLMISC::CPath::setCurrentPath(s2.c_str()); - string ss = NLMISC::CPath::getFullPath(Path); - NLMISC::CPath::setCurrentPath (ss.c_str()); - - uint32 i, m, n, o, p; - uint8 k, l; - - vector ZoneNames; - zb.getCategoryValues ("zone", ZoneNames); - for (i = 0; i < ZoneNames.size(); ++i) - { - // Progress - getMainFrame ()->progressLoadingDialog ((float)i / (float)ZoneNames.size()); - - SElement zdbTmp; - CZoneBankElement *pZBE = zb.getElementByZoneName (ZoneNames[i]); - // Read the texture file - string zdbTmpName = ZoneNames[i]; - zdbTmp.SizeX = pZBE->getSizeX (); - zdbTmp.SizeY = pZBE->getSizeY (); - const vector &rMask = pZBE->getMask(); - - NLMISC::CBitmap *pBitmap = loadBitmap (getTextureFile(zdbTmpName)); - - // Should not return NULL ! - nlassert (pBitmap); - - // Wanted zone size - uint width = _RefSizeX * zdbTmp.SizeX; - uint height = _RefSizeY * zdbTmp.SizeY; - - // Good size ? - if ((pBitmap->getWidth () != width) || (pBitmap->getHeight () != height)) - { - // Resize it - pBitmap->resample (width, height); - } - - zdbTmp.WinBitmap = convertToWin (pBitmap); - pBitmap->flipV (); - - for (l = 0; l < zdbTmp.SizeY; ++l) - for (k = 0; k < zdbTmp.SizeX; ++k) - if (rMask[k+l*zdbTmp.SizeX]) - { - SCacheZone czTmp; - - czTmp.PosX = k; - czTmp.PosY = l; - - // Found first non full texture cache - for (m = 0; m < 64; ++m) - if (_CacheTexture[m].Enabled == false) - { - // Create the texture - _CacheTexture[m].FreePlace.resize (_RefCacheTextureNbEltX*_RefCacheTextureNbEltY, true); - _CacheTexture[m].Texture = new CTextureMem(); - _CacheTexture[m].Texture->setAllowDegradation (true); - _CacheTexture[m].PtrMem.resize (4*_RefCacheTextureSizeX*_RefCacheTextureSizeY); - _CacheTexture[m].Texture->resize (_RefCacheTextureSizeX, _RefCacheTextureSizeY); - _CacheTexture[m].Texture->setPointer (&_CacheTexture[m].PtrMem[0], 4*_RefCacheTextureSizeX*_RefCacheTextureSizeY, - false, false, _RefCacheTextureSizeX, _RefCacheTextureSizeY); - - _CacheTexture[m].Enabled = true; - break; - } - else - { - if (!_CacheTexture[m].isFull()) - break; - } - - nlassert (m<64); - - // Found first place in this texture - - for (n = 0; n < _CacheTexture[m].FreePlace.size(); ++n) - if (_CacheTexture[m].FreePlace[n]) - { - sint32 xSrc = k*_RefSizeX; - sint32 ySrc = l*_RefSizeY; - sint32 xDst = (n%_RefCacheTextureNbEltX)*_RefSizeX; - sint32 yDst = (n/_RefCacheTextureNbEltX)*_RefSizeY; - uint8 *pSrc = &pBitmap->getPixels()[(xSrc+ySrc*pBitmap->getWidth())*4]; - uint8 *pDst = &_CacheTexture[m].PtrMem[(xDst+yDst*_RefCacheTextureSizeX)*4]; - // Copy part of the bitmap into cache texture - for (p = 0; p < _RefSizeY; ++p) - for (o = 0; o < _RefSizeX; ++o) - { - pDst[(o+p*_RefCacheTextureSizeX)*4+0] = pSrc[(o+p*pBitmap->getWidth())*4+0]; - pDst[(o+p*_RefCacheTextureSizeX)*4+1] = pSrc[(o+p*pBitmap->getWidth())*4+1]; - pDst[(o+p*_RefCacheTextureSizeX)*4+2] = pSrc[(o+p*pBitmap->getWidth())*4+2]; - pDst[(o+p*_RefCacheTextureSizeX)*4+3] = pSrc[(o+p*pBitmap->getWidth())*4+3]; - } - czTmp.PosUV.U = ((float)xDst) / ((float)_RefCacheTextureSizeX); - czTmp.PosUV.V = ((float)yDst) / ((float)_RefCacheTextureSizeY); - czTmp.CacheTexture = _CacheTexture[m].Texture; - _CacheTexture[m].FreePlace[n] = false; - break; - } - //nlassert (m<_CacheTexture[m].FreePlace.size()); - zdbTmp.ZonePieces.push_back (czTmp); - } - // Add the entry in the DataBase - _ZoneDBmap.insert (pair(zdbTmpName, zdbTmp)); - delete pBitmap; - } - - // Upload all textures in VRAM - for (m = 0; m < 64; ++m) - if (_CacheTexture[m].Enabled) - _CacheTexture[m].Texture->touch (); - - _UnusedTexture = loadTexture (getTextureFile("_UNUSED_")); - - NLMISC::CPath::setCurrentPath(sDirBackup); - return true; -} - -// --------------------------------------------------------------------------- -CBitmap *CDataBase::getBitmap (const string &ZoneName) -{ - map::iterator it = _ZoneDBmap.find (ZoneName); - if (it != _ZoneDBmap.end()) - return (it->second.WinBitmap); - else - return NULL; -} - -// --------------------------------------------------------------------------- -ITexture* CDataBase::getTexture (const string &ZoneName, sint32 nPosX, sint32 nPosY, CUV &retUVmin, CUV &retUVmax) -{ - if (ZoneName == STRING_UNUSED) - { - retUVmin.U = 0.0f; - retUVmin.V = 1.0f - 0.0f; - retUVmax.U = 1.0f; - retUVmax.V = 1.0f - 1.0f; - return _UnusedTexture; - } - - map::iterator it = _ZoneDBmap.find (ZoneName); - if (it != _ZoneDBmap.end()) - { - SElement &rElt = it->second; - for (uint32 j = 0; j < rElt.ZonePieces.size(); ++j) - if ((rElt.ZonePieces[j].PosX == nPosX) && (rElt.ZonePieces[j].PosY == nPosY)) - { - retUVmin = rElt.ZonePieces[j].PosUV; - retUVmin.U += 0.5f / ((float)_RefCacheTextureSizeX); - retUVmin.V += 0.5f / ((float)_RefCacheTextureSizeY); - retUVmax = retUVmin; - retUVmax.U += ((float)_RefSizeX-1) / ((float)_RefCacheTextureSizeX); - retUVmax.V += ((float)_RefSizeY-1) / ((float)_RefCacheTextureSizeY); - return rElt.ZonePieces[j].CacheTexture; - } - } - - return NULL; -} - -// --------------------------------------------------------------------------- -// Private -// --------------------------------------------------------------------------- - -// --------------------------------------------------------------------------- -// Divisor to initialize windows bitmap -#define WIDTH_DIVISOR 2 -#define HEIGHT_DIVISOR 2 - -CBitmap *CDataBase::convertToWin (NLMISC::CBitmap *pBitmap) -{ - CBitmap *pWinBitmap = new CBitmap; - NLMISC::CObjectVector &rPixel = pBitmap->getPixels(); - uint32 nNewWidth = pBitmap->getWidth()/WIDTH_DIVISOR; - uint32 nNewHeight = pBitmap->getHeight()/HEIGHT_DIVISOR; - uint8 *pNewPixel = new uint8[nNewHeight*nNewWidth*4]; - uint32 i, j; - for (j = 0; j < nNewHeight; ++j) - for (i = 0; i < nNewWidth; ++i) - { - pNewPixel[(i+j*nNewWidth)*4+0] = rPixel[(i*WIDTH_DIVISOR+j*HEIGHT_DIVISOR*pBitmap->getWidth())*4+2]; - pNewPixel[(i+j*nNewWidth)*4+1] = rPixel[(i*WIDTH_DIVISOR+j*HEIGHT_DIVISOR*pBitmap->getWidth())*4+1]; - pNewPixel[(i+j*nNewWidth)*4+2] = rPixel[(i*WIDTH_DIVISOR+j*HEIGHT_DIVISOR*pBitmap->getWidth())*4+0]; - pNewPixel[(i+j*nNewWidth)*4+3] = rPixel[(i*WIDTH_DIVISOR+j*HEIGHT_DIVISOR*pBitmap->getWidth())*4+3]; - } - pWinBitmap->CreateBitmap (nNewWidth, nNewHeight, 1, 32, pNewPixel); - if (pNewPixel == NULL) - { - delete pWinBitmap; - return NULL; - } - else - return pWinBitmap; -} - -// --------------------------------------------------------------------------- -CTextureFile *CDataBase::loadTexture (const std::string &fileName) -{ - CTextureFile *pTexture = new CTextureFile; - pTexture->setFileName (fileName); - pTexture->setReleasable (false); - pTexture->generate (); - return pTexture; -} - -// --------------------------------------------------------------------------- -NLMISC::CBitmap *CDataBase::loadBitmap (const std::string &fileName) -{ - NLMISC::CBitmap *pBitmap = new NLMISC::CBitmap(); - - try - { - CIFile fileIn; - if (fileIn.open (fileName)) - { - pBitmap->load (fileIn); - } - else - { - pBitmap->makeDummy(); - nlwarning ("Bitmap not found : %s", fileName.c_str()); - } - } - catch (Exception& e) - { - pBitmap->makeDummy(); - theApp.errorMessage ("Error while loading bitmap %s : %s", fileName.c_str(), e.what()); - } - - return pBitmap; -} - -// *************************************************************************** -// CBuilderZone -// *************************************************************************** -// --------------------------------------------------------------------------- -// PRIVATE -// --------------------------------------------------------------------------- - -// --------------------------------------------------------------------------- -void CBuilderZone::calcMask() -{ - sint32 i; - sint32 x, y; - - _MinY = _MinX = 1000000; - _MaxY = _MaxX = -1000000; - - if (_ZoneRegions.size() == 0) - return; - - CWorldEditorDoc *doc = getDocument (); - - for (i = 0; i < (sint32)_ZoneRegions.size(); ++i) - { - const CZoneRegion *pBZR = &(doc->getZoneRegion (i)); - - if (_MinX > pBZR->getMinX()) - _MinX = pBZR->getMinX(); - if (_MinY > pBZR->getMinY()) - _MinY = pBZR->getMinY(); - if (_MaxX < pBZR->getMaxX()) - _MaxX = pBZR->getMaxX(); - if (_MaxY < pBZR->getMaxY()) - _MaxY = pBZR->getMaxY(); - } - - _ZoneMask.resize ((1+_MaxX-_MinX)*(1+_MaxY-_MinY)); - sint32 stride = (1+_MaxX-_MinX); - for (y = _MinY; y <= _MaxY; ++y) - for (x = _MinX; x <= _MaxX; ++x) - { - _ZoneMask[x-_MinX+(y-_MinY)*stride] = true; - - for (i = 0; i < (sint32)_ZoneRegions.size(); ++i) - if (i != _ZoneRegionSelected) - { - const CZoneRegion *pBZR = &(doc->getZoneRegion (i)); - - const string &rSZone = pBZR->getName (x, y); - if ((rSZone != STRING_OUT_OF_BOUND) && (rSZone != STRING_UNUSED)) - { - _ZoneMask[x-_MinX+(y-_MinY)*stride] = false; - } - } - } -} - -// --------------------------------------------------------------------------- -// PUBLIC -// --------------------------------------------------------------------------- - -// --------------------------------------------------------------------------- -CBuilderZone::CBuilderZone (uint bitmapSize) : _DataBase (bitmapSize) -{ - // Set Current Filter - _FilterType1 = STRING_UNUSED; _FilterValue1 = ""; - _FilterType2 = STRING_UNUSED; _FilterValue2 = ""; - _FilterType3 = STRING_UNUSED; _FilterValue3 = ""; - _FilterType4 = STRING_UNUSED; _FilterValue4 = ""; - _FilterOperator2 = 0; - _FilterOperator3 = 0; - _FilterOperator4 = 0; - _RandomSelection = false; - _CurSelectedZone = -1; - _ZoneRegionSelected = -1; - _ApplyRot = 0; - _ApplyRotType = 0; - _ApplyFlip = 0; - _ApplyFlipType = 0; - - _Display = NULL; - _ApplyRotCycle = 0; - _ApplyFlipCycle = 0; - _CycleSelection = false; - _ApplyCycleSelection = 0; - _NotPropagate = false; - _Force = false; - _LastPathName = ""; - _ToolsZone = NULL; -} - -// --------------------------------------------------------------------------- -bool CBuilderZone::init (const string &sPathName, bool makeAZone, CDisplay *display) -{ - // Set the display - _Display = display; - - bool bRet = true; - if (sPathName != _LastPathName) - { - _LastPathName = sPathName; - string sZoneBankPath = sPathName; - sZoneBankPath += "\\zoneligos\\"; - // Init the ZoneBank - _ZoneBank.reset (); - if (!initZoneBank (sZoneBankPath)) - { - _ZoneBank.reset (); - return false; - } - - // Construct the DataBase from the ZoneBank - string sZoneBitmapPath = sPathName; - sZoneBitmapPath += "\\zonebitmaps\\"; - _DataBase.reset (); - if (!_DataBase.init (sZoneBitmapPath.c_str(), _ZoneBank)) - { - _DataBase.reset (); - _ZoneBank.reset (); - return false; - } - } - - if ((makeAZone) && (bRet)) - newZone(); - - return bRet; -} - -// --------------------------------------------------------------------------- -void CBuilderZone::setToolsZone (CToolsZone *pTool) -{ - _ToolsZone = pTool; -} - -// --------------------------------------------------------------------------- -void CBuilderZone::updateToolsZone () -{ - uint32 i; - - if (_ToolsZone == NULL) - return; - - // Execute the filter - _ZoneBank.resetSelection (); - if(_FilterType1 != STRING_UNUSED) - _ZoneBank.addOrSwitch (_FilterType1, _FilterValue1); - - if(_FilterType2 != STRING_UNUSED) - { - if (_FilterOperator2 == 0) // AND switch wanted - _ZoneBank.addAndSwitch (_FilterType2, _FilterValue2); - else // OR switch wanted - _ZoneBank.addOrSwitch (_FilterType2, _FilterValue2); - } - - if(_FilterType3 != STRING_UNUSED) - { - if (_FilterOperator3 == 0) // AND switch wanted - _ZoneBank.addAndSwitch (_FilterType3, _FilterValue3); - else // OR switch wanted - _ZoneBank.addOrSwitch (_FilterType3, _FilterValue3); - } - - if(_FilterType4 != STRING_UNUSED) - { - if (_FilterOperator4 == 0) // AND switch wanted - _ZoneBank.addAndSwitch (_FilterType4, _FilterValue4); - else // OR switch wanted - _ZoneBank.addOrSwitch (_FilterType4, _FilterValue4); - } - - _ZoneBank.getSelection (_CurrentSelection); - - // Create the corresponding image list from selected item using DataBase - - vector vIL; - vIL.resize (_CurrentSelection.size()); - for (i = 0; i < _CurrentSelection.size(); ++i) - { - CZoneBankElement *pElt = _CurrentSelection[i]; - // Get bitmap from DataBase - vIL[i] = _DataBase.getBitmap (pElt->getName()); - } - - // Construct the tree add first items then the images! - _ToolsZone->getListCtrl()->reset (); - for (i = 0; i < _CurrentSelection.size(); ++i) - { - CZoneBankElement *pElt = _CurrentSelection[i]; - _ToolsZone->getListCtrl()->addItem (pElt->getName()); - } - _ToolsZone->getListCtrl()->setImages (vIL); - if (_CurrentSelection.size() > 0) - { - _ToolsZone->getListCtrl()->SetCurSel (0); - _CurSelectedZone = 0; - } - else - _CurSelectedZone = -1; - _ApplyCycleSelection = 0; - - - _ToolsZone->Invalidate(); - _ToolsZone->UpdateWindow(); -} - -// --------------------------------------------------------------------------- -bool CBuilderZone::refresh () -{ - // Reset all - _ZoneRegions.clear (); - _ZoneRegionSelected = -1; - - CWorldEditorDoc *doc = getDocument (); - for (uint j=0; jgetNumDatabaseElement (); j++) - { - // Is it a landscape ? - if (doc->isLandscape (j)) - { - _ZoneRegionSelected++; - - newZone (false); - - // Check if we can load this zone - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (_ZoneRegionSelected)); - for (sint32 y = pBZR->getMinY(); y <= pBZR->getMaxY(); ++y) - for (sint32 x = pBZR->getMinX(); x <= pBZR->getMaxX(); ++x) - { - const string &refSZone = pBZR->getName (x, y); - if (refSZone != STRING_UNUSED) - { - sint zoneRegionSelected2 = -1; - CWorldEditorDoc *doc = getDocument (); - for (uint i=0; igetNumDatabaseElement (); i++) - { - // Is it a landscape ? - if (doc->isLandscape (i)) - { - zoneRegionSelected2++; - if (i!=j) - { - const CZoneRegion *pBZR2 = &(getDocument ()->getZoneRegion (zoneRegionSelected2)); - const string &sZone = pBZR2->getName (x, y); - if ((sZone != STRING_UNUSED)&&(sZone != STRING_OUT_OF_BOUND)) - { - unload (_ZoneRegionSelected); - MessageBox (NULL, "Cannot add this zone because it overlaps existing ones", - "Error", MB_ICONERROR|MB_OK); - return false; - } - } - } - } - } - } - - string error; - if (!_ZoneRegions[_ZoneRegionSelected]->init (&_ZoneBank, this, error)) - { - unload (_ZoneRegionSelected); - MessageBox (NULL, ("Cannot add this zone :\n"+error).c_str(), - "Error", MB_ICONERROR|MB_OK); - return false; - } - - _Display->_Offset.x = _Display->_CellSize*(pBZR->getMinX() + - pBZR->getMaxX()) / 2.0f; - _Display->_Offset.y = _Display->_CellSize*(pBZR->getMinY() + - pBZR->getMaxY()) / 2.0f; - calcMask (); - } - } - return true; -} - -// --------------------------------------------------------------------------- - -void CBuilderZone::newZone (bool bDisplay) -{ - _ZoneRegions.push_back (new CBuilderZoneRegion (_ZoneRegions.size())); - _ZoneRegionSelected = _ZoneRegions.size() - 1; - // Select starting point for the moment 0,0 - sint32 i; - sint32 x = 0, y = 0; - // If there are some zone already present increase x until free - for (i = 0; i < (sint32)_ZoneRegions.size(); ++i) - { - if (getDocument ()->isLandscape (i)) - { - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (i)); - const string &rsZone = pBZR->getName (x, y); - if ((rsZone != STRING_OUT_OF_BOUND) && (rsZone != STRING_UNUSED)) - { - ++x; i = -1; - } - } - } - // _ZoneRegions[_ZoneRegionSelected]->setStart (x,y); - calcMask (); -} - -// --------------------------------------------------------------------------- -void CBuilderZone::unload (uint32 pos) -{ - uint32 i = 0; - if (_ZoneRegions.size() == 0) - return; - - delete _ZoneRegions[pos]; - for (i = pos; i < (_ZoneRegions.size()-1); ++i) - { - _ZoneRegions[i] = _ZoneRegions[i+1]; - } - _ZoneRegions.resize (_ZoneRegions.size()-1); - if (_ZoneRegionSelected == (sint32)_ZoneRegions.size()) - _ZoneRegionSelected = _ZoneRegions.size()-1; - calcMask (); -} - -// --------------------------------------------------------------------------- -void CBuilderZone::move (sint32 x, sint32 y) -{ - if (_ZoneRegions.size() == 0) - return; - _ZoneRegions[_ZoneRegionSelected]->move(x, y); -} - -// --------------------------------------------------------------------------- -uint32 CBuilderZone::countZones () -{ - if (_ZoneRegions.size() == 0) - return 0; - return _ZoneRegions[_ZoneRegionSelected]->countZones (); -} - -// --------------------------------------------------------------------------- -void CBuilderZone::snapshot (const char *fileName, uint sizeSource, bool grayscale) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (_ZoneRegionSelected)); - sint32 nMinX = pBZR->getMinX(); - sint32 nMaxX = pBZR->getMaxX(); - sint32 nMinY = pBZR->getMinY(); - sint32 nMaxY = pBZR->getMaxY(); - - uint width = (nMaxX - nMinX + 1)*sizeSource; - uint height = (nMaxY - nMinY + 1)*sizeSource; - snapshotCustom (fileName, width, height, false, sizeSource, grayscale); -} - -// --------------------------------------------------------------------------- -void CBuilderZone::snapshotCustom (const char *fileName, uint width, uint height, bool keepRatio, uint sizeSource, bool grayscale) -{ - if (_ZoneRegions.size() == 0) - return; - - // Some bitmaps - NLMISC::CBitmap bitmapTmp; - NLMISC::CBitmap bitmapDest; - - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (_ZoneRegionSelected)); - sint32 nMinX = pBZR->getMinX(); - sint32 nMaxX = pBZR->getMaxX(); - sint32 nMinY = pBZR->getMinY(); - sint32 nMaxY = pBZR->getMaxY(); - - uint nSizeX = (nMaxX - nMinX + 1)*sizeSource; - uint nSizeY = (nMaxY - nMinY + 1)*sizeSource; - sint x, y, j; - - // Keep ratio ? - if (keepRatio) - height = (width * nSizeY) / nSizeX; - - // Resize the bitmaps - bitmapDest.resize (nSizeX, nSizeY, NLMISC::CBitmap::RGBA); - - // white all - NLMISC::CObjectVector &rPixels = bitmapDest.getPixels(); - memset (&rPixels[0], 0xff, rPixels.size ()); - - // Copy ZoneBitmaps in the bitmap - CUV uvMin, uvMax; - ITexture *pTexture; - CZoneBankElement *pZBE; - uint8 nRot, nFlip; - - // For each tiles - for (y = nMinY; y <= nMaxY; ++y) - for (x = nMinX; x <= nMaxX; ++x) - { - const string &rsZoneName = pBZR->getName (x, y); - if ((rsZoneName == STRING_OUT_OF_BOUND) && (rsZoneName == STRING_UNUSED)) - continue; - - pZBE = _ZoneBank.getElementByZoneName (rsZoneName); - if (pZBE == NULL) - continue; - - // Get the texture - pTexture = _DataBase.getTexture (rsZoneName, pBZR->getPosX(x, y), - pBZR->getPosY(x, y), uvMin, uvMax); - - // Generate it - pTexture->generate (); - - // Be sure it is tga - pTexture->convertToType (NLMISC::CBitmap::RGBA); - - // Get rot - nRot = pBZR->getRot(x, y); - - // Get flip - nFlip = pBZR->getFlip(x, y); - - // Copy the texture - - // Dest bitmap size - uint destWidth = 1+(uint)((float)pTexture->getWidth() * (uvMax.U - uvMin.U)); - uint destHeight = 1+(uint)((float)pTexture->getHeight() * (uvMax.V - uvMin.V)); - bitmapTmp.resize (destWidth, destHeight, NLMISC::CBitmap::RGBA); - - // Source bitmap size and position - uint u = (uint)((float)pTexture->getWidth() * uvMin.U); - uint v = (uint)((float)pTexture->getHeight() * uvMin.V); - uint sourceWidth = pTexture->getWidth(); - uint sourceHeight = pTexture->getHeight(); - - // Source pointer - uint8 *srcPixels = &(pTexture->getPixels ()[0]); - - // Destination pointer - uint8 *destPixels = &(bitmapTmp.getPixels ()[0]); - - // Copy the temp bitmap - for (j = 0; j < (sint)destHeight; ++j) - // Copy the line - memcpy (destPixels+(4*j*destWidth), srcPixels + 4 * ( (v + j) * sourceWidth + u), destWidth*4); - - // Flip ? - if (nFlip) - bitmapTmp.flipH(); - - // Rot ? - while (nRot) - { - bitmapTmp.rot90CW (); - nRot--; - } - - // Resize the bitmap to normal size - if ( (bitmapTmp.getWidth () != sizeSource) || (bitmapTmp.getHeight () != sizeSource) ) - bitmapTmp.resample (sizeSource, sizeSource); - - // Copy it in the map - bitmapDest.blit (&bitmapTmp, (x-nMinX)*sizeSource, (y-nMinY)*sizeSource); - - pTexture->release (); - } - - // Resample the final bitmap - bitmapDest.resample (width, height); - bitmapDest.flipV (); - - COFile f(fileName, false, false, true); - - if (grayscale) - { - bitmapDest.convertToType (NLMISC::CBitmap::Luminance); - if (bitmapDest.writeTGA (f, 8)) - f.close(); - } - else - { - if (bitmapDest.writeTGA (f, 32)) - f.close(); - } -} - -// --------------------------------------------------------------------------- -CBuilderZone::SCacheRender::SCacheRender () -{ - Used = false; - Mat.initUnlit (); - Mat.setBlend (false); - VB.setVertexFormat (CVertexBuffer::PositionFlag|CVertexBuffer::TexCoord0Flag|CVertexBuffer::PrimaryColorFlag); -} - -// --------------------------------------------------------------------------- -void CBuilderZone::render (const NLMISC::CVector &viewMin, const NLMISC::CVector &viewMax) -{ - sint32 i, zoneSelected; - - DWORD backgroundColor = GetSysColor (COLOR_WINDOW); - - // Reset the cache - for (i = 0; i < (CACHE_RENDER_SIZE); ++i) - { - _CacheRender[i].VB.setNumVertices (0); - _CacheRender[i].PB.setNumIndexes (0); - _CacheRender[i].Used = false; - } - - // Select all blocks visible - float minx = floorf(viewMin.x/_Display->_CellSize)*_Display->_CellSize; - float miny = floorf(viewMin.y/_Display->_CellSize)*_Display->_CellSize; - float maxx = ceilf(viewMax.x/_Display->_CellSize)*_Display->_CellSize; - float maxy = ceilf(viewMax.y/_Display->_CellSize)*_Display->_CellSize; - CVector pos1, pos2, pos3, pos4; - CUV uvMin, uvMax; - sint32 x, y; - ITexture *pTexture; - - while (minx < maxx) - { - miny = floorf(viewMin.y/_Display->_CellSize)*_Display->_CellSize; - while (miny < maxy) - { - x = (sint32)floor(minx / _Display->_CellSize); - y = (sint32)floor(miny / _Display->_CellSize); - - i = 0; - string sZone = STRING_OUT_OF_BOUND; - zoneSelected = 0; - for (i = 0; i < (sint32)_ZoneRegions.size(); ++i) - { - const string &rSZone = getDocument ()->getZoneRegion (i).getName (x, y); - if ((sZone == STRING_OUT_OF_BOUND) && (rSZone == STRING_UNUSED)) - { - sZone = STRING_UNUSED; - zoneSelected = i; - } - if ((rSZone != STRING_OUT_OF_BOUND) && (rSZone != STRING_UNUSED)) - { - sZone = rSZone; - zoneSelected = i; - } - } - CZoneBankElement *pZBE = _ZoneBank.getElementByZoneName (sZone); - - if (pZBE == NULL) - pTexture = _DataBase.getTexture (sZone, 0, 0, uvMin, uvMax); - else - pTexture = _DataBase.getTexture (sZone, getDocument ()->getZoneRegion (zoneSelected).getPosX(x, y), - getDocument ()->getZoneRegion (zoneSelected).getPosY(x, y), uvMin, uvMax); - - // Look if already existing texture exists in the cache - for (i = 0; i < (CACHE_RENDER_SIZE); ++i) - if (_CacheRender[i].Used) - if (_CacheRender[i].Mat.getTexture(0) == pTexture) - break; - - if (i == (CACHE_RENDER_SIZE)) - { - // Use a new CacheRender slot - for (i = 0; i < (CACHE_RENDER_SIZE); ++i) - if (!_CacheRender[i].Used) - break; - nlassert(i<(CACHE_RENDER_SIZE)); - _CacheRender[i].Used = true; - _CacheRender[i].Mat.setTexture (0, pTexture); - } - - pos1.x = (minx-viewMin.x)/(viewMax.x-viewMin.x); - pos1.y = 0.0f; - pos1.z = (miny-viewMin.y)/(viewMax.y-viewMin.y); - - pos2.x = (_Display->_CellSize+minx-viewMin.x)/(viewMax.x-viewMin.x); - pos2.y = 0.0f; - pos2.z = (miny-viewMin.y)/(viewMax.y-viewMin.y); - - pos3.x = (_Display->_CellSize+minx-viewMin.x)/(viewMax.x-viewMin.x); - pos3.y = 0.0f; - pos3.z = (_Display->_CellSize+miny-viewMin.y)/(viewMax.y-viewMin.y); - - pos4.x = (minx-viewMin.x)/(viewMax.x-viewMin.x); - pos4.y = 0.0f; - pos4.z = (_Display->_CellSize+miny-viewMin.y)/(viewMax.y-viewMin.y); - - uint32 nBasePt = _CacheRender[i].VB.getNumVertices(); - _CacheRender[i].VB.setNumVertices (nBasePt+4); - CVertexBufferReadWrite vba; - _CacheRender[i].VB.lock (vba); - vba.setVertexCoord (nBasePt+0, pos1); - vba.setVertexCoord (nBasePt+1, pos2); - vba.setVertexCoord (nBasePt+2, pos3); - vba.setVertexCoord (nBasePt+3, pos4); - - - uint32 nBaseTri = _CacheRender[i].PB.getNumIndexes (); - _CacheRender[i].PB.setNumIndexes (nBaseTri+6); - CIndexBufferReadWrite iba; - _CacheRender[i].PB.lock (iba); - iba.setTri (nBaseTri+0, nBasePt+0, nBasePt+1, nBasePt+2); - iba.setTri (nBaseTri+3, nBasePt+0, nBasePt+2, nBasePt+3); - - if ((zoneSelected>=0)&&(zoneSelected<(sint32)_ZoneRegions.size())) - { - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (zoneSelected)); - if (pBZR->getFlip (x, y) == 1) - { - float rTmp = uvMin.U; - uvMin.U = uvMax.U; - uvMax.U = rTmp; - } - - vba.setTexCoord (nBasePt+(pBZR->getRot (x, y)+0)%4, 0, CUV(uvMin.U, uvMin.V)); - vba.setTexCoord (nBasePt+(pBZR->getRot (x, y)+1)%4, 0, CUV(uvMax.U, uvMin.V)); - vba.setTexCoord (nBasePt+(pBZR->getRot (x, y)+2)%4, 0, CUV(uvMax.U, uvMax.V)); - vba.setTexCoord (nBasePt+(pBZR->getRot (x, y)+3)%4, 0, CUV(uvMin.U, uvMax.V)); - } - else - { - vba.setTexCoord (nBasePt+0, 0, CUV(uvMin.U, uvMin.V)); - vba.setTexCoord (nBasePt+1, 0, CUV(uvMax.U, uvMin.V)); - vba.setTexCoord (nBasePt+2, 0, CUV(uvMax.U, uvMax.V)); - vba.setTexCoord (nBasePt+3, 0, CUV(uvMin.U, uvMax.V)); - } - - NLMISC::CRGBA color; - - if ((zoneSelected>=0)&&(zoneSelected<(sint32)_ZoneRegions.size())) - { - if (getZoneMask(x,y)) - color = NLMISC::CRGBA(255, 255, 255, 255); - else - color = NLMISC::CRGBA(127, 127, 127, 255); - } - else - color = NLMISC::CRGBA(255, 255, 255, 255); - - if (pTexture == NULL) - color = _Display->_BackgroundColor; - - vba.setColor (nBasePt+0, color); - vba.setColor (nBasePt+1, color); - vba.setColor (nBasePt+2, color); - vba.setColor (nBasePt+3, color); - - miny += _Display->_CellSize; - } - minx += _Display->_CellSize; - } - - //MessageBox(NULL, "CBuilderZone::render", "3", MB_OK); - - if (DontUse3D) - return; - - // Flush the cache to the screen - CMatrix mtx; - mtx.identity(); - CNELU::Driver->setupViewport (CViewport()); - CNELU::Driver->setupViewMatrix (mtx); - CNELU::Driver->setupModelMatrix (mtx); - CNELU::Driver->setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false); - - //MessageBox(NULL, "CBuilderZone::render", "4", MB_OK); - - for (i = 0; i < (CACHE_RENDER_SIZE); ++i) - if (_CacheRender[i].Used) - { - // Render with driver - CNELU::Driver->activeVertexBuffer (_CacheRender[i].VB); - CNELU::Driver->activeIndexBuffer (_CacheRender[i].PB); - CNELU::Driver->renderTriangles (_CacheRender[i].Mat, 0, _CacheRender[i].PB.getNumIndexes()/3); - } -} - -// --------------------------------------------------------------------------- -void CBuilderZone::renderTransition (const NLMISC::CVector &viewMin, const NLMISC::CVector &viewMax) -{ - // Selected ? - if (_ZoneRegionSelected != -1) - { - // Select all blocks visible - float rMinX = floorf (viewMin.x / _Display->_CellSize)*_Display->_CellSize; - float rMinY = floorf (viewMin.y / _Display->_CellSize)*_Display->_CellSize; - float rMaxX = ceilf (viewMax.x / _Display->_CellSize)*_Display->_CellSize; - float rMaxY = ceilf (viewMax.y / _Display->_CellSize)*_Display->_CellSize; - - sint32 nMinX = (sint32)floor (rMinX / _Display->_CellSize); - sint32 nMinY = (sint32)floor (rMinY / _Display->_CellSize); - sint32 nMaxX = (sint32)floor (rMaxX / _Display->_CellSize); - sint32 nMaxY = (sint32)floor (rMaxY / _Display->_CellSize); - - CVertexBuffer VB , VBSel; - CIndexBuffer PB, PBSel; - CMaterial Mat, MatSel; - - Mat.initUnlit (); - Mat.setBlend (false); - MatSel.initUnlit (); - MatSel.setBlend (false); - MatSel.setColor(NLMISC::CRGBA(255,0,0,0)); - VB.setVertexFormat (CVertexBuffer::PositionFlag); - VB.reserve ((nMaxX-nMinX+1)*(nMaxY-nMinY+1)*4*2); - VBSel.setVertexFormat (CVertexBuffer::PositionFlag); - VBSel.reserve ((nMaxX-nMinX+1)*(nMaxY-nMinY+1)*4*2); - - CVertexBufferReadWrite vba; - VB.lock (vba); - CVertexBufferReadWrite vbaSel; - VBSel.lock (vbaSel); - - sint32 nVertCount = 0; - sint32 nVertCountSel = 0; - sint32 x, y, k; - CVector worldPos, screenPos; - for (y = nMinY; y <= nMaxY; ++y) - for (x = nMinX; x <= nMaxX; ++x) - { - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (_ZoneRegionSelected)); - uint8 ceUp = pBZR->getCutEdge (x, y, 0); - uint8 ceLeft = pBZR->getCutEdge (x, y, 2); - - if ((ceUp > 0) && (ceUp < 3)) - for (k = 0; k < 2; ++k) - { - if (ceUp == 1) - worldPos.x = x * _Display->_CellSize + 3.0f * _Display->_CellSize / 12.0f; - else - worldPos.x = x * _Display->_CellSize + 7.0f * _Display->_CellSize / 12.0f; - worldPos.y = (y+1)*_Display->_CellSize + _Display->_CellSize / 12.0f; - worldPos.z = 0; - // World -> Screen conversion - screenPos.x = (worldPos.x - viewMin.x) / (viewMax.x - viewMin.x); - screenPos.y = 0.0f; - screenPos.z = (worldPos.y - viewMin.y) / (viewMax.y - viewMin.y); - if (k == 0) - { - vba.setVertexCoord (nVertCount, screenPos); - ++nVertCount; - } - else - { - vbaSel.setVertexCoord (nVertCountSel, screenPos); - ++nVertCountSel; - } - - worldPos.y = (y+1)*_Display->_CellSize - _Display->_CellSize / 12.0f; - screenPos.z = (worldPos.y - viewMin.y) / (viewMax.y - viewMin.y); - if (k == 0) - { - vba.setVertexCoord (nVertCount, screenPos); - ++nVertCount; - } - else - { - vbaSel.setVertexCoord (nVertCountSel, screenPos); - ++nVertCountSel; - } - - if (ceUp == 1) - worldPos.x = x * _Display->_CellSize + 5.0f * _Display->_CellSize / 12.0f; - else - worldPos.x = x * _Display->_CellSize + 9.0f * _Display->_CellSize / 12.0f; - screenPos.x = (worldPos.x - viewMin.x) / (viewMax.x - viewMin.x); - if (k == 0) - { - vba.setVertexCoord (nVertCount, screenPos); - ++nVertCount; - } - else - { - vbaSel.setVertexCoord (nVertCountSel, screenPos); - ++nVertCountSel; - } - - worldPos.y = (y+1)*_Display->_CellSize + _Display->_CellSize / 12.0f; - screenPos.z = (worldPos.y - viewMin.y) / (viewMax.y - viewMin.y); - if (k == 0) - { - vba.setVertexCoord (nVertCount, screenPos); - ++nVertCount; - } - else - { - vbaSel.setVertexCoord (nVertCountSel, screenPos); - ++nVertCountSel; - } - ceUp = 3 - ceUp; - } - - if ((ceLeft > 0) && (ceLeft < 3)) - for (k = 0; k < 2; ++k) - { - worldPos.x = x * _Display->_CellSize - _Display->_CellSize / 12.0f; - if (ceLeft == 1) - worldPos.y = y * _Display->_CellSize + 3.0f * _Display->_CellSize / 12.0f; - else - worldPos.y = y * _Display->_CellSize + 7.0f * _Display->_CellSize / 12.0f; - worldPos.z = 0; - // World -> Screen conversion - screenPos.x = (worldPos.x - viewMin.x) / (viewMax.x - viewMin.x); - screenPos.y = 0.0f; - screenPos.z = (worldPos.y - viewMin.y) / (viewMax.y - viewMin.y); - if (k == 0) - { - vba.setVertexCoord (nVertCount, screenPos); - ++nVertCount; - } - else - { - vbaSel.setVertexCoord (nVertCountSel, screenPos); - ++nVertCountSel; - } - - worldPos.x = x * _Display->_CellSize + _Display->_CellSize / 12.0f; - screenPos.x = (worldPos.x - viewMin.x) / (viewMax.x - viewMin.x); - if (k == 0) - { - vba.setVertexCoord (nVertCount, screenPos); - ++nVertCount; - } - else - { - vbaSel.setVertexCoord (nVertCountSel, screenPos); - ++nVertCountSel; - } - - if (ceLeft == 1) - worldPos.y = y * _Display->_CellSize + 5.0f * _Display->_CellSize / 12.0f; - else - worldPos.y = y * _Display->_CellSize + 9.0f * _Display->_CellSize / 12.0f; - screenPos.z = (worldPos.y - viewMin.y) / (viewMax.y - viewMin.y); - if (k == 0) - { - vba.setVertexCoord (nVertCount, screenPos); - ++nVertCount; - } - else - { - vbaSel.setVertexCoord (nVertCountSel, screenPos); - ++nVertCountSel; - } - - worldPos.x = x * _Display->_CellSize - _Display->_CellSize / 12.0f; - screenPos.x = (worldPos.x - viewMin.x) / (viewMax.x - viewMin.x); - if (k == 0) - { - vba.setVertexCoord (nVertCount, screenPos); - ++nVertCount; - } - else - { - vbaSel.setVertexCoord (nVertCountSel, screenPos); - ++nVertCountSel; - } - ceLeft = 3 - ceLeft; - } - } - - vba.unlock(); - VB.setNumVertices (nVertCount); - PB.setNumIndexes (nVertCount*2); - CIndexBufferReadWrite iba; - PB.lock (iba); - for (x = 0; x < (nVertCount/4); ++x) - { - iba.setLine (x*4+0, x*4+0, x*4+1); - iba.setLine (x*4+1, x*4+1, x*4+2); - iba.setLine (x*4+2, x*4+2, x*4+3); - iba.setLine (x*4+3, x*4+3, x*4+0); - } - iba.unlock(); - - vbaSel.unlock(); - VBSel.setNumVertices (nVertCountSel); - PBSel.setNumIndexes (nVertCountSel*2); - CIndexBufferReadWrite ibaSel; - PBSel.lock (ibaSel); - for (x = 0; x < (nVertCountSel/4); ++x) - { - ibaSel.setLine (x*4+0, x*4+0, x*4+1); - ibaSel.setLine (x*4+1, x*4+1, x*4+2); - ibaSel.setLine (x*4+2, x*4+2, x*4+3); - ibaSel.setLine (x*4+3, x*4+3, x*4+0); - } - ibaSel.unlock(); - - if (DontUse3D) - return; - - // Render - CMatrix mtx; - mtx.identity(); - CNELU::Driver->setupViewport (CViewport()); - CNELU::Driver->setupViewMatrix (mtx); - CNELU::Driver->setupModelMatrix (mtx); - CNELU::Driver->setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false); - CNELU::Driver->activeVertexBuffer (VB); - CNELU::Driver->activeIndexBuffer (PB); - CNELU::Driver->renderLines (Mat, 0, PB.getNumIndexes()/2); - CNELU::Driver->activeVertexBuffer (VBSel); - CNELU::Driver->activeIndexBuffer (PBSel); - CNELU::Driver->renderLines (MatSel, 0, PBSel.getNumIndexes()/2); - } -} - -// --------------------------------------------------------------------------- -void CBuilderZone::displayGrid (const NLMISC::CVector &viewMin, const NLMISC::CVector &viewMax) -{ - // Select all blocks visible - float rMinX = floorf (viewMin.x / _Display->_CellSize)*_Display->_CellSize; - float rMinY = floorf (viewMin.y / _Display->_CellSize)*_Display->_CellSize; - float rMaxX = ceilf (viewMax.x / _Display->_CellSize)*_Display->_CellSize; - float rMaxY = ceilf (viewMax.y / _Display->_CellSize)*_Display->_CellSize; - - sint32 nMinX = (sint32)floor (rMinX / _Display->_CellSize); - sint32 nMinY = (sint32)floor (rMinY / _Display->_CellSize); - sint32 nMaxX = (sint32)floor (rMaxX / _Display->_CellSize); - sint32 nMaxY = (sint32)floor (rMaxY / _Display->_CellSize); - - static vector vBars; - sint32 nBarsW = (nMaxX-nMinX)+1; - sint32 nBarsH = (nMaxY-nMinY)+1; - vBars.resize (nBarsW*nBarsH); - sint32 x, y, i, j, zoneSelected; - for (i = 0; i < nBarsW*nBarsH; ++i) - vBars[i] = 0; - - - for (y = nMinY; y <= nMaxY; ++y) - for (x = nMinX; x <= nMaxX; ++x) - { - - string sZone = STRING_OUT_OF_BOUND; - zoneSelected = 0; - for (i = 0; i < (sint32)_ZoneRegions.size(); ++i) - { - const string &rSZone = getDocument ()->getZoneRegion (i).getName (x, y); - if ((sZone == STRING_OUT_OF_BOUND) && (rSZone == STRING_UNUSED)) - { - sZone = STRING_UNUSED; - zoneSelected = i; - } - if ((rSZone != STRING_OUT_OF_BOUND) && (rSZone != STRING_UNUSED)) - { - sZone = rSZone; - zoneSelected = i; - } - } - - - //const string &sZone = _ZoneRegion.getName (x, y); - CZoneBankElement *pZBE = _ZoneBank.getElementByZoneName (sZone); - if (pZBE != NULL) - if ((pZBE->getSizeX() > 1) || (pZBE->getSizeY() > 1)) - { - const CZoneRegion *pSelected = &(getDocument ()->getZoneRegion (zoneSelected)); - sint32 sizeX = pZBE->getSizeX(), sizeY = pZBE->getSizeY(); - sint32 posX = pSelected->getPosX (x, y), posY = pSelected->getPosY (x, y); - uint8 rot = pSelected->getRot (x, y); - uint8 flip = pSelected->getFlip (x, y); - sint32 deltaX, deltaY; - - if (flip == 0) - { - switch (rot) - { - case 0: deltaX = -posX; deltaY = -posY; break; - case 1: deltaX = -(sizeY-1-posY); deltaY = -posX; break; - case 2: deltaX = -(sizeX-1-posX); deltaY = -(sizeY-1-posY); break; - case 3: deltaX = -posY; deltaY = -(sizeX-1-posX); break; - } - } - else - { - switch (rot) - { - case 0: deltaX = -(sizeX-1-posX); deltaY = -posY; break; - case 1: deltaX = -(sizeY-1-posY); deltaY = -(sizeX-1-posX); break; - case 2: deltaX = -posX; deltaY = -(sizeY-1-posY); break; - case 3: deltaX = -posY; deltaY = -posX; break; - } - } - - static SPiece sMask; - sMask.Tab.resize (sizeX*sizeY); - for(i = 0; i < sizeX*sizeY; ++i) - sMask.Tab[i] = pZBE->getMask()[i]; - sMask.w = sizeX; - sMask.h = sizeY; - sMask.rotFlip (rot, flip); - - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - if (((x+deltaX+i-nMinX)>=0) && ((x+deltaX+i-nMinX)=0) && ((y+deltaY+j-nMinY) 0) && (sMask.Tab[i-1+j*sMask.w])) - vBars[x+deltaX+i-nMinX + (y+deltaY+j-nMinY)*nBarsW] |= 1; - - if ((j > 0) && (sMask.Tab[i+(j-1)*sMask.w])) - vBars[x+deltaX+i-nMinX + (y+deltaY+j-nMinY)*nBarsW] |= 2; - } - } - } - } - - CVertexBuffer VB; - CIndexBuffer PB; - CMaterial Mat; - - Mat.initUnlit (); - Mat.setBlend (false); - VB.setVertexFormat (CVertexBuffer::PositionFlag); - VB.setNumVertices ((nBarsW+1)*(nBarsH+1)); - CVertexBufferReadWrite vba; - VB.lock (vba); - - for (y = nMinY; y <= nMaxY+1; ++y) - for (x = nMinX; x <= nMaxX+1; ++x) - { - CVector pos; - - pos.x = (x*_Display->_CellSize - viewMin.x)/(viewMax.x-viewMin.x); - pos.y = 0.0f; - pos.z = (y*_Display->_CellSize - viewMin.y)/(viewMax.y-viewMin.y); - vba.setVertexCoord (x-nMinX+(y-nMinY)*(nBarsW+1), pos); - } - - PB.setNumIndexes (nBarsW*nBarsH*2*2); - CIndexBufferReadWrite iba; - PB.lock (iba); - uint32 nNbLine = 0; - for (y = 0; y < nBarsH; ++y) - for (x = 0; x < nBarsW; ++x) - { - // Vertical Line ? - if ((vBars[x+y*nBarsW] & 1) == 0) - { - iba.setLine (nNbLine*2, x+y*(nBarsW+1), x+(y+1)*(nBarsW+1)); - ++nNbLine; - } - - // Horizontal Line ? - if ((vBars[x+y*nBarsW] & 2) == 0) - { - iba.setLine (nNbLine*2, x+y*(nBarsW+1), (x+1)+y*(nBarsW+1)); - ++nNbLine; - } - } - iba.unlock(); - PB.setNumIndexes (nNbLine*2); - - if (DontUse3D) - return; - - // Render with driver - CMatrix mtx; - mtx.identity(); - vba.unlock(); - CNELU::Driver->setupViewport (CViewport()); - CNELU::Driver->setupViewMatrix (mtx); - CNELU::Driver->setupModelMatrix (mtx); - CNELU::Driver->setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false); - CNELU::Driver->activeVertexBuffer (VB); - CNELU::Driver->activeIndexBuffer (PB); - CNELU::Driver->renderLines (Mat, 0, PB.getNumIndexes()/2); - -} - -// --------------------------------------------------------------------------- -void CBuilderZone::add (const CVector &worldPos) -{ - sint32 x = (sint32)floor (worldPos.x / _Display->_CellSize); - sint32 y = (sint32)floor (worldPos.y / _Display->_CellSize); - uint8 rot, flip; - - if (_ZoneRegions.size() == 0) - return; - - if (_RandomSelection) - { - if (_CurrentSelection.size() > 0) - { - uint32 nSel = (uint32)(NLMISC::frand (1.0) * _CurrentSelection.size()); - NLMISC::clamp (nSel, (uint32)0, (uint32)(_CurrentSelection.size()-1)); - _CurSelectedZone = nSel; - } - } - if (_CycleSelection) - { - _CurSelectedZone = _ApplyCycleSelection; - _ApplyCycleSelection++; - _ApplyCycleSelection = _ApplyCycleSelection%_CurrentSelection.size(); - } - - if (_ApplyRotType == 1) - { - uint32 nSel = (uint32)(NLMISC::frand (1.0) * 4); - NLMISC::clamp (nSel, (uint32)0, (uint32)3); - rot = (uint8)nSel; - } - else if (_ApplyRotType == 0) - { - rot = _ApplyRot; - } - else if (_ApplyRotType == 2) - { - rot = _ApplyRotCycle; - _ApplyRotCycle++; - _ApplyRotCycle = _ApplyRotCycle%4; - } - - - if (_ApplyFlipType == 1) - { - uint32 nSel = (uint32)(NLMISC::frand (1.0) * 2); - NLMISC::clamp (nSel, (uint32)0, (uint32)1); - flip = (uint8)nSel; - } - else if (_ApplyFlipType == 0) - { - flip = _ApplyFlip; - } - else if (_ApplyFlipType == 2) - { - flip = _ApplyFlipCycle; - _ApplyFlipCycle++; - _ApplyFlipCycle = _ApplyFlipCycle%2; - } - - if ((_CurSelectedZone >= 0)&&(_CurSelectedZone <= ((sint32)_CurrentSelection.size()-1))) - { - CZoneBankElement *pZBE = _CurrentSelection[_CurSelectedZone]; - string error; - _ZoneRegions[_ZoneRegionSelected]->init (&_ZoneBank, this, error); - - if (_Force) - { - _ZoneRegions[_ZoneRegionSelected]->addForce (x, y, rot, flip, pZBE); - } - else - { - if (_NotPropagate) - _ZoneRegions[_ZoneRegionSelected]->addNotPropagate (x, y, rot, flip, pZBE); - else - _ZoneRegions[_ZoneRegionSelected]->add (x, y, rot, flip, pZBE); - } - } -} - -// --------------------------------------------------------------------------- -void CBuilderZone::addTransition (const NLMISC::CVector &worldPos) -{ - sint32 x = (sint32)floor (worldPos.x / _Display->_CellSize); - sint32 y = (sint32)floor (worldPos.y / _Display->_CellSize); - sint32 k; - - if (_ZoneRegions.size() == 0) - return; - - // Detect if we are in a transition square to switch - CBuilderZoneRegion *pBZR2 = _ZoneRegions[_ZoneRegionSelected]; - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (_ZoneRegionSelected)); - bool bCutEdgeTouched = false; - for (uint8 transPos = 0; transPos < 4; ++transPos) - { - uint ce = pBZR->getCutEdge (x, y, transPos); - - if ((ce > 0) && (ce < 3)) - for (k = 0; k < 2; ++k) - { - float xTrans, yTrans; - - if ((transPos == 0) || (transPos == 1)) - { - if (ce == 1) - xTrans = _Display->_CellSize / 3.0f; - else - xTrans = 2.0f * _Display->_CellSize / 3.0f; - } - else - { - if (transPos == 2) - xTrans = 0; - else - xTrans = _Display->_CellSize; - } - xTrans += x * _Display->_CellSize; - - if ((transPos == 2) || (transPos == 3)) - { - if (ce == 1) - yTrans = _Display->_CellSize / 3.0f; - else - yTrans = 2.0f * _Display->_CellSize / 3.0f; - } - else - { - if (transPos == 1) - yTrans = 0; - else - yTrans = _Display->_CellSize; - } - yTrans += y * _Display->_CellSize; - - if ((worldPos.x >= (xTrans-_Display->_CellSize/12.0f)) && (worldPos.x <= (xTrans+_Display->_CellSize/12.0f)) && - (worldPos.y >= (yTrans-_Display->_CellSize/12.0f)) && (worldPos.y <= (yTrans+_Display->_CellSize/12.0f))) - { - pBZR2->invertCutEdge (x, y, transPos); - bCutEdgeTouched = true; - } - ce = 3 - ce; - } - } - - // If not clicked to change the cutEdge so the user want to change the transition - if (!bCutEdgeTouched) - { - pBZR2->cycleTransition (x, y); - } -} - -// --------------------------------------------------------------------------- -void CBuilderZone::del (const CVector &worldPos) -{ - sint32 x = (sint32)floor (worldPos.x / _Display->_CellSize); - sint32 y = (sint32)floor (worldPos.y / _Display->_CellSize); - - if (_ZoneRegions.size() == 0) - return; - - CBuilderZoneRegion *pBZR = _ZoneRegions[_ZoneRegionSelected]; - string error; - pBZR->init (&_ZoneBank, this, error); - pBZR->del (x, y); -} - -// --------------------------------------------------------------------------- -bool CBuilderZone::initZoneBank (const string &sPathName) -{ - char sDirBackup[512]; - GetCurrentDirectory (512, sDirBackup); - SetCurrentDirectory (sPathName.c_str()); - WIN32_FIND_DATA findData; - HANDLE hFind; - hFind = FindFirstFile ("*.ligozone", &findData); - - while (hFind != INVALID_HANDLE_VALUE) - { - // If the name of the file is not . or .. then its a valid entry in the DataBase - if (!((strcmp (findData.cFileName, ".") == 0) || (strcmp (findData.cFileName, "..") == 0))) - { - string error; - if (!_ZoneBank.addElement (findData.cFileName, error)) - theApp.errorMessage (error.c_str()); - } - if (FindNextFile (hFind, &findData) == 0) - break; - } - SetCurrentDirectory (sDirBackup); - return true; -} - -// --------------------------------------------------------------------------- - -uint32 CBuilderZone::getNbZoneRegion () -{ - return _ZoneRegions.size (); -} - -// --------------------------------------------------------------------------- - -string CBuilderZone::getZoneName (sint32 x, sint32 y) -{ - string sRet = STRING_UNUSED; - uint32 nNbRegion = _ZoneRegions.size(); - for (uint32 i = 0; i < nNbRegion; ++i) - { - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (i)); - if ((x < pBZR->getMinX())||(x > pBZR->getMaxX())||(y < pBZR->getMinY())||(y > pBZR->getMaxY())) - continue; - if (pBZR->getName(x, y) != STRING_UNUSED) - { - sRet = pBZR->getName(x, y); - return sRet; - } - } - sRet = ""; - return sRet; -} - -// --------------------------------------------------------------------------- -uint8 CBuilderZone::getRot (sint32 x, sint32 y) -{ - uint8 sRet = 0; - uint32 nNbRegion = _ZoneRegions.size(); - for (uint32 i = 0; i < nNbRegion; ++i) - { - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (i)); - if ((x < pBZR->getMinX())||(x > pBZR->getMaxX())||(y < pBZR->getMinY())||(y > pBZR->getMaxY())) - continue; - if (pBZR->getName(x, y) != STRING_UNUSED) - { - sRet = pBZR->getRot(x, y); - return sRet; - } - } - sRet = 0; - return sRet; -} - -// --------------------------------------------------------------------------- -uint8 CBuilderZone::getFlip (sint32 x, sint32 y) -{ - uint8 sRet = 0; - uint32 nNbRegion = _ZoneRegions.size(); - for (uint32 i = 0; i < nNbRegion; ++i) - { - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (i)); - if ((x < pBZR->getMinX())||(x > pBZR->getMaxX())||(y < pBZR->getMinY())||(y > pBZR->getMaxY())) - continue; - if (pBZR->getName(x, y) != STRING_UNUSED) - { - sRet = pBZR->getFlip(x, y); - return sRet; - } - } - sRet = 0; - return sRet; -} - -// --------------------------------------------------------------------------- -CBuilderZoneRegion* CBuilderZone::getPtrCurZoneRegion () -{ - if (_ZoneRegions.size() == 0) - return NULL; - return _ZoneRegions[_ZoneRegionSelected]; -} - -// --------------------------------------------------------------------------- -uint32 CBuilderZone::getCurZoneRegion () -{ - return _ZoneRegionSelected; -} - -// --------------------------------------------------------------------------- -void CBuilderZone::setCurZoneRegion (uint32 sel) -{ - _ZoneRegionSelected = sel; - calcMask(); -} - -// --------------------------------------------------------------------------- -bool CBuilderZone::getZoneMask (sint32 x, sint32 y) -{ - if ((x < _MinX) || (x > _MaxX) || - (y < _MinY) || (y > _MaxY)) - { - return true; - } - else - { - return _ZoneMask[(x-_MinX)+(y-_MinY)*(1+_MaxX-_MinX)]; - } -} - -// --------------------------------------------------------------------------- -/* -void CBuilderZone::generate (sint32 nMinX, sint32 nMinY, sint32 nMaxX, sint32 nMaxY, - sint32 nZoneBaseX, sint32 nZoneBaseY, const char *MaterialString) -{ - if ((nMinX > nMaxX) || (nMinY > nMaxY)) - return; - - for (sint32 j = nMinY; j <= nMaxY; ++j) - for (sint32 i = nMinX; i <= nMaxX; ++i) - { - // Generate zone name - string ZoneName = "converted-"+CExport::getZoneNameFromXY (i, j); - ZoneName = NLMISC::strlwr (ZoneName); - CZoneBankElement *pZBE = _ZoneBank.getElementByZoneName (ZoneName); - if (pZBE != NULL) - { - _ZoneRegions[_ZoneRegionSelected]->init (&_ZoneBank, this); - _ZoneRegions[_ZoneRegionSelected]->add (i, j, 0, 0, pZBE); - } - } -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" +#include "nel/misc/object_vector.h" +#include "nel/misc/path.h" + +#include "world_editor.h" +#include "world_editor_doc.h" +#include "builder_zone.h" +#include "main_frm.h" +#include "display.h" +#include "tools_zone.h" + +extern bool DontUse3D; + +using namespace std; +using namespace NLLIGO; + +// Because we cant use the namespace NLMISC or NL3D in global due to some collision (CBitmap,...) +using NLMISC::CIFile; +using NLMISC::Exception; +using NLMISC::CVector; +using NLMISC::CUV; +using NLMISC::CMatrix; +using NLMISC::CSmartPtr; +using NLMISC::CIFile; +using NLMISC::COFile; + +using NL3D::ITexture; +using NL3D::CTextureMem; +using NL3D::CTextureFile; +using NL3D::CVertexBuffer; +using NL3D::CIndexBuffer; +using NL3D::CMaterial; +using NL3D::CViewport; +using NL3D::CNELU; +using NL3D::CVertexBufferReadWrite; +using NL3D::CIndexBufferReadWrite; + +// *************************************************************************** +// CDataBase::SCacheTexture +// *************************************************************************** + +// --------------------------------------------------------------------------- +CDataBase::SCacheTexture::SCacheTexture() +{ + Enabled = false; + Texture = NULL; +} + +// --------------------------------------------------------------------------- +bool CDataBase::SCacheTexture::isFull() +{ + if (!Enabled) + return false; + for (uint32 i = 0; i < FreePlace.size(); ++i) + if (FreePlace[i]) + return false; + return true; +} + +// *************************************************************************** +// CDataBase +// *************************************************************************** + +// --------------------------------------------------------------------------- +CDataBase::CDataBase (uint bitmapSize) +{ + _RefCacheTextureSizeX = _RefCacheTextureSizeY = 1024; // Size of the texture cache + _RefSizeX = _RefSizeY = bitmapSize; // Size of a zone in pixel + _RefCacheTextureNbEltX = _RefCacheTextureSizeX / _RefSizeX; + _RefCacheTextureNbEltY = _RefCacheTextureSizeY / _RefSizeY; + for (uint32 i = 0; i < 64; ++i) + _CacheTexture[i].Enabled = false; +} + +// --------------------------------------------------------------------------- +CDataBase::~CDataBase () +{ + reset (); +} + +// --------------------------------------------------------------------------- +void CDataBase::reset () +{ + for (uint32 i = 0; i < 64; ++i) + { + _CacheTexture[i].Enabled = false; + _CacheTexture[i].Texture = NULL; // Because its a smart ptr + _CacheTexture[i].PtrMem.resize (0); + _CacheTexture[i].FreePlace.resize(0); + } + + map::iterator it = _ZoneDBmap.begin (); + while (it != _ZoneDBmap.end()) + { + string sName = it->first; + SElement &rElt = it->second; + delete rElt.WinBitmap; + rElt.WinBitmap = NULL; + ++it; + } + _ZoneDBmap.clear (); + _UnusedTexture = NULL; +} + +// --------------------------------------------------------------------------- +bool CDataBase::initFromPath (const string &Path) +{ + return false; +} + +// --------------------------------------------------------------------------- +bool CDataBase::init (const string &Path, CZoneBank &zb) +{ + string sDirBackup = NLMISC::CPath::getCurrentPath(); + + // "Path" can be relative to the doc path so we have to be first in the doc path + string s2 = NLMISC::CFile::getPath ((LPCTSTR)getMainFrame()->getDocument()->GetPathName()); + NLMISC::CPath::setCurrentPath(s2.c_str()); + string ss = NLMISC::CPath::getFullPath(Path); + NLMISC::CPath::setCurrentPath (ss.c_str()); + + uint32 i, m, n, o, p; + uint8 k, l; + + vector ZoneNames; + zb.getCategoryValues ("zone", ZoneNames); + for (i = 0; i < ZoneNames.size(); ++i) + { + // Progress + getMainFrame ()->progressLoadingDialog ((float)i / (float)ZoneNames.size()); + + SElement zdbTmp; + CZoneBankElement *pZBE = zb.getElementByZoneName (ZoneNames[i]); + // Read the texture file + string zdbTmpName = ZoneNames[i]; + zdbTmp.SizeX = pZBE->getSizeX (); + zdbTmp.SizeY = pZBE->getSizeY (); + const vector &rMask = pZBE->getMask(); + + NLMISC::CBitmap *pBitmap = loadBitmap (getTextureFile(zdbTmpName)); + + // Should not return NULL ! + nlassert (pBitmap); + + // Wanted zone size + uint width = _RefSizeX * zdbTmp.SizeX; + uint height = _RefSizeY * zdbTmp.SizeY; + + // Good size ? + if ((pBitmap->getWidth () != width) || (pBitmap->getHeight () != height)) + { + // Resize it + pBitmap->resample (width, height); + } + + zdbTmp.WinBitmap = convertToWin (pBitmap); + pBitmap->flipV (); + + for (l = 0; l < zdbTmp.SizeY; ++l) + for (k = 0; k < zdbTmp.SizeX; ++k) + if (rMask[k+l*zdbTmp.SizeX]) + { + SCacheZone czTmp; + + czTmp.PosX = k; + czTmp.PosY = l; + + // Found first non full texture cache + for (m = 0; m < 64; ++m) + if (_CacheTexture[m].Enabled == false) + { + // Create the texture + _CacheTexture[m].FreePlace.resize (_RefCacheTextureNbEltX*_RefCacheTextureNbEltY, true); + _CacheTexture[m].Texture = new CTextureMem(); + _CacheTexture[m].Texture->setAllowDegradation (true); + _CacheTexture[m].PtrMem.resize (4*_RefCacheTextureSizeX*_RefCacheTextureSizeY); + _CacheTexture[m].Texture->resize (_RefCacheTextureSizeX, _RefCacheTextureSizeY); + _CacheTexture[m].Texture->setPointer (&_CacheTexture[m].PtrMem[0], 4*_RefCacheTextureSizeX*_RefCacheTextureSizeY, + false, false, _RefCacheTextureSizeX, _RefCacheTextureSizeY); + + _CacheTexture[m].Enabled = true; + break; + } + else + { + if (!_CacheTexture[m].isFull()) + break; + } + + nlassert (m<64); + + // Found first place in this texture + + for (n = 0; n < _CacheTexture[m].FreePlace.size(); ++n) + if (_CacheTexture[m].FreePlace[n]) + { + sint32 xSrc = k*_RefSizeX; + sint32 ySrc = l*_RefSizeY; + sint32 xDst = (n%_RefCacheTextureNbEltX)*_RefSizeX; + sint32 yDst = (n/_RefCacheTextureNbEltX)*_RefSizeY; + uint8 *pSrc = &pBitmap->getPixels()[(xSrc+ySrc*pBitmap->getWidth())*4]; + uint8 *pDst = &_CacheTexture[m].PtrMem[(xDst+yDst*_RefCacheTextureSizeX)*4]; + // Copy part of the bitmap into cache texture + for (p = 0; p < _RefSizeY; ++p) + for (o = 0; o < _RefSizeX; ++o) + { + pDst[(o+p*_RefCacheTextureSizeX)*4+0] = pSrc[(o+p*pBitmap->getWidth())*4+0]; + pDst[(o+p*_RefCacheTextureSizeX)*4+1] = pSrc[(o+p*pBitmap->getWidth())*4+1]; + pDst[(o+p*_RefCacheTextureSizeX)*4+2] = pSrc[(o+p*pBitmap->getWidth())*4+2]; + pDst[(o+p*_RefCacheTextureSizeX)*4+3] = pSrc[(o+p*pBitmap->getWidth())*4+3]; + } + czTmp.PosUV.U = ((float)xDst) / ((float)_RefCacheTextureSizeX); + czTmp.PosUV.V = ((float)yDst) / ((float)_RefCacheTextureSizeY); + czTmp.CacheTexture = _CacheTexture[m].Texture; + _CacheTexture[m].FreePlace[n] = false; + break; + } + //nlassert (m<_CacheTexture[m].FreePlace.size()); + zdbTmp.ZonePieces.push_back (czTmp); + } + // Add the entry in the DataBase + _ZoneDBmap.insert (pair(zdbTmpName, zdbTmp)); + delete pBitmap; + } + + // Upload all textures in VRAM + for (m = 0; m < 64; ++m) + if (_CacheTexture[m].Enabled) + _CacheTexture[m].Texture->touch (); + + _UnusedTexture = loadTexture (getTextureFile("_UNUSED_")); + + NLMISC::CPath::setCurrentPath(sDirBackup); + return true; +} + +// --------------------------------------------------------------------------- +CBitmap *CDataBase::getBitmap (const string &ZoneName) +{ + map::iterator it = _ZoneDBmap.find (ZoneName); + if (it != _ZoneDBmap.end()) + return (it->second.WinBitmap); + else + return NULL; +} + +// --------------------------------------------------------------------------- +ITexture* CDataBase::getTexture (const string &ZoneName, sint32 nPosX, sint32 nPosY, CUV &retUVmin, CUV &retUVmax) +{ + if (ZoneName == STRING_UNUSED) + { + retUVmin.U = 0.0f; + retUVmin.V = 1.0f - 0.0f; + retUVmax.U = 1.0f; + retUVmax.V = 1.0f - 1.0f; + return _UnusedTexture; + } + + map::iterator it = _ZoneDBmap.find (ZoneName); + if (it != _ZoneDBmap.end()) + { + SElement &rElt = it->second; + for (uint32 j = 0; j < rElt.ZonePieces.size(); ++j) + if ((rElt.ZonePieces[j].PosX == nPosX) && (rElt.ZonePieces[j].PosY == nPosY)) + { + retUVmin = rElt.ZonePieces[j].PosUV; + retUVmin.U += 0.5f / ((float)_RefCacheTextureSizeX); + retUVmin.V += 0.5f / ((float)_RefCacheTextureSizeY); + retUVmax = retUVmin; + retUVmax.U += ((float)_RefSizeX-1) / ((float)_RefCacheTextureSizeX); + retUVmax.V += ((float)_RefSizeY-1) / ((float)_RefCacheTextureSizeY); + return rElt.ZonePieces[j].CacheTexture; + } + } + + return NULL; +} + +// --------------------------------------------------------------------------- +// Private +// --------------------------------------------------------------------------- + +// --------------------------------------------------------------------------- +// Divisor to initialize windows bitmap +#define WIDTH_DIVISOR 2 +#define HEIGHT_DIVISOR 2 + +CBitmap *CDataBase::convertToWin (NLMISC::CBitmap *pBitmap) +{ + CBitmap *pWinBitmap = new CBitmap; + NLMISC::CObjectVector &rPixel = pBitmap->getPixels(); + uint32 nNewWidth = pBitmap->getWidth()/WIDTH_DIVISOR; + uint32 nNewHeight = pBitmap->getHeight()/HEIGHT_DIVISOR; + uint8 *pNewPixel = new uint8[nNewHeight*nNewWidth*4]; + uint32 i, j; + for (j = 0; j < nNewHeight; ++j) + for (i = 0; i < nNewWidth; ++i) + { + pNewPixel[(i+j*nNewWidth)*4+0] = rPixel[(i*WIDTH_DIVISOR+j*HEIGHT_DIVISOR*pBitmap->getWidth())*4+2]; + pNewPixel[(i+j*nNewWidth)*4+1] = rPixel[(i*WIDTH_DIVISOR+j*HEIGHT_DIVISOR*pBitmap->getWidth())*4+1]; + pNewPixel[(i+j*nNewWidth)*4+2] = rPixel[(i*WIDTH_DIVISOR+j*HEIGHT_DIVISOR*pBitmap->getWidth())*4+0]; + pNewPixel[(i+j*nNewWidth)*4+3] = rPixel[(i*WIDTH_DIVISOR+j*HEIGHT_DIVISOR*pBitmap->getWidth())*4+3]; + } + pWinBitmap->CreateBitmap (nNewWidth, nNewHeight, 1, 32, pNewPixel); + if (pNewPixel == NULL) + { + delete pWinBitmap; + return NULL; + } + else + return pWinBitmap; +} + +// --------------------------------------------------------------------------- +CTextureFile *CDataBase::loadTexture (const std::string &fileName) +{ + CTextureFile *pTexture = new CTextureFile; + pTexture->setFileName (fileName); + pTexture->setReleasable (false); + pTexture->generate (); + return pTexture; +} + +// --------------------------------------------------------------------------- +NLMISC::CBitmap *CDataBase::loadBitmap (const std::string &fileName) +{ + NLMISC::CBitmap *pBitmap = new NLMISC::CBitmap(); + + try + { + CIFile fileIn; + if (fileIn.open (fileName)) + { + pBitmap->load (fileIn); + } + else + { + pBitmap->makeDummy(); + nlwarning ("Bitmap not found : %s", fileName.c_str()); + } + } + catch (Exception& e) + { + pBitmap->makeDummy(); + theApp.errorMessage ("Error while loading bitmap %s : %s", fileName.c_str(), e.what()); + } + + return pBitmap; +} + +// *************************************************************************** +// CBuilderZone +// *************************************************************************** +// --------------------------------------------------------------------------- +// PRIVATE +// --------------------------------------------------------------------------- + +// --------------------------------------------------------------------------- +void CBuilderZone::calcMask() +{ + sint32 i; + sint32 x, y; + + _MinY = _MinX = 1000000; + _MaxY = _MaxX = -1000000; + + if (_ZoneRegions.size() == 0) + return; + + CWorldEditorDoc *doc = getDocument (); + + for (i = 0; i < (sint32)_ZoneRegions.size(); ++i) + { + const CZoneRegion *pBZR = &(doc->getZoneRegion (i)); + + if (_MinX > pBZR->getMinX()) + _MinX = pBZR->getMinX(); + if (_MinY > pBZR->getMinY()) + _MinY = pBZR->getMinY(); + if (_MaxX < pBZR->getMaxX()) + _MaxX = pBZR->getMaxX(); + if (_MaxY < pBZR->getMaxY()) + _MaxY = pBZR->getMaxY(); + } + + _ZoneMask.resize ((1+_MaxX-_MinX)*(1+_MaxY-_MinY)); + sint32 stride = (1+_MaxX-_MinX); + for (y = _MinY; y <= _MaxY; ++y) + for (x = _MinX; x <= _MaxX; ++x) + { + _ZoneMask[x-_MinX+(y-_MinY)*stride] = true; + + for (i = 0; i < (sint32)_ZoneRegions.size(); ++i) + if (i != _ZoneRegionSelected) + { + const CZoneRegion *pBZR = &(doc->getZoneRegion (i)); + + const string &rSZone = pBZR->getName (x, y); + if ((rSZone != STRING_OUT_OF_BOUND) && (rSZone != STRING_UNUSED)) + { + _ZoneMask[x-_MinX+(y-_MinY)*stride] = false; + } + } + } +} + +// --------------------------------------------------------------------------- +// PUBLIC +// --------------------------------------------------------------------------- + +// --------------------------------------------------------------------------- +CBuilderZone::CBuilderZone (uint bitmapSize) : _DataBase (bitmapSize) +{ + // Set Current Filter + _FilterType1 = STRING_UNUSED; _FilterValue1 = ""; + _FilterType2 = STRING_UNUSED; _FilterValue2 = ""; + _FilterType3 = STRING_UNUSED; _FilterValue3 = ""; + _FilterType4 = STRING_UNUSED; _FilterValue4 = ""; + _FilterOperator2 = 0; + _FilterOperator3 = 0; + _FilterOperator4 = 0; + _RandomSelection = false; + _CurSelectedZone = -1; + _ZoneRegionSelected = -1; + _ApplyRot = 0; + _ApplyRotType = 0; + _ApplyFlip = 0; + _ApplyFlipType = 0; + + _Display = NULL; + _ApplyRotCycle = 0; + _ApplyFlipCycle = 0; + _CycleSelection = false; + _ApplyCycleSelection = 0; + _NotPropagate = false; + _Force = false; + _LastPathName = ""; + _ToolsZone = NULL; +} + +// --------------------------------------------------------------------------- +bool CBuilderZone::init (const string &sPathName, bool makeAZone, CDisplay *display) +{ + // Set the display + _Display = display; + + bool bRet = true; + if (sPathName != _LastPathName) + { + _LastPathName = sPathName; + string sZoneBankPath = sPathName; + sZoneBankPath += "\\zoneligos\\"; + // Init the ZoneBank + _ZoneBank.reset (); + if (!initZoneBank (sZoneBankPath)) + { + _ZoneBank.reset (); + return false; + } + + // Construct the DataBase from the ZoneBank + string sZoneBitmapPath = sPathName; + sZoneBitmapPath += "\\zonebitmaps\\"; + _DataBase.reset (); + if (!_DataBase.init (sZoneBitmapPath.c_str(), _ZoneBank)) + { + _DataBase.reset (); + _ZoneBank.reset (); + return false; + } + } + + if ((makeAZone) && (bRet)) + newZone(); + + return bRet; +} + +// --------------------------------------------------------------------------- +void CBuilderZone::setToolsZone (CToolsZone *pTool) +{ + _ToolsZone = pTool; +} + +// --------------------------------------------------------------------------- +void CBuilderZone::updateToolsZone () +{ + uint32 i; + + if (_ToolsZone == NULL) + return; + + // Execute the filter + _ZoneBank.resetSelection (); + if(_FilterType1 != STRING_UNUSED) + _ZoneBank.addOrSwitch (_FilterType1, _FilterValue1); + + if(_FilterType2 != STRING_UNUSED) + { + if (_FilterOperator2 == 0) // AND switch wanted + _ZoneBank.addAndSwitch (_FilterType2, _FilterValue2); + else // OR switch wanted + _ZoneBank.addOrSwitch (_FilterType2, _FilterValue2); + } + + if(_FilterType3 != STRING_UNUSED) + { + if (_FilterOperator3 == 0) // AND switch wanted + _ZoneBank.addAndSwitch (_FilterType3, _FilterValue3); + else // OR switch wanted + _ZoneBank.addOrSwitch (_FilterType3, _FilterValue3); + } + + if(_FilterType4 != STRING_UNUSED) + { + if (_FilterOperator4 == 0) // AND switch wanted + _ZoneBank.addAndSwitch (_FilterType4, _FilterValue4); + else // OR switch wanted + _ZoneBank.addOrSwitch (_FilterType4, _FilterValue4); + } + + _ZoneBank.getSelection (_CurrentSelection); + + // Create the corresponding image list from selected item using DataBase + + vector vIL; + vIL.resize (_CurrentSelection.size()); + for (i = 0; i < _CurrentSelection.size(); ++i) + { + CZoneBankElement *pElt = _CurrentSelection[i]; + // Get bitmap from DataBase + vIL[i] = _DataBase.getBitmap (pElt->getName()); + } + + // Construct the tree add first items then the images! + _ToolsZone->getListCtrl()->reset (); + for (i = 0; i < _CurrentSelection.size(); ++i) + { + CZoneBankElement *pElt = _CurrentSelection[i]; + _ToolsZone->getListCtrl()->addItem (pElt->getName()); + } + _ToolsZone->getListCtrl()->setImages (vIL); + if (_CurrentSelection.size() > 0) + { + _ToolsZone->getListCtrl()->SetCurSel (0); + _CurSelectedZone = 0; + } + else + _CurSelectedZone = -1; + _ApplyCycleSelection = 0; + + + _ToolsZone->Invalidate(); + _ToolsZone->UpdateWindow(); +} + +// --------------------------------------------------------------------------- +bool CBuilderZone::refresh () +{ + // Reset all + _ZoneRegions.clear (); + _ZoneRegionSelected = -1; + + CWorldEditorDoc *doc = getDocument (); + for (uint j=0; jgetNumDatabaseElement (); j++) + { + // Is it a landscape ? + if (doc->isLandscape (j)) + { + _ZoneRegionSelected++; + + newZone (false); + + // Check if we can load this zone + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (_ZoneRegionSelected)); + for (sint32 y = pBZR->getMinY(); y <= pBZR->getMaxY(); ++y) + for (sint32 x = pBZR->getMinX(); x <= pBZR->getMaxX(); ++x) + { + const string &refSZone = pBZR->getName (x, y); + if (refSZone != STRING_UNUSED) + { + sint zoneRegionSelected2 = -1; + CWorldEditorDoc *doc = getDocument (); + for (uint i=0; igetNumDatabaseElement (); i++) + { + // Is it a landscape ? + if (doc->isLandscape (i)) + { + zoneRegionSelected2++; + if (i!=j) + { + const CZoneRegion *pBZR2 = &(getDocument ()->getZoneRegion (zoneRegionSelected2)); + const string &sZone = pBZR2->getName (x, y); + if ((sZone != STRING_UNUSED)&&(sZone != STRING_OUT_OF_BOUND)) + { + unload (_ZoneRegionSelected); + MessageBox (NULL, "Cannot add this zone because it overlaps existing ones", + "Error", MB_ICONERROR|MB_OK); + return false; + } + } + } + } + } + } + + string error; + if (!_ZoneRegions[_ZoneRegionSelected]->init (&_ZoneBank, this, error)) + { + unload (_ZoneRegionSelected); + MessageBox (NULL, ("Cannot add this zone :\n"+error).c_str(), + "Error", MB_ICONERROR|MB_OK); + return false; + } + + _Display->_Offset.x = _Display->_CellSize*(pBZR->getMinX() + + pBZR->getMaxX()) / 2.0f; + _Display->_Offset.y = _Display->_CellSize*(pBZR->getMinY() + + pBZR->getMaxY()) / 2.0f; + calcMask (); + } + } + return true; +} + +// --------------------------------------------------------------------------- + +void CBuilderZone::newZone (bool bDisplay) +{ + _ZoneRegions.push_back (new CBuilderZoneRegion (_ZoneRegions.size())); + _ZoneRegionSelected = _ZoneRegions.size() - 1; + // Select starting point for the moment 0,0 + sint32 i; + sint32 x = 0, y = 0; + // If there are some zone already present increase x until free + for (i = 0; i < (sint32)_ZoneRegions.size(); ++i) + { + if (getDocument ()->isLandscape (i)) + { + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (i)); + const string &rsZone = pBZR->getName (x, y); + if ((rsZone != STRING_OUT_OF_BOUND) && (rsZone != STRING_UNUSED)) + { + ++x; i = -1; + } + } + } + // _ZoneRegions[_ZoneRegionSelected]->setStart (x,y); + calcMask (); +} + +// --------------------------------------------------------------------------- +void CBuilderZone::unload (uint32 pos) +{ + uint32 i = 0; + if (_ZoneRegions.size() == 0) + return; + + delete _ZoneRegions[pos]; + for (i = pos; i < (_ZoneRegions.size()-1); ++i) + { + _ZoneRegions[i] = _ZoneRegions[i+1]; + } + _ZoneRegions.resize (_ZoneRegions.size()-1); + if (_ZoneRegionSelected == (sint32)_ZoneRegions.size()) + _ZoneRegionSelected = _ZoneRegions.size()-1; + calcMask (); +} + +// --------------------------------------------------------------------------- +void CBuilderZone::move (sint32 x, sint32 y) +{ + if (_ZoneRegions.size() == 0) + return; + _ZoneRegions[_ZoneRegionSelected]->move(x, y); +} + +// --------------------------------------------------------------------------- +uint32 CBuilderZone::countZones () +{ + if (_ZoneRegions.size() == 0) + return 0; + return _ZoneRegions[_ZoneRegionSelected]->countZones (); +} + +// --------------------------------------------------------------------------- +void CBuilderZone::snapshot (const char *fileName, uint sizeSource, bool grayscale) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (_ZoneRegionSelected)); + sint32 nMinX = pBZR->getMinX(); + sint32 nMaxX = pBZR->getMaxX(); + sint32 nMinY = pBZR->getMinY(); + sint32 nMaxY = pBZR->getMaxY(); + + uint width = (nMaxX - nMinX + 1)*sizeSource; + uint height = (nMaxY - nMinY + 1)*sizeSource; + snapshotCustom (fileName, width, height, false, sizeSource, grayscale); +} + +// --------------------------------------------------------------------------- +void CBuilderZone::snapshotCustom (const char *fileName, uint width, uint height, bool keepRatio, uint sizeSource, bool grayscale) +{ + if (_ZoneRegions.size() == 0) + return; + + // Some bitmaps + NLMISC::CBitmap bitmapTmp; + NLMISC::CBitmap bitmapDest; + + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (_ZoneRegionSelected)); + sint32 nMinX = pBZR->getMinX(); + sint32 nMaxX = pBZR->getMaxX(); + sint32 nMinY = pBZR->getMinY(); + sint32 nMaxY = pBZR->getMaxY(); + + uint nSizeX = (nMaxX - nMinX + 1)*sizeSource; + uint nSizeY = (nMaxY - nMinY + 1)*sizeSource; + sint x, y, j; + + // Keep ratio ? + if (keepRatio) + height = (width * nSizeY) / nSizeX; + + // Resize the bitmaps + bitmapDest.resize (nSizeX, nSizeY, NLMISC::CBitmap::RGBA); + + // white all + NLMISC::CObjectVector &rPixels = bitmapDest.getPixels(); + memset (&rPixels[0], 0xff, rPixels.size ()); + + // Copy ZoneBitmaps in the bitmap + CUV uvMin, uvMax; + ITexture *pTexture; + CZoneBankElement *pZBE; + uint8 nRot, nFlip; + + // For each tiles + for (y = nMinY; y <= nMaxY; ++y) + for (x = nMinX; x <= nMaxX; ++x) + { + const string &rsZoneName = pBZR->getName (x, y); + if ((rsZoneName == STRING_OUT_OF_BOUND) && (rsZoneName == STRING_UNUSED)) + continue; + + pZBE = _ZoneBank.getElementByZoneName (rsZoneName); + if (pZBE == NULL) + continue; + + // Get the texture + pTexture = _DataBase.getTexture (rsZoneName, pBZR->getPosX(x, y), + pBZR->getPosY(x, y), uvMin, uvMax); + + // Generate it + pTexture->generate (); + + // Be sure it is tga + pTexture->convertToType (NLMISC::CBitmap::RGBA); + + // Get rot + nRot = pBZR->getRot(x, y); + + // Get flip + nFlip = pBZR->getFlip(x, y); + + // Copy the texture + + // Dest bitmap size + uint destWidth = 1+(uint)((float)pTexture->getWidth() * (uvMax.U - uvMin.U)); + uint destHeight = 1+(uint)((float)pTexture->getHeight() * (uvMax.V - uvMin.V)); + bitmapTmp.resize (destWidth, destHeight, NLMISC::CBitmap::RGBA); + + // Source bitmap size and position + uint u = (uint)((float)pTexture->getWidth() * uvMin.U); + uint v = (uint)((float)pTexture->getHeight() * uvMin.V); + uint sourceWidth = pTexture->getWidth(); + uint sourceHeight = pTexture->getHeight(); + + // Source pointer + uint8 *srcPixels = &(pTexture->getPixels ()[0]); + + // Destination pointer + uint8 *destPixels = &(bitmapTmp.getPixels ()[0]); + + // Copy the temp bitmap + for (j = 0; j < (sint)destHeight; ++j) + // Copy the line + memcpy (destPixels+(4*j*destWidth), srcPixels + 4 * ( (v + j) * sourceWidth + u), destWidth*4); + + // Flip ? + if (nFlip) + bitmapTmp.flipH(); + + // Rot ? + while (nRot) + { + bitmapTmp.rot90CW (); + nRot--; + } + + // Resize the bitmap to normal size + if ( (bitmapTmp.getWidth () != sizeSource) || (bitmapTmp.getHeight () != sizeSource) ) + bitmapTmp.resample (sizeSource, sizeSource); + + // Copy it in the map + bitmapDest.blit (&bitmapTmp, (x-nMinX)*sizeSource, (y-nMinY)*sizeSource); + + pTexture->release (); + } + + // Resample the final bitmap + bitmapDest.resample (width, height); + bitmapDest.flipV (); + + COFile f(fileName, false, false, true); + + if (grayscale) + { + bitmapDest.convertToType (NLMISC::CBitmap::Luminance); + if (bitmapDest.writeTGA (f, 8)) + f.close(); + } + else + { + if (bitmapDest.writeTGA (f, 32)) + f.close(); + } +} + +// --------------------------------------------------------------------------- +CBuilderZone::SCacheRender::SCacheRender () +{ + Used = false; + Mat.initUnlit (); + Mat.setBlend (false); + VB.setVertexFormat (CVertexBuffer::PositionFlag|CVertexBuffer::TexCoord0Flag|CVertexBuffer::PrimaryColorFlag); +} + +// --------------------------------------------------------------------------- +void CBuilderZone::render (const NLMISC::CVector &viewMin, const NLMISC::CVector &viewMax) +{ + sint32 i, zoneSelected; + + DWORD backgroundColor = GetSysColor (COLOR_WINDOW); + + // Reset the cache + for (i = 0; i < (CACHE_RENDER_SIZE); ++i) + { + _CacheRender[i].VB.setNumVertices (0); + _CacheRender[i].PB.setNumIndexes (0); + _CacheRender[i].Used = false; + } + + // Select all blocks visible + float minx = floorf(viewMin.x/_Display->_CellSize)*_Display->_CellSize; + float miny = floorf(viewMin.y/_Display->_CellSize)*_Display->_CellSize; + float maxx = ceilf(viewMax.x/_Display->_CellSize)*_Display->_CellSize; + float maxy = ceilf(viewMax.y/_Display->_CellSize)*_Display->_CellSize; + CVector pos1, pos2, pos3, pos4; + CUV uvMin, uvMax; + sint32 x, y; + ITexture *pTexture; + + while (minx < maxx) + { + miny = floorf(viewMin.y/_Display->_CellSize)*_Display->_CellSize; + while (miny < maxy) + { + x = (sint32)floor(minx / _Display->_CellSize); + y = (sint32)floor(miny / _Display->_CellSize); + + i = 0; + string sZone = STRING_OUT_OF_BOUND; + zoneSelected = 0; + for (i = 0; i < (sint32)_ZoneRegions.size(); ++i) + { + const string &rSZone = getDocument ()->getZoneRegion (i).getName (x, y); + if ((sZone == STRING_OUT_OF_BOUND) && (rSZone == STRING_UNUSED)) + { + sZone = STRING_UNUSED; + zoneSelected = i; + } + if ((rSZone != STRING_OUT_OF_BOUND) && (rSZone != STRING_UNUSED)) + { + sZone = rSZone; + zoneSelected = i; + } + } + CZoneBankElement *pZBE = _ZoneBank.getElementByZoneName (sZone); + + if (pZBE == NULL) + pTexture = _DataBase.getTexture (sZone, 0, 0, uvMin, uvMax); + else + pTexture = _DataBase.getTexture (sZone, getDocument ()->getZoneRegion (zoneSelected).getPosX(x, y), + getDocument ()->getZoneRegion (zoneSelected).getPosY(x, y), uvMin, uvMax); + + // Look if already existing texture exists in the cache + for (i = 0; i < (CACHE_RENDER_SIZE); ++i) + if (_CacheRender[i].Used) + if (_CacheRender[i].Mat.getTexture(0) == pTexture) + break; + + if (i == (CACHE_RENDER_SIZE)) + { + // Use a new CacheRender slot + for (i = 0; i < (CACHE_RENDER_SIZE); ++i) + if (!_CacheRender[i].Used) + break; + nlassert(i<(CACHE_RENDER_SIZE)); + _CacheRender[i].Used = true; + _CacheRender[i].Mat.setTexture (0, pTexture); + } + + pos1.x = (minx-viewMin.x)/(viewMax.x-viewMin.x); + pos1.y = 0.0f; + pos1.z = (miny-viewMin.y)/(viewMax.y-viewMin.y); + + pos2.x = (_Display->_CellSize+minx-viewMin.x)/(viewMax.x-viewMin.x); + pos2.y = 0.0f; + pos2.z = (miny-viewMin.y)/(viewMax.y-viewMin.y); + + pos3.x = (_Display->_CellSize+minx-viewMin.x)/(viewMax.x-viewMin.x); + pos3.y = 0.0f; + pos3.z = (_Display->_CellSize+miny-viewMin.y)/(viewMax.y-viewMin.y); + + pos4.x = (minx-viewMin.x)/(viewMax.x-viewMin.x); + pos4.y = 0.0f; + pos4.z = (_Display->_CellSize+miny-viewMin.y)/(viewMax.y-viewMin.y); + + uint32 nBasePt = _CacheRender[i].VB.getNumVertices(); + _CacheRender[i].VB.setNumVertices (nBasePt+4); + CVertexBufferReadWrite vba; + _CacheRender[i].VB.lock (vba); + vba.setVertexCoord (nBasePt+0, pos1); + vba.setVertexCoord (nBasePt+1, pos2); + vba.setVertexCoord (nBasePt+2, pos3); + vba.setVertexCoord (nBasePt+3, pos4); + + + uint32 nBaseTri = _CacheRender[i].PB.getNumIndexes (); + _CacheRender[i].PB.setNumIndexes (nBaseTri+6); + CIndexBufferReadWrite iba; + _CacheRender[i].PB.lock (iba); + iba.setTri (nBaseTri+0, nBasePt+0, nBasePt+1, nBasePt+2); + iba.setTri (nBaseTri+3, nBasePt+0, nBasePt+2, nBasePt+3); + + if ((zoneSelected>=0)&&(zoneSelected<(sint32)_ZoneRegions.size())) + { + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (zoneSelected)); + if (pBZR->getFlip (x, y) == 1) + { + float rTmp = uvMin.U; + uvMin.U = uvMax.U; + uvMax.U = rTmp; + } + + vba.setTexCoord (nBasePt+(pBZR->getRot (x, y)+0)%4, 0, CUV(uvMin.U, uvMin.V)); + vba.setTexCoord (nBasePt+(pBZR->getRot (x, y)+1)%4, 0, CUV(uvMax.U, uvMin.V)); + vba.setTexCoord (nBasePt+(pBZR->getRot (x, y)+2)%4, 0, CUV(uvMax.U, uvMax.V)); + vba.setTexCoord (nBasePt+(pBZR->getRot (x, y)+3)%4, 0, CUV(uvMin.U, uvMax.V)); + } + else + { + vba.setTexCoord (nBasePt+0, 0, CUV(uvMin.U, uvMin.V)); + vba.setTexCoord (nBasePt+1, 0, CUV(uvMax.U, uvMin.V)); + vba.setTexCoord (nBasePt+2, 0, CUV(uvMax.U, uvMax.V)); + vba.setTexCoord (nBasePt+3, 0, CUV(uvMin.U, uvMax.V)); + } + + NLMISC::CRGBA color; + + if ((zoneSelected>=0)&&(zoneSelected<(sint32)_ZoneRegions.size())) + { + if (getZoneMask(x,y)) + color = NLMISC::CRGBA(255, 255, 255, 255); + else + color = NLMISC::CRGBA(127, 127, 127, 255); + } + else + color = NLMISC::CRGBA(255, 255, 255, 255); + + if (pTexture == NULL) + color = _Display->_BackgroundColor; + + vba.setColor (nBasePt+0, color); + vba.setColor (nBasePt+1, color); + vba.setColor (nBasePt+2, color); + vba.setColor (nBasePt+3, color); + + miny += _Display->_CellSize; + } + minx += _Display->_CellSize; + } + + //MessageBox(NULL, "CBuilderZone::render", "3", MB_OK); + + if (DontUse3D) + return; + + // Flush the cache to the screen + CMatrix mtx; + mtx.identity(); + CNELU::Driver->setupViewport (CViewport()); + CNELU::Driver->setupViewMatrix (mtx); + CNELU::Driver->setupModelMatrix (mtx); + CNELU::Driver->setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false); + + //MessageBox(NULL, "CBuilderZone::render", "4", MB_OK); + + for (i = 0; i < (CACHE_RENDER_SIZE); ++i) + if (_CacheRender[i].Used) + { + // Render with driver + CNELU::Driver->activeVertexBuffer (_CacheRender[i].VB); + CNELU::Driver->activeIndexBuffer (_CacheRender[i].PB); + CNELU::Driver->renderTriangles (_CacheRender[i].Mat, 0, _CacheRender[i].PB.getNumIndexes()/3); + } +} + +// --------------------------------------------------------------------------- +void CBuilderZone::renderTransition (const NLMISC::CVector &viewMin, const NLMISC::CVector &viewMax) +{ + // Selected ? + if (_ZoneRegionSelected != -1) + { + // Select all blocks visible + float rMinX = floorf (viewMin.x / _Display->_CellSize)*_Display->_CellSize; + float rMinY = floorf (viewMin.y / _Display->_CellSize)*_Display->_CellSize; + float rMaxX = ceilf (viewMax.x / _Display->_CellSize)*_Display->_CellSize; + float rMaxY = ceilf (viewMax.y / _Display->_CellSize)*_Display->_CellSize; + + sint32 nMinX = (sint32)floor (rMinX / _Display->_CellSize); + sint32 nMinY = (sint32)floor (rMinY / _Display->_CellSize); + sint32 nMaxX = (sint32)floor (rMaxX / _Display->_CellSize); + sint32 nMaxY = (sint32)floor (rMaxY / _Display->_CellSize); + + CVertexBuffer VB , VBSel; + CIndexBuffer PB, PBSel; + CMaterial Mat, MatSel; + + Mat.initUnlit (); + Mat.setBlend (false); + MatSel.initUnlit (); + MatSel.setBlend (false); + MatSel.setColor(NLMISC::CRGBA(255,0,0,0)); + VB.setVertexFormat (CVertexBuffer::PositionFlag); + VB.reserve ((nMaxX-nMinX+1)*(nMaxY-nMinY+1)*4*2); + VBSel.setVertexFormat (CVertexBuffer::PositionFlag); + VBSel.reserve ((nMaxX-nMinX+1)*(nMaxY-nMinY+1)*4*2); + + CVertexBufferReadWrite vba; + VB.lock (vba); + CVertexBufferReadWrite vbaSel; + VBSel.lock (vbaSel); + + sint32 nVertCount = 0; + sint32 nVertCountSel = 0; + sint32 x, y, k; + CVector worldPos, screenPos; + for (y = nMinY; y <= nMaxY; ++y) + for (x = nMinX; x <= nMaxX; ++x) + { + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (_ZoneRegionSelected)); + uint8 ceUp = pBZR->getCutEdge (x, y, 0); + uint8 ceLeft = pBZR->getCutEdge (x, y, 2); + + if ((ceUp > 0) && (ceUp < 3)) + for (k = 0; k < 2; ++k) + { + if (ceUp == 1) + worldPos.x = x * _Display->_CellSize + 3.0f * _Display->_CellSize / 12.0f; + else + worldPos.x = x * _Display->_CellSize + 7.0f * _Display->_CellSize / 12.0f; + worldPos.y = (y+1)*_Display->_CellSize + _Display->_CellSize / 12.0f; + worldPos.z = 0; + // World -> Screen conversion + screenPos.x = (worldPos.x - viewMin.x) / (viewMax.x - viewMin.x); + screenPos.y = 0.0f; + screenPos.z = (worldPos.y - viewMin.y) / (viewMax.y - viewMin.y); + if (k == 0) + { + vba.setVertexCoord (nVertCount, screenPos); + ++nVertCount; + } + else + { + vbaSel.setVertexCoord (nVertCountSel, screenPos); + ++nVertCountSel; + } + + worldPos.y = (y+1)*_Display->_CellSize - _Display->_CellSize / 12.0f; + screenPos.z = (worldPos.y - viewMin.y) / (viewMax.y - viewMin.y); + if (k == 0) + { + vba.setVertexCoord (nVertCount, screenPos); + ++nVertCount; + } + else + { + vbaSel.setVertexCoord (nVertCountSel, screenPos); + ++nVertCountSel; + } + + if (ceUp == 1) + worldPos.x = x * _Display->_CellSize + 5.0f * _Display->_CellSize / 12.0f; + else + worldPos.x = x * _Display->_CellSize + 9.0f * _Display->_CellSize / 12.0f; + screenPos.x = (worldPos.x - viewMin.x) / (viewMax.x - viewMin.x); + if (k == 0) + { + vba.setVertexCoord (nVertCount, screenPos); + ++nVertCount; + } + else + { + vbaSel.setVertexCoord (nVertCountSel, screenPos); + ++nVertCountSel; + } + + worldPos.y = (y+1)*_Display->_CellSize + _Display->_CellSize / 12.0f; + screenPos.z = (worldPos.y - viewMin.y) / (viewMax.y - viewMin.y); + if (k == 0) + { + vba.setVertexCoord (nVertCount, screenPos); + ++nVertCount; + } + else + { + vbaSel.setVertexCoord (nVertCountSel, screenPos); + ++nVertCountSel; + } + ceUp = 3 - ceUp; + } + + if ((ceLeft > 0) && (ceLeft < 3)) + for (k = 0; k < 2; ++k) + { + worldPos.x = x * _Display->_CellSize - _Display->_CellSize / 12.0f; + if (ceLeft == 1) + worldPos.y = y * _Display->_CellSize + 3.0f * _Display->_CellSize / 12.0f; + else + worldPos.y = y * _Display->_CellSize + 7.0f * _Display->_CellSize / 12.0f; + worldPos.z = 0; + // World -> Screen conversion + screenPos.x = (worldPos.x - viewMin.x) / (viewMax.x - viewMin.x); + screenPos.y = 0.0f; + screenPos.z = (worldPos.y - viewMin.y) / (viewMax.y - viewMin.y); + if (k == 0) + { + vba.setVertexCoord (nVertCount, screenPos); + ++nVertCount; + } + else + { + vbaSel.setVertexCoord (nVertCountSel, screenPos); + ++nVertCountSel; + } + + worldPos.x = x * _Display->_CellSize + _Display->_CellSize / 12.0f; + screenPos.x = (worldPos.x - viewMin.x) / (viewMax.x - viewMin.x); + if (k == 0) + { + vba.setVertexCoord (nVertCount, screenPos); + ++nVertCount; + } + else + { + vbaSel.setVertexCoord (nVertCountSel, screenPos); + ++nVertCountSel; + } + + if (ceLeft == 1) + worldPos.y = y * _Display->_CellSize + 5.0f * _Display->_CellSize / 12.0f; + else + worldPos.y = y * _Display->_CellSize + 9.0f * _Display->_CellSize / 12.0f; + screenPos.z = (worldPos.y - viewMin.y) / (viewMax.y - viewMin.y); + if (k == 0) + { + vba.setVertexCoord (nVertCount, screenPos); + ++nVertCount; + } + else + { + vbaSel.setVertexCoord (nVertCountSel, screenPos); + ++nVertCountSel; + } + + worldPos.x = x * _Display->_CellSize - _Display->_CellSize / 12.0f; + screenPos.x = (worldPos.x - viewMin.x) / (viewMax.x - viewMin.x); + if (k == 0) + { + vba.setVertexCoord (nVertCount, screenPos); + ++nVertCount; + } + else + { + vbaSel.setVertexCoord (nVertCountSel, screenPos); + ++nVertCountSel; + } + ceLeft = 3 - ceLeft; + } + } + + vba.unlock(); + VB.setNumVertices (nVertCount); + PB.setNumIndexes (nVertCount*2); + CIndexBufferReadWrite iba; + PB.lock (iba); + for (x = 0; x < (nVertCount/4); ++x) + { + iba.setLine (x*4+0, x*4+0, x*4+1); + iba.setLine (x*4+1, x*4+1, x*4+2); + iba.setLine (x*4+2, x*4+2, x*4+3); + iba.setLine (x*4+3, x*4+3, x*4+0); + } + iba.unlock(); + + vbaSel.unlock(); + VBSel.setNumVertices (nVertCountSel); + PBSel.setNumIndexes (nVertCountSel*2); + CIndexBufferReadWrite ibaSel; + PBSel.lock (ibaSel); + for (x = 0; x < (nVertCountSel/4); ++x) + { + ibaSel.setLine (x*4+0, x*4+0, x*4+1); + ibaSel.setLine (x*4+1, x*4+1, x*4+2); + ibaSel.setLine (x*4+2, x*4+2, x*4+3); + ibaSel.setLine (x*4+3, x*4+3, x*4+0); + } + ibaSel.unlock(); + + if (DontUse3D) + return; + + // Render + CMatrix mtx; + mtx.identity(); + CNELU::Driver->setupViewport (CViewport()); + CNELU::Driver->setupViewMatrix (mtx); + CNELU::Driver->setupModelMatrix (mtx); + CNELU::Driver->setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false); + CNELU::Driver->activeVertexBuffer (VB); + CNELU::Driver->activeIndexBuffer (PB); + CNELU::Driver->renderLines (Mat, 0, PB.getNumIndexes()/2); + CNELU::Driver->activeVertexBuffer (VBSel); + CNELU::Driver->activeIndexBuffer (PBSel); + CNELU::Driver->renderLines (MatSel, 0, PBSel.getNumIndexes()/2); + } +} + +// --------------------------------------------------------------------------- +void CBuilderZone::displayGrid (const NLMISC::CVector &viewMin, const NLMISC::CVector &viewMax) +{ + // Select all blocks visible + float rMinX = floorf (viewMin.x / _Display->_CellSize)*_Display->_CellSize; + float rMinY = floorf (viewMin.y / _Display->_CellSize)*_Display->_CellSize; + float rMaxX = ceilf (viewMax.x / _Display->_CellSize)*_Display->_CellSize; + float rMaxY = ceilf (viewMax.y / _Display->_CellSize)*_Display->_CellSize; + + sint32 nMinX = (sint32)floor (rMinX / _Display->_CellSize); + sint32 nMinY = (sint32)floor (rMinY / _Display->_CellSize); + sint32 nMaxX = (sint32)floor (rMaxX / _Display->_CellSize); + sint32 nMaxY = (sint32)floor (rMaxY / _Display->_CellSize); + + static vector vBars; + sint32 nBarsW = (nMaxX-nMinX)+1; + sint32 nBarsH = (nMaxY-nMinY)+1; + vBars.resize (nBarsW*nBarsH); + sint32 x, y, i, j, zoneSelected; + for (i = 0; i < nBarsW*nBarsH; ++i) + vBars[i] = 0; + + + for (y = nMinY; y <= nMaxY; ++y) + for (x = nMinX; x <= nMaxX; ++x) + { + + string sZone = STRING_OUT_OF_BOUND; + zoneSelected = 0; + for (i = 0; i < (sint32)_ZoneRegions.size(); ++i) + { + const string &rSZone = getDocument ()->getZoneRegion (i).getName (x, y); + if ((sZone == STRING_OUT_OF_BOUND) && (rSZone == STRING_UNUSED)) + { + sZone = STRING_UNUSED; + zoneSelected = i; + } + if ((rSZone != STRING_OUT_OF_BOUND) && (rSZone != STRING_UNUSED)) + { + sZone = rSZone; + zoneSelected = i; + } + } + + + //const string &sZone = _ZoneRegion.getName (x, y); + CZoneBankElement *pZBE = _ZoneBank.getElementByZoneName (sZone); + if (pZBE != NULL) + if ((pZBE->getSizeX() > 1) || (pZBE->getSizeY() > 1)) + { + const CZoneRegion *pSelected = &(getDocument ()->getZoneRegion (zoneSelected)); + sint32 sizeX = pZBE->getSizeX(), sizeY = pZBE->getSizeY(); + sint32 posX = pSelected->getPosX (x, y), posY = pSelected->getPosY (x, y); + uint8 rot = pSelected->getRot (x, y); + uint8 flip = pSelected->getFlip (x, y); + sint32 deltaX, deltaY; + + if (flip == 0) + { + switch (rot) + { + case 0: deltaX = -posX; deltaY = -posY; break; + case 1: deltaX = -(sizeY-1-posY); deltaY = -posX; break; + case 2: deltaX = -(sizeX-1-posX); deltaY = -(sizeY-1-posY); break; + case 3: deltaX = -posY; deltaY = -(sizeX-1-posX); break; + } + } + else + { + switch (rot) + { + case 0: deltaX = -(sizeX-1-posX); deltaY = -posY; break; + case 1: deltaX = -(sizeY-1-posY); deltaY = -(sizeX-1-posX); break; + case 2: deltaX = -posX; deltaY = -(sizeY-1-posY); break; + case 3: deltaX = -posY; deltaY = -posX; break; + } + } + + static SPiece sMask; + sMask.Tab.resize (sizeX*sizeY); + for(i = 0; i < sizeX*sizeY; ++i) + sMask.Tab[i] = pZBE->getMask()[i]; + sMask.w = sizeX; + sMask.h = sizeY; + sMask.rotFlip (rot, flip); + + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + if (((x+deltaX+i-nMinX)>=0) && ((x+deltaX+i-nMinX)=0) && ((y+deltaY+j-nMinY) 0) && (sMask.Tab[i-1+j*sMask.w])) + vBars[x+deltaX+i-nMinX + (y+deltaY+j-nMinY)*nBarsW] |= 1; + + if ((j > 0) && (sMask.Tab[i+(j-1)*sMask.w])) + vBars[x+deltaX+i-nMinX + (y+deltaY+j-nMinY)*nBarsW] |= 2; + } + } + } + } + + CVertexBuffer VB; + CIndexBuffer PB; + CMaterial Mat; + + Mat.initUnlit (); + Mat.setBlend (false); + VB.setVertexFormat (CVertexBuffer::PositionFlag); + VB.setNumVertices ((nBarsW+1)*(nBarsH+1)); + CVertexBufferReadWrite vba; + VB.lock (vba); + + for (y = nMinY; y <= nMaxY+1; ++y) + for (x = nMinX; x <= nMaxX+1; ++x) + { + CVector pos; + + pos.x = (x*_Display->_CellSize - viewMin.x)/(viewMax.x-viewMin.x); + pos.y = 0.0f; + pos.z = (y*_Display->_CellSize - viewMin.y)/(viewMax.y-viewMin.y); + vba.setVertexCoord (x-nMinX+(y-nMinY)*(nBarsW+1), pos); + } + + PB.setNumIndexes (nBarsW*nBarsH*2*2); + CIndexBufferReadWrite iba; + PB.lock (iba); + uint32 nNbLine = 0; + for (y = 0; y < nBarsH; ++y) + for (x = 0; x < nBarsW; ++x) + { + // Vertical Line ? + if ((vBars[x+y*nBarsW] & 1) == 0) + { + iba.setLine (nNbLine*2, x+y*(nBarsW+1), x+(y+1)*(nBarsW+1)); + ++nNbLine; + } + + // Horizontal Line ? + if ((vBars[x+y*nBarsW] & 2) == 0) + { + iba.setLine (nNbLine*2, x+y*(nBarsW+1), (x+1)+y*(nBarsW+1)); + ++nNbLine; + } + } + iba.unlock(); + PB.setNumIndexes (nNbLine*2); + + if (DontUse3D) + return; + + // Render with driver + CMatrix mtx; + mtx.identity(); + vba.unlock(); + CNELU::Driver->setupViewport (CViewport()); + CNELU::Driver->setupViewMatrix (mtx); + CNELU::Driver->setupModelMatrix (mtx); + CNELU::Driver->setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false); + CNELU::Driver->activeVertexBuffer (VB); + CNELU::Driver->activeIndexBuffer (PB); + CNELU::Driver->renderLines (Mat, 0, PB.getNumIndexes()/2); + +} + +// --------------------------------------------------------------------------- +void CBuilderZone::add (const CVector &worldPos) +{ + sint32 x = (sint32)floor (worldPos.x / _Display->_CellSize); + sint32 y = (sint32)floor (worldPos.y / _Display->_CellSize); + uint8 rot, flip; + + if (_ZoneRegions.size() == 0) + return; + + if (_RandomSelection) + { + if (_CurrentSelection.size() > 0) + { + uint32 nSel = (uint32)(NLMISC::frand (1.0) * _CurrentSelection.size()); + NLMISC::clamp (nSel, (uint32)0, (uint32)(_CurrentSelection.size()-1)); + _CurSelectedZone = nSel; + } + } + if (_CycleSelection) + { + _CurSelectedZone = _ApplyCycleSelection; + _ApplyCycleSelection++; + _ApplyCycleSelection = _ApplyCycleSelection%_CurrentSelection.size(); + } + + if (_ApplyRotType == 1) + { + uint32 nSel = (uint32)(NLMISC::frand (1.0) * 4); + NLMISC::clamp (nSel, (uint32)0, (uint32)3); + rot = (uint8)nSel; + } + else if (_ApplyRotType == 0) + { + rot = _ApplyRot; + } + else if (_ApplyRotType == 2) + { + rot = _ApplyRotCycle; + _ApplyRotCycle++; + _ApplyRotCycle = _ApplyRotCycle%4; + } + + + if (_ApplyFlipType == 1) + { + uint32 nSel = (uint32)(NLMISC::frand (1.0) * 2); + NLMISC::clamp (nSel, (uint32)0, (uint32)1); + flip = (uint8)nSel; + } + else if (_ApplyFlipType == 0) + { + flip = _ApplyFlip; + } + else if (_ApplyFlipType == 2) + { + flip = _ApplyFlipCycle; + _ApplyFlipCycle++; + _ApplyFlipCycle = _ApplyFlipCycle%2; + } + + if ((_CurSelectedZone >= 0)&&(_CurSelectedZone <= ((sint32)_CurrentSelection.size()-1))) + { + CZoneBankElement *pZBE = _CurrentSelection[_CurSelectedZone]; + string error; + _ZoneRegions[_ZoneRegionSelected]->init (&_ZoneBank, this, error); + + if (_Force) + { + _ZoneRegions[_ZoneRegionSelected]->addForce (x, y, rot, flip, pZBE); + } + else + { + if (_NotPropagate) + _ZoneRegions[_ZoneRegionSelected]->addNotPropagate (x, y, rot, flip, pZBE); + else + _ZoneRegions[_ZoneRegionSelected]->add (x, y, rot, flip, pZBE); + } + } +} + +// --------------------------------------------------------------------------- +void CBuilderZone::addTransition (const NLMISC::CVector &worldPos) +{ + sint32 x = (sint32)floor (worldPos.x / _Display->_CellSize); + sint32 y = (sint32)floor (worldPos.y / _Display->_CellSize); + sint32 k; + + if (_ZoneRegions.size() == 0) + return; + + // Detect if we are in a transition square to switch + CBuilderZoneRegion *pBZR2 = _ZoneRegions[_ZoneRegionSelected]; + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (_ZoneRegionSelected)); + bool bCutEdgeTouched = false; + for (uint8 transPos = 0; transPos < 4; ++transPos) + { + uint ce = pBZR->getCutEdge (x, y, transPos); + + if ((ce > 0) && (ce < 3)) + for (k = 0; k < 2; ++k) + { + float xTrans, yTrans; + + if ((transPos == 0) || (transPos == 1)) + { + if (ce == 1) + xTrans = _Display->_CellSize / 3.0f; + else + xTrans = 2.0f * _Display->_CellSize / 3.0f; + } + else + { + if (transPos == 2) + xTrans = 0; + else + xTrans = _Display->_CellSize; + } + xTrans += x * _Display->_CellSize; + + if ((transPos == 2) || (transPos == 3)) + { + if (ce == 1) + yTrans = _Display->_CellSize / 3.0f; + else + yTrans = 2.0f * _Display->_CellSize / 3.0f; + } + else + { + if (transPos == 1) + yTrans = 0; + else + yTrans = _Display->_CellSize; + } + yTrans += y * _Display->_CellSize; + + if ((worldPos.x >= (xTrans-_Display->_CellSize/12.0f)) && (worldPos.x <= (xTrans+_Display->_CellSize/12.0f)) && + (worldPos.y >= (yTrans-_Display->_CellSize/12.0f)) && (worldPos.y <= (yTrans+_Display->_CellSize/12.0f))) + { + pBZR2->invertCutEdge (x, y, transPos); + bCutEdgeTouched = true; + } + ce = 3 - ce; + } + } + + // If not clicked to change the cutEdge so the user want to change the transition + if (!bCutEdgeTouched) + { + pBZR2->cycleTransition (x, y); + } +} + +// --------------------------------------------------------------------------- +void CBuilderZone::del (const CVector &worldPos) +{ + sint32 x = (sint32)floor (worldPos.x / _Display->_CellSize); + sint32 y = (sint32)floor (worldPos.y / _Display->_CellSize); + + if (_ZoneRegions.size() == 0) + return; + + CBuilderZoneRegion *pBZR = _ZoneRegions[_ZoneRegionSelected]; + string error; + pBZR->init (&_ZoneBank, this, error); + pBZR->del (x, y); +} + +// --------------------------------------------------------------------------- +bool CBuilderZone::initZoneBank (const string &sPathName) +{ + char sDirBackup[512]; + GetCurrentDirectory (512, sDirBackup); + SetCurrentDirectory (sPathName.c_str()); + WIN32_FIND_DATA findData; + HANDLE hFind; + hFind = FindFirstFile ("*.ligozone", &findData); + + while (hFind != INVALID_HANDLE_VALUE) + { + // If the name of the file is not . or .. then its a valid entry in the DataBase + if (!((strcmp (findData.cFileName, ".") == 0) || (strcmp (findData.cFileName, "..") == 0))) + { + string error; + if (!_ZoneBank.addElement (findData.cFileName, error)) + theApp.errorMessage (error.c_str()); + } + if (FindNextFile (hFind, &findData) == 0) + break; + } + SetCurrentDirectory (sDirBackup); + return true; +} + +// --------------------------------------------------------------------------- + +uint32 CBuilderZone::getNbZoneRegion () +{ + return _ZoneRegions.size (); +} + +// --------------------------------------------------------------------------- + +string CBuilderZone::getZoneName (sint32 x, sint32 y) +{ + string sRet = STRING_UNUSED; + uint32 nNbRegion = _ZoneRegions.size(); + for (uint32 i = 0; i < nNbRegion; ++i) + { + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (i)); + if ((x < pBZR->getMinX())||(x > pBZR->getMaxX())||(y < pBZR->getMinY())||(y > pBZR->getMaxY())) + continue; + if (pBZR->getName(x, y) != STRING_UNUSED) + { + sRet = pBZR->getName(x, y); + return sRet; + } + } + sRet = ""; + return sRet; +} + +// --------------------------------------------------------------------------- +uint8 CBuilderZone::getRot (sint32 x, sint32 y) +{ + uint8 sRet = 0; + uint32 nNbRegion = _ZoneRegions.size(); + for (uint32 i = 0; i < nNbRegion; ++i) + { + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (i)); + if ((x < pBZR->getMinX())||(x > pBZR->getMaxX())||(y < pBZR->getMinY())||(y > pBZR->getMaxY())) + continue; + if (pBZR->getName(x, y) != STRING_UNUSED) + { + sRet = pBZR->getRot(x, y); + return sRet; + } + } + sRet = 0; + return sRet; +} + +// --------------------------------------------------------------------------- +uint8 CBuilderZone::getFlip (sint32 x, sint32 y) +{ + uint8 sRet = 0; + uint32 nNbRegion = _ZoneRegions.size(); + for (uint32 i = 0; i < nNbRegion; ++i) + { + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (i)); + if ((x < pBZR->getMinX())||(x > pBZR->getMaxX())||(y < pBZR->getMinY())||(y > pBZR->getMaxY())) + continue; + if (pBZR->getName(x, y) != STRING_UNUSED) + { + sRet = pBZR->getFlip(x, y); + return sRet; + } + } + sRet = 0; + return sRet; +} + +// --------------------------------------------------------------------------- +CBuilderZoneRegion* CBuilderZone::getPtrCurZoneRegion () +{ + if (_ZoneRegions.size() == 0) + return NULL; + return _ZoneRegions[_ZoneRegionSelected]; +} + +// --------------------------------------------------------------------------- +uint32 CBuilderZone::getCurZoneRegion () +{ + return _ZoneRegionSelected; +} + +// --------------------------------------------------------------------------- +void CBuilderZone::setCurZoneRegion (uint32 sel) +{ + _ZoneRegionSelected = sel; + calcMask(); +} + +// --------------------------------------------------------------------------- +bool CBuilderZone::getZoneMask (sint32 x, sint32 y) +{ + if ((x < _MinX) || (x > _MaxX) || + (y < _MinY) || (y > _MaxY)) + { + return true; + } + else + { + return _ZoneMask[(x-_MinX)+(y-_MinY)*(1+_MaxX-_MinX)]; + } +} + +// --------------------------------------------------------------------------- +/* +void CBuilderZone::generate (sint32 nMinX, sint32 nMinY, sint32 nMaxX, sint32 nMaxY, + sint32 nZoneBaseX, sint32 nZoneBaseY, const char *MaterialString) +{ + if ((nMinX > nMaxX) || (nMinY > nMaxY)) + return; + + for (sint32 j = nMinY; j <= nMaxY; ++j) + for (sint32 i = nMinX; i <= nMaxX; ++i) + { + // Generate zone name + string ZoneName = "converted-"+CExport::getZoneNameFromXY (i, j); + ZoneName = NLMISC::strlwr (ZoneName); + CZoneBankElement *pZBE = _ZoneBank.getElementByZoneName (ZoneName); + if (pZBE != NULL) + { + _ZoneRegions[_ZoneRegionSelected]->init (&_ZoneBank, this); + _ZoneRegions[_ZoneRegionSelected]->add (i, j, 0, 0, pZBE); + } + } +} */ \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone.h index 9329d5699..105f40a94 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone.h @@ -1,226 +1,226 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// This class is interface between all that is displayed in -// display/tools view and the game core - -#ifndef BUILDERZONE_H -#define BUILDERZONE_H - -// *************************************************************************** - -#include "builder_zone_region.h" - -#include -#include - -// *************************************************************************** - -class CDisplay; -class CToolsZone; - -namespace NL3D -{ - class CVertexBuffer; - class CIndexBuffer; - class CTextureFile; - class CTextureMem; - class ITexture; -} - -#define CACHE_RENDER_SIZE (64+2) - -// *************************************************************************** -// CDataBase contains the image database for Nel and Windows -// A big texture (called CacheTexture) contains all zone (called SCacheZone) -// There are 64 cache texture of 1024x1024 (it should be enough) -// An element is composed of zones (the number of zones is equal to the number -// of true in the mask (the mask is in the zone bank)) - -class CDataBase -{ - struct SCacheTexture - { - bool Enabled; - NLMISC::CSmartPtr Texture; - std::vector FreePlace; - std::vector PtrMem; - - SCacheTexture(); - bool isFull(); - }; - - struct SCacheZone - { - NL3D::CTextureMem *CacheTexture; - NLMISC::CUV PosUV; - uint8 PosX, PosY; - }; - - struct SElement - { - uint8 SizeX, SizeY; - std::vector ZonePieces; - CBitmap *WinBitmap; - }; - -private: - - CBitmap *convertToWin (NLMISC::CBitmap *pBitmap); - NL3D::CTextureFile *loadTexture (const std::string &fileName); - NLMISC::CBitmap *loadBitmap (const std::string &fileName); - -private: - - SCacheTexture _CacheTexture[64]; - std::map _ZoneDBmap; - NLMISC::CSmartPtr _UnusedTexture; - - uint32 _RefSizeX, _RefSizeY; - uint32 _RefCacheTextureSizeX, _RefCacheTextureSizeY; - uint32 _RefCacheTextureNbEltX, _RefCacheTextureNbEltY; - -public: - - CDataBase (uint bitmapSize); - ~CDataBase(); - - bool initFromPath (const std::string &Path); - void reset (); - bool init (const std::string &Path, NLLIGO::CZoneBank &zb); - - CBitmap *getBitmap (const std::string &ZoneName); - NL3D::ITexture *getTexture (const std::string &ZoneName, sint32 nPosX, sint32 nPosY, - NLMISC::CUV &retUVmin, NLMISC::CUV &retUVmax); -}; - -// *************************************************************************** -// CBuilderZone contains all the shared data between the tools and the engine -// ZoneBank contains the macro zones that is composed of several zones plus a mask -// DataBase contains the graphics for the zones -class CBuilderZone -{ -public: - std::string _LastPathName; - - NLLIGO::CZoneBank _ZoneBank; - - CDataBase _DataBase; - - std::vector _ZoneRegions; - - sint32 _ZoneRegionSelected; - - sint32 _MinX, _MaxX, _MinY, _MaxY; - std::vector _ZoneMask; - - CDisplay *_Display; - CToolsZone *_ToolsZone; - -public: - - std::string _FilterType1, _FilterValue1; - std::string _FilterType2, _FilterValue2; - uint8 _FilterOperator2; // 0 -> AND, 1 -> OR - std::string _FilterType3, _FilterValue3; - uint8 _FilterOperator3; // 0 -> AND, 1 -> OR - std::string _FilterType4, _FilterValue4; - uint8 _FilterOperator4; // 0 -> AND, 1 -> OR - - bool _RandomSelection; - bool _CycleSelection; - uint8 _ApplyCycleSelection; - sint32 _CurSelectedZone; - - bool _NotPropagate; - bool _Force; - - uint8 _ApplyRot; - uint8 _ApplyRotType; // (0-Normal)(1-Random)(2-Cycle) - uint8 _ApplyRotCycle; - - uint8 _ApplyFlip; - uint8 _ApplyFlipType; // (0-Normal)(1-Random)(2-Cycle) - uint8 _ApplyFlipCycle; - - std::vector _CurrentSelection; - -private: - - void calcMask(); - bool initZoneBank (const std::string &Path); - -public: - - CBuilderZone (uint bitmapSize); - - bool init (const std::string &sPath, bool bMakeAZone, CDisplay *display); - - void setToolsZone (CToolsZone *pTool); - void updateToolsZone (); - bool refresh (); // Full name - void newZone (bool bDisplay=true); - void unload (uint32 i); - void move (sint32 x, sint32 y); - uint32 countZones (); - void snapshot (const char *fileName, uint sizeSource, bool grayscale); - void snapshotCustom (const char *fileName, uint width, uint height, bool keepRatio, uint sizeSource, bool grayscale); - - void add (const NLMISC::CVector &worldPos); - void addTransition (const NLMISC::CVector &worldPos); - void del (const NLMISC::CVector &worldPos); - - // Accessors - NLLIGO::CZoneBank &getZoneBank () { return _ZoneBank; } - - void render (const NLMISC::CVector &viewMin, const NLMISC::CVector &viewMax); - void renderTransition (const NLMISC::CVector &viewMin, const NLMISC::CVector &viewMax); - void displayGrid (const NLMISC::CVector &viewMin, const NLMISC::CVector &viewMax); - - uint32 getNbZoneRegion (); - std::string getZoneName (sint32 x, sint32 y); - - uint8 getRot (sint32 x, sint32 y); - uint8 getFlip (sint32 x, sint32 y); - CBuilderZoneRegion* getPtrCurZoneRegion (); - uint32 getCurZoneRegion (); - void setCurZoneRegion (uint32 i); - bool getZoneMask (sint32 x, sint32 y); - - /* void generate (sint32 nMinX, sint32 nMinY, sint32 nMaxX, sint32 nMaxY, - sint32 nZoneBaseX, sint32 nZoneBaseY, const char *MaterialString); */ - -private: - - // SCacheRender is a simple structure to store triangles for each texture in the scene - struct SCacheRender - { - bool Used; - NL3D::CVertexBuffer VB; - NL3D::CIndexBuffer PB; - NL3D::CMaterial Mat; - - SCacheRender(); - }; - - // There are one CacheRender per cacheTexture + texture unused and NULL (no texture) - SCacheRender _CacheRender[CACHE_RENDER_SIZE]; - -}; - -// *************************************************************************** - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// This class is interface between all that is displayed in +// display/tools view and the game core + +#ifndef BUILDERZONE_H +#define BUILDERZONE_H + +// *************************************************************************** + +#include "builder_zone_region.h" + +#include +#include + +// *************************************************************************** + +class CDisplay; +class CToolsZone; + +namespace NL3D +{ + class CVertexBuffer; + class CIndexBuffer; + class CTextureFile; + class CTextureMem; + class ITexture; +} + +#define CACHE_RENDER_SIZE (64+2) + +// *************************************************************************** +// CDataBase contains the image database for Nel and Windows +// A big texture (called CacheTexture) contains all zone (called SCacheZone) +// There are 64 cache texture of 1024x1024 (it should be enough) +// An element is composed of zones (the number of zones is equal to the number +// of true in the mask (the mask is in the zone bank)) + +class CDataBase +{ + struct SCacheTexture + { + bool Enabled; + NLMISC::CSmartPtr Texture; + std::vector FreePlace; + std::vector PtrMem; + + SCacheTexture(); + bool isFull(); + }; + + struct SCacheZone + { + NL3D::CTextureMem *CacheTexture; + NLMISC::CUV PosUV; + uint8 PosX, PosY; + }; + + struct SElement + { + uint8 SizeX, SizeY; + std::vector ZonePieces; + CBitmap *WinBitmap; + }; + +private: + + CBitmap *convertToWin (NLMISC::CBitmap *pBitmap); + NL3D::CTextureFile *loadTexture (const std::string &fileName); + NLMISC::CBitmap *loadBitmap (const std::string &fileName); + +private: + + SCacheTexture _CacheTexture[64]; + std::map _ZoneDBmap; + NLMISC::CSmartPtr _UnusedTexture; + + uint32 _RefSizeX, _RefSizeY; + uint32 _RefCacheTextureSizeX, _RefCacheTextureSizeY; + uint32 _RefCacheTextureNbEltX, _RefCacheTextureNbEltY; + +public: + + CDataBase (uint bitmapSize); + ~CDataBase(); + + bool initFromPath (const std::string &Path); + void reset (); + bool init (const std::string &Path, NLLIGO::CZoneBank &zb); + + CBitmap *getBitmap (const std::string &ZoneName); + NL3D::ITexture *getTexture (const std::string &ZoneName, sint32 nPosX, sint32 nPosY, + NLMISC::CUV &retUVmin, NLMISC::CUV &retUVmax); +}; + +// *************************************************************************** +// CBuilderZone contains all the shared data between the tools and the engine +// ZoneBank contains the macro zones that is composed of several zones plus a mask +// DataBase contains the graphics for the zones +class CBuilderZone +{ +public: + std::string _LastPathName; + + NLLIGO::CZoneBank _ZoneBank; + + CDataBase _DataBase; + + std::vector _ZoneRegions; + + sint32 _ZoneRegionSelected; + + sint32 _MinX, _MaxX, _MinY, _MaxY; + std::vector _ZoneMask; + + CDisplay *_Display; + CToolsZone *_ToolsZone; + +public: + + std::string _FilterType1, _FilterValue1; + std::string _FilterType2, _FilterValue2; + uint8 _FilterOperator2; // 0 -> AND, 1 -> OR + std::string _FilterType3, _FilterValue3; + uint8 _FilterOperator3; // 0 -> AND, 1 -> OR + std::string _FilterType4, _FilterValue4; + uint8 _FilterOperator4; // 0 -> AND, 1 -> OR + + bool _RandomSelection; + bool _CycleSelection; + uint8 _ApplyCycleSelection; + sint32 _CurSelectedZone; + + bool _NotPropagate; + bool _Force; + + uint8 _ApplyRot; + uint8 _ApplyRotType; // (0-Normal)(1-Random)(2-Cycle) + uint8 _ApplyRotCycle; + + uint8 _ApplyFlip; + uint8 _ApplyFlipType; // (0-Normal)(1-Random)(2-Cycle) + uint8 _ApplyFlipCycle; + + std::vector _CurrentSelection; + +private: + + void calcMask(); + bool initZoneBank (const std::string &Path); + +public: + + CBuilderZone (uint bitmapSize); + + bool init (const std::string &sPath, bool bMakeAZone, CDisplay *display); + + void setToolsZone (CToolsZone *pTool); + void updateToolsZone (); + bool refresh (); // Full name + void newZone (bool bDisplay=true); + void unload (uint32 i); + void move (sint32 x, sint32 y); + uint32 countZones (); + void snapshot (const char *fileName, uint sizeSource, bool grayscale); + void snapshotCustom (const char *fileName, uint width, uint height, bool keepRatio, uint sizeSource, bool grayscale); + + void add (const NLMISC::CVector &worldPos); + void addTransition (const NLMISC::CVector &worldPos); + void del (const NLMISC::CVector &worldPos); + + // Accessors + NLLIGO::CZoneBank &getZoneBank () { return _ZoneBank; } + + void render (const NLMISC::CVector &viewMin, const NLMISC::CVector &viewMax); + void renderTransition (const NLMISC::CVector &viewMin, const NLMISC::CVector &viewMax); + void displayGrid (const NLMISC::CVector &viewMin, const NLMISC::CVector &viewMax); + + uint32 getNbZoneRegion (); + std::string getZoneName (sint32 x, sint32 y); + + uint8 getRot (sint32 x, sint32 y); + uint8 getFlip (sint32 x, sint32 y); + CBuilderZoneRegion* getPtrCurZoneRegion (); + uint32 getCurZoneRegion (); + void setCurZoneRegion (uint32 i); + bool getZoneMask (sint32 x, sint32 y); + + /* void generate (sint32 nMinX, sint32 nMinY, sint32 nMaxX, sint32 nMaxY, + sint32 nZoneBaseX, sint32 nZoneBaseY, const char *MaterialString); */ + +private: + + // SCacheRender is a simple structure to store triangles for each texture in the scene + struct SCacheRender + { + bool Used; + NL3D::CVertexBuffer VB; + NL3D::CIndexBuffer PB; + NL3D::CMaterial Mat; + + SCacheRender(); + }; + + // There are one CacheRender per cacheTexture + texture unused and NULL (no texture) + SCacheRender _CacheRender[CACHE_RENDER_SIZE]; + +}; + +// *************************************************************************** + #endif // BUILDERZONE_H \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone_region.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone_region.cpp index 1c59b47da..415e00f70 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone_region.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone_region.cpp @@ -1,2093 +1,2093 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" - -#include "action.h" -#include "world_editor_doc.h" -#include "builder_zone_region.h" -#include "builder_zone.h" - -#include - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; - -// *************************************************************************** -// CBuilderZoneRegion -// *************************************************************************** - - -// --------------------------------------------------------------------------- -CBuilderZoneRegion::CBuilderZoneRegion (uint regionId) -{ - _ZeBank = NULL; - RegionId = regionId; -} - -// --------------------------------------------------------------------------- -bool CBuilderZoneRegion::init (NLLIGO::CZoneBank *pBank, CBuilderZone *pBuilder, string &error) -{ - if (_ZeBank != NULL) - return true; - _ZeBank = pBank; - _Builder = pBuilder; - // Build the material tree - uint32 i, j, k; - SMatNode mn; - vector AllValues; - _ZeBank->getCategoryValues ("material", AllValues); - for (i = 0; i < AllValues.size(); ++i) - { - mn.Name = AllValues[i]; - _MatTree.push_back (mn); - } - // Link between materials - AllValues.clear (); - _ZeBank->getCategoryValues ("transname", AllValues); - for (i = 0; i < AllValues.size(); ++i) - { - // Get the 2 materials linked together - string matAstr, matBstr; - for (j = 0; j < AllValues[i].size(); ++j) - { - if (AllValues[i][j] == '-') - break; - else - matAstr += AllValues[i][j]; - } - ++j; - for (; j < AllValues[i].size(); ++j) - matBstr += AllValues[i][j]; - - // Find matA - for (j = 0; j < _MatTree.size(); ++j) - if (_MatTree[j].Name == matAstr) - break; - - if (j < _MatTree.size()) - { - // Find matB - for (k = 0; k < _MatTree.size(); ++k) - if (_MatTree[k].Name == matBstr) - break; - - if (k < _MatTree.size()) - { - _MatTree[j].Arcs.push_back (k); // Add a ref to matB in node matA - _MatTree[k].Arcs.push_back (j); // Add a ref to matA in node matB - } - } - } - - // DEBUG - // DEBUG - // DEBUG -/* - _MatTree.clear(); - _MatTree.resize (6); - _MatTree[0].Name = "A"; - _MatTree[0].Arcs.resize (2); - _MatTree[0].Arcs[0] = 1; - _MatTree[0].Arcs[1] = 2; - - _MatTree[1].Name = "F"; - _MatTree[1].Arcs.resize (3); - _MatTree[1].Arcs[0] = 0; - _MatTree[1].Arcs[1] = 4; - _MatTree[1].Arcs[2] = 5; - - _MatTree[2].Name = "B"; - _MatTree[2].Arcs.resize (3); - _MatTree[2].Arcs[0] = 0; - _MatTree[2].Arcs[1] = 3; - _MatTree[2].Arcs[2] = 5; - - _MatTree[3].Name = "C"; - _MatTree[3].Arcs.resize (1); - _MatTree[3].Arcs[0] = 2; - - _MatTree[4].Name = "Z"; - _MatTree[4].Arcs.resize (1); - _MatTree[4].Arcs[0] = 1; - - _MatTree[5].Name = "E"; - _MatTree[5].Arcs.resize (2); - _MatTree[5].Arcs[0] = 1; - _MatTree[5].Arcs[1] = 2; - - vector vRetPath; - tryPath(0, 3, vRetPath); - - uint32 ij; - ++ij; - ij = 0; -*/ - // DEBUG - // DEBUG - // DEBUG - return true; -} - -// --------------------------------------------------------------------------- -class CToUpdate -{ - struct SElt - { - sint32 x, y; - string MatPut; // Material put into the cell to update - CBuilderZoneRegion *BZR; - }; - - vector Elts; - -public: - - void add (CBuilderZoneRegion* pBZR, sint32 x, sint32 y, const string &MatName) - { - bool bFound = false; - for (uint32 m = 0; m < Elts.size(); ++m) - if ((Elts[m].x == x) && (Elts[m].y == y)) - { - bFound = true; - break; - } - if (!bFound) - { - SElt tuTmp; - tuTmp.x = x; - tuTmp.y = y; - tuTmp.MatPut = MatName; - tuTmp.BZR = pBZR; - Elts.push_back (tuTmp); - } - } - - void del (sint32 x, sint32 y) - { - bool bFound = false; - uint32 m; - for (m = 0; m < Elts.size(); ++m) - if ((Elts[m].x == x) && (Elts[m].y == y)) - { - bFound = true; - break; - } - if (bFound) - { - for (; m < Elts.size()-1; ++m) - Elts[m] = Elts[m+1]; - Elts.resize (Elts.size()-1); - } - } - - uint32 size() - { - return Elts.size(); - } - - sint32 getX (uint32 m) - { - return Elts[m].x; - } - - sint32 getY (uint32 m) - { - return Elts[m].y; - } - - CBuilderZoneRegion* getBZR (uint32 m) - { - return Elts[m].BZR; - } - - const string& getMat (uint32 m) - { - return Elts[m].MatPut; - } -}; - -// --------------------------------------------------------------------------- -void CBuilderZoneRegion::add (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt) -{ - sint32 sizeX = pElt->getSizeX(), sizeY = pElt->getSizeY(); - sint32 i, j; - SPiece sMask, sPosX, sPosY; - CToUpdate tUpdate; // Transition to update - - if (!_Builder->getZoneMask (x,y)) - return; - - if (pElt->getCategory("transname") != STRING_NO_CAT_TYPE) - { - addTransition (x, y, nRot, nFlip, pElt); - return; - } - - // Create the mask in the good rotation and flip - sMask.Tab.resize (sizeX*sizeY); - sPosX.Tab.resize (sizeX*sizeY); - sPosY.Tab.resize (sizeX*sizeY); - - for (j = 0; j < sizeY; ++j) - for (i = 0; i < sizeX; ++i) - { - sPosX.Tab[i+j*sizeX] = (uint8)i; - sPosY.Tab[i+j*sizeX] = (uint8)j; - sMask.Tab[i+j*sizeX] = pElt->getMask()[i+j*sizeX]; - } - sPosX.w = sPosY.w = sMask.w = sizeX; - sPosX.h = sPosY.h = sMask.h = sizeY; - sMask.rotFlip (nRot, nFlip); - sPosX.rotFlip (nRot, nFlip); - sPosY.rotFlip (nRot, nFlip); - - // Test if the pieces can be put (due to mask) - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - if (_Builder->getZoneMask(x+i, y+j) == false) - return; - } - - // Delete all pieces that are under the mask - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - del (x+i, y+j, true, &tUpdate); - } - - // Delete all around all material that are not from the same as us - const string &CurMat = pElt->getCategory ("material"); - - if (CurMat != STRING_NO_CAT_TYPE) - { // This element is a valid material - // Place the piece - const string &EltName = pElt->getName (); - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - set (x+i, y+j, sPosX.Tab[i+j*sPosX.w], sPosY.Tab[i+j*sPosY.w], EltName); - setRot (x+i, y+j, nRot); - setFlip (x+i, y+j, nFlip); - } - - // Put all transitions between different materials - putTransitions (x, y, sMask, CurMat, &tUpdate); - - // Place the piece - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - set (x+i, y+j, sPosX.Tab[i+j*sPosX.w], sPosY.Tab[i+j*sPosY.w], EltName); - setRot (x+i, y+j, nRot); - setFlip (x+i, y+j, nFlip); - } - } -} - -// --------------------------------------------------------------------------- -void CBuilderZoneRegion::invertCutEdge (sint32 x, sint32 y, uint8 cePos) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - if ((x < pBZR->getMinX ()) || (x > pBZR->getMaxX ()) || - (y < pBZR->getMinY ()) || (y > pBZR->getMaxY ())) - return; - CZoneBankElement *pElt = _ZeBank->getElementByZoneName (pBZR->getName (x, y)); - if (pElt == NULL) - return; - if (pElt->getCategory("transname") == STRING_NO_CAT_TYPE) - return; - - CDatabaseLocator zonePos (RegionId, x, y); - CLigoData dataZonePos; - getDocument ()->getLigoData (dataZonePos, zonePos); - if (dataZonePos.SharingCutEdges[cePos] != 3 - dataZonePos.SharingCutEdges[cePos]) - { - dataZonePos.SharingCutEdges[cePos] = 3 - dataZonePos.SharingCutEdges[cePos]; - getDocument ()->addModification (new CActionLigoTile (dataZonePos, zonePos)); - } - updateTrans (x, y); - - // If the transition number is not the same propagate the change - // Propagate where the edge is cut (1/3 or 2/3) and update the transition - if (cePos == 2) - if (dataZonePos.SharingMatNames[0] != dataZonePos.SharingMatNames[2]) - { - if (x > pBZR->getMinX ()) - { // [x-1][y].right = [x][y].left - - // _Zones[(x-1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[3] = dataZonePos.SharingCutEdges[2]; - CDatabaseLocator zoneTemp (RegionId, x-1, y); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - if (dataZoneTemp.SharingCutEdges[3] != dataZonePos.SharingCutEdges[2]) - { - dataZoneTemp.SharingCutEdges[3] = dataZonePos.SharingCutEdges[2]; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - } - updateTrans (x-1, y); - } - if (cePos == 3) - if (dataZonePos.SharingMatNames[1] != dataZonePos.SharingMatNames[3]) - { - if (x < pBZR->getMaxX ()) - { // [x+1][y].left = [x][y].right - - CDatabaseLocator zoneTemp (RegionId, x+1, y); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - if (dataZoneTemp.SharingCutEdges[2] != dataZonePos.SharingCutEdges[3]) - { - dataZoneTemp.SharingCutEdges[2] = dataZonePos.SharingCutEdges[3]; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - } - updateTrans (x+1, y); - } - if (cePos == 1) - if (dataZonePos.SharingMatNames[0] != dataZonePos.SharingMatNames[1]) - { - if (y > pBZR->getMinY ()) - { // [x][y-1].up = [x][y].down - - CDatabaseLocator zoneTemp (RegionId, x, y-1); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - if (dataZoneTemp.SharingCutEdges[0] != dataZonePos.SharingCutEdges[1]) - { - dataZoneTemp.SharingCutEdges[0] = dataZonePos.SharingCutEdges[1]; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - } - updateTrans (x, y-1); - } - if (cePos == 0) - if (dataZonePos.SharingMatNames[2] != dataZonePos.SharingMatNames[3]) - { - if (y < pBZR->getMaxY ()) - { // [x][y+1].down = [x][y].up - - CDatabaseLocator zoneTemp (RegionId, x, y+1); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - if (dataZoneTemp.SharingCutEdges[1] != dataZonePos.SharingCutEdges[0]) - { - dataZoneTemp.SharingCutEdges[1] = dataZonePos.SharingCutEdges[0]; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - } - updateTrans (x, y+1); - } -} - -// --------------------------------------------------------------------------- -void CBuilderZoneRegion::cycleTransition (sint32 x, sint32 y) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - if ((x < pBZR->getMinX ()) || (x > pBZR->getMaxX ()) || - (y < pBZR->getMinY ()) || (y > pBZR->getMaxY ())) - return; - /* todo remove - sint32 stride = (1 + pBZR->getMaxX () - pBZR->getMinX ()); - sint32 zonePos = (x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride; - */ - CZoneBankElement *pElt = _ZeBank->getElementByZoneName (pBZR->getName (x, y)); - if (pElt == NULL) - return; - if (pElt->getCategory("transname") == STRING_NO_CAT_TYPE) - return; - - // \todo trap -> choose the good transition in function of the transition under the current location - // Choose the next possible transition if not the same as the first one - // Choose among all transition of the same number - - updateTrans (x, y); -} - -// --------------------------------------------------------------------------- -bool CBuilderZoneRegion::addNotPropagate (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - sint32 sizeX = pElt->getSizeX(), sizeY = pElt->getSizeY(); - sint32 i, j; - SPiece sMask, sPosX, sPosY; - CToUpdate tUpdate; // Transition to update - - if (!_Builder->getZoneMask (x,y)) - return false; - - if (pElt->getCategory("transname") != STRING_NO_CAT_TYPE) - { - addTransition (x, y, nRot, nFlip, pElt); - return true; - } - - // Create the mask in the good rotation and flip - sMask.Tab.resize (sizeX*sizeY); - sPosX.Tab.resize (sizeX*sizeY); - sPosY.Tab.resize (sizeX*sizeY); - - for (j = 0; j < sizeY; ++j) - for (i = 0; i < sizeX; ++i) - { - sPosX.Tab[i+j*sizeX] = (uint8)i; - sPosY.Tab[i+j*sizeX] = (uint8)j; - sMask.Tab[i+j*sizeX] = pElt->getMask()[i+j*sizeX]; - } - sPosX.w = sPosY.w = sMask.w = sizeX; - sPosX.h = sPosY.h = sMask.h = sizeY; - sMask.rotFlip (nRot, nFlip); - sPosX.rotFlip (nRot, nFlip); - sPosY.rotFlip (nRot, nFlip); - - // Test if the pieces can be put (due to mask) - sint32 stride = (1 + pBZR->getMaxX () - pBZR->getMinX ()); - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - if (_Builder->getZoneMask(x+i, y+j) == false) - return false; - if (((x+i) < pBZR->getMinX ()) || ((x+i) > pBZR->getMaxX ()) || - ((y+j) < pBZR->getMinY ()) || ((y+j) > pBZR->getMaxY ())) - return false; - CZoneBankElement *pEltUnder = _ZeBank->getElementByZoneName(pBZR->getName (x+i, y+j)); - if (pEltUnder == NULL) - return false; - if (pEltUnder->getCategory("material") != pElt->getCategory("material")) - return false; - } - - // Delete all pieces that are under the mask - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - del (x+i, y+j, true, &tUpdate); - } - - const string &CurMat = pElt->getCategory ("material"); - - if (CurMat != STRING_NO_CAT_TYPE) - { // This element is a valid material - // Place the piece - const string &EltName = pElt->getName (); - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - set (x+i, y+j, sPosX.Tab[i+j*sPosX.w], sPosY.Tab[i+j*sPosY.w], EltName); - setRot (x+i, y+j, nRot); - setFlip (x+i, y+j, nFlip); - } - } - - return true; -} - -// --------------------------------------------------------------------------- -// Brutal adding a zone over empty space do not propagate in any way -> can result -// in inconsistency when trying the propagation mode -void CBuilderZoneRegion::addForce (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - sint32 sizeX = pElt->getSizeX(), sizeY = pElt->getSizeY(); - sint32 i, j; - SPiece sMask, sPosX, sPosY; - CToUpdate tUpdate; // Transition to update - - if (!_Builder->getZoneMask (x,y)) - return; - - /* - if (pElt->getCategory("transname") != STRING_NO_CAT_TYPE) - { - addTransition (x, y, nRot, nFlip, pElt); - return; - }*/ - - // Create the mask in the good rotation and flip - sMask.Tab.resize (sizeX*sizeY); - sPosX.Tab.resize (sizeX*sizeY); - sPosY.Tab.resize (sizeX*sizeY); - - for (j = 0; j < sizeY; ++j) - for (i = 0; i < sizeX; ++i) - { - sPosX.Tab[i+j*sizeX] = (uint8)i; - sPosY.Tab[i+j*sizeX] = (uint8)j; - sMask.Tab[i+j*sizeX] = pElt->getMask()[i+j*sizeX]; - } - sPosX.w = sPosY.w = sMask.w = sizeX; - sPosX.h = sPosY.h = sMask.h = sizeY; - sMask.rotFlip (nRot, nFlip); - sPosX.rotFlip (nRot, nFlip); - sPosY.rotFlip (nRot, nFlip); - - // Test if the pieces can be put (due to mask) - // All space under the mask must be empty - sint32 stride = (1 + pBZR->getMaxX () - pBZR->getMinX ()); - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - if (_Builder->getZoneMask(x+i, y+j) == false) - return; - if (((x+i) < pBZR->getMinX ()) || ((x+i) > pBZR->getMaxX ()) || - ((y+j) < pBZR->getMinY ()) || ((y+j) > pBZR->getMaxY ())) - return; - CZoneBankElement *pEltUnder = _ZeBank->getElementByZoneName(pBZR->getName (x+i, y+i)); - if (pEltUnder != NULL) - return; - } - - // Delete all pieces that are under the mask - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - del (x+i, y+j, true, &tUpdate); - } - - const string &CurMat = pElt->getCategory ("material"); - const bool transition = pElt->getCategory("transname") != STRING_NO_CAT_TYPE; - - if (CurMat != STRING_NO_CAT_TYPE || transition) - { // This element is a valid material - // Place the piece - const string &EltName = pElt->getName (); - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - set (x+i, y+j, sPosX.Tab[i+j*sPosX.w], sPosY.Tab[i+j*sPosY.w], EltName, transition); - setRot (x+i, y+j, nRot); - setFlip (x+i, y+j, nFlip); - } - } -} - -// --------------------------------------------------------------------------- - -// Convert (transNum,flip,rot) to cutEdge(up,down,left,right) -uint8 TransToEdge[72][4] = -{ - { 0, 0, 1, 1 }, // TransNum = 0, Flip = 0, Rot = 0 - { 2, 2, 0, 0 }, // TransNum = 0, Flip = 0, Rot = 1 - { 0, 0, 2, 2 }, // TransNum = 0, Flip = 0, Rot = 2 - { 1, 1, 0, 0 }, // TransNum = 0, Flip = 0, Rot = 3 - { 0, 0, 1, 1 }, // TransNum = 0, Flip = 1, Rot = 0 - { 2, 2, 0, 0 }, // TransNum = 0, Flip = 1, Rot = 1 - { 0, 0, 2, 2 }, // TransNum = 0, Flip = 1, Rot = 2 - { 1, 1, 0, 0 }, // TransNum = 0, Flip = 1, Rot = 3 - - { 0, 0, 1, 2 }, // TransNum = 1, Flip = 0, Rot = 0 - { 1, 2, 0, 0 }, // TransNum = 1, Flip = 0, Rot = 1 - { 0, 0, 1, 2 }, // TransNum = 1, Flip = 0, Rot = 2 - { 1, 2, 0, 0 }, // TransNum = 1, Flip = 0, Rot = 3 - { 0, 0, 2, 1 }, // TransNum = 1, Flip = 1, Rot = 0 - { 2, 1, 0, 0 }, // TransNum = 1, Flip = 1, Rot = 1 - { 0, 0, 2, 1 }, // TransNum = 1, Flip = 1, Rot = 2 - { 2, 1, 0, 0 }, // TransNum = 1, Flip = 1, Rot = 3 - - { 0, 0, 2, 2 }, // TransNum = 2, Flip = 0, Rot = 0 - { 1, 1, 0, 0 }, // TransNum = 2, Flip = 0, Rot = 1 - { 0, 0, 1, 1 }, // TransNum = 2, Flip = 0, Rot = 2 - { 2, 2, 0, 0 }, // TransNum = 2, Flip = 0, Rot = 3 - { 0, 0, 2, 2 }, // TransNum = 2, Flip = 1, Rot = 0 - { 1, 1, 0, 0 }, // TransNum = 2, Flip = 1, Rot = 1 - { 0, 0, 1, 1 }, // TransNum = 2, Flip = 1, Rot = 2 - { 2, 2, 0, 0 }, // TransNum = 2, Flip = 1, Rot = 3 - - { 0, 1, 1, 0 }, // TransNum = 3, Flip = 0, Rot = 0 - { 0, 2, 0, 1 }, // TransNum = 3, Flip = 0, Rot = 1 - { 2, 0, 0, 2 }, // TransNum = 3, Flip = 0, Rot = 2 - { 1, 0, 2, 0 }, // TransNum = 3, Flip = 0, Rot = 3 - { 0, 2, 0, 1 }, // TransNum = 3, Flip = 1, Rot = 0 - { 2, 0, 0, 2 }, // TransNum = 3, Flip = 1, Rot = 1 - { 1, 0, 2, 0 }, // TransNum = 3, Flip = 1, Rot = 2 - { 0, 1, 1, 0 }, // TransNum = 3, Flip = 1, Rot = 3 - - { 0, 2, 1, 0 }, // TransNum = 4, Flip = 0, Rot = 0 - { 0, 2, 0, 2 }, // TransNum = 4, Flip = 0, Rot = 1 - { 1, 0, 0, 2 }, // TransNum = 4, Flip = 0, Rot = 2 - { 1, 0, 1, 0 }, // TransNum = 4, Flip = 0, Rot = 3 - { 0, 1, 0, 1 }, // TransNum = 4, Flip = 1, Rot = 0 - { 2, 0, 0, 1 }, // TransNum = 4, Flip = 1, Rot = 1 - { 2, 0, 2, 0 }, // TransNum = 4, Flip = 1, Rot = 2 - { 0, 1, 2, 0 }, // TransNum = 4, Flip = 1, Rot = 3 - - { 0, 2, 2, 0 }, // TransNum = 5, Flip = 0, Rot = 0 - { 0, 1, 0, 2 }, // TransNum = 5, Flip = 0, Rot = 1 - { 1, 0, 0, 1 }, // TransNum = 5, Flip = 0, Rot = 2 - { 2, 0, 1, 0 }, // TransNum = 5, Flip = 0, Rot = 3 - { 0, 1, 0, 2 }, // TransNum = 5, Flip = 1, Rot = 0 - { 1, 0, 0, 1 }, // TransNum = 5, Flip = 1, Rot = 1 - { 2, 0, 1, 0 }, // TransNum = 5, Flip = 1, Rot = 2 - { 0, 2, 2, 0 }, // TransNum = 5, Flip = 1, Rot = 3 - - { 0, 1, 1, 0 }, // TransNum = 6, Flip = 0, Rot = 0 - { 0, 2, 0, 1 }, // TransNum = 6, Flip = 0, Rot = 1 - { 2, 0, 0, 2 }, // TransNum = 6, Flip = 0, Rot = 2 - { 1, 0, 2, 0 }, // TransNum = 6, Flip = 0, Rot = 3 - { 0, 2, 0, 1 }, // TransNum = 6, Flip = 1, Rot = 0 - { 2, 0, 0, 2 }, // TransNum = 6, Flip = 1, Rot = 1 - { 1, 0, 2, 0 }, // TransNum = 6, Flip = 1, Rot = 2 - { 0, 1, 1, 0 }, // TransNum = 6, Flip = 1, Rot = 3 - - { 0, 2, 1, 0 }, // TransNum = 7, Flip = 0, Rot = 0 - { 0, 2, 0, 2 }, // TransNum = 7, Flip = 0, Rot = 1 - { 1, 0, 0, 2 }, // TransNum = 7, Flip = 0, Rot = 2 - { 1, 0, 1, 0 }, // TransNum = 7, Flip = 0, Rot = 3 - { 0, 1, 0, 1 }, // TransNum = 7, Flip = 1, Rot = 0 - { 2, 0, 0, 1 }, // TransNum = 7, Flip = 1, Rot = 1 - { 2, 0, 2, 0 }, // TransNum = 7, Flip = 1, Rot = 2 - { 0, 1, 2, 0 }, // TransNum = 7, Flip = 1, Rot = 3 - - { 0, 2, 2, 0 }, // TransNum = 8, Flip = 0, Rot = 0 - { 0, 1, 0, 2 }, // TransNum = 8, Flip = 0, Rot = 1 - { 1, 0, 0, 1 }, // TransNum = 8, Flip = 0, Rot = 2 - { 2, 0, 1, 0 }, // TransNum = 8, Flip = 0, Rot = 3 - { 0, 1, 0, 2 }, // TransNum = 8, Flip = 1, Rot = 0 - { 1, 0, 0, 1 }, // TransNum = 8, Flip = 1, Rot = 1 - { 2, 0, 1, 0 }, // TransNum = 8, Flip = 1, Rot = 2 - { 0, 2, 2, 0 }, // TransNum = 8, Flip = 1, Rot = 3 -}; -void CBuilderZoneRegion::addTransition (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - uint32 i; - // Check that we write in an already defined place - if ((x < pBZR->getMinX ()) || (x > pBZR->getMaxX ()) || - (y < pBZR->getMinY ()) || (y > pBZR->getMaxY ())) - return; - - // Check size - if ((pElt->getSizeX() != 1) || (pElt->getSizeY() != 1)) - return; - - // Check that an element already exist at position we want put the transition - CZoneBankElement *pEltUnder = _ZeBank->getElementByZoneName(pBZR->getName (x, y)); - if (pEltUnder == NULL) - return; - - // And check that this element is also a transition and the same transition - if (pEltUnder->getCategory ("transname") == STRING_NO_CAT_TYPE) - return; - if (pEltUnder->getCategory ("transname") != pElt->getCategory ("transname")) - return; - - string underType = pEltUnder->getCategory ("transtype"); - string overType = pElt->getCategory ("transtype"); - string underNum = pEltUnder->getCategory ("transnum"); - string overNum = pElt->getCategory ("transnum"); - - CDatabaseLocator zoneTemp (RegionId, x, y); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - CLigoData dataZoneOriginal = dataZoneTemp; - - bool bMustPropagate = false; - // Same type of transition ? - if (pEltUnder->getCategory ("transtype") != pElt->getCategory ("transtype")) - { - // No so random the cutEdges - for (i = 0; i < 4; ++i) - { - uint8 nCut = (uint8)(1.0f+NLMISC::frand(2.0f)); - NLMISC::clamp (nCut, (uint8)1, (uint8)2); - - dataZoneTemp.SharingCutEdges[i] = nCut; - } - pElt = NULL; - bMustPropagate = true; - } - else - { - // Put exactly the transition as given - sint32 transnum = atoi (pElt->getCategory ("transnum").c_str()); - sint32 flip = pBZR->getFlip (x, y); - sint32 rot = pBZR->getRot (x, y); - sint32 pos1 = -1, pos2 = -1; - - for (i = 0; i < 4; ++i) - { - if ((TransToEdge[transnum*8+flip*4+rot][i] != 0) && - (TransToEdge[transnum*8+flip*4+rot][i] != dataZoneTemp.SharingCutEdges[i])) - bMustPropagate = true; - - dataZoneTemp.SharingCutEdges[i] = TransToEdge[transnum*8+flip*4+rot][i]; - - if ((pos1 != -1) && (dataZoneTemp.SharingCutEdges[i] != 0)) - pos2 = i; - if ((pos1 == -1) && (dataZoneTemp.SharingCutEdges[i] != 0)) - pos1 = i; - } - // Exchange cutedges != 0 one time /2 to permit all positions - if ((transnum == 1) || (transnum == 4) || (transnum == 7)) - if (pElt->getName() == pEltUnder->getName()) - { - bMustPropagate = true; - - dataZoneTemp.SharingCutEdges[pos1] = 3 - dataZoneTemp.SharingCutEdges[pos1]; - dataZoneTemp.SharingCutEdges[pos2] = 3 - dataZoneTemp.SharingCutEdges[pos2]; - } - } - if (dataZoneTemp != dataZoneOriginal) - { - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - updateTrans (x, y, pElt); - - // If the transition number is not the same propagate the change - if (bMustPropagate) - { - // Propagate where the edge is cut (1/3 or 2/3) and update the transition - if (dataZoneTemp.SharingMatNames[0] != dataZoneTemp.SharingMatNames[2]) - { - if (x > pBZR->getMinX ()) - { // [x-1][y].right = [x][y].left - // _Zones[(x-1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[3] = dataZoneTemp.SharingCutEdges[2]; - CDatabaseLocator zoneTemp2 (RegionId, x-1, y); - CLigoData dataZoneTemp2; - getDocument ()->getLigoData (dataZoneTemp2, zoneTemp2); - if (dataZoneTemp2.SharingCutEdges[3] != dataZoneTemp.SharingCutEdges[2]) - { - dataZoneTemp2.SharingCutEdges[3] = dataZoneTemp.SharingCutEdges[2]; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp2, zoneTemp2)); - } - } - updateTrans (x-1, y); - } - if (dataZoneTemp.SharingMatNames[1] != dataZoneTemp.SharingMatNames[3]) - { - if (x < pBZR->getMaxX ()) - { // [x+1][y].left = [x][y].right - //_Zones[(x+1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[2] = dataZoneTemp.SharingCutEdges[3]; - CDatabaseLocator zoneTemp2 (RegionId, x+1, y); - CLigoData dataZoneTemp2; - getDocument ()->getLigoData (dataZoneTemp2, zoneTemp2); - if (dataZoneTemp2.SharingCutEdges[2] != dataZoneTemp.SharingCutEdges[3]) - { - dataZoneTemp2.SharingCutEdges[2] = dataZoneTemp.SharingCutEdges[3]; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp2, zoneTemp2)); - } - } - updateTrans (x+1, y); - } - if (dataZoneTemp.SharingMatNames[0] != dataZoneTemp.SharingMatNames[1]) - { - if (y > pBZR->getMinY ()) - { // [x][y-1].up = [x][y].down - //_Zones[(x-pBZR->getMinX ())+(y-1-pBZR->getMinY ())*stride].SharingCutEdges[0] = dataZoneTemp.SharingCutEdges[1]; - CDatabaseLocator zoneTemp2 (RegionId, x, y-1); - CLigoData dataZoneTemp2; - getDocument ()->getLigoData (dataZoneTemp2, zoneTemp2); - if (dataZoneTemp2.SharingCutEdges[0] != dataZoneTemp.SharingCutEdges[1]) - { - dataZoneTemp2.SharingCutEdges[0] = dataZoneTemp.SharingCutEdges[1]; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp2, zoneTemp2)); - } - } - updateTrans (x, y-1); - } - if (dataZoneTemp.SharingMatNames[2] != dataZoneTemp.SharingMatNames[3]) - { - if (y < pBZR->getMaxY ()) - { // [x][y+1].down = [x][y].up - //_Zones[(x-pBZR->getMinX ())+(y+1-pBZR->getMinY ())*stride].SharingCutEdges[1] = dataZoneTemp.SharingCutEdges[0]; - CDatabaseLocator zoneTemp2 (RegionId, x, y+1); - CLigoData dataZoneTemp2; - getDocument ()->getLigoData (dataZoneTemp2, zoneTemp2); - if (dataZoneTemp2.SharingCutEdges[1] != dataZoneTemp.SharingCutEdges[0]) - { - dataZoneTemp2.SharingCutEdges[1] = dataZoneTemp.SharingCutEdges[0]; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp2, zoneTemp2)); - } - } - updateTrans (x, y+1); - } - } -} - -// --------------------------------------------------------------------------- -void CBuilderZoneRegion::addToUpdateAndCreate (CBuilderZoneRegion *pBZRfrom, sint32 sharePos, sint32 x, sint32 y, const string &sNewMat, void *pInt1, void *pInt2) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - CToUpdate *ptCreate = (CToUpdate*)pInt1; - CToUpdate *ptUpdate = (CToUpdate*)pInt2; - sint32 stride = (1+pBZR->getMaxX ()-pBZR->getMinX ()); - - CDatabaseLocator locator; - if (getDocument ()->getZoneAmongRegions (locator, pBZRfrom, x, y)) - { - CLigoData data; - getDocument ()->getLigoData (data, locator); - if (data.SharingMatNames[sharePos] != sNewMat) - { - data.SharingMatNames[sharePos] = sNewMat; - getDocument ()->addModification (new CActionLigoTile (data, locator)); - } - pBZRfrom->del (x, y, true, ptUpdate); - ptCreate->add (pBZRfrom, x, y, sNewMat); - } -} - -// --------------------------------------------------------------------------- -void CBuilderZoneRegion::putTransitions (sint32 inX, sint32 inY, const SPiece &rMask, const string &MatName, - void *pInternal) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - CToUpdate tCreate; // Transition to create - CToUpdate *ptUpdate = (CToUpdate*)pInternal; // Transition to update - - sint32 i, j, k, l, m; - sint32 x = inX, y = inY; - for (j = 0; j < rMask.h; ++j) - for (i = 0; i < rMask.w; ++i) - if (rMask.Tab[i+j*rMask.w]) - { - for (k = -1; k <= 1; ++k) - for (l = -1; l <= 1; ++l) - { - CBuilderZoneRegion *pBZR2 = this; - CDatabaseLocator locator; - if (getDocument ()->getZoneAmongRegions (locator, pBZR2, inX+i+l, inY+j+k)) - tCreate.add (pBZR2, inX+i+l, inY+j+k, MatName); - } - } - - // Check coherency of the transition to update - for (m = 0; m < (sint32)tCreate.size(); ++m) - { - CBuilderZoneRegion *pBZR2 = tCreate.getBZR(m); - x = tCreate.getX(m); - y = tCreate.getY(m); - string putMat = tCreate.getMat(m); - - //if ((x < pBZR->getMinX ())||(x > pBZR->getMaxX ())||(y < pBZR->getMinY ())||(y > pBZR->getMaxY ())) - // continue; - - CDatabaseLocator zoneTemp (pBZR2->RegionId, x, y); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - - if (!((dataZoneTemp.SharingMatNames[0] == dataZoneTemp.SharingMatNames[1])&& - (dataZoneTemp.SharingMatNames[1] == dataZoneTemp.SharingMatNames[2])&& - (dataZoneTemp.SharingMatNames[2] == dataZoneTemp.SharingMatNames[3]))) - pBZR2->del (x, y, true, ptUpdate); - - // Check to see material can be posed - uint corner; - for (corner = 0; corner < 4; corner++) - { - string newMat = getNextMatInTree (putMat, dataZoneTemp.SharingMatNames[corner]); - - // Can't be posed ? - if (newMat == STRING_UNUSED) - break; - } - if ( (corner < 4) && (m != 0) ) - { - // The material can't be paused - dataZoneTemp.SharingMatNames[0] = STRING_UNUSED; - dataZoneTemp.SharingMatNames[1] = STRING_UNUSED; - dataZoneTemp.SharingMatNames[2] = STRING_UNUSED; - dataZoneTemp.SharingMatNames[3] = STRING_UNUSED; - - // Don't propagate any more - } - else - { - // Expand material for the 1st quarter - string newMat = getNextMatInTree (putMat, dataZoneTemp.SharingMatNames[0]); - if (newMat != dataZoneTemp.SharingMatNames[0]) - { // Update the quarter - if (dataZoneTemp.SharingMatNames[0] != newMat) - { - dataZoneTemp.SharingMatNames[0] = newMat; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - - addToUpdateAndCreate (pBZR2, 1, x-1, y, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate (pBZR2, 3, x-1, y-1, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate (pBZR2, 2, x, y-1, newMat, &tCreate, ptUpdate); - } - - // Expand material for the 2nd quarter - newMat = getNextMatInTree (putMat, dataZoneTemp.SharingMatNames[1]); - if (newMat != dataZoneTemp.SharingMatNames[1]) - { // Update the quarter - //if (_Builder->getZoneMask(x,y)) - if (dataZoneTemp.SharingMatNames[1] != newMat) - { - dataZoneTemp.SharingMatNames[1] = newMat; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - - addToUpdateAndCreate (pBZR2, 0, x+1, y, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate (pBZR2, 2, x+1, y-1, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate (pBZR2, 3, x, y-1, newMat, &tCreate, ptUpdate); - } - - // Expand material for the 3rd quarter - newMat = getNextMatInTree (putMat, dataZoneTemp.SharingMatNames[2]); - if (newMat != dataZoneTemp.SharingMatNames[2]) - { // Update the quarter - //if (_Builder->getZoneMask(x,y)) - if (dataZoneTemp.SharingMatNames[2] != newMat) - { - dataZoneTemp.SharingMatNames[2] = newMat; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - - addToUpdateAndCreate (pBZR2, 3, x-1, y, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate (pBZR2, 1, x-1, y+1, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate (pBZR2, 0, x, y+1, newMat, &tCreate, ptUpdate); - } - - // Expand material for the 4th quarter - newMat = getNextMatInTree (putMat, dataZoneTemp.SharingMatNames[3]); - if (newMat != dataZoneTemp.SharingMatNames[3]) - { // Update the quarter - //if (_Builder->getZoneMask(x,y)) - if (dataZoneTemp.SharingMatNames[3] != newMat) - { - dataZoneTemp.SharingMatNames[3] = newMat; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - - addToUpdateAndCreate (pBZR2, 2, x+1, y, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate (pBZR2, 0, x+1, y+1, newMat, &tCreate, ptUpdate); - addToUpdateAndCreate (pBZR2, 1, x, y+1, newMat, &tCreate, ptUpdate); - } - } - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - - // Delete transitions that are inside the mask - for (j = 0; j < rMask.h; ++j) - for (i = 0; i < rMask.w; ++i) - if (rMask.Tab[i+j*rMask.w]) - { - tCreate.del (inX+i, inY+j); - } - - // For all transition to update choose the cut edge - for (m = 0; m < (sint32)tCreate.size(); ++m) - { - const CZoneRegion *pBZR2 = &(getDocument ()->getZoneRegion (tCreate.getBZR(m)->RegionId)); - x = tCreate.getX(m); - y = tCreate.getY(m); - - if ((x < pBZR2->getMinX ())||(x > pBZR2->getMaxX ())||(y < pBZR2->getMinY ())||(y > pBZR2->getMaxY ())) - continue; - - CDatabaseLocator zoneTemp (tCreate.getBZR(m)->RegionId, x, y); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - CLigoData dataZoneTempOriginal = dataZoneTemp; - - for (i = 0; i < 4; ++i) - { - uint8 nCut = (uint8)(1.0f+NLMISC::frand(2.0f)); - NLMISC::clamp (nCut, (uint8)1, (uint8)2); - dataZoneTemp.SharingCutEdges[i] = nCut; - } - - if (dataZoneTempOriginal != dataZoneTemp) - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - - // Propagate - if (dataZoneTemp.SharingMatNames[0] != dataZoneTemp.SharingMatNames[2]) - { // [x-1][y].right = [x][y].left - CBuilderZoneRegion *pBZR3 = tCreate.getBZR(m); - CDatabaseLocator pZU; - if (getDocument ()->getZoneAmongRegions (pZU, pBZR3, x-1, y)) - { - CLigoData data; - getDocument ()->getLigoData (data, pZU); - if (data.SharingCutEdges[3] != dataZoneTemp.SharingCutEdges[2]) - { - data.SharingCutEdges[3] = dataZoneTemp.SharingCutEdges[2]; - getDocument ()->addModification (new CActionLigoTile (data, pZU)); - } - ptUpdate->add (pBZR3, x-1, y, ""); - } - } - else - { - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - if (dataZoneTemp.SharingCutEdges[2] != 0) - { - dataZoneTemp.SharingCutEdges[2] = 0; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - } - - if (dataZoneTemp.SharingMatNames[0] != dataZoneTemp.SharingMatNames[1]) - { // [x][y-1].up = [x][y].down - CBuilderZoneRegion *pBZR3 = tCreate.getBZR(m); - CDatabaseLocator pZU; - if (getDocument ()->getZoneAmongRegions (pZU, pBZR3, x, y-1)) - { - CLigoData data; - getDocument ()->getLigoData (data, pZU); - if (data.SharingCutEdges[0] != dataZoneTemp.SharingCutEdges[1]) - { - data.SharingCutEdges[0] = dataZoneTemp.SharingCutEdges[1]; - getDocument ()->addModification (new CActionLigoTile (data, pZU)); - } - ptUpdate->add (pBZR3, x, y-1, ""); - } - } - else - { - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - if (dataZoneTemp.SharingCutEdges[1] != 0) - { - dataZoneTemp.SharingCutEdges[1] = 0; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - } - - if (dataZoneTemp.SharingMatNames[3] != dataZoneTemp.SharingMatNames[1]) - { // [x+1][y].left = [x][y].right - CBuilderZoneRegion *pBZR3 = tCreate.getBZR(m); - CDatabaseLocator pZU; - if (getDocument ()->getZoneAmongRegions (pZU, pBZR3, x+1, y)) - { - CLigoData data; - getDocument ()->getLigoData (data, pZU); - if (data.SharingCutEdges[2] != dataZoneTemp.SharingCutEdges[3]) - { - data.SharingCutEdges[2] = dataZoneTemp.SharingCutEdges[3]; - getDocument ()->addModification (new CActionLigoTile (data, pZU)); - } - ptUpdate->add (pBZR3, x+1, y, ""); - } - } - else - { - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - if (dataZoneTemp.SharingCutEdges[3] != 0) - { - dataZoneTemp.SharingCutEdges[3] = 0; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - } - - if (dataZoneTemp.SharingMatNames[2] != dataZoneTemp.SharingMatNames[3]) - { // [x][y+1].down = [x][y].up - CBuilderZoneRegion *pBZR3 = tCreate.getBZR(m); - CDatabaseLocator pZU; - if (getDocument ()->getZoneAmongRegions (pZU, pBZR3, x, y+1)) - { - CLigoData data; - getDocument ()->getLigoData (data, pZU); - if (data.SharingCutEdges[1] = dataZoneTemp.SharingCutEdges[0]) - { - data.SharingCutEdges[1] = dataZoneTemp.SharingCutEdges[0]; - getDocument ()->addModification (new CActionLigoTile (data, pZU)); - } - ptUpdate->add (pBZR3, x, y+1, ""); - } - } - else - { - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - if (dataZoneTemp.SharingCutEdges[0] = 0) - { - dataZoneTemp.SharingCutEdges[0] = 0; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } - } - } - - // Delete in tUpdate each element in common with tCreate - for (m = 0; m < (sint32)tCreate.size(); ++m) - { - x = tCreate.getX(m); - y = tCreate.getY(m); - ptUpdate->del (x,y); - } - - // Finally update all transition - for (m = 0; m < (sint32)tCreate.size(); ++m) - { - const CZoneRegion *pBZR2 = &(getDocument ()->getZoneRegion (tCreate.getBZR(m)->RegionId)); - x = tCreate.getX(m); - y = tCreate.getY(m); - - if ((x >= pBZR2->getMinX ())&&(x <= pBZR2->getMaxX ())&&(y >= pBZR2->getMinY ())&&(y <= pBZR2->getMaxY ())) - tCreate.getBZR(m)->updateTrans (x, y); - } - for (m = 0; m < (sint32)ptUpdate->size(); ++m) - { - const CZoneRegion *pBZR2 = &(getDocument ()->getZoneRegion (tCreate.getBZR(m)->RegionId)); - x = ptUpdate->getX(m); - y = ptUpdate->getY(m); - if ((x >= pBZR2->getMinX ())&&(x <= pBZR2->getMaxX ())&&(y >= pBZR2->getMinY ())&&(y <= pBZR2->getMaxY ())) - tCreate.getBZR(m)->updateTrans (x, y); - } - - // Cross material - for (m = 0; m < (sint32)tCreate.size(); ++m) - { - const CZoneRegion *pBZR2 = &(getDocument ()->getZoneRegion (tCreate.getBZR(m)->RegionId)); - x = tCreate.getX(m); - y = tCreate.getY(m); - - - CDatabaseLocator zoneTemp (RegionId, x, y); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - - std::set matNameSet; - for (i = 0; i < 4; ++i) - matNameSet.insert (dataZoneTemp.SharingMatNames[i]); - - if (((dataZoneTemp.SharingMatNames[0] == dataZoneTemp.SharingMatNames[3]) && - (dataZoneTemp.SharingMatNames[1] == dataZoneTemp.SharingMatNames[2]) && - (dataZoneTemp.SharingMatNames[0] != dataZoneTemp.SharingMatNames[1])) - || (matNameSet.size()>2)) - { - - _ZeBank->resetSelection (); - _ZeBank->addOrSwitch ("material", tCreate.getMat(m)); - _ZeBank->addAndSwitch ("size", "1x1"); - vector vElts; - _ZeBank->getSelection (vElts); - if (vElts.size() == 0) - return; - sint32 nRan = (sint32)(NLMISC::frand((float)vElts.size())); - NLMISC::clamp (nRan, (sint32)0, (sint32)(vElts.size()-1)); - CZoneBankElement *pZBE = vElts[nRan]; - nRan = (uint32)(NLMISC::frand (1.0) * 4); - NLMISC::clamp (nRan, (sint32)0, (sint32)3); - uint8 rot = (uint8)nRan; - nRan = (uint32)(NLMISC::frand (1.0) * 2); - NLMISC::clamp (nRan, (sint32)0, (sint32)1); - uint8 flip = (uint8)nRan; - - tCreate.getBZR(m)->add (x, y, rot, flip, pZBE); - } - } - -} - - -// --------------------------------------------------------------------------- -/*void CBuilderZoneRegion::putTransition (sint32 x, sint32 y, const string &MatName) -{ - const string &rSZone = getName (x, y); - if (rSZone != STRING_UNUSED) - return; - - sint32 stride = (1+pBZR->getMaxX ()-pBZR->getMinX ()); - sint32 m; - // Set Random edges - for (m = 0; m < 4; ++m) - { - uint8 nCut = (uint8)(1.0f+NLMISC::frand(2.0f)); - NLMISC::clamp (nCut, (uint8)1, (uint8)2); - _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[m] = nCut; - } - // Propagate - if (x > pBZR->getMinX ()) - { // [x-1][y].right = [x][y].left - _Zones[(x-1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[3] = - _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[2]; - } - if (y > pBZR->getMinY ()) - { // [x][y-1].up = [x][y].down - _Zones[(x-pBZR->getMinX ())+(y-1-pBZR->getMinY ())*stride].SharingCutEdges[0] = - _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[1]; - } - if (x < pBZR->getMaxX ()) - { // [x+1][y].left = [x][y].right - _Zones[(x+1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[2] = - _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[3]; - } - if (y < pBZR->getMaxY ()) - { // [x][y+1].down = [x][y].up - _Zones[(x-pBZR->getMinX ())+(y+1-pBZR->getMinY ())*stride].SharingCutEdges[1] = - _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[0]; - } - - // Update Transitions - updateTrans (x, y); - if (_Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[0] != _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[2]) - updateTrans (x-1, y); - if (_Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[1] != _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[3]) - updateTrans (x+1, y); - if (_Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[0] != _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[1]) - updateTrans (x, y-1); - if (_Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[2] != _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[3]) - updateTrans (x, y+1); -} -*/ -// --------------------------------------------------------------------------- -struct STrans -{ - uint8 Num; - uint8 Rot; - uint8 Flip; -}; - -// --------------------------------------------------------------------------- -STrans TranConvTable[128] = -{ - { 0,0,0 }, // Quart = 0, CutEdge = 0, Np = 0 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 0, Np = 1 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 1, Np = 0 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 1, Np = 1 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 2, Np = 0 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 2, Np = 1 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 3, Np = 0 UNUSED - { 0,0,0 }, // Quart = 0, CutEdge = 3, Np = 1 UNUSED - - { 6,0,0 }, // Quart = 1, CutEdge = 0, Np = 0 - { 6,3,1 }, // Quart = 1, CutEdge = 0, Np = 1 - { 7,0,0 }, // Quart = 1, CutEdge = 1, Np = 0 - { 7,0,0 }, // Quart = 1, CutEdge = 1, Np = 1 - { 7,3,1 }, // Quart = 1, CutEdge = 2, Np = 0 - { 7,3,1 }, // Quart = 1, CutEdge = 2, Np = 1 - { 8,0,0 }, // Quart = 1, CutEdge = 3, Np = 0 - { 8,3,1 }, // Quart = 1, CutEdge = 3, Np = 1 - - { 7,0,1 }, // Quart = 2, CutEdge = 0, Np = 0 - { 7,0,1 }, // Quart = 2, CutEdge = 0, Np = 1 - { 6,0,1 }, // Quart = 2, CutEdge = 1, Np = 0 - { 6,1,0 }, // Quart = 2, CutEdge = 1, Np = 1 - { 8,1,0 }, // Quart = 2, CutEdge = 2, Np = 0 - { 8,0,1 }, // Quart = 2, CutEdge = 2, Np = 1 - { 7,1,0 }, // Quart = 2, CutEdge = 3, Np = 0 - { 7,1,0 }, // Quart = 2, CutEdge = 3, Np = 1 - - { 0,0,0 }, // Quart = 3, CutEdge = 0, Np = 0 - { 0,0,1 }, // Quart = 3, CutEdge = 0, Np = 1 - { 1,0,1 }, // Quart = 3, CutEdge = 1, Np = 0 - { 1,0,1 }, // Quart = 3, CutEdge = 1, Np = 1 - { 1,0,0 }, // Quart = 3, CutEdge = 2, Np = 0 - { 1,0,0 }, // Quart = 3, CutEdge = 2, Np = 1 - { 2,0,0 }, // Quart = 3, CutEdge = 3, Np = 0 - { 2,0,1 }, // Quart = 3, CutEdge = 3, Np = 1 - - { 7,3,0 }, // Quart = 4, CutEdge = 0, Np = 0 - { 7,3,0 }, // Quart = 4, CutEdge = 0, Np = 1 - { 8,3,0 }, // Quart = 4, CutEdge = 1, Np = 0 - { 8,2,1 }, // Quart = 4, CutEdge = 1, Np = 1 - { 6,3,0 }, // Quart = 4, CutEdge = 2, Np = 0 - { 6,2,1 }, // Quart = 4, CutEdge = 2, Np = 1 - { 7,2,1 }, // Quart = 4, CutEdge = 3, Np = 0 - { 7,2,1 }, // Quart = 4, CutEdge = 3, Np = 1 - - { 0,3,0 }, // Quart = 5, CutEdge = 0, Np = 0 - { 0,3,1 }, // Quart = 5, CutEdge = 0, Np = 1 - { 1,3,1 }, // Quart = 5, CutEdge = 1, Np = 0 - { 1,3,1 }, // Quart = 5, CutEdge = 1, Np = 1 - { 1,3,0 }, // Quart = 5, CutEdge = 2, Np = 0 - { 1,3,0 }, // Quart = 5, CutEdge = 2, Np = 1 - { 2,3,0 }, // Quart = 5, CutEdge = 3, Np = 0 - { 2,3,1 }, // Quart = 5, CutEdge = 3, Np = 1 - - { 0,0,0 }, // Quart = 6, CutEdge = 0, Np = 0 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 0, Np = 1 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 1, Np = 0 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 1, Np = 1 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 2, Np = 0 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 2, Np = 1 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 3, Np = 0 UNUSED - { 0,0,0 }, // Quart = 6, CutEdge = 3, Np = 1 UNUSED - - { 5,2,0 }, // Quart = 7, CutEdge = 0, Np = 0 - { 5,1,1 }, // Quart = 7, CutEdge = 0, Np = 1 - { 4,1,1 }, // Quart = 7, CutEdge = 1, Np = 0 - { 4,1,1 }, // Quart = 7, CutEdge = 1, Np = 1 - { 4,2,0 }, // Quart = 7, CutEdge = 2, Np = 0 - { 4,2,0 }, // Quart = 7, CutEdge = 2, Np = 1 - { 3,2,0 }, // Quart = 7, CutEdge = 3, Np = 0 - { 3,1,1 }, // Quart = 7, CutEdge = 3, Np = 1 - - { 8,2,0 }, // Quart = 8, CutEdge = 0, Np = 0 - { 8,1,1 }, // Quart = 8, CutEdge = 0, Np = 1 - { 7,1,1 }, // Quart = 8, CutEdge = 1, Np = 0 - { 7,1,1 }, // Quart = 8, CutEdge = 1, Np = 1 - { 7,2,0 }, // Quart = 8, CutEdge = 2, Np = 0 - { 7,2,0 }, // Quart = 8, CutEdge = 2, Np = 1 - { 6,2,0 }, // Quart = 8, CutEdge = 3, Np = 0 - { 6,1,1 }, // Quart = 8, CutEdge = 3, Np = 1 - - { 0,0,0 }, // Quart = 9, CutEdge = 0, Np = 0 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 0, Np = 1 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 1, Np = 0 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 1, Np = 1 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 2, Np = 0 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 2, Np = 1 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 3, Np = 0 UNUSED - { 0,0,0 }, // Quart = 9, CutEdge = 3, Np = 1 UNUSED - - { 2,1,0 }, // Quart = 10, CutEdge = 0, Np = 0 - { 2,1,1 }, // Quart = 10, CutEdge = 0, Np = 1 - { 1,1,1 }, // Quart = 10, CutEdge = 1, Np = 0 - { 1,1,1 }, // Quart = 10, CutEdge = 1, Np = 1 - { 1,1,0 }, // Quart = 10, CutEdge = 2, Np = 0 - { 1,1,0 }, // Quart = 10, CutEdge = 2, Np = 1 - { 0,1,0 }, // Quart = 10, CutEdge = 3, Np = 0 - { 0,1,1 }, // Quart = 10, CutEdge = 3, Np = 1 - - { 4,3,0 }, // Quart = 11, CutEdge = 0, Np = 0 - { 4,3,0 }, // Quart = 11, CutEdge = 0, Np = 1 - { 5,3,0 }, // Quart = 11, CutEdge = 1, Np = 0 - { 5,2,1 }, // Quart = 11, CutEdge = 1, Np = 1 - { 3,3,0 }, // Quart = 11, CutEdge = 2, Np = 0 - { 3,2,1 }, // Quart = 11, CutEdge = 2, Np = 1 - { 4,2,1 }, // Quart = 11, CutEdge = 3, Np = 0 - { 4,2,1 }, // Quart = 11, CutEdge = 3, Np = 1 - - { 2,2,0 }, // Quart = 12, CutEdge = 0, Np = 0 - { 2,2,1 }, // Quart = 12, CutEdge = 0, Np = 1 - { 1,2,1 }, // Quart = 12, CutEdge = 1, Np = 0 - { 1,2,1 }, // Quart = 12, CutEdge = 1, Np = 1 - { 1,2,0 }, // Quart = 12, CutEdge = 2, Np = 0 - { 1,2,0 }, // Quart = 12, CutEdge = 2, Np = 1 - { 0,2,0 }, // Quart = 12, CutEdge = 3, Np = 0 - { 0,2,1 }, // Quart = 12, CutEdge = 3, Np = 1 - - { 4,0,1 }, // Quart = 13, CutEdge = 0, Np = 0 - { 4,0,1 }, // Quart = 13, CutEdge = 0, Np = 1 - { 3,1,0 }, // Quart = 13, CutEdge = 1, Np = 0 - { 3,0,1 }, // Quart = 13, CutEdge = 1, Np = 1 - { 5,1,0 }, // Quart = 13, CutEdge = 2, Np = 0 - { 5,0,1 }, // Quart = 13, CutEdge = 2, Np = 1 - { 4,1,0 }, // Quart = 13, CutEdge = 3, Np = 0 - { 4,1,0 }, // Quart = 13, CutEdge = 3, Np = 1 - - { 3,0,0 }, // Quart = 14, CutEdge = 0, Np = 0 - { 3,3,1 }, // Quart = 14, CutEdge = 0, Np = 1 - { 4,0,0 }, // Quart = 14, CutEdge = 1, Np = 0 - { 4,0,0 }, // Quart = 14, CutEdge = 1, Np = 1 - { 4,3,1 }, // Quart = 14, CutEdge = 2, Np = 0 - { 4,3,1 }, // Quart = 14, CutEdge = 2, Np = 1 - { 5,0,0 }, // Quart = 14, CutEdge = 3, Np = 0 - { 5,3,1 }, // Quart = 14, CutEdge = 3, Np = 1 - - { 0,0,0 }, // Quart = 15, CutEdge = 0, Np = 0 UNUSED - { 0,0,0 }, // Quart = 15, CutEdge = 0, Np = 1 UNUSED - { 0,0,0 }, // Quart = 15, CutEdge = 1, Np = 0 UNUSED - { 0,0,0 }, // Quart = 15, CutEdge = 1, Np = 1 UNUSED - { 0,0,0 }, // Quart = 15, CutEdge = 2, Np = 0 UNUSED - { 0,0,0 }, // Quart = 15, CutEdge = 2, Np = 1 UNUSED - { 0,0,0 }, // Quart = 15, CutEdge = 3, Np = 0 UNUSED - { 0,0,0 } // Quart = 15, CutEdge = 3, Np = 1 UNUSED -}; - -// --------------------------------------------------------------------------- -void CBuilderZoneRegion::updateTrans (sint32 x, sint32 y, CZoneBankElement *pElt) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - if ((x < pBZR->getMinX ()) || (x > pBZR->getMaxX ()) || (y < pBZR->getMinY ()) || (y > pBZR->getMaxY ())) - return; - - //if (!_Builder->getZoneMask(x,y)) - // return; - - // Interpret the transition info - x -= pBZR->getMinX (); - y -= pBZR->getMinY (); - sint32 m; - // Calculate the number of material around with transition info - std::set matNameSet; - - CDatabaseLocator zoneTemp (RegionId, x+pBZR->getMinX (), y+pBZR->getMinY ()); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - CLigoData dataZoneTempOriginal = dataZoneTemp; - - for (m = 0; m < 4; ++m) - matNameSet.insert (dataZoneTemp.SharingMatNames[m]); - - if (matNameSet.size() == 1) - { - if (dataZoneTemp.SharingMatNames[0] == STRING_UNUSED) - { - del (x+pBZR->getMinX (), y+pBZR->getMinY ()); - // set (x+pBZR->getMinX (), y+pBZR->getMinY (), 0, 0, STRING_UNUSED, false); - return; - } - else - { - CZoneBankElement *pZBE = _ZeBank->getElementByZoneName (dataZoneTemp.ZoneName); - if ((pZBE != NULL) && (pZBE->getCategory("material")==dataZoneTemp.SharingMatNames[0])) - return; - _ZeBank->resetSelection (); - _ZeBank->addOrSwitch ("material", dataZoneTemp.SharingMatNames[0]); - _ZeBank->addAndSwitch ("size", "1x1"); - vector vElts; - _ZeBank->getSelection (vElts); - if (vElts.size() == 0) - return; - sint32 nRan = (sint32)(NLMISC::frand((float)vElts.size())); - NLMISC::clamp (nRan, (sint32)0, (sint32)(vElts.size()-1)); - pZBE = vElts[nRan]; - nRan = (uint32)(NLMISC::frand (1.0) * 4); - NLMISC::clamp (nRan, (sint32)0, (sint32)3); - uint8 rot = (uint8)nRan; - nRan = (uint32)(NLMISC::frand (1.0) * 2); - NLMISC::clamp (nRan, (sint32)0, (sint32)1); - uint8 flip = (uint8)nRan; - - set (x+pBZR->getMinX (), y+pBZR->getMinY (), 0, 0, pZBE->getName(), false); - setRot (x+pBZR->getMinX (), y+pBZR->getMinY (), rot); - setFlip (x+pBZR->getMinX (), y+pBZR->getMinY (), flip); - return; - } - } - - // No 2 materials so the transition system dont work - if (matNameSet.size() != 2) - return; - - std::set::iterator it = matNameSet.begin(); - string sMatA = *it; - ++it; - string sMatB = *it; - - _ZeBank->resetSelection (); - _ZeBank->addOrSwitch ("transname", sMatA + "-" + sMatB); - vector selection; - _ZeBank->getSelection (selection); - if (selection.size() == 0) - { - string sTmp = sMatA; - sMatA = sMatB; - sMatB = sTmp; - _ZeBank->resetSelection (); - _ZeBank->addOrSwitch ("transname", sMatA + "-" + sMatB); - _ZeBank->getSelection (selection); - } - - if (selection.size() == 0) - return; - - // Convert the sharingCutEdges and SharingNames to the num and type of transition - uint8 nQuart = 0; // 0-MatA 1-MatB - for (m = 0; m < 4; ++m) - if (dataZoneTemp.SharingMatNames[m] == sMatB) - nQuart |= (1<0, 2->1) - if ((nQuart == 4)||(nQuart == 5)||(nQuart == 7)||(nQuart == 8)||(nQuart == 10)||(nQuart == 11)) - { - if (dataZoneTemp.SharingCutEdges[0] == 2) - nCutEdge |= 1 << nPosCorner; - ++nPosCorner; - } - else - { - dataZoneTemp.SharingCutEdges[0] = 0; - } - - // Same for down edge - if ((nQuart == 1)||(nQuart == 2)||(nQuart == 5)||(nQuart == 10)||(nQuart == 13)||(nQuart == 14)) - { - if (dataZoneTemp.SharingCutEdges[1] == 2) - nCutEdge |= 1 << nPosCorner; - ++nPosCorner; - } - else - { - dataZoneTemp.SharingCutEdges[1] = 0; - } - - // Same for left edge - if ((nQuart == 1)||(nQuart == 3)||(nQuart == 4)||(nQuart == 11)||(nQuart == 12)||(nQuart == 14)) - { - if (dataZoneTemp.SharingCutEdges[2] == 2) - nCutEdge |= 1 << nPosCorner; - ++nPosCorner; - } - else - { - dataZoneTemp.SharingCutEdges[2] = 0; - } - - // Same for right edge - if ((nQuart == 2)||(nQuart == 3)||(nQuart == 7)||(nQuart == 8)||(nQuart == 12)||(nQuart == 13)) - { - if (dataZoneTemp.SharingCutEdges[3] == 2) - nCutEdge |= 1 << nPosCorner; - ++nPosCorner; - } - else - { - dataZoneTemp.SharingCutEdges[3] = 0; - } - - nlassert (nPosCorner == 2); // If not this means that more than 2 edges are cut which is not possible - - STrans Trans, TransTmp1, TransTmp2; - - TransTmp1 = TranConvTable[nQuart*8+2*nCutEdge+0]; - TransTmp2 = TranConvTable[nQuart*8+2*nCutEdge+1]; - - // Choose one or the two - sint32 nTrans = (sint32)(NLMISC::frand(2.0f)); - NLMISC::clamp (nTrans, (sint32)0, (sint32)1); - if (nTrans == 0) - Trans = TransTmp1; - else - Trans = TransTmp2; - - _ZeBank->addAndSwitch ("transnum", NLMISC::toString(Trans.Num)); - _ZeBank->getSelection (selection); - - if (selection.size() > 0) - { - if (pElt != NULL) - { - dataZoneTemp.ZoneName = pElt->getName(); - } - else - { - nTrans = (uint32)(NLMISC::frand (1.0) * selection.size()); - NLMISC::clamp (nTrans, (sint32)0, (sint32)(selection.size()-1)); - dataZoneTemp.ZoneName = selection[nTrans]->getName(); - } - dataZoneTemp.PosX = dataZoneTemp.PosY = 0; - dataZoneTemp.Rot = Trans.Rot; - dataZoneTemp.Flip = Trans.Flip; - } - if (dataZoneTempOriginal != dataZoneTemp) - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); -} - -// --------------------------------------------------------------------------- -string CBuilderZoneRegion::getNextMatInTree (const string &sMatA, const string &sMatB) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - uint32 i, posA = 10000, posB = 10000; - - if (sMatA == sMatB) - return sMatA; - - for (i = 0; i < _MatTree.size(); ++i) - { - if (_MatTree[i].Name == sMatA) - posA = i; - if (_MatTree[i].Name == sMatB) - posB = i; - } - if ((posA == 10000) || (posB == 10000)) - return STRING_UNUSED; - - vector vTemp; - tryPath (posA, posB, vTemp); - if (vTemp.size() <= 1) - return STRING_UNUSED; - else - return _MatTree[vTemp[1]].Name; -} - -// --------------------------------------------------------------------------- -struct SNode -{ - sint32 NodePos, Dist, PrevNodePos; - - SNode() - { - NodePos = Dist = PrevNodePos = -1; - } -}; - -// --------------------------------------------------------------------------- -// Find the fastest way between posA and posB in the MatTree (Dijkstra) -void CBuilderZoneRegion::tryPath (uint32 posA, uint32 posB, vector &vPath) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - // Build the adjascence matrix - vector matAdj; - sint32 nNumNodes = _MatTree.size(); - sint32 i, j, cost; - matAdj.resize (nNumNodes*nNumNodes, -1); - for (i = 0; i < nNumNodes; ++i) - for (j = 0; j < (sint32)_MatTree[i].Arcs.size(); ++j) - matAdj[i+_MatTree[i].Arcs[j]*nNumNodes] = 1; - - vector vNodes; // NodesPos == index - vNodes.resize (nNumNodes); - for (i = 0; i < nNumNodes; ++i) - vNodes[i].NodePos = i; - vNodes[posA].Dist = 0; - - queue qNodes; - qNodes.push (vNodes[posA]); - - while (qNodes.size() > 0) - { - SNode node = qNodes.front (); - qNodes.pop (); - - for (i = 0; i < nNumNodes; ++i) - { - cost = matAdj[node.NodePos+i*nNumNodes]; - if (cost != -1) - { - if ((vNodes[i].Dist == -1) || (vNodes[i].Dist > (cost+node.Dist))) - { - vNodes[i].Dist = cost+node.Dist; - vNodes[i].PrevNodePos = node.NodePos; - qNodes.push (vNodes[i]); - } - } - } - } - - // Get path length - i = posB; - j = 0; - while (i != -1) - { - ++j; - i = vNodes[i].PrevNodePos; - } - - // Write the path in the good order (from posA to posB) - vPath.resize (j); - i = posB; - while (i != -1) - { - --j; - vPath[j] = i; - i = vNodes[i].PrevNodePos; - } -} - - - -// --------------------------------------------------------------------------- -void CBuilderZoneRegion::del (sint32 x, sint32 y, bool transition, void *pInternal) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - if (!_Builder->getZoneMask (x,y)) - return; - - const string &rSZone = pBZR->getName (x, y); - - CToUpdate *pUpdate = (CToUpdate *)pInternal; - - CZoneBankElement *pZBE = _ZeBank->getElementByZoneName (rSZone); - if (pZBE != NULL) - { - sint32 sizeX = pZBE->getSizeX(), sizeY = pZBE->getSizeY(); - sint32 posX = pBZR->getPosX (x, y), posY = pBZR->getPosY (x, y); - uint8 rot = pBZR->getRot (x, y); - uint8 flip = pBZR->getFlip (x, y); - sint32 i, j; - sint32 deltaX, deltaY; - - if (flip == 0) - { - switch (rot) - { - case 0: deltaX = -posX; deltaY = -posY; break; - case 1: deltaX = -(sizeY-1-posY); deltaY = -posX; break; - case 2: deltaX = -(sizeX-1-posX); deltaY = -(sizeY-1-posY); break; - case 3: deltaX = -posY; deltaY = -(sizeX-1-posX); break; - } - } - else - { - switch (rot) - { - case 0: deltaX = -(sizeX-1-posX); deltaY = -posY; break; - case 1: deltaX = -(sizeY-1-posY); deltaY = -(sizeX-1-posX); break; - case 2: deltaX = -posX; deltaY = -(sizeY-1-posY); break; - case 3: deltaX = -posY; deltaY = -posX; break; - } - } - - SPiece sMask; - sMask.Tab.resize (sizeX*sizeY); - for(i = 0; i < sizeX*sizeY; ++i) - sMask.Tab[i] = pZBE->getMask()[i]; - sMask.w = sizeX; - sMask.h = sizeY; - sMask.rotFlip (rot, flip); - - for (j = 0; j < sMask.h; ++j) - for (i = 0; i < sMask.w; ++i) - if (sMask.Tab[i+j*sMask.w]) - { - set (x+deltaX+i, y+deltaY+j, 0, 0, STRING_UNUSED, true); - setRot (x+deltaX+i, y+deltaY+j, 0); - setFlip (x+deltaX+i, y+deltaY+j, 0); - if (pUpdate != NULL) - { - pUpdate->add (this, x+deltaX+i, y+deltaY+j, ""); - } - } - if (!transition) - reduceMin (); - } - else - { - if ((x < pBZR->getMinX ()) || (x > pBZR->getMaxX ()) || (y < pBZR->getMinY ()) || (y > pBZR->getMaxY ())) - return; - - CDatabaseLocator zoneTemp (RegionId, x, y); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - CLigoData dataZoneTempOriginal = dataZoneTemp; - - dataZoneTemp.ZoneName = STRING_UNUSED; - dataZoneTemp.PosX = 0; - dataZoneTemp.PosY = 0; - - for (uint32 i = 0; i < 4; ++i) - { - dataZoneTemp.SharingMatNames[i] = STRING_UNUSED; - dataZoneTemp.SharingCutEdges[i] = 0; - } - - if (dataZoneTempOriginal != dataZoneTemp) - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - - } -} - -// --------------------------------------------------------------------------- - -void CBuilderZoneRegion::move (sint32 x, sint32 y) -{ - getDocument ()->addModification (new CActionLigoMove (getDocument()->regionIDToDatabaseElementID(RegionId), x, y)); -} - -// --------------------------------------------------------------------------- -uint32 CBuilderZoneRegion::countZones () -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - sint32 x, y; - - uint32 counter = 0; - - for (y = pBZR->getMinY (); y <= pBZR->getMaxY (); ++y) - for (x = pBZR->getMinX (); x <= pBZR->getMaxX (); ++x) - if (pBZR->getName (x, y) != STRING_UNUSED) - ++counter; - - return counter; -} - -// --------------------------------------------------------------------------- -void CBuilderZoneRegion::set (sint32 x, sint32 y, sint32 PosX, sint32 PosY, - const std::string &ZoneName, bool transition) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - // Do we need to resize ? - if ((x < pBZR->getMinX ()) || (x > pBZR->getMaxX ()) || - (y < pBZR->getMinY ()) || (y > pBZR->getMaxY ())) - { - sint32 newMinX = (xgetMinX ()?x:pBZR->getMinX ()), newMinY = (ygetMinY ()?y:pBZR->getMinY ()); - sint32 newMaxX = (x>pBZR->getMaxX ()?x:pBZR->getMaxX ()), newMaxY = (y>pBZR->getMaxY ()?y:pBZR->getMaxY ()); - - resize (newMinX, newMaxX, newMinY, newMaxY); - } - - CDatabaseLocator zoneTemp (RegionId, x, y); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - CLigoData dataZoneTempOriginal = dataZoneTemp; - - dataZoneTemp.ZoneName = ZoneName; - dataZoneTemp.PosX = (uint8)PosX; - dataZoneTemp.PosY = (uint8)PosY; - - if (!transition) - { - CZoneBankElement *pZBE = _ZeBank->getElementByZoneName (ZoneName); - if (pZBE == NULL) - return; - const string &sMatName = pZBE->getCategory ("material"); - if (sMatName == STRING_NO_CAT_TYPE) - return; - for (uint32 i = 0; i < 4; ++i) - { - dataZoneTemp.SharingMatNames[i] = sMatName; - dataZoneTemp.SharingCutEdges[i] = 0; - } - - if (dataZoneTempOriginal != dataZoneTemp) - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - - CBuilderZoneRegion *pBZR = this; - CDatabaseLocator pZU; - if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x-1, y-1)) - { - CLigoData data; - getDocument ()->getLigoData (data, pZU); - if (data.SharingMatNames[3] != sMatName) - { - data.SharingMatNames[3] = sMatName; - getDocument ()->addModification (new CActionLigoTile (data, pZU)); - } - } - pBZR = this; - if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x, y-1)) - { - CLigoData data; - getDocument ()->getLigoData (data, pZU); - if ((data.SharingMatNames[2] != sMatName) || (data.SharingMatNames[3] != sMatName)) - { - data.SharingMatNames[2] = sMatName; - data.SharingMatNames[3] = sMatName; - getDocument ()->addModification (new CActionLigoTile (data, pZU)); - } - } - pBZR = this; - if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x+1, y-1)) - { - CLigoData data; - getDocument ()->getLigoData (data, pZU); - if (data.SharingMatNames[2] != sMatName) - { - data.SharingMatNames[2] = sMatName; - getDocument ()->addModification (new CActionLigoTile (data, pZU)); - } - } - pBZR = this; - if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x-1, y)) - { - CLigoData data; - getDocument ()->getLigoData (data, pZU); - if ((data.SharingMatNames[1] != sMatName) || (data.SharingMatNames[3] != sMatName)) - { - data.SharingMatNames[1] = sMatName; - data.SharingMatNames[3] = sMatName; - getDocument ()->addModification (new CActionLigoTile (data, pZU)); - } - } - pBZR = this; - if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x+1, y)) - { - CLigoData data; - getDocument ()->getLigoData (data, pZU); - if ((data.SharingMatNames[0] != sMatName) || (data.SharingMatNames[2] != sMatName)) - { - data.SharingMatNames[0] = sMatName; - data.SharingMatNames[2] = sMatName; - getDocument ()->addModification (new CActionLigoTile (data, pZU)); - } - } - pBZR = this; - if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x-1, y+1)) - { - CLigoData data; - getDocument ()->getLigoData (data, pZU); - if (data.SharingMatNames[1] != sMatName) - { - data.SharingMatNames[1] = sMatName; - getDocument ()->addModification (new CActionLigoTile (data, pZU)); - } - } - pBZR = this; - if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x, y+1)) - { - CLigoData data; - getDocument ()->getLigoData (data, pZU); - if ((data.SharingMatNames[0] != sMatName) || (data.SharingMatNames[1] != sMatName)) - { - data.SharingMatNames[0] = sMatName; - data.SharingMatNames[1] = sMatName; - getDocument ()->addModification (new CActionLigoTile (data, pZU)); - } - } - pBZR = this; - if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x+1, y+1)) - { - CLigoData data; - getDocument ()->getLigoData (data, pZU); - if (data.SharingMatNames[0] != sMatName) - { - data.SharingMatNames[0] = sMatName; - getDocument ()->addModification (new CActionLigoTile (data, pZU)); - } - } - } - else - { - if (dataZoneTempOriginal != dataZoneTemp) - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } -} - -// --------------------------------------------------------------------------- -void CBuilderZoneRegion::setRot (sint32 x, sint32 y, uint8 rot) -{ - CDatabaseLocator zoneTemp (RegionId, x, y); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - if (dataZoneTemp.Rot != rot) - { - dataZoneTemp.Rot = rot; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } -} - -// --------------------------------------------------------------------------- -void CBuilderZoneRegion::setFlip (sint32 x, sint32 y, uint8 flip) -{ - CDatabaseLocator zoneTemp (RegionId, x, y); - CLigoData dataZoneTemp; - getDocument ()->getLigoData (dataZoneTemp, zoneTemp); - if (dataZoneTemp.Flip != flip) - { - dataZoneTemp.Flip = flip; - getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); - } -} - - -// --------------------------------------------------------------------------- -void CBuilderZoneRegion::reduceMin () -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - sint32 i, j; - - sint32 newMinX = pBZR->getMinX (), newMinY = pBZR->getMinY (); - sint32 newMaxX = pBZR->getMaxX (), newMaxY = pBZR->getMaxY (); - bool bCanSuppr; - - // Reduce the MinY - while (true) - { - if (newMinY == newMaxY) - break; - j = newMinY; - bCanSuppr = true; - for (i = newMinX; i <= newMaxX; ++i) - { - string str = pBZR->getName (i, j) ; - if (!str.empty() && (str != STRING_UNUSED)) - { - bCanSuppr = false; - break; - } - } - if (bCanSuppr) - ++newMinY; - else - break; - } - - // Reduce the MaxY - while (true) - { - if (newMinY == newMaxY) - break; - j = newMaxY; - bCanSuppr = true; - for (i = newMinX; i <= newMaxX; ++i) - { - string str = pBZR->getName (i, j) ; - if (!str.empty() && (str != STRING_UNUSED)) - { - bCanSuppr = false; - break; - } - } - if (bCanSuppr) - --newMaxY; - else - break; - } - - // Reduce the MinX - while (true) - { - if (newMinX == newMaxX) - break; - i = newMinX; - bCanSuppr = true; - for (j = newMinY; j <= newMaxY; ++j) - { - string str = pBZR->getName (i, j) ; - if (!str.empty() && (str != STRING_UNUSED)) - { - bCanSuppr = false; - break; - } - } - if (bCanSuppr) - ++newMinX; - else - break; - } - - // Reduce the MaxX - while (true) - { - if (newMinX == newMaxX) - break; - i = newMaxX; - bCanSuppr = true; - for (j = newMinY; j <= newMaxY; ++j) - { - string str = pBZR->getName (i, j) ; - if (!str.empty() && (str != STRING_UNUSED)) - { - bCanSuppr = false; - break; - } - } - if (bCanSuppr) - --newMaxX; - else - break; - } - - if ((newMinX != pBZR->getMinX ()) || (newMinY != pBZR->getMinY ()) || (newMaxX != pBZR->getMaxX ()) || (newMaxY != pBZR->getMaxY ())) - { - resize (newMinX, newMaxX, newMinY, newMaxY); - } -} - -// --------------------------------------------------------------------------- -void CBuilderZoneRegion::resize (sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY) -{ - const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); - if ((pBZR->getMinX ()!= newMinX) || (pBZR->getMaxX ()!= newMaxX) || (pBZR->getMinY ()!= newMinY) || (pBZR->getMaxY ()!= newMaxY)) - { - getDocument ()->addModification (new CActionLigoResize (getDocument()->regionIDToDatabaseElementID(RegionId), newMinX, newMaxX, newMinY, newMaxY)); - - } -} - -// --------------------------------------------------------------------------- +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" + +#include "action.h" +#include "world_editor_doc.h" +#include "builder_zone_region.h" +#include "builder_zone.h" + +#include + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; + +// *************************************************************************** +// CBuilderZoneRegion +// *************************************************************************** + + +// --------------------------------------------------------------------------- +CBuilderZoneRegion::CBuilderZoneRegion (uint regionId) +{ + _ZeBank = NULL; + RegionId = regionId; +} + +// --------------------------------------------------------------------------- +bool CBuilderZoneRegion::init (NLLIGO::CZoneBank *pBank, CBuilderZone *pBuilder, string &error) +{ + if (_ZeBank != NULL) + return true; + _ZeBank = pBank; + _Builder = pBuilder; + // Build the material tree + uint32 i, j, k; + SMatNode mn; + vector AllValues; + _ZeBank->getCategoryValues ("material", AllValues); + for (i = 0; i < AllValues.size(); ++i) + { + mn.Name = AllValues[i]; + _MatTree.push_back (mn); + } + // Link between materials + AllValues.clear (); + _ZeBank->getCategoryValues ("transname", AllValues); + for (i = 0; i < AllValues.size(); ++i) + { + // Get the 2 materials linked together + string matAstr, matBstr; + for (j = 0; j < AllValues[i].size(); ++j) + { + if (AllValues[i][j] == '-') + break; + else + matAstr += AllValues[i][j]; + } + ++j; + for (; j < AllValues[i].size(); ++j) + matBstr += AllValues[i][j]; + + // Find matA + for (j = 0; j < _MatTree.size(); ++j) + if (_MatTree[j].Name == matAstr) + break; + + if (j < _MatTree.size()) + { + // Find matB + for (k = 0; k < _MatTree.size(); ++k) + if (_MatTree[k].Name == matBstr) + break; + + if (k < _MatTree.size()) + { + _MatTree[j].Arcs.push_back (k); // Add a ref to matB in node matA + _MatTree[k].Arcs.push_back (j); // Add a ref to matA in node matB + } + } + } + + // DEBUG + // DEBUG + // DEBUG +/* + _MatTree.clear(); + _MatTree.resize (6); + _MatTree[0].Name = "A"; + _MatTree[0].Arcs.resize (2); + _MatTree[0].Arcs[0] = 1; + _MatTree[0].Arcs[1] = 2; + + _MatTree[1].Name = "F"; + _MatTree[1].Arcs.resize (3); + _MatTree[1].Arcs[0] = 0; + _MatTree[1].Arcs[1] = 4; + _MatTree[1].Arcs[2] = 5; + + _MatTree[2].Name = "B"; + _MatTree[2].Arcs.resize (3); + _MatTree[2].Arcs[0] = 0; + _MatTree[2].Arcs[1] = 3; + _MatTree[2].Arcs[2] = 5; + + _MatTree[3].Name = "C"; + _MatTree[3].Arcs.resize (1); + _MatTree[3].Arcs[0] = 2; + + _MatTree[4].Name = "Z"; + _MatTree[4].Arcs.resize (1); + _MatTree[4].Arcs[0] = 1; + + _MatTree[5].Name = "E"; + _MatTree[5].Arcs.resize (2); + _MatTree[5].Arcs[0] = 1; + _MatTree[5].Arcs[1] = 2; + + vector vRetPath; + tryPath(0, 3, vRetPath); + + uint32 ij; + ++ij; + ij = 0; +*/ + // DEBUG + // DEBUG + // DEBUG + return true; +} + +// --------------------------------------------------------------------------- +class CToUpdate +{ + struct SElt + { + sint32 x, y; + string MatPut; // Material put into the cell to update + CBuilderZoneRegion *BZR; + }; + + vector Elts; + +public: + + void add (CBuilderZoneRegion* pBZR, sint32 x, sint32 y, const string &MatName) + { + bool bFound = false; + for (uint32 m = 0; m < Elts.size(); ++m) + if ((Elts[m].x == x) && (Elts[m].y == y)) + { + bFound = true; + break; + } + if (!bFound) + { + SElt tuTmp; + tuTmp.x = x; + tuTmp.y = y; + tuTmp.MatPut = MatName; + tuTmp.BZR = pBZR; + Elts.push_back (tuTmp); + } + } + + void del (sint32 x, sint32 y) + { + bool bFound = false; + uint32 m; + for (m = 0; m < Elts.size(); ++m) + if ((Elts[m].x == x) && (Elts[m].y == y)) + { + bFound = true; + break; + } + if (bFound) + { + for (; m < Elts.size()-1; ++m) + Elts[m] = Elts[m+1]; + Elts.resize (Elts.size()-1); + } + } + + uint32 size() + { + return Elts.size(); + } + + sint32 getX (uint32 m) + { + return Elts[m].x; + } + + sint32 getY (uint32 m) + { + return Elts[m].y; + } + + CBuilderZoneRegion* getBZR (uint32 m) + { + return Elts[m].BZR; + } + + const string& getMat (uint32 m) + { + return Elts[m].MatPut; + } +}; + +// --------------------------------------------------------------------------- +void CBuilderZoneRegion::add (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt) +{ + sint32 sizeX = pElt->getSizeX(), sizeY = pElt->getSizeY(); + sint32 i, j; + SPiece sMask, sPosX, sPosY; + CToUpdate tUpdate; // Transition to update + + if (!_Builder->getZoneMask (x,y)) + return; + + if (pElt->getCategory("transname") != STRING_NO_CAT_TYPE) + { + addTransition (x, y, nRot, nFlip, pElt); + return; + } + + // Create the mask in the good rotation and flip + sMask.Tab.resize (sizeX*sizeY); + sPosX.Tab.resize (sizeX*sizeY); + sPosY.Tab.resize (sizeX*sizeY); + + for (j = 0; j < sizeY; ++j) + for (i = 0; i < sizeX; ++i) + { + sPosX.Tab[i+j*sizeX] = (uint8)i; + sPosY.Tab[i+j*sizeX] = (uint8)j; + sMask.Tab[i+j*sizeX] = pElt->getMask()[i+j*sizeX]; + } + sPosX.w = sPosY.w = sMask.w = sizeX; + sPosX.h = sPosY.h = sMask.h = sizeY; + sMask.rotFlip (nRot, nFlip); + sPosX.rotFlip (nRot, nFlip); + sPosY.rotFlip (nRot, nFlip); + + // Test if the pieces can be put (due to mask) + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + if (_Builder->getZoneMask(x+i, y+j) == false) + return; + } + + // Delete all pieces that are under the mask + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + del (x+i, y+j, true, &tUpdate); + } + + // Delete all around all material that are not from the same as us + const string &CurMat = pElt->getCategory ("material"); + + if (CurMat != STRING_NO_CAT_TYPE) + { // This element is a valid material + // Place the piece + const string &EltName = pElt->getName (); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + set (x+i, y+j, sPosX.Tab[i+j*sPosX.w], sPosY.Tab[i+j*sPosY.w], EltName); + setRot (x+i, y+j, nRot); + setFlip (x+i, y+j, nFlip); + } + + // Put all transitions between different materials + putTransitions (x, y, sMask, CurMat, &tUpdate); + + // Place the piece + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + set (x+i, y+j, sPosX.Tab[i+j*sPosX.w], sPosY.Tab[i+j*sPosY.w], EltName); + setRot (x+i, y+j, nRot); + setFlip (x+i, y+j, nFlip); + } + } +} + +// --------------------------------------------------------------------------- +void CBuilderZoneRegion::invertCutEdge (sint32 x, sint32 y, uint8 cePos) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + if ((x < pBZR->getMinX ()) || (x > pBZR->getMaxX ()) || + (y < pBZR->getMinY ()) || (y > pBZR->getMaxY ())) + return; + CZoneBankElement *pElt = _ZeBank->getElementByZoneName (pBZR->getName (x, y)); + if (pElt == NULL) + return; + if (pElt->getCategory("transname") == STRING_NO_CAT_TYPE) + return; + + CDatabaseLocator zonePos (RegionId, x, y); + CLigoData dataZonePos; + getDocument ()->getLigoData (dataZonePos, zonePos); + if (dataZonePos.SharingCutEdges[cePos] != 3 - dataZonePos.SharingCutEdges[cePos]) + { + dataZonePos.SharingCutEdges[cePos] = 3 - dataZonePos.SharingCutEdges[cePos]; + getDocument ()->addModification (new CActionLigoTile (dataZonePos, zonePos)); + } + updateTrans (x, y); + + // If the transition number is not the same propagate the change + // Propagate where the edge is cut (1/3 or 2/3) and update the transition + if (cePos == 2) + if (dataZonePos.SharingMatNames[0] != dataZonePos.SharingMatNames[2]) + { + if (x > pBZR->getMinX ()) + { // [x-1][y].right = [x][y].left + + // _Zones[(x-1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[3] = dataZonePos.SharingCutEdges[2]; + CDatabaseLocator zoneTemp (RegionId, x-1, y); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + if (dataZoneTemp.SharingCutEdges[3] != dataZonePos.SharingCutEdges[2]) + { + dataZoneTemp.SharingCutEdges[3] = dataZonePos.SharingCutEdges[2]; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + } + updateTrans (x-1, y); + } + if (cePos == 3) + if (dataZonePos.SharingMatNames[1] != dataZonePos.SharingMatNames[3]) + { + if (x < pBZR->getMaxX ()) + { // [x+1][y].left = [x][y].right + + CDatabaseLocator zoneTemp (RegionId, x+1, y); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + if (dataZoneTemp.SharingCutEdges[2] != dataZonePos.SharingCutEdges[3]) + { + dataZoneTemp.SharingCutEdges[2] = dataZonePos.SharingCutEdges[3]; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + } + updateTrans (x+1, y); + } + if (cePos == 1) + if (dataZonePos.SharingMatNames[0] != dataZonePos.SharingMatNames[1]) + { + if (y > pBZR->getMinY ()) + { // [x][y-1].up = [x][y].down + + CDatabaseLocator zoneTemp (RegionId, x, y-1); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + if (dataZoneTemp.SharingCutEdges[0] != dataZonePos.SharingCutEdges[1]) + { + dataZoneTemp.SharingCutEdges[0] = dataZonePos.SharingCutEdges[1]; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + } + updateTrans (x, y-1); + } + if (cePos == 0) + if (dataZonePos.SharingMatNames[2] != dataZonePos.SharingMatNames[3]) + { + if (y < pBZR->getMaxY ()) + { // [x][y+1].down = [x][y].up + + CDatabaseLocator zoneTemp (RegionId, x, y+1); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + if (dataZoneTemp.SharingCutEdges[1] != dataZonePos.SharingCutEdges[0]) + { + dataZoneTemp.SharingCutEdges[1] = dataZonePos.SharingCutEdges[0]; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + } + updateTrans (x, y+1); + } +} + +// --------------------------------------------------------------------------- +void CBuilderZoneRegion::cycleTransition (sint32 x, sint32 y) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + if ((x < pBZR->getMinX ()) || (x > pBZR->getMaxX ()) || + (y < pBZR->getMinY ()) || (y > pBZR->getMaxY ())) + return; + /* todo remove + sint32 stride = (1 + pBZR->getMaxX () - pBZR->getMinX ()); + sint32 zonePos = (x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride; + */ + CZoneBankElement *pElt = _ZeBank->getElementByZoneName (pBZR->getName (x, y)); + if (pElt == NULL) + return; + if (pElt->getCategory("transname") == STRING_NO_CAT_TYPE) + return; + + // \todo trap -> choose the good transition in function of the transition under the current location + // Choose the next possible transition if not the same as the first one + // Choose among all transition of the same number + + updateTrans (x, y); +} + +// --------------------------------------------------------------------------- +bool CBuilderZoneRegion::addNotPropagate (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + sint32 sizeX = pElt->getSizeX(), sizeY = pElt->getSizeY(); + sint32 i, j; + SPiece sMask, sPosX, sPosY; + CToUpdate tUpdate; // Transition to update + + if (!_Builder->getZoneMask (x,y)) + return false; + + if (pElt->getCategory("transname") != STRING_NO_CAT_TYPE) + { + addTransition (x, y, nRot, nFlip, pElt); + return true; + } + + // Create the mask in the good rotation and flip + sMask.Tab.resize (sizeX*sizeY); + sPosX.Tab.resize (sizeX*sizeY); + sPosY.Tab.resize (sizeX*sizeY); + + for (j = 0; j < sizeY; ++j) + for (i = 0; i < sizeX; ++i) + { + sPosX.Tab[i+j*sizeX] = (uint8)i; + sPosY.Tab[i+j*sizeX] = (uint8)j; + sMask.Tab[i+j*sizeX] = pElt->getMask()[i+j*sizeX]; + } + sPosX.w = sPosY.w = sMask.w = sizeX; + sPosX.h = sPosY.h = sMask.h = sizeY; + sMask.rotFlip (nRot, nFlip); + sPosX.rotFlip (nRot, nFlip); + sPosY.rotFlip (nRot, nFlip); + + // Test if the pieces can be put (due to mask) + sint32 stride = (1 + pBZR->getMaxX () - pBZR->getMinX ()); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + if (_Builder->getZoneMask(x+i, y+j) == false) + return false; + if (((x+i) < pBZR->getMinX ()) || ((x+i) > pBZR->getMaxX ()) || + ((y+j) < pBZR->getMinY ()) || ((y+j) > pBZR->getMaxY ())) + return false; + CZoneBankElement *pEltUnder = _ZeBank->getElementByZoneName(pBZR->getName (x+i, y+j)); + if (pEltUnder == NULL) + return false; + if (pEltUnder->getCategory("material") != pElt->getCategory("material")) + return false; + } + + // Delete all pieces that are under the mask + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + del (x+i, y+j, true, &tUpdate); + } + + const string &CurMat = pElt->getCategory ("material"); + + if (CurMat != STRING_NO_CAT_TYPE) + { // This element is a valid material + // Place the piece + const string &EltName = pElt->getName (); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + set (x+i, y+j, sPosX.Tab[i+j*sPosX.w], sPosY.Tab[i+j*sPosY.w], EltName); + setRot (x+i, y+j, nRot); + setFlip (x+i, y+j, nFlip); + } + } + + return true; +} + +// --------------------------------------------------------------------------- +// Brutal adding a zone over empty space do not propagate in any way -> can result +// in inconsistency when trying the propagation mode +void CBuilderZoneRegion::addForce (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + sint32 sizeX = pElt->getSizeX(), sizeY = pElt->getSizeY(); + sint32 i, j; + SPiece sMask, sPosX, sPosY; + CToUpdate tUpdate; // Transition to update + + if (!_Builder->getZoneMask (x,y)) + return; + + /* + if (pElt->getCategory("transname") != STRING_NO_CAT_TYPE) + { + addTransition (x, y, nRot, nFlip, pElt); + return; + }*/ + + // Create the mask in the good rotation and flip + sMask.Tab.resize (sizeX*sizeY); + sPosX.Tab.resize (sizeX*sizeY); + sPosY.Tab.resize (sizeX*sizeY); + + for (j = 0; j < sizeY; ++j) + for (i = 0; i < sizeX; ++i) + { + sPosX.Tab[i+j*sizeX] = (uint8)i; + sPosY.Tab[i+j*sizeX] = (uint8)j; + sMask.Tab[i+j*sizeX] = pElt->getMask()[i+j*sizeX]; + } + sPosX.w = sPosY.w = sMask.w = sizeX; + sPosX.h = sPosY.h = sMask.h = sizeY; + sMask.rotFlip (nRot, nFlip); + sPosX.rotFlip (nRot, nFlip); + sPosY.rotFlip (nRot, nFlip); + + // Test if the pieces can be put (due to mask) + // All space under the mask must be empty + sint32 stride = (1 + pBZR->getMaxX () - pBZR->getMinX ()); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + if (_Builder->getZoneMask(x+i, y+j) == false) + return; + if (((x+i) < pBZR->getMinX ()) || ((x+i) > pBZR->getMaxX ()) || + ((y+j) < pBZR->getMinY ()) || ((y+j) > pBZR->getMaxY ())) + return; + CZoneBankElement *pEltUnder = _ZeBank->getElementByZoneName(pBZR->getName (x+i, y+i)); + if (pEltUnder != NULL) + return; + } + + // Delete all pieces that are under the mask + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + del (x+i, y+j, true, &tUpdate); + } + + const string &CurMat = pElt->getCategory ("material"); + const bool transition = pElt->getCategory("transname") != STRING_NO_CAT_TYPE; + + if (CurMat != STRING_NO_CAT_TYPE || transition) + { // This element is a valid material + // Place the piece + const string &EltName = pElt->getName (); + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + set (x+i, y+j, sPosX.Tab[i+j*sPosX.w], sPosY.Tab[i+j*sPosY.w], EltName, transition); + setRot (x+i, y+j, nRot); + setFlip (x+i, y+j, nFlip); + } + } +} + +// --------------------------------------------------------------------------- + +// Convert (transNum,flip,rot) to cutEdge(up,down,left,right) +uint8 TransToEdge[72][4] = +{ + { 0, 0, 1, 1 }, // TransNum = 0, Flip = 0, Rot = 0 + { 2, 2, 0, 0 }, // TransNum = 0, Flip = 0, Rot = 1 + { 0, 0, 2, 2 }, // TransNum = 0, Flip = 0, Rot = 2 + { 1, 1, 0, 0 }, // TransNum = 0, Flip = 0, Rot = 3 + { 0, 0, 1, 1 }, // TransNum = 0, Flip = 1, Rot = 0 + { 2, 2, 0, 0 }, // TransNum = 0, Flip = 1, Rot = 1 + { 0, 0, 2, 2 }, // TransNum = 0, Flip = 1, Rot = 2 + { 1, 1, 0, 0 }, // TransNum = 0, Flip = 1, Rot = 3 + + { 0, 0, 1, 2 }, // TransNum = 1, Flip = 0, Rot = 0 + { 1, 2, 0, 0 }, // TransNum = 1, Flip = 0, Rot = 1 + { 0, 0, 1, 2 }, // TransNum = 1, Flip = 0, Rot = 2 + { 1, 2, 0, 0 }, // TransNum = 1, Flip = 0, Rot = 3 + { 0, 0, 2, 1 }, // TransNum = 1, Flip = 1, Rot = 0 + { 2, 1, 0, 0 }, // TransNum = 1, Flip = 1, Rot = 1 + { 0, 0, 2, 1 }, // TransNum = 1, Flip = 1, Rot = 2 + { 2, 1, 0, 0 }, // TransNum = 1, Flip = 1, Rot = 3 + + { 0, 0, 2, 2 }, // TransNum = 2, Flip = 0, Rot = 0 + { 1, 1, 0, 0 }, // TransNum = 2, Flip = 0, Rot = 1 + { 0, 0, 1, 1 }, // TransNum = 2, Flip = 0, Rot = 2 + { 2, 2, 0, 0 }, // TransNum = 2, Flip = 0, Rot = 3 + { 0, 0, 2, 2 }, // TransNum = 2, Flip = 1, Rot = 0 + { 1, 1, 0, 0 }, // TransNum = 2, Flip = 1, Rot = 1 + { 0, 0, 1, 1 }, // TransNum = 2, Flip = 1, Rot = 2 + { 2, 2, 0, 0 }, // TransNum = 2, Flip = 1, Rot = 3 + + { 0, 1, 1, 0 }, // TransNum = 3, Flip = 0, Rot = 0 + { 0, 2, 0, 1 }, // TransNum = 3, Flip = 0, Rot = 1 + { 2, 0, 0, 2 }, // TransNum = 3, Flip = 0, Rot = 2 + { 1, 0, 2, 0 }, // TransNum = 3, Flip = 0, Rot = 3 + { 0, 2, 0, 1 }, // TransNum = 3, Flip = 1, Rot = 0 + { 2, 0, 0, 2 }, // TransNum = 3, Flip = 1, Rot = 1 + { 1, 0, 2, 0 }, // TransNum = 3, Flip = 1, Rot = 2 + { 0, 1, 1, 0 }, // TransNum = 3, Flip = 1, Rot = 3 + + { 0, 2, 1, 0 }, // TransNum = 4, Flip = 0, Rot = 0 + { 0, 2, 0, 2 }, // TransNum = 4, Flip = 0, Rot = 1 + { 1, 0, 0, 2 }, // TransNum = 4, Flip = 0, Rot = 2 + { 1, 0, 1, 0 }, // TransNum = 4, Flip = 0, Rot = 3 + { 0, 1, 0, 1 }, // TransNum = 4, Flip = 1, Rot = 0 + { 2, 0, 0, 1 }, // TransNum = 4, Flip = 1, Rot = 1 + { 2, 0, 2, 0 }, // TransNum = 4, Flip = 1, Rot = 2 + { 0, 1, 2, 0 }, // TransNum = 4, Flip = 1, Rot = 3 + + { 0, 2, 2, 0 }, // TransNum = 5, Flip = 0, Rot = 0 + { 0, 1, 0, 2 }, // TransNum = 5, Flip = 0, Rot = 1 + { 1, 0, 0, 1 }, // TransNum = 5, Flip = 0, Rot = 2 + { 2, 0, 1, 0 }, // TransNum = 5, Flip = 0, Rot = 3 + { 0, 1, 0, 2 }, // TransNum = 5, Flip = 1, Rot = 0 + { 1, 0, 0, 1 }, // TransNum = 5, Flip = 1, Rot = 1 + { 2, 0, 1, 0 }, // TransNum = 5, Flip = 1, Rot = 2 + { 0, 2, 2, 0 }, // TransNum = 5, Flip = 1, Rot = 3 + + { 0, 1, 1, 0 }, // TransNum = 6, Flip = 0, Rot = 0 + { 0, 2, 0, 1 }, // TransNum = 6, Flip = 0, Rot = 1 + { 2, 0, 0, 2 }, // TransNum = 6, Flip = 0, Rot = 2 + { 1, 0, 2, 0 }, // TransNum = 6, Flip = 0, Rot = 3 + { 0, 2, 0, 1 }, // TransNum = 6, Flip = 1, Rot = 0 + { 2, 0, 0, 2 }, // TransNum = 6, Flip = 1, Rot = 1 + { 1, 0, 2, 0 }, // TransNum = 6, Flip = 1, Rot = 2 + { 0, 1, 1, 0 }, // TransNum = 6, Flip = 1, Rot = 3 + + { 0, 2, 1, 0 }, // TransNum = 7, Flip = 0, Rot = 0 + { 0, 2, 0, 2 }, // TransNum = 7, Flip = 0, Rot = 1 + { 1, 0, 0, 2 }, // TransNum = 7, Flip = 0, Rot = 2 + { 1, 0, 1, 0 }, // TransNum = 7, Flip = 0, Rot = 3 + { 0, 1, 0, 1 }, // TransNum = 7, Flip = 1, Rot = 0 + { 2, 0, 0, 1 }, // TransNum = 7, Flip = 1, Rot = 1 + { 2, 0, 2, 0 }, // TransNum = 7, Flip = 1, Rot = 2 + { 0, 1, 2, 0 }, // TransNum = 7, Flip = 1, Rot = 3 + + { 0, 2, 2, 0 }, // TransNum = 8, Flip = 0, Rot = 0 + { 0, 1, 0, 2 }, // TransNum = 8, Flip = 0, Rot = 1 + { 1, 0, 0, 1 }, // TransNum = 8, Flip = 0, Rot = 2 + { 2, 0, 1, 0 }, // TransNum = 8, Flip = 0, Rot = 3 + { 0, 1, 0, 2 }, // TransNum = 8, Flip = 1, Rot = 0 + { 1, 0, 0, 1 }, // TransNum = 8, Flip = 1, Rot = 1 + { 2, 0, 1, 0 }, // TransNum = 8, Flip = 1, Rot = 2 + { 0, 2, 2, 0 }, // TransNum = 8, Flip = 1, Rot = 3 +}; +void CBuilderZoneRegion::addTransition (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + uint32 i; + // Check that we write in an already defined place + if ((x < pBZR->getMinX ()) || (x > pBZR->getMaxX ()) || + (y < pBZR->getMinY ()) || (y > pBZR->getMaxY ())) + return; + + // Check size + if ((pElt->getSizeX() != 1) || (pElt->getSizeY() != 1)) + return; + + // Check that an element already exist at position we want put the transition + CZoneBankElement *pEltUnder = _ZeBank->getElementByZoneName(pBZR->getName (x, y)); + if (pEltUnder == NULL) + return; + + // And check that this element is also a transition and the same transition + if (pEltUnder->getCategory ("transname") == STRING_NO_CAT_TYPE) + return; + if (pEltUnder->getCategory ("transname") != pElt->getCategory ("transname")) + return; + + string underType = pEltUnder->getCategory ("transtype"); + string overType = pElt->getCategory ("transtype"); + string underNum = pEltUnder->getCategory ("transnum"); + string overNum = pElt->getCategory ("transnum"); + + CDatabaseLocator zoneTemp (RegionId, x, y); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + CLigoData dataZoneOriginal = dataZoneTemp; + + bool bMustPropagate = false; + // Same type of transition ? + if (pEltUnder->getCategory ("transtype") != pElt->getCategory ("transtype")) + { + // No so random the cutEdges + for (i = 0; i < 4; ++i) + { + uint8 nCut = (uint8)(1.0f+NLMISC::frand(2.0f)); + NLMISC::clamp (nCut, (uint8)1, (uint8)2); + + dataZoneTemp.SharingCutEdges[i] = nCut; + } + pElt = NULL; + bMustPropagate = true; + } + else + { + // Put exactly the transition as given + sint32 transnum = atoi (pElt->getCategory ("transnum").c_str()); + sint32 flip = pBZR->getFlip (x, y); + sint32 rot = pBZR->getRot (x, y); + sint32 pos1 = -1, pos2 = -1; + + for (i = 0; i < 4; ++i) + { + if ((TransToEdge[transnum*8+flip*4+rot][i] != 0) && + (TransToEdge[transnum*8+flip*4+rot][i] != dataZoneTemp.SharingCutEdges[i])) + bMustPropagate = true; + + dataZoneTemp.SharingCutEdges[i] = TransToEdge[transnum*8+flip*4+rot][i]; + + if ((pos1 != -1) && (dataZoneTemp.SharingCutEdges[i] != 0)) + pos2 = i; + if ((pos1 == -1) && (dataZoneTemp.SharingCutEdges[i] != 0)) + pos1 = i; + } + // Exchange cutedges != 0 one time /2 to permit all positions + if ((transnum == 1) || (transnum == 4) || (transnum == 7)) + if (pElt->getName() == pEltUnder->getName()) + { + bMustPropagate = true; + + dataZoneTemp.SharingCutEdges[pos1] = 3 - dataZoneTemp.SharingCutEdges[pos1]; + dataZoneTemp.SharingCutEdges[pos2] = 3 - dataZoneTemp.SharingCutEdges[pos2]; + } + } + if (dataZoneTemp != dataZoneOriginal) + { + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + updateTrans (x, y, pElt); + + // If the transition number is not the same propagate the change + if (bMustPropagate) + { + // Propagate where the edge is cut (1/3 or 2/3) and update the transition + if (dataZoneTemp.SharingMatNames[0] != dataZoneTemp.SharingMatNames[2]) + { + if (x > pBZR->getMinX ()) + { // [x-1][y].right = [x][y].left + // _Zones[(x-1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[3] = dataZoneTemp.SharingCutEdges[2]; + CDatabaseLocator zoneTemp2 (RegionId, x-1, y); + CLigoData dataZoneTemp2; + getDocument ()->getLigoData (dataZoneTemp2, zoneTemp2); + if (dataZoneTemp2.SharingCutEdges[3] != dataZoneTemp.SharingCutEdges[2]) + { + dataZoneTemp2.SharingCutEdges[3] = dataZoneTemp.SharingCutEdges[2]; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp2, zoneTemp2)); + } + } + updateTrans (x-1, y); + } + if (dataZoneTemp.SharingMatNames[1] != dataZoneTemp.SharingMatNames[3]) + { + if (x < pBZR->getMaxX ()) + { // [x+1][y].left = [x][y].right + //_Zones[(x+1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[2] = dataZoneTemp.SharingCutEdges[3]; + CDatabaseLocator zoneTemp2 (RegionId, x+1, y); + CLigoData dataZoneTemp2; + getDocument ()->getLigoData (dataZoneTemp2, zoneTemp2); + if (dataZoneTemp2.SharingCutEdges[2] != dataZoneTemp.SharingCutEdges[3]) + { + dataZoneTemp2.SharingCutEdges[2] = dataZoneTemp.SharingCutEdges[3]; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp2, zoneTemp2)); + } + } + updateTrans (x+1, y); + } + if (dataZoneTemp.SharingMatNames[0] != dataZoneTemp.SharingMatNames[1]) + { + if (y > pBZR->getMinY ()) + { // [x][y-1].up = [x][y].down + //_Zones[(x-pBZR->getMinX ())+(y-1-pBZR->getMinY ())*stride].SharingCutEdges[0] = dataZoneTemp.SharingCutEdges[1]; + CDatabaseLocator zoneTemp2 (RegionId, x, y-1); + CLigoData dataZoneTemp2; + getDocument ()->getLigoData (dataZoneTemp2, zoneTemp2); + if (dataZoneTemp2.SharingCutEdges[0] != dataZoneTemp.SharingCutEdges[1]) + { + dataZoneTemp2.SharingCutEdges[0] = dataZoneTemp.SharingCutEdges[1]; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp2, zoneTemp2)); + } + } + updateTrans (x, y-1); + } + if (dataZoneTemp.SharingMatNames[2] != dataZoneTemp.SharingMatNames[3]) + { + if (y < pBZR->getMaxY ()) + { // [x][y+1].down = [x][y].up + //_Zones[(x-pBZR->getMinX ())+(y+1-pBZR->getMinY ())*stride].SharingCutEdges[1] = dataZoneTemp.SharingCutEdges[0]; + CDatabaseLocator zoneTemp2 (RegionId, x, y+1); + CLigoData dataZoneTemp2; + getDocument ()->getLigoData (dataZoneTemp2, zoneTemp2); + if (dataZoneTemp2.SharingCutEdges[1] != dataZoneTemp.SharingCutEdges[0]) + { + dataZoneTemp2.SharingCutEdges[1] = dataZoneTemp.SharingCutEdges[0]; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp2, zoneTemp2)); + } + } + updateTrans (x, y+1); + } + } +} + +// --------------------------------------------------------------------------- +void CBuilderZoneRegion::addToUpdateAndCreate (CBuilderZoneRegion *pBZRfrom, sint32 sharePos, sint32 x, sint32 y, const string &sNewMat, void *pInt1, void *pInt2) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + CToUpdate *ptCreate = (CToUpdate*)pInt1; + CToUpdate *ptUpdate = (CToUpdate*)pInt2; + sint32 stride = (1+pBZR->getMaxX ()-pBZR->getMinX ()); + + CDatabaseLocator locator; + if (getDocument ()->getZoneAmongRegions (locator, pBZRfrom, x, y)) + { + CLigoData data; + getDocument ()->getLigoData (data, locator); + if (data.SharingMatNames[sharePos] != sNewMat) + { + data.SharingMatNames[sharePos] = sNewMat; + getDocument ()->addModification (new CActionLigoTile (data, locator)); + } + pBZRfrom->del (x, y, true, ptUpdate); + ptCreate->add (pBZRfrom, x, y, sNewMat); + } +} + +// --------------------------------------------------------------------------- +void CBuilderZoneRegion::putTransitions (sint32 inX, sint32 inY, const SPiece &rMask, const string &MatName, + void *pInternal) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + CToUpdate tCreate; // Transition to create + CToUpdate *ptUpdate = (CToUpdate*)pInternal; // Transition to update + + sint32 i, j, k, l, m; + sint32 x = inX, y = inY; + for (j = 0; j < rMask.h; ++j) + for (i = 0; i < rMask.w; ++i) + if (rMask.Tab[i+j*rMask.w]) + { + for (k = -1; k <= 1; ++k) + for (l = -1; l <= 1; ++l) + { + CBuilderZoneRegion *pBZR2 = this; + CDatabaseLocator locator; + if (getDocument ()->getZoneAmongRegions (locator, pBZR2, inX+i+l, inY+j+k)) + tCreate.add (pBZR2, inX+i+l, inY+j+k, MatName); + } + } + + // Check coherency of the transition to update + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + CBuilderZoneRegion *pBZR2 = tCreate.getBZR(m); + x = tCreate.getX(m); + y = tCreate.getY(m); + string putMat = tCreate.getMat(m); + + //if ((x < pBZR->getMinX ())||(x > pBZR->getMaxX ())||(y < pBZR->getMinY ())||(y > pBZR->getMaxY ())) + // continue; + + CDatabaseLocator zoneTemp (pBZR2->RegionId, x, y); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + + if (!((dataZoneTemp.SharingMatNames[0] == dataZoneTemp.SharingMatNames[1])&& + (dataZoneTemp.SharingMatNames[1] == dataZoneTemp.SharingMatNames[2])&& + (dataZoneTemp.SharingMatNames[2] == dataZoneTemp.SharingMatNames[3]))) + pBZR2->del (x, y, true, ptUpdate); + + // Check to see material can be posed + uint corner; + for (corner = 0; corner < 4; corner++) + { + string newMat = getNextMatInTree (putMat, dataZoneTemp.SharingMatNames[corner]); + + // Can't be posed ? + if (newMat == STRING_UNUSED) + break; + } + if ( (corner < 4) && (m != 0) ) + { + // The material can't be paused + dataZoneTemp.SharingMatNames[0] = STRING_UNUSED; + dataZoneTemp.SharingMatNames[1] = STRING_UNUSED; + dataZoneTemp.SharingMatNames[2] = STRING_UNUSED; + dataZoneTemp.SharingMatNames[3] = STRING_UNUSED; + + // Don't propagate any more + } + else + { + // Expand material for the 1st quarter + string newMat = getNextMatInTree (putMat, dataZoneTemp.SharingMatNames[0]); + if (newMat != dataZoneTemp.SharingMatNames[0]) + { // Update the quarter + if (dataZoneTemp.SharingMatNames[0] != newMat) + { + dataZoneTemp.SharingMatNames[0] = newMat; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + + addToUpdateAndCreate (pBZR2, 1, x-1, y, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate (pBZR2, 3, x-1, y-1, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate (pBZR2, 2, x, y-1, newMat, &tCreate, ptUpdate); + } + + // Expand material for the 2nd quarter + newMat = getNextMatInTree (putMat, dataZoneTemp.SharingMatNames[1]); + if (newMat != dataZoneTemp.SharingMatNames[1]) + { // Update the quarter + //if (_Builder->getZoneMask(x,y)) + if (dataZoneTemp.SharingMatNames[1] != newMat) + { + dataZoneTemp.SharingMatNames[1] = newMat; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + + addToUpdateAndCreate (pBZR2, 0, x+1, y, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate (pBZR2, 2, x+1, y-1, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate (pBZR2, 3, x, y-1, newMat, &tCreate, ptUpdate); + } + + // Expand material for the 3rd quarter + newMat = getNextMatInTree (putMat, dataZoneTemp.SharingMatNames[2]); + if (newMat != dataZoneTemp.SharingMatNames[2]) + { // Update the quarter + //if (_Builder->getZoneMask(x,y)) + if (dataZoneTemp.SharingMatNames[2] != newMat) + { + dataZoneTemp.SharingMatNames[2] = newMat; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + + addToUpdateAndCreate (pBZR2, 3, x-1, y, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate (pBZR2, 1, x-1, y+1, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate (pBZR2, 0, x, y+1, newMat, &tCreate, ptUpdate); + } + + // Expand material for the 4th quarter + newMat = getNextMatInTree (putMat, dataZoneTemp.SharingMatNames[3]); + if (newMat != dataZoneTemp.SharingMatNames[3]) + { // Update the quarter + //if (_Builder->getZoneMask(x,y)) + if (dataZoneTemp.SharingMatNames[3] != newMat) + { + dataZoneTemp.SharingMatNames[3] = newMat; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + + addToUpdateAndCreate (pBZR2, 2, x+1, y, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate (pBZR2, 0, x+1, y+1, newMat, &tCreate, ptUpdate); + addToUpdateAndCreate (pBZR2, 1, x, y+1, newMat, &tCreate, ptUpdate); + } + } + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + + // Delete transitions that are inside the mask + for (j = 0; j < rMask.h; ++j) + for (i = 0; i < rMask.w; ++i) + if (rMask.Tab[i+j*rMask.w]) + { + tCreate.del (inX+i, inY+j); + } + + // For all transition to update choose the cut edge + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + const CZoneRegion *pBZR2 = &(getDocument ()->getZoneRegion (tCreate.getBZR(m)->RegionId)); + x = tCreate.getX(m); + y = tCreate.getY(m); + + if ((x < pBZR2->getMinX ())||(x > pBZR2->getMaxX ())||(y < pBZR2->getMinY ())||(y > pBZR2->getMaxY ())) + continue; + + CDatabaseLocator zoneTemp (tCreate.getBZR(m)->RegionId, x, y); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + CLigoData dataZoneTempOriginal = dataZoneTemp; + + for (i = 0; i < 4; ++i) + { + uint8 nCut = (uint8)(1.0f+NLMISC::frand(2.0f)); + NLMISC::clamp (nCut, (uint8)1, (uint8)2); + dataZoneTemp.SharingCutEdges[i] = nCut; + } + + if (dataZoneTempOriginal != dataZoneTemp) + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + + // Propagate + if (dataZoneTemp.SharingMatNames[0] != dataZoneTemp.SharingMatNames[2]) + { // [x-1][y].right = [x][y].left + CBuilderZoneRegion *pBZR3 = tCreate.getBZR(m); + CDatabaseLocator pZU; + if (getDocument ()->getZoneAmongRegions (pZU, pBZR3, x-1, y)) + { + CLigoData data; + getDocument ()->getLigoData (data, pZU); + if (data.SharingCutEdges[3] != dataZoneTemp.SharingCutEdges[2]) + { + data.SharingCutEdges[3] = dataZoneTemp.SharingCutEdges[2]; + getDocument ()->addModification (new CActionLigoTile (data, pZU)); + } + ptUpdate->add (pBZR3, x-1, y, ""); + } + } + else + { + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + if (dataZoneTemp.SharingCutEdges[2] != 0) + { + dataZoneTemp.SharingCutEdges[2] = 0; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + } + + if (dataZoneTemp.SharingMatNames[0] != dataZoneTemp.SharingMatNames[1]) + { // [x][y-1].up = [x][y].down + CBuilderZoneRegion *pBZR3 = tCreate.getBZR(m); + CDatabaseLocator pZU; + if (getDocument ()->getZoneAmongRegions (pZU, pBZR3, x, y-1)) + { + CLigoData data; + getDocument ()->getLigoData (data, pZU); + if (data.SharingCutEdges[0] != dataZoneTemp.SharingCutEdges[1]) + { + data.SharingCutEdges[0] = dataZoneTemp.SharingCutEdges[1]; + getDocument ()->addModification (new CActionLigoTile (data, pZU)); + } + ptUpdate->add (pBZR3, x, y-1, ""); + } + } + else + { + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + if (dataZoneTemp.SharingCutEdges[1] != 0) + { + dataZoneTemp.SharingCutEdges[1] = 0; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + } + + if (dataZoneTemp.SharingMatNames[3] != dataZoneTemp.SharingMatNames[1]) + { // [x+1][y].left = [x][y].right + CBuilderZoneRegion *pBZR3 = tCreate.getBZR(m); + CDatabaseLocator pZU; + if (getDocument ()->getZoneAmongRegions (pZU, pBZR3, x+1, y)) + { + CLigoData data; + getDocument ()->getLigoData (data, pZU); + if (data.SharingCutEdges[2] != dataZoneTemp.SharingCutEdges[3]) + { + data.SharingCutEdges[2] = dataZoneTemp.SharingCutEdges[3]; + getDocument ()->addModification (new CActionLigoTile (data, pZU)); + } + ptUpdate->add (pBZR3, x+1, y, ""); + } + } + else + { + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + if (dataZoneTemp.SharingCutEdges[3] != 0) + { + dataZoneTemp.SharingCutEdges[3] = 0; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + } + + if (dataZoneTemp.SharingMatNames[2] != dataZoneTemp.SharingMatNames[3]) + { // [x][y+1].down = [x][y].up + CBuilderZoneRegion *pBZR3 = tCreate.getBZR(m); + CDatabaseLocator pZU; + if (getDocument ()->getZoneAmongRegions (pZU, pBZR3, x, y+1)) + { + CLigoData data; + getDocument ()->getLigoData (data, pZU); + if (data.SharingCutEdges[1] = dataZoneTemp.SharingCutEdges[0]) + { + data.SharingCutEdges[1] = dataZoneTemp.SharingCutEdges[0]; + getDocument ()->addModification (new CActionLigoTile (data, pZU)); + } + ptUpdate->add (pBZR3, x, y+1, ""); + } + } + else + { + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + if (dataZoneTemp.SharingCutEdges[0] = 0) + { + dataZoneTemp.SharingCutEdges[0] = 0; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } + } + } + + // Delete in tUpdate each element in common with tCreate + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + x = tCreate.getX(m); + y = tCreate.getY(m); + ptUpdate->del (x,y); + } + + // Finally update all transition + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + const CZoneRegion *pBZR2 = &(getDocument ()->getZoneRegion (tCreate.getBZR(m)->RegionId)); + x = tCreate.getX(m); + y = tCreate.getY(m); + + if ((x >= pBZR2->getMinX ())&&(x <= pBZR2->getMaxX ())&&(y >= pBZR2->getMinY ())&&(y <= pBZR2->getMaxY ())) + tCreate.getBZR(m)->updateTrans (x, y); + } + for (m = 0; m < (sint32)ptUpdate->size(); ++m) + { + const CZoneRegion *pBZR2 = &(getDocument ()->getZoneRegion (tCreate.getBZR(m)->RegionId)); + x = ptUpdate->getX(m); + y = ptUpdate->getY(m); + if ((x >= pBZR2->getMinX ())&&(x <= pBZR2->getMaxX ())&&(y >= pBZR2->getMinY ())&&(y <= pBZR2->getMaxY ())) + tCreate.getBZR(m)->updateTrans (x, y); + } + + // Cross material + for (m = 0; m < (sint32)tCreate.size(); ++m) + { + const CZoneRegion *pBZR2 = &(getDocument ()->getZoneRegion (tCreate.getBZR(m)->RegionId)); + x = tCreate.getX(m); + y = tCreate.getY(m); + + + CDatabaseLocator zoneTemp (RegionId, x, y); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + + std::set matNameSet; + for (i = 0; i < 4; ++i) + matNameSet.insert (dataZoneTemp.SharingMatNames[i]); + + if (((dataZoneTemp.SharingMatNames[0] == dataZoneTemp.SharingMatNames[3]) && + (dataZoneTemp.SharingMatNames[1] == dataZoneTemp.SharingMatNames[2]) && + (dataZoneTemp.SharingMatNames[0] != dataZoneTemp.SharingMatNames[1])) + || (matNameSet.size()>2)) + { + + _ZeBank->resetSelection (); + _ZeBank->addOrSwitch ("material", tCreate.getMat(m)); + _ZeBank->addAndSwitch ("size", "1x1"); + vector vElts; + _ZeBank->getSelection (vElts); + if (vElts.size() == 0) + return; + sint32 nRan = (sint32)(NLMISC::frand((float)vElts.size())); + NLMISC::clamp (nRan, (sint32)0, (sint32)(vElts.size()-1)); + CZoneBankElement *pZBE = vElts[nRan]; + nRan = (uint32)(NLMISC::frand (1.0) * 4); + NLMISC::clamp (nRan, (sint32)0, (sint32)3); + uint8 rot = (uint8)nRan; + nRan = (uint32)(NLMISC::frand (1.0) * 2); + NLMISC::clamp (nRan, (sint32)0, (sint32)1); + uint8 flip = (uint8)nRan; + + tCreate.getBZR(m)->add (x, y, rot, flip, pZBE); + } + } + +} + + +// --------------------------------------------------------------------------- +/*void CBuilderZoneRegion::putTransition (sint32 x, sint32 y, const string &MatName) +{ + const string &rSZone = getName (x, y); + if (rSZone != STRING_UNUSED) + return; + + sint32 stride = (1+pBZR->getMaxX ()-pBZR->getMinX ()); + sint32 m; + // Set Random edges + for (m = 0; m < 4; ++m) + { + uint8 nCut = (uint8)(1.0f+NLMISC::frand(2.0f)); + NLMISC::clamp (nCut, (uint8)1, (uint8)2); + _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[m] = nCut; + } + // Propagate + if (x > pBZR->getMinX ()) + { // [x-1][y].right = [x][y].left + _Zones[(x-1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[3] = + _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[2]; + } + if (y > pBZR->getMinY ()) + { // [x][y-1].up = [x][y].down + _Zones[(x-pBZR->getMinX ())+(y-1-pBZR->getMinY ())*stride].SharingCutEdges[0] = + _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[1]; + } + if (x < pBZR->getMaxX ()) + { // [x+1][y].left = [x][y].right + _Zones[(x+1-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[2] = + _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[3]; + } + if (y < pBZR->getMaxY ()) + { // [x][y+1].down = [x][y].up + _Zones[(x-pBZR->getMinX ())+(y+1-pBZR->getMinY ())*stride].SharingCutEdges[1] = + _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingCutEdges[0]; + } + + // Update Transitions + updateTrans (x, y); + if (_Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[0] != _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[2]) + updateTrans (x-1, y); + if (_Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[1] != _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[3]) + updateTrans (x+1, y); + if (_Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[0] != _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[1]) + updateTrans (x, y-1); + if (_Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[2] != _Zones[(x-pBZR->getMinX ())+(y-pBZR->getMinY ())*stride].SharingMatNames[3]) + updateTrans (x, y+1); +} +*/ +// --------------------------------------------------------------------------- +struct STrans +{ + uint8 Num; + uint8 Rot; + uint8 Flip; +}; + +// --------------------------------------------------------------------------- +STrans TranConvTable[128] = +{ + { 0,0,0 }, // Quart = 0, CutEdge = 0, Np = 0 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 0, Np = 1 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 1, Np = 0 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 1, Np = 1 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 2, Np = 0 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 2, Np = 1 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 3, Np = 0 UNUSED + { 0,0,0 }, // Quart = 0, CutEdge = 3, Np = 1 UNUSED + + { 6,0,0 }, // Quart = 1, CutEdge = 0, Np = 0 + { 6,3,1 }, // Quart = 1, CutEdge = 0, Np = 1 + { 7,0,0 }, // Quart = 1, CutEdge = 1, Np = 0 + { 7,0,0 }, // Quart = 1, CutEdge = 1, Np = 1 + { 7,3,1 }, // Quart = 1, CutEdge = 2, Np = 0 + { 7,3,1 }, // Quart = 1, CutEdge = 2, Np = 1 + { 8,0,0 }, // Quart = 1, CutEdge = 3, Np = 0 + { 8,3,1 }, // Quart = 1, CutEdge = 3, Np = 1 + + { 7,0,1 }, // Quart = 2, CutEdge = 0, Np = 0 + { 7,0,1 }, // Quart = 2, CutEdge = 0, Np = 1 + { 6,0,1 }, // Quart = 2, CutEdge = 1, Np = 0 + { 6,1,0 }, // Quart = 2, CutEdge = 1, Np = 1 + { 8,1,0 }, // Quart = 2, CutEdge = 2, Np = 0 + { 8,0,1 }, // Quart = 2, CutEdge = 2, Np = 1 + { 7,1,0 }, // Quart = 2, CutEdge = 3, Np = 0 + { 7,1,0 }, // Quart = 2, CutEdge = 3, Np = 1 + + { 0,0,0 }, // Quart = 3, CutEdge = 0, Np = 0 + { 0,0,1 }, // Quart = 3, CutEdge = 0, Np = 1 + { 1,0,1 }, // Quart = 3, CutEdge = 1, Np = 0 + { 1,0,1 }, // Quart = 3, CutEdge = 1, Np = 1 + { 1,0,0 }, // Quart = 3, CutEdge = 2, Np = 0 + { 1,0,0 }, // Quart = 3, CutEdge = 2, Np = 1 + { 2,0,0 }, // Quart = 3, CutEdge = 3, Np = 0 + { 2,0,1 }, // Quart = 3, CutEdge = 3, Np = 1 + + { 7,3,0 }, // Quart = 4, CutEdge = 0, Np = 0 + { 7,3,0 }, // Quart = 4, CutEdge = 0, Np = 1 + { 8,3,0 }, // Quart = 4, CutEdge = 1, Np = 0 + { 8,2,1 }, // Quart = 4, CutEdge = 1, Np = 1 + { 6,3,0 }, // Quart = 4, CutEdge = 2, Np = 0 + { 6,2,1 }, // Quart = 4, CutEdge = 2, Np = 1 + { 7,2,1 }, // Quart = 4, CutEdge = 3, Np = 0 + { 7,2,1 }, // Quart = 4, CutEdge = 3, Np = 1 + + { 0,3,0 }, // Quart = 5, CutEdge = 0, Np = 0 + { 0,3,1 }, // Quart = 5, CutEdge = 0, Np = 1 + { 1,3,1 }, // Quart = 5, CutEdge = 1, Np = 0 + { 1,3,1 }, // Quart = 5, CutEdge = 1, Np = 1 + { 1,3,0 }, // Quart = 5, CutEdge = 2, Np = 0 + { 1,3,0 }, // Quart = 5, CutEdge = 2, Np = 1 + { 2,3,0 }, // Quart = 5, CutEdge = 3, Np = 0 + { 2,3,1 }, // Quart = 5, CutEdge = 3, Np = 1 + + { 0,0,0 }, // Quart = 6, CutEdge = 0, Np = 0 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 0, Np = 1 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 1, Np = 0 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 1, Np = 1 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 2, Np = 0 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 2, Np = 1 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 3, Np = 0 UNUSED + { 0,0,0 }, // Quart = 6, CutEdge = 3, Np = 1 UNUSED + + { 5,2,0 }, // Quart = 7, CutEdge = 0, Np = 0 + { 5,1,1 }, // Quart = 7, CutEdge = 0, Np = 1 + { 4,1,1 }, // Quart = 7, CutEdge = 1, Np = 0 + { 4,1,1 }, // Quart = 7, CutEdge = 1, Np = 1 + { 4,2,0 }, // Quart = 7, CutEdge = 2, Np = 0 + { 4,2,0 }, // Quart = 7, CutEdge = 2, Np = 1 + { 3,2,0 }, // Quart = 7, CutEdge = 3, Np = 0 + { 3,1,1 }, // Quart = 7, CutEdge = 3, Np = 1 + + { 8,2,0 }, // Quart = 8, CutEdge = 0, Np = 0 + { 8,1,1 }, // Quart = 8, CutEdge = 0, Np = 1 + { 7,1,1 }, // Quart = 8, CutEdge = 1, Np = 0 + { 7,1,1 }, // Quart = 8, CutEdge = 1, Np = 1 + { 7,2,0 }, // Quart = 8, CutEdge = 2, Np = 0 + { 7,2,0 }, // Quart = 8, CutEdge = 2, Np = 1 + { 6,2,0 }, // Quart = 8, CutEdge = 3, Np = 0 + { 6,1,1 }, // Quart = 8, CutEdge = 3, Np = 1 + + { 0,0,0 }, // Quart = 9, CutEdge = 0, Np = 0 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 0, Np = 1 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 1, Np = 0 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 1, Np = 1 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 2, Np = 0 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 2, Np = 1 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 3, Np = 0 UNUSED + { 0,0,0 }, // Quart = 9, CutEdge = 3, Np = 1 UNUSED + + { 2,1,0 }, // Quart = 10, CutEdge = 0, Np = 0 + { 2,1,1 }, // Quart = 10, CutEdge = 0, Np = 1 + { 1,1,1 }, // Quart = 10, CutEdge = 1, Np = 0 + { 1,1,1 }, // Quart = 10, CutEdge = 1, Np = 1 + { 1,1,0 }, // Quart = 10, CutEdge = 2, Np = 0 + { 1,1,0 }, // Quart = 10, CutEdge = 2, Np = 1 + { 0,1,0 }, // Quart = 10, CutEdge = 3, Np = 0 + { 0,1,1 }, // Quart = 10, CutEdge = 3, Np = 1 + + { 4,3,0 }, // Quart = 11, CutEdge = 0, Np = 0 + { 4,3,0 }, // Quart = 11, CutEdge = 0, Np = 1 + { 5,3,0 }, // Quart = 11, CutEdge = 1, Np = 0 + { 5,2,1 }, // Quart = 11, CutEdge = 1, Np = 1 + { 3,3,0 }, // Quart = 11, CutEdge = 2, Np = 0 + { 3,2,1 }, // Quart = 11, CutEdge = 2, Np = 1 + { 4,2,1 }, // Quart = 11, CutEdge = 3, Np = 0 + { 4,2,1 }, // Quart = 11, CutEdge = 3, Np = 1 + + { 2,2,0 }, // Quart = 12, CutEdge = 0, Np = 0 + { 2,2,1 }, // Quart = 12, CutEdge = 0, Np = 1 + { 1,2,1 }, // Quart = 12, CutEdge = 1, Np = 0 + { 1,2,1 }, // Quart = 12, CutEdge = 1, Np = 1 + { 1,2,0 }, // Quart = 12, CutEdge = 2, Np = 0 + { 1,2,0 }, // Quart = 12, CutEdge = 2, Np = 1 + { 0,2,0 }, // Quart = 12, CutEdge = 3, Np = 0 + { 0,2,1 }, // Quart = 12, CutEdge = 3, Np = 1 + + { 4,0,1 }, // Quart = 13, CutEdge = 0, Np = 0 + { 4,0,1 }, // Quart = 13, CutEdge = 0, Np = 1 + { 3,1,0 }, // Quart = 13, CutEdge = 1, Np = 0 + { 3,0,1 }, // Quart = 13, CutEdge = 1, Np = 1 + { 5,1,0 }, // Quart = 13, CutEdge = 2, Np = 0 + { 5,0,1 }, // Quart = 13, CutEdge = 2, Np = 1 + { 4,1,0 }, // Quart = 13, CutEdge = 3, Np = 0 + { 4,1,0 }, // Quart = 13, CutEdge = 3, Np = 1 + + { 3,0,0 }, // Quart = 14, CutEdge = 0, Np = 0 + { 3,3,1 }, // Quart = 14, CutEdge = 0, Np = 1 + { 4,0,0 }, // Quart = 14, CutEdge = 1, Np = 0 + { 4,0,0 }, // Quart = 14, CutEdge = 1, Np = 1 + { 4,3,1 }, // Quart = 14, CutEdge = 2, Np = 0 + { 4,3,1 }, // Quart = 14, CutEdge = 2, Np = 1 + { 5,0,0 }, // Quart = 14, CutEdge = 3, Np = 0 + { 5,3,1 }, // Quart = 14, CutEdge = 3, Np = 1 + + { 0,0,0 }, // Quart = 15, CutEdge = 0, Np = 0 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 0, Np = 1 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 1, Np = 0 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 1, Np = 1 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 2, Np = 0 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 2, Np = 1 UNUSED + { 0,0,0 }, // Quart = 15, CutEdge = 3, Np = 0 UNUSED + { 0,0,0 } // Quart = 15, CutEdge = 3, Np = 1 UNUSED +}; + +// --------------------------------------------------------------------------- +void CBuilderZoneRegion::updateTrans (sint32 x, sint32 y, CZoneBankElement *pElt) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + if ((x < pBZR->getMinX ()) || (x > pBZR->getMaxX ()) || (y < pBZR->getMinY ()) || (y > pBZR->getMaxY ())) + return; + + //if (!_Builder->getZoneMask(x,y)) + // return; + + // Interpret the transition info + x -= pBZR->getMinX (); + y -= pBZR->getMinY (); + sint32 m; + // Calculate the number of material around with transition info + std::set matNameSet; + + CDatabaseLocator zoneTemp (RegionId, x+pBZR->getMinX (), y+pBZR->getMinY ()); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + CLigoData dataZoneTempOriginal = dataZoneTemp; + + for (m = 0; m < 4; ++m) + matNameSet.insert (dataZoneTemp.SharingMatNames[m]); + + if (matNameSet.size() == 1) + { + if (dataZoneTemp.SharingMatNames[0] == STRING_UNUSED) + { + del (x+pBZR->getMinX (), y+pBZR->getMinY ()); + // set (x+pBZR->getMinX (), y+pBZR->getMinY (), 0, 0, STRING_UNUSED, false); + return; + } + else + { + CZoneBankElement *pZBE = _ZeBank->getElementByZoneName (dataZoneTemp.ZoneName); + if ((pZBE != NULL) && (pZBE->getCategory("material")==dataZoneTemp.SharingMatNames[0])) + return; + _ZeBank->resetSelection (); + _ZeBank->addOrSwitch ("material", dataZoneTemp.SharingMatNames[0]); + _ZeBank->addAndSwitch ("size", "1x1"); + vector vElts; + _ZeBank->getSelection (vElts); + if (vElts.size() == 0) + return; + sint32 nRan = (sint32)(NLMISC::frand((float)vElts.size())); + NLMISC::clamp (nRan, (sint32)0, (sint32)(vElts.size()-1)); + pZBE = vElts[nRan]; + nRan = (uint32)(NLMISC::frand (1.0) * 4); + NLMISC::clamp (nRan, (sint32)0, (sint32)3); + uint8 rot = (uint8)nRan; + nRan = (uint32)(NLMISC::frand (1.0) * 2); + NLMISC::clamp (nRan, (sint32)0, (sint32)1); + uint8 flip = (uint8)nRan; + + set (x+pBZR->getMinX (), y+pBZR->getMinY (), 0, 0, pZBE->getName(), false); + setRot (x+pBZR->getMinX (), y+pBZR->getMinY (), rot); + setFlip (x+pBZR->getMinX (), y+pBZR->getMinY (), flip); + return; + } + } + + // No 2 materials so the transition system dont work + if (matNameSet.size() != 2) + return; + + std::set::iterator it = matNameSet.begin(); + string sMatA = *it; + ++it; + string sMatB = *it; + + _ZeBank->resetSelection (); + _ZeBank->addOrSwitch ("transname", sMatA + "-" + sMatB); + vector selection; + _ZeBank->getSelection (selection); + if (selection.size() == 0) + { + string sTmp = sMatA; + sMatA = sMatB; + sMatB = sTmp; + _ZeBank->resetSelection (); + _ZeBank->addOrSwitch ("transname", sMatA + "-" + sMatB); + _ZeBank->getSelection (selection); + } + + if (selection.size() == 0) + return; + + // Convert the sharingCutEdges and SharingNames to the num and type of transition + uint8 nQuart = 0; // 0-MatA 1-MatB + for (m = 0; m < 4; ++m) + if (dataZoneTemp.SharingMatNames[m] == sMatB) + nQuart |= (1<0, 2->1) + if ((nQuart == 4)||(nQuart == 5)||(nQuart == 7)||(nQuart == 8)||(nQuart == 10)||(nQuart == 11)) + { + if (dataZoneTemp.SharingCutEdges[0] == 2) + nCutEdge |= 1 << nPosCorner; + ++nPosCorner; + } + else + { + dataZoneTemp.SharingCutEdges[0] = 0; + } + + // Same for down edge + if ((nQuart == 1)||(nQuart == 2)||(nQuart == 5)||(nQuart == 10)||(nQuart == 13)||(nQuart == 14)) + { + if (dataZoneTemp.SharingCutEdges[1] == 2) + nCutEdge |= 1 << nPosCorner; + ++nPosCorner; + } + else + { + dataZoneTemp.SharingCutEdges[1] = 0; + } + + // Same for left edge + if ((nQuart == 1)||(nQuart == 3)||(nQuart == 4)||(nQuart == 11)||(nQuart == 12)||(nQuart == 14)) + { + if (dataZoneTemp.SharingCutEdges[2] == 2) + nCutEdge |= 1 << nPosCorner; + ++nPosCorner; + } + else + { + dataZoneTemp.SharingCutEdges[2] = 0; + } + + // Same for right edge + if ((nQuart == 2)||(nQuart == 3)||(nQuart == 7)||(nQuart == 8)||(nQuart == 12)||(nQuart == 13)) + { + if (dataZoneTemp.SharingCutEdges[3] == 2) + nCutEdge |= 1 << nPosCorner; + ++nPosCorner; + } + else + { + dataZoneTemp.SharingCutEdges[3] = 0; + } + + nlassert (nPosCorner == 2); // If not this means that more than 2 edges are cut which is not possible + + STrans Trans, TransTmp1, TransTmp2; + + TransTmp1 = TranConvTable[nQuart*8+2*nCutEdge+0]; + TransTmp2 = TranConvTable[nQuart*8+2*nCutEdge+1]; + + // Choose one or the two + sint32 nTrans = (sint32)(NLMISC::frand(2.0f)); + NLMISC::clamp (nTrans, (sint32)0, (sint32)1); + if (nTrans == 0) + Trans = TransTmp1; + else + Trans = TransTmp2; + + _ZeBank->addAndSwitch ("transnum", NLMISC::toString(Trans.Num)); + _ZeBank->getSelection (selection); + + if (selection.size() > 0) + { + if (pElt != NULL) + { + dataZoneTemp.ZoneName = pElt->getName(); + } + else + { + nTrans = (uint32)(NLMISC::frand (1.0) * selection.size()); + NLMISC::clamp (nTrans, (sint32)0, (sint32)(selection.size()-1)); + dataZoneTemp.ZoneName = selection[nTrans]->getName(); + } + dataZoneTemp.PosX = dataZoneTemp.PosY = 0; + dataZoneTemp.Rot = Trans.Rot; + dataZoneTemp.Flip = Trans.Flip; + } + if (dataZoneTempOriginal != dataZoneTemp) + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); +} + +// --------------------------------------------------------------------------- +string CBuilderZoneRegion::getNextMatInTree (const string &sMatA, const string &sMatB) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + uint32 i, posA = 10000, posB = 10000; + + if (sMatA == sMatB) + return sMatA; + + for (i = 0; i < _MatTree.size(); ++i) + { + if (_MatTree[i].Name == sMatA) + posA = i; + if (_MatTree[i].Name == sMatB) + posB = i; + } + if ((posA == 10000) || (posB == 10000)) + return STRING_UNUSED; + + vector vTemp; + tryPath (posA, posB, vTemp); + if (vTemp.size() <= 1) + return STRING_UNUSED; + else + return _MatTree[vTemp[1]].Name; +} + +// --------------------------------------------------------------------------- +struct SNode +{ + sint32 NodePos, Dist, PrevNodePos; + + SNode() + { + NodePos = Dist = PrevNodePos = -1; + } +}; + +// --------------------------------------------------------------------------- +// Find the fastest way between posA and posB in the MatTree (Dijkstra) +void CBuilderZoneRegion::tryPath (uint32 posA, uint32 posB, vector &vPath) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + // Build the adjascence matrix + vector matAdj; + sint32 nNumNodes = _MatTree.size(); + sint32 i, j, cost; + matAdj.resize (nNumNodes*nNumNodes, -1); + for (i = 0; i < nNumNodes; ++i) + for (j = 0; j < (sint32)_MatTree[i].Arcs.size(); ++j) + matAdj[i+_MatTree[i].Arcs[j]*nNumNodes] = 1; + + vector vNodes; // NodesPos == index + vNodes.resize (nNumNodes); + for (i = 0; i < nNumNodes; ++i) + vNodes[i].NodePos = i; + vNodes[posA].Dist = 0; + + queue qNodes; + qNodes.push (vNodes[posA]); + + while (qNodes.size() > 0) + { + SNode node = qNodes.front (); + qNodes.pop (); + + for (i = 0; i < nNumNodes; ++i) + { + cost = matAdj[node.NodePos+i*nNumNodes]; + if (cost != -1) + { + if ((vNodes[i].Dist == -1) || (vNodes[i].Dist > (cost+node.Dist))) + { + vNodes[i].Dist = cost+node.Dist; + vNodes[i].PrevNodePos = node.NodePos; + qNodes.push (vNodes[i]); + } + } + } + } + + // Get path length + i = posB; + j = 0; + while (i != -1) + { + ++j; + i = vNodes[i].PrevNodePos; + } + + // Write the path in the good order (from posA to posB) + vPath.resize (j); + i = posB; + while (i != -1) + { + --j; + vPath[j] = i; + i = vNodes[i].PrevNodePos; + } +} + + + +// --------------------------------------------------------------------------- +void CBuilderZoneRegion::del (sint32 x, sint32 y, bool transition, void *pInternal) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + if (!_Builder->getZoneMask (x,y)) + return; + + const string &rSZone = pBZR->getName (x, y); + + CToUpdate *pUpdate = (CToUpdate *)pInternal; + + CZoneBankElement *pZBE = _ZeBank->getElementByZoneName (rSZone); + if (pZBE != NULL) + { + sint32 sizeX = pZBE->getSizeX(), sizeY = pZBE->getSizeY(); + sint32 posX = pBZR->getPosX (x, y), posY = pBZR->getPosY (x, y); + uint8 rot = pBZR->getRot (x, y); + uint8 flip = pBZR->getFlip (x, y); + sint32 i, j; + sint32 deltaX, deltaY; + + if (flip == 0) + { + switch (rot) + { + case 0: deltaX = -posX; deltaY = -posY; break; + case 1: deltaX = -(sizeY-1-posY); deltaY = -posX; break; + case 2: deltaX = -(sizeX-1-posX); deltaY = -(sizeY-1-posY); break; + case 3: deltaX = -posY; deltaY = -(sizeX-1-posX); break; + } + } + else + { + switch (rot) + { + case 0: deltaX = -(sizeX-1-posX); deltaY = -posY; break; + case 1: deltaX = -(sizeY-1-posY); deltaY = -(sizeX-1-posX); break; + case 2: deltaX = -posX; deltaY = -(sizeY-1-posY); break; + case 3: deltaX = -posY; deltaY = -posX; break; + } + } + + SPiece sMask; + sMask.Tab.resize (sizeX*sizeY); + for(i = 0; i < sizeX*sizeY; ++i) + sMask.Tab[i] = pZBE->getMask()[i]; + sMask.w = sizeX; + sMask.h = sizeY; + sMask.rotFlip (rot, flip); + + for (j = 0; j < sMask.h; ++j) + for (i = 0; i < sMask.w; ++i) + if (sMask.Tab[i+j*sMask.w]) + { + set (x+deltaX+i, y+deltaY+j, 0, 0, STRING_UNUSED, true); + setRot (x+deltaX+i, y+deltaY+j, 0); + setFlip (x+deltaX+i, y+deltaY+j, 0); + if (pUpdate != NULL) + { + pUpdate->add (this, x+deltaX+i, y+deltaY+j, ""); + } + } + if (!transition) + reduceMin (); + } + else + { + if ((x < pBZR->getMinX ()) || (x > pBZR->getMaxX ()) || (y < pBZR->getMinY ()) || (y > pBZR->getMaxY ())) + return; + + CDatabaseLocator zoneTemp (RegionId, x, y); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + CLigoData dataZoneTempOriginal = dataZoneTemp; + + dataZoneTemp.ZoneName = STRING_UNUSED; + dataZoneTemp.PosX = 0; + dataZoneTemp.PosY = 0; + + for (uint32 i = 0; i < 4; ++i) + { + dataZoneTemp.SharingMatNames[i] = STRING_UNUSED; + dataZoneTemp.SharingCutEdges[i] = 0; + } + + if (dataZoneTempOriginal != dataZoneTemp) + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + + } +} + +// --------------------------------------------------------------------------- + +void CBuilderZoneRegion::move (sint32 x, sint32 y) +{ + getDocument ()->addModification (new CActionLigoMove (getDocument()->regionIDToDatabaseElementID(RegionId), x, y)); +} + +// --------------------------------------------------------------------------- +uint32 CBuilderZoneRegion::countZones () +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + sint32 x, y; + + uint32 counter = 0; + + for (y = pBZR->getMinY (); y <= pBZR->getMaxY (); ++y) + for (x = pBZR->getMinX (); x <= pBZR->getMaxX (); ++x) + if (pBZR->getName (x, y) != STRING_UNUSED) + ++counter; + + return counter; +} + +// --------------------------------------------------------------------------- +void CBuilderZoneRegion::set (sint32 x, sint32 y, sint32 PosX, sint32 PosY, + const std::string &ZoneName, bool transition) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + // Do we need to resize ? + if ((x < pBZR->getMinX ()) || (x > pBZR->getMaxX ()) || + (y < pBZR->getMinY ()) || (y > pBZR->getMaxY ())) + { + sint32 newMinX = (xgetMinX ()?x:pBZR->getMinX ()), newMinY = (ygetMinY ()?y:pBZR->getMinY ()); + sint32 newMaxX = (x>pBZR->getMaxX ()?x:pBZR->getMaxX ()), newMaxY = (y>pBZR->getMaxY ()?y:pBZR->getMaxY ()); + + resize (newMinX, newMaxX, newMinY, newMaxY); + } + + CDatabaseLocator zoneTemp (RegionId, x, y); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + CLigoData dataZoneTempOriginal = dataZoneTemp; + + dataZoneTemp.ZoneName = ZoneName; + dataZoneTemp.PosX = (uint8)PosX; + dataZoneTemp.PosY = (uint8)PosY; + + if (!transition) + { + CZoneBankElement *pZBE = _ZeBank->getElementByZoneName (ZoneName); + if (pZBE == NULL) + return; + const string &sMatName = pZBE->getCategory ("material"); + if (sMatName == STRING_NO_CAT_TYPE) + return; + for (uint32 i = 0; i < 4; ++i) + { + dataZoneTemp.SharingMatNames[i] = sMatName; + dataZoneTemp.SharingCutEdges[i] = 0; + } + + if (dataZoneTempOriginal != dataZoneTemp) + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + + CBuilderZoneRegion *pBZR = this; + CDatabaseLocator pZU; + if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x-1, y-1)) + { + CLigoData data; + getDocument ()->getLigoData (data, pZU); + if (data.SharingMatNames[3] != sMatName) + { + data.SharingMatNames[3] = sMatName; + getDocument ()->addModification (new CActionLigoTile (data, pZU)); + } + } + pBZR = this; + if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x, y-1)) + { + CLigoData data; + getDocument ()->getLigoData (data, pZU); + if ((data.SharingMatNames[2] != sMatName) || (data.SharingMatNames[3] != sMatName)) + { + data.SharingMatNames[2] = sMatName; + data.SharingMatNames[3] = sMatName; + getDocument ()->addModification (new CActionLigoTile (data, pZU)); + } + } + pBZR = this; + if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x+1, y-1)) + { + CLigoData data; + getDocument ()->getLigoData (data, pZU); + if (data.SharingMatNames[2] != sMatName) + { + data.SharingMatNames[2] = sMatName; + getDocument ()->addModification (new CActionLigoTile (data, pZU)); + } + } + pBZR = this; + if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x-1, y)) + { + CLigoData data; + getDocument ()->getLigoData (data, pZU); + if ((data.SharingMatNames[1] != sMatName) || (data.SharingMatNames[3] != sMatName)) + { + data.SharingMatNames[1] = sMatName; + data.SharingMatNames[3] = sMatName; + getDocument ()->addModification (new CActionLigoTile (data, pZU)); + } + } + pBZR = this; + if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x+1, y)) + { + CLigoData data; + getDocument ()->getLigoData (data, pZU); + if ((data.SharingMatNames[0] != sMatName) || (data.SharingMatNames[2] != sMatName)) + { + data.SharingMatNames[0] = sMatName; + data.SharingMatNames[2] = sMatName; + getDocument ()->addModification (new CActionLigoTile (data, pZU)); + } + } + pBZR = this; + if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x-1, y+1)) + { + CLigoData data; + getDocument ()->getLigoData (data, pZU); + if (data.SharingMatNames[1] != sMatName) + { + data.SharingMatNames[1] = sMatName; + getDocument ()->addModification (new CActionLigoTile (data, pZU)); + } + } + pBZR = this; + if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x, y+1)) + { + CLigoData data; + getDocument ()->getLigoData (data, pZU); + if ((data.SharingMatNames[0] != sMatName) || (data.SharingMatNames[1] != sMatName)) + { + data.SharingMatNames[0] = sMatName; + data.SharingMatNames[1] = sMatName; + getDocument ()->addModification (new CActionLigoTile (data, pZU)); + } + } + pBZR = this; + if (getDocument ()->getZoneAmongRegions (pZU, pBZR, x+1, y+1)) + { + CLigoData data; + getDocument ()->getLigoData (data, pZU); + if (data.SharingMatNames[0] != sMatName) + { + data.SharingMatNames[0] = sMatName; + getDocument ()->addModification (new CActionLigoTile (data, pZU)); + } + } + } + else + { + if (dataZoneTempOriginal != dataZoneTemp) + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } +} + +// --------------------------------------------------------------------------- +void CBuilderZoneRegion::setRot (sint32 x, sint32 y, uint8 rot) +{ + CDatabaseLocator zoneTemp (RegionId, x, y); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + if (dataZoneTemp.Rot != rot) + { + dataZoneTemp.Rot = rot; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } +} + +// --------------------------------------------------------------------------- +void CBuilderZoneRegion::setFlip (sint32 x, sint32 y, uint8 flip) +{ + CDatabaseLocator zoneTemp (RegionId, x, y); + CLigoData dataZoneTemp; + getDocument ()->getLigoData (dataZoneTemp, zoneTemp); + if (dataZoneTemp.Flip != flip) + { + dataZoneTemp.Flip = flip; + getDocument ()->addModification (new CActionLigoTile (dataZoneTemp, zoneTemp)); + } +} + + +// --------------------------------------------------------------------------- +void CBuilderZoneRegion::reduceMin () +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + sint32 i, j; + + sint32 newMinX = pBZR->getMinX (), newMinY = pBZR->getMinY (); + sint32 newMaxX = pBZR->getMaxX (), newMaxY = pBZR->getMaxY (); + bool bCanSuppr; + + // Reduce the MinY + while (true) + { + if (newMinY == newMaxY) + break; + j = newMinY; + bCanSuppr = true; + for (i = newMinX; i <= newMaxX; ++i) + { + string str = pBZR->getName (i, j) ; + if (!str.empty() && (str != STRING_UNUSED)) + { + bCanSuppr = false; + break; + } + } + if (bCanSuppr) + ++newMinY; + else + break; + } + + // Reduce the MaxY + while (true) + { + if (newMinY == newMaxY) + break; + j = newMaxY; + bCanSuppr = true; + for (i = newMinX; i <= newMaxX; ++i) + { + string str = pBZR->getName (i, j) ; + if (!str.empty() && (str != STRING_UNUSED)) + { + bCanSuppr = false; + break; + } + } + if (bCanSuppr) + --newMaxY; + else + break; + } + + // Reduce the MinX + while (true) + { + if (newMinX == newMaxX) + break; + i = newMinX; + bCanSuppr = true; + for (j = newMinY; j <= newMaxY; ++j) + { + string str = pBZR->getName (i, j) ; + if (!str.empty() && (str != STRING_UNUSED)) + { + bCanSuppr = false; + break; + } + } + if (bCanSuppr) + ++newMinX; + else + break; + } + + // Reduce the MaxX + while (true) + { + if (newMinX == newMaxX) + break; + i = newMaxX; + bCanSuppr = true; + for (j = newMinY; j <= newMaxY; ++j) + { + string str = pBZR->getName (i, j) ; + if (!str.empty() && (str != STRING_UNUSED)) + { + bCanSuppr = false; + break; + } + } + if (bCanSuppr) + --newMaxX; + else + break; + } + + if ((newMinX != pBZR->getMinX ()) || (newMinY != pBZR->getMinY ()) || (newMaxX != pBZR->getMaxX ()) || (newMaxY != pBZR->getMaxY ())) + { + resize (newMinX, newMaxX, newMinY, newMaxY); + } +} + +// --------------------------------------------------------------------------- +void CBuilderZoneRegion::resize (sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY) +{ + const CZoneRegion *pBZR = &(getDocument ()->getZoneRegion (RegionId)); + if ((pBZR->getMinX ()!= newMinX) || (pBZR->getMaxX ()!= newMaxX) || (pBZR->getMinY ()!= newMinY) || (pBZR->getMaxY ()!= newMaxY)) + { + getDocument ()->addModification (new CActionLigoResize (getDocument()->regionIDToDatabaseElementID(RegionId), newMinX, newMaxX, newMinY, newMaxY)); + + } +} + +// --------------------------------------------------------------------------- diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone_region.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone_region.h index b657ca34d..68036d8d6 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone_region.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/builder_zone_region.h @@ -1,104 +1,104 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// This class is interface between all that is displayed in -// display/tools view and the game core - -#ifndef BUILDERZONEREGION_H -#define BUILDERZONEREGION_H - -// *************************************************************************** - -namespace NLLIGO -{ - class CZoneBank; - class CZoneBankElement; - struct SPiece; -} - -namespace NLMISC -{ - class IStream; -} - -class CBuilderZone; - -// *************************************************************************** - -// CZoneRegion contains informations about the zones painted -class CBuilderZoneRegion -{ - -public: - uint RegionId; - -public: - - CBuilderZoneRegion (uint regionId); - - - // New interface - bool init (NLLIGO::CZoneBank *pBank, CBuilderZone *pBuilder, std::string &error); - void add (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt); - void invertCutEdge (sint32 x, sint32 y, uint8 cePos); - void cycleTransition (sint32 x, sint32 y); - bool addNotPropagate (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt); - void addForce (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt); - void del (sint32 x, sint32 y, bool transition=false, void *pInternal=NULL); - void move (sint32 x, sint32 y); - uint32 countZones (); - void reduceMin (); - - - // Accessors - -private: - - // An element of the graph - struct SMatNode - { - std::string Name; - std::vector Arcs; // Position in the tree (vector of nodes) - }; - -private: - - NLLIGO::CZoneBank *_ZeBank; - CBuilderZone *_Builder; // To use the global mask - - std::vector _MatTree; // The tree of transition between materials - -private: - - void addTransition (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt); - - void addToUpdateAndCreate (CBuilderZoneRegion* pBZRfrom, sint32 sharePos, sint32 x, sint32 y, const std::string &sNewMat, void *pInt1, void *pInt2); - - void putTransitions (sint32 x, sint32 y, const NLLIGO::SPiece &rMask, const std::string &MatName, void *pInternal); - //void putTransition (sint32 x, sint32 y, const std::string &MatName); - void updateTrans (sint32 x, sint32 y, NLLIGO::CZoneBankElement *pElt = NULL); - - std::string getNextMatInTree(const std::string &sMatA, const std::string &sMatB); - void tryPath (uint32 posA, uint32 posB, std::vector &vPath); - - void set (sint32 x, sint32 y, sint32 nPosX, sint32 nPosY, const std::string &ZoneName, bool transition=false); - void setRot (sint32 x, sint32 y, uint8 rot); - void setFlip (sint32 x, sint32 y, uint8 flip); - void resize (sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY); - -}; - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// This class is interface between all that is displayed in +// display/tools view and the game core + +#ifndef BUILDERZONEREGION_H +#define BUILDERZONEREGION_H + +// *************************************************************************** + +namespace NLLIGO +{ + class CZoneBank; + class CZoneBankElement; + struct SPiece; +} + +namespace NLMISC +{ + class IStream; +} + +class CBuilderZone; + +// *************************************************************************** + +// CZoneRegion contains informations about the zones painted +class CBuilderZoneRegion +{ + +public: + uint RegionId; + +public: + + CBuilderZoneRegion (uint regionId); + + + // New interface + bool init (NLLIGO::CZoneBank *pBank, CBuilderZone *pBuilder, std::string &error); + void add (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt); + void invertCutEdge (sint32 x, sint32 y, uint8 cePos); + void cycleTransition (sint32 x, sint32 y); + bool addNotPropagate (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt); + void addForce (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt); + void del (sint32 x, sint32 y, bool transition=false, void *pInternal=NULL); + void move (sint32 x, sint32 y); + uint32 countZones (); + void reduceMin (); + + + // Accessors + +private: + + // An element of the graph + struct SMatNode + { + std::string Name; + std::vector Arcs; // Position in the tree (vector of nodes) + }; + +private: + + NLLIGO::CZoneBank *_ZeBank; + CBuilderZone *_Builder; // To use the global mask + + std::vector _MatTree; // The tree of transition between materials + +private: + + void addTransition (sint32 x, sint32 y, uint8 nRot, uint8 nFlip, NLLIGO::CZoneBankElement *pElt); + + void addToUpdateAndCreate (CBuilderZoneRegion* pBZRfrom, sint32 sharePos, sint32 x, sint32 y, const std::string &sNewMat, void *pInt1, void *pInt2); + + void putTransitions (sint32 x, sint32 y, const NLLIGO::SPiece &rMask, const std::string &MatName, void *pInternal); + //void putTransition (sint32 x, sint32 y, const std::string &MatName); + void updateTrans (sint32 x, sint32 y, NLLIGO::CZoneBankElement *pElt = NULL); + + std::string getNextMatInTree(const std::string &sMatA, const std::string &sMatB); + void tryPath (uint32 posA, uint32 posB, std::vector &vPath); + + void set (sint32 x, sint32 y, sint32 nPosX, sint32 nPosY, const std::string &ZoneName, bool transition=false); + void setRot (sint32 x, sint32 y, uint8 rot); + void setFlip (sint32 x, sint32 y, uint8 flip); + void resize (sint32 newMinX, sint32 newMaxX, sint32 newMinY, sint32 newMaxY); + +}; + #endif // BUILDERZONEREGION_H \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/color_button.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/color_button.cpp index aacad9939..230b45261 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/color_button.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/color_button.cpp @@ -1,68 +1,68 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -// color_button.cpp : implementation file -// - -#include "stdafx.h" -//#include "object_viewer.h" -#include "color_button.h" - - -WNDPROC CColorButton::_BasicButtonWndProc = NULL ; - - -///////////////////////////////////////////////////////////////////////////// -// CColorButton - -CColorButton::CColorButton() : _Color(CRGBA::White) -{ -} - -CColorButton::~CColorButton() -{ -} - - -BEGIN_MESSAGE_MAP(CColorButton, CButton) - //{{AFX_MSG_MAP(CColorButton) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CColorButton message handlers - -void CColorButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) -{ - // TODO: Add your code to draw the specified item - HDC dc = lpDrawItemStruct->hDC ; - - RECT r ; - - GetClientRect(&r) ; - - r.left += 4 ; - r.top += 4 ; - r.bottom -= 4 ; - r.right -= 4 ; - GetClientRect(&r) ; - CBrush b ; - b.CreateSolidBrush(RGB(_Color.R, _Color.G, _Color.B)) ; - ::FillRect(dc, &r, (HBRUSH) b) ; - - -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +// color_button.cpp : implementation file +// + +#include "stdafx.h" +//#include "object_viewer.h" +#include "color_button.h" + + +WNDPROC CColorButton::_BasicButtonWndProc = NULL ; + + +///////////////////////////////////////////////////////////////////////////// +// CColorButton + +CColorButton::CColorButton() : _Color(CRGBA::White) +{ +} + +CColorButton::~CColorButton() +{ +} + + +BEGIN_MESSAGE_MAP(CColorButton, CButton) + //{{AFX_MSG_MAP(CColorButton) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CColorButton message handlers + +void CColorButton::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + // TODO: Add your code to draw the specified item + HDC dc = lpDrawItemStruct->hDC ; + + RECT r ; + + GetClientRect(&r) ; + + r.left += 4 ; + r.top += 4 ; + r.bottom -= 4 ; + r.right -= 4 ; + GetClientRect(&r) ; + CBrush b ; + b.CreateSolidBrush(RGB(_Color.R, _Color.G, _Color.B)) ; + ::FillRect(dc, &r, (HBRUSH) b) ; + + +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/color_button.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/color_button.h index 1795cec90..be164537a 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/color_button.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/color_button.h @@ -1,92 +1,92 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#if !defined(AFX_COLOR_BUTTON_H__286CFF58_DD7F_4310_95EB_3477F5A2B923__INCLUDED_) -#define AFX_COLOR_BUTTON_H__286CFF58_DD7F_4310_95EB_3477F5A2B923__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -using NLMISC::CRGBA ; - - - - -///////////////////////////////////////////////////////////////////////////// -// CColorButton window - -class CColorButton : public CButton -{ - -// Construction -public: - CColorButton(); - -// Attributes -public: - // set a nex color for the button - void setColor(CRGBA col) { _Color = col ; /*Invalidate() ;*/ } - - // get the color of the button - CRGBA getColor(void) const { return _Color ; } - - -// Operations -public: - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CColorButton) - public: - virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); - //}}AFX_VIRTUAL - -// Implementation -public: - virtual ~CColorButton(); - - // register this custom control to window - static void CColorButton::registerClass(void) ; - - // Generated message map functions -protected: - //{{AFX_MSG(CColorButton) - //}}AFX_MSG - - DECLARE_MESSAGE_MAP() - - - // current color of the button - CRGBA _Color ; - - - // the event proc for basic cbutton... - static WNDPROC _BasicButtonWndProc ; - - // a hook to create the dialog - static LRESULT CALLBACK EXPORT WndProcHook(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) ; - - -}; - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_COLOR_BUTTON_H__286CFF58_DD7F_4310_95EB_3477F5A2B923__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#if !defined(AFX_COLOR_BUTTON_H__286CFF58_DD7F_4310_95EB_3477F5A2B923__INCLUDED_) +#define AFX_COLOR_BUTTON_H__286CFF58_DD7F_4310_95EB_3477F5A2B923__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +using NLMISC::CRGBA ; + + + + +///////////////////////////////////////////////////////////////////////////// +// CColorButton window + +class CColorButton : public CButton +{ + +// Construction +public: + CColorButton(); + +// Attributes +public: + // set a nex color for the button + void setColor(CRGBA col) { _Color = col ; /*Invalidate() ;*/ } + + // get the color of the button + CRGBA getColor(void) const { return _Color ; } + + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CColorButton) + public: + virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CColorButton(); + + // register this custom control to window + static void CColorButton::registerClass(void) ; + + // Generated message map functions +protected: + //{{AFX_MSG(CColorButton) + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() + + + // current color of the button + CRGBA _Color ; + + + // the event proc for basic cbutton... + static WNDPROC _BasicButtonWndProc ; + + // a hook to create the dialog + static LRESULT CALLBACK EXPORT WndProcHook(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) ; + + +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_COLOR_BUTTON_H__286CFF58_DD7F_4310_95EB_3477F5A2B923__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/custom_snapshot.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/custom_snapshot.cpp index 86953ea3f..188f2a767 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/custom_snapshot.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/custom_snapshot.cpp @@ -1,115 +1,115 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// custom_snapshot.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "custom_snapshot.h" - -///////////////////////////////////////////////////////////////////////////// -// CCustomSnapshot dialog - - -CCustomSnapshot::CCustomSnapshot(CWnd* pParent /*=NULL*/) - : CDialog(CCustomSnapshot::IDD, pParent) -{ - //{{AFX_DATA_INIT(CCustomSnapshot) - Height = 512; - Width = 512; - KeepRatio = TRUE; - FixedSize = 0; - OutputRGB = 0; - //}}AFX_DATA_INIT -} - - -void CCustomSnapshot::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CCustomSnapshot) - DDX_Control(pDX, IDC_KEEPRATIO, KeepRatioCtrl); - DDX_Control(pDX, IDC_HEIGHT, HeightCtrl); - DDX_Control(pDX, IDC_WIDTH, WidthCtrl); - DDX_Text(pDX, IDC_HEIGHT, Height); - DDV_MinMaxUInt(pDX, Height, 1, 65535); - DDX_Text(pDX, IDC_WIDTH, Width); - DDV_MinMaxUInt(pDX, Width, 1, 65535); - DDX_Check(pDX, IDC_KEEPRATIO, KeepRatio); - DDX_Radio(pDX, IDC_FIXED_SIZE, FixedSize); - DDX_Radio(pDX, IDC_RGBA, OutputRGB); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CCustomSnapshot, CDialog) - //{{AFX_MSG_MAP(CCustomSnapshot) - ON_BN_CLICKED(IDC_KEEPRATIO, OnKeepratio) - ON_BN_CLICKED(IDC_FIXED_SIZE, OnFixedSize) - ON_BN_CLICKED(IDC_GRAY_SCALE2, OnGrayScale2) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CCustomSnapshot message handlers - -// *************************************************************************** - -void CCustomSnapshot::OnKeepratio() -{ - updateData (); -} - -// *************************************************************************** - -void CCustomSnapshot::OnFixedSize() -{ - updateData (); -} - -// *************************************************************************** - -void CCustomSnapshot::OnGrayScale2() -{ - updateData (); -} - -// *************************************************************************** - -BOOL CCustomSnapshot::OnInitDialog() -{ - CDialog::OnInitDialog(); - - updateData (); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -// *************************************************************************** - -void CCustomSnapshot::updateData () -{ - UpdateData (); - BOOL enable = FixedSize != 0; - WidthCtrl.EnableWindow (enable); - HeightCtrl.EnableWindow (enable && !KeepRatio); - KeepRatioCtrl.EnableWindow (enable); - UpdateData (FALSE); -} - -// *************************************************************************** +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// custom_snapshot.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "custom_snapshot.h" + +///////////////////////////////////////////////////////////////////////////// +// CCustomSnapshot dialog + + +CCustomSnapshot::CCustomSnapshot(CWnd* pParent /*=NULL*/) + : CDialog(CCustomSnapshot::IDD, pParent) +{ + //{{AFX_DATA_INIT(CCustomSnapshot) + Height = 512; + Width = 512; + KeepRatio = TRUE; + FixedSize = 0; + OutputRGB = 0; + //}}AFX_DATA_INIT +} + + +void CCustomSnapshot::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CCustomSnapshot) + DDX_Control(pDX, IDC_KEEPRATIO, KeepRatioCtrl); + DDX_Control(pDX, IDC_HEIGHT, HeightCtrl); + DDX_Control(pDX, IDC_WIDTH, WidthCtrl); + DDX_Text(pDX, IDC_HEIGHT, Height); + DDV_MinMaxUInt(pDX, Height, 1, 65535); + DDX_Text(pDX, IDC_WIDTH, Width); + DDV_MinMaxUInt(pDX, Width, 1, 65535); + DDX_Check(pDX, IDC_KEEPRATIO, KeepRatio); + DDX_Radio(pDX, IDC_FIXED_SIZE, FixedSize); + DDX_Radio(pDX, IDC_RGBA, OutputRGB); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CCustomSnapshot, CDialog) + //{{AFX_MSG_MAP(CCustomSnapshot) + ON_BN_CLICKED(IDC_KEEPRATIO, OnKeepratio) + ON_BN_CLICKED(IDC_FIXED_SIZE, OnFixedSize) + ON_BN_CLICKED(IDC_GRAY_SCALE2, OnGrayScale2) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CCustomSnapshot message handlers + +// *************************************************************************** + +void CCustomSnapshot::OnKeepratio() +{ + updateData (); +} + +// *************************************************************************** + +void CCustomSnapshot::OnFixedSize() +{ + updateData (); +} + +// *************************************************************************** + +void CCustomSnapshot::OnGrayScale2() +{ + updateData (); +} + +// *************************************************************************** + +BOOL CCustomSnapshot::OnInitDialog() +{ + CDialog::OnInitDialog(); + + updateData (); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +// *************************************************************************** + +void CCustomSnapshot::updateData () +{ + UpdateData (); + BOOL enable = FixedSize != 0; + WidthCtrl.EnableWindow (enable); + HeightCtrl.EnableWindow (enable && !KeepRatio); + KeepRatioCtrl.EnableWindow (enable); + UpdateData (FALSE); +} + +// *************************************************************************** diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/custom_snapshot.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/custom_snapshot.h index ba92ac8b6..343efaaa4 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/custom_snapshot.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/custom_snapshot.h @@ -1,75 +1,75 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_CUSTOM_SNAPSHOT_H__FED230C3_4E53_4AA6_95A5_6B0F887FF7AB__INCLUDED_) -#define AFX_CUSTOM_SNAPSHOT_H__FED230C3_4E53_4AA6_95A5_6B0F887FF7AB__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// custom_snapshot.h : header file -// - -#include "resource.h" - -///////////////////////////////////////////////////////////////////////////// -// CCustomSnapshot dialog - -class CCustomSnapshot : public CDialog -{ -// Construction -public: - CCustomSnapshot(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CCustomSnapshot) - enum { IDD = IDD_CUSTOM_SNAPSHOT }; - CButton KeepRatioCtrl; - CEdit HeightCtrl; - CEdit WidthCtrl; - UINT Height; - UINT Width; - BOOL KeepRatio; - int FixedSize; - int OutputRGB; - //}}AFX_DATA - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CCustomSnapshot) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - void updateData(); - - // Generated message map functions - //{{AFX_MSG(CCustomSnapshot) - afx_msg void OnKeepratio(); - afx_msg void OnFixedSize(); - afx_msg void OnGrayScale2(); - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_CUSTOM_SNAPSHOT_H__FED230C3_4E53_4AA6_95A5_6B0F887FF7AB__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_CUSTOM_SNAPSHOT_H__FED230C3_4E53_4AA6_95A5_6B0F887FF7AB__INCLUDED_) +#define AFX_CUSTOM_SNAPSHOT_H__FED230C3_4E53_4AA6_95A5_6B0F887FF7AB__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// custom_snapshot.h : header file +// + +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// CCustomSnapshot dialog + +class CCustomSnapshot : public CDialog +{ +// Construction +public: + CCustomSnapshot(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CCustomSnapshot) + enum { IDD = IDD_CUSTOM_SNAPSHOT }; + CButton KeepRatioCtrl; + CEdit HeightCtrl; + CEdit WidthCtrl; + UINT Height; + UINT Width; + BOOL KeepRatio; + int FixedSize; + int OutputRGB; + //}}AFX_DATA + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CCustomSnapshot) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + void updateData(); + + // Generated message map functions + //{{AFX_MSG(CCustomSnapshot) + afx_msg void OnKeepratio(); + afx_msg void OnFixedSize(); + afx_msg void OnGrayScale2(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_CUSTOM_SNAPSHOT_H__FED230C3_4E53_4AA6_95A5_6B0F887FF7AB__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/dialog_properties.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/dialog_properties.cpp index 9b0d5dd12..31189622a 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/dialog_properties.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/dialog_properties.cpp @@ -1,3712 +1,3712 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// dialog_properties.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "main_frm.h" -#include "dialog_properties.h" -#include "nel/misc/path.h" -#include "action.h" -#include -#include "nel/ligo/primitive.h" -#include "tools_logic.h" -#include "external_editor.h" -#include "file_dialog_ex.h" - -using namespace std; -using namespace NLLIGO; -using namespace NLMISC; - -// *************************************************************************** - -#define SCROLLING_STEPS 2 // parameter to finetune the scroller - -#define CHECKBOX_HEIGHT 20 -#define COMBO_REAL_HEIGHT 300 -#define COMBO_HEIGHT 20 -#define LABEL_HEIGHT 15 -#define SPACE_HEIGHT (widgetPos.left) -#define EDIT_HEIGHT 18 -#define FIRST_WIDGET 10 -#define LAST_WIDGET 100 -#define FILE_BUTTON_WIDTH 50 - -#define STRING_SELECT_COMBOBOX_ID 9 - -#define DIFFERENT_VALUE_STRING "" -#define DIFFERENT_VALUE_MULTI_STRING "" - -//CDialogProperties PropertyDialog; -std::list PropertiesDialogs; -CPoint CDialogProperties::s_lastPosition = CPoint( -1, -1 ); - - -BOOL CScrollPane::OnCommand(WPARAM wParam, LPARAM lParam) -{ - // forward control command to dialog. - return m_dlgProperty->OnCommand(wParam, lParam); -} - -LRESULT CScrollPane::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case LBN_CHANGE: - m_dlgProperty->WindowProc(message, wParam, lParam); - break; - } - - return CStatic::WindowProc(message, wParam, lParam); -} - -// *************************************************************************** -// CDialogProperties dialog -// *************************************************************************** - -CDialogProperties::CDialogProperties() -{ - m_PropertyCont.init(this); - _Modal = false; - _Cancel = true; - _ScrollBar = false; -} - -// *************************************************************************** - -CDialogProperties::CDialogProperties(std::list &locators, CWnd* pParent /*=NULL*/) - : CDialog(CDialogProperties::IDD, pParent) -{ - //{{AFX_DATA_INIT(CDialogProperties) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT - - m_PropertyCont.init(this); - - // Reserve some memory - _PropDlgLocators.reserve (locators.size ()); - - CWorldEditorDoc *doc = getDocument (); - std::list::iterator ite = locators.begin (); - while (ite != locators.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - _PropDlgLocators.push_back (locator); - ite++; - } - - _Modal = true; - _Cancel = false; -} - -// *************************************************************************** - -void CDialogProperties::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CDialogProperties) - DDX_Control(pDX, IDUPDATE, m_updateButton); - DDX_Control(pDX, IDOK, m_OKButton); - DDX_Control(pDX, IDC_FIRST_PROP, m_FirstProp); - DDX_Control(pDX, IDC_PROPERTY_FRAME, m_PropertyFrame); - DDX_Control(pDX, IDC_SCROLLBAR_PROP, m_ScrollBar); - //}}AFX_DATA_MAP -} - -// *************************************************************************** - -BEGIN_MESSAGE_MAP(CDialogProperties, CDialog) - //ON_NOTIFY_RANGE( LVN_ITEMACTIVATE, 0, -1, onListCtrlItemActivate ) - //{{AFX_MSG_MAP(CDialogProperties) - ON_WM_SHOWWINDOW() - ON_BN_CLICKED(IDUPDATE, OnUpdate) - ON_WM_VSCROLL() - ON_WM_MOUSEWHEEL() - ON_WM_SIZE() - ON_WM_GETMINMAXINFO() - ON_WM_SETFOCUS() - ON_WM_MOVE() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// *************************************************************************** -// CDialogProperties message handlers -// *************************************************************************** - -void CDialogProperties::OnOK() -{ - - OnUpdate(); - - ::CRect rect; - GetWindowRect( &rect ); - - s_lastPosition = CPoint( rect.left, rect.top ); - PropertiesDialogs.remove( this ); - - CDialog::OnOK(); -} - -// *************************************************************************** - -void CDialogProperties::OnCancel() -{ - ::CRect rect; - GetWindowRect( &rect ); - - s_lastPosition = CPoint( rect.left, rect.top ); - PropertiesDialogs.remove( this ); - - CDialog::OnCancel(); -} - -// *************************************************************************** - -void CDialogProperties::removeWidgets () -{ - std::list::iterator ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - /* - CWidget &widget = *ite; - // Create a label ? - if ( (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstString) || - (widget.Parameter.Type == CPrimitiveClass::CParameter::String) || - (widget.Parameter.Type == CPrimitiveClass::CParameter::StringArray) || - (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray)) - { - // Create the label - widget.Static.DestroyWindow (); - } - - // What kind of primitive ? - if (widget.Parameter.Type == CPrimitiveClass::CParameter::Boolean) - { - widget.CheckBox.DestroyWindow (); - - } - else if (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstString) - { - widget.ComboBox.DestroyWindow (); - } - else if (widget.Parameter.Type == CPrimitiveClass::CParameter::String) - { - widget.EditBox.DestroyWindow (); - if (widget.Parameter.FileExtension != "") - { - widget.CheckBox.DestroyWindow (); - } - } - else if (widget.Parameter.Type == CPrimitiveClass::CParameter::StringArray) - { - widget.MultiLineEditBox.DestroyWindow (); - if (widget.Parameter.Folder != "" || !widget.Parameter.FileExtension.empty()) - { - widget.CheckBox.DestroyWindow (); - } - } - else if (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) - { - widget.ListEditBox.DestroyWindow (); - } - - // File ? - if (widget.Parameter.Filename) - { - widget.CheckBox.DestroyWindow (); - } - */ - CWidget &widget = *ite; - CWnd *windows[] = { &widget.Static, &widget.ComboBox, &widget.CheckBox, &widget.EditBox, &widget.MultiLineEditBox, &widget.ListEditBox}; - int i; - for (i=0; iDestroyWindow (); - } - - ite++; - } - - Widgets.clear (); - -/* RECT rect; - GetWindowRect (&rect); - rect.bottom = rect.top + WindowHeight; - MoveWindow (&rect); - GetDlgItem (IDOK)->GetWindowRect (&rect); - ScreenToClient (&rect); - rect.top = WidgetPos.top; - rect.bottom = WidgetPos.bottom; - GetDlgItem (IDOK)->MoveWindow (&rect); - GetDlgItem (IDCANCEL)->GetWindowRect (&rect); - ScreenToClient (&rect); - rect.top = WidgetPos.top; - rect.bottom = WidgetPos.bottom; - GetDlgItem (IDCANCEL)->MoveWindow (&rect); - GetDlgItem (IDUPDATE)->GetWindowRect (&rect); - ScreenToClient (&rect); - rect.top = WidgetPos.top; - rect.bottom = WidgetPos.bottom; - GetDlgItem (IDUPDATE)->MoveWindow (&rect); -*/ - -} - -// *************************************************************************** - -void CDialogProperties::addWidget (const CPrimitiveClass::CParameter ¶meter, RECT &widgetPos, bool frozen) -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Get client rect - RECT clientRect; - m_PropertyCont.GetClientRect(&clientRect); -// GetClientRect (&clientRect); - RECT firstProp; - m_FirstProp.GetWindowRect(&firstProp); - - // Backup top - uint oldTop = widgetPos.top; - // backup right - uint oldRight = widgetPos.right; - - // Set the right limit -// widgetPos.right = clientRect.right - widgetPos.left; -// widgetPos.right = firstProp.right; - - // File ? - if (parameter.Filename - || (parameter.Type==CPrimitiveClass::CParameter::String && parameter.FileExtension != "") - || (parameter.Type==CPrimitiveClass::CParameter::StringArray && parameter.Folder != "") ) - widgetPos.right -= FILE_BUTTON_WIDTH; - - // Widget id - uint id = Widgets.size ()+FIRST_WIDGET; - - // Add a widget - Widgets.push_back (CWidget (this)); - CWidget &widget = Widgets.back (); - - // Copy the parameter - widget.Parameter = parameter; - - // Widget enabled ? - bool enabled = !parameter.ReadOnly && !frozen; - - // Create a label ? - if ( (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstString) || - (widget.Parameter.Type == CPrimitiveClass::CParameter::String) || - (widget.Parameter.Type == CPrimitiveClass::CParameter::StringArray) || - (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) ) - { - // Resize the widgetPos - widgetPos.bottom = widgetPos.top + LABEL_HEIGHT; - - if (widget.Parameter.Type == CPrimitiveClass::CParameter::StringArray && widget.Parameter.Folder != "") - { - RECT buttonRect = widgetPos; - buttonRect.left = buttonRect.right; - buttonRect.right = buttonRect.left + FILE_BUTTON_WIDTH; - - // Create an edit box - nlverify (widget.CheckBox.Create ("Select", BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), buttonRect, &m_PropertyCont, id)); - widget.CheckBox.SetFont (GetFont ()); - } - - // Create the label - widget.Static.Create ("", WS_VISIBLE, widgetPos, &m_PropertyCont); - widget.Static.SetFont (GetFont ()); - - // Next position - widgetPos.top = widgetPos.bottom; - } - - // What kind of primitive ? - if (widget.Parameter.Type == CPrimitiveClass::CParameter::Boolean) - { - // Resize the widgetPos - widgetPos.bottom = widgetPos.top + CHECKBOX_HEIGHT; - - string Name = widget.Parameter.Name; - - // Create a check box - nlverify (widget.CheckBox.Create (Name.c_str (), BS_3STATE|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), widgetPos, &m_PropertyCont, id)); - widget.CheckBox.SetFont (GetFont ()); - } - else if (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstString) - { - // Resize the widgetPos - RECT comboPos = widgetPos; - widgetPos.bottom = widgetPos.top + COMBO_HEIGHT; - comboPos.bottom = widgetPos.top + COMBO_REAL_HEIGHT; - - // Create a combo box - //nlverify (widget.ComboBox.Create (CBS_DISABLENOSCROLL|WS_VSCROLL|CBS_DROPDOWNLIST|(widget.Parameter.SortEntries?CBS_SORT:0)|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), comboPos, &m_PropertyCont, id)); - nlverify (widget.ComboBox.Create (CBS_DISABLENOSCROLL|WS_VSCROLL|(widget.Parameter.Editable?CBS_DROPDOWN:CBS_DROPDOWNLIST)|(widget.Parameter.SortEntries?CBS_SORT:0)|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), comboPos, &m_PropertyCont, id)); - widget.ComboBox.loaded = false; - widget.ComboBox.Widget = &widget; - widget.ComboBox.SetFont (GetFont ()); - - // Get the good list - widget.ComboBox.ResetContent (); - string ctx = doc->getContext (); - std::map::iterator ite = widget.Parameter.ComboValues.find (doc->getContext ().c_str()); - // we insert an empty string in case of a default value - if (!widget.Parameter.SortEntries) - { - widget.ComboBox.InsertString( -1, ""); - } - else - { - widget.ComboBox.AddString(""); - } - if (ite != widget.Parameter.ComboValues.end ()) - { - vector PathList; - { - ite->second.appendFilePath(PathList); - - vector relativePrimPaths; - { - vector startPrimPath; - for (uint locIndex=0;locIndex<_PropDlgLocators.size();locIndex++) - startPrimPath.push_back(_PropDlgLocators[locIndex].Primitive); - ite->second.getPrimitivesForPrimPath(relativePrimPaths, startPrimPath); - } - - ite->second.appendPrimPath(PathList, relativePrimPaths); - } - if (widget.Parameter.SortEntries) - std::sort(PathList.begin(), PathList.end()); - widget.ComboBox.setData(PathList); - } - - // Add default values - if (doc->getContext () != "default") - { - ite = widget.Parameter.ComboValues.find ("default"); - if (ite != widget.Parameter.ComboValues.end ()) - { - vector PathList; - { - ite->second.appendFilePath(PathList); - - vector relativePrimPaths; - { - vector startPrimPath; - for (uint locIndex=0;locIndex<_PropDlgLocators.size();locIndex++) - startPrimPath.push_back(_PropDlgLocators[locIndex].Primitive); - ite->second.getPrimitivesForPrimPath(relativePrimPaths, startPrimPath); - } - - ite->second.appendPrimPath(PathList, relativePrimPaths); - } - if (widget.Parameter.SortEntries) - std::sort(PathList.begin(), PathList.end()); - widget.ComboBox.setData(PathList); - } - } - } - else if (widget.Parameter.Type == CPrimitiveClass::CParameter::String) - { - // Resize the widgetPos - widgetPos.bottom = widgetPos.top + EDIT_HEIGHT; - - // Create an edit box - nlverify (widget.EditBox.CreateEx (WS_EX_CLIENTEDGE, _T("EDIT"), "", WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL|(enabled?0:ES_READONLY), widgetPos, &m_PropertyCont, id)); - widget.EditBox.SetFont (GetFont ()); - if (widget.Parameter.FileExtension != "") - { - RECT buttonRect = widgetPos; - buttonRect.left = buttonRect.right; - buttonRect.right = buttonRect.left + FILE_BUTTON_WIDTH; - - // Create an edit box - nlverify (widget.CheckBox.Create ("Open...", BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), buttonRect, &m_PropertyCont, id)); - widget.CheckBox.SetFont (GetFont ()); - } - } - else if (widget.Parameter.Type == CPrimitiveClass::CParameter::StringArray) - { - // Resize the widgetPos - widgetPos.bottom = widgetPos.top + widget.Parameter.WidgetHeight; - - // Create an edit box - if (widget.Parameter.DisplayHS) - { - nlverify (widget.MultiLineEditBox.CreateEx (WS_EX_CLIENTEDGE, _T("EDIT"), "", - WS_VSCROLL|WS_HSCROLL|ES_MULTILINE|ES_WANTRETURN|WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL|ES_AUTOVSCROLL|(enabled?0:ES_READONLY), widgetPos, &m_PropertyCont, id)); - } - else - { - nlverify (widget.MultiLineEditBox.CreateEx (WS_EX_CLIENTEDGE, _T("EDIT"), "", - WS_VSCROLL|ES_MULTILINE|ES_WANTRETURN|WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL|ES_AUTOVSCROLL|(enabled?0:ES_READONLY), widgetPos, &m_PropertyCont, id)); - } - - - // Resize the column - RECT listRect; - widget.MultiLineEditBox.GetClientRect (&listRect); - - CFont font; - font.CreateStockObject (ANSI_FIXED_FONT); - widget.MultiLineEditBox.SetFont (&font); - - // Create an "EDIT" button if the text is editable (FileExtension != "") - if (widget.Parameter.FileExtension != "") - { - widgetPos.top = widgetPos.bottom; - widgetPos.bottom += LABEL_HEIGHT; - RECT buttonRect = widgetPos; - - // Create an edit box - nlverify (widget.CheckBox.Create ("Edit...", BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), buttonRect, &m_PropertyCont, id)); - widget.CheckBox.SetFont (GetFont ()); - } - } - else if (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) - { - // Resize the widgetPos - widgetPos.bottom = widgetPos.top + widget.Parameter.WidgetHeight; - - // Create an edit box - nlverify (widget.ListEditBox.CreateEx (WS_EX_CLIENTEDGE, _T("LISTBOX"), "", WS_VSCROLL|WS_CHILD|WS_VISIBLE|WS_TABSTOP|LBS_NOTIFY|(enabled?0:WS_DISABLED), widgetPos, &m_PropertyCont, id)); - - // Resize the column - RECT listRect; - widget.ListEditBox.GetClientRect (&listRect); - - // Get the good list - widget.ListEditBox.StringSelectComboBox.ResetContent (); - std::map::iterator ite = widget.Parameter.ComboValues.find (doc->getContext ().c_str()); - // we insert an empty string in case of a default value - widget.ListEditBox.StringSelectComboBox.InsertString( -1, ""); - if (ite != widget.Parameter.ComboValues.end ()) - { - vector PathList; - { - ite->second.appendFilePath(PathList); - - vector relativePrimPaths; - { - vector startPrimPath; - for (uint locIndex=0;locIndex<_PropDlgLocators.size();locIndex++) - startPrimPath.push_back(_PropDlgLocators[locIndex].Primitive); - ite->second.getPrimitivesForPrimPath(relativePrimPaths, startPrimPath); - } - - ite->second.appendPrimPath(PathList, relativePrimPaths); - } - - for (vector::iterator it=PathList.begin(), itEnd=PathList.end(); it!=itEnd; ++it) - { - widget.ListEditBox.StringSelectComboBox.InsertString( -1, it->c_str ()); - } - } - - // Add default values - if (doc->getContext () != "default") - { - ite = widget.Parameter.ComboValues.find ("default"); - if (ite != widget.Parameter.ComboValues.end ()) - { - vector PathList; - { - ite->second.appendFilePath(PathList); - - vector relativePrimPaths; - { - vector startPrimPath; - for (uint locIndex=0;locIndex<_PropDlgLocators.size();locIndex++) - startPrimPath.push_back(_PropDlgLocators[locIndex].Primitive); - ite->second.getPrimitivesForPrimPath(relativePrimPaths, startPrimPath); - } - - ite->second.appendPrimPath(PathList, relativePrimPaths); - } - - for (vector::iterator it=PathList.begin(), itEnd=PathList.end(); it!=itEnd; ++it) - { - widget.ListEditBox.StringSelectComboBox.InsertString( -1, it->c_str ()); - } - } - } - - widget.ListEditBox.SetFont (GetFont ()); - widget.ListEditBox.StringSelectComboBox.SetFont (GetFont ()); - } - - // File ? - // if ((parameter.Filename) && (widget.Parameter.Type != CPrimitiveClass::CParameter::ConstStringArray)) - if (parameter.Filename && (parameter.FileExtension.empty() || widget.Parameter.Type != CPrimitiveClass::CParameter::StringArray)) - { - // Resize the widgetPos - RECT buttonRect = widgetPos; - buttonRect.left = buttonRect.right; - buttonRect.right = buttonRect.left + FILE_BUTTON_WIDTH; - - // Create an edit box - //nlverify (widget.CheckBox.Create ("Open...", BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP, buttonRect, this, id)); - nlverify (widget.CheckBox.Create ("View...", BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), buttonRect, &m_PropertyCont, id)); - widget.CheckBox.SetFont (GetFont ()); - } - - // Next position - widgetPos.top = widgetPos.bottom + SPACE_HEIGHT; - - // Move ok and cancel button -// uint heightGrow = widgetPos.top - oldTop; -/* RECT okRect; - GetDlgItem (IDOK)->GetWindowRect (&okRect); - ScreenToClient (&okRect); - okRect.top += heightGrow; - okRect.bottom += heightGrow; - GetDlgItem (IDOK)->MoveWindow (&okRect); - GetDlgItem (IDCANCEL)->GetWindowRect (&okRect); - ScreenToClient (&okRect); - okRect.top += heightGrow; - okRect.bottom += heightGrow; - GetDlgItem (IDCANCEL)->MoveWindow (&okRect); - GetDlgItem (IDUPDATE)->GetWindowRect (&okRect); - ScreenToClient (&okRect); - okRect.top += heightGrow; - okRect.bottom += heightGrow; - GetDlgItem (IDUPDATE)->MoveWindow (&okRect); - - // Resize the dialog box - RECT windowRect; - GetWindowRect (&windowRect); - - // Center only modal window - if (_Modal) - { - sint width = windowRect.right - windowRect.left; - sint height = windowRect.bottom - windowRect.top; - RECT desktop; - GetDesktopWindow ()->GetClientRect (&desktop); - windowRect.left = (desktop.right - desktop.left - width) / 2; - windowRect.right = windowRect.left + width; - windowRect.top = (desktop.bottom - desktop.top - height) / 2; - windowRect.top -= heightGrow/2; - windowRect.bottom = windowRect.top + height + heightGrow; - } - else - { - windowRect.bottom += heightGrow; - } -*/ - // resize the property container - RECT contRect; - m_PropertyCont.GetClientRect(&contRect); - contRect.bottom = widgetPos.top; - m_PropertyCont.CalcWindowRect(&contRect, 0); - m_PropertyCont.MoveWindow(&contRect, TRUE); - - // Not set - widget.Set = false; - - // restore righ - widgetPos.right = oldRight; -} - -// *************************************************************************** - -BOOL CDialogProperties::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // Load accel table - nlverify (_AccelTable = LoadAccelerators (theApp.m_hInstance, MAKEINTRESOURCE(IDR_DIALOG))); - - // Get the OK Button position -// GetDlgItem (IDOK)->GetWindowRect (&WidgetPos); - RECT winRect; - GetWindowRect (&winRect); - WindowWidth = winRect.right - winRect.left; - WindowHeight = winRect.bottom - winRect.top; - - // Center only modal window - RECT desktop; - GetDesktopWindow ()->GetClientRect (&desktop); - GetWindowRect (&winRect); - uint width = winRect.right - winRect.left; - uint height = winRect.bottom - winRect.top; - winRect.top = (desktop.bottom - desktop.top - height) / 2; - winRect.left = (desktop.right - desktop.left - width) / 2; - winRect.right = winRect.left + width; - winRect.bottom = winRect.top + height; - MoveWindow (&winRect); - - RECT contRect; - m_PropertyFrame.GetClientRect(&contRect); - m_ContMinHeight = contRect.bottom; -// m_PropertyFrame.ClientToScreen(&contRect); - // leave 16 px for the scroll bar - contRect.right-=16; - m_PropertyCont.Create("", 0, contRect, &m_PropertyFrame); -// m_PropertyCont.SetCursor() - - m_PropertyCont.ShowWindow(SW_SHOW); - - // store the relative starting position for widget - m_FirstProp.GetWindowRect (&WidgetPos); - m_PropertyCont.ScreenToClient (&WidgetPos); - - // Store the relative button position - RECT buttonRect, dialogRect; - m_OKButton.GetWindowRect(&buttonRect); - ScreenToClient(&buttonRect); - GetClientRect(&dialogRect); - m_ButtonPos = dialogRect.bottom - buttonRect.top; - - // Store the property frame position - m_PropertyFrame.GetWindowRect(&PropertyFrameRect); - ScreenToClient(&PropertyFrameRect); - - // Store the relative frame position - GetWindowRect(&dialogRect); - ScreenToClient(&dialogRect); - m_FrameTopSpace = PropertyFrameRect.top - dialogRect.top; - m_FrameBottomSpace = dialogRect.bottom - PropertyFrameRect.bottom; - -// RECT desktop; - SystemParametersInfo(SPI_GETWORKAREA, 0, &desktop, 0); - m_MaxFrameHeight = desktop.bottom - desktop.top - m_FrameTopSpace - m_FrameBottomSpace; - - - // Rebuild the dialog - rebuildDialog (); - - // Show / hide cancel - GetDlgItem (IDCANCEL)->ShowWindow ( SW_SHOW );//_Cancel?SW_SHOW:SW_HIDE); - GetDlgItem (IDUPDATE)->ShowWindow ( SW_SHOW );//_Cancel?SW_SHOW:SW_HIDE); - - GetDlgItem(IDUPDATE)->GetWindowRect(&buttonRect); - ScreenToClient(&buttonRect); - m_buttonWidth = buttonRect.right; - GetDlgItem(IDOK)->GetWindowRect(&buttonRect); - ScreenToClient(&buttonRect); - m_buttonWidth -= buttonRect.left; - - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -// *************************************************************************** -// CDialogProperties::CWidget -// *************************************************************************** - -bool CDialogProperties::CWidget::fromParameter (const IProperty *property, const IPrimitive &primitive, const CPrimitiveClass *primitiveClass, const CPrimitiveClass::CParameter ¶meter) -{ - // Good one ? - if (parameter == Parameter) - { - // Get pointers - const CPropertyString *propString = dynamic_cast (property); - const CPropertyStringArray *propStringString = dynamic_cast (property); - - // Default value ? - if ( (property == NULL) - || (!Set && property->Default)) - Default = true; - - // Check box ? - if (Parameter.Type == CPrimitiveClass::CParameter::StringArray) - { - if (propStringString) - { - // Get the value - vector currentValue; - getValue (currentValue); - - // Already sets ? - if (Set && (((currentValue != propStringString->StringArray) && (!Default || !propStringString->Default)) || (Default != propStringString->Default))) - { - // Not by default - Default = false; - - // Set as uninitialized - setEditTextMultiLine (MultiLineEditBox, DIFFERENT_VALUE_STRING); - updateMultiline (); - MultipleValues = true; - } - else - { - // Set as filled - Set = true; - - // Add the string - setEditTextMultiLine (MultiLineEditBox, propStringString->StringArray); - updateMultiline (); - } - } - else - { - // Add the strings - string temp; - vector result; - Parameter.getDefaultValue (result, primitive, *primitiveClass, &FromWhere); - - uint i; - for (i=0; i currentValue; - getValue (currentValue); - - // Already sets ? - if (Set && (((currentValue != propStringString->StringArray) && (!Default || !propStringString->Default)) || (Default != propStringString->Default))) - { - // Not by default - Default = false; - - // Set as uninitialized - vector tmp; - { - tmp=currentValue; - const vector &temp=propStringString->StringArray; - - // Check if we have all previous values. - for (uint tmpInd=0;tmpInd=temp.size()) // Not Found ? - tmp[tmpInd]=DIFFERENT_VALUE_MULTI_STRING+tmp[tmpInd]; // Set as different. - } - - for (uint tempInd=0;tempInd=tmp.size()) // Not Found ? - tmp.push_back(DIFFERENT_VALUE_MULTI_STRING+temp[tempInd]); // Set as different. - } - - } - - setEditTextMultiLine (ListEditBox, tmp); - updateList (); - MultipleValues = true; - } - else - { - // Set as filled - Set = true; - - // Add the string - setEditTextMultiLine (ListEditBox, propStringString->StringArray); - updateList (); - } - } - else - { - // Add the strings - vector result; - Parameter.getDefaultValue (result, primitive, *primitiveClass, &FromWhere); - - setEditTextMultiLine (ListEditBox, result); - updateList (); - - // Set as filled - Set= true; - } - } - else - { - // Already sets ? - if (propString) - { - // Get the value - string currentValue; - getValue (currentValue); - - // Multi value ? - if (Set && (((currentValue != propString->String) && (!Default || !propString->Default)) || (Default != propString->Default))) - { - // Not by default - Default = false; - - // Boolean ? - switch (Parameter.Type) - { - case CPrimitiveClass::CParameter::Boolean: - // Set as uninitialized - CheckBox.SetCheck (2); - updateBoolean (); - break; - case CPrimitiveClass::CParameter::ConstString: - // Set as uninitialized - if (!Parameter.SortEntries) - ComboBox.InsertString (-1, DIFFERENT_VALUE_STRING); - else - ComboBox.AddString( DIFFERENT_VALUE_STRING); - ComboBox.SelectString(-1 ,DIFFERENT_VALUE_STRING); - OriginalString = DIFFERENT_VALUE_STRING; - updateCombo (); - break; - case CPrimitiveClass::CParameter::String: - // Set as uninitialized - EditBox.SetWindowText (DIFFERENT_VALUE_STRING); - break; - } - MultipleValues = true; - } - else - { - // Set as filled - Set= true; - - // Boolean ? - switch (Parameter.Type) - { - case CPrimitiveClass::CParameter::Boolean: - // Check the box - CheckBox.SetCheck (Default?2:(propString->String == "true")?1:0); - updateBoolean (); - break; - case CPrimitiveClass::CParameter::ConstString: - if (Parameter.Editable || ComboBox.SelectString(-1 ,propString->String.c_str ()) == CB_ERR) - { - ComboBox.SetWindowText(propString->String.c_str ()); - ComboBox.InsertString( -1, propString->String.c_str()); - ComboBox.SelectString(-1 ,propString->String.c_str ()); - } - OriginalString = propString->String.c_str(); - updateCombo (); - break; - case CPrimitiveClass::CParameter::String: - { - bool backupDefault = Default; - Initializing = true; - setWindowTextUTF8 (EditBox, propString->String.c_str ()); - Default = backupDefault; - Initializing = false; - } - break; - } - } - } - else - { - if (primitiveClass) - { - // Boolean ? - std::string result; - Parameter.getDefaultValue (result, primitive, *primitiveClass, &FromWhere); - if (!result.empty()) - { - switch (Parameter.Type) - { - case CPrimitiveClass::CParameter::Boolean: - // Check the box - CheckBox.SetCheck (2); - updateBoolean (); - break; - case CPrimitiveClass::CParameter::ConstString: - ComboBox.SelectString(-1 ,result.c_str ()); - OriginalString = result.c_str(); - updateCombo (); - break; - case CPrimitiveClass::CParameter::String: - { - setWindowTextUTF8 (EditBox, result.c_str ()); - Default = true; - } - break; - } - } - } - - // Set as filled - Set= true; - } - } - - // Done - setStaticName(); - return true; - } - return false; -} - -// *************************************************************************** - -bool CDialogProperties::CWidget::toParameter (const CDatabaseLocatorPointer &locator, const CPrimitiveClass::CParameter ¶meter) -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Set the parameter - if (Parameter == parameter) - { - // Widget ok ? - if (Set && (!MultipleValues)) - { - // What type ? - if ( (parameter.Type == CPrimitiveClass::CParameter::StringArray) || (parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) - || (parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) ) - { - // Get the value - vector value; - /* todo hulud remove if (Default) - value.clear (); - else*/ - getValue (value); - - if (parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) - { - // Get Current Value. - const IProperty *prop; - vector newValues; - bool haveToUpdate=false; - - if (locator.Primitive->getPropertyByName (parameter.Name.c_str (), prop)) - { - // Dynamic cast - const CPropertyStringArray *const propStringArray = dynamic_cast (prop); - nlassert (propStringArray); - newValues=propStringArray->StringArray; - } - - // have to remove some string ? - // on parse las valeur de la primitive - for (int newValueInd=0;newValueInd<(int)newValues.size();newValueInd++) - { - uint valueInd; - // On check si elles existent dans la dialog - for (valueInd=0;valueInd=value.size()) // not found -> remove it - { - haveToUpdate=true; - newValues.erase(newValues.begin()+newValueInd); - newValueInd--; - } - - } - - // have to add some string ? - // on parse les valeurs de la dialog - std::vector::iterator insertIt=newValues.begin(); - for (uint valueInd=0;valueInd::iterator foundIt=find(newValues.begin(), newValues.end(), value[valueInd]); - if (foundIt==newValues.end()) - { - haveToUpdate=true; - if (insertIt==newValues.end()) - { - newValues.push_back(value[valueInd]); - insertIt=newValues.begin(); - } - else - { - insertIt=newValues.insert(insertIt+1, value[valueInd]); // .push_back(value[valueInd]); - } - - } - else - { - insertIt=foundIt; - } - - } - - } - if (haveToUpdate) - doc->addModification (new CActionSetPrimitivePropertyStringArray (locator, parameter.Name.c_str (), newValues, Default)); - } - - if (parameter.Type == CPrimitiveClass::CParameter::StringArray) - { - // Set the value - if ( value.empty() - || (value[0] != DIFFERENT_VALUE_STRING)) - { - doc->addModification (new CActionSetPrimitivePropertyStringArray (locator, parameter.Name.c_str (), value, Default)); - } - else - { - if (value.size()>1) // More than DIFFERENT_VALUE_STRING - { - // Get Current Value. - const IProperty *prop; - vector newValues; - - if (locator.Primitive->getPropertyByName (parameter.Name.c_str (), prop)) - { - // Dynamic cast - const CPropertyStringArray *const propStringArray = dynamic_cast (prop); - nlassert (propStringArray); - newValues=propStringArray->StringArray; - } - - for (size_t valIndex=1;valIndexaddModification (new CActionSetPrimitivePropertyStringArray (locator, parameter.Name.c_str (), newValues, Default)); - } - - } - - } - - } - else - { - // Get the value - string value; - /* todo hulud remove if (Default) - value = ""; - else*/ - getValue (value); - - // Set the value - if (value != DIFFERENT_VALUE_STRING) - doc->addModification (new CActionSetPrimitivePropertyString (locator, parameter.Name.c_str (), value.c_str (), Default)); - } - } - return true; - } - return false; -} - -// *************************************************************************** - -void CDialogProperties::CWidget::getValue (std::string &result) const -{ - nlassert (Parameter.Type != CPrimitiveClass::CParameter::StringArray); - - // Check box ? - if (Parameter.Type == CPrimitiveClass::CParameter::Boolean) - { - // Get the value - if (CheckBox.GetCheck() == 1) - result = "true"; - else if (CheckBox.GetCheck() == 0) - result = "false"; - else - result = ""; - } - else if (Parameter.Type == CPrimitiveClass::CParameter::ConstString) - { - // Get the text - CString str; - getWindowTextUTF8 (ComboBox, str); - result = (const char*)str; - } - else - { - nlassert (Parameter.Type == CPrimitiveClass::CParameter::String); - - // Get the text - CString str; - getWindowTextUTF8 (EditBox, str); - result = (const char*)str; - } -} - -// *************************************************************************** - -void CDialogProperties::CWidget::getValue (std::vector &result) const -{ - nlassert ( (Parameter.Type == CPrimitiveClass::CParameter::StringArray) || - (Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) ); - - // Get the string - result.clear (); - CString str; - if (Parameter.Type == CPrimitiveClass::CParameter::StringArray) - { - getWindowTextUTF8 (MultiLineEditBox, str); -// MultiLineEditBox.UnloadText(str); - const char *strP = str; - string dst; - while (*strP) - { - // New line ? - if (*strP == '\n') - { - result.push_back (dst); - dst = ""; - } - else if (*strP != '\r') - { - dst += *strP; - } - strP++; - } - if (!dst.empty()) - result.push_back (dst); - } - else - { - uint i; - const uint size = ListEditBox.GetCount(); - result.resize (size); - for (i=0; isetDefaultValue (this, value); - CheckBox.SetCheck(((!value.empty())&&(value=="true"))?1:0); - } - -/* todo hulud remove - if (oldValue != CheckBox.GetCheck()) - ApplyAutoname(widget);*/ - setStaticName(); -} - -// *************************************************************************** - -void CDialogProperties::CWidget::updateCombo () -{ - // No multiple value - MultipleValues = false; - Set = true; - - // Get the default value - if (Default) - { - string value; - DialogProperties->setDefaultValue (this, value); - if (value != "") - { - int index = ComboBox.FindString (-1, value.c_str()); - if (index != CB_ERR) - ComboBox.SetCurSel (index); - } - } - - /* todo hulud remove - if (curSel != ComboBox.GetCurSel()) - ApplyAutoname(widget);*/ - setStaticName(); -} - -// *************************************************************************** - -void CDialogProperties::CWidget::updateMultiline () -{ - // No multiple value - MultipleValues = false; - Set = true; - - // Default ? - if (Default) - { - vector vectString; - DialogProperties->setDefaultValue (this, vectString); - if (!vectString.empty()) - { - // Add the string - string temp; - uint i; - for (i=0; i vectString; - DialogProperties->setDefaultValue (this, vectString); - if (!vectString.empty()) - { - setEditTextMultiLine (ListEditBox, vectString); - } - } - setStaticName(); -} - -// *************************************************************************** - -bool CDialogProperties::isModified() -{ - list::iterator iteWid; - - for (iteWid=Widgets.begin();iteWid!=Widgets.end();iteWid++) - { - if ((*iteWid).Modified) - { - return true; - } - // special case for editable combo box - if ((*iteWid).Parameter.Type == CPrimitiveClass::CParameter::ConstString) - { - CString text; - getWindowTextUTF8 ((*iteWid).ComboBox, text); - if ((*iteWid).OriginalString.c_str() != text) - { - return true; - } - } - } - return false; -} - -// *************************************************************************** - - - -void CDialogProperties::CWidget::getFilename (string &result) -{ - if (Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) - { - int sel = ListEditBox.GetCurSel(); - if (sel != LB_ERR) - { - CString cstr; - ListEditBox.GetText (sel, cstr); - result = (const char*)cstr; - } - else - result = ""; - } - else - { - getValue (result); - } -} - -// *************************************************************************** - -// return true if the given hwnd is one of this widget -bool CDialogProperties::CWidget::isHwndMatch(HWND hWnd) -{ - if (IsWindow (Static.m_hWnd) && Static.m_hWnd == hWnd) - return true; - if (IsWindow (ComboBox.m_hWnd) && ComboBox.m_hWnd == hWnd) - return true; - if (IsWindow (CheckBox.m_hWnd) && CheckBox.m_hWnd == hWnd) - return true; - if (IsWindow (EditBox.m_hWnd) && EditBox.m_hWnd == hWnd) - return true; - if (IsWindow (MultiLineEditBox.m_hWnd) && MultiLineEditBox.m_hWnd == hWnd) - return true; - if (IsWindow (ListEditBox.m_hWnd) && ListEditBox.m_hWnd == hWnd) - return true; - - return false; -} - -// *************************************************************************** - -// get the next window -HWND CDialogProperties::CWidget::getNextWindow(HWND hWnd) -{ - if (hWnd == 0) - { - if (IsWindow (ComboBox.m_hWnd)) - return ComboBox.m_hWnd; - if (IsWindow (EditBox.m_hWnd)) - return EditBox.m_hWnd; - if (IsWindow (MultiLineEditBox.m_hWnd)) - return MultiLineEditBox.m_hWnd; - if (IsWindow (ListEditBox.m_hWnd)) - return ListEditBox.m_hWnd; - if (IsWindow (CheckBox.m_hWnd)) - return CheckBox.m_hWnd; - } - else - { - if (IsWindow (ComboBox.m_hWnd) && ComboBox.m_hWnd == hWnd && IsWindow (CheckBox.m_hWnd)) - return CheckBox.m_hWnd; - if (IsWindow (EditBox.m_hWnd) && EditBox.m_hWnd == hWnd && IsWindow (CheckBox.m_hWnd)) - return CheckBox.m_hWnd; - if (IsWindow (MultiLineEditBox.m_hWnd) && MultiLineEditBox.m_hWnd == hWnd && IsWindow (CheckBox.m_hWnd)) - return CheckBox.m_hWnd; - if (IsWindow (ListEditBox.m_hWnd) && ListEditBox.m_hWnd == hWnd && IsWindow (CheckBox.m_hWnd)) - return CheckBox.m_hWnd; - } - - return 0; -} - -// *************************************************************************** - -// get the previous window -HWND CDialogProperties::CWidget::getPreviousWindow(HWND hWnd) -{ - if (hWnd == 0) - { - if (IsWindow (CheckBox.m_hWnd)) - return CheckBox.m_hWnd; - if (IsWindow (ListEditBox.m_hWnd)) - return ListEditBox.m_hWnd; - if (IsWindow (MultiLineEditBox.m_hWnd)) - return MultiLineEditBox.m_hWnd; - if (IsWindow (EditBox.m_hWnd)) - return EditBox.m_hWnd; - if (IsWindow (ComboBox.m_hWnd)) - return ComboBox.m_hWnd; - } - else - { - if (IsWindow (CheckBox.m_hWnd) && CheckBox.m_hWnd == hWnd) - { - if (IsWindow (ComboBox.m_hWnd)) - return ComboBox.m_hWnd; - if (IsWindow (EditBox.m_hWnd)) - return EditBox.m_hWnd; - if (IsWindow (MultiLineEditBox.m_hWnd)) - return MultiLineEditBox.m_hWnd; - if (IsWindow (ListEditBox.m_hWnd)) - return ListEditBox.m_hWnd; - } - } - - return 0; -} - - -// *************************************************************************** - -bool CDialogProperties::CWidget::OnSize( int cx, int cy, int decY ) -{ - RECT rect; - bool sizeY = false; - - if ( Static.m_hWnd ) - { - Static.GetWindowRect( &rect ); - DialogProperties->m_PropertyFrame.ScreenToClient( &rect ); - rect.top += decY; - rect.bottom += decY; - Static.MoveWindow( &rect ); - } - - if ( ComboBox.m_hWnd && IsWindow( ComboBox.m_hWnd ) ) - { - ComboBox.GetWindowRect( &rect ); - DialogProperties->m_PropertyFrame.ScreenToClient( &rect ); - rect.top += decY; - rect.bottom += decY; - rect.right += cx; - ComboBox.MoveWindow( &rect ); - } - - if ( EditBox.m_hWnd && IsWindow( EditBox.m_hWnd ) ) - { - EditBox.GetWindowRect( &rect ); - DialogProperties->m_PropertyFrame.ScreenToClient( &rect ); - rect.top += decY; - rect.bottom += decY; - rect.right += cx; - EditBox.MoveWindow( &rect ); - } - - if ( MultiLineEditBox.m_hWnd && IsWindow( MultiLineEditBox.m_hWnd ) ) - { - MultiLineEditBox.GetWindowRect( &rect ); - DialogProperties->m_PropertyFrame.ScreenToClient( &rect ); - rect.right += cx; - rect.top += decY; - rect.bottom += decY; - if ( rect.bottom + cy >= rect.top + 100 ) - { - ::CRect dlgRect; - DialogProperties->GetWindowRect( &dlgRect ); - - if ( ( cy <= 0 ) || ( dlgRect.Height() > DialogProperties->getOriginalHeight() ) ) - { - rect.bottom += cy; - sizeY = true; - decY += cy; - } - } - MultiLineEditBox.MoveWindow( &rect ); - } - - if ( ListEditBox.m_hWnd && IsWindow( ListEditBox.m_hWnd ) ) - { - ListEditBox.GetWindowRect( &rect ); - DialogProperties->m_PropertyFrame.ScreenToClient( &rect ); - rect.right += cx; - rect.top += decY; - rect.bottom += decY; - ListEditBox.MoveWindow( &rect ); - } - - if ( CheckBox.m_hWnd ) - { - CheckBox.GetWindowRect( &rect ); - DialogProperties->m_PropertyFrame.ScreenToClient( &rect ); - if ( rect.left > 30 ) - { - rect.left += cx; - rect.right += cx; - } - - CString text; - CheckBox.GetWindowText( text ); - if ( text == "Edit..." ) - { - rect.right += cx; - } - - rect.top += decY; - rect.bottom += decY; - CheckBox.MoveWindow( &rect ); - } - - return sizeY; -} - -// *************************************************************************** - -// *************************************************************************** - -BOOL CDialogProperties::OnCommand(WPARAM wParam, LPARAM lParam) -{ - WORD wNotifyCode = HIWORD(wParam); // notification code - - switch (wNotifyCode) - { - case BN_CLICKED: - { - // Button id - int idButton = (int) LOWORD(wParam); // identifier of button - if (idButton >= FIRST_WIDGET) - { - // Get the widget - CWidget *widget = getWidget (idButton-FIRST_WIDGET); - - // Check box ? - if (widget->Parameter.Type == CPrimitiveClass::CParameter::Boolean) - { - if (widget->Default) - widget->CheckBox.SetCheck(0); - else - widget->CheckBox.SetCheck((widget->CheckBox.GetCheck()+1)%3); - - // If 2 set as default - widget->Default = widget->CheckBox.GetCheck() == 2; - - widget->updateBoolean (); - widget->Modified = true; - } - else if (widget->Parameter.Type == CPrimitiveClass::CParameter::String) - { - // we open a file selector - nlassert (widget->Parameter.FileExtension != ""); - - // Create a dialog file, starting at the specified Folder - /* todo hulud remove - CString oldValue; - widget->EditBox.GetWindowText (oldValue);*/ - CFileDialogEx dialog (BASE_REGISTRY_KEY, "default", TRUE, widget->Parameter.FileExtension.c_str (), NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, - (widget->Parameter.FileExtension+" (*."+widget->Parameter.FileExtension+")|*."+widget->Parameter.FileExtension+"|All Files (*.*)|*.*||").c_str (), getMainFrame ()); - if (widget->Parameter.Folder != "") - { - dialog.m_ofn.lpstrInitialDir = widget->Parameter.Folder.c_str(); - } - if (dialog.DoModal() == IDOK) - { - CString str; - str = dialog.GetFileTitle(); - setWindowTextUTF8 (widget->EditBox, str); - - /* todo hulud remove - if ((const char*)oldValue != str) - ApplyAutoname(widget);*/ - widget->setStaticName(); - widget->Modified = true; - } - } - else if (widget->Parameter.Type == CPrimitiveClass::CParameter::StringArray) - { - if (widget->Parameter.FileExtension.empty()) - { - nlassert (widget->Parameter.Folder != ""); - SelectFolder(widget); - } - else - { - // Edit with an external editor - std::vector result; - widget->getValue (result); - uint i; - string text = ""; - for (i=0; igetConfigFile().getVarPtr ("TextEditor"); - char windows[512]; - GetWindowsDirectory (windows, sizeof (windows)); - if (EditExternalText (var?var->asString():windows+string ("/notepad.exe"), text, widget->Parameter.FileExtension.c_str ())) - { - widget->Default = false; - widget->Modified = true; - widget->updateMultiline(); - setEditTextMultiLine (widget->MultiLineEditBox, text.c_str()); - } - } - } - else - { - // Should be a filename - nlassert (widget->Parameter.Filename); - - // No multiple values ? - if (!widget->MultipleValues) - { - // Get the string - string filename; - widget->getFilename (filename); - - // Not empty ? - if (!filename.empty ()) - { - // Open the file - if (!widget->Parameter.FileExtension.empty ()) - filename += "."+widget->Parameter.FileExtension; - - // Lookup - if (widget->Parameter.Lookup) - filename = CPath::lookup (filename, false, false, false); - if (!filename.empty ()) - { - // Open the file - if (!openFile (filename.c_str ())) - // Error - theApp.errorMessage ("Can't open the file %s", filename.c_str ()); - } - else - { - // Error - widget->getFilename (filename); - theApp.errorMessage ("Can't find the file %s", filename.c_str ()); - } - } - } - } - } - } - break; - case CBN_SELCHANGE: - { - int idComboBox = (int) LOWORD(wParam); // identifier of combo box - nlassert ((idComboBox >= FIRST_WIDGET) || (idComboBox==STRING_SELECT_COMBOBOX_ID)); - - CWidget *widget = getWidget (idComboBox-FIRST_WIDGET); - if (widget->Parameter.Type == CPrimitiveClass::CParameter::ConstString) - { - // Get the widget - int curSel = widget->ComboBox.GetCurSel(); - - // Check box ? - nlassert (widget->Parameter.Type == CPrimitiveClass::CParameter::ConstString); - - // Remove - int index = widget->ComboBox.FindString (-1, DIFFERENT_VALUE_STRING); - if (index != CB_ERR) - widget->ComboBox.DeleteString(index); - - // Default value ? - widget->Default = (widget->ComboBox.GetCurSel () == 0); - widget->updateCombo (); - widget->Modified = true; - } - } - break; - case EN_CHANGE: - { - int idEditCtrl = (int) LOWORD(wParam); // identifier of edit control - if ((idEditCtrl >= FIRST_WIDGET) && (idEditCtrl <= LAST_WIDGET)) - { - // Get the widget - CWidget *widget = getWidget (idEditCtrl-FIRST_WIDGET); - - // Check box ? - if (widget->Parameter.Type == CPrimitiveClass::CParameter::String) - { - // No multiple value - widget->MultipleValues = false; - if (!widget->Initializing) - widget->Modified = true; - widget->Set = true; - - /* todo hulud remove - CString oldValue; - widget->EditBox.GetWindowText (oldValue);*/ - - // String NULL ? - CString text; - getWindowTextUTF8 (widget->EditBox, text); - widget->Default = (text == ""); - - // Default ? - if (widget->Default) - { - string value; - setDefaultValue (widget, value); - if (!value.empty()) - { - setWindowTextUTF8 (widget->EditBox, value.c_str()); - widget->Default = true; - } - } - else if ( text == DIFFERENT_VALUE_STRING ) - widget->Modified = false; - - /* todo hulud remove - CString newValue; - widget->EditBox.GetWindowText (newValue); - if (newValue != oldValue) - ApplyAutoname(widget);*/ - - // No more multiple value - widget->setStaticName(); - } - else if (widget->Parameter.Type == CPrimitiveClass::CParameter::StringArray) - { - nlassert (widget->Parameter.Type == CPrimitiveClass::CParameter::StringArray); - - // String NULL ? - std::vector result; - widget->getValue (result); - widget->Default = result.empty(); - widget->updateMultiline (); - widget->Modified = true; - } - /*else - { - nlassert (widget->Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray); - - // String NULL ? - std::vector result; - widget->getValue (result); - widget->Default = result.empty(); - widget->updateList (); - }*/ - } - } - break; - } - - return CDialog::OnCommand(wParam, lParam); -} - -// *************************************************************************** - -CDialogProperties::CWidget *CDialogProperties::getWidget (uint widgetId) -{ - std::list::iterator ite = Widgets.begin (); - while (widgetId > 0) - { - widgetId--; - ite++; - } - return &(*ite); -} - -// *************************************************************************** - -void CDialogProperties::changeSelection (std::list &locators) -{ - // Print a message if changes will be lost - if (isModified() && !getMainFrame()->yesNoMessage("All changes will be lost ! Are you sure ?")) - return; - - _PropDlgLocators.clear (); - CWorldEditorDoc *doc = getDocument (); - std::list::iterator ite = locators.begin (); - while (ite != locators.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - _PropDlgLocators.push_back (locator); - ite++; - } - - // Shown ? - if (IsWindowVisible ()) - { - rebuildDialog (); - } -} - -// *************************************************************************** -bool CDialogProperties::containsSelection( std::list &locators ) -{ - std::list::iterator ite = locators.begin (); - while (ite != locators.end ()) - { - std::vector::iterator itDB = _PropDlgLocators.begin(); - - bool ok = false; - while ( !ok && ( itDB != _PropDlgLocators.end() ) ) - { - ok = ( (*itDB).Primitive == (*ite) ); - itDB++; - } - - if ( !ok ) - return false; - - ite++; - } - - return true; -} - -// *************************************************************************** -bool CDialogProperties::containsSelection( std::vector &locators ) -{ - std::vector::iterator ite = locators.begin (); - while (ite != locators.end ()) - { - std::vector::iterator itDB = _PropDlgLocators.begin(); - - bool ok = false; - while ( !ok && ( itDB != _PropDlgLocators.end() ) ) - { - ok = ( (*itDB) == (*ite) ); - itDB++; - } - - if ( !ok ) - return false; - - ite++; - } - - return true; -} - -// *************************************************************************** - -bool CDialogProperties::equalsSelection( std::list &locators ) -{ - if ( locators.size() != _PropDlgLocators.size() ) - return false; - - return containsSelection( locators ); -} - -// *************************************************************************** - -void CDialogProperties::rebuildDialog () -{ - // Remove widgets - removeWidgets (); - - // Something selected ? - const uint selSize = _PropDlgLocators.size (); - - // The parameter list - set parameterList; - - // Does at least one of the selected primitive is a static child ? - bool staticChildSelected = false; - - // For each selected primitive - uint i; - for (i=0; i(_PropDlgLocators[i].Primitive)->getParent()==NULL) - { - - /*const CPrimitiveClass::CParameter *tac=&primClass->Parameters[0]; - string sou=tac->DefaultValue[0].Name; - sou="test";*/ - const_cast(_PropDlgLocators[i].Primitive)->removePropertyByName("name"); - const_cast(_PropDlgLocators[i].Primitive)->removePropertyByName("path"); - //TODO faire une fonction dans CWorldDoc pour recup m_strPathName - string name; - getDocument()->getPrimitiveDisplayName(name,_PropDlgLocators[i].getDatabaseIndex()); - string path; - getDocument()->getFilePath(_PropDlgLocators[i].getDatabaseIndex(),path); - - const_cast(_PropDlgLocators[i].Primitive)->addPropertyByName("name",new CPropertyString (name)); - const_cast(_PropDlgLocators[i].Primitive)->addPropertyByName("path",new CPropertyString (path)); - } - - const IPrimitive * primitive= _PropDlgLocators[i].Primitive; - - if (primitive) - { - staticChildSelected |= theApp.Config.isStaticChild (*primitive); - - // Get the class name - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*primitive); - - // Use the class or not ? - if (primClass) - { - // For each properties of the class - for (uint p=0; pParameters.size (); p++) - { - // Is the parameter visible ? - if (primClass->Parameters[p].Visible) - { - parameterList.insert (primClass->Parameters[p]); - } - } - } - else - { - // For each primitive property - uint numProp = primitive->getNumProperty (); - for (uint p=0; pgetProperty (p, propertyName, prop)); - - // Add a default property - CPrimitiveClass::CParameter defProp (*prop, propertyName.c_str ()); - parameterList.insert (defProp); - } - } - } - } - - // Remove property Name, Hidden and Selected - set::iterator ite = parameterList.begin (); - while (ite != parameterList.end ()) - { - // Next iterator - set::iterator next = ite; - next++; - - // Property name ? - if (/*(ite->Name == "name") || *//*(ite->Name == "hidden")*/ /*|| (ite->Name == "selected") ||*/ (ite->Name == "class")) - { - // Remove it - parameterList.erase (ite); - } - - ite = next; - } - - // Add the default parameter - CPrimitiveClass::CParameter defaultParameter; - defaultParameter.Visible = true; - defaultParameter.Filename = false; - - // The name - RECT widgetPos = WidgetPos; - - - // Add the other widgets - //for (i=0;i<3;++i) //JC: a small debug trick to artifically simulate a huge DialogBox - { - // Add first the name - ite = parameterList.begin (); - while (ite != parameterList.end ()) - { - if (ite->Name == "name") - { - addWidget (*ite, widgetPos, staticChildSelected); - break; - } - ite++; - } - - // Then add the other one - ite = parameterList.begin (); - while (ite != parameterList.end ()) - { - if (ite->Name != "name") - addWidget (*ite, widgetPos, false); - - ite++; - } - } - - std::string windowName; - - // For each selected primitive - for (i=0; iName; - else if (primClass->Name != windowName) - windowName = ""; - - // Get the property for name - /*const IProperty *propName; - if (primitive->getPropertyByName ("name", propName)) - { - // Create a default property - CPrimitiveClass::CParameter defProp (*propName, "name"); - - // Add the property in the good widget - std::list::iterator ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - // Set the parameter - if (ite->fromParameter (propName, *primitive, primClass, defProp)) - break; - - ite++; - } - }*/ - - // For each properties of the class - for (uint p=0; pParameters.size (); p++) - { - // Is the parameter visible ? - if (primClass->Parameters[p].Visible) - { - // Get the property - const IProperty *prop; - if (primitive->getPropertyByName (primClass->Parameters[p].Name.c_str(), prop)) - { - // Add the property in the good widget - std::list::iterator ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - // Set the parameter - if (ite->fromParameter (prop, *primitive, primClass, primClass->Parameters[p])) - break; - - ite++; - } - } - else - { - // Add the property in the good widget - std::list::iterator ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - // Set the parameter - if (ite->fromParameter (NULL, *primitive, primClass, primClass->Parameters[p])) - break; - - ite++; - } - } - } - } - } - else - { - // For each primitive property - uint numProp = primitive->getNumProperty (); - for (uint p=0; pgetProperty (p, propertyName, prop)); - - // Create a default property - CPrimitiveClass::CParameter defProp (*prop, propertyName.c_str ()); - - // Add the property in the good widget - std::list::iterator ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - // Set the parameter - if (ite->fromParameter (prop, *primitive, NULL, defProp)) - break; - - ite++; - } - } - } - } - } - - // resize the dialog and sub control to the max or min extend possible - { - // force the cont to it's minimum size before other resizing code - { - RECT contRect; - m_PropertyCont.GetWindowRect(&contRect); - m_PropertyFrame.ScreenToClient(&contRect); - contRect.bottom = max(int(contRect.bottom), m_ContMinHeight); - contRect.right = contRect.left + 425; - m_PropertyCont.MoveWindow(&contRect); - } - // first size to ideal size - RECT desktop; - SystemParametersInfo(SPI_GETWORKAREA, 0, &desktop, 0); - - // resize frame cont - ::CRect contRect; - m_PropertyCont.GetWindowRect(&contRect); - m_PropertyFrame.ScreenToClient(&contRect); - contRect.bottom += -contRect.top; - contRect.bottom = min(int(contRect.bottom), m_MaxFrameHeight); - contRect.top = 0; - AdjustWindowRectEx(&contRect, - m_PropertyFrame.GetStyle(), - false, - m_PropertyFrame.GetExStyle()); -// m_PropertyFrame.CalcWindowRect(&contRect); - int height = contRect.Height(); - m_PropertyFrame.MoveWindow(PropertyFrameRect.top, - PropertyFrameRect.left, - 445,//PropertyFrameRect.right-PropertyFrameRect.left, - height); - m_PropertyFrame.GetClientRect(&contRect); - - // resize dialog - RECT dialogRect; - GetWindowRect(&dialogRect); - ScreenToClient(&dialogRect); - m_PropertyFrame.GetWindowRect(&contRect); - ScreenToClient(&contRect); - dialogRect.bottom = contRect.bottom + m_FrameBottomSpace; - ClientToScreen(&dialogRect); - dialogRect.right = dialogRect.left + 455; - m_curDlgRect = dialogRect; - m_originalHeight = m_curDlgRect.Height(); - MoveWindow(&dialogRect); - - // replace the dialog in available window place - GetWindowRect(&dialogRect); - if (dialogRect.top < desktop.top) - { - dialogRect.bottom = desktop.top + (dialogRect.bottom - dialogRect.top); - dialogRect.top = desktop.top; - } - if (dialogRect.bottom > desktop.bottom) - { - dialogRect.top = desktop.bottom - (dialogRect.bottom - dialogRect.top); - dialogRect.bottom = desktop.bottom; - } - - - MoveWindow(&dialogRect); - m_DialogWidth = dialogRect.right - dialogRect.left; - -/* // now, size to physical available size and minimum size - int height = dialogRect.bottom - dialogRect.top; - int deskHeight = desktop.bottom - desktop.top; - height = min(height, deskHeight); - height = max(height, int(PropertyFrameRect.bottom-PropertyFrameRect.top)); - - dialogRect.bottom = dialogRect.top + height; - - if (dialogRect.bottom > desktop.bottom) - { - dialogRect.top -= dialogRect.bottom-desktop.bottom; - dialogRect.bottom = desktop.bottom; - } - - MoveWindow(&dialogRect); - ScreenToClient(&dialogRect); - - // resize frame to desktop size - m_PropertyFrame.GetWindowRect(&contRect); - ScreenToClient(&contRect); - contRect.bottom = dialogRect.bottom-m_FramePos; - m_PropertyFrame.MoveWindow(&contRect); - // resize container window - m_PropertyCont.GetWindowRect(&contRect); - m_PropertyFrame.ScreenToClient(&contRect); - - - - if (contRect.bottom-contRect.top < m_ContMinHeight) - contRect.bottom = contRect.top + m_ContMinHeight; - - m_PropertyCont.MoveWindow(&contRect); -*/ - } - - // replace the 3 button - RECT dialogRect; - GetClientRect(&dialogRect); - RECT buttonRect; - // OK - GetDlgItem(IDOK)->GetWindowRect(&buttonRect); - ScreenToClient(&buttonRect); - buttonRect.bottom = (dialogRect.bottom - m_ButtonPos) + (buttonRect.bottom-buttonRect.top); - buttonRect.top = dialogRect.bottom - m_ButtonPos; - GetDlgItem(IDOK)->MoveWindow(&buttonRect); - // cancel - GetDlgItem(IDCANCEL)->GetWindowRect(&buttonRect); - ScreenToClient(&buttonRect); - buttonRect.bottom = (dialogRect.bottom - m_ButtonPos) + (buttonRect.bottom-buttonRect.top); - buttonRect.top = dialogRect.bottom - m_ButtonPos; - GetDlgItem(IDCANCEL)->MoveWindow(&buttonRect); - //IDUPDATE - GetDlgItem(IDUPDATE)->GetWindowRect(&buttonRect); - ScreenToClient(&buttonRect); - buttonRect.bottom = (dialogRect.bottom - m_ButtonPos) + (buttonRect.bottom-buttonRect.top); - buttonRect.top = dialogRect.bottom - m_ButtonPos; - GetDlgItem(IDUPDATE)->MoveWindow(&buttonRect); - - RECT contRect; - m_PropertyCont.GetWindowRect(&contRect); - RECT frameRect; - m_PropertyFrame.GetClientRect(&frameRect); - // Set the scroll bar value - SCROLLINFO si; - si.cbSize = sizeof(SCROLLINFO); - si.fMask = SIF_PAGE | SIF_RANGE/*SIF_ALL*/|SIF_DISABLENOSCROLL; // SIF_ALL = SIF_PAGE | SIF_RANGE | SIF_POS; - si.nMin = 0; - si.nMax = contRect.bottom - contRect.top; - si.nPage = frameRect.bottom; - int pos = std::min(LONG(m_ScrollBar.GetScrollPos()), std::max(LONG(0), LONG(si.nMax - si.nPage))); - m_ScrollBar.SetScrollInfo(&si, FALSE); - // foul MFC by sending a pseudo message - OnVScroll(SB_THUMBPOSITION, pos, &m_ScrollBar); - - // replace the scroll bar control - RECT scrollRect; - m_PropertyFrame.GetClientRect(&scrollRect); - m_PropertyFrame.ClientToScreen(&scrollRect); - scrollRect.left = scrollRect.right-16; - ScreenToClient(&scrollRect); - m_ScrollBar.MoveWindow(&scrollRect, TRUE); - - // set the name of the dlg according to displayed class - SetWindowText( ( std::string( "Properties for : " ) + windowName ).c_str() ); - -// // JC: added scrolling properties -// ::CRect clientRect; -// GetClientRect (clientRect); -// GetWindowRect (m_rect); -// -// m_nScrollPos = 0; -// -// HWND hWndEntireScreen = ::GetDesktopWindow(); -// BOOL bSuccess = ::GetWindowRect(hWndEntireScreen,&rectEntireScreen); -// _ScrollBar = false; -// if (bSuccess != FALSE) -// { -// RECT desktop; -// GetDesktopWindow()->GetClientRect(&desktop); -//// GetDesktopWindow()->ClientToScreen(&desktop); -// -// int nHeightOfMyDlg = m_rect.Height(); -// int nMaxDesiredHeight = desktop.bottom; -// if (nHeightOfMyDlg >= nMaxDesiredHeight) -// { -// // resize to 90% of the entire screen, and vertically center it on the screen -// MoveWindow(m_rect.left,(int)(0.05*rectEntireScreen.Height()), m_rect.Width(),nMaxDesiredHeight); -// } -// -// GetWindowRect (m_rect2); -// -// int nScrollMax = clientRect.Height(); -// GetClientRect (clientRect); -// int nScrollPage = clientRect.Height()+1; // clientRect.Height(); -// -// SCROLLINFO si; -// si.cbSize = sizeof(SCROLLINFO); -// si.fMask = SIF_ALL|SIF_DISABLENOSCROLL; // SIF_ALL = SIF_PAGE | SIF_RANGE | SIF_POS; -// si.nMin = 0; -// si.nMax = nScrollMax; -// si.nPage = nScrollPage; // si.nMax/SCROLLING_STEPS; -// si.nPos = 0; -// m_ScrollBar.SetScrollInfo(/*(SB_VERT/*|SB_CTL*/ &si, TRUE); -// _ScrollBar = true; -// } - - ApplyAutoname(); - - for (i=0; i(_PropDlgLocators[i].Primitive)->getParent()==NULL) - { - const_cast(_PropDlgLocators[i].Primitive)->removePropertyByName("name"); - const_cast(_PropDlgLocators[i].Primitive)->removePropertyByName("path"); - const_cast(_PropDlgLocators[i].Primitive)->addPropertyByName("name",new CPropertyString ("")); - } - } - - // focus the first control - if (!Widgets.empty()) - { - HWND toFocus = Widgets.begin()->getNextWindow(0); - //(*Widgets.begin()).setFocus(); - ::SetFocus(toFocus); - ::RedrawWindow(toFocus, NULL, NULL, RDW_INVALIDATE|RDW_INTERNALPAINT); - // It's "name", so select content - Widgets.begin()->EditBox.SetSel(0, -1, true); -// if (focusName.empty()) -// { -// toFocus = Widgets.begin()->getNextWindow(0); -// } -// else -// { -// // try to find a widget with the same parameter name as previous -// list::iterator first(Widgets.begin()), last(Widgets.end()); -// for (; first != last; ++first) -// { -// if (first->Parameter.Name == focusName) -// { -// toFocus = first->getNextWindow(0); -// break; -// } -// } -// // no match, focus the first -// if (first == last) -// { -// toFocus = Widgets.begin()->getNextWindow(0); -// } -// } - -// // keep the focused control in slider visibility -// { -// int move = 0; -// -// RECT focusPos; -// ::GetWindowRect(toFocus, &focusPos); -// -// m_PropertyFrame.ScreenToClient(&focusPos); -// RECT framePos; -// m_PropertyFrame.GetClientRect(&framePos); -// if (focusPos.top < framePos.top) -// move = focusPos.top - framePos.top; -// else if (focusPos.bottom > framePos.bottom) -// move = focusPos.bottom - framePos.bottom; -// -// if (move != 0) -// { -// move = m_ScrollBar.GetScrollPos()+move; -// // full MFC by sending a pseudo message -// OnVScroll(SB_THUMBPOSITION, move, &m_ScrollBar); -// } -// -// } - - } - - SetActiveWindow(); - // trigger a global redraw of the dialog - Invalidate(); -} - -// *************************************************************************** - -void CDialogProperties::OnShowWindow(BOOL bShow, UINT nStatus) -{ - if (bShow) - rebuildDialog (); - - CDialog::OnShowWindow(bShow, nStatus); -} - -// *************************************************************************** - -void CDialogProperties::OnUpdate() -{ - // we update the current dialog - updateModification (); - updateModification (); - - // then, we look for other dialogs to be updated - std::list::iterator it = PropertiesDialogs.begin(); - - while ( it != PropertiesDialogs.end() ) - { - if ( (*it)->containsSelection( _PropDlgLocators ) || - containsSelection( (*it)->_PropDlgLocators ) ) - (*it)->rebuildDialog(); - it++; - } -} - -// *************************************************************************** - -void CDialogProperties::updateModification () -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Something selected ? - const uint selSize = _PropDlgLocators.size (); - - // Auto name - ApplyAutoname (); - - // Modification - bool inModificationMode = doc->inModificationMode(); - if (/*!_Modal &&*/ !inModificationMode) - doc->beginModification (); - - // For each selected primitive - for (uint i=0; igetPropertyByName ("name", propName)) - { - // Create a default property - CPrimitiveClass::CParameter defProp (*propName, "name"); - - // Add the property in the good widget - std::list::iterator ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - // Set the parameter - if (ite->toParameter (_PropDlgLocators[i], defProp)) - break; - (*ite).Modified=false; - - ite++; - } - } - - // For each properties of the class - for (uint p=0; pParameters.size (); p++) - { - // Is the parameter visible ? - if (primClass->Parameters[p].Visible) - { - // Add the property in the good widget - std::list::iterator ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - (*ite).Modified=false; - if (ite->toParameter (_PropDlgLocators[i], primClass->Parameters[p])) - break; - - - ite++; - } - } - } - } - else - { - // For each primitive property - uint numProp = primitive->getNumProperty (); - for (uint p=0; pgetProperty (p, propertyName, prop)); - - // Create a default property - CPrimitiveClass::CParameter defProp (*prop, propertyName.c_str ()); - - // Add the property in the good widget - std::list::iterator ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - (*ite).Modified=false; - if (ite->toParameter (_PropDlgLocators[i], defProp)) - break; - - ite++; - } - } - } - } - } - - // Modification - if (/*!_Modal &&*/ !inModificationMode) - doc->endModification (); - - getMainFrame ()->updateData (); -} - -// *************************************************************************** - -void CDialogProperties::updateModifiedState () -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Something selected ? - const uint selSize = _PropDlgLocators.size (); - - - - // Modification - bool inModificationMode = doc->inModificationMode(); - if (!_Modal && !inModificationMode) - doc->beginModification (); - - // For each selected primitive - for (uint i=0; igetPropertyByName ("name", propName)) - { - // Create a default property - CPrimitiveClass::CParameter defProp (*propName, "name"); - - // Add the property in the good widget - std::list::iterator ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - - (*ite).Modified=false; - - ite++; - } - } - - // For each properties of the class - for (uint p=0; pParameters.size (); p++) - { - // Is the parameter visible ? - if (primClass->Parameters[p].Visible) - { - // Add the property in the good widget - std::list::iterator ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - (*ite).Modified=false; - - - - ite++; - } - } - } - } - else - { - // For each primitive property - uint numProp = primitive->getNumProperty (); - for (uint p=0; pgetProperty (p, propertyName, prop)); - - // Create a default property - CPrimitiveClass::CParameter defProp (*prop, propertyName.c_str ()); - - // Add the property in the good widget - std::list::iterator ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - (*ite).Modified=false; - - ite++; - } - } - } - } - } - - // Modification - if (!_Modal && !inModificationMode) - doc->endModification (); -} - -// *************************************************************************** - -void CDialogProperties::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) -{ - // TODO: Add your message handler code here and/or call default - -// m_ScrollBar.OnVScroll(nSBCode, nPos, pScrollBar); - - if ( !IsWindowVisible() ) - return; - - CDialog::OnVScroll(nSBCode, nPos, pScrollBar); - - RECT frameRect; - m_PropertyFrame.GetClientRect(&frameRect); -// m_PropertyFrame.ScreenToClient(&contRect); -// contRect.top = -m_ScrollBar.GetScrollPos(); -// contRect.bottom = -m_ScrollBar.GetScrollPos(); -// m_PropertyCont.s&contRect, TRUE); - -// -// int nDelta; -// int nMaxPos = m_rect.Height() - m_rect2.Height(); -// - int newPos; - int limit = pScrollBar->GetScrollLimit(); - switch (nSBCode) - { - case SB_LINEDOWN: - newPos = std::min(limit, int(pScrollBar->GetScrollPos()+16)); - break; - - case SB_LINEUP: - newPos = std::max(0, int(pScrollBar->GetScrollPos()-16)); - break; - - case SB_PAGEDOWN: - newPos = std::min(limit, int(pScrollBar->GetScrollPos()+frameRect.bottom)); - break; - - case SB_PAGEUP: - newPos = std::max(0, int(pScrollBar->GetScrollPos()-frameRect.bottom)); - break; - - case SB_THUMBPOSITION: - case SB_THUMBTRACK: - newPos = nPos; - break; - default: - return; - } -// m_nScrollPos += nDelta; -// m_ScrollBar.SetScrollPos(SB_VERT,m_nScrollPos,TRUE); - pScrollBar->SetScrollPos(newPos, TRUE); - RECT contRect; - m_PropertyCont.GetWindowRect(&contRect); - m_PropertyFrame.ScreenToClient(&contRect); -// int delta = -contRect.top - newPos; - int height = contRect.bottom - contRect.top; - contRect.top = -newPos; - contRect.bottom = contRect.top + height; -// m_PropertyFrame.ClientToScreen(&contRect); - m_PropertyCont.MoveWindow(&contRect, TRUE); - - m_PropertyFrame.GetWindowRect(&contRect); - ScreenToClient(&contRect); - -// m_PropertyCont.ScrollWindow(0, delta); - -} - -// *************************************************************************** - -void CDialogProperties::ApplyAutoname() -{ - // Update default parameters - std::list::iterator ite = Widgets.begin(); - while (ite != Widgets.end()) - { - if (ite->Default) - { - if (ite->Parameter.Type == CPrimitiveClass::CParameter::Boolean) - { - ite->CheckBox.SetCheck (2); - ite->updateBoolean (); - } - else if (ite->Parameter.Type == CPrimitiveClass::CParameter::ConstString) - { - ite->ComboBox.SelectString(-1 , ""); - ite->updateCombo (); - } - else if (ite->Parameter.Type == CPrimitiveClass::CParameter::String) - { - ite->Initializing = true; - ite->EditBox.SetWindowText(""); - ite->Initializing = false; - } - else if (ite->Parameter.Type == CPrimitiveClass::CParameter::StringArray) - { - ite->Initializing = true; - ite->MultiLineEditBox.SetWindowText(""); - ite->Initializing = false; -// ite->MultiLineEditBox.LoadText(CString()); - ite->updateMultiline (); - } - else if (ite->Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) - { - ite->Initializing = true; - ite->ListEditBox.SetWindowText(""); - ite->Initializing = false; - ite->updateList (); - } - } - - ite++; - } - -/* // is the widget Autonamable ? - string b = widget->Parameter.Autoname; - if (!b.empty()) - { - // we get the widget's name to propagate it to the linked name - CString result; - if (widget->Parameter.Type == CPrimitiveClass::CParameter::Boolean) - { - if (widget->CheckBox.GetCheck() == 1) - result = "true"; - else if (widget->CheckBox.GetCheck() == 0) - result = "false"; - } - else if (widget->Parameter.Type == CPrimitiveClass::CParameter::ConstString) - { - // and we rename the correct field accordingly - widget->ComboBox.GetLBText(widget->ComboBox.GetCurSel(), result); - } - else if (widget->Parameter.Type == CPrimitiveClass::CParameter::String) - { - widget->EditBox.GetWindowText(result); - } - else if (widget->Parameter.Type == CPrimitiveClass::CParameter::StringArray) - { - // we just get the first element - std::vector tempArray; - widget->getValue (tempArray); - if (!tempArray.empty()) - { - result = tempArray[0].c_str(); - } - } - - std::list::iterator ite; - // if the widget has autoname, we simply copy its name to the linked widget - ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - CWidget &widget2 = *ite; - if (widget2.Parameter.Type == CPrimitiveClass::CParameter::String) - { - string a = widget2.Parameter.Name; - if (a == b) - { - // propagate the name to the autonamed field - CString str2; - widget2.EditBox.GetWindowText(str2); - int i = str2.GetLength(); - while(--i >= 0) - { - if (str2[i] <'0' || str2[i]>'9') - { - break; - } - } - // copy the name, followed by the existing number - widget2.EditBox.SetWindowText(result+"_"+str2.Mid(i+1)); - } - } - ite++; - } - } - else - { - const uint selSize = _Locators.size (); - - // The parameter list - set parameterList; - - // For each selected primitive - uint i; - for (i=0; iAutoname != "") - { - // we rename the string in one pass - CString Name = primClass->Autoname.c_str(); - // is the widget useful for building the name ? No->let's continue - CString fnd = widget->Parameter.Name.c_str(); - fnd = "$"+fnd+"$"; - if (Name.Find(fnd)<0) continue; - - std::list::iterator ite; - // if the widget has autoname, we simply copy its name to the linked widget - ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - CWidget &widget2 = *ite; - // we get the widget's name to propagate it to the linked name - CString result; - CString old = widget2.Parameter.Name.c_str(); - old = "$"+old+"$"; - if (widget2.Parameter.Type == CPrimitiveClass::CParameter::Boolean) - { - if (widget2.CheckBox.GetCheck() == 1) - result = "true"; - else if (widget2.CheckBox.GetCheck() == 0) - result = "false"; - Name.Replace(old, result); - } - else if (widget2.Parameter.Type == CPrimitiveClass::CParameter::ConstString) - { - // and we rename the correct field accordingly - int sel=widget2.ComboBox.GetCurSel(); - if (sel != -1) - { - widget2.ComboBox.GetLBText(sel, result); - } - Name.Replace(old, result); - } - else if (widget2.Parameter.Type == CPrimitiveClass::CParameter::String) - { - if (widget2.Parameter.Name != "name") - { - widget2.EditBox.GetWindowText(result); - Name.Replace(old, result); - } - } - else if (widget2.Parameter.Type == CPrimitiveClass::CParameter::StringArray) - { - // we just get the first element - std::vector tempArray; - widget2.getValue (tempArray); - if (!tempArray.empty()) - { - result = tempArray[0].c_str(); - } - } - ite++; - } - - // then, we set the name of the "name" editbox - ite = Widgets.begin (); - while (ite != Widgets.end ()) - { - CWidget &widget2 = *ite; - - if (widget2.Parameter.Type == CPrimitiveClass::CParameter::String) - { - if (widget2.Parameter.Name == "name") - { - // propagate the name to the autonamed field - CString str2; - if (Name != str2) - { - widget2.EditBox.SetWindowText(Name); - } - } - } - ite++; - } - - } - - } - } - } - }*/ -} - -// *************************************************************************** - -void CDialogProperties::CWidget::setStaticName() -{ - string Name = Parameter.Name; - if (Default) - { - Name += " (default value)"; - } - if (Parameter.Type == CPrimitiveClass::CParameter::Boolean) - { - setWindowTextUTF8 (CheckBox, Name.c_str()); - } - else - { - setWindowTextUTF8 (Static, Name.c_str()); - } -} - -// *************************************************************************** - -void CDialogProperties::SelectFolder(CWidget *widget) -{ - // select a directory in Win95 and NT4 (ugly code taken from Microsoft) - BROWSEINFO bi; - memset((LPVOID)&bi, 0, sizeof(bi)); - TCHAR szDisplayName[_MAX_PATH]; - szDisplayName[0] = '\0'; - bi.hwndOwner = GetSafeHwnd(); - bi.pszDisplayName = szDisplayName; - bi.lpszTitle = _T("Pick a folder, any folder:"); - bi.ulFlags = BIF_RETURNONLYFSDIRS; - bi.lpfn = NULL; - bi.lParam = 0; - - LPITEMIDLIST pidlRoot = NULL; - LPSHELLFOLDER desktop; - OLECHAR olePath[_MAX_PATH + 1]; - ULONG ulDummy; - - SHGetDesktopFolder (&desktop); - - if (widget->Parameter.Folder != "") - { - LPTSTR szPath = (char *)widget->Parameter.Folder.c_str(); - MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, szPath, -1, olePath, _MAX_PATH); - desktop->ParseDisplayName (NULL, NULL, olePath, &ulDummy, &pidlRoot, &ulDummy); - } - bi.pidlRoot = pidlRoot; - - LPMALLOC pMalloc; - HRESULT hr = SHGetMalloc(&pMalloc); - - LPITEMIDLIST pIIL = ::SHBrowseForFolder(&bi); - - if (pIIL != NULL) - { - TCHAR szInitialDir[_MAX_PATH]; - BOOL bRet = ::SHGetPathFromIDList(pIIL, (char*)&szInitialDir); - if (bRet) - { - int s = strlen(szInitialDir); - while (s) - { - --s; - if (szInitialDir[s] == '\\' || szInitialDir[s] == ':') - { - ++s; - break; - } - } - - std::vector tempArray; - widget->getValue (tempArray); - tempArray.push_back (szInitialDir+s); - setEditTextMultiLine (widget->MultiLineEditBox, tempArray); - widget->updateMultiline (); - - widget->MultipleValues = false; - widget->Modified = true; - widget->Set = true; - widget->Default = false; - /* todo hulud remove - ApplyAutoname(widget);*/ - widget->setStaticName(); - - pMalloc->Free(pIIL); - } - } - - desktop->Release (); - if (pidlRoot) pMalloc->Free (pidlRoot); - pMalloc->Release (); -} - -// *************************************************************************** - -BOOL CDialogProperties::PreTranslateMessage(MSG* pMsg) -{ - if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) - { - UINT &message = pMsg->message; - // handle 'tab' for widgets - if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB) - { - bool shift = ::GetAsyncKeyState(VK_SHIFT) != 0; - bool widgetWindow = true; - HWND tabTo = 0; - - // yep, we got a tab, check the wnd - std::list::iterator first(Widgets.begin()), last(Widgets.end()); - for (; first != last; ++first) - { - if (first->isHwndMatch(pMsg->hwnd)) - { - // ok, we got the good one, focus the next widget or wrap - if (!shift) - { - tabTo = first->getNextWindow(pMsg->hwnd); - if (!tabTo) - { - // advance to next widget - ++first; - if (first == last) - { - tabTo = m_OKButton.m_hWnd; - widgetWindow = false; - } - else - tabTo = first->getNextWindow(0); - } - } - else - { - tabTo = first->getPreviousWindow(pMsg->hwnd); - if (!tabTo) - { - // advance to previous widget - if (first == Widgets.begin()) - { - tabTo = m_updateButton.m_hWnd; - widgetWindow = false; - } - else - { - --first; - tabTo = first->getPreviousWindow(0); - } - } - } - - // stop to parse the widget - break; - - } - } - - // if no tab found, try the main button - if (!tabTo && !Widgets.empty()) - { - // not a widget window, check Ok and Update buttons - if (pMsg->hwnd == m_OKButton.m_hWnd && shift) - { - // select the last widget - CWidget &wg = Widgets.back(); - tabTo = wg.getPreviousWindow(0); - widgetWindow = false; - } - else if (pMsg->hwnd == m_updateButton.m_hWnd && !shift) - { - // select the first widget - CWidget &wg = Widgets.front(); - tabTo = wg.getNextWindow(0); - widgetWindow = true; - } - } - - // some focus to set ? - if (tabTo) - { - // focus and redraw the control (to showup focus rectagne if needed) - ::SetFocus(tabTo); - ::RedrawWindow(tabTo, NULL, NULL, RDW_INVALIDATE|RDW_INTERNALPAINT); - // keep the focused control in slider visibility - if (widgetWindow) - { - int move = 0; - - RECT focusPos; - ::GetWindowRect(tabTo, &focusPos); - - m_PropertyFrame.ScreenToClient(&focusPos); - // add the additionnal space for label (we like to see the label of current control !) - focusPos.top -= LABEL_HEIGHT + 5; - - RECT framePos; - m_PropertyFrame.GetClientRect(&framePos); - if (focusPos.top < framePos.top) - move = focusPos.top - framePos.top; - else if (focusPos.bottom > framePos.bottom) - move = focusPos.bottom - framePos.bottom; - - if (move != 0) - { - move = m_ScrollBar.GetScrollPos()+move; - // full MFC by sending a pseudo message - OnVScroll(SB_THUMBPOSITION, move, &m_ScrollBar); - } - - } - return TRUE; - } - } - // handle ALT+arrow to change selection - else if (pMsg->message == WM_SYSKEYDOWN - && (pMsg->wParam == VK_UP - || pMsg->wParam == VK_DOWN - || pMsg->wParam == VK_LEFT - || pMsg->wParam == VK_RIGHT)) - { - - CToolsLogic *toolWnd = dynamic_cast(getMainFrame ()->m_wndSplitter.GetPane(0,1)); - - toolWnd->GetTreeCtrl()->SendMessage(WM_KEYDOWN, pMsg->wParam, 0); - - return TRUE; - } - - // finally, translate the message - if (::TranslateAccelerator(theApp.m_pMainWnd->m_hWnd, _AccelTable, pMsg)) - return TRUE; - - } - - return CDialog::PreTranslateMessage(pMsg); -} - -// *************************************************************************** - -void CDialogProperties::setDefaultValue (CWidget *widget, string &value) -{ - value = ""; - bool foundOne = false; - widget->MultipleValues = false; - string fromWhere; - - // Something selected ? - const uint selSize = _PropDlgLocators.size (); - - // For each selected primitive - for (uint i=0; iParameters.size(); p++) - { - if (primClass->Parameters[p].Name == widget->Parameter.Name) - { - string temp; - primClass->Parameters[p].getDefaultValue (temp, *primitive, *primClass, &fromWhere); - - if (foundOne) - { - if (value != temp) - { - value = DIFFERENT_VALUE_STRING; - widget->MultipleValues = true; - } - if (widget->FromWhere != fromWhere) - { - widget->FromWhere = ""; - } - } - else - { - value = temp; - foundOne = true; - widget->FromWhere = fromWhere; - } - - break; - } - } - } - } - } -} - -// *************************************************************************** - -void CDialogProperties::setDefaultValue (CWidget *widget, std::vector &value) -{ - value.clear (); - bool foundOne = false; - widget->MultipleValues = false; - string fromWhere; - - // Something selected ? - const uint selSize = _PropDlgLocators.size (); - - // For each selected primitive - for (uint i=0; iParameters.size(); p++) - { - if (primClass->Parameters[p].Name == widget->Parameter.Name) - { - vector temp; - primClass->Parameters[p].getDefaultValue (temp, *primitive, *primClass, &fromWhere); - - if (foundOne) - { - if (value != temp) - { - value.resize (1); - value[0] = DIFFERENT_VALUE_STRING; - widget->MultipleValues = true; - } - if (widget->FromWhere != fromWhere) - { - widget->FromWhere = ""; - } - } - else - { - value = temp; - foundOne = true; - widget->FromWhere = fromWhere; - } - - break; - } - } - } - } - } -} - -// *************************************************************************** - -LRESULT CDialogProperties::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) -{ - switch (message) - { - case LBN_CHANGE: - // Button id - int idButton = wParam; // identifier of button - if (idButton >= FIRST_WIDGET) - { - // Get the widget - CWidget *widget = getWidget (idButton-FIRST_WIDGET); - nlassert (widget->Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray); - - // String NULL ? - std::vector result; - widget->getValue (result); - widget->Default = result.empty(); - widget->updateList (); - widget->Modified = true; - } - - break; - } - - return CDialog::WindowProc(message, wParam, lParam); -} - -// *************************************************************************** - -void CDialogProperties::OnSetFocus(CWnd*) -{ - if(!Widgets.empty()) - { - list::iterator ite=Widgets.begin(); - (*ite).setFocus(); - } -} - -// *************************************************************************** - -BOOL CDialogProperties::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) -{ - int pos = m_ScrollBar.GetScrollPos(); - pos -= zDelta; - m_ScrollBar.SetScrollPos(pos, FALSE); - pos = m_ScrollBar.GetScrollPos(); - OnVScroll(SB_THUMBPOSITION, pos, &m_ScrollBar); -// m_ScrollBar.OnMouseWheel(nFlags, zDelta, pt); -/* if (_ScrollBar) - { - int newPos = m_nScrollPos - zDelta; - clamp(newPos, 0, m_rect.Height() - m_rect2.Height()); - int delta = newPos - m_nScrollPos; - if (delta) - { - m_nScrollPos += delta; - SetScrollPos(SB_VERT,m_nScrollPos,TRUE); - ScrollWindow(0,-delta); - } - } -*/ - return CDialog::OnMouseWheel(nFlags, zDelta, pt); - -} - -// *************************************************************************** - -bool dataToClipboard (CWnd *wnd, UINT format, void *data, uint len) -{ - // Open the clipboard - if (wnd->OpenClipboard ()) - { - nlverify (EmptyClipboard ()); - if (data) - { - // Alloc a global memory - HGLOBAL hData = GlobalAlloc (GMEM_MOVEABLE|GMEM_DDESHARE, len); - if (hData) - { - // Copy the string - LPVOID dataPtr = GlobalLock (hData); - nlverify (dataPtr); - memcpy (dataPtr, data, len); - - // Release the pointer - GlobalUnlock (hData); - - // Set the clipboard - nlverify (SetClipboardData (format, hData)); - - // Close the clipboard - CloseClipboard (); - - // Ok - return true; - } - } - - // Close the clipboard - CloseClipboard (); - } - return false; -} - -// *************************************************************************** - -bool dataFromClipboard (CWnd *wnd, UINT format, void *data, uint lenMax) -{ - // Open the clipboard - if (wnd->OpenClipboard ()) - { - // Get the clipboard data - HANDLE hData = GetClipboardData (format); - if (hData) - { - DWORD len = GlobalSize (hData); - - // Get the string - LPVOID dataPtr = GlobalLock (hData); - nlverify (dataPtr); - - // Copy the string - memcpy (data, dataPtr, std::min(len, (DWORD)lenMax)); - - // Close the clipboard - CloseClipboard (); - - // Ok - return true; - } - - // Close the clipboard - CloseClipboard (); - } - return false; -} - -// *************************************************************************** - -void CMyComboBox::reloadData() -{ - if (!loaded) - { - int n = GetCurSel(); - CString s; - if(n != CB_ERR) GetLBText(n, s); - ResetContent(); - SetRedraw(FALSE); - InsertString(-1, ""); - for (vector::iterator it=_data.begin(), itEnd=_data.end(); it!=itEnd; ++it) - InsertString(-1, it->c_str()); - loaded = true; - SetRedraw(TRUE); - if(n != CB_ERR) SelectString(-1, s); - } -} - -// *************************************************************************** - -BOOL CMyComboBox::PreTranslateMessage( MSG* pMsg ) -{ - if (Widget != NULL && ((CDialogProperties::CWidget*)Widget)->Parameter.Editable) - { - if (pMsg->message == WM_CHAR) - GetParent()->SendMessage(WM_COMMAND, MAKELPARAM(GetDlgCtrlID(), CBN_SELCHANGE), (LPARAM)m_hWnd); - else if (pMsg->message == WM_LBUTTONDOWN) - reloadData(); - return CComboBox::PreTranslateMessage(pMsg); - } - - bool search = false; - if (pMsg->message == WM_CHAR) - { - // Erase key buffer ? - sint64 time = NLMISC::CTime::getLocalTime (); - if (time - _LastStrokeTime > COMBO_STROKE_DELAI) - _LastString = ""; - - // Add this char - _LastString.push_back (tolower((TCHAR) pMsg->wParam)); - search = true; - - // New stroke time - _LastStrokeTime = time; - } - // Copy ? - else if ((pMsg->message == WM_KEYDOWN) && ('C' == (int) pMsg->wParam) && (GetAsyncKeyState (VK_CONTROL) & 0x8000)) - { - int curSel = GetCurSel (); - if (curSel != CB_ERR) - { - CString rString; - GetLBText (curSel, rString); - dataToClipboard (this, CF_TEXT, (void*)(const char*)rString, rString.GetLength()+1); - } - } - // Paste ? - else if ((pMsg->message == WM_KEYDOWN) && ('V' == (int) pMsg->wParam) && (GetAsyncKeyState (VK_CONTROL) & 0x8000)) - { - char text[512]; - if (dataFromClipboard (this, CF_TEXT, text, 511)) - { - // 0 final - text[511] = 0; - _LastString = text; - search = true; - } - } - // Button down ? - else if (pMsg->message == WM_LBUTTONDOWN) - reloadData(); - - // Process string search ? - if (search) - { - // Find a string with this name - const uint count = GetCount(); - uint i; - uint matchSize = 0; - sint matchItem = -1; - for (i=0; i matchSize) - { - if (strncmp(tmp.c_str(), _LastString.c_str(), size) == 0) - { - matchItem = i; - matchSize = size; - } - } - } - - // Found something ? - if (matchItem != -1) - { - SetCurSel (matchItem); - GetParent()->SendMessage(WM_COMMAND, MAKELPARAM(GetDlgCtrlID(), CBN_SELCHANGE), (LPARAM)m_hWnd); - } - - return TRUE; - } - - return FALSE; -} - -// *************************************************************************** - -void CDialogProperties::OnSize(UINT nType, int cx, int cy) -{ - CDialog::OnSize( nType, cx, cy ); - - if ( !IsWindowVisible() ) - return; - - - ::CRect newDlgRect; - int deltaX, deltaY; - GetWindowRect( &newDlgRect ); - deltaX = newDlgRect.Width() - m_curDlgRect.Width(); - deltaY = newDlgRect.Height() - m_curDlgRect.Height(); - m_curDlgRect = newDlgRect; - - OnVScroll(SB_THUMBPOSITION, 0, &m_ScrollBar); - - { - RECT frameRect; - m_PropertyFrame.GetWindowRect( &frameRect ); - ScreenToClient( &frameRect ); - frameRect.right += deltaX; - frameRect.bottom += deltaY; - m_PropertyFrame.MoveWindow( &frameRect ); - } - - list::iterator ite=Widgets.begin(); - int decPosY = 0; - - while ( ite != Widgets.end() ) - { - if ( (*ite).OnSize( deltaX, deltaY, decPosY ) == true ) - decPosY += deltaY; - ite++; - } - - { - RECT contRect; - m_PropertyCont.GetWindowRect( &contRect ); - m_PropertyFrame.ScreenToClient( &contRect ); - contRect.right += deltaX; - contRect.bottom += decPosY; - //contRect.bottom = contRect.top + cy - m_FrameBottomSpace; - m_PropertyCont.MoveWindow ( &contRect ); - } - - // replace the 3 button - RECT buttonRect, dialogRect; - int space = ( newDlgRect.Width() - m_buttonWidth ) / 2; - int decalage; - GetClientRect(&dialogRect); - - // OK - GetDlgItem(IDOK)->GetWindowRect(&buttonRect); - ScreenToClient(&buttonRect); - buttonRect.bottom = (dialogRect.bottom - m_ButtonPos) + (buttonRect.bottom-buttonRect.top); - buttonRect.top = dialogRect.bottom - m_ButtonPos; - decalage = space - buttonRect.left; - buttonRect.left += decalage; - buttonRect.right += decalage; - GetDlgItem(IDOK)->MoveWindow(&buttonRect); - // cancel - GetDlgItem(IDCANCEL)->GetWindowRect(&buttonRect); - ScreenToClient(&buttonRect); - buttonRect.bottom = (dialogRect.bottom - m_ButtonPos) + (buttonRect.bottom-buttonRect.top); - buttonRect.top = dialogRect.bottom - m_ButtonPos; - buttonRect.left += decalage; - buttonRect.right += decalage; - GetDlgItem(IDCANCEL)->MoveWindow(&buttonRect); - //IDUPDATE - GetDlgItem(IDUPDATE)->GetWindowRect(&buttonRect); - ScreenToClient(&buttonRect); - buttonRect.bottom = (dialogRect.bottom - m_ButtonPos) + (buttonRect.bottom-buttonRect.top); - buttonRect.top = dialogRect.bottom - m_ButtonPos; - buttonRect.left += decalage; - buttonRect.right += decalage; - GetDlgItem(IDUPDATE)->MoveWindow(&buttonRect); - - RECT contRect; - m_PropertyCont.GetWindowRect(&contRect); - RECT frameRect; - m_PropertyFrame.GetClientRect(&frameRect); - // Set the scroll bar value - SCROLLINFO si; - si.cbSize = sizeof(SCROLLINFO); - si.fMask = SIF_PAGE | SIF_RANGE /*SIF_ALL*/|SIF_DISABLENOSCROLL; // SIF_ALL = SIF_PAGE | SIF_RANGE | SIF_POS; - si.nMin = 0; - si.nMax = contRect.bottom - contRect.top; - si.nPage = frameRect.bottom; - int pos = std::min(LONG(m_ScrollBar.GetScrollPos()), std::max(LONG(0), LONG(si.nMax - si.nPage))); - m_ScrollBar.SetScrollInfo(&si, FALSE); - // foul MFC by sending a pseudo message - OnVScroll(SB_THUMBPOSITION, pos, &m_ScrollBar); - - // replace the scroll bar control - RECT scrollRect; - m_PropertyFrame.GetClientRect(&scrollRect); - m_PropertyFrame.ClientToScreen(&scrollRect); - scrollRect.left = scrollRect.right-16; - ScreenToClient(&scrollRect); - m_ScrollBar.MoveWindow(&scrollRect, TRUE); - - - Invalidate(); -} - -// *************************************************************************** - -void CDialogProperties::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI ) -{ - CDialog::OnGetMinMaxInfo( lpMMI ); - - lpMMI->ptMinTrackSize.x = 455; - lpMMI->ptMinTrackSize.y = 50; -} - -// *************************************************************************** - -bool CDialogProperties::removePrimitives( list &locators ) -{ - for(list::iterator itP = locators.begin(); itP != locators.end(); itP++) - { - NLLIGO::IPrimitive* pPrim = *itP; - - for(vector::iterator it = _PropDlgLocators.begin(); it != _PropDlgLocators.end(); it++) - { - if ( (*it).Primitive == pPrim ) - { - _PropDlgLocators.erase( it ); - break; - } - } - } - - if(_PropDlgLocators.empty()) - { - // if all primitives were removed, the dialog is closed - OnCancel(); - return true; - } - else - { - OnUpdate(); - return false; - } -} - - -void CDialogProperties::OnMove(int x, int y) -{ - CDialog::OnMove(x, y); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// dialog_properties.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "main_frm.h" +#include "dialog_properties.h" +#include "nel/misc/path.h" +#include "action.h" +#include +#include "nel/ligo/primitive.h" +#include "tools_logic.h" +#include "external_editor.h" +#include "file_dialog_ex.h" + +using namespace std; +using namespace NLLIGO; +using namespace NLMISC; + +// *************************************************************************** + +#define SCROLLING_STEPS 2 // parameter to finetune the scroller + +#define CHECKBOX_HEIGHT 20 +#define COMBO_REAL_HEIGHT 300 +#define COMBO_HEIGHT 20 +#define LABEL_HEIGHT 15 +#define SPACE_HEIGHT (widgetPos.left) +#define EDIT_HEIGHT 18 +#define FIRST_WIDGET 10 +#define LAST_WIDGET 100 +#define FILE_BUTTON_WIDTH 50 + +#define STRING_SELECT_COMBOBOX_ID 9 + +#define DIFFERENT_VALUE_STRING "" +#define DIFFERENT_VALUE_MULTI_STRING "" + +//CDialogProperties PropertyDialog; +std::list PropertiesDialogs; +CPoint CDialogProperties::s_lastPosition = CPoint( -1, -1 ); + + +BOOL CScrollPane::OnCommand(WPARAM wParam, LPARAM lParam) +{ + // forward control command to dialog. + return m_dlgProperty->OnCommand(wParam, lParam); +} + +LRESULT CScrollPane::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case LBN_CHANGE: + m_dlgProperty->WindowProc(message, wParam, lParam); + break; + } + + return CStatic::WindowProc(message, wParam, lParam); +} + +// *************************************************************************** +// CDialogProperties dialog +// *************************************************************************** + +CDialogProperties::CDialogProperties() +{ + m_PropertyCont.init(this); + _Modal = false; + _Cancel = true; + _ScrollBar = false; +} + +// *************************************************************************** + +CDialogProperties::CDialogProperties(std::list &locators, CWnd* pParent /*=NULL*/) + : CDialog(CDialogProperties::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDialogProperties) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + + m_PropertyCont.init(this); + + // Reserve some memory + _PropDlgLocators.reserve (locators.size ()); + + CWorldEditorDoc *doc = getDocument (); + std::list::iterator ite = locators.begin (); + while (ite != locators.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + _PropDlgLocators.push_back (locator); + ite++; + } + + _Modal = true; + _Cancel = false; +} + +// *************************************************************************** + +void CDialogProperties::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDialogProperties) + DDX_Control(pDX, IDUPDATE, m_updateButton); + DDX_Control(pDX, IDOK, m_OKButton); + DDX_Control(pDX, IDC_FIRST_PROP, m_FirstProp); + DDX_Control(pDX, IDC_PROPERTY_FRAME, m_PropertyFrame); + DDX_Control(pDX, IDC_SCROLLBAR_PROP, m_ScrollBar); + //}}AFX_DATA_MAP +} + +// *************************************************************************** + +BEGIN_MESSAGE_MAP(CDialogProperties, CDialog) + //ON_NOTIFY_RANGE( LVN_ITEMACTIVATE, 0, -1, onListCtrlItemActivate ) + //{{AFX_MSG_MAP(CDialogProperties) + ON_WM_SHOWWINDOW() + ON_BN_CLICKED(IDUPDATE, OnUpdate) + ON_WM_VSCROLL() + ON_WM_MOUSEWHEEL() + ON_WM_SIZE() + ON_WM_GETMINMAXINFO() + ON_WM_SETFOCUS() + ON_WM_MOVE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// *************************************************************************** +// CDialogProperties message handlers +// *************************************************************************** + +void CDialogProperties::OnOK() +{ + + OnUpdate(); + + ::CRect rect; + GetWindowRect( &rect ); + + s_lastPosition = CPoint( rect.left, rect.top ); + PropertiesDialogs.remove( this ); + + CDialog::OnOK(); +} + +// *************************************************************************** + +void CDialogProperties::OnCancel() +{ + ::CRect rect; + GetWindowRect( &rect ); + + s_lastPosition = CPoint( rect.left, rect.top ); + PropertiesDialogs.remove( this ); + + CDialog::OnCancel(); +} + +// *************************************************************************** + +void CDialogProperties::removeWidgets () +{ + std::list::iterator ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + /* + CWidget &widget = *ite; + // Create a label ? + if ( (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstString) || + (widget.Parameter.Type == CPrimitiveClass::CParameter::String) || + (widget.Parameter.Type == CPrimitiveClass::CParameter::StringArray) || + (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray)) + { + // Create the label + widget.Static.DestroyWindow (); + } + + // What kind of primitive ? + if (widget.Parameter.Type == CPrimitiveClass::CParameter::Boolean) + { + widget.CheckBox.DestroyWindow (); + + } + else if (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstString) + { + widget.ComboBox.DestroyWindow (); + } + else if (widget.Parameter.Type == CPrimitiveClass::CParameter::String) + { + widget.EditBox.DestroyWindow (); + if (widget.Parameter.FileExtension != "") + { + widget.CheckBox.DestroyWindow (); + } + } + else if (widget.Parameter.Type == CPrimitiveClass::CParameter::StringArray) + { + widget.MultiLineEditBox.DestroyWindow (); + if (widget.Parameter.Folder != "" || !widget.Parameter.FileExtension.empty()) + { + widget.CheckBox.DestroyWindow (); + } + } + else if (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) + { + widget.ListEditBox.DestroyWindow (); + } + + // File ? + if (widget.Parameter.Filename) + { + widget.CheckBox.DestroyWindow (); + } + */ + CWidget &widget = *ite; + CWnd *windows[] = { &widget.Static, &widget.ComboBox, &widget.CheckBox, &widget.EditBox, &widget.MultiLineEditBox, &widget.ListEditBox}; + int i; + for (i=0; iDestroyWindow (); + } + + ite++; + } + + Widgets.clear (); + +/* RECT rect; + GetWindowRect (&rect); + rect.bottom = rect.top + WindowHeight; + MoveWindow (&rect); + GetDlgItem (IDOK)->GetWindowRect (&rect); + ScreenToClient (&rect); + rect.top = WidgetPos.top; + rect.bottom = WidgetPos.bottom; + GetDlgItem (IDOK)->MoveWindow (&rect); + GetDlgItem (IDCANCEL)->GetWindowRect (&rect); + ScreenToClient (&rect); + rect.top = WidgetPos.top; + rect.bottom = WidgetPos.bottom; + GetDlgItem (IDCANCEL)->MoveWindow (&rect); + GetDlgItem (IDUPDATE)->GetWindowRect (&rect); + ScreenToClient (&rect); + rect.top = WidgetPos.top; + rect.bottom = WidgetPos.bottom; + GetDlgItem (IDUPDATE)->MoveWindow (&rect); +*/ + +} + +// *************************************************************************** + +void CDialogProperties::addWidget (const CPrimitiveClass::CParameter ¶meter, RECT &widgetPos, bool frozen) +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Get client rect + RECT clientRect; + m_PropertyCont.GetClientRect(&clientRect); +// GetClientRect (&clientRect); + RECT firstProp; + m_FirstProp.GetWindowRect(&firstProp); + + // Backup top + uint oldTop = widgetPos.top; + // backup right + uint oldRight = widgetPos.right; + + // Set the right limit +// widgetPos.right = clientRect.right - widgetPos.left; +// widgetPos.right = firstProp.right; + + // File ? + if (parameter.Filename + || (parameter.Type==CPrimitiveClass::CParameter::String && parameter.FileExtension != "") + || (parameter.Type==CPrimitiveClass::CParameter::StringArray && parameter.Folder != "") ) + widgetPos.right -= FILE_BUTTON_WIDTH; + + // Widget id + uint id = Widgets.size ()+FIRST_WIDGET; + + // Add a widget + Widgets.push_back (CWidget (this)); + CWidget &widget = Widgets.back (); + + // Copy the parameter + widget.Parameter = parameter; + + // Widget enabled ? + bool enabled = !parameter.ReadOnly && !frozen; + + // Create a label ? + if ( (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstString) || + (widget.Parameter.Type == CPrimitiveClass::CParameter::String) || + (widget.Parameter.Type == CPrimitiveClass::CParameter::StringArray) || + (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) ) + { + // Resize the widgetPos + widgetPos.bottom = widgetPos.top + LABEL_HEIGHT; + + if (widget.Parameter.Type == CPrimitiveClass::CParameter::StringArray && widget.Parameter.Folder != "") + { + RECT buttonRect = widgetPos; + buttonRect.left = buttonRect.right; + buttonRect.right = buttonRect.left + FILE_BUTTON_WIDTH; + + // Create an edit box + nlverify (widget.CheckBox.Create ("Select", BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), buttonRect, &m_PropertyCont, id)); + widget.CheckBox.SetFont (GetFont ()); + } + + // Create the label + widget.Static.Create ("", WS_VISIBLE, widgetPos, &m_PropertyCont); + widget.Static.SetFont (GetFont ()); + + // Next position + widgetPos.top = widgetPos.bottom; + } + + // What kind of primitive ? + if (widget.Parameter.Type == CPrimitiveClass::CParameter::Boolean) + { + // Resize the widgetPos + widgetPos.bottom = widgetPos.top + CHECKBOX_HEIGHT; + + string Name = widget.Parameter.Name; + + // Create a check box + nlverify (widget.CheckBox.Create (Name.c_str (), BS_3STATE|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), widgetPos, &m_PropertyCont, id)); + widget.CheckBox.SetFont (GetFont ()); + } + else if (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstString) + { + // Resize the widgetPos + RECT comboPos = widgetPos; + widgetPos.bottom = widgetPos.top + COMBO_HEIGHT; + comboPos.bottom = widgetPos.top + COMBO_REAL_HEIGHT; + + // Create a combo box + //nlverify (widget.ComboBox.Create (CBS_DISABLENOSCROLL|WS_VSCROLL|CBS_DROPDOWNLIST|(widget.Parameter.SortEntries?CBS_SORT:0)|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), comboPos, &m_PropertyCont, id)); + nlverify (widget.ComboBox.Create (CBS_DISABLENOSCROLL|WS_VSCROLL|(widget.Parameter.Editable?CBS_DROPDOWN:CBS_DROPDOWNLIST)|(widget.Parameter.SortEntries?CBS_SORT:0)|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), comboPos, &m_PropertyCont, id)); + widget.ComboBox.loaded = false; + widget.ComboBox.Widget = &widget; + widget.ComboBox.SetFont (GetFont ()); + + // Get the good list + widget.ComboBox.ResetContent (); + string ctx = doc->getContext (); + std::map::iterator ite = widget.Parameter.ComboValues.find (doc->getContext ().c_str()); + // we insert an empty string in case of a default value + if (!widget.Parameter.SortEntries) + { + widget.ComboBox.InsertString( -1, ""); + } + else + { + widget.ComboBox.AddString(""); + } + if (ite != widget.Parameter.ComboValues.end ()) + { + vector PathList; + { + ite->second.appendFilePath(PathList); + + vector relativePrimPaths; + { + vector startPrimPath; + for (uint locIndex=0;locIndex<_PropDlgLocators.size();locIndex++) + startPrimPath.push_back(_PropDlgLocators[locIndex].Primitive); + ite->second.getPrimitivesForPrimPath(relativePrimPaths, startPrimPath); + } + + ite->second.appendPrimPath(PathList, relativePrimPaths); + } + if (widget.Parameter.SortEntries) + std::sort(PathList.begin(), PathList.end()); + widget.ComboBox.setData(PathList); + } + + // Add default values + if (doc->getContext () != "default") + { + ite = widget.Parameter.ComboValues.find ("default"); + if (ite != widget.Parameter.ComboValues.end ()) + { + vector PathList; + { + ite->second.appendFilePath(PathList); + + vector relativePrimPaths; + { + vector startPrimPath; + for (uint locIndex=0;locIndex<_PropDlgLocators.size();locIndex++) + startPrimPath.push_back(_PropDlgLocators[locIndex].Primitive); + ite->second.getPrimitivesForPrimPath(relativePrimPaths, startPrimPath); + } + + ite->second.appendPrimPath(PathList, relativePrimPaths); + } + if (widget.Parameter.SortEntries) + std::sort(PathList.begin(), PathList.end()); + widget.ComboBox.setData(PathList); + } + } + } + else if (widget.Parameter.Type == CPrimitiveClass::CParameter::String) + { + // Resize the widgetPos + widgetPos.bottom = widgetPos.top + EDIT_HEIGHT; + + // Create an edit box + nlverify (widget.EditBox.CreateEx (WS_EX_CLIENTEDGE, _T("EDIT"), "", WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL|(enabled?0:ES_READONLY), widgetPos, &m_PropertyCont, id)); + widget.EditBox.SetFont (GetFont ()); + if (widget.Parameter.FileExtension != "") + { + RECT buttonRect = widgetPos; + buttonRect.left = buttonRect.right; + buttonRect.right = buttonRect.left + FILE_BUTTON_WIDTH; + + // Create an edit box + nlverify (widget.CheckBox.Create ("Open...", BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), buttonRect, &m_PropertyCont, id)); + widget.CheckBox.SetFont (GetFont ()); + } + } + else if (widget.Parameter.Type == CPrimitiveClass::CParameter::StringArray) + { + // Resize the widgetPos + widgetPos.bottom = widgetPos.top + widget.Parameter.WidgetHeight; + + // Create an edit box + if (widget.Parameter.DisplayHS) + { + nlverify (widget.MultiLineEditBox.CreateEx (WS_EX_CLIENTEDGE, _T("EDIT"), "", + WS_VSCROLL|WS_HSCROLL|ES_MULTILINE|ES_WANTRETURN|WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL|ES_AUTOVSCROLL|(enabled?0:ES_READONLY), widgetPos, &m_PropertyCont, id)); + } + else + { + nlverify (widget.MultiLineEditBox.CreateEx (WS_EX_CLIENTEDGE, _T("EDIT"), "", + WS_VSCROLL|ES_MULTILINE|ES_WANTRETURN|WS_CHILD|WS_VISIBLE|WS_TABSTOP|ES_AUTOHSCROLL|ES_AUTOVSCROLL|(enabled?0:ES_READONLY), widgetPos, &m_PropertyCont, id)); + } + + + // Resize the column + RECT listRect; + widget.MultiLineEditBox.GetClientRect (&listRect); + + CFont font; + font.CreateStockObject (ANSI_FIXED_FONT); + widget.MultiLineEditBox.SetFont (&font); + + // Create an "EDIT" button if the text is editable (FileExtension != "") + if (widget.Parameter.FileExtension != "") + { + widgetPos.top = widgetPos.bottom; + widgetPos.bottom += LABEL_HEIGHT; + RECT buttonRect = widgetPos; + + // Create an edit box + nlverify (widget.CheckBox.Create ("Edit...", BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), buttonRect, &m_PropertyCont, id)); + widget.CheckBox.SetFont (GetFont ()); + } + } + else if (widget.Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) + { + // Resize the widgetPos + widgetPos.bottom = widgetPos.top + widget.Parameter.WidgetHeight; + + // Create an edit box + nlverify (widget.ListEditBox.CreateEx (WS_EX_CLIENTEDGE, _T("LISTBOX"), "", WS_VSCROLL|WS_CHILD|WS_VISIBLE|WS_TABSTOP|LBS_NOTIFY|(enabled?0:WS_DISABLED), widgetPos, &m_PropertyCont, id)); + + // Resize the column + RECT listRect; + widget.ListEditBox.GetClientRect (&listRect); + + // Get the good list + widget.ListEditBox.StringSelectComboBox.ResetContent (); + std::map::iterator ite = widget.Parameter.ComboValues.find (doc->getContext ().c_str()); + // we insert an empty string in case of a default value + widget.ListEditBox.StringSelectComboBox.InsertString( -1, ""); + if (ite != widget.Parameter.ComboValues.end ()) + { + vector PathList; + { + ite->second.appendFilePath(PathList); + + vector relativePrimPaths; + { + vector startPrimPath; + for (uint locIndex=0;locIndex<_PropDlgLocators.size();locIndex++) + startPrimPath.push_back(_PropDlgLocators[locIndex].Primitive); + ite->second.getPrimitivesForPrimPath(relativePrimPaths, startPrimPath); + } + + ite->second.appendPrimPath(PathList, relativePrimPaths); + } + + for (vector::iterator it=PathList.begin(), itEnd=PathList.end(); it!=itEnd; ++it) + { + widget.ListEditBox.StringSelectComboBox.InsertString( -1, it->c_str ()); + } + } + + // Add default values + if (doc->getContext () != "default") + { + ite = widget.Parameter.ComboValues.find ("default"); + if (ite != widget.Parameter.ComboValues.end ()) + { + vector PathList; + { + ite->second.appendFilePath(PathList); + + vector relativePrimPaths; + { + vector startPrimPath; + for (uint locIndex=0;locIndex<_PropDlgLocators.size();locIndex++) + startPrimPath.push_back(_PropDlgLocators[locIndex].Primitive); + ite->second.getPrimitivesForPrimPath(relativePrimPaths, startPrimPath); + } + + ite->second.appendPrimPath(PathList, relativePrimPaths); + } + + for (vector::iterator it=PathList.begin(), itEnd=PathList.end(); it!=itEnd; ++it) + { + widget.ListEditBox.StringSelectComboBox.InsertString( -1, it->c_str ()); + } + } + } + + widget.ListEditBox.SetFont (GetFont ()); + widget.ListEditBox.StringSelectComboBox.SetFont (GetFont ()); + } + + // File ? + // if ((parameter.Filename) && (widget.Parameter.Type != CPrimitiveClass::CParameter::ConstStringArray)) + if (parameter.Filename && (parameter.FileExtension.empty() || widget.Parameter.Type != CPrimitiveClass::CParameter::StringArray)) + { + // Resize the widgetPos + RECT buttonRect = widgetPos; + buttonRect.left = buttonRect.right; + buttonRect.right = buttonRect.left + FILE_BUTTON_WIDTH; + + // Create an edit box + //nlverify (widget.CheckBox.Create ("Open...", BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP, buttonRect, this, id)); + nlverify (widget.CheckBox.Create ("View...", BS_PUSHBUTTON|WS_VISIBLE|WS_TABSTOP|(enabled?0:WS_DISABLED), buttonRect, &m_PropertyCont, id)); + widget.CheckBox.SetFont (GetFont ()); + } + + // Next position + widgetPos.top = widgetPos.bottom + SPACE_HEIGHT; + + // Move ok and cancel button +// uint heightGrow = widgetPos.top - oldTop; +/* RECT okRect; + GetDlgItem (IDOK)->GetWindowRect (&okRect); + ScreenToClient (&okRect); + okRect.top += heightGrow; + okRect.bottom += heightGrow; + GetDlgItem (IDOK)->MoveWindow (&okRect); + GetDlgItem (IDCANCEL)->GetWindowRect (&okRect); + ScreenToClient (&okRect); + okRect.top += heightGrow; + okRect.bottom += heightGrow; + GetDlgItem (IDCANCEL)->MoveWindow (&okRect); + GetDlgItem (IDUPDATE)->GetWindowRect (&okRect); + ScreenToClient (&okRect); + okRect.top += heightGrow; + okRect.bottom += heightGrow; + GetDlgItem (IDUPDATE)->MoveWindow (&okRect); + + // Resize the dialog box + RECT windowRect; + GetWindowRect (&windowRect); + + // Center only modal window + if (_Modal) + { + sint width = windowRect.right - windowRect.left; + sint height = windowRect.bottom - windowRect.top; + RECT desktop; + GetDesktopWindow ()->GetClientRect (&desktop); + windowRect.left = (desktop.right - desktop.left - width) / 2; + windowRect.right = windowRect.left + width; + windowRect.top = (desktop.bottom - desktop.top - height) / 2; + windowRect.top -= heightGrow/2; + windowRect.bottom = windowRect.top + height + heightGrow; + } + else + { + windowRect.bottom += heightGrow; + } +*/ + // resize the property container + RECT contRect; + m_PropertyCont.GetClientRect(&contRect); + contRect.bottom = widgetPos.top; + m_PropertyCont.CalcWindowRect(&contRect, 0); + m_PropertyCont.MoveWindow(&contRect, TRUE); + + // Not set + widget.Set = false; + + // restore righ + widgetPos.right = oldRight; +} + +// *************************************************************************** + +BOOL CDialogProperties::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Load accel table + nlverify (_AccelTable = LoadAccelerators (theApp.m_hInstance, MAKEINTRESOURCE(IDR_DIALOG))); + + // Get the OK Button position +// GetDlgItem (IDOK)->GetWindowRect (&WidgetPos); + RECT winRect; + GetWindowRect (&winRect); + WindowWidth = winRect.right - winRect.left; + WindowHeight = winRect.bottom - winRect.top; + + // Center only modal window + RECT desktop; + GetDesktopWindow ()->GetClientRect (&desktop); + GetWindowRect (&winRect); + uint width = winRect.right - winRect.left; + uint height = winRect.bottom - winRect.top; + winRect.top = (desktop.bottom - desktop.top - height) / 2; + winRect.left = (desktop.right - desktop.left - width) / 2; + winRect.right = winRect.left + width; + winRect.bottom = winRect.top + height; + MoveWindow (&winRect); + + RECT contRect; + m_PropertyFrame.GetClientRect(&contRect); + m_ContMinHeight = contRect.bottom; +// m_PropertyFrame.ClientToScreen(&contRect); + // leave 16 px for the scroll bar + contRect.right-=16; + m_PropertyCont.Create("", 0, contRect, &m_PropertyFrame); +// m_PropertyCont.SetCursor() + + m_PropertyCont.ShowWindow(SW_SHOW); + + // store the relative starting position for widget + m_FirstProp.GetWindowRect (&WidgetPos); + m_PropertyCont.ScreenToClient (&WidgetPos); + + // Store the relative button position + RECT buttonRect, dialogRect; + m_OKButton.GetWindowRect(&buttonRect); + ScreenToClient(&buttonRect); + GetClientRect(&dialogRect); + m_ButtonPos = dialogRect.bottom - buttonRect.top; + + // Store the property frame position + m_PropertyFrame.GetWindowRect(&PropertyFrameRect); + ScreenToClient(&PropertyFrameRect); + + // Store the relative frame position + GetWindowRect(&dialogRect); + ScreenToClient(&dialogRect); + m_FrameTopSpace = PropertyFrameRect.top - dialogRect.top; + m_FrameBottomSpace = dialogRect.bottom - PropertyFrameRect.bottom; + +// RECT desktop; + SystemParametersInfo(SPI_GETWORKAREA, 0, &desktop, 0); + m_MaxFrameHeight = desktop.bottom - desktop.top - m_FrameTopSpace - m_FrameBottomSpace; + + + // Rebuild the dialog + rebuildDialog (); + + // Show / hide cancel + GetDlgItem (IDCANCEL)->ShowWindow ( SW_SHOW );//_Cancel?SW_SHOW:SW_HIDE); + GetDlgItem (IDUPDATE)->ShowWindow ( SW_SHOW );//_Cancel?SW_SHOW:SW_HIDE); + + GetDlgItem(IDUPDATE)->GetWindowRect(&buttonRect); + ScreenToClient(&buttonRect); + m_buttonWidth = buttonRect.right; + GetDlgItem(IDOK)->GetWindowRect(&buttonRect); + ScreenToClient(&buttonRect); + m_buttonWidth -= buttonRect.left; + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +// *************************************************************************** +// CDialogProperties::CWidget +// *************************************************************************** + +bool CDialogProperties::CWidget::fromParameter (const IProperty *property, const IPrimitive &primitive, const CPrimitiveClass *primitiveClass, const CPrimitiveClass::CParameter ¶meter) +{ + // Good one ? + if (parameter == Parameter) + { + // Get pointers + const CPropertyString *propString = dynamic_cast (property); + const CPropertyStringArray *propStringString = dynamic_cast (property); + + // Default value ? + if ( (property == NULL) + || (!Set && property->Default)) + Default = true; + + // Check box ? + if (Parameter.Type == CPrimitiveClass::CParameter::StringArray) + { + if (propStringString) + { + // Get the value + vector currentValue; + getValue (currentValue); + + // Already sets ? + if (Set && (((currentValue != propStringString->StringArray) && (!Default || !propStringString->Default)) || (Default != propStringString->Default))) + { + // Not by default + Default = false; + + // Set as uninitialized + setEditTextMultiLine (MultiLineEditBox, DIFFERENT_VALUE_STRING); + updateMultiline (); + MultipleValues = true; + } + else + { + // Set as filled + Set = true; + + // Add the string + setEditTextMultiLine (MultiLineEditBox, propStringString->StringArray); + updateMultiline (); + } + } + else + { + // Add the strings + string temp; + vector result; + Parameter.getDefaultValue (result, primitive, *primitiveClass, &FromWhere); + + uint i; + for (i=0; i currentValue; + getValue (currentValue); + + // Already sets ? + if (Set && (((currentValue != propStringString->StringArray) && (!Default || !propStringString->Default)) || (Default != propStringString->Default))) + { + // Not by default + Default = false; + + // Set as uninitialized + vector tmp; + { + tmp=currentValue; + const vector &temp=propStringString->StringArray; + + // Check if we have all previous values. + for (uint tmpInd=0;tmpInd=temp.size()) // Not Found ? + tmp[tmpInd]=DIFFERENT_VALUE_MULTI_STRING+tmp[tmpInd]; // Set as different. + } + + for (uint tempInd=0;tempInd=tmp.size()) // Not Found ? + tmp.push_back(DIFFERENT_VALUE_MULTI_STRING+temp[tempInd]); // Set as different. + } + + } + + setEditTextMultiLine (ListEditBox, tmp); + updateList (); + MultipleValues = true; + } + else + { + // Set as filled + Set = true; + + // Add the string + setEditTextMultiLine (ListEditBox, propStringString->StringArray); + updateList (); + } + } + else + { + // Add the strings + vector result; + Parameter.getDefaultValue (result, primitive, *primitiveClass, &FromWhere); + + setEditTextMultiLine (ListEditBox, result); + updateList (); + + // Set as filled + Set= true; + } + } + else + { + // Already sets ? + if (propString) + { + // Get the value + string currentValue; + getValue (currentValue); + + // Multi value ? + if (Set && (((currentValue != propString->String) && (!Default || !propString->Default)) || (Default != propString->Default))) + { + // Not by default + Default = false; + + // Boolean ? + switch (Parameter.Type) + { + case CPrimitiveClass::CParameter::Boolean: + // Set as uninitialized + CheckBox.SetCheck (2); + updateBoolean (); + break; + case CPrimitiveClass::CParameter::ConstString: + // Set as uninitialized + if (!Parameter.SortEntries) + ComboBox.InsertString (-1, DIFFERENT_VALUE_STRING); + else + ComboBox.AddString( DIFFERENT_VALUE_STRING); + ComboBox.SelectString(-1 ,DIFFERENT_VALUE_STRING); + OriginalString = DIFFERENT_VALUE_STRING; + updateCombo (); + break; + case CPrimitiveClass::CParameter::String: + // Set as uninitialized + EditBox.SetWindowText (DIFFERENT_VALUE_STRING); + break; + } + MultipleValues = true; + } + else + { + // Set as filled + Set= true; + + // Boolean ? + switch (Parameter.Type) + { + case CPrimitiveClass::CParameter::Boolean: + // Check the box + CheckBox.SetCheck (Default?2:(propString->String == "true")?1:0); + updateBoolean (); + break; + case CPrimitiveClass::CParameter::ConstString: + if (Parameter.Editable || ComboBox.SelectString(-1 ,propString->String.c_str ()) == CB_ERR) + { + ComboBox.SetWindowText(propString->String.c_str ()); + ComboBox.InsertString( -1, propString->String.c_str()); + ComboBox.SelectString(-1 ,propString->String.c_str ()); + } + OriginalString = propString->String.c_str(); + updateCombo (); + break; + case CPrimitiveClass::CParameter::String: + { + bool backupDefault = Default; + Initializing = true; + setWindowTextUTF8 (EditBox, propString->String.c_str ()); + Default = backupDefault; + Initializing = false; + } + break; + } + } + } + else + { + if (primitiveClass) + { + // Boolean ? + std::string result; + Parameter.getDefaultValue (result, primitive, *primitiveClass, &FromWhere); + if (!result.empty()) + { + switch (Parameter.Type) + { + case CPrimitiveClass::CParameter::Boolean: + // Check the box + CheckBox.SetCheck (2); + updateBoolean (); + break; + case CPrimitiveClass::CParameter::ConstString: + ComboBox.SelectString(-1 ,result.c_str ()); + OriginalString = result.c_str(); + updateCombo (); + break; + case CPrimitiveClass::CParameter::String: + { + setWindowTextUTF8 (EditBox, result.c_str ()); + Default = true; + } + break; + } + } + } + + // Set as filled + Set= true; + } + } + + // Done + setStaticName(); + return true; + } + return false; +} + +// *************************************************************************** + +bool CDialogProperties::CWidget::toParameter (const CDatabaseLocatorPointer &locator, const CPrimitiveClass::CParameter ¶meter) +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Set the parameter + if (Parameter == parameter) + { + // Widget ok ? + if (Set && (!MultipleValues)) + { + // What type ? + if ( (parameter.Type == CPrimitiveClass::CParameter::StringArray) || (parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) + || (parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) ) + { + // Get the value + vector value; + /* todo hulud remove if (Default) + value.clear (); + else*/ + getValue (value); + + if (parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) + { + // Get Current Value. + const IProperty *prop; + vector newValues; + bool haveToUpdate=false; + + if (locator.Primitive->getPropertyByName (parameter.Name.c_str (), prop)) + { + // Dynamic cast + const CPropertyStringArray *const propStringArray = dynamic_cast (prop); + nlassert (propStringArray); + newValues=propStringArray->StringArray; + } + + // have to remove some string ? + // on parse las valeur de la primitive + for (int newValueInd=0;newValueInd<(int)newValues.size();newValueInd++) + { + uint valueInd; + // On check si elles existent dans la dialog + for (valueInd=0;valueInd=value.size()) // not found -> remove it + { + haveToUpdate=true; + newValues.erase(newValues.begin()+newValueInd); + newValueInd--; + } + + } + + // have to add some string ? + // on parse les valeurs de la dialog + std::vector::iterator insertIt=newValues.begin(); + for (uint valueInd=0;valueInd::iterator foundIt=find(newValues.begin(), newValues.end(), value[valueInd]); + if (foundIt==newValues.end()) + { + haveToUpdate=true; + if (insertIt==newValues.end()) + { + newValues.push_back(value[valueInd]); + insertIt=newValues.begin(); + } + else + { + insertIt=newValues.insert(insertIt+1, value[valueInd]); // .push_back(value[valueInd]); + } + + } + else + { + insertIt=foundIt; + } + + } + + } + if (haveToUpdate) + doc->addModification (new CActionSetPrimitivePropertyStringArray (locator, parameter.Name.c_str (), newValues, Default)); + } + + if (parameter.Type == CPrimitiveClass::CParameter::StringArray) + { + // Set the value + if ( value.empty() + || (value[0] != DIFFERENT_VALUE_STRING)) + { + doc->addModification (new CActionSetPrimitivePropertyStringArray (locator, parameter.Name.c_str (), value, Default)); + } + else + { + if (value.size()>1) // More than DIFFERENT_VALUE_STRING + { + // Get Current Value. + const IProperty *prop; + vector newValues; + + if (locator.Primitive->getPropertyByName (parameter.Name.c_str (), prop)) + { + // Dynamic cast + const CPropertyStringArray *const propStringArray = dynamic_cast (prop); + nlassert (propStringArray); + newValues=propStringArray->StringArray; + } + + for (size_t valIndex=1;valIndexaddModification (new CActionSetPrimitivePropertyStringArray (locator, parameter.Name.c_str (), newValues, Default)); + } + + } + + } + + } + else + { + // Get the value + string value; + /* todo hulud remove if (Default) + value = ""; + else*/ + getValue (value); + + // Set the value + if (value != DIFFERENT_VALUE_STRING) + doc->addModification (new CActionSetPrimitivePropertyString (locator, parameter.Name.c_str (), value.c_str (), Default)); + } + } + return true; + } + return false; +} + +// *************************************************************************** + +void CDialogProperties::CWidget::getValue (std::string &result) const +{ + nlassert (Parameter.Type != CPrimitiveClass::CParameter::StringArray); + + // Check box ? + if (Parameter.Type == CPrimitiveClass::CParameter::Boolean) + { + // Get the value + if (CheckBox.GetCheck() == 1) + result = "true"; + else if (CheckBox.GetCheck() == 0) + result = "false"; + else + result = ""; + } + else if (Parameter.Type == CPrimitiveClass::CParameter::ConstString) + { + // Get the text + CString str; + getWindowTextUTF8 (ComboBox, str); + result = (const char*)str; + } + else + { + nlassert (Parameter.Type == CPrimitiveClass::CParameter::String); + + // Get the text + CString str; + getWindowTextUTF8 (EditBox, str); + result = (const char*)str; + } +} + +// *************************************************************************** + +void CDialogProperties::CWidget::getValue (std::vector &result) const +{ + nlassert ( (Parameter.Type == CPrimitiveClass::CParameter::StringArray) || + (Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) ); + + // Get the string + result.clear (); + CString str; + if (Parameter.Type == CPrimitiveClass::CParameter::StringArray) + { + getWindowTextUTF8 (MultiLineEditBox, str); +// MultiLineEditBox.UnloadText(str); + const char *strP = str; + string dst; + while (*strP) + { + // New line ? + if (*strP == '\n') + { + result.push_back (dst); + dst = ""; + } + else if (*strP != '\r') + { + dst += *strP; + } + strP++; + } + if (!dst.empty()) + result.push_back (dst); + } + else + { + uint i; + const uint size = ListEditBox.GetCount(); + result.resize (size); + for (i=0; isetDefaultValue (this, value); + CheckBox.SetCheck(((!value.empty())&&(value=="true"))?1:0); + } + +/* todo hulud remove + if (oldValue != CheckBox.GetCheck()) + ApplyAutoname(widget);*/ + setStaticName(); +} + +// *************************************************************************** + +void CDialogProperties::CWidget::updateCombo () +{ + // No multiple value + MultipleValues = false; + Set = true; + + // Get the default value + if (Default) + { + string value; + DialogProperties->setDefaultValue (this, value); + if (value != "") + { + int index = ComboBox.FindString (-1, value.c_str()); + if (index != CB_ERR) + ComboBox.SetCurSel (index); + } + } + + /* todo hulud remove + if (curSel != ComboBox.GetCurSel()) + ApplyAutoname(widget);*/ + setStaticName(); +} + +// *************************************************************************** + +void CDialogProperties::CWidget::updateMultiline () +{ + // No multiple value + MultipleValues = false; + Set = true; + + // Default ? + if (Default) + { + vector vectString; + DialogProperties->setDefaultValue (this, vectString); + if (!vectString.empty()) + { + // Add the string + string temp; + uint i; + for (i=0; i vectString; + DialogProperties->setDefaultValue (this, vectString); + if (!vectString.empty()) + { + setEditTextMultiLine (ListEditBox, vectString); + } + } + setStaticName(); +} + +// *************************************************************************** + +bool CDialogProperties::isModified() +{ + list::iterator iteWid; + + for (iteWid=Widgets.begin();iteWid!=Widgets.end();iteWid++) + { + if ((*iteWid).Modified) + { + return true; + } + // special case for editable combo box + if ((*iteWid).Parameter.Type == CPrimitiveClass::CParameter::ConstString) + { + CString text; + getWindowTextUTF8 ((*iteWid).ComboBox, text); + if ((*iteWid).OriginalString.c_str() != text) + { + return true; + } + } + } + return false; +} + +// *************************************************************************** + + + +void CDialogProperties::CWidget::getFilename (string &result) +{ + if (Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) + { + int sel = ListEditBox.GetCurSel(); + if (sel != LB_ERR) + { + CString cstr; + ListEditBox.GetText (sel, cstr); + result = (const char*)cstr; + } + else + result = ""; + } + else + { + getValue (result); + } +} + +// *************************************************************************** + +// return true if the given hwnd is one of this widget +bool CDialogProperties::CWidget::isHwndMatch(HWND hWnd) +{ + if (IsWindow (Static.m_hWnd) && Static.m_hWnd == hWnd) + return true; + if (IsWindow (ComboBox.m_hWnd) && ComboBox.m_hWnd == hWnd) + return true; + if (IsWindow (CheckBox.m_hWnd) && CheckBox.m_hWnd == hWnd) + return true; + if (IsWindow (EditBox.m_hWnd) && EditBox.m_hWnd == hWnd) + return true; + if (IsWindow (MultiLineEditBox.m_hWnd) && MultiLineEditBox.m_hWnd == hWnd) + return true; + if (IsWindow (ListEditBox.m_hWnd) && ListEditBox.m_hWnd == hWnd) + return true; + + return false; +} + +// *************************************************************************** + +// get the next window +HWND CDialogProperties::CWidget::getNextWindow(HWND hWnd) +{ + if (hWnd == 0) + { + if (IsWindow (ComboBox.m_hWnd)) + return ComboBox.m_hWnd; + if (IsWindow (EditBox.m_hWnd)) + return EditBox.m_hWnd; + if (IsWindow (MultiLineEditBox.m_hWnd)) + return MultiLineEditBox.m_hWnd; + if (IsWindow (ListEditBox.m_hWnd)) + return ListEditBox.m_hWnd; + if (IsWindow (CheckBox.m_hWnd)) + return CheckBox.m_hWnd; + } + else + { + if (IsWindow (ComboBox.m_hWnd) && ComboBox.m_hWnd == hWnd && IsWindow (CheckBox.m_hWnd)) + return CheckBox.m_hWnd; + if (IsWindow (EditBox.m_hWnd) && EditBox.m_hWnd == hWnd && IsWindow (CheckBox.m_hWnd)) + return CheckBox.m_hWnd; + if (IsWindow (MultiLineEditBox.m_hWnd) && MultiLineEditBox.m_hWnd == hWnd && IsWindow (CheckBox.m_hWnd)) + return CheckBox.m_hWnd; + if (IsWindow (ListEditBox.m_hWnd) && ListEditBox.m_hWnd == hWnd && IsWindow (CheckBox.m_hWnd)) + return CheckBox.m_hWnd; + } + + return 0; +} + +// *************************************************************************** + +// get the previous window +HWND CDialogProperties::CWidget::getPreviousWindow(HWND hWnd) +{ + if (hWnd == 0) + { + if (IsWindow (CheckBox.m_hWnd)) + return CheckBox.m_hWnd; + if (IsWindow (ListEditBox.m_hWnd)) + return ListEditBox.m_hWnd; + if (IsWindow (MultiLineEditBox.m_hWnd)) + return MultiLineEditBox.m_hWnd; + if (IsWindow (EditBox.m_hWnd)) + return EditBox.m_hWnd; + if (IsWindow (ComboBox.m_hWnd)) + return ComboBox.m_hWnd; + } + else + { + if (IsWindow (CheckBox.m_hWnd) && CheckBox.m_hWnd == hWnd) + { + if (IsWindow (ComboBox.m_hWnd)) + return ComboBox.m_hWnd; + if (IsWindow (EditBox.m_hWnd)) + return EditBox.m_hWnd; + if (IsWindow (MultiLineEditBox.m_hWnd)) + return MultiLineEditBox.m_hWnd; + if (IsWindow (ListEditBox.m_hWnd)) + return ListEditBox.m_hWnd; + } + } + + return 0; +} + + +// *************************************************************************** + +bool CDialogProperties::CWidget::OnSize( int cx, int cy, int decY ) +{ + RECT rect; + bool sizeY = false; + + if ( Static.m_hWnd ) + { + Static.GetWindowRect( &rect ); + DialogProperties->m_PropertyFrame.ScreenToClient( &rect ); + rect.top += decY; + rect.bottom += decY; + Static.MoveWindow( &rect ); + } + + if ( ComboBox.m_hWnd && IsWindow( ComboBox.m_hWnd ) ) + { + ComboBox.GetWindowRect( &rect ); + DialogProperties->m_PropertyFrame.ScreenToClient( &rect ); + rect.top += decY; + rect.bottom += decY; + rect.right += cx; + ComboBox.MoveWindow( &rect ); + } + + if ( EditBox.m_hWnd && IsWindow( EditBox.m_hWnd ) ) + { + EditBox.GetWindowRect( &rect ); + DialogProperties->m_PropertyFrame.ScreenToClient( &rect ); + rect.top += decY; + rect.bottom += decY; + rect.right += cx; + EditBox.MoveWindow( &rect ); + } + + if ( MultiLineEditBox.m_hWnd && IsWindow( MultiLineEditBox.m_hWnd ) ) + { + MultiLineEditBox.GetWindowRect( &rect ); + DialogProperties->m_PropertyFrame.ScreenToClient( &rect ); + rect.right += cx; + rect.top += decY; + rect.bottom += decY; + if ( rect.bottom + cy >= rect.top + 100 ) + { + ::CRect dlgRect; + DialogProperties->GetWindowRect( &dlgRect ); + + if ( ( cy <= 0 ) || ( dlgRect.Height() > DialogProperties->getOriginalHeight() ) ) + { + rect.bottom += cy; + sizeY = true; + decY += cy; + } + } + MultiLineEditBox.MoveWindow( &rect ); + } + + if ( ListEditBox.m_hWnd && IsWindow( ListEditBox.m_hWnd ) ) + { + ListEditBox.GetWindowRect( &rect ); + DialogProperties->m_PropertyFrame.ScreenToClient( &rect ); + rect.right += cx; + rect.top += decY; + rect.bottom += decY; + ListEditBox.MoveWindow( &rect ); + } + + if ( CheckBox.m_hWnd ) + { + CheckBox.GetWindowRect( &rect ); + DialogProperties->m_PropertyFrame.ScreenToClient( &rect ); + if ( rect.left > 30 ) + { + rect.left += cx; + rect.right += cx; + } + + CString text; + CheckBox.GetWindowText( text ); + if ( text == "Edit..." ) + { + rect.right += cx; + } + + rect.top += decY; + rect.bottom += decY; + CheckBox.MoveWindow( &rect ); + } + + return sizeY; +} + +// *************************************************************************** + +// *************************************************************************** + +BOOL CDialogProperties::OnCommand(WPARAM wParam, LPARAM lParam) +{ + WORD wNotifyCode = HIWORD(wParam); // notification code + + switch (wNotifyCode) + { + case BN_CLICKED: + { + // Button id + int idButton = (int) LOWORD(wParam); // identifier of button + if (idButton >= FIRST_WIDGET) + { + // Get the widget + CWidget *widget = getWidget (idButton-FIRST_WIDGET); + + // Check box ? + if (widget->Parameter.Type == CPrimitiveClass::CParameter::Boolean) + { + if (widget->Default) + widget->CheckBox.SetCheck(0); + else + widget->CheckBox.SetCheck((widget->CheckBox.GetCheck()+1)%3); + + // If 2 set as default + widget->Default = widget->CheckBox.GetCheck() == 2; + + widget->updateBoolean (); + widget->Modified = true; + } + else if (widget->Parameter.Type == CPrimitiveClass::CParameter::String) + { + // we open a file selector + nlassert (widget->Parameter.FileExtension != ""); + + // Create a dialog file, starting at the specified Folder + /* todo hulud remove + CString oldValue; + widget->EditBox.GetWindowText (oldValue);*/ + CFileDialogEx dialog (BASE_REGISTRY_KEY, "default", TRUE, widget->Parameter.FileExtension.c_str (), NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, + (widget->Parameter.FileExtension+" (*."+widget->Parameter.FileExtension+")|*."+widget->Parameter.FileExtension+"|All Files (*.*)|*.*||").c_str (), getMainFrame ()); + if (widget->Parameter.Folder != "") + { + dialog.m_ofn.lpstrInitialDir = widget->Parameter.Folder.c_str(); + } + if (dialog.DoModal() == IDOK) + { + CString str; + str = dialog.GetFileTitle(); + setWindowTextUTF8 (widget->EditBox, str); + + /* todo hulud remove + if ((const char*)oldValue != str) + ApplyAutoname(widget);*/ + widget->setStaticName(); + widget->Modified = true; + } + } + else if (widget->Parameter.Type == CPrimitiveClass::CParameter::StringArray) + { + if (widget->Parameter.FileExtension.empty()) + { + nlassert (widget->Parameter.Folder != ""); + SelectFolder(widget); + } + else + { + // Edit with an external editor + std::vector result; + widget->getValue (result); + uint i; + string text = ""; + for (i=0; igetConfigFile().getVarPtr ("TextEditor"); + char windows[512]; + GetWindowsDirectory (windows, sizeof (windows)); + if (EditExternalText (var?var->asString():windows+string ("/notepad.exe"), text, widget->Parameter.FileExtension.c_str ())) + { + widget->Default = false; + widget->Modified = true; + widget->updateMultiline(); + setEditTextMultiLine (widget->MultiLineEditBox, text.c_str()); + } + } + } + else + { + // Should be a filename + nlassert (widget->Parameter.Filename); + + // No multiple values ? + if (!widget->MultipleValues) + { + // Get the string + string filename; + widget->getFilename (filename); + + // Not empty ? + if (!filename.empty ()) + { + // Open the file + if (!widget->Parameter.FileExtension.empty ()) + filename += "."+widget->Parameter.FileExtension; + + // Lookup + if (widget->Parameter.Lookup) + filename = CPath::lookup (filename, false, false, false); + if (!filename.empty ()) + { + // Open the file + if (!openFile (filename.c_str ())) + // Error + theApp.errorMessage ("Can't open the file %s", filename.c_str ()); + } + else + { + // Error + widget->getFilename (filename); + theApp.errorMessage ("Can't find the file %s", filename.c_str ()); + } + } + } + } + } + } + break; + case CBN_SELCHANGE: + { + int idComboBox = (int) LOWORD(wParam); // identifier of combo box + nlassert ((idComboBox >= FIRST_WIDGET) || (idComboBox==STRING_SELECT_COMBOBOX_ID)); + + CWidget *widget = getWidget (idComboBox-FIRST_WIDGET); + if (widget->Parameter.Type == CPrimitiveClass::CParameter::ConstString) + { + // Get the widget + int curSel = widget->ComboBox.GetCurSel(); + + // Check box ? + nlassert (widget->Parameter.Type == CPrimitiveClass::CParameter::ConstString); + + // Remove + int index = widget->ComboBox.FindString (-1, DIFFERENT_VALUE_STRING); + if (index != CB_ERR) + widget->ComboBox.DeleteString(index); + + // Default value ? + widget->Default = (widget->ComboBox.GetCurSel () == 0); + widget->updateCombo (); + widget->Modified = true; + } + } + break; + case EN_CHANGE: + { + int idEditCtrl = (int) LOWORD(wParam); // identifier of edit control + if ((idEditCtrl >= FIRST_WIDGET) && (idEditCtrl <= LAST_WIDGET)) + { + // Get the widget + CWidget *widget = getWidget (idEditCtrl-FIRST_WIDGET); + + // Check box ? + if (widget->Parameter.Type == CPrimitiveClass::CParameter::String) + { + // No multiple value + widget->MultipleValues = false; + if (!widget->Initializing) + widget->Modified = true; + widget->Set = true; + + /* todo hulud remove + CString oldValue; + widget->EditBox.GetWindowText (oldValue);*/ + + // String NULL ? + CString text; + getWindowTextUTF8 (widget->EditBox, text); + widget->Default = (text == ""); + + // Default ? + if (widget->Default) + { + string value; + setDefaultValue (widget, value); + if (!value.empty()) + { + setWindowTextUTF8 (widget->EditBox, value.c_str()); + widget->Default = true; + } + } + else if ( text == DIFFERENT_VALUE_STRING ) + widget->Modified = false; + + /* todo hulud remove + CString newValue; + widget->EditBox.GetWindowText (newValue); + if (newValue != oldValue) + ApplyAutoname(widget);*/ + + // No more multiple value + widget->setStaticName(); + } + else if (widget->Parameter.Type == CPrimitiveClass::CParameter::StringArray) + { + nlassert (widget->Parameter.Type == CPrimitiveClass::CParameter::StringArray); + + // String NULL ? + std::vector result; + widget->getValue (result); + widget->Default = result.empty(); + widget->updateMultiline (); + widget->Modified = true; + } + /*else + { + nlassert (widget->Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray); + + // String NULL ? + std::vector result; + widget->getValue (result); + widget->Default = result.empty(); + widget->updateList (); + }*/ + } + } + break; + } + + return CDialog::OnCommand(wParam, lParam); +} + +// *************************************************************************** + +CDialogProperties::CWidget *CDialogProperties::getWidget (uint widgetId) +{ + std::list::iterator ite = Widgets.begin (); + while (widgetId > 0) + { + widgetId--; + ite++; + } + return &(*ite); +} + +// *************************************************************************** + +void CDialogProperties::changeSelection (std::list &locators) +{ + // Print a message if changes will be lost + if (isModified() && !getMainFrame()->yesNoMessage("All changes will be lost ! Are you sure ?")) + return; + + _PropDlgLocators.clear (); + CWorldEditorDoc *doc = getDocument (); + std::list::iterator ite = locators.begin (); + while (ite != locators.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + _PropDlgLocators.push_back (locator); + ite++; + } + + // Shown ? + if (IsWindowVisible ()) + { + rebuildDialog (); + } +} + +// *************************************************************************** +bool CDialogProperties::containsSelection( std::list &locators ) +{ + std::list::iterator ite = locators.begin (); + while (ite != locators.end ()) + { + std::vector::iterator itDB = _PropDlgLocators.begin(); + + bool ok = false; + while ( !ok && ( itDB != _PropDlgLocators.end() ) ) + { + ok = ( (*itDB).Primitive == (*ite) ); + itDB++; + } + + if ( !ok ) + return false; + + ite++; + } + + return true; +} + +// *************************************************************************** +bool CDialogProperties::containsSelection( std::vector &locators ) +{ + std::vector::iterator ite = locators.begin (); + while (ite != locators.end ()) + { + std::vector::iterator itDB = _PropDlgLocators.begin(); + + bool ok = false; + while ( !ok && ( itDB != _PropDlgLocators.end() ) ) + { + ok = ( (*itDB) == (*ite) ); + itDB++; + } + + if ( !ok ) + return false; + + ite++; + } + + return true; +} + +// *************************************************************************** + +bool CDialogProperties::equalsSelection( std::list &locators ) +{ + if ( locators.size() != _PropDlgLocators.size() ) + return false; + + return containsSelection( locators ); +} + +// *************************************************************************** + +void CDialogProperties::rebuildDialog () +{ + // Remove widgets + removeWidgets (); + + // Something selected ? + const uint selSize = _PropDlgLocators.size (); + + // The parameter list + set parameterList; + + // Does at least one of the selected primitive is a static child ? + bool staticChildSelected = false; + + // For each selected primitive + uint i; + for (i=0; i(_PropDlgLocators[i].Primitive)->getParent()==NULL) + { + + /*const CPrimitiveClass::CParameter *tac=&primClass->Parameters[0]; + string sou=tac->DefaultValue[0].Name; + sou="test";*/ + const_cast(_PropDlgLocators[i].Primitive)->removePropertyByName("name"); + const_cast(_PropDlgLocators[i].Primitive)->removePropertyByName("path"); + //TODO faire une fonction dans CWorldDoc pour recup m_strPathName + string name; + getDocument()->getPrimitiveDisplayName(name,_PropDlgLocators[i].getDatabaseIndex()); + string path; + getDocument()->getFilePath(_PropDlgLocators[i].getDatabaseIndex(),path); + + const_cast(_PropDlgLocators[i].Primitive)->addPropertyByName("name",new CPropertyString (name)); + const_cast(_PropDlgLocators[i].Primitive)->addPropertyByName("path",new CPropertyString (path)); + } + + const IPrimitive * primitive= _PropDlgLocators[i].Primitive; + + if (primitive) + { + staticChildSelected |= theApp.Config.isStaticChild (*primitive); + + // Get the class name + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*primitive); + + // Use the class or not ? + if (primClass) + { + // For each properties of the class + for (uint p=0; pParameters.size (); p++) + { + // Is the parameter visible ? + if (primClass->Parameters[p].Visible) + { + parameterList.insert (primClass->Parameters[p]); + } + } + } + else + { + // For each primitive property + uint numProp = primitive->getNumProperty (); + for (uint p=0; pgetProperty (p, propertyName, prop)); + + // Add a default property + CPrimitiveClass::CParameter defProp (*prop, propertyName.c_str ()); + parameterList.insert (defProp); + } + } + } + } + + // Remove property Name, Hidden and Selected + set::iterator ite = parameterList.begin (); + while (ite != parameterList.end ()) + { + // Next iterator + set::iterator next = ite; + next++; + + // Property name ? + if (/*(ite->Name == "name") || *//*(ite->Name == "hidden")*/ /*|| (ite->Name == "selected") ||*/ (ite->Name == "class")) + { + // Remove it + parameterList.erase (ite); + } + + ite = next; + } + + // Add the default parameter + CPrimitiveClass::CParameter defaultParameter; + defaultParameter.Visible = true; + defaultParameter.Filename = false; + + // The name + RECT widgetPos = WidgetPos; + + + // Add the other widgets + //for (i=0;i<3;++i) //JC: a small debug trick to artifically simulate a huge DialogBox + { + // Add first the name + ite = parameterList.begin (); + while (ite != parameterList.end ()) + { + if (ite->Name == "name") + { + addWidget (*ite, widgetPos, staticChildSelected); + break; + } + ite++; + } + + // Then add the other one + ite = parameterList.begin (); + while (ite != parameterList.end ()) + { + if (ite->Name != "name") + addWidget (*ite, widgetPos, false); + + ite++; + } + } + + std::string windowName; + + // For each selected primitive + for (i=0; iName; + else if (primClass->Name != windowName) + windowName = ""; + + // Get the property for name + /*const IProperty *propName; + if (primitive->getPropertyByName ("name", propName)) + { + // Create a default property + CPrimitiveClass::CParameter defProp (*propName, "name"); + + // Add the property in the good widget + std::list::iterator ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + // Set the parameter + if (ite->fromParameter (propName, *primitive, primClass, defProp)) + break; + + ite++; + } + }*/ + + // For each properties of the class + for (uint p=0; pParameters.size (); p++) + { + // Is the parameter visible ? + if (primClass->Parameters[p].Visible) + { + // Get the property + const IProperty *prop; + if (primitive->getPropertyByName (primClass->Parameters[p].Name.c_str(), prop)) + { + // Add the property in the good widget + std::list::iterator ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + // Set the parameter + if (ite->fromParameter (prop, *primitive, primClass, primClass->Parameters[p])) + break; + + ite++; + } + } + else + { + // Add the property in the good widget + std::list::iterator ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + // Set the parameter + if (ite->fromParameter (NULL, *primitive, primClass, primClass->Parameters[p])) + break; + + ite++; + } + } + } + } + } + else + { + // For each primitive property + uint numProp = primitive->getNumProperty (); + for (uint p=0; pgetProperty (p, propertyName, prop)); + + // Create a default property + CPrimitiveClass::CParameter defProp (*prop, propertyName.c_str ()); + + // Add the property in the good widget + std::list::iterator ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + // Set the parameter + if (ite->fromParameter (prop, *primitive, NULL, defProp)) + break; + + ite++; + } + } + } + } + } + + // resize the dialog and sub control to the max or min extend possible + { + // force the cont to it's minimum size before other resizing code + { + RECT contRect; + m_PropertyCont.GetWindowRect(&contRect); + m_PropertyFrame.ScreenToClient(&contRect); + contRect.bottom = max(int(contRect.bottom), m_ContMinHeight); + contRect.right = contRect.left + 425; + m_PropertyCont.MoveWindow(&contRect); + } + // first size to ideal size + RECT desktop; + SystemParametersInfo(SPI_GETWORKAREA, 0, &desktop, 0); + + // resize frame cont + ::CRect contRect; + m_PropertyCont.GetWindowRect(&contRect); + m_PropertyFrame.ScreenToClient(&contRect); + contRect.bottom += -contRect.top; + contRect.bottom = min(int(contRect.bottom), m_MaxFrameHeight); + contRect.top = 0; + AdjustWindowRectEx(&contRect, + m_PropertyFrame.GetStyle(), + false, + m_PropertyFrame.GetExStyle()); +// m_PropertyFrame.CalcWindowRect(&contRect); + int height = contRect.Height(); + m_PropertyFrame.MoveWindow(PropertyFrameRect.top, + PropertyFrameRect.left, + 445,//PropertyFrameRect.right-PropertyFrameRect.left, + height); + m_PropertyFrame.GetClientRect(&contRect); + + // resize dialog + RECT dialogRect; + GetWindowRect(&dialogRect); + ScreenToClient(&dialogRect); + m_PropertyFrame.GetWindowRect(&contRect); + ScreenToClient(&contRect); + dialogRect.bottom = contRect.bottom + m_FrameBottomSpace; + ClientToScreen(&dialogRect); + dialogRect.right = dialogRect.left + 455; + m_curDlgRect = dialogRect; + m_originalHeight = m_curDlgRect.Height(); + MoveWindow(&dialogRect); + + // replace the dialog in available window place + GetWindowRect(&dialogRect); + if (dialogRect.top < desktop.top) + { + dialogRect.bottom = desktop.top + (dialogRect.bottom - dialogRect.top); + dialogRect.top = desktop.top; + } + if (dialogRect.bottom > desktop.bottom) + { + dialogRect.top = desktop.bottom - (dialogRect.bottom - dialogRect.top); + dialogRect.bottom = desktop.bottom; + } + + + MoveWindow(&dialogRect); + m_DialogWidth = dialogRect.right - dialogRect.left; + +/* // now, size to physical available size and minimum size + int height = dialogRect.bottom - dialogRect.top; + int deskHeight = desktop.bottom - desktop.top; + height = min(height, deskHeight); + height = max(height, int(PropertyFrameRect.bottom-PropertyFrameRect.top)); + + dialogRect.bottom = dialogRect.top + height; + + if (dialogRect.bottom > desktop.bottom) + { + dialogRect.top -= dialogRect.bottom-desktop.bottom; + dialogRect.bottom = desktop.bottom; + } + + MoveWindow(&dialogRect); + ScreenToClient(&dialogRect); + + // resize frame to desktop size + m_PropertyFrame.GetWindowRect(&contRect); + ScreenToClient(&contRect); + contRect.bottom = dialogRect.bottom-m_FramePos; + m_PropertyFrame.MoveWindow(&contRect); + // resize container window + m_PropertyCont.GetWindowRect(&contRect); + m_PropertyFrame.ScreenToClient(&contRect); + + + + if (contRect.bottom-contRect.top < m_ContMinHeight) + contRect.bottom = contRect.top + m_ContMinHeight; + + m_PropertyCont.MoveWindow(&contRect); +*/ + } + + // replace the 3 button + RECT dialogRect; + GetClientRect(&dialogRect); + RECT buttonRect; + // OK + GetDlgItem(IDOK)->GetWindowRect(&buttonRect); + ScreenToClient(&buttonRect); + buttonRect.bottom = (dialogRect.bottom - m_ButtonPos) + (buttonRect.bottom-buttonRect.top); + buttonRect.top = dialogRect.bottom - m_ButtonPos; + GetDlgItem(IDOK)->MoveWindow(&buttonRect); + // cancel + GetDlgItem(IDCANCEL)->GetWindowRect(&buttonRect); + ScreenToClient(&buttonRect); + buttonRect.bottom = (dialogRect.bottom - m_ButtonPos) + (buttonRect.bottom-buttonRect.top); + buttonRect.top = dialogRect.bottom - m_ButtonPos; + GetDlgItem(IDCANCEL)->MoveWindow(&buttonRect); + //IDUPDATE + GetDlgItem(IDUPDATE)->GetWindowRect(&buttonRect); + ScreenToClient(&buttonRect); + buttonRect.bottom = (dialogRect.bottom - m_ButtonPos) + (buttonRect.bottom-buttonRect.top); + buttonRect.top = dialogRect.bottom - m_ButtonPos; + GetDlgItem(IDUPDATE)->MoveWindow(&buttonRect); + + RECT contRect; + m_PropertyCont.GetWindowRect(&contRect); + RECT frameRect; + m_PropertyFrame.GetClientRect(&frameRect); + // Set the scroll bar value + SCROLLINFO si; + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_PAGE | SIF_RANGE/*SIF_ALL*/|SIF_DISABLENOSCROLL; // SIF_ALL = SIF_PAGE | SIF_RANGE | SIF_POS; + si.nMin = 0; + si.nMax = contRect.bottom - contRect.top; + si.nPage = frameRect.bottom; + int pos = std::min(LONG(m_ScrollBar.GetScrollPos()), std::max(LONG(0), LONG(si.nMax - si.nPage))); + m_ScrollBar.SetScrollInfo(&si, FALSE); + // foul MFC by sending a pseudo message + OnVScroll(SB_THUMBPOSITION, pos, &m_ScrollBar); + + // replace the scroll bar control + RECT scrollRect; + m_PropertyFrame.GetClientRect(&scrollRect); + m_PropertyFrame.ClientToScreen(&scrollRect); + scrollRect.left = scrollRect.right-16; + ScreenToClient(&scrollRect); + m_ScrollBar.MoveWindow(&scrollRect, TRUE); + + // set the name of the dlg according to displayed class + SetWindowText( ( std::string( "Properties for : " ) + windowName ).c_str() ); + +// // JC: added scrolling properties +// ::CRect clientRect; +// GetClientRect (clientRect); +// GetWindowRect (m_rect); +// +// m_nScrollPos = 0; +// +// HWND hWndEntireScreen = ::GetDesktopWindow(); +// BOOL bSuccess = ::GetWindowRect(hWndEntireScreen,&rectEntireScreen); +// _ScrollBar = false; +// if (bSuccess != FALSE) +// { +// RECT desktop; +// GetDesktopWindow()->GetClientRect(&desktop); +//// GetDesktopWindow()->ClientToScreen(&desktop); +// +// int nHeightOfMyDlg = m_rect.Height(); +// int nMaxDesiredHeight = desktop.bottom; +// if (nHeightOfMyDlg >= nMaxDesiredHeight) +// { +// // resize to 90% of the entire screen, and vertically center it on the screen +// MoveWindow(m_rect.left,(int)(0.05*rectEntireScreen.Height()), m_rect.Width(),nMaxDesiredHeight); +// } +// +// GetWindowRect (m_rect2); +// +// int nScrollMax = clientRect.Height(); +// GetClientRect (clientRect); +// int nScrollPage = clientRect.Height()+1; // clientRect.Height(); +// +// SCROLLINFO si; +// si.cbSize = sizeof(SCROLLINFO); +// si.fMask = SIF_ALL|SIF_DISABLENOSCROLL; // SIF_ALL = SIF_PAGE | SIF_RANGE | SIF_POS; +// si.nMin = 0; +// si.nMax = nScrollMax; +// si.nPage = nScrollPage; // si.nMax/SCROLLING_STEPS; +// si.nPos = 0; +// m_ScrollBar.SetScrollInfo(/*(SB_VERT/*|SB_CTL*/ &si, TRUE); +// _ScrollBar = true; +// } + + ApplyAutoname(); + + for (i=0; i(_PropDlgLocators[i].Primitive)->getParent()==NULL) + { + const_cast(_PropDlgLocators[i].Primitive)->removePropertyByName("name"); + const_cast(_PropDlgLocators[i].Primitive)->removePropertyByName("path"); + const_cast(_PropDlgLocators[i].Primitive)->addPropertyByName("name",new CPropertyString ("")); + } + } + + // focus the first control + if (!Widgets.empty()) + { + HWND toFocus = Widgets.begin()->getNextWindow(0); + //(*Widgets.begin()).setFocus(); + ::SetFocus(toFocus); + ::RedrawWindow(toFocus, NULL, NULL, RDW_INVALIDATE|RDW_INTERNALPAINT); + // It's "name", so select content + Widgets.begin()->EditBox.SetSel(0, -1, true); +// if (focusName.empty()) +// { +// toFocus = Widgets.begin()->getNextWindow(0); +// } +// else +// { +// // try to find a widget with the same parameter name as previous +// list::iterator first(Widgets.begin()), last(Widgets.end()); +// for (; first != last; ++first) +// { +// if (first->Parameter.Name == focusName) +// { +// toFocus = first->getNextWindow(0); +// break; +// } +// } +// // no match, focus the first +// if (first == last) +// { +// toFocus = Widgets.begin()->getNextWindow(0); +// } +// } + +// // keep the focused control in slider visibility +// { +// int move = 0; +// +// RECT focusPos; +// ::GetWindowRect(toFocus, &focusPos); +// +// m_PropertyFrame.ScreenToClient(&focusPos); +// RECT framePos; +// m_PropertyFrame.GetClientRect(&framePos); +// if (focusPos.top < framePos.top) +// move = focusPos.top - framePos.top; +// else if (focusPos.bottom > framePos.bottom) +// move = focusPos.bottom - framePos.bottom; +// +// if (move != 0) +// { +// move = m_ScrollBar.GetScrollPos()+move; +// // full MFC by sending a pseudo message +// OnVScroll(SB_THUMBPOSITION, move, &m_ScrollBar); +// } +// +// } + + } + + SetActiveWindow(); + // trigger a global redraw of the dialog + Invalidate(); +} + +// *************************************************************************** + +void CDialogProperties::OnShowWindow(BOOL bShow, UINT nStatus) +{ + if (bShow) + rebuildDialog (); + + CDialog::OnShowWindow(bShow, nStatus); +} + +// *************************************************************************** + +void CDialogProperties::OnUpdate() +{ + // we update the current dialog + updateModification (); + updateModification (); + + // then, we look for other dialogs to be updated + std::list::iterator it = PropertiesDialogs.begin(); + + while ( it != PropertiesDialogs.end() ) + { + if ( (*it)->containsSelection( _PropDlgLocators ) || + containsSelection( (*it)->_PropDlgLocators ) ) + (*it)->rebuildDialog(); + it++; + } +} + +// *************************************************************************** + +void CDialogProperties::updateModification () +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Something selected ? + const uint selSize = _PropDlgLocators.size (); + + // Auto name + ApplyAutoname (); + + // Modification + bool inModificationMode = doc->inModificationMode(); + if (/*!_Modal &&*/ !inModificationMode) + doc->beginModification (); + + // For each selected primitive + for (uint i=0; igetPropertyByName ("name", propName)) + { + // Create a default property + CPrimitiveClass::CParameter defProp (*propName, "name"); + + // Add the property in the good widget + std::list::iterator ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + // Set the parameter + if (ite->toParameter (_PropDlgLocators[i], defProp)) + break; + (*ite).Modified=false; + + ite++; + } + } + + // For each properties of the class + for (uint p=0; pParameters.size (); p++) + { + // Is the parameter visible ? + if (primClass->Parameters[p].Visible) + { + // Add the property in the good widget + std::list::iterator ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + (*ite).Modified=false; + if (ite->toParameter (_PropDlgLocators[i], primClass->Parameters[p])) + break; + + + ite++; + } + } + } + } + else + { + // For each primitive property + uint numProp = primitive->getNumProperty (); + for (uint p=0; pgetProperty (p, propertyName, prop)); + + // Create a default property + CPrimitiveClass::CParameter defProp (*prop, propertyName.c_str ()); + + // Add the property in the good widget + std::list::iterator ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + (*ite).Modified=false; + if (ite->toParameter (_PropDlgLocators[i], defProp)) + break; + + ite++; + } + } + } + } + } + + // Modification + if (/*!_Modal &&*/ !inModificationMode) + doc->endModification (); + + getMainFrame ()->updateData (); +} + +// *************************************************************************** + +void CDialogProperties::updateModifiedState () +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Something selected ? + const uint selSize = _PropDlgLocators.size (); + + + + // Modification + bool inModificationMode = doc->inModificationMode(); + if (!_Modal && !inModificationMode) + doc->beginModification (); + + // For each selected primitive + for (uint i=0; igetPropertyByName ("name", propName)) + { + // Create a default property + CPrimitiveClass::CParameter defProp (*propName, "name"); + + // Add the property in the good widget + std::list::iterator ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + + (*ite).Modified=false; + + ite++; + } + } + + // For each properties of the class + for (uint p=0; pParameters.size (); p++) + { + // Is the parameter visible ? + if (primClass->Parameters[p].Visible) + { + // Add the property in the good widget + std::list::iterator ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + (*ite).Modified=false; + + + + ite++; + } + } + } + } + else + { + // For each primitive property + uint numProp = primitive->getNumProperty (); + for (uint p=0; pgetProperty (p, propertyName, prop)); + + // Create a default property + CPrimitiveClass::CParameter defProp (*prop, propertyName.c_str ()); + + // Add the property in the good widget + std::list::iterator ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + (*ite).Modified=false; + + ite++; + } + } + } + } + } + + // Modification + if (!_Modal && !inModificationMode) + doc->endModification (); +} + +// *************************************************************************** + +void CDialogProperties::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + // TODO: Add your message handler code here and/or call default + +// m_ScrollBar.OnVScroll(nSBCode, nPos, pScrollBar); + + if ( !IsWindowVisible() ) + return; + + CDialog::OnVScroll(nSBCode, nPos, pScrollBar); + + RECT frameRect; + m_PropertyFrame.GetClientRect(&frameRect); +// m_PropertyFrame.ScreenToClient(&contRect); +// contRect.top = -m_ScrollBar.GetScrollPos(); +// contRect.bottom = -m_ScrollBar.GetScrollPos(); +// m_PropertyCont.s&contRect, TRUE); + +// +// int nDelta; +// int nMaxPos = m_rect.Height() - m_rect2.Height(); +// + int newPos; + int limit = pScrollBar->GetScrollLimit(); + switch (nSBCode) + { + case SB_LINEDOWN: + newPos = std::min(limit, int(pScrollBar->GetScrollPos()+16)); + break; + + case SB_LINEUP: + newPos = std::max(0, int(pScrollBar->GetScrollPos()-16)); + break; + + case SB_PAGEDOWN: + newPos = std::min(limit, int(pScrollBar->GetScrollPos()+frameRect.bottom)); + break; + + case SB_PAGEUP: + newPos = std::max(0, int(pScrollBar->GetScrollPos()-frameRect.bottom)); + break; + + case SB_THUMBPOSITION: + case SB_THUMBTRACK: + newPos = nPos; + break; + default: + return; + } +// m_nScrollPos += nDelta; +// m_ScrollBar.SetScrollPos(SB_VERT,m_nScrollPos,TRUE); + pScrollBar->SetScrollPos(newPos, TRUE); + RECT contRect; + m_PropertyCont.GetWindowRect(&contRect); + m_PropertyFrame.ScreenToClient(&contRect); +// int delta = -contRect.top - newPos; + int height = contRect.bottom - contRect.top; + contRect.top = -newPos; + contRect.bottom = contRect.top + height; +// m_PropertyFrame.ClientToScreen(&contRect); + m_PropertyCont.MoveWindow(&contRect, TRUE); + + m_PropertyFrame.GetWindowRect(&contRect); + ScreenToClient(&contRect); + +// m_PropertyCont.ScrollWindow(0, delta); + +} + +// *************************************************************************** + +void CDialogProperties::ApplyAutoname() +{ + // Update default parameters + std::list::iterator ite = Widgets.begin(); + while (ite != Widgets.end()) + { + if (ite->Default) + { + if (ite->Parameter.Type == CPrimitiveClass::CParameter::Boolean) + { + ite->CheckBox.SetCheck (2); + ite->updateBoolean (); + } + else if (ite->Parameter.Type == CPrimitiveClass::CParameter::ConstString) + { + ite->ComboBox.SelectString(-1 , ""); + ite->updateCombo (); + } + else if (ite->Parameter.Type == CPrimitiveClass::CParameter::String) + { + ite->Initializing = true; + ite->EditBox.SetWindowText(""); + ite->Initializing = false; + } + else if (ite->Parameter.Type == CPrimitiveClass::CParameter::StringArray) + { + ite->Initializing = true; + ite->MultiLineEditBox.SetWindowText(""); + ite->Initializing = false; +// ite->MultiLineEditBox.LoadText(CString()); + ite->updateMultiline (); + } + else if (ite->Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray) + { + ite->Initializing = true; + ite->ListEditBox.SetWindowText(""); + ite->Initializing = false; + ite->updateList (); + } + } + + ite++; + } + +/* // is the widget Autonamable ? + string b = widget->Parameter.Autoname; + if (!b.empty()) + { + // we get the widget's name to propagate it to the linked name + CString result; + if (widget->Parameter.Type == CPrimitiveClass::CParameter::Boolean) + { + if (widget->CheckBox.GetCheck() == 1) + result = "true"; + else if (widget->CheckBox.GetCheck() == 0) + result = "false"; + } + else if (widget->Parameter.Type == CPrimitiveClass::CParameter::ConstString) + { + // and we rename the correct field accordingly + widget->ComboBox.GetLBText(widget->ComboBox.GetCurSel(), result); + } + else if (widget->Parameter.Type == CPrimitiveClass::CParameter::String) + { + widget->EditBox.GetWindowText(result); + } + else if (widget->Parameter.Type == CPrimitiveClass::CParameter::StringArray) + { + // we just get the first element + std::vector tempArray; + widget->getValue (tempArray); + if (!tempArray.empty()) + { + result = tempArray[0].c_str(); + } + } + + std::list::iterator ite; + // if the widget has autoname, we simply copy its name to the linked widget + ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + CWidget &widget2 = *ite; + if (widget2.Parameter.Type == CPrimitiveClass::CParameter::String) + { + string a = widget2.Parameter.Name; + if (a == b) + { + // propagate the name to the autonamed field + CString str2; + widget2.EditBox.GetWindowText(str2); + int i = str2.GetLength(); + while(--i >= 0) + { + if (str2[i] <'0' || str2[i]>'9') + { + break; + } + } + // copy the name, followed by the existing number + widget2.EditBox.SetWindowText(result+"_"+str2.Mid(i+1)); + } + } + ite++; + } + } + else + { + const uint selSize = _Locators.size (); + + // The parameter list + set parameterList; + + // For each selected primitive + uint i; + for (i=0; iAutoname != "") + { + // we rename the string in one pass + CString Name = primClass->Autoname.c_str(); + // is the widget useful for building the name ? No->let's continue + CString fnd = widget->Parameter.Name.c_str(); + fnd = "$"+fnd+"$"; + if (Name.Find(fnd)<0) continue; + + std::list::iterator ite; + // if the widget has autoname, we simply copy its name to the linked widget + ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + CWidget &widget2 = *ite; + // we get the widget's name to propagate it to the linked name + CString result; + CString old = widget2.Parameter.Name.c_str(); + old = "$"+old+"$"; + if (widget2.Parameter.Type == CPrimitiveClass::CParameter::Boolean) + { + if (widget2.CheckBox.GetCheck() == 1) + result = "true"; + else if (widget2.CheckBox.GetCheck() == 0) + result = "false"; + Name.Replace(old, result); + } + else if (widget2.Parameter.Type == CPrimitiveClass::CParameter::ConstString) + { + // and we rename the correct field accordingly + int sel=widget2.ComboBox.GetCurSel(); + if (sel != -1) + { + widget2.ComboBox.GetLBText(sel, result); + } + Name.Replace(old, result); + } + else if (widget2.Parameter.Type == CPrimitiveClass::CParameter::String) + { + if (widget2.Parameter.Name != "name") + { + widget2.EditBox.GetWindowText(result); + Name.Replace(old, result); + } + } + else if (widget2.Parameter.Type == CPrimitiveClass::CParameter::StringArray) + { + // we just get the first element + std::vector tempArray; + widget2.getValue (tempArray); + if (!tempArray.empty()) + { + result = tempArray[0].c_str(); + } + } + ite++; + } + + // then, we set the name of the "name" editbox + ite = Widgets.begin (); + while (ite != Widgets.end ()) + { + CWidget &widget2 = *ite; + + if (widget2.Parameter.Type == CPrimitiveClass::CParameter::String) + { + if (widget2.Parameter.Name == "name") + { + // propagate the name to the autonamed field + CString str2; + if (Name != str2) + { + widget2.EditBox.SetWindowText(Name); + } + } + } + ite++; + } + + } + + } + } + } + }*/ +} + +// *************************************************************************** + +void CDialogProperties::CWidget::setStaticName() +{ + string Name = Parameter.Name; + if (Default) + { + Name += " (default value)"; + } + if (Parameter.Type == CPrimitiveClass::CParameter::Boolean) + { + setWindowTextUTF8 (CheckBox, Name.c_str()); + } + else + { + setWindowTextUTF8 (Static, Name.c_str()); + } +} + +// *************************************************************************** + +void CDialogProperties::SelectFolder(CWidget *widget) +{ + // select a directory in Win95 and NT4 (ugly code taken from Microsoft) + BROWSEINFO bi; + memset((LPVOID)&bi, 0, sizeof(bi)); + TCHAR szDisplayName[_MAX_PATH]; + szDisplayName[0] = '\0'; + bi.hwndOwner = GetSafeHwnd(); + bi.pszDisplayName = szDisplayName; + bi.lpszTitle = _T("Pick a folder, any folder:"); + bi.ulFlags = BIF_RETURNONLYFSDIRS; + bi.lpfn = NULL; + bi.lParam = 0; + + LPITEMIDLIST pidlRoot = NULL; + LPSHELLFOLDER desktop; + OLECHAR olePath[_MAX_PATH + 1]; + ULONG ulDummy; + + SHGetDesktopFolder (&desktop); + + if (widget->Parameter.Folder != "") + { + LPTSTR szPath = (char *)widget->Parameter.Folder.c_str(); + MultiByteToWideChar (CP_ACP, MB_PRECOMPOSED, szPath, -1, olePath, _MAX_PATH); + desktop->ParseDisplayName (NULL, NULL, olePath, &ulDummy, &pidlRoot, &ulDummy); + } + bi.pidlRoot = pidlRoot; + + LPMALLOC pMalloc; + HRESULT hr = SHGetMalloc(&pMalloc); + + LPITEMIDLIST pIIL = ::SHBrowseForFolder(&bi); + + if (pIIL != NULL) + { + TCHAR szInitialDir[_MAX_PATH]; + BOOL bRet = ::SHGetPathFromIDList(pIIL, (char*)&szInitialDir); + if (bRet) + { + int s = strlen(szInitialDir); + while (s) + { + --s; + if (szInitialDir[s] == '\\' || szInitialDir[s] == ':') + { + ++s; + break; + } + } + + std::vector tempArray; + widget->getValue (tempArray); + tempArray.push_back (szInitialDir+s); + setEditTextMultiLine (widget->MultiLineEditBox, tempArray); + widget->updateMultiline (); + + widget->MultipleValues = false; + widget->Modified = true; + widget->Set = true; + widget->Default = false; + /* todo hulud remove + ApplyAutoname(widget);*/ + widget->setStaticName(); + + pMalloc->Free(pIIL); + } + } + + desktop->Release (); + if (pidlRoot) pMalloc->Free (pidlRoot); + pMalloc->Release (); +} + +// *************************************************************************** + +BOOL CDialogProperties::PreTranslateMessage(MSG* pMsg) +{ + if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST) + { + UINT &message = pMsg->message; + // handle 'tab' for widgets + if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_TAB) + { + bool shift = ::GetAsyncKeyState(VK_SHIFT) != 0; + bool widgetWindow = true; + HWND tabTo = 0; + + // yep, we got a tab, check the wnd + std::list::iterator first(Widgets.begin()), last(Widgets.end()); + for (; first != last; ++first) + { + if (first->isHwndMatch(pMsg->hwnd)) + { + // ok, we got the good one, focus the next widget or wrap + if (!shift) + { + tabTo = first->getNextWindow(pMsg->hwnd); + if (!tabTo) + { + // advance to next widget + ++first; + if (first == last) + { + tabTo = m_OKButton.m_hWnd; + widgetWindow = false; + } + else + tabTo = first->getNextWindow(0); + } + } + else + { + tabTo = first->getPreviousWindow(pMsg->hwnd); + if (!tabTo) + { + // advance to previous widget + if (first == Widgets.begin()) + { + tabTo = m_updateButton.m_hWnd; + widgetWindow = false; + } + else + { + --first; + tabTo = first->getPreviousWindow(0); + } + } + } + + // stop to parse the widget + break; + + } + } + + // if no tab found, try the main button + if (!tabTo && !Widgets.empty()) + { + // not a widget window, check Ok and Update buttons + if (pMsg->hwnd == m_OKButton.m_hWnd && shift) + { + // select the last widget + CWidget &wg = Widgets.back(); + tabTo = wg.getPreviousWindow(0); + widgetWindow = false; + } + else if (pMsg->hwnd == m_updateButton.m_hWnd && !shift) + { + // select the first widget + CWidget &wg = Widgets.front(); + tabTo = wg.getNextWindow(0); + widgetWindow = true; + } + } + + // some focus to set ? + if (tabTo) + { + // focus and redraw the control (to showup focus rectagne if needed) + ::SetFocus(tabTo); + ::RedrawWindow(tabTo, NULL, NULL, RDW_INVALIDATE|RDW_INTERNALPAINT); + // keep the focused control in slider visibility + if (widgetWindow) + { + int move = 0; + + RECT focusPos; + ::GetWindowRect(tabTo, &focusPos); + + m_PropertyFrame.ScreenToClient(&focusPos); + // add the additionnal space for label (we like to see the label of current control !) + focusPos.top -= LABEL_HEIGHT + 5; + + RECT framePos; + m_PropertyFrame.GetClientRect(&framePos); + if (focusPos.top < framePos.top) + move = focusPos.top - framePos.top; + else if (focusPos.bottom > framePos.bottom) + move = focusPos.bottom - framePos.bottom; + + if (move != 0) + { + move = m_ScrollBar.GetScrollPos()+move; + // full MFC by sending a pseudo message + OnVScroll(SB_THUMBPOSITION, move, &m_ScrollBar); + } + + } + return TRUE; + } + } + // handle ALT+arrow to change selection + else if (pMsg->message == WM_SYSKEYDOWN + && (pMsg->wParam == VK_UP + || pMsg->wParam == VK_DOWN + || pMsg->wParam == VK_LEFT + || pMsg->wParam == VK_RIGHT)) + { + + CToolsLogic *toolWnd = dynamic_cast(getMainFrame ()->m_wndSplitter.GetPane(0,1)); + + toolWnd->GetTreeCtrl()->SendMessage(WM_KEYDOWN, pMsg->wParam, 0); + + return TRUE; + } + + // finally, translate the message + if (::TranslateAccelerator(theApp.m_pMainWnd->m_hWnd, _AccelTable, pMsg)) + return TRUE; + + } + + return CDialog::PreTranslateMessage(pMsg); +} + +// *************************************************************************** + +void CDialogProperties::setDefaultValue (CWidget *widget, string &value) +{ + value = ""; + bool foundOne = false; + widget->MultipleValues = false; + string fromWhere; + + // Something selected ? + const uint selSize = _PropDlgLocators.size (); + + // For each selected primitive + for (uint i=0; iParameters.size(); p++) + { + if (primClass->Parameters[p].Name == widget->Parameter.Name) + { + string temp; + primClass->Parameters[p].getDefaultValue (temp, *primitive, *primClass, &fromWhere); + + if (foundOne) + { + if (value != temp) + { + value = DIFFERENT_VALUE_STRING; + widget->MultipleValues = true; + } + if (widget->FromWhere != fromWhere) + { + widget->FromWhere = ""; + } + } + else + { + value = temp; + foundOne = true; + widget->FromWhere = fromWhere; + } + + break; + } + } + } + } + } +} + +// *************************************************************************** + +void CDialogProperties::setDefaultValue (CWidget *widget, std::vector &value) +{ + value.clear (); + bool foundOne = false; + widget->MultipleValues = false; + string fromWhere; + + // Something selected ? + const uint selSize = _PropDlgLocators.size (); + + // For each selected primitive + for (uint i=0; iParameters.size(); p++) + { + if (primClass->Parameters[p].Name == widget->Parameter.Name) + { + vector temp; + primClass->Parameters[p].getDefaultValue (temp, *primitive, *primClass, &fromWhere); + + if (foundOne) + { + if (value != temp) + { + value.resize (1); + value[0] = DIFFERENT_VALUE_STRING; + widget->MultipleValues = true; + } + if (widget->FromWhere != fromWhere) + { + widget->FromWhere = ""; + } + } + else + { + value = temp; + foundOne = true; + widget->FromWhere = fromWhere; + } + + break; + } + } + } + } + } +} + +// *************************************************************************** + +LRESULT CDialogProperties::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case LBN_CHANGE: + // Button id + int idButton = wParam; // identifier of button + if (idButton >= FIRST_WIDGET) + { + // Get the widget + CWidget *widget = getWidget (idButton-FIRST_WIDGET); + nlassert (widget->Parameter.Type == CPrimitiveClass::CParameter::ConstStringArray); + + // String NULL ? + std::vector result; + widget->getValue (result); + widget->Default = result.empty(); + widget->updateList (); + widget->Modified = true; + } + + break; + } + + return CDialog::WindowProc(message, wParam, lParam); +} + +// *************************************************************************** + +void CDialogProperties::OnSetFocus(CWnd*) +{ + if(!Widgets.empty()) + { + list::iterator ite=Widgets.begin(); + (*ite).setFocus(); + } +} + +// *************************************************************************** + +BOOL CDialogProperties::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) +{ + int pos = m_ScrollBar.GetScrollPos(); + pos -= zDelta; + m_ScrollBar.SetScrollPos(pos, FALSE); + pos = m_ScrollBar.GetScrollPos(); + OnVScroll(SB_THUMBPOSITION, pos, &m_ScrollBar); +// m_ScrollBar.OnMouseWheel(nFlags, zDelta, pt); +/* if (_ScrollBar) + { + int newPos = m_nScrollPos - zDelta; + clamp(newPos, 0, m_rect.Height() - m_rect2.Height()); + int delta = newPos - m_nScrollPos; + if (delta) + { + m_nScrollPos += delta; + SetScrollPos(SB_VERT,m_nScrollPos,TRUE); + ScrollWindow(0,-delta); + } + } +*/ + return CDialog::OnMouseWheel(nFlags, zDelta, pt); + +} + +// *************************************************************************** + +bool dataToClipboard (CWnd *wnd, UINT format, void *data, uint len) +{ + // Open the clipboard + if (wnd->OpenClipboard ()) + { + nlverify (EmptyClipboard ()); + if (data) + { + // Alloc a global memory + HGLOBAL hData = GlobalAlloc (GMEM_MOVEABLE|GMEM_DDESHARE, len); + if (hData) + { + // Copy the string + LPVOID dataPtr = GlobalLock (hData); + nlverify (dataPtr); + memcpy (dataPtr, data, len); + + // Release the pointer + GlobalUnlock (hData); + + // Set the clipboard + nlverify (SetClipboardData (format, hData)); + + // Close the clipboard + CloseClipboard (); + + // Ok + return true; + } + } + + // Close the clipboard + CloseClipboard (); + } + return false; +} + +// *************************************************************************** + +bool dataFromClipboard (CWnd *wnd, UINT format, void *data, uint lenMax) +{ + // Open the clipboard + if (wnd->OpenClipboard ()) + { + // Get the clipboard data + HANDLE hData = GetClipboardData (format); + if (hData) + { + DWORD len = GlobalSize (hData); + + // Get the string + LPVOID dataPtr = GlobalLock (hData); + nlverify (dataPtr); + + // Copy the string + memcpy (data, dataPtr, std::min(len, (DWORD)lenMax)); + + // Close the clipboard + CloseClipboard (); + + // Ok + return true; + } + + // Close the clipboard + CloseClipboard (); + } + return false; +} + +// *************************************************************************** + +void CMyComboBox::reloadData() +{ + if (!loaded) + { + int n = GetCurSel(); + CString s; + if(n != CB_ERR) GetLBText(n, s); + ResetContent(); + SetRedraw(FALSE); + InsertString(-1, ""); + for (vector::iterator it=_data.begin(), itEnd=_data.end(); it!=itEnd; ++it) + InsertString(-1, it->c_str()); + loaded = true; + SetRedraw(TRUE); + if(n != CB_ERR) SelectString(-1, s); + } +} + +// *************************************************************************** + +BOOL CMyComboBox::PreTranslateMessage( MSG* pMsg ) +{ + if (Widget != NULL && ((CDialogProperties::CWidget*)Widget)->Parameter.Editable) + { + if (pMsg->message == WM_CHAR) + GetParent()->SendMessage(WM_COMMAND, MAKELPARAM(GetDlgCtrlID(), CBN_SELCHANGE), (LPARAM)m_hWnd); + else if (pMsg->message == WM_LBUTTONDOWN) + reloadData(); + return CComboBox::PreTranslateMessage(pMsg); + } + + bool search = false; + if (pMsg->message == WM_CHAR) + { + // Erase key buffer ? + sint64 time = NLMISC::CTime::getLocalTime (); + if (time - _LastStrokeTime > COMBO_STROKE_DELAI) + _LastString = ""; + + // Add this char + _LastString.push_back (tolower((TCHAR) pMsg->wParam)); + search = true; + + // New stroke time + _LastStrokeTime = time; + } + // Copy ? + else if ((pMsg->message == WM_KEYDOWN) && ('C' == (int) pMsg->wParam) && (GetAsyncKeyState (VK_CONTROL) & 0x8000)) + { + int curSel = GetCurSel (); + if (curSel != CB_ERR) + { + CString rString; + GetLBText (curSel, rString); + dataToClipboard (this, CF_TEXT, (void*)(const char*)rString, rString.GetLength()+1); + } + } + // Paste ? + else if ((pMsg->message == WM_KEYDOWN) && ('V' == (int) pMsg->wParam) && (GetAsyncKeyState (VK_CONTROL) & 0x8000)) + { + char text[512]; + if (dataFromClipboard (this, CF_TEXT, text, 511)) + { + // 0 final + text[511] = 0; + _LastString = text; + search = true; + } + } + // Button down ? + else if (pMsg->message == WM_LBUTTONDOWN) + reloadData(); + + // Process string search ? + if (search) + { + // Find a string with this name + const uint count = GetCount(); + uint i; + uint matchSize = 0; + sint matchItem = -1; + for (i=0; i matchSize) + { + if (strncmp(tmp.c_str(), _LastString.c_str(), size) == 0) + { + matchItem = i; + matchSize = size; + } + } + } + + // Found something ? + if (matchItem != -1) + { + SetCurSel (matchItem); + GetParent()->SendMessage(WM_COMMAND, MAKELPARAM(GetDlgCtrlID(), CBN_SELCHANGE), (LPARAM)m_hWnd); + } + + return TRUE; + } + + return FALSE; +} + +// *************************************************************************** + +void CDialogProperties::OnSize(UINT nType, int cx, int cy) +{ + CDialog::OnSize( nType, cx, cy ); + + if ( !IsWindowVisible() ) + return; + + + ::CRect newDlgRect; + int deltaX, deltaY; + GetWindowRect( &newDlgRect ); + deltaX = newDlgRect.Width() - m_curDlgRect.Width(); + deltaY = newDlgRect.Height() - m_curDlgRect.Height(); + m_curDlgRect = newDlgRect; + + OnVScroll(SB_THUMBPOSITION, 0, &m_ScrollBar); + + { + RECT frameRect; + m_PropertyFrame.GetWindowRect( &frameRect ); + ScreenToClient( &frameRect ); + frameRect.right += deltaX; + frameRect.bottom += deltaY; + m_PropertyFrame.MoveWindow( &frameRect ); + } + + list::iterator ite=Widgets.begin(); + int decPosY = 0; + + while ( ite != Widgets.end() ) + { + if ( (*ite).OnSize( deltaX, deltaY, decPosY ) == true ) + decPosY += deltaY; + ite++; + } + + { + RECT contRect; + m_PropertyCont.GetWindowRect( &contRect ); + m_PropertyFrame.ScreenToClient( &contRect ); + contRect.right += deltaX; + contRect.bottom += decPosY; + //contRect.bottom = contRect.top + cy - m_FrameBottomSpace; + m_PropertyCont.MoveWindow ( &contRect ); + } + + // replace the 3 button + RECT buttonRect, dialogRect; + int space = ( newDlgRect.Width() - m_buttonWidth ) / 2; + int decalage; + GetClientRect(&dialogRect); + + // OK + GetDlgItem(IDOK)->GetWindowRect(&buttonRect); + ScreenToClient(&buttonRect); + buttonRect.bottom = (dialogRect.bottom - m_ButtonPos) + (buttonRect.bottom-buttonRect.top); + buttonRect.top = dialogRect.bottom - m_ButtonPos; + decalage = space - buttonRect.left; + buttonRect.left += decalage; + buttonRect.right += decalage; + GetDlgItem(IDOK)->MoveWindow(&buttonRect); + // cancel + GetDlgItem(IDCANCEL)->GetWindowRect(&buttonRect); + ScreenToClient(&buttonRect); + buttonRect.bottom = (dialogRect.bottom - m_ButtonPos) + (buttonRect.bottom-buttonRect.top); + buttonRect.top = dialogRect.bottom - m_ButtonPos; + buttonRect.left += decalage; + buttonRect.right += decalage; + GetDlgItem(IDCANCEL)->MoveWindow(&buttonRect); + //IDUPDATE + GetDlgItem(IDUPDATE)->GetWindowRect(&buttonRect); + ScreenToClient(&buttonRect); + buttonRect.bottom = (dialogRect.bottom - m_ButtonPos) + (buttonRect.bottom-buttonRect.top); + buttonRect.top = dialogRect.bottom - m_ButtonPos; + buttonRect.left += decalage; + buttonRect.right += decalage; + GetDlgItem(IDUPDATE)->MoveWindow(&buttonRect); + + RECT contRect; + m_PropertyCont.GetWindowRect(&contRect); + RECT frameRect; + m_PropertyFrame.GetClientRect(&frameRect); + // Set the scroll bar value + SCROLLINFO si; + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_PAGE | SIF_RANGE /*SIF_ALL*/|SIF_DISABLENOSCROLL; // SIF_ALL = SIF_PAGE | SIF_RANGE | SIF_POS; + si.nMin = 0; + si.nMax = contRect.bottom - contRect.top; + si.nPage = frameRect.bottom; + int pos = std::min(LONG(m_ScrollBar.GetScrollPos()), std::max(LONG(0), LONG(si.nMax - si.nPage))); + m_ScrollBar.SetScrollInfo(&si, FALSE); + // foul MFC by sending a pseudo message + OnVScroll(SB_THUMBPOSITION, pos, &m_ScrollBar); + + // replace the scroll bar control + RECT scrollRect; + m_PropertyFrame.GetClientRect(&scrollRect); + m_PropertyFrame.ClientToScreen(&scrollRect); + scrollRect.left = scrollRect.right-16; + ScreenToClient(&scrollRect); + m_ScrollBar.MoveWindow(&scrollRect, TRUE); + + + Invalidate(); +} + +// *************************************************************************** + +void CDialogProperties::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI ) +{ + CDialog::OnGetMinMaxInfo( lpMMI ); + + lpMMI->ptMinTrackSize.x = 455; + lpMMI->ptMinTrackSize.y = 50; +} + +// *************************************************************************** + +bool CDialogProperties::removePrimitives( list &locators ) +{ + for(list::iterator itP = locators.begin(); itP != locators.end(); itP++) + { + NLLIGO::IPrimitive* pPrim = *itP; + + for(vector::iterator it = _PropDlgLocators.begin(); it != _PropDlgLocators.end(); it++) + { + if ( (*it).Primitive == pPrim ) + { + _PropDlgLocators.erase( it ); + break; + } + } + } + + if(_PropDlgLocators.empty()) + { + // if all primitives were removed, the dialog is closed + OnCancel(); + return true; + } + else + { + OnUpdate(); + return false; + } +} + + +void CDialogProperties::OnMove(int x, int y) +{ + CDialog::OnMove(x, y); +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/dialog_properties.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/dialog_properties.h index 108b2b40f..330138b27 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/dialog_properties.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/dialog_properties.h @@ -1,350 +1,350 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_DIALOG_PROPERTIES_H__0F911E98_1C9F_489C_B898_7D8E4455FADE__INCLUDED_) -#define AFX_DIALOG_PROPERTIES_H__0F911E98_1C9F_489C_B898_7D8E4455FADE__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// dialog_properties.h : header file -// - -#include "my_list_box.h" -//#include "color_edit_wnd.h" - - -class CScrollPane : public CStatic -{ - class CDialogProperties *m_dlgProperty; -public: - - void init(class CDialogProperties *dlgProp) - { - m_dlgProperty = dlgProp; - } - - BOOL OnCommand(WPARAM wParam, LPARAM lParam); - LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); -}; - -///////////////////////////////////////////////////////////////////////////// -// CDialogProperties dialog - -#define COMBO_STROKE_DELAI 500 - -class CMyComboBox : public CComboBox -{ -public: - CMyComboBox () - { - _LastStrokeTime = 0; - Widget = NULL; - loaded = false; - } - void* Widget; - void setData(const std::vector& data) { _data = data; } - bool loaded; - -private: - std::string _LastString; - sint64 _LastStrokeTime; - std::vector _data; - void reloadData(); - virtual BOOL PreTranslateMessage( MSG* pMsg ); -}; - - -class CDialogProperties : public CDialog -{ - friend class CScrollPane; - friend class CMyComboBox; -// Construction -public: - CDialogProperties(); - CDialogProperties(std::list &locators, CWnd* pParent = NULL); // standard constructor - - // Change the selection - void changeSelection (std::list &locators); - - bool containsSelection( std::list &locators ); - bool containsSelection( std::vector &locators ); - bool equalsSelection( std::list &locators ); - bool removePrimitives( std::list &locators ); - - inline int getOriginalHeight() { return m_originalHeight; } - -private: - - // Cancel button ? - bool _Cancel; - - // Modal window ? - bool _Modal; - - // Scrollbar ? - bool _ScrollBar; - - // locators - std::vector _PropDlgLocators; - - // Class for a widget - class CWidget - { - public: - CWidget (CDialogProperties *dlg) -// : MultiLineEditBox(CString("ui/ryzom.color"), true) - { - Set = false; - Default = false; - MultipleValues = false; - Modified = false; - Initializing = false; - DialogProperties = dlg; - }; - CWidget (const CWidget &other) -// : MultiLineEditBox(CString("ui/ryzom.color"), true) - { - Static.Attach (other.Static.m_hWnd); - ComboBox.Attach (other.ComboBox.m_hWnd); - CheckBox.Attach (other.CheckBox.m_hWnd); - EditBox.Attach (other.EditBox.m_hWnd); - MultiLineEditBox.Attach (other.MultiLineEditBox.m_hWnd); - ListEditBox.Attach (other.ListEditBox.m_hWnd); - Set = other.Set; - Default = other.Default; - MultipleValues = other.MultipleValues; - Modified = other.Modified; - Initializing = other.Initializing; - Parameter = other.Parameter; - DialogProperties = other.DialogProperties; - } - ~CWidget () - { - if (IsWindow (Static.m_hWnd)) - { - Static.Detach (); - } - if (IsWindow (ComboBox.m_hWnd)) - { - ComboBox.Detach (); - } - if (IsWindow (CheckBox.m_hWnd)) - { - CheckBox.Detach (); - } - if (IsWindow (EditBox.m_hWnd)) - { - EditBox.Detach (); - } - if (IsWindow (MultiLineEditBox.m_hWnd)) - { - MultiLineEditBox.Detach (); - } - if (IsWindow (ListEditBox.m_hWnd)) - { - ListEditBox.Detach (); - } - } - - void setFocus(); - // Set from the parameter - bool fromParameter (const NLLIGO::IProperty *property, const NLLIGO::IPrimitive &primitive, const NLLIGO::CPrimitiveClass *primitiveClass, const NLLIGO::CPrimitiveClass::CParameter ¶meter); - - // Get to the parameter - bool toParameter (const CDatabaseLocatorPointer &locator, const NLLIGO::CPrimitiveClass::CParameter ¶meter); - - // Get the parameter - void getValue (std::string &result) const; - - // Get the parameter - void getValue (std::vector &result) const; - - // Set the label name - void setStaticName(); - - // A value is set ? - bool Set; - - // Default value or not ? - bool Default; - - // Multiple value ? - bool MultipleValues; - // The user has modified this property - bool Modified; - - // If true, EN_CHANGE is called because initialization process has made a setWindowText - // If false, EN_CHANGE is called because the user has modified the text in the window text - bool Initializing; - - // Different MFC Widget - CStatic Static; - CMyComboBox ComboBox; - CButton CheckBox; - CEdit EditBox; - CEdit MultiLineEditBox; -// ColorEditWnd MultiLineEditBox; - CMyListBox ListEditBox; - std::string FromWhere; - // CListCtrl ListBox; - - /// For combo box only - std::string OriginalString; - - // The dialog property - CDialogProperties *DialogProperties; - - // The parameter - NLLIGO::CPrimitiveClass::CParameter Parameter; - - // Update boolean value - void updateBoolean (); - void updateCombo (); - void updateMultiline (); - void updateList (); - - // Get the filename to open, return "" if nothing to open. - void getFilename (std::string &result); - - - // return true if the given hwnd is one of this widget - bool isHwndMatch(HWND hWnd); - - // get the next window - HWND getNextWindow(HWND hwnd); - // get the previous window - HWND getPreviousWindow(HWND hwnd); - - bool OnSize( int cx, int cy, int decY ); - }; - -public: - // Get the default value for this widget, return true if multiple value has been found - void setDefaultValue (CWidget *widget, std::string &value); - void setDefaultValue (CWidget *widget, std::vector &value); - - -private: - // Array of widget - std::list Widgets; - - // The default widget position - RECT WidgetPos; - // minium dialog size - uint WindowWidth; - uint WindowHeight; - - static CPoint s_lastPosition; - -private: - - // Accelerator table - HACCEL _AccelTable; - - CWidget *getWidget (uint widgetId); - - // Rebuild the dialog - void rebuildDialog (); - void ApplyAutoname(); - void SelectFolder(CWidget *widget); - -public: - // Add some widget - void addWidget (const NLLIGO::CPrimitiveClass::CParameter ¶meter, RECT &widgetPos, bool frozen); - - // Clear the widgets - void removeWidgets (); - void updateModification (); - - void updateModifiedState(); - - //test whether any widget has been modified - bool isModified(); - - static const CPoint& getLastPosition() { return s_lastPosition; } - -// Dialog Data - //{{AFX_DATA(CDialogProperties) - enum { IDD = IDD_PROPERTIES }; - CButton m_updateButton; - CButton m_OKButton; - CStatic m_FirstProp; - CStatic m_PropertyFrame; - CScrollBar m_ScrollBar; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CDialogProperties) - public: - virtual BOOL PreTranslateMessage(MSG* pMsg); - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); - virtual void OnSetFocus(CWnd*); - //}}AFX_VIRTUAL - -// Implementation -protected: - int m_nScrollPos; - //CRect m_rect, m_rect2; - //CRect rectEntireScreen; - - // Dynamicaly create control to contains the scrollable part - CScrollPane m_PropertyCont; -// CStatic m_PropertyCont; - // Relative top position of button from the dialog bottom client rect - int m_ButtonPos; - // default property frame position - RECT PropertyFrameRect; - /// Relative bottom position of property frame from the dialog bottom client rect. - int m_FrameTopSpace; - int m_FrameBottomSpace; - int m_MaxFrameHeight; - int m_DialogWidth; - /// Minimum container size - int m_ContMinHeight; - - CRect m_curDlgRect; - int m_originalHeight; - int m_buttonWidth; - - // Generated message map functions - //{{AFX_MSG(CDialogProperties) - virtual void OnOK(); - virtual void OnCancel(); - virtual BOOL OnInitDialog(); - afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); - afx_msg void OnUpdate(); - afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); - afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); - afx_msg void OnSize(UINT nType, int cx, int cy); - afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI ); - afx_msg void OnMove(int x, int y); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//extern CDialogProperties PropertyDialog; -extern std::list PropertiesDialogs; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_DIALOG_PROPERTIES_H__0F911E98_1C9F_489C_B898_7D8E4455FADE__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_DIALOG_PROPERTIES_H__0F911E98_1C9F_489C_B898_7D8E4455FADE__INCLUDED_) +#define AFX_DIALOG_PROPERTIES_H__0F911E98_1C9F_489C_B898_7D8E4455FADE__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// dialog_properties.h : header file +// + +#include "my_list_box.h" +//#include "color_edit_wnd.h" + + +class CScrollPane : public CStatic +{ + class CDialogProperties *m_dlgProperty; +public: + + void init(class CDialogProperties *dlgProp) + { + m_dlgProperty = dlgProp; + } + + BOOL OnCommand(WPARAM wParam, LPARAM lParam); + LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); +}; + +///////////////////////////////////////////////////////////////////////////// +// CDialogProperties dialog + +#define COMBO_STROKE_DELAI 500 + +class CMyComboBox : public CComboBox +{ +public: + CMyComboBox () + { + _LastStrokeTime = 0; + Widget = NULL; + loaded = false; + } + void* Widget; + void setData(const std::vector& data) { _data = data; } + bool loaded; + +private: + std::string _LastString; + sint64 _LastStrokeTime; + std::vector _data; + void reloadData(); + virtual BOOL PreTranslateMessage( MSG* pMsg ); +}; + + +class CDialogProperties : public CDialog +{ + friend class CScrollPane; + friend class CMyComboBox; +// Construction +public: + CDialogProperties(); + CDialogProperties(std::list &locators, CWnd* pParent = NULL); // standard constructor + + // Change the selection + void changeSelection (std::list &locators); + + bool containsSelection( std::list &locators ); + bool containsSelection( std::vector &locators ); + bool equalsSelection( std::list &locators ); + bool removePrimitives( std::list &locators ); + + inline int getOriginalHeight() { return m_originalHeight; } + +private: + + // Cancel button ? + bool _Cancel; + + // Modal window ? + bool _Modal; + + // Scrollbar ? + bool _ScrollBar; + + // locators + std::vector _PropDlgLocators; + + // Class for a widget + class CWidget + { + public: + CWidget (CDialogProperties *dlg) +// : MultiLineEditBox(CString("ui/ryzom.color"), true) + { + Set = false; + Default = false; + MultipleValues = false; + Modified = false; + Initializing = false; + DialogProperties = dlg; + }; + CWidget (const CWidget &other) +// : MultiLineEditBox(CString("ui/ryzom.color"), true) + { + Static.Attach (other.Static.m_hWnd); + ComboBox.Attach (other.ComboBox.m_hWnd); + CheckBox.Attach (other.CheckBox.m_hWnd); + EditBox.Attach (other.EditBox.m_hWnd); + MultiLineEditBox.Attach (other.MultiLineEditBox.m_hWnd); + ListEditBox.Attach (other.ListEditBox.m_hWnd); + Set = other.Set; + Default = other.Default; + MultipleValues = other.MultipleValues; + Modified = other.Modified; + Initializing = other.Initializing; + Parameter = other.Parameter; + DialogProperties = other.DialogProperties; + } + ~CWidget () + { + if (IsWindow (Static.m_hWnd)) + { + Static.Detach (); + } + if (IsWindow (ComboBox.m_hWnd)) + { + ComboBox.Detach (); + } + if (IsWindow (CheckBox.m_hWnd)) + { + CheckBox.Detach (); + } + if (IsWindow (EditBox.m_hWnd)) + { + EditBox.Detach (); + } + if (IsWindow (MultiLineEditBox.m_hWnd)) + { + MultiLineEditBox.Detach (); + } + if (IsWindow (ListEditBox.m_hWnd)) + { + ListEditBox.Detach (); + } + } + + void setFocus(); + // Set from the parameter + bool fromParameter (const NLLIGO::IProperty *property, const NLLIGO::IPrimitive &primitive, const NLLIGO::CPrimitiveClass *primitiveClass, const NLLIGO::CPrimitiveClass::CParameter ¶meter); + + // Get to the parameter + bool toParameter (const CDatabaseLocatorPointer &locator, const NLLIGO::CPrimitiveClass::CParameter ¶meter); + + // Get the parameter + void getValue (std::string &result) const; + + // Get the parameter + void getValue (std::vector &result) const; + + // Set the label name + void setStaticName(); + + // A value is set ? + bool Set; + + // Default value or not ? + bool Default; + + // Multiple value ? + bool MultipleValues; + // The user has modified this property + bool Modified; + + // If true, EN_CHANGE is called because initialization process has made a setWindowText + // If false, EN_CHANGE is called because the user has modified the text in the window text + bool Initializing; + + // Different MFC Widget + CStatic Static; + CMyComboBox ComboBox; + CButton CheckBox; + CEdit EditBox; + CEdit MultiLineEditBox; +// ColorEditWnd MultiLineEditBox; + CMyListBox ListEditBox; + std::string FromWhere; + // CListCtrl ListBox; + + /// For combo box only + std::string OriginalString; + + // The dialog property + CDialogProperties *DialogProperties; + + // The parameter + NLLIGO::CPrimitiveClass::CParameter Parameter; + + // Update boolean value + void updateBoolean (); + void updateCombo (); + void updateMultiline (); + void updateList (); + + // Get the filename to open, return "" if nothing to open. + void getFilename (std::string &result); + + + // return true if the given hwnd is one of this widget + bool isHwndMatch(HWND hWnd); + + // get the next window + HWND getNextWindow(HWND hwnd); + // get the previous window + HWND getPreviousWindow(HWND hwnd); + + bool OnSize( int cx, int cy, int decY ); + }; + +public: + // Get the default value for this widget, return true if multiple value has been found + void setDefaultValue (CWidget *widget, std::string &value); + void setDefaultValue (CWidget *widget, std::vector &value); + + +private: + // Array of widget + std::list Widgets; + + // The default widget position + RECT WidgetPos; + // minium dialog size + uint WindowWidth; + uint WindowHeight; + + static CPoint s_lastPosition; + +private: + + // Accelerator table + HACCEL _AccelTable; + + CWidget *getWidget (uint widgetId); + + // Rebuild the dialog + void rebuildDialog (); + void ApplyAutoname(); + void SelectFolder(CWidget *widget); + +public: + // Add some widget + void addWidget (const NLLIGO::CPrimitiveClass::CParameter ¶meter, RECT &widgetPos, bool frozen); + + // Clear the widgets + void removeWidgets (); + void updateModification (); + + void updateModifiedState(); + + //test whether any widget has been modified + bool isModified(); + + static const CPoint& getLastPosition() { return s_lastPosition; } + +// Dialog Data + //{{AFX_DATA(CDialogProperties) + enum { IDD = IDD_PROPERTIES }; + CButton m_updateButton; + CButton m_OKButton; + CStatic m_FirstProp; + CStatic m_PropertyFrame; + CScrollBar m_ScrollBar; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDialogProperties) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + virtual void OnSetFocus(CWnd*); + //}}AFX_VIRTUAL + +// Implementation +protected: + int m_nScrollPos; + //CRect m_rect, m_rect2; + //CRect rectEntireScreen; + + // Dynamicaly create control to contains the scrollable part + CScrollPane m_PropertyCont; +// CStatic m_PropertyCont; + // Relative top position of button from the dialog bottom client rect + int m_ButtonPos; + // default property frame position + RECT PropertyFrameRect; + /// Relative bottom position of property frame from the dialog bottom client rect. + int m_FrameTopSpace; + int m_FrameBottomSpace; + int m_MaxFrameHeight; + int m_DialogWidth; + /// Minimum container size + int m_ContMinHeight; + + CRect m_curDlgRect; + int m_originalHeight; + int m_buttonWidth; + + // Generated message map functions + //{{AFX_MSG(CDialogProperties) + virtual void OnOK(); + virtual void OnCancel(); + virtual BOOL OnInitDialog(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + afx_msg void OnUpdate(); + afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt); + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI ); + afx_msg void OnMove(int x, int y); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//extern CDialogProperties PropertyDialog; +extern std::list PropertiesDialogs; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DIALOG_PROPERTIES_H__0F911E98_1C9F_489C_B898_7D8E4455FADE__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/display.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/display.cpp index 6b0d64015..dd2a17d82 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/display.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/display.cpp @@ -1,3913 +1,3913 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" -#include "display.h" -#include "world_editor_doc.h" -#include "world_editor.h" -#include "editor_primitive.h" -#include "tools_logic.h" -#include -#include - -#include "main_frm.h" -#include "action.h" -#include "pacs.h" - -#include "nel/misc/path.h" -#include "nel/misc/bitmap.h" - -using namespace std; -using namespace NL3D; -using namespace NLMISC; -using namespace NLLIGO; - - -extern bool DontUse3D; - -// Color definition - -#define DEFAULT_ARROW_PRIMITIVE_COLOR (CRGBA (128, 0, 0, 255)) -#define DEFAULT_DOT_PRIMITIVE_COLOR (CRGBA (0, 0, 0, 255)) -#define SELECTED_PRIMITIVE_COLOR (CRGBA (255, 255, 255, 128)) -#define SELECTED_ARROW_PRIMITIVE_COLOR (CRGBA (255, 0, 0, 255)) -#define SELECTED_DOT_PRIMITIVE_COLOR (CRGBA (255, 255, 0, 255)) -#define SELECTED_DOT_COLOR (CRGBA (255, 0, 0, 255)) -#define LINK_LINE_COLOR (CRGBA (255, 255, 255, 128)) - -// Size definition - -#define POINT_ARROW_LINE_SIZE (20.f) -#define POINT_ARROW_HEAD_SIZE (8.f) -#define POINT_DOT_SIZE (3.f) - -// Circle - -#define CIRCLE_SEGMENT_SIZE 20 -#define CIRCLE_MIN_SEGMENT_COUNT 8 - -// Pick definition -#define PICK_DOT_SIZE (10) -#define PICK_PATH_SIZE (10) -#define LINK_LINE_SIZE (2) - -// Rotate per pixel -#define ROTATE_PER_PIXEL (2.f*(float)Pi/640.f) - -// Scale per pixel -#define SCALE_PER_PIXEL (4.f/640.f) - -// *************************************************************************** - -/* - -Primitive mouse state machine ------------------------------ - -LClickDown: - - CLICKED_ON_SELECTED = false - if subobject mode and add point mode - { - add a point in selected primitives - select the new points - active move transformation mode - } - else - { - if left/right click on primitives - { - if left click + ctrl + click on primitive - { - choose a clicked primitive - toggle its selection state - } - else - { - if at least one clicked primitive is selected - { - CLICKED_ON_SELECTED = true - } - else - { - unselect all - choose the first clicked primitive - select it - } - } - } - - if left click and the mouse is over a selected primitive - { - enable selected tranformation mode - } - } - - if left click and no transformation mode actived - { - if in subobject mode and over a selected primitive edge - { - add a point on this edge - select the point - active move transformation mode - } - } - - if left click and no transformation mode actived - { - disable tranformation mode - show rect selection - } - - if right click - { - show menu - } - -LClickUp: - - if the mouse moved - { - if tranformation mode is enabled - { - make the tranformation - } - else - { - hide rect selection - make a rect selection - if nothing selected in the rect and CTRL not pushed - unselect all - } - } - else - { - if tranformation mode is enabled - { - hide rect selection - } - - if CLICKED_ON_SELECTED == true - { - choose a not selected clicked primitive - unselect all - select it - } - - if no primitive under the mouse and CTRL not pushed - { - unselect all - } - } - -*/ - - - - - - - -BEGIN_MESSAGE_MAP (CDisplay, CView) - //{{AFX_MSG_MAP(CDisplay) - ON_WM_CREATE () - ON_WM_SIZE () - ON_WM_PAINT () - ON_WM_MOUSEWHEEL () - ON_WM_MBUTTONDOWN () - ON_WM_LBUTTONDOWN () - // ON_WM_LBUTTONDBLCLK () - ON_WM_RBUTTONDOWN () - ON_WM_MBUTTONUP () - ON_WM_LBUTTONUP () - ON_WM_RBUTTONUP () - ON_WM_MOUSEMOVE () - ON_WM_CHAR () - ON_WM_KEYUP () - ON_WM_DESTROY () - ON_WM_ERASEBKGND () - ON_WM_KEYDOWN() - ON_WM_KEYUP() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// *************************************************************************** -IMPLEMENT_DYNCREATE (CDisplay, CView) - -// *************************************************************************** -CDisplay::CDisplay () -{ - _MouseMode = Nothing; - _MouseRightDown = false; - _MouseLeftDown = false; - _MouseMidDown = false; - _MouseMoved = false; - _MouseMoving = false; - _Factor = 1.0f; - _Offset = CVector(0.0f, 0.0f, 0.0f); - _DisplayGrid = true; - _LastX = _LastY = -10000; - _CtrlKeyDown = false; - _MainFrame = NULL; - _BackgroundColor = CRGBA(192,192,192,255); - _LastPickedPrimitiveId = 0; - _TranformAction = NULL; - Interactif = true; - invalidateCursor (); - _DrawSelection = false; - for (int i=0;i < 4;++i) - { - _collisionTexture[i] = NULL; - _lastXCollisionTexture[i] = 100; - _lastYCollisionTexture[i] = 100; - } - _lastXCollisionTextureMove = 100; - _lastYCollisionTextureMove = 100; - - _FontManager = new NL3D::CFontManager; - _FontManager->setMaxMemory(2000000); - _TextContext = new NL3D::CTextContext; -} - -CDisplay::~CDisplay() -{ - delete _TextContext; - delete _FontManager; -} - -// *************************************************************************** -void CDisplay::print(const ucstring &text, float x, float y, uint32 fontSize, NLMISC::CRGBA color, THotSpot hotspot) -{ - _TextContext->setColor(color); - _TextContext->setFontSize(fontSize); - _TextContext->setHotSpot((NL3D::CComputedString::THotSpot) hotspot); - uint32 width, height; - nlassert(CNELU::Driver); - CNELU::Driver->getWindowSize(width, height); - _TextContext->printAt(x / (float) width, y / (float) height, text); -} - -// *************************************************************************** -void CDisplay::print(const std::string &text, float x, float y, uint32 fontSize, NLMISC::CRGBA color, THotSpot hotspot) -{ - print(ucstring(text), x, y, fontSize, color, hotspot); -} - - -// *************************************************************************** -void CDisplay::init (CMainFrame *pMF) -{ - _MainFrame = pMF; - - if (!DontUse3D) - { - registerSerial3d (); - CScene::registerBasics (); - init3d (); - - try - { - //CNELU::init (512, 512, CViewport(), 32, true, this->m_hWnd); - //NL3D::registerSerial3d(); - CNELU::initDriver (512, 512, 32, true, this->m_hWnd); - CNELU::initScene (CViewport()); - - CNELU::Driver->forceDXTCCompression (true); - - // setMatrixMode2D11 - CFrustum f(0.0f,1.0f,0.0f,1.0f,-1.0f,1.0f,false); - CVector I(1,0,0); - CVector J(0,0,1); - CVector K(0,-1,0); - CMatrix ViewMatrix, ModelMatrix; - ViewMatrix.identity (); - ViewMatrix.setRot (I,J,K, true); - ModelMatrix.identity (); - - CNELU::Driver->setFrustum (f.Left, f.Right, f.Bottom, f.Top, f.Near, f.Far, f.Perspective); - CNELU::Driver->setupViewMatrix (ViewMatrix); - CNELU::Driver->setupModelMatrix (ModelMatrix); - CNELU::Driver->activate (); - CNELU::clearBuffers (); - CNELU::swapBuffers (); - - // init the text context - _TextContext->init(CNELU::Driver, _FontManager); - _TextContext->setFontGenerator(NLMISC::CPath::getWindowsDirectory() + "Fonts\\arial.ttf"); - _TextContext->setKeep800x600Ratio(true); - _TextContext->setShaded(true); - _TextContext->setShadeColor(NLMISC::CRGBA::Black); - } - catch(...) - { - DontUse3D = true; - } - } - - SetCurrentDirectory (pMF->_ExeDir.c_str()); -} - -// *************************************************************************** -void CDisplay::setCellSize (float size) -{ - _CellSize = size; - _InitViewMax = CVector (5.5f*_CellSize, 5.5f*_CellSize, 0.0f); - _InitViewMin = CVector (-5.5f*_CellSize, -5.5f*_CellSize, 0.0f); -} - -// *************************************************************************** -void CDisplay::setBackgroundColor (NLMISC::CRGBA &col) -{ - _BackgroundColor = col; -} - -// *************************************************************************** -NLMISC::CRGBA CDisplay::getBackgroundColor () -{ - return _BackgroundColor; -} - -// *************************************************************************** -void CDisplay::setDisplayGrid (bool bDisp) -{ - _DisplayGrid = bDisp; -} - -// *************************************************************************** -bool CDisplay::getDisplayGrid () -{ - return _DisplayGrid; -} - -// *************************************************************************** -void CDisplay::calcCurView() -{ - _CurViewMin = _InitViewMin * _Factor + _Offset; - _CurViewMax = _InitViewMax * _Factor + _Offset; - - if (DontUse3D) - return; - - // View to world matrix - CNELU::Driver->getWindowSize (_WindowWidth, _WindowHeight); - _View2World.identity (); - if ((_WindowWidth > 0) && (_WindowHeight > 0) ) - _View2World.scale (CVector ((_CurViewMax.x - _CurViewMin.x)/(float)_WindowWidth, (_CurViewMax.y - _CurViewMin.y)/(float)_WindowHeight, 1)); - _View2World.setPos (_CurViewMin); - - // World to view matrix - _World2View = _View2World; - _World2View.invert (); - -} - -// *************************************************************************** -CVector CDisplay::convertToWorld (CPoint&p) -{ - CVector ret; - ::CRect rect; - - GetClientRect (rect); - calcCurView (); - ret.x = ((float)p.x) / ((float)rect.Width()); - ret.x = ret.x*(_CurViewMax.x-_CurViewMin.x) + _CurViewMin.x; - ret.y = 1.0f - (((float)p.y) / ((float)rect.Height())); - ret.y = ret.y*(_CurViewMax.y-_CurViewMin.y) + _CurViewMin.y; - ret.z = 0.0f; - - return ret; -} - -// *************************************************************************** - -void CDisplay::renderPluginPosition() -{ - CVector p1, p2, p3, p4; - float size = 500; - - p1 = _MainFrame->_PositionControl; - p1.x = (p1.x-_CurViewMin.x) / (_CurViewMax.x-_CurViewMin.x); - p1.y = (p1.y-_CurViewMin.y) / (_CurViewMax.y-_CurViewMin.y); - - p2 = p3 = p4 = p1; - - p1.x -= size; - p1.y -= size; - p2.x += size; - p2.y += size; - p3.x -= size; - p3.y += size; - p4.x += size; - p4.y -= size; - - if (DontUse3D) - return; - - CDRU::drawLine (p1.x, p1.y, p2.x, p2.y, *CNELU::Driver, CRGBA(0,255,0,255)); - CDRU::drawLine (p3.x, p3.y, p4.x, p4.y, *CNELU::Driver, CRGBA(0,255,0,255)); - -} - -// *************************************************************************** - -void CDisplay::initRenderProxy () -{ - // Init the material (RGBA + Alpha blend) - _ProxyMaterial.initUnlit (); - _ProxyMaterial.setSrcBlend(CMaterial::srcalpha); - _ProxyMaterial.setDstBlend(CMaterial::invsrcalpha); - _ProxyMaterial.setBlend (true); - _ProxyMaterial.setColor (CRGBA(255, 255, 255, 192)); - _ProxyMaterial.setZFunc (CMaterial::always); - _ProxyMaterial.setDoubleSided(true); - - // Init the vertex buffers - for (uint i=0; isetupViewport (CViewport()); - - // View to world matrix - mtx2.identity (); - mtx.identity (); - mtx.scale (CVector (_CurViewMax.x - _CurViewMin.x, 1, _CurViewMax.y - _CurViewMin.y)); - mtx2.rotateX ((float)(-Pi/2.0)); - mtx2 *= mtx; - mtx2.setPos (CVector (_CurViewMin.x, _CurViewMin.y, 0)); - - // World to view matrix - mtx2.invert (); - CNELU::Driver->setupViewMatrix (mtx2); - - // Model matrix - mtx.identity(); - CNELU::Driver->setupModelMatrix (mtx); - - // Frustrum - CNELU::Driver->setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false); -} - -// *************************************************************************** -void CDisplay::flushRenderProxy () -{ - if (DontUse3D) - return; - - // Setup matrix - setupWorldMatrixAndFrustum (); - - uint i; - for (i=0; iactiveVertexBuffer (_ProxyVB[i]); - CNELU::Driver->activeIndexBuffer (_ProxyPBTri[i]); - CNELU::Driver->renderTriangles (_ProxyMaterial, 0, _ProxyPBTri[i].getNumIndexes()/3); - CNELU::Driver->activeIndexBuffer (_ProxyPBLine[i]); - CNELU::Driver->renderLines (_ProxyMaterial, 0, _ProxyPBLine[i].getNumIndexes()/2); - } - - // Render points - _ProxyVBPointsAccess.unlock (); - if (_ProxyVBPoints.getNumVertices()) - { - CNELU::Driver->activeVertexBuffer (_ProxyVBPoints); - CNELU::Driver->renderRawPoints (_ProxyMaterial, 0, _ProxyVBPoints.getNumVertices()); - } - - // Render textured quads - for (i=0; i_Texture) - { - _ProxyMaterial.setTexture(0, _ProxyTexture[i]->_Texture); - } - else - { - _ProxyMaterial.setTexture(0, NULL); - } - _ProxyVBTexQuadsAccess[i].unlock(); - CNELU::Driver->activeVertexBuffer(_ProxyVBTexQuads[i]); - CNELU::Driver->renderRawQuads(_ProxyMaterial, 0, _ProxyVBTexQuads[i].getNumVertices() / 4); - } - _ProxyMaterial.setTexture(0, NULL); -} - -// *************************************************************************** - -void CDisplay::lineRenderProxy (CRGBA color, const CVector& pos0, const CVector& pos1, uint primitive) -{ - nlassert(primitive < NUM_PRIM_LAYER); - // Add two vertices - CVector p0 = pos0; - p0.z = 0; - CVector p1 = pos1; - p1.z = 0; - uint first = _ProxyVB[primitive].getNumVertices (); - if ((first+2) > _ProxyVB[primitive].capacity()) - { - _ProxyVBAccess[primitive].unlock(); - _ProxyVB[primitive].reserve (first*2); - _ProxyVB[primitive].lock (_ProxyVBAccess[primitive]); - } - _ProxyVB[primitive].setNumVertices (first + 2); - _ProxyVBAccess[primitive].setVertexCoord(first, p0); - _ProxyVBAccess[primitive].setVertexCoord(first+1, p1); - _ProxyVBAccess[primitive].setColor(first, color); - _ProxyVBAccess[primitive].setColor(first+1, color); - - uint firstIndex = _ProxyPBLine[primitive].getNumIndexes (); - if ((firstIndex+2) > _ProxyPBLine[primitive].capacity()) - { - _ProxyPBLineAccess[primitive].unlock(); - _ProxyPBLine[primitive].reserve (firstIndex*2); - _ProxyPBLine[primitive].lock (_ProxyPBLineAccess[primitive]); - } - _ProxyPBLine[primitive].setNumIndexes (firstIndex+2); - _ProxyPBLineAccess[primitive].setLine (firstIndex, first, first + 1); -} - -// *************************************************************************** - -void CDisplay::triRenderProxy (CRGBA color, const CVector& pos0, const CVector& pos1, const CVector& pos2, uint primitive) -{ - nlassert(primitive < NUM_PRIM_LAYER); - // Add three vertices - CVector p0 = pos0; - p0.z = 0; - CVector p1 = pos1; - p1.z = 0; - CVector p2 = pos2; - p2.z = 0; - uint first = _ProxyVB[primitive].getNumVertices (); - if ((first+3) > _ProxyVB[primitive].capacity()) - { - _ProxyVBAccess[primitive].unlock(); - _ProxyVB[primitive].reserve (first*2); - _ProxyVB[primitive].lock (_ProxyVBAccess[primitive]); - } - _ProxyVB[primitive].setNumVertices (first + 3); - _ProxyVBAccess[primitive].setVertexCoord(first, p0); - _ProxyVBAccess[primitive].setVertexCoord(first+1, p1); - _ProxyVBAccess[primitive].setVertexCoord(first+2, p2); - _ProxyVBAccess[primitive].setColor(first, color); - _ProxyVBAccess[primitive].setColor(first+1, color); - _ProxyVBAccess[primitive].setColor(first+2, color); - - - uint firstIndex = _ProxyPBTri[primitive].getNumIndexes (); - if ((firstIndex+3) > _ProxyPBTri[primitive].capacity()) - { - _ProxyPBTriAccess[primitive].unlock(); - _ProxyPBTri[primitive].reserve (firstIndex*2); - _ProxyPBTri[primitive].lock (_ProxyPBTriAccess[primitive]); - } - _ProxyPBTri[primitive].setNumIndexes (firstIndex+3); - _ProxyPBTriAccess[primitive].setTri (firstIndex, first, first + 1, first + 2); -} - -// *************************************************************************** - -void CDisplay::texQuadRenderProxy(const NLMISC::CQuadColorUV &quad, uint primLayer) -{ - nlassert(primLayer < NUM_PRIM_LAYER); - NL3D::CVertexBuffer &vb = _ProxyVBTexQuads[primLayer]; - NL3D::CVertexBufferReadWrite &vba = _ProxyVBTexQuadsAccess[primLayer]; - uint first = vb.getNumVertices (); - if ((first+4) > vb.capacity()) - { - vba.unlock(); - vb.reserve (first*2); - vb.lock (vba); - } - vb.setNumVertices (first + 4); - vba.setVertexCoord(first, quad.V0); - vba.setVertexCoord(first+1, quad.V1); - vba.setVertexCoord(first+2, quad.V2); - vba.setVertexCoord(first+3, quad.V3); - vba.setColor(first, quad.Color0); - vba.setColor(first+1, quad.Color1); - vba.setColor(first+2, quad.Color2); - vba.setColor(first+3, quad.Color3); - vba.setTexCoord(first, 0, quad.Uv0); - vba.setTexCoord(first + 1, 0, quad.Uv1); - vba.setTexCoord(first + 2, 0, quad.Uv2); - vba.setTexCoord(first + 3, 0, quad.Uv3); - -} - - -// *************************************************************************** - -void CDisplay::pointRenderProxy (CRGBA color, const CVector& pos0) -{ - // Add three vertices - CVector p0 = pos0; - p0.z = 0; - uint first = _ProxyVBPoints.getNumVertices (); - if ((first+1) > _ProxyVBPoints.capacity()) - { - _ProxyVBPointsAccess.unlock (); - _ProxyVBPoints.reserve (first*2); - _ProxyVBPoints.lock (_ProxyVBPointsAccess); - } - _ProxyVBPoints.setNumVertices (first + 1); - _ProxyVBPointsAccess.setVertexCoord(first, p0); - _ProxyVBPointsAccess.setColor(first, color); -} - - - -// *************************************************************************** -void CDisplay::primitiveRenderProxy(const NLLIGO::IPrimitive &primitive) -{ - drawPrimitive(&primitive, true); -} - - -// *************************************************************************** -void CDisplay::flush() -{ - flushRenderProxy(); - initRenderProxy(); -} - - -// *************************************************************************** - -void CDisplay::pixelToWorld (CVector &pixels) -{ - pixels = _View2World * pixels; -} - -void CDisplay::pixelVectorToWorld(NLMISC::CVector &pixels) -{ - pixels = _View2World.mulVector(pixels); -} - - -// *************************************************************************** - -inline float CDisplay::intToWorld (uint value) const -{ - if (_WindowWidth == 0) - return 0.0f; - return (float)value * (_CurViewMax.x - _CurViewMin.x) / _WindowWidth; -} - -// *************************************************************************** - -inline void CDisplay::worldToPixel (CVector &pixels) -{ - pixels = _World2View * pixels; - pixels.x = (float)(sint32)pixels.x; - pixels.y = (float)(sint32)pixels.y; - pixels.z = (float)(sint32)pixels.z; -} - -// *************************************************************************** -void CDisplay::worldToFloatPixel(NLMISC::CVector &pixels) -{ - pixels = _World2View * pixels; -} - -// *************************************************************************** - -void CDisplay::worldVectorToPixelVector(NLMISC::CVector &pixels) -{ - pixels = _World2View.mulVector(pixels); - pixels.x = (float)(sint32)pixels.x; - pixels.y = (float)(sint32)pixels.y; - pixels.z = (float)(sint32)pixels.z; -} - -// *************************************************************************** - -void CDisplay::worldVectorToFloatPixelVector(NLMISC::CVector &pixels) -{ - pixels = _World2View.mulVector(pixels); -} - - - -// *************************************************************************** - -bool CDisplay::isClipped (const CPrimVector *pVec, uint32 nNbVec) -{ - uint32 i; - for (i = 0; i < nNbVec; ++i) - if (pVec[i].x > _CurViewMin.x) - break; - if (i == nNbVec) - return true; // Entirely clipped - - for (i = 0; i < nNbVec; ++i) - if (pVec[i].x < _CurViewMax.x) - break; - if (i == nNbVec) - return true; - - for (i = 0; i < nNbVec; ++i) - if (pVec[i].y > _CurViewMin.y) - break; - if (i == nNbVec) - return true; - - for (i = 0; i < nNbVec; ++i) - if (pVec[i].y < _CurViewMax.y) - break; - if (i == nNbVec) - return true; - return false; // Not entirely clipped -} - -// *************************************************************************** - -bool CDisplay::isInTriangleOrEdge( double x, double y, - double xt1, double yt1, - double xt2, double yt2, - double xt3, double yt3 ) -{ - // Test vector T1X and T1T2 - double sign1 = ((xt2-xt1)*(y-yt1) - (yt2-yt1)*(x-xt1)); - // Test vector T2X and T2T3 - double sign2 = ((xt3-xt2)*(y-yt2) - (yt3-yt2)*(x-xt2)); - // Test vector T3X and T3T1 - double sign3 = ((xt1-xt3)*(y-yt3) - (yt1-yt3)*(x-xt3)); - if( (sign1 <= 0.0)&&(sign2 <= 0.0)&&(sign3 <= 0.0) ) - return true; - if( (sign1 >= 0.0)&&(sign2 >= 0.0)&&(sign3 >= 0.0) ) - return true; - return false; -} - -// *************************************************************************** - -void CDisplay::drawPrimitive (const NLLIGO::IPrimitive *primitive, bool forceDefaultDisplay) -{ - - // Configurations - const std::vector &configurations = theApp.Config.getPrimitiveConfiguration(); - - // Get the hide property - bool hide = !isPrimitiveVisible (primitive); - - // Not hide ? - if (!hide) - { - // Get the select property - bool selected = getPrimitiveEditor(primitive)->getSelected(); - - // Get a color parameter - CRGBA mainColor; - CRGBA arrowColor; - CRGBA dotColor; - CRGBA lineColor; - - // Is selected ? - if (selected) - { - mainColor = SELECTED_PRIMITIVE_COLOR; - arrowColor = SELECTED_ARROW_PRIMITIVE_COLOR; - dotColor = SELECTED_DOT_PRIMITIVE_COLOR; - } - else - { - // Get the primitive color - mainColor = theApp.Config.getPrimitiveColor (*primitive); - arrowColor = DEFAULT_ARROW_PRIMITIVE_COLOR; - dotColor = DEFAULT_DOT_PRIMITIVE_COLOR; - uint8 alpha = mainColor.A; - - // Look for the configuration - sint search = 0; - bool colorFound = false; - while ((search = theApp.getActiveConfiguration (*primitive, search)) != -1) - { - // Configuration activated ? - if (theApp.Configurations[search].Activated) - { - colorFound = true; - mainColor = configurations[search].Color; - break; - } - search++; - } - - // try to get the primitive color ? - if (!colorFound) - primitive->getPropertyByName ("Color", mainColor); - - // Restore alpha - mainColor.A = alpha; - } - - // Line color - lineColor = mainColor; - lineColor.A = 255; - - // check if there is a plug in to draw this primitive - string *className; - primitive->getPropertyByName("class", className); -// const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*className); - - std::map::iterator it; - if (!forceDefaultDisplay) - { - it = theApp.PrimitiveDisplayers.find(*className); - } - if (!forceDefaultDisplay && it != theApp.PrimitiveDisplayers.end()) - { - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (className->c_str()); - // use a plug in displayer - IPrimitiveDisplayer::TRenderContext ctx; - ctx.ShowDetail = _MainFrame->showDetails (); - ctx.Selected = selected; - ctx.MainColor = mainColor; - ctx.ArrowColor = arrowColor; - ctx.DotColor = dotColor; - ctx.LineColor = lineColor; - ctx.PrimitiveClass = primClass; - ctx.Display = this; - - it->second->drawPrimitive(primitive, ctx); - } - else - { - // use internal drawing code - - // Point primitive ? - const CPrimPointEditor *point = dynamic_cast(primitive); - if (point) - { - // Clip ? - if (!isClipped (&point->Point, 1)) - { - // Position in world - CVector center = point->Point; - worldToPixel (center); - - // Dot - CVector dot0, dot1, dot2, dot3; - dot0 = center; - dot0.x += POINT_DOT_SIZE; - dot0.y += POINT_DOT_SIZE; - dot1 = center; - dot1.x -= POINT_DOT_SIZE; - dot1.y += POINT_DOT_SIZE; - dot2 = center; - dot2.x -= POINT_DOT_SIZE; - dot2.y -= POINT_DOT_SIZE; - dot3 = center; - dot3.x += POINT_DOT_SIZE; - dot3.y -= POINT_DOT_SIZE; - - // Transform primitive - transformVector (dot0, point->Angle, center); - transformVector (dot1, point->Angle, center); - transformVector (dot2, point->Angle, center); - transformVector (dot3, point->Angle, center); - - // In world space - pixelToWorld (center); - pixelToWorld (dot0); - pixelToWorld (dot1); - pixelToWorld (dot2); - pixelToWorld (dot3); - - // Draw it - triRenderProxy (mainColor, dot0, dot1, dot2, selected?2:0); - triRenderProxy (mainColor, dot2, dot3, dot0, selected?2:0); - - // Got a radius ? - if (_MainFrame->showDetails ()) - { - // Prim class available ? - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*point); - if (primClass != NULL) - { - // Draw an arraow ? - if (primClass->ShowArrow) - { - // Position in world - center = point->Point; - worldToPixel (center); - CVector arrow = center; - CVector arrow0 = center; - arrow.x += POINT_ARROW_LINE_SIZE; - CVector arrow1 = arrow; - CVector arrow2 = arrow; - arrow0.x += POINT_ARROW_LINE_SIZE + POINT_ARROW_HEAD_SIZE; - arrow1.y += POINT_ARROW_HEAD_SIZE; - arrow2.y -= POINT_ARROW_HEAD_SIZE; - - // Transform primitive - transformVector (arrow, point->Angle, center); - transformVector (arrow0, point->Angle, center); - transformVector (arrow1, point->Angle, center); - transformVector (arrow2, point->Angle, center); - - // In world space - pixelToWorld (center); - pixelToWorld (arrow); - pixelToWorld (arrow0); - pixelToWorld (arrow1); - pixelToWorld (arrow2); - - // Draw it - lineRenderProxy (mainColor, center, arrow, selected?2:0); - triRenderProxy (arrowColor, arrow0, arrow1, arrow2, selected?2:0); - } - } - - // Have a radius ? - string radius; - if (primitive->getPropertyByName ("radius", radius)) - { - // Get it - float fRadius = (float)atof (radius.c_str ()); - - // Get the perimeter - float perimeter = 2.f*(float)Pi*fRadius; - - // Get the perimeter on the screen - perimeter *= (float)_WindowWidth / (_CurViewMax.x - _CurViewMin.x); - - // Get the segement count - perimeter /= (float)CIRCLE_SEGMENT_SIZE; - - // Clamp - if (perimeter < CIRCLE_MIN_SEGMENT_COUNT) - perimeter = CIRCLE_MIN_SEGMENT_COUNT; - - // Segment count - uint segmentCount = (uint)perimeter; - - // Draw a circle - CVector posInit = center; - posInit.x += fRadius; - CVector posPrevious = posInit; - for (uint i=1; i(primitive); - const CPrimZoneEditor *zone = dynamic_cast(primitive); - if (path || zone) - { - // Get the pointer on the points - uint pointsCount = path?path->VPoints.size ():zone->VPoints.size (); - if (pointsCount) - { - const CPrimVector *points = path?&(path->VPoints[0]):&(zone->VPoints[0]); - - // Clipped ? - if (!isClipped (points, pointsCount)) - { - // Is a zone ? - if (zone) - { - // - vector vRef; - vRef.resize(pointsCount); - - uint32 nStart; - - uint i; - for(i = 0; i < vRef.size(); ++i) - vRef[i] = i; - - nStart = 0; - while (vRef.size() > 2) - { - // Is triangle (nStart, nStart+1, nStart+2) back face ? - sint32 nP1 = vRef[nStart]; - sint32 nP2 = vRef[(nStart+1)%vRef.size()]; - sint32 nP3 = vRef[(nStart+2)%vRef.size()]; - const CVector &pos1 = points[nP1]; - const CVector &pos2 = points[nP2]; - const CVector &pos3 = points[nP3]; - if (((pos2.x-pos1.x) * (pos3.y-pos1.y) - (pos2.y-pos1.y) * (pos3.x-pos1.x)) < 0.0f) - { - // Yes -> next triangle - nStart++; - - if (nStart == vRef.size()) - break; - continue; - } - - // Is triangle (nStart, nStart+1, nStart+2) contains the other point ? - bool bInside = false; - for (i = 0; i < vRef.size(); ++i) - { - if ((vRef[i] != nP1) && (vRef[i] != nP2) && (vRef[i] != nP3)) - { - if (isInTriangleOrEdge( points[vRef[i]].x, points[vRef[i]].y, - pos1.x, pos1.y, - pos2.x, pos2.y, - pos3.x, pos3.y )) - { - bInside = true; - break; - } - } - } - - if (bInside) - { - // Yes -> next triangle - nStart++; - - if (nStart == vRef.size()) - break; - continue; - } - - // Draw the triangle - triRenderProxy (mainColor, pos1, pos2, pos3, selected?2:0); - - // Erase the point in the middle - for (i = 1+((nStart+1)%vRef.size()); i < vRef.size(); ++i) - vRef[i-1] = vRef[i]; - vRef.resize (vRef.size()-1); - nStart = 0; - } - } - - // Draw the lines - uint pt; - const CPrimVector *previous = path ? &(points[0]) : &(points[pointsCount-1]); - for (pt=path?1:0; ptisSelectionLocked ()) - { - // Draw points - for (pt=0; ptshowDetails () && (pointsCount>=2)) - { - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*path); - if (primClass != NULL) - { - if (primClass->ShowArrow) - { - // Position in world - CVector center = points[pointsCount-1]; - CVector i = center - points[pointsCount-2]; - i.z = 0; - i.normalize (); - CVector j = CVector::K ^ i; - j.normalize (); - worldToPixel (center); - CVector arrow0 = center; - CVector arrow1 = center; - CVector arrow2 = center; - arrow0 += i*POINT_ARROW_HEAD_SIZE; - arrow1 += j*POINT_ARROW_HEAD_SIZE; - arrow2 -= j*POINT_ARROW_HEAD_SIZE; - - // In world space - pixelToWorld (arrow0); - pixelToWorld (arrow1); - pixelToWorld (arrow2); - - // Draw it - triRenderProxy (arrowColor, arrow0, arrow1, arrow2, selected?2:0); - } - } - } - } - } - } - } - } - } -} - -// *************************************************************************** - -void CDisplay::drawLink (const NLLIGO::IPrimitive *first, const NLLIGO::IPrimitive *second) -{ - // Is shown ? - if (_MainFrame->showDetails () && isPrimitiveVisible (first) && isPrimitiveVisible (second)) - { - // Is a point ? - const CPrimPointEditor *pointFirst = dynamic_cast(first); - const CPrimPointEditor *pointSecond = dynamic_cast(second); - if (pointFirst && pointSecond) - { - CVector v[4]; - v[0] = pointFirst->Point; - v[1] = pointFirst->Point; - v[2] = pointSecond->Point; - v[3] = pointSecond->Point; - - uint i; - for (i=0; i<4; i++) - worldToPixel (v[i]); - - // Get the width direction - CVector dir = v[0] - v[2]; - dir.z = 0; - dir.normalize (); - dir *= (float)LINK_LINE_SIZE; - float temp = dir.x; - dir.x = dir.y; - dir.y = -temp; - v[0] -= dir; - v[1] += dir; - v[2] -= dir; - v[3] += dir; - - for (i=0; i<4; i++) - pixelToWorld (v[i]); - - // Draw a line - triRenderProxy (LINK_LINE_COLOR, v[0], v[2], v[3], 0); - triRenderProxy (LINK_LINE_COLOR, v[3], v[1], v[0], 0); - } - } -} - -// *************************************************************************** - -void CDisplay::OnDraw (CDC* pDC) -{ - if (DontUse3D) - { - // just fill the window client ara witha white brush - RECT client; - GetClientRect(&client); - pDC->SelectObject(GetStockObject(WHITE_BRUSH)); - pDC->Rectangle(&client); - return; - } - - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; - - CNELU::clearBuffers (_BackgroundColor); - - // Display the grid - calcCurView (); - - // Document - CWorldEditorDoc *doc = getDocument (); - - if (_MainFrame->showLandscape ()) - _MainFrame->_ZoneBuilder->render (_CurViewMin, _CurViewMax); - - if (_MainFrame->showLayers ()) - { - initRenderProxy (); - // Setup matrix - setupWorldMatrixAndFrustum (); - - // For each database elements - for (uint i=0; igetNumDatabaseElement (); i++) - { - // Is a landscape ? - if (doc->isLandscape (i)) - { - // Get the region - const NLLIGO::CZoneRegion ®ion = doc->getZoneRegionAbsolute (i); - float minx = (float)region.getMinX () * theApp.Config.CellSize; - float maxx = (float)(region.getMaxX ()+1) * theApp.Config.CellSize; - float miny = (float)region.getMinY () * theApp.Config.CellSize; - float maxy = (float)(region.getMaxY ()+1) * theApp.Config.CellSize; - - // Get the primitive - const NLLIGO::CPrimitives &primitives = doc->getDatabaseElements (i); - - // For each child - uint numChildren = primitives.RootNode->getNumChildren (); - for (uint j=0; jgetChild (child, j)); - - // Is it a bitmap ? - const CPrimBitmap *bitmap = dynamic_cast (child); - if (bitmap) - { - // Is shown ? - if (isPrimitiveVisible (bitmap)) - { - // Create a material - CMaterial material; - material.initUnlit (); - material.setTexture (0, bitmap->getTexture ()); - material.setZFunc (CMaterial::always); - material.setZWrite (false); - - // Blend function - string blendFunc; - if (bitmap->getPropertyByName ("blend_type", blendFunc)) - { - if (blendFunc == "additif") - { - material.setBlend (true); - material.setBlendFunc (CMaterial::one, CMaterial::one); - } - else if (blendFunc == "blend") - { - material.setBlend (true); - material.setBlendFunc (CMaterial::srcalpha, CMaterial::invsrcalpha); - } - else if (blendFunc == "blend additif") - { - material.setBlend (true); - material.setBlendFunc (CMaterial::srcalpha, CMaterial::one); - } - else if (blendFunc == "mix") - { - material.setBlend (true); - material.setBlendFunc (CMaterial::srcalpha, CMaterial::invsrcalpha); - material.texEnvArg0Alpha (0, CMaterial::Constant, CMaterial::SrcAlpha); - material.texConstantColor (0, CRGBA(0,0,0, 128)); - } - } - - // Create the vertices - std::vector vertices (2); - vertices[0].V0.x = minx; - vertices[0].V0.y = maxy; - vertices[0].V0.z = 0; - vertices[0].Uv0.U = 0; - vertices[0].Uv0.V = 0; - vertices[0].V1.x = minx; - vertices[0].V1.y = miny; - vertices[0].V1.z = 0; - vertices[0].Uv1.U = 0; - vertices[0].Uv1.V = 1; - vertices[0].V2.x = maxx; - vertices[0].V2.y = miny; - vertices[0].V2.z = 0; - vertices[0].Uv2.U = 1; - vertices[0].Uv2.V = 1; - vertices[1].V0.x = maxx; - vertices[1].V0.y = miny; - vertices[1].V0.z = 0; - vertices[1].Uv0.U = 1; - vertices[1].Uv0.V = 1; - vertices[1].V1.x = maxx; - vertices[1].V1.y = maxy; - vertices[1].V1.z = 0; - vertices[1].Uv1.U = 1; - vertices[1].Uv1.V = 0; - vertices[1].V2.x = minx; - vertices[1].V2.y = maxy; - vertices[1].V2.z = 0; - vertices[1].Uv2.U = 0; - vertices[1].Uv2.V = 0; - - - // Display it - CDRU::drawTrianglesUnlit (vertices, material, *CNELU::Driver); - } - } - } - } - } - flushRenderProxy (); - } - - if (_MainFrame->showCollisions()) - { - sint32 i; - sint32 dx, dy; - sint32 fx, fy; - i = 0; - double rx = fmod(_CurPos.x, _CellSize); - double ry = fabs(fmod(_CurPos.y, _CellSize)); - sint32 sy; - sy = 0; - - if (rx*2 < _CellSize) - { - fx = -1; - } - else - { - fx = 0; - } - - if (ry*2 < _CellSize) - { - fy = 0; - sy = 1; - } - else - { - fy = -1; - sy = 1; - } - - initRenderProxy (); - for (dy = fy;dy<=fy+sy;++dy) - { - for (dx = fx;dx<=fx+1;++dx) - { - DrawCollisionTexture(i, _CurPos.x+dx*_CellSize, _CurPos.y+dy*_CellSize); - ++i; - } - } - flushRenderProxy (); - } - - if (_MainFrame->showPACS ()) - { - initRenderProxy (); - - // Setup matrix - setupWorldMatrixAndFrustum (); - - // Draw pacs - PacsManager.displayPacs(*this); - - // Flush primitives - flushRenderProxy (); - } - - if (_MainFrame->showGrid ()) - _MainFrame->_ZoneBuilder->displayGrid (_CurViewMin, _CurViewMax); - - if (_MainFrame->showPrimitives ()) - { - // Render the primitives - - // Accelerate rendering with vertex buffer - initRenderProxy (); - - // Select the visible primitive in the quad grid - PrimitiveQuadGrid.select (_CurViewMin, _CurViewMax); - - // Parse - TPrimQuadGrid::CIterator ite = PrimitiveQuadGrid.begin(); - while (ite != PrimitiveQuadGrid.end ()) - { - // Is it a primitive or a link ? - if ((*ite).Second) - drawLink ((*ite).First, (*ite).Second); - else - drawPrimitive ((*ite).First); - ite++; - } - - // Flush primitives - flushRenderProxy (); - } - - if (!theApp.Plugins.empty()) - { - initRenderProxy (); - // plugins post render - for(uint k = 0; k < theApp.Plugins.size(); ++k) - { - theApp.Plugins[k]->postRender(*this); - } - flushRenderProxy (); - } - - - if (_MainFrame->showPoints ()) - displayPoints (); - - if (_MainFrame->_Mode == 2) // If we are in transition mode - _MainFrame->_ZoneBuilder->renderTransition (_CurViewMin, _CurViewMax); - - CNELU::Scene->render (); - - if (_MainFrame->_Mode == 3) // Disply the plugin position control ? - renderPluginPosition(); - - CNELU::swapBuffers (); - - if (_DrawSelection) - drawSelection (); -} - -// *************************************************************************** -int CDisplay::OnCreate (LPCREATESTRUCT lpCreateStruct) -{ - if (CView::OnCreate (lpCreateStruct) == -1) - return -1; - SetTimer (1, 200, NULL); - return 0; -} - -// *************************************************************************** -void CDisplay::OnDestroy () -{ - KillTimer (1); - CView::OnDestroy (); -} - -// *************************************************************************** -/*void*/BOOL CDisplay::OnMouseWheel (UINT nFlags, short zDelta, CPoint point) -{ - if (!Interactif) - return FALSE; - - if (DontUse3D) - return FALSE; - - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return FALSE; - float newFactor = _Factor; - if (zDelta < 0) - newFactor *= 2.0f; - else - newFactor /= 2.0f; - - setFactor (newFactor, true, _CurPos); - - return TRUE; -} - -// *************************************************************************** -void CDisplay::OnMButtonDown (UINT nFlags, CPoint point) -{ - if (!Interactif) - return; - - if (DontUse3D) - return; - - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; - _LastMousePos = point; - - nlassert (!_MouseMidDown); - _MouseMidDown = true; - - // Mouse capture On ! - if (!_MouseLeftDown && !_MouseRightDown) - SetCapture (); - - // Update mouse mode - updateMouseMode (nFlags); - - // Invalidate cursor - invalidateCursor (); - - // Update data - _MainFrame->updateData (); -} - -// *************************************************************************** -void CDisplay::OnMButtonUp (UINT nFlags, CPoint point) -{ - if (!Interactif) - return; - - if (DontUse3D) - return; - - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; - - // Release capture - if (_MouseMidDown && !_MouseLeftDown && !_MouseRightDown) - ReleaseCapture (); - - _MouseMidDown = false; - - // Update mouse mode - updateMouseMode (nFlags); - - // Invalidate cursor - invalidateCursor (); - - // Update data - _MainFrame->updateData (); -} - -// *************************************************************************** - -inline bool CDisplay::pickPoint (const CVector &pickPos, const CVector &point, float bias) -{ - CVector delta = pickPos; - delta -= point; - delta.z = 0; - return delta.sqrnorm () <= (bias*bias); -} - -// *************************************************************************** - -inline bool CDisplay::pickRect (const CVector &pickPosMin, const CVector &pickPosMax, const CVector &point) -{ - return ( (point.x >= pickPosMin.x) && (point.y >= pickPosMin.y) && (point.x <= pickPosMax.x) && (point.y <= pickPosMax.y)); -} - -// *************************************************************************** - -inline bool CDisplay::pickPoint (const CVector &pickPos, const CVector &v0, const CVector &v1, float bias) -{ - - // Segment vector - CVector segment = v1; - segment -= v0; - float vectorNorm = segment.norm (); - - // Segment NULL ? - if (vectorNorm == 0) - return false; - - // Normalize - segment /= vectorNorm; - - // Project - CVector tmp = pickPos; - tmp -= v0; - float dist = segment * tmp; - - // Clip - if ( (dist > -bias) && (dist < vectorNorm + bias) ) - { - // Pos on the seg - segment *= dist; - segment += v0; - segment -= pickPos; - return segment.sqrnorm () <= (bias*bias); - } - return false; -} - -// *************************************************************************** - -inline bool testValue (float t0, float t1, float v0, float v1, float t, float vMin, float vMax) -{ - if ( ((t0 < t) && (t1 >= t)) || ((t1 < t) && (t0 >= t))) - { - float v = v0 + (v1 - v0) * (t - t0) / (t1 - t0); - return (v >= vMin) && (v <= vMax); - } - return false; -} - -// *************************************************************************** - -inline bool CDisplay::pickRect (const CVector &pickPosMin, const CVector &pickPosMax, const CVector &v0, const CVector &v1) -{ - // Point inside ? - if (pickRect (pickPosMin, pickPosMax, v0) || pickRect (pickPosMin, pickPosMax, v1)) - return true; - - // Test segment - return ((testValue (v0.x, v1.x, v0.y, v1.y, pickPosMin.x, pickPosMin.y, pickPosMax.y)) || - (testValue (v0.x, v1.x, v0.y, v1.y, pickPosMax.x, pickPosMin.y, pickPosMax.y)) || - (testValue (v0.y, v1.y, v0.x, v1.x, pickPosMin.y, pickPosMin.x, pickPosMax.x)) || - (testValue (v0.y, v1.y, v0.x, v1.x, pickPosMax.y, pickPosMin.x, pickPosMax.x))); -} - -// *************************************************************************** - -bool CDisplay::getSelectedAverage (CVector &average) -{ - // Update data - UpdateSelection (); - - // Reset average - average = CVector::Null; - uint averageCount = 0; - - // Locked ? - bool locked = _MainFrame->isSelectionLocked (); - - // For each selected primitive - CWorldEditorDoc *doc = getDocument (); - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Is there a primitive at this node ? - if (locator.Primitive) - { - // Hidden ? - if (isPrimitiveVisible (locator.Primitive)) - { - // Selected ? - if (getPrimitiveEditor(locator.Primitive)->getSelected()) - { - // For each point - uint numVector = locator.Primitive->getNumVector (); - const CPrimVector *primVector = locator.Primitive->getPrimVector (); - for (uint vect=0; vect(locator.Primitive)) - { - average += primVector[vect]; - averageCount++; - } - } - } - } - } - - ite++; - } - - if (averageCount) - average /= (float)averageCount; - - return averageCount != 0; -} - -// *************************************************************************** - -bool CDisplay::pickPoint (const CVector &pickPos, std::vector &result, bool pickOnlySelected) -{ - // Clear result - result.clear (); - - float worldPickDotSize = intToWorld (PICK_DOT_SIZE); - float worldPickPathSize = intToWorld (PICK_PATH_SIZE); - - // The selection coordinate - const float maxDelta = std::max (worldPickPathSize, worldPickDotSize); - CVector minPos = pickPos - CVector (maxDelta, maxDelta, maxDelta); - CVector maxPos = pickPos + CVector (maxDelta, maxDelta, maxDelta); - - // Select the primitives - PrimitiveQuadGrid.select (minPos, maxPos); - - // Locked ? - CWorldEditorDoc *doc = getDocument (); - if (_MainFrame->isSelectionLocked ()) - { - TPrimQuadGrid::CIterator ite = PrimitiveQuadGrid.begin (); - while (ite != PrimitiveQuadGrid.end ()) - { - // Skip links - if ((*ite).Second == NULL) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, (*ite).First); - - // Selected ? - if (getPrimitiveEditor((*ite).First)->getSelected()) - { - // Hidden ? - if (isPrimitiveVisible ((*ite).First)) - { - // Pick it - const CPrimPointEditor *point = dynamic_cast ((*ite).First); - if (point) - { - // Pick it ? - if (pickPoint (pickPos, point->Point, worldPickDotSize) && (!pickOnlySelected || getPrimitiveEditor((*ite).First)->getSelected())) - { - // Add this point - result.push_back (locator); - result.back ().XSubPrim = 0; - } - } - else - { - // Pick it - const CPrimPathEditor *path = dynamic_cast ((*ite).First); - if (path) - { - // For each vertex - const uint numPt = path->VPoints.size (); - for (uint i=0; iVPoints[i], worldPickDotSize) && (!pickOnlySelected || path->VPoints[i].Selected)) - { - // Add this path - result.push_back (locator); - result.back ().XSubPrim = i; - } - } - } - else - { - // Pick it - const CPrimZoneEditor *zone = dynamic_cast ((*ite).First); - if (zone) - { - // For each vertex - const uint numPt = zone->VPoints.size (); - for (uint i=0; iVPoints[i], worldPickDotSize) && (!pickOnlySelected || zone->VPoints[i].Selected)) - { - // Add this zone - result.push_back (locator); - result.back ().XSubPrim = i; - } - } - } - } - } - } - } - } - - // Next primitive - ite++; - } - } - else - { - TPrimQuadGrid::CIterator ite = PrimitiveQuadGrid.begin (); - while (ite != PrimitiveQuadGrid.end ()) - { - // Skip links - if ((*ite).Second == NULL) - { - // Is there a primitive at this node ? - CDatabaseLocatorPointer locator; - doc->getLocator (locator, (*ite).First); - { - // Hidden ? - if (isPrimitiveVisible ((*ite).First)) - { - // Pick it - const CPrimPointEditor *point = dynamic_cast ((*ite).First); - if (point) - { - // Pick it ? - if (pickPoint (pickPos, point->Point, worldPickDotSize) && (!pickOnlySelected || getPrimitiveEditor((*ite).First)->getSelected())) - { - // Add this point - result.push_back (locator); - } - } - else - { - // Pick it - const CPrimPathEditor *path = dynamic_cast ((*ite).First); - if (path) - { - // For each segment - const uint numPt = path->VPoints.size (); - if (numPt>1) - { - for (uint i=0; iVPoints[i], path->VPoints[i+1], worldPickPathSize) && (!pickOnlySelected || getPrimitiveEditor((*ite).First)->getSelected())) - { - // Add this path - result.push_back (locator); - } - } - } - } - else - { - // Pick it - const CPrimZoneEditor *zone = dynamic_cast ((*ite).First); - if (zone) - { - // Pick it ? - if (zone->contains (pickPos) && (!pickOnlySelected || getPrimitiveEditor((*ite).First)->getSelected())) - { - // Add this path - result.push_back (locator); - } - } - } - } - } - } - } - - // Next primitive - ite++; - } - } - - return !result.empty(); -} - -// *************************************************************************** - -bool CDisplay::pickEdgePoint (const CVector &pickPos, std::vector &result) -{ - // Clear result - result.clear (); - - float worldPickPathSize = intToWorld (PICK_PATH_SIZE); - - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // The selection coordinate - CVector minPos = pickPos - CVector (worldPickPathSize, worldPickPathSize, worldPickPathSize); - CVector maxPos = pickPos + CVector (worldPickPathSize, worldPickPathSize, worldPickPathSize); - - // Select the primitives - PrimitiveQuadGrid.select (minPos, maxPos); - - TPrimQuadGrid::CIterator ite = PrimitiveQuadGrid.begin (); - while (ite != PrimitiveQuadGrid.end ()) - { - // Skip links - if ((*ite).Second == NULL) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, (*ite).First); - - // Hidden ? - if (isPrimitiveVisible ((*ite).First)) - { - // Selected ? - if (getPrimitiveEditor((*ite).First)->getSelected()) - { - // Pick it - const CPrimPathEditor *path = dynamic_cast ((*ite).First); - if (path) - { - // For each vertex - const uint numPt = path->VPoints.size (); - if (numPt > 1) - { - for (uint i=0; iVPoints[i], path->VPoints[i+1], worldPickPathSize)) - { - // Add this path - result.push_back (locator); - result.back ().XSubPrim = i; - } - } - } - } - else - { - // Pick it - const CPrimZoneEditor *zone = dynamic_cast ((*ite).First); - if (zone) - { - // For each vertex - const uint numPt = zone->VPoints.size (); - if (numPt > 1) - { - uint previous = numPt-1; - for (uint i=0; iVPoints[previous], zone->VPoints[i], worldPickPathSize)) - { - // Add this zone - result.push_back (locator); - result.back ().XSubPrim = previous; - } - - // Nex previous - previous = i; - } - } - } - } - } - } - } - - // Next primitive - ite++; - } - - return !result.empty(); -} - -// *************************************************************************** - -bool CDisplay::pickRect (const CVector &pickPosMin, const CVector &pickPosMax, std::vector &result, bool pickOnlyShown) -{ - // Clear result - result.clear (); - - // Select the primitives - PrimitiveQuadGrid.select (pickPosMin, pickPosMax); - - // Locked ? - CWorldEditorDoc *doc = getDocument (); - if (_MainFrame->isSelectionLocked ()) - { - TPrimQuadGrid::CIterator ite = PrimitiveQuadGrid.begin (); - while (ite != PrimitiveQuadGrid.end ()) - { - // Skip links - if ((*ite).Second == NULL) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, (*ite).First); - - // Selected ? - if (getPrimitiveEditor((*ite).First)->getSelected()) - { - // Hidden ? - if ((!pickOnlyShown) || (isPrimitiveVisible ((*ite).First))) - { - // Pick it - const CPrimPointEditor *point = dynamic_cast ((*ite).First); - if (point) - { - // Pick it ? - if (pickRect (pickPosMin, pickPosMax, point->Point)) - { - // Add this point - result.push_back (locator); - result.back ().XSubPrim = 0; - } - } - else - { - // Pick it - const CPrimPathEditor *path = dynamic_cast ((*ite).First); - if (path) - { - // For each vertex - const uint numPt = path->VPoints.size (); - for (uint i=0; iVPoints[i])) - { - // Add this path - result.push_back (locator); - result.back ().XSubPrim = i; - } - } - } - else - { - // Pick it - const CPrimZoneEditor *zone = dynamic_cast ((*ite).First); - if (zone) - { - // For each vertex - const uint numPt = zone->VPoints.size (); - for (uint i=0; iVPoints[i])) - { - // Add this zone - result.push_back (locator); - result.back ().XSubPrim = i; - } - } - } - } - } - } - } - } - - // Next primitive - ite++; - } - } - else - { - TPrimQuadGrid::CIterator ite = PrimitiveQuadGrid.begin (); - while (ite != PrimitiveQuadGrid.end ()) - { - // Skip links - if ((*ite).Second == NULL) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, (*ite).First); - { - // Hidden ? - if ((!pickOnlyShown) || (isPrimitiveVisible ((*ite).First))) - { - // Pick it - const CPrimPointEditor *point = dynamic_cast ((*ite).First); - if (point) - { - // Pick it ? - if (pickRect (pickPosMin, pickPosMax, point->Point)) - { - // Add this point - result.push_back (locator); - } - } - else - { - // Pick it - const CPrimPathEditor *path = dynamic_cast ((*ite).First); - if (path) - { - // For each segment - const uint numPt = path->VPoints.size (); - if (numPt>1) - { - for (uint i=0; iVPoints[i], path->VPoints[i+1])) - { - // Add this path - result.push_back (locator); - } - } - } - } - else - { - // Pick it - const CPrimZoneEditor *zone = dynamic_cast ((*ite).First); - if (zone) - { - // For each segment - const uint numPt = zone->VPoints.size (); - if (numPt>1) - { - // Last point - uint lastPt = numPt-1; - for (uint i=0; iVPoints[i], zone->VPoints[lastPt])) - { - // Add this zone - result.push_back (locator); - } - - // Next segment - lastPt = i; - } - } - } - } - } - } - } - } - - // Next primitive - ite++; - } - } - return !result.empty(); -} - -// *************************************************************************** - -void CDisplay::OnLButtonDown (UINT nFlags, CPoint point) -{ - if (!Interactif) - return; - - if (DontUse3D) - return; - - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; - - nlassert (!_MouseLeftDown); - _MouseLeftDown = true; - - // Mouse capture On ! - if (!_MouseMidDown && !_MouseRightDown) - SetCapture (); - - // Update mouse mode - updateMouseMode (nFlags); - - buttonDown (Left, nFlags, point); - - invalidateCursor (); - - // Update data - _MainFrame->updateData (); -} - -// *************************************************************************** - -void CDisplay::OnRButtonDown (UINT nFlags, CPoint point) -{ - if (!Interactif) - return; - - if (DontUse3D) - return; - - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; - - nlassert (!_MouseRightDown); - _MouseRightDown = true; - - // Mouse capture On ! - if (!_MouseMidDown && !_MouseLeftDown) - SetCapture (); - - // Update mouse mode - updateMouseMode (nFlags); - - buttonDown (Right, nFlags, point); - - invalidateCursor (); - - // Update data - _MainFrame->updateData (); -} - -// *************************************************************************** - -void CDisplay::buttonDown (TButton button, UINT nFlags, CPoint point) -{ - // this bool is used to fix a nasty bug: when a popup window appears, the message pump is called - bool EndModification = false; - _ClickedSelected = false; - CWorldEditorDoc *doc = getDocument (); - _CurPos = convertToWorld (point); - - // Begin of an undo stack element - doc->beginModification (); - - // Mode Zone - if ((_MouseMode == DrawTiles) || (_MouseMode == RemoveTiles)) - { - if (_MouseMode == DrawTiles) - _MainFrame->_ZoneBuilder->add (_CurPos); - if (_MouseMode == RemoveTiles) - _MainFrame->_ZoneBuilder->del (_CurPos); - - _LastX = (sint32)floor (_CurPos.x / _CellSize); - _LastY = (sint32)floor (_CurPos.y / _CellSize); - } - - // Cancel tranform ? - if (_TranformAction && (_MouseMode != TransformPrimitive)) - { - _TranformAction->undo (); - _TranformAction = NULL; - } - - // Mode Logic - if ((_MouseMode == TransformPrimitive) || (_MouseMode == MenuPrimitive)) - { - _SelectionMin = point; - _SelectionMax = point; - - CVector pickPosMin ((float)_SelectionMin.x, (float)(_WindowHeight-_SelectionMin.y-1), 0); - pixelToWorld (pickPosMin); - - // Left or right only - if ((button == Left) || (button == Right)) - { - // Add sub element vertex mode ? - bool addPointSub = (_MainFrame->getTransformMode () == CMainFrame::AddPoint) && (_MainFrame->isSelectionLocked ()); - if ( !addPointSub || (button == Right) ) - { - // Pick a primitive that exist - std::vector result; - if (pickPoint (pickPosMin, result, false)) - { - if ((nFlags & MK_CONTROL) != 0) - { - // Next primitives - _LastPickedPrimitiveId++; - _LastPickedPrimitiveId %= result.size (); - - // Array - std::vector selectPrimitive; - selectPrimitive.push_back (result[_LastPickedPrimitiveId]); - selectPrimitives (selectPrimitive, true); - } - else - { - // Over something selected ? - uint prim; - for (prim=0; primisSelectionLocked ()) - { - // Is selected ? - nlassert ((uint)result[prim].XSubPrim < result[prim].Primitive->getNumVector ()); - if (result[prim].Primitive->getPrimVector ()[result[prim].XSubPrim].Selected) - break; - } - else - { - // Selected ? - if (getPrimitiveEditor(result[prim].Primitive)->getSelected()) - break; - } - } - - // Over something selected ? - if (prim < result.size ()) - { - _ClickedSelected = true; - } - else - { - // Next primitives - _LastPickedPrimitiveId++; - _LastPickedPrimitiveId %= result.size (); - - // Select the primitive - std::vector selectPrimitive; - selectPrimitive.push_back (result[_LastPickedPrimitiveId]); - selectPrimitives (selectPrimitive, false); - } - } - } - - // Update selection - UpdateSelection (); - - // Over something selected ? - result.clear (); - if (pickPoint (pickPosMin, result, true) && (button == Left)) - { - // Translate or rotate ? - switch (_MainFrame->getTransformMode ()) - { - case CMainFrame::Move: - { - nlassert (_TranformAction == NULL); - - // Add a new action - CActionMove *moveAction = new CActionMove (_MainFrame->isSelectionLocked ()); - _TranformAction = moveAction; - moveAction->setTranslation (CVector::Null); - moveAction->redo (); - } - break; - case CMainFrame::Rotate: - case CMainFrame::Turn: - { - nlassert (_TranformAction == NULL); - - // Get the pivot - CVector pivot; - if (getSelectedAverage (pivot)) - { - // Add a new action - CActionRotate *moveAction = new CActionRotate (_MainFrame->isSelectionLocked (), pivot); - _TranformAction = moveAction; - moveAction->setAngle (0, false, false); - moveAction->redo (); - } - } - break; - case CMainFrame::Scale: - case CMainFrame::Radius: - { - nlassert (_TranformAction == NULL); - - // Get the pivot - CVector pivot; - if (getSelectedAverage (pivot)) - { - // Add a new action - CActionScale *moveAction = new CActionScale (_MainFrame->isSelectionLocked (), pivot); - _TranformAction = moveAction; - moveAction->setScale (1, false, false); - moveAction->redo (); - } - } - break; - } - } - } - else - { - if (_MainFrame->isSelectionLocked ()) - { - nlassert (_TranformAction == NULL); - - // Update selection - UpdateSelection (); - - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Primitive ? - if (locator.Primitive) - { - // Hidden ? - if (isPrimitiveVisible (locator.Primitive)) - { - // Path or zone ? - if (dynamic_cast(locator.Primitive) || dynamic_cast(locator.Primitive)) - { - // The locator - locator.XSubPrim = locator.Primitive->getNumVector ()-1; - - // Add a new action - doc->addModification (new CActionAddVertex (locator, pickPosMin)); - - // Select it - locator.XSubPrim++; - doc->addModification (new CActionUnselectAllSub ()); - doc->addModification (new CActionSelectSub (locator)); - } - } - } - ite++; - } - - // Set the transform mode - nlassert (_TranformAction == NULL); - - // Add a new action - CActionMove *moveAction = new CActionMove (_MainFrame->isSelectionLocked ()); - _TranformAction = moveAction; - moveAction->setTranslation (CVector::Null); - moveAction->redo (); - } - } - - // Left click ? - if (button == Left) - { - // No action actived ? - if (!_TranformAction && (_MainFrame->getTransformMode () != CMainFrame::Select) ) - { - // *** Try to add vertices in sub mode - - // Are we in sub mode ? - if (_MainFrame->isSelectionLocked ()) - { - // Pick the vertex before the clicked edge - std::vector result; - if (pickEdgePoint (pickPosMin, result)) - { - // Add a vertex in the first segment - doc->addModification (new CActionAddVertex (result[0], pickPosMin)); - - // Select it - result[0].XSubPrim++; - doc->addModification (new CActionUnselectAllSub ()); - doc->addModification (new CActionSelectSub (result[0])); - - // Set the transform mode - nlassert (_TranformAction == NULL); - - // Add a new action - CActionMove *moveAction = new CActionMove (_MainFrame->isSelectionLocked ()); - _TranformAction = moveAction; - moveAction->setTranslation (CVector::Null); - moveAction->redo (); - } - } - } - - // No action performed ? - if (!_TranformAction) - { - // Remove old selection - drawSelection (); - _DrawSelection = true; - } - } - else - { - // Update selection - UpdateSelection (); - // we stop the modifications before opening the popupmenu (otherwise, it crashes on the plugin !) - EndModification = true; - doc->endModification (); - - // Right - CPoint point2 = point; - ClientToScreen (&point2); - _MainFrame->createContextMenu (_MainFrame, point2, true); - - // No more button - _MouseRightDown = false; - _MouseLeftDown = false; - _MouseMidDown = false; - updateMouseMode (nFlags); - } - } - } - - // Mode Transition - if (_MouseMode == DrawTransition) - { - _MainFrame->_ZoneBuilder->addTransition (_CurPos); - _LastX = (sint32)floor (_CurPos.x / _CellSize); - _LastY = (sint32)floor (_CurPos.y / _CellSize); - } - - // Plugin position control - if (_MouseMode == PluginMove) - { - _MainFrame->_PositionControl = _CurPos; - if (_MainFrame->_CurrentPlugin) - { - _MainFrame->_CurrentPlugin->positionMoved(_CurPos); - // invalide display to update cursor position - _MainFrame->Invalidate(FALSE); - } - } - - // End of an undo stack element - if (!EndModification) - { - doc->endModification (); - } - - _MouseMoved = false; - _LastMousePos = point; - - // Update data - _MainFrame->updateData (); -} - -// *************************************************************************** -void CDisplay::OnLButtonDblClk (UINT nFlags, CPoint point) -{ - if (!Interactif) - return; - - if (DontUse3D) - return; - - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; - if (_MouseRightDown || _MouseMidDown) - return; - - _CurPos = convertToWorld (point); - - // Begin of an undo stack element - getDocument ()->beginModification (); - - if (_MainFrame->_Mode == 2) // Mode Transition - { - _MainFrame->_ZoneBuilder->addTransition (_CurPos); - _LastX = (sint32)floor (_CurPos.x / _CellSize); - _LastY = (sint32)floor (_CurPos.y / _CellSize); - } - - if (_MainFrame->_Mode == 1) // Mode Logic - { - } - - // End of an undo stack element - getDocument ()->endModification (); - - _LastMousePos = point; - - // Update data - _MainFrame->updateData (); -} - -// *************************************************************************** - -void CDisplay::selectPrimitives (const std::vector &result, bool addSelection) -{ - // The docmuent - CWorldEditorDoc *doc = getDocument (); - - // Ctrl ? - if (!addSelection) - { - if (_MainFrame->isSelectionLocked ()) - { - // Unselect - doc->addModification (new CActionUnselectAllSub ()); - } - else - { - // Unselect - doc->addModification (new CActionUnselectAll ()); - } - } - - // Backup selected flag - std::vector selected (result.size ()); - - // For each primitive - uint i; - for (i=0; iisSelectionLocked ()) - { - // Check the vertex flag - nlassert ((uint)result[i].XSubPrim < result[i].Primitive->getNumVector ()); - selected[i] = result[i].Primitive->getPrimVector ()[result[i].XSubPrim].Selected; - } - else - { - // Get selection property -// IProperty *prop; - selected[i] = getPrimitiveEditor(result[i].Primitive)->getSelected(); - } - } - - // For each primitive - for (i=0; iisSelectionLocked ()) - { - // Select it - doc->addModification (new CActionUnselectSub (result[i])); - } - else - { - // Select it - doc->addModification (new CActionUnselect (result[i])); - } - } - } - else - { - // Select it - if (_MainFrame->isSelectionLocked ()) - { - doc->addModification (new CActionSelectSub (result[i])); - } - else - { - doc->addModification (new CActionSelect (result[i])); - } - } - } -} - -// *************************************************************************** - -void CDisplay::OnLButtonUp (UINT nFlags, CPoint point) -{ - if (!Interactif) - return; - - if (DontUse3D) - return; - - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; - - // Release capture - if (!_MouseMidDown && _MouseLeftDown && !_MouseRightDown) - ReleaseCapture (); - - // Mouse was down ? - if (_MouseMode == TransformPrimitive) - { - // Get the document - CWorldEditorDoc *doc = getDocument (); - - _CurPos = convertToWorld (point); - - // Begin of an undo stack element - getDocument ()->beginModification (); - - // Transform ? - if (_SelectionMin != _SelectionMax) - { - if (_TranformAction) - { - // Add the action - _TranformAction->undo (); - doc->addModification (_TranformAction); - - // Reset action - _TranformAction = NULL; - } - else - { - // Erase selection - drawSelection (); - _DrawSelection = false; - - // Pick position - CVector pickPosMin ((float)_SelectionMin.x, (float)(_WindowHeight-_SelectionMin.y-1), 0); - CVector pickPosMax ((float)_SelectionMax.x, (float)(_WindowHeight-_SelectionMax.y-1), 0); - if (pickPosMin.x > pickPosMax.x) - { - float temp = pickPosMin.x; - pickPosMin.x = pickPosMax.x; - pickPosMax.x = temp; - } - if (pickPosMin.y > pickPosMax.y) - { - float temp = pickPosMin.y; - pickPosMin.y = pickPosMax.y; - pickPosMax.y = temp; - } - - // In world - pixelToWorld (pickPosMin); - pixelToWorld (pickPosMax); - - std::vector result; - if (pickRect (pickPosMin, pickPosMax, result, true)) - { - // Select it - selectPrimitives (result, (nFlags & MK_CONTROL) != 0); - } - else - { - // No ctrl ? - if ((nFlags & MK_CONTROL) == 0) - { - // Unselect all - if (_MainFrame->isSelectionLocked ()) - { - doc->addModification (new CActionUnselectAllSub ()); - } - else - { - doc->addModification (new CActionUnselectAll ()); - } - } - } - } - } - else - { - if (_TranformAction) - { - // Reset action - delete _TranformAction; - _TranformAction = NULL; - } - else - { - // Erase selection - drawSelection (); - _DrawSelection = false; - } - - // Pick position - CVector pickPosMin ((float)_SelectionMin.x, (float)(_WindowHeight-_SelectionMin.y-1), 0); - CVector pickPosMax ((float)_SelectionMax.x, (float)(_WindowHeight-_SelectionMax.y-1), 0); - if (pickPosMin.x > pickPosMax.x) - { - float temp = pickPosMin.x; - pickPosMin.x = pickPosMax.x; - pickPosMax.x = temp; - } - if (pickPosMin.y > pickPosMax.y) - { - float temp = pickPosMin.y; - pickPosMin.y = pickPosMax.y; - pickPosMax.y = temp; - } - - // In world - pixelToWorld (pickPosMin); - - // Pick - std::vector result; - bool picked = pickPoint (pickPosMin, result, false); - - - // Pick a primitive that exist - if (_ClickedSelected) - { - // Should e something under the mouse - nlassert (picked); - - // Look for a non selected primitive -// IProperty *prop; - uint prim; - for (prim=0; primgetSelected()) - break; - } - - // Should be over a selected primitive - nlassert (_LastPickedPrimitiveId != result.size ()); - - // Array - std::vector selectPrimitive; - selectPrimitive.push_back (result[_LastPickedPrimitiveId]); - selectPrimitives (selectPrimitive, false); - } - - // Something under the mouse ? - if (!picked) - { - // No ctrl ? - if ((nFlags & MK_CONTROL) == 0) - { - // Unselect all - if (_MainFrame->isSelectionLocked ()) - { - doc->addModification (new CActionUnselectAllSub ()); - } - else - { - doc->addModification (new CActionUnselectAll ()); - } - } - } - } - - // End of an undo stack element - getDocument ()->endModification (); - } - - _MouseLeftDown = false; - - // Update mouse mode - updateMouseMode (nFlags); - - // Invalidate cursor - invalidateCursor (); - - // Update data - _MainFrame->updateData (); - nlassert (_DrawSelection == false); -} - -// *************************************************************************** - -void CDisplay::OnRButtonUp (UINT nFlags, CPoint point) -{ - if (DontUse3D) - return; - - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; - _MouseRightDown = false; - - // Release capture - if (!_MouseMidDown && !_MouseLeftDown && _MouseRightDown) - ReleaseCapture (); - - // Update mouse mode - updateMouseMode (nFlags); - - // Invalidate cursor - invalidateCursor (); - - // Update data - _MainFrame->updateData (); -} - -// *************************************************************************** - -void CDisplay::drawSelection () -{ - // Get the DC - CDC *pDC = GetDC (); - - // Rect - RECT rect; - rect.left = std::min (_SelectionMin.x, _SelectionMax.x); - rect.top = std::min (_SelectionMin.y, _SelectionMax.y); - rect.right = std::max (_SelectionMin.x, _SelectionMax.x); - rect.bottom = std::max (_SelectionMin.y, _SelectionMax.y); - - // Draw a xor focus rect - pDC->DrawFocusRect (&rect); - - // Release the DC - ReleaseDC (pDC); -} - -// *************************************************************************** -void CDisplay::OnMouseMove (UINT nFlags, CPoint point) -{ - if (!Interactif) - return; - - if (DontUse3D) - return; - - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; - - if (_MainFrame->GetActiveWindow() == _MainFrame) - SetFocus(); - - if ((_LastMousePos.x == point.x) && (_LastMousePos.y == point.y)) - return; - - _MouseMoving = true; - - // Begin of an undo stack element - CWorldEditorDoc *doc = getDocument (); - if (doc) - { - doc->beginModification (); - } - - // Get the current position in world - _CurPos = convertToWorld (point); - _MouseMoved = true; - - const bool shiftPushed = (nFlags & MK_SHIFT) != 0; - const bool altPushed = (GetAsyncKeyState (VK_MENU) & 0x8000) != 0; - const bool ctrlPushed = ( ( GetAsyncKeyState (VK_LCONTROL) | GetAsyncKeyState (VK_RCONTROL) ) & 0x8000 ) != 0; - switch (_MouseMode) - { - // Mode Zone - case DrawTiles: - { - sint32 x = (sint32)floor (_CurPos.x / _CellSize); - sint32 y = (sint32)floor (_CurPos.y / _CellSize); - if ((x!=_LastX)||(y!=_LastY)) - { - _LastX = x; - _LastY = y; - _MainFrame->_ZoneBuilder->add (_CurPos); - } - } - break; - case RemoveTiles: - { - sint32 x = (sint32)floor (_CurPos.x / _CellSize); - sint32 y = (sint32)floor (_CurPos.y / _CellSize); - if ((x!=_LastX)||(y!=_LastY)) - { - _LastX = x; - _LastY = y; - _MainFrame->_ZoneBuilder->del (_CurPos); - } - } - break; - case TransformPrimitive: - { - // Tranform mode ? - if (_TranformAction) - { - // New position - _SelectionMax = point; - - switch (_MainFrame->getTransformMode ()) - { - case CMainFrame::Move: - { - // Get the action - CActionMove *moveAction = dynamic_cast (_TranformAction); - if (moveAction) - { - CVector pickPosMin ((float)_SelectionMin.x, (float)(_WindowHeight-_SelectionMin.y-1), 0); - CVector pickPosMax ((float)_SelectionMax.x, (float)(_WindowHeight-_SelectionMax.y-1), 0); - pixelToWorld (pickPosMin); - pixelToWorld (pickPosMax); - - // Set the new translation - CVector translation = pickPosMax; - translation -= pickPosMin; - translation.z = 0; - - // Undo the action - moveAction->undo (); - - // Set the new translation - moveAction->setTranslation (translation); - - // Redo the action - moveAction->redo (); - } - } - break; - case CMainFrame::Rotate: - case CMainFrame::Turn: - { - CActionRotate *moveAction = dynamic_cast (_TranformAction); - if (moveAction) - { - // Set the new rotation - float angle = (_SelectionMin.x - _SelectionMax.x + _SelectionMax.y - _SelectionMin.y) * ROTATE_PER_PIXEL; - - // Undo the action - moveAction->undo (); - - // Set the new translation - const bool turn = _MainFrame->getTransformMode () == CMainFrame::Turn || ctrlPushed || altPushed || shiftPushed; - moveAction->setAngle (angle, _MainFrame->getTransformMode ()==CMainFrame::Rotate, turn); - - // Redo the action - moveAction->redo (); - } - } - break; - case CMainFrame::Scale: - case CMainFrame::Radius: - { - // Get the action - CActionScale *moveAction = dynamic_cast (_TranformAction); - if (moveAction) - { - // Set the new scale - float scale = (_SelectionMin.x - _SelectionMax.x + _SelectionMax.y - _SelectionMin.y) * SCALE_PER_PIXEL + 1.f; - - // Undo the action - moveAction->undo (); - - // Set the new translation - const bool radius = _MainFrame->getTransformMode () == CMainFrame::Radius || ctrlPushed || altPushed || shiftPushed; - moveAction->setScale (std::max (0.001f, scale), _MainFrame->getTransformMode ()==CMainFrame::Scale, radius); - - // Redo the action - moveAction->redo (); - } - } - break; - } - } - else - { - // Remove old selection - nlassert (_DrawSelection); - drawSelection (); - - // New position - _SelectionMax = point; - - // Draw new selection - drawSelection (); - } - } - break; - // Plugin position control - case PluginMove: - { - _MainFrame->_PositionControl = _CurPos; - if (_MainFrame->_CurrentPlugin) - { - _MainFrame->_CurrentPlugin->positionMoved(_CurPos); - _MainFrame->Invalidate(FALSE); - } - } - break; - // View displacement - case DragView: - { - ::CRect rect; - GetClientRect (rect); - - float dx = ((float)(point.x-_LastMousePos.x)) / ((float)rect.Width()); - float dy = -((float)(point.y-_LastMousePos.y)) / ((float)rect.Height()); - - _Offset.x -= dx * (_InitViewMax.x-_InitViewMin.x) * _Factor; - _Offset.y -= dy * (_InitViewMax.y-_InitViewMin.y) * _Factor; - - invalidateLeftView (); - } - break; - case ZoomView: - { - ::CRect rect; - GetClientRect (rect); - - float dx = ((float)(point.x-_LastMousePos.x)) / ((float)rect.Width()); - float dy = -((float)(point.y-_LastMousePos.y)) / ((float)rect.Height()); - if (DontUse3D) - return; - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; - setFactor (_Factor*(float)pow(4.0f, dx+dy), true, _OrigineZoom); - } - break; - } - - // End of an undo stack element - if (doc) - doc->endModification (); - - // Nothing pushed ? - bool displayInfo = false; - if (_MouseMode == Nothing) - { - if (_MainFrame->_Mode == 1) // Mode Logic - { - // Pick pos - CVector pickPos ((float)point.x, (float)(_WindowHeight-point.y-1), 0); - pixelToWorld (pickPos); - - // Pick something.. - std::vector result; - if (pickPoint (pickPos, result, false)) - { - // Point ? - uint i; - for (i=0; i (result[i].Primitive) || dynamic_cast (result[i].Primitive)) - break; - } - - // Not found ? - if (i == result.size ()) - i = 0; - - // Set the name - _MainFrame->displayInfo (result[i].getPathName ().c_str ()); - displayInfo = true; - } - } - } - - // if we have to show the Collisions map, we simply Invalidate the window - if (_MainFrame->showCollisions()) - { - sint32 x, y; - x = (sint32)floor(2*_CurPos.x / _CellSize); - y = (sint32)floor(2*_CurPos.y / _CellSize); - - if (x != _lastXCollisionTextureMove || y != _lastYCollisionTextureMove) - { - _lastXCollisionTextureMove = x; - _lastYCollisionTextureMove = y; - Invalidate(FALSE); - } - } - - // No display info ? - if (!displayInfo) - _MainFrame->displayInfo (""); - - _LastMousePos = point; - - // Invalidate mouse cursor - invalidateCursor (); - - // Display the current position in the world in the status bar - _MainFrame->displayStatusBarInfo (); - - // Update data - _MainFrame->updateData (); -} - -// *************************************************************************** -void CDisplay::OnChar (UINT nChar, UINT nRepCnt, UINT nFlags) -{ - /* todo remov all this and set normal accelerator */ - if (DontUse3D) - return; - - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; - - if (nChar == 32) // Space bar == middle mouse button - { - _MouseMidDown = true; - updateMouseMode (nFlags); - } - - /* if ((nChar == 'g') || (nChar == 'G')) - { - _MainFrame->onMenuViewGrid (); - } */ - - if ((nChar == 't') || (nChar == 'T')) - { - if (_MainFrame->_Mode == 2) - _MainFrame->onMenuModeZone (); - else if (_MainFrame->_Mode == 0) - _MainFrame->onMenuModeTransition (); - /* else if (_MainFrame->_Mode == 1) - _MainFrame->transfert (_MainFrame->_PRegionBuilder.getSelPBName()); */ - } - - // Georges binds - if ((nChar == 'l') || (nChar == 'L')) - { - /* if (_MainFrame->_Mode == 1) - _MainFrame->lineDown (); */ - } - if ((nChar == 'o') || (nChar == 'O')) - { - /* if (_MainFrame->_Mode == 1) - _MainFrame->lineUp (); */ - } - - // Escape stop plugin position control. - if (nChar == 27 && _MainFrame->_Mode == 3) - { - if (_MainFrame->_CurrentPlugin != 0) - { - _MainFrame->_CurrentPlugin->lostPositionControl(); - _MainFrame->_CurrentPlugin = 0; - } - _MainFrame->_Mode = _MainFrame->_LastMode; - _MainFrame->Invalidate(FALSE); - } -} - -// *************************************************************************** -void CDisplay::OnKeyUp (UINT nChar, UINT nRepCnt, UINT nFlags) -{ - if (DontUse3D) - return; - - if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; - if (nChar == 32) - { - _MouseMidDown = false; - updateMouseMode (nFlags); - } - - // Invalidate cursor - invalidateCursor (); - - // Update data - _MainFrame->updateData (); -} - -// *************************************************************************** -void CDisplay::OnSize (UINT nType, int cx, int cy) -{ - if (nType == SIZE_RESTORED) - { - if ((cx > 25) && (cy > 25)) - { - float xRatio = (float)(cx) / 800.0f; - float yRatio = (float)(cy) / 800.0f; - - _InitViewMax = CVector (5.5f*xRatio*_CellSize, 5.5f*yRatio*_CellSize, 0.0f); - _InitViewMin = CVector (-5.5f*xRatio*_CellSize, -5.5f*yRatio*_CellSize, 0.0f); - } - } - invalidateLeftView (); -} - -// *************************************************************************** -LRESULT CDisplay::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) -{ - // TODO: Add your specialized code here and/or call the base class - if (!DontUse3D && CNELU::Driver) - { - typedef void (*winProc)(NL3D::IDriver *drv, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - winProc drvWndProc= (winProc)CNELU::Driver->getWindowProc(); - drvWndProc (CNELU::Driver, m_hWnd, message, wParam, lParam); - } - - return CView::WindowProc(message, wParam, lParam); -} - -// *************************************************************************** - -BOOL CDisplay::OnEraseBkgnd (CDC *pC) -{ - return TRUE; -} - -// *************************************************************************** - -CDisplay *getDisplay () -{ - CMainFrame *mainFrame = getMainFrame (); - if (mainFrame) - return dynamic_cast(getMainFrame ()->m_wndSplitter.GetPane(0,0)); - else - return NULL; -} - - -// *************************************************************************** -BOOL CDisplay::PreTranslateMessage(MSG *pmsg) -{ - if (pmsg->message == WM_KEYDOWN) - { - if (pmsg->wParam >= VK_LEFT && pmsg->wParam <=VK_DOWN) - { - CToolsLogic *toolWnd = dynamic_cast(getMainFrame ()->m_wndSplitter.GetPane(0,1)); - - if (toolWnd) - { - toolWnd->GetTreeCtrl()->SendMessage(WM_KEYDOWN, pmsg->wParam, 0); - } - - return TRUE; - - } - } - - return CView::PreTranslateMessage(pmsg); -} - -// *************************************************************************** - -void CDisplay::updateCursor () -{ - if (!_ValidMouse) - { - // Choose a cursor - HCURSOR cursor = LoadCursor (NULL, IDC_ARROW); - - bool ctrlPushed = ( ( GetAsyncKeyState (VK_LCONTROL) | GetAsyncKeyState (VK_RCONTROL) ) & 0x8000 ) != 0; - - // No click - switch (_MouseMode) - { - case Nothing: - { - // Mode prim ? - if (_MainFrame->_Mode == 1) - { - CVector pickPosMin ((float)_LastMousePos.x, (float)(_WindowHeight-_LastMousePos.y-1), 0); - pixelToWorld (pickPosMin); - - bool actionActived = false; - - // Add sub element vertex mode ? - bool addPointSub = (_MainFrame->getTransformMode () == CMainFrame::AddPoint) && (_MainFrame->isSelectionLocked ()); - if ( !addPointSub ) - { - if (ctrlPushed) - { - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_COPY)); - } - else - { - // Pick a primitive that exist - std::vector result; - if (pickPoint (pickPosMin, result, false)) - { - if (_MainFrame->getTransformMode () != CMainFrame::Select) - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_MOVE + _MainFrame->getTransformMode () - 1)); - actionActived = true; - } - } - - // Over something selected ? - /*result.clear (); - if (pickPoint (pickPosMin, result, true)) - { - // Translate or rotate ? - switch (_MainFrame->getTransformMode ()) - { - case CMainFrame::Move: - { - } - break; - case CMainFrame::Rotate: - { - } - break; - case CMainFrame::Turn: - { - } - break; - case CMainFrame::Scale: - { - } - break; - } - actionActived = true; - }*/ - } - else - { - if (_MainFrame->isSelectionLocked ()) - { - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_ADD_POINT)); - } - } - - // No action actived ? - if (!actionActived) - { - // *** Try to add vertices in sub mode - - // Are we in sub mode ? - if (_MainFrame->isSelectionLocked ()) - { - // Pick the vertex before the clicked edge - std::vector result; - if (pickEdgePoint (pickPosMin, result)) - { - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_INSERT_POINT)); - } - } - } - } - } - break; - - // Moved with middle click ? - case DragView: - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_HAND)); - break; - - // Moved with left click ? - case TransformPrimitive: - { - if (_TranformAction) - { - switch (_MainFrame->getTransformMode ()) - { - case CMainFrame::Move: - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_MOVE)); - break; - case CMainFrame::Rotate: - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_ROTATE)); - break; - case CMainFrame::Turn: - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_TURN)); - break; - case CMainFrame::Scale: - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_SCALE)); - break; - case CMainFrame::Radius: - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_RADIUS)); - break; - } - } - else - { - if (ctrlPushed) - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_SELECT_COPY)); - else - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_SELECT)); - } - } - break; - - // Zoom ? - case ZoomView: - cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_ZOOM)); - break; - } - - _ValidMouse = true; - - // Set the cursor - SetCursor (cursor); - } -} - -// *************************************************************************** - -void CDisplay::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) -{ - // Invalidate cursor - invalidateCursor (); - - // Update data - _MainFrame->updateData (); -} - -// *************************************************************************** - -void CDisplay::setDisplayRegion (const CVector &min, const CVector &max) -{ - // Set the new offset - _Offset = (min+max)/2; - - // Clac new factor - _Factor = std::max ((min.x-_Offset.x)/_InitViewMin.x, (min.y-_Offset.y)/_InitViewMin.y); - NLMISC::clamp (_Factor, 0.015625f, 8.0f); - - // Recalc view parameters - calcCurView(); - - // Invalidate - invalidateCursor (); - - // Invalidate left view - invalidateLeftView (); -} - -// *************************************************************************** - -void CDisplay::setDisplayCenter (const CVector ¢er, bool zoom) -{ - // Set the new offset - _Offset = center; - - if (zoom) - { - // set min view factor - _Factor = 0.015625f; - } - - // Recalc view parameters - calcCurView(); - - // Invalidate - invalidateCursor (); - - // Invalidate left view - invalidateLeftView (); -} - - -// *************************************************************************** - -void CDisplay::DrawCollisionTexture(sint32 count, float x1, float y1) -{ - if (DontUse3D) - return; - - if ((x1 >= 0) && (x1 <= 255*_CellSize) && (y1 <= 0) && (y1 >= -255*_CellSize)) - { - sint32 x2, y2; - x2 = (sint32)floor(x1 / _CellSize); - y2 = (sint32)floor(y1 / _CellSize); - - if (x2 != _lastXCollisionTexture[count] || y2 != _lastYCollisionTexture[count]) - { - // lookup in cache to see if the texture is already there - std::list::iterator first(_collisionTextureCache.begin()), last(_collisionTextureCache.end()); - CTextureFile *tex = 0; - for (; first != last; ++first) - { - if (first->PosX == x2 && first->PosY == y2) - { - // we found it, bring it in first place in the vector - tex = first->Texture; - - _collisionTextureCache.push_front(*first); - _collisionTextureCache.erase(first); - break; - } - } - - // load the texture - _lastXCollisionTexture[count] = x2; - _lastYCollisionTexture[count] = y2; - string Name; - getZoneNameFromXY(x2, y2, Name); - _collisionTexture[count] = NULL; - if (tex != NULL) - { - _collisionTexture[count] = tex; - } - else - { - string sDirBackup = NLMISC::CPath::getCurrentPath(); - - string dir = getDocument ()->getDataDir (); - if (dir.empty()) dir = _MainFrame->_ExeDir; - dir += "\\collisionmap\\"; - SetCurrentDirectory (dir.c_str()); - - if(NLMISC::CFile::fileExists(Name+".tga") || NLMISC::CFile::fileExists(Name+".png")) - { - string filename = getTextureFile(Name); - - _collisionTexture[count] = new CTextureFile; - _collisionTexture[count]->setUploadFormat(ITexture::RGB565); - // we don't want compression - _collisionTexture[count]->setAllowDegradation(false); - _collisionTexture[count]->setFilterMode(ITexture::Nearest,ITexture::NearestMipMapOff); - - _collisionTexture[count]->setFileName (filename); - _collisionTexture[count]->setReleasable (true); - _collisionTexture[count]->generate (); - - // store the texture in cache - if (_collisionTextureCache.size() > COLLISION_TEXTURE_CACHE_SIZE) - _collisionTextureCache.pop_back(); - TCollisionTextureCache ctc; - ctc.PosX = x2; - ctc.PosY = y2; - ctc.Texture = _collisionTexture[count]; - - _collisionTextureCache.push_front(ctc); - } - - NLMISC::CPath::setCurrentPath(sDirBackup); - } - } - - // Create a material - CMaterial material; - material.initUnlit (); - material.setTexture (0, _collisionTexture[count]); - material.setZFunc (CMaterial::always); - material.setZWrite (false); - - // Blend function - material.setBlend (true); - //material.setBlendFunc (CMaterial::srcalpha, CMaterial::invsrcalpha); - //material.setBlendFunc (CMaterial::srcalpha, CMaterial::one); - material.setBlendFunc (CMaterial::one, CMaterial::one); - - float minx = x2*_CellSize -0.5f; - float miny = y2*_CellSize - 0.5f; - float maxx = minx + _CellSize; - float maxy = miny + _CellSize; - -#define PIXEL_RATIO (160.0/256.0) - - // Create the vertices - std::vector vertices (2); - vertices[0].V0.x = minx; - vertices[0].V0.y = maxy; - vertices[0].V0.z = 0; - vertices[0].Uv0.U = 0; - vertices[0].Uv0.V = 0; - vertices[0].V1.x = minx; - vertices[0].V1.y = miny; - vertices[0].V1.z = 0; - vertices[0].Uv1.U = 0; - vertices[0].Uv1.V = PIXEL_RATIO; - vertices[0].V2.x = maxx; - vertices[0].V2.y = miny; - vertices[0].V2.z = 0; - vertices[0].Uv2.U = PIXEL_RATIO; - vertices[0].Uv2.V = PIXEL_RATIO; - vertices[1].V0.x = maxx; - vertices[1].V0.y = miny; - vertices[1].V0.z = 0; - vertices[1].Uv0.U = PIXEL_RATIO; - vertices[1].Uv0.V = PIXEL_RATIO; - vertices[1].V1.x = maxx; - vertices[1].V1.y = maxy; - vertices[1].V1.z = 0; - vertices[1].Uv1.U = PIXEL_RATIO; - vertices[1].Uv1.V = 0; - vertices[1].V2.x = minx; - vertices[1].V2.y = maxy; - vertices[1].V2.z = 0; - vertices[1].Uv2.U = 0; - vertices[1].Uv2.V = 0; - - // Display it - CDRU::drawTrianglesUnlit (vertices, material, *CNELU::Driver); - } -} - -// *************************************************************************** - -void CDisplay::updateMouseMode (UINT nFlags) -{ - // Zoom ? - if (_MouseMidDown || ((_MouseLeftDown) && ((GetAsyncKeyState (VK_MENU) ) & 0x8000))) - { - _MouseMode = DragView; - return; - } - - if ((_MouseLeftDown) && (nFlags&MK_SHIFT)) - { - _MouseMode = ZoomView; - _OrigineZoom = _CurPos; - return; - } - - if (_MouseRightDown) - { - // Choose the mode - switch (_MainFrame->_Mode) - { - case 0: - _MouseMode = RemoveTiles; - return; - case 1: - _MouseMode = MenuPrimitive; - return; - case 3: - _MouseMode = PluginMove; - return; - } - } - - if (_MouseLeftDown) - { - // Choose the mode - switch (_MainFrame->_Mode) - { - case 0: - _MouseMode = DrawTiles; - return; - case 1: - _MouseMode = TransformPrimitive; - return; - case 2: - _MouseMode = DrawTransition; - return; - case 3: - _MouseMode = PluginMove; - return; - } - } - - _MouseMode = Nothing; -} - -// *************************************************************************** - -void CDisplay::setFactor (float newFactor, bool follow, const CVector &position) -{ - static const float factorMin = 0.015625f; - static const float factorMax = 8.0f; - static const float logFactorMin = 0.015625f; //(float)log(0.015625f); - static const float logFactorMax = 8.0f; //(float)log(8.0f); - NLMISC::clamp (newFactor, factorMin, factorMax); - - // Follow the zoom with a drag ? - if (follow) - { - // Position delta - /*float oldPos = ((float)log(_Factor) - logFactorMin) / (logFactorMax-logFactorMin); - float newPos = ((float)log(newFactor) - logFactorMin) / (logFactorMax-logFactorMin);*/ - float oldPos = (_Factor - logFactorMin) / (logFactorMax-logFactorMin); - float newPos = (newFactor - logFactorMin) / (logFactorMax-logFactorMin); - - // Source position - if (oldPos == 0) - { - _Offset = position; - } - else - { - CVector src = (_Offset - position) / oldPos + position; - - _Offset = (position - src) * (1.f-newPos) + src; - } - } - - _Factor = newFactor; - - invalidateLeftView (); -} - -// *************************************************************************** - -void CDisplay::displayPoints () -{ - if (DontUse3D) - return; - - if (CNELU::Driver) - { - // Size of the pixel, must be > 0.5 meter - uint32 width, height; - sint32 step = 1; - float xsize = 1.0f; - CNELU::Driver->getWindowSize (width, height); - if (width == 0) - return; - if ( (_CurViewMax.x-_CurViewMin.x)/(float)width > 0.25f*16*16 ) - return; - if ( (_CurViewMax.x-_CurViewMin.x)/(float)width > 0.25f*16 ) - { - step = 256; - xsize = 64.0f; - } - else if ( (_CurViewMax.x-_CurViewMin.x)/(float)width > 0.25f ) - { - step = 16; - xsize = 4.0f; - } - - { - initRenderProxy (); - // Setup matrix - setupWorldMatrixAndFrustum (); - - sint startX = (sint)(_CurViewMin.x) & (~(step-1)); - sint startY = (sint)(_CurViewMin.y) & (~(step-1)); - sint endX = (sint)(_CurViewMax.x) & (~(step-1)); - sint endY = (sint)(_CurViewMax.y) & (~(step-1)); - if (startX > endX) swap(startX, endX); - if (startY > endY) swap(startY, endY); - endX++; - endY++; - sint x, y; - for (y=startY; ygetText (text); - return false; -} - -// *************************************************************************** - -bool CDisplay::getActionHelp (string &text) -{ - if (_TranformAction) - return _TranformAction->getHelp (text); - return false; -} - -// *************************************************************************** - -void CDisplay::setLayerTexture(uint primitiveLayer, CPrimTexture *tex) -{ - nlassert(primitiveLayer < NUM_PRIM_LAYER); - _ProxyTexture[primitiveLayer] = tex; -} - - -// *************************************************************************** - -void CPrimTexture::buildFromFile(const std::string &filename) -{ - // Load tex size - std::string path = CPath::lookup(filename, false, false); - _Width = _Height = 0; - if (!path.empty()) - { - try - { - uint32 width, height; - NLMISC::CBitmap::loadSize(path, width, height); - _Width = (uint) width; - _Height = (uint) height; - } - catch (NLMISC::EStream) - { - nlwarning("Couldn't retrieve size for %s", filename.c_str()); - } - } - NL3D::CTextureFile *tex = new NL3D::CTextureFile(filename); - _Texture = tex; - _Texture->setFilterMode(NL3D::ITexture::Nearest, NL3D::ITexture::NearestMipMapOff); -} - - -// *************************************************************************** - -void CPrimTexture::buildFromNLBitmap(const NLMISC::CBitmap &bm) -{ - _Width = _Height = 0; - class CTextureFromNLBitmap : public NL3D::ITexture - { - public: - NLMISC_DECLARE_CLASS(CTextureFromNLBitmap); - NLMISC::CBitmap _SrcBM; - virtual void doGenerate(bool async = false) - { - (NLMISC::CBitmap &) *this = _SrcBM; - } - }; - CTextureFromNLBitmap *tfbm = new CTextureFromNLBitmap; - tfbm->_SrcBM = bm; - _Texture = tfbm; - _Texture->setFilterMode(NL3D::ITexture::Nearest, NL3D::ITexture::NearestMipMapOff); - _Width = bm.getWidth(); - _Height = bm.getHeight(); -} - - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" +#include "display.h" +#include "world_editor_doc.h" +#include "world_editor.h" +#include "editor_primitive.h" +#include "tools_logic.h" +#include +#include + +#include "main_frm.h" +#include "action.h" +#include "pacs.h" + +#include "nel/misc/path.h" +#include "nel/misc/bitmap.h" + +using namespace std; +using namespace NL3D; +using namespace NLMISC; +using namespace NLLIGO; + + +extern bool DontUse3D; + +// Color definition + +#define DEFAULT_ARROW_PRIMITIVE_COLOR (CRGBA (128, 0, 0, 255)) +#define DEFAULT_DOT_PRIMITIVE_COLOR (CRGBA (0, 0, 0, 255)) +#define SELECTED_PRIMITIVE_COLOR (CRGBA (255, 255, 255, 128)) +#define SELECTED_ARROW_PRIMITIVE_COLOR (CRGBA (255, 0, 0, 255)) +#define SELECTED_DOT_PRIMITIVE_COLOR (CRGBA (255, 255, 0, 255)) +#define SELECTED_DOT_COLOR (CRGBA (255, 0, 0, 255)) +#define LINK_LINE_COLOR (CRGBA (255, 255, 255, 128)) + +// Size definition + +#define POINT_ARROW_LINE_SIZE (20.f) +#define POINT_ARROW_HEAD_SIZE (8.f) +#define POINT_DOT_SIZE (3.f) + +// Circle + +#define CIRCLE_SEGMENT_SIZE 20 +#define CIRCLE_MIN_SEGMENT_COUNT 8 + +// Pick definition +#define PICK_DOT_SIZE (10) +#define PICK_PATH_SIZE (10) +#define LINK_LINE_SIZE (2) + +// Rotate per pixel +#define ROTATE_PER_PIXEL (2.f*(float)Pi/640.f) + +// Scale per pixel +#define SCALE_PER_PIXEL (4.f/640.f) + +// *************************************************************************** + +/* + +Primitive mouse state machine +----------------------------- + +LClickDown: + + CLICKED_ON_SELECTED = false + if subobject mode and add point mode + { + add a point in selected primitives + select the new points + active move transformation mode + } + else + { + if left/right click on primitives + { + if left click + ctrl + click on primitive + { + choose a clicked primitive + toggle its selection state + } + else + { + if at least one clicked primitive is selected + { + CLICKED_ON_SELECTED = true + } + else + { + unselect all + choose the first clicked primitive + select it + } + } + } + + if left click and the mouse is over a selected primitive + { + enable selected tranformation mode + } + } + + if left click and no transformation mode actived + { + if in subobject mode and over a selected primitive edge + { + add a point on this edge + select the point + active move transformation mode + } + } + + if left click and no transformation mode actived + { + disable tranformation mode + show rect selection + } + + if right click + { + show menu + } + +LClickUp: + + if the mouse moved + { + if tranformation mode is enabled + { + make the tranformation + } + else + { + hide rect selection + make a rect selection + if nothing selected in the rect and CTRL not pushed + unselect all + } + } + else + { + if tranformation mode is enabled + { + hide rect selection + } + + if CLICKED_ON_SELECTED == true + { + choose a not selected clicked primitive + unselect all + select it + } + + if no primitive under the mouse and CTRL not pushed + { + unselect all + } + } + +*/ + + + + + + + +BEGIN_MESSAGE_MAP (CDisplay, CView) + //{{AFX_MSG_MAP(CDisplay) + ON_WM_CREATE () + ON_WM_SIZE () + ON_WM_PAINT () + ON_WM_MOUSEWHEEL () + ON_WM_MBUTTONDOWN () + ON_WM_LBUTTONDOWN () + // ON_WM_LBUTTONDBLCLK () + ON_WM_RBUTTONDOWN () + ON_WM_MBUTTONUP () + ON_WM_LBUTTONUP () + ON_WM_RBUTTONUP () + ON_WM_MOUSEMOVE () + ON_WM_CHAR () + ON_WM_KEYUP () + ON_WM_DESTROY () + ON_WM_ERASEBKGND () + ON_WM_KEYDOWN() + ON_WM_KEYUP() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// *************************************************************************** +IMPLEMENT_DYNCREATE (CDisplay, CView) + +// *************************************************************************** +CDisplay::CDisplay () +{ + _MouseMode = Nothing; + _MouseRightDown = false; + _MouseLeftDown = false; + _MouseMidDown = false; + _MouseMoved = false; + _MouseMoving = false; + _Factor = 1.0f; + _Offset = CVector(0.0f, 0.0f, 0.0f); + _DisplayGrid = true; + _LastX = _LastY = -10000; + _CtrlKeyDown = false; + _MainFrame = NULL; + _BackgroundColor = CRGBA(192,192,192,255); + _LastPickedPrimitiveId = 0; + _TranformAction = NULL; + Interactif = true; + invalidateCursor (); + _DrawSelection = false; + for (int i=0;i < 4;++i) + { + _collisionTexture[i] = NULL; + _lastXCollisionTexture[i] = 100; + _lastYCollisionTexture[i] = 100; + } + _lastXCollisionTextureMove = 100; + _lastYCollisionTextureMove = 100; + + _FontManager = new NL3D::CFontManager; + _FontManager->setMaxMemory(2000000); + _TextContext = new NL3D::CTextContext; +} + +CDisplay::~CDisplay() +{ + delete _TextContext; + delete _FontManager; +} + +// *************************************************************************** +void CDisplay::print(const ucstring &text, float x, float y, uint32 fontSize, NLMISC::CRGBA color, THotSpot hotspot) +{ + _TextContext->setColor(color); + _TextContext->setFontSize(fontSize); + _TextContext->setHotSpot((NL3D::CComputedString::THotSpot) hotspot); + uint32 width, height; + nlassert(CNELU::Driver); + CNELU::Driver->getWindowSize(width, height); + _TextContext->printAt(x / (float) width, y / (float) height, text); +} + +// *************************************************************************** +void CDisplay::print(const std::string &text, float x, float y, uint32 fontSize, NLMISC::CRGBA color, THotSpot hotspot) +{ + print(ucstring(text), x, y, fontSize, color, hotspot); +} + + +// *************************************************************************** +void CDisplay::init (CMainFrame *pMF) +{ + _MainFrame = pMF; + + if (!DontUse3D) + { + registerSerial3d (); + CScene::registerBasics (); + init3d (); + + try + { + //CNELU::init (512, 512, CViewport(), 32, true, this->m_hWnd); + //NL3D::registerSerial3d(); + CNELU::initDriver (512, 512, 32, true, this->m_hWnd); + CNELU::initScene (CViewport()); + + CNELU::Driver->forceDXTCCompression (true); + + // setMatrixMode2D11 + CFrustum f(0.0f,1.0f,0.0f,1.0f,-1.0f,1.0f,false); + CVector I(1,0,0); + CVector J(0,0,1); + CVector K(0,-1,0); + CMatrix ViewMatrix, ModelMatrix; + ViewMatrix.identity (); + ViewMatrix.setRot (I,J,K, true); + ModelMatrix.identity (); + + CNELU::Driver->setFrustum (f.Left, f.Right, f.Bottom, f.Top, f.Near, f.Far, f.Perspective); + CNELU::Driver->setupViewMatrix (ViewMatrix); + CNELU::Driver->setupModelMatrix (ModelMatrix); + CNELU::Driver->activate (); + CNELU::clearBuffers (); + CNELU::swapBuffers (); + + // init the text context + _TextContext->init(CNELU::Driver, _FontManager); + _TextContext->setFontGenerator(NLMISC::CPath::getWindowsDirectory() + "Fonts\\arial.ttf"); + _TextContext->setKeep800x600Ratio(true); + _TextContext->setShaded(true); + _TextContext->setShadeColor(NLMISC::CRGBA::Black); + } + catch(...) + { + DontUse3D = true; + } + } + + SetCurrentDirectory (pMF->_ExeDir.c_str()); +} + +// *************************************************************************** +void CDisplay::setCellSize (float size) +{ + _CellSize = size; + _InitViewMax = CVector (5.5f*_CellSize, 5.5f*_CellSize, 0.0f); + _InitViewMin = CVector (-5.5f*_CellSize, -5.5f*_CellSize, 0.0f); +} + +// *************************************************************************** +void CDisplay::setBackgroundColor (NLMISC::CRGBA &col) +{ + _BackgroundColor = col; +} + +// *************************************************************************** +NLMISC::CRGBA CDisplay::getBackgroundColor () +{ + return _BackgroundColor; +} + +// *************************************************************************** +void CDisplay::setDisplayGrid (bool bDisp) +{ + _DisplayGrid = bDisp; +} + +// *************************************************************************** +bool CDisplay::getDisplayGrid () +{ + return _DisplayGrid; +} + +// *************************************************************************** +void CDisplay::calcCurView() +{ + _CurViewMin = _InitViewMin * _Factor + _Offset; + _CurViewMax = _InitViewMax * _Factor + _Offset; + + if (DontUse3D) + return; + + // View to world matrix + CNELU::Driver->getWindowSize (_WindowWidth, _WindowHeight); + _View2World.identity (); + if ((_WindowWidth > 0) && (_WindowHeight > 0) ) + _View2World.scale (CVector ((_CurViewMax.x - _CurViewMin.x)/(float)_WindowWidth, (_CurViewMax.y - _CurViewMin.y)/(float)_WindowHeight, 1)); + _View2World.setPos (_CurViewMin); + + // World to view matrix + _World2View = _View2World; + _World2View.invert (); + +} + +// *************************************************************************** +CVector CDisplay::convertToWorld (CPoint&p) +{ + CVector ret; + ::CRect rect; + + GetClientRect (rect); + calcCurView (); + ret.x = ((float)p.x) / ((float)rect.Width()); + ret.x = ret.x*(_CurViewMax.x-_CurViewMin.x) + _CurViewMin.x; + ret.y = 1.0f - (((float)p.y) / ((float)rect.Height())); + ret.y = ret.y*(_CurViewMax.y-_CurViewMin.y) + _CurViewMin.y; + ret.z = 0.0f; + + return ret; +} + +// *************************************************************************** + +void CDisplay::renderPluginPosition() +{ + CVector p1, p2, p3, p4; + float size = 500; + + p1 = _MainFrame->_PositionControl; + p1.x = (p1.x-_CurViewMin.x) / (_CurViewMax.x-_CurViewMin.x); + p1.y = (p1.y-_CurViewMin.y) / (_CurViewMax.y-_CurViewMin.y); + + p2 = p3 = p4 = p1; + + p1.x -= size; + p1.y -= size; + p2.x += size; + p2.y += size; + p3.x -= size; + p3.y += size; + p4.x += size; + p4.y -= size; + + if (DontUse3D) + return; + + CDRU::drawLine (p1.x, p1.y, p2.x, p2.y, *CNELU::Driver, CRGBA(0,255,0,255)); + CDRU::drawLine (p3.x, p3.y, p4.x, p4.y, *CNELU::Driver, CRGBA(0,255,0,255)); + +} + +// *************************************************************************** + +void CDisplay::initRenderProxy () +{ + // Init the material (RGBA + Alpha blend) + _ProxyMaterial.initUnlit (); + _ProxyMaterial.setSrcBlend(CMaterial::srcalpha); + _ProxyMaterial.setDstBlend(CMaterial::invsrcalpha); + _ProxyMaterial.setBlend (true); + _ProxyMaterial.setColor (CRGBA(255, 255, 255, 192)); + _ProxyMaterial.setZFunc (CMaterial::always); + _ProxyMaterial.setDoubleSided(true); + + // Init the vertex buffers + for (uint i=0; isetupViewport (CViewport()); + + // View to world matrix + mtx2.identity (); + mtx.identity (); + mtx.scale (CVector (_CurViewMax.x - _CurViewMin.x, 1, _CurViewMax.y - _CurViewMin.y)); + mtx2.rotateX ((float)(-Pi/2.0)); + mtx2 *= mtx; + mtx2.setPos (CVector (_CurViewMin.x, _CurViewMin.y, 0)); + + // World to view matrix + mtx2.invert (); + CNELU::Driver->setupViewMatrix (mtx2); + + // Model matrix + mtx.identity(); + CNELU::Driver->setupModelMatrix (mtx); + + // Frustrum + CNELU::Driver->setFrustum (0.f, 1.f, 0.f, 1.f, -1.f, 1.f, false); +} + +// *************************************************************************** +void CDisplay::flushRenderProxy () +{ + if (DontUse3D) + return; + + // Setup matrix + setupWorldMatrixAndFrustum (); + + uint i; + for (i=0; iactiveVertexBuffer (_ProxyVB[i]); + CNELU::Driver->activeIndexBuffer (_ProxyPBTri[i]); + CNELU::Driver->renderTriangles (_ProxyMaterial, 0, _ProxyPBTri[i].getNumIndexes()/3); + CNELU::Driver->activeIndexBuffer (_ProxyPBLine[i]); + CNELU::Driver->renderLines (_ProxyMaterial, 0, _ProxyPBLine[i].getNumIndexes()/2); + } + + // Render points + _ProxyVBPointsAccess.unlock (); + if (_ProxyVBPoints.getNumVertices()) + { + CNELU::Driver->activeVertexBuffer (_ProxyVBPoints); + CNELU::Driver->renderRawPoints (_ProxyMaterial, 0, _ProxyVBPoints.getNumVertices()); + } + + // Render textured quads + for (i=0; i_Texture) + { + _ProxyMaterial.setTexture(0, _ProxyTexture[i]->_Texture); + } + else + { + _ProxyMaterial.setTexture(0, NULL); + } + _ProxyVBTexQuadsAccess[i].unlock(); + CNELU::Driver->activeVertexBuffer(_ProxyVBTexQuads[i]); + CNELU::Driver->renderRawQuads(_ProxyMaterial, 0, _ProxyVBTexQuads[i].getNumVertices() / 4); + } + _ProxyMaterial.setTexture(0, NULL); +} + +// *************************************************************************** + +void CDisplay::lineRenderProxy (CRGBA color, const CVector& pos0, const CVector& pos1, uint primitive) +{ + nlassert(primitive < NUM_PRIM_LAYER); + // Add two vertices + CVector p0 = pos0; + p0.z = 0; + CVector p1 = pos1; + p1.z = 0; + uint first = _ProxyVB[primitive].getNumVertices (); + if ((first+2) > _ProxyVB[primitive].capacity()) + { + _ProxyVBAccess[primitive].unlock(); + _ProxyVB[primitive].reserve (first*2); + _ProxyVB[primitive].lock (_ProxyVBAccess[primitive]); + } + _ProxyVB[primitive].setNumVertices (first + 2); + _ProxyVBAccess[primitive].setVertexCoord(first, p0); + _ProxyVBAccess[primitive].setVertexCoord(first+1, p1); + _ProxyVBAccess[primitive].setColor(first, color); + _ProxyVBAccess[primitive].setColor(first+1, color); + + uint firstIndex = _ProxyPBLine[primitive].getNumIndexes (); + if ((firstIndex+2) > _ProxyPBLine[primitive].capacity()) + { + _ProxyPBLineAccess[primitive].unlock(); + _ProxyPBLine[primitive].reserve (firstIndex*2); + _ProxyPBLine[primitive].lock (_ProxyPBLineAccess[primitive]); + } + _ProxyPBLine[primitive].setNumIndexes (firstIndex+2); + _ProxyPBLineAccess[primitive].setLine (firstIndex, first, first + 1); +} + +// *************************************************************************** + +void CDisplay::triRenderProxy (CRGBA color, const CVector& pos0, const CVector& pos1, const CVector& pos2, uint primitive) +{ + nlassert(primitive < NUM_PRIM_LAYER); + // Add three vertices + CVector p0 = pos0; + p0.z = 0; + CVector p1 = pos1; + p1.z = 0; + CVector p2 = pos2; + p2.z = 0; + uint first = _ProxyVB[primitive].getNumVertices (); + if ((first+3) > _ProxyVB[primitive].capacity()) + { + _ProxyVBAccess[primitive].unlock(); + _ProxyVB[primitive].reserve (first*2); + _ProxyVB[primitive].lock (_ProxyVBAccess[primitive]); + } + _ProxyVB[primitive].setNumVertices (first + 3); + _ProxyVBAccess[primitive].setVertexCoord(first, p0); + _ProxyVBAccess[primitive].setVertexCoord(first+1, p1); + _ProxyVBAccess[primitive].setVertexCoord(first+2, p2); + _ProxyVBAccess[primitive].setColor(first, color); + _ProxyVBAccess[primitive].setColor(first+1, color); + _ProxyVBAccess[primitive].setColor(first+2, color); + + + uint firstIndex = _ProxyPBTri[primitive].getNumIndexes (); + if ((firstIndex+3) > _ProxyPBTri[primitive].capacity()) + { + _ProxyPBTriAccess[primitive].unlock(); + _ProxyPBTri[primitive].reserve (firstIndex*2); + _ProxyPBTri[primitive].lock (_ProxyPBTriAccess[primitive]); + } + _ProxyPBTri[primitive].setNumIndexes (firstIndex+3); + _ProxyPBTriAccess[primitive].setTri (firstIndex, first, first + 1, first + 2); +} + +// *************************************************************************** + +void CDisplay::texQuadRenderProxy(const NLMISC::CQuadColorUV &quad, uint primLayer) +{ + nlassert(primLayer < NUM_PRIM_LAYER); + NL3D::CVertexBuffer &vb = _ProxyVBTexQuads[primLayer]; + NL3D::CVertexBufferReadWrite &vba = _ProxyVBTexQuadsAccess[primLayer]; + uint first = vb.getNumVertices (); + if ((first+4) > vb.capacity()) + { + vba.unlock(); + vb.reserve (first*2); + vb.lock (vba); + } + vb.setNumVertices (first + 4); + vba.setVertexCoord(first, quad.V0); + vba.setVertexCoord(first+1, quad.V1); + vba.setVertexCoord(first+2, quad.V2); + vba.setVertexCoord(first+3, quad.V3); + vba.setColor(first, quad.Color0); + vba.setColor(first+1, quad.Color1); + vba.setColor(first+2, quad.Color2); + vba.setColor(first+3, quad.Color3); + vba.setTexCoord(first, 0, quad.Uv0); + vba.setTexCoord(first + 1, 0, quad.Uv1); + vba.setTexCoord(first + 2, 0, quad.Uv2); + vba.setTexCoord(first + 3, 0, quad.Uv3); + +} + + +// *************************************************************************** + +void CDisplay::pointRenderProxy (CRGBA color, const CVector& pos0) +{ + // Add three vertices + CVector p0 = pos0; + p0.z = 0; + uint first = _ProxyVBPoints.getNumVertices (); + if ((first+1) > _ProxyVBPoints.capacity()) + { + _ProxyVBPointsAccess.unlock (); + _ProxyVBPoints.reserve (first*2); + _ProxyVBPoints.lock (_ProxyVBPointsAccess); + } + _ProxyVBPoints.setNumVertices (first + 1); + _ProxyVBPointsAccess.setVertexCoord(first, p0); + _ProxyVBPointsAccess.setColor(first, color); +} + + + +// *************************************************************************** +void CDisplay::primitiveRenderProxy(const NLLIGO::IPrimitive &primitive) +{ + drawPrimitive(&primitive, true); +} + + +// *************************************************************************** +void CDisplay::flush() +{ + flushRenderProxy(); + initRenderProxy(); +} + + +// *************************************************************************** + +void CDisplay::pixelToWorld (CVector &pixels) +{ + pixels = _View2World * pixels; +} + +void CDisplay::pixelVectorToWorld(NLMISC::CVector &pixels) +{ + pixels = _View2World.mulVector(pixels); +} + + +// *************************************************************************** + +inline float CDisplay::intToWorld (uint value) const +{ + if (_WindowWidth == 0) + return 0.0f; + return (float)value * (_CurViewMax.x - _CurViewMin.x) / _WindowWidth; +} + +// *************************************************************************** + +inline void CDisplay::worldToPixel (CVector &pixels) +{ + pixels = _World2View * pixels; + pixels.x = (float)(sint32)pixels.x; + pixels.y = (float)(sint32)pixels.y; + pixels.z = (float)(sint32)pixels.z; +} + +// *************************************************************************** +void CDisplay::worldToFloatPixel(NLMISC::CVector &pixels) +{ + pixels = _World2View * pixels; +} + +// *************************************************************************** + +void CDisplay::worldVectorToPixelVector(NLMISC::CVector &pixels) +{ + pixels = _World2View.mulVector(pixels); + pixels.x = (float)(sint32)pixels.x; + pixels.y = (float)(sint32)pixels.y; + pixels.z = (float)(sint32)pixels.z; +} + +// *************************************************************************** + +void CDisplay::worldVectorToFloatPixelVector(NLMISC::CVector &pixels) +{ + pixels = _World2View.mulVector(pixels); +} + + + +// *************************************************************************** + +bool CDisplay::isClipped (const CPrimVector *pVec, uint32 nNbVec) +{ + uint32 i; + for (i = 0; i < nNbVec; ++i) + if (pVec[i].x > _CurViewMin.x) + break; + if (i == nNbVec) + return true; // Entirely clipped + + for (i = 0; i < nNbVec; ++i) + if (pVec[i].x < _CurViewMax.x) + break; + if (i == nNbVec) + return true; + + for (i = 0; i < nNbVec; ++i) + if (pVec[i].y > _CurViewMin.y) + break; + if (i == nNbVec) + return true; + + for (i = 0; i < nNbVec; ++i) + if (pVec[i].y < _CurViewMax.y) + break; + if (i == nNbVec) + return true; + return false; // Not entirely clipped +} + +// *************************************************************************** + +bool CDisplay::isInTriangleOrEdge( double x, double y, + double xt1, double yt1, + double xt2, double yt2, + double xt3, double yt3 ) +{ + // Test vector T1X and T1T2 + double sign1 = ((xt2-xt1)*(y-yt1) - (yt2-yt1)*(x-xt1)); + // Test vector T2X and T2T3 + double sign2 = ((xt3-xt2)*(y-yt2) - (yt3-yt2)*(x-xt2)); + // Test vector T3X and T3T1 + double sign3 = ((xt1-xt3)*(y-yt3) - (yt1-yt3)*(x-xt3)); + if( (sign1 <= 0.0)&&(sign2 <= 0.0)&&(sign3 <= 0.0) ) + return true; + if( (sign1 >= 0.0)&&(sign2 >= 0.0)&&(sign3 >= 0.0) ) + return true; + return false; +} + +// *************************************************************************** + +void CDisplay::drawPrimitive (const NLLIGO::IPrimitive *primitive, bool forceDefaultDisplay) +{ + + // Configurations + const std::vector &configurations = theApp.Config.getPrimitiveConfiguration(); + + // Get the hide property + bool hide = !isPrimitiveVisible (primitive); + + // Not hide ? + if (!hide) + { + // Get the select property + bool selected = getPrimitiveEditor(primitive)->getSelected(); + + // Get a color parameter + CRGBA mainColor; + CRGBA arrowColor; + CRGBA dotColor; + CRGBA lineColor; + + // Is selected ? + if (selected) + { + mainColor = SELECTED_PRIMITIVE_COLOR; + arrowColor = SELECTED_ARROW_PRIMITIVE_COLOR; + dotColor = SELECTED_DOT_PRIMITIVE_COLOR; + } + else + { + // Get the primitive color + mainColor = theApp.Config.getPrimitiveColor (*primitive); + arrowColor = DEFAULT_ARROW_PRIMITIVE_COLOR; + dotColor = DEFAULT_DOT_PRIMITIVE_COLOR; + uint8 alpha = mainColor.A; + + // Look for the configuration + sint search = 0; + bool colorFound = false; + while ((search = theApp.getActiveConfiguration (*primitive, search)) != -1) + { + // Configuration activated ? + if (theApp.Configurations[search].Activated) + { + colorFound = true; + mainColor = configurations[search].Color; + break; + } + search++; + } + + // try to get the primitive color ? + if (!colorFound) + primitive->getPropertyByName ("Color", mainColor); + + // Restore alpha + mainColor.A = alpha; + } + + // Line color + lineColor = mainColor; + lineColor.A = 255; + + // check if there is a plug in to draw this primitive + string *className; + primitive->getPropertyByName("class", className); +// const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*className); + + std::map::iterator it; + if (!forceDefaultDisplay) + { + it = theApp.PrimitiveDisplayers.find(*className); + } + if (!forceDefaultDisplay && it != theApp.PrimitiveDisplayers.end()) + { + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (className->c_str()); + // use a plug in displayer + IPrimitiveDisplayer::TRenderContext ctx; + ctx.ShowDetail = _MainFrame->showDetails (); + ctx.Selected = selected; + ctx.MainColor = mainColor; + ctx.ArrowColor = arrowColor; + ctx.DotColor = dotColor; + ctx.LineColor = lineColor; + ctx.PrimitiveClass = primClass; + ctx.Display = this; + + it->second->drawPrimitive(primitive, ctx); + } + else + { + // use internal drawing code + + // Point primitive ? + const CPrimPointEditor *point = dynamic_cast(primitive); + if (point) + { + // Clip ? + if (!isClipped (&point->Point, 1)) + { + // Position in world + CVector center = point->Point; + worldToPixel (center); + + // Dot + CVector dot0, dot1, dot2, dot3; + dot0 = center; + dot0.x += POINT_DOT_SIZE; + dot0.y += POINT_DOT_SIZE; + dot1 = center; + dot1.x -= POINT_DOT_SIZE; + dot1.y += POINT_DOT_SIZE; + dot2 = center; + dot2.x -= POINT_DOT_SIZE; + dot2.y -= POINT_DOT_SIZE; + dot3 = center; + dot3.x += POINT_DOT_SIZE; + dot3.y -= POINT_DOT_SIZE; + + // Transform primitive + transformVector (dot0, point->Angle, center); + transformVector (dot1, point->Angle, center); + transformVector (dot2, point->Angle, center); + transformVector (dot3, point->Angle, center); + + // In world space + pixelToWorld (center); + pixelToWorld (dot0); + pixelToWorld (dot1); + pixelToWorld (dot2); + pixelToWorld (dot3); + + // Draw it + triRenderProxy (mainColor, dot0, dot1, dot2, selected?2:0); + triRenderProxy (mainColor, dot2, dot3, dot0, selected?2:0); + + // Got a radius ? + if (_MainFrame->showDetails ()) + { + // Prim class available ? + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*point); + if (primClass != NULL) + { + // Draw an arraow ? + if (primClass->ShowArrow) + { + // Position in world + center = point->Point; + worldToPixel (center); + CVector arrow = center; + CVector arrow0 = center; + arrow.x += POINT_ARROW_LINE_SIZE; + CVector arrow1 = arrow; + CVector arrow2 = arrow; + arrow0.x += POINT_ARROW_LINE_SIZE + POINT_ARROW_HEAD_SIZE; + arrow1.y += POINT_ARROW_HEAD_SIZE; + arrow2.y -= POINT_ARROW_HEAD_SIZE; + + // Transform primitive + transformVector (arrow, point->Angle, center); + transformVector (arrow0, point->Angle, center); + transformVector (arrow1, point->Angle, center); + transformVector (arrow2, point->Angle, center); + + // In world space + pixelToWorld (center); + pixelToWorld (arrow); + pixelToWorld (arrow0); + pixelToWorld (arrow1); + pixelToWorld (arrow2); + + // Draw it + lineRenderProxy (mainColor, center, arrow, selected?2:0); + triRenderProxy (arrowColor, arrow0, arrow1, arrow2, selected?2:0); + } + } + + // Have a radius ? + string radius; + if (primitive->getPropertyByName ("radius", radius)) + { + // Get it + float fRadius = (float)atof (radius.c_str ()); + + // Get the perimeter + float perimeter = 2.f*(float)Pi*fRadius; + + // Get the perimeter on the screen + perimeter *= (float)_WindowWidth / (_CurViewMax.x - _CurViewMin.x); + + // Get the segement count + perimeter /= (float)CIRCLE_SEGMENT_SIZE; + + // Clamp + if (perimeter < CIRCLE_MIN_SEGMENT_COUNT) + perimeter = CIRCLE_MIN_SEGMENT_COUNT; + + // Segment count + uint segmentCount = (uint)perimeter; + + // Draw a circle + CVector posInit = center; + posInit.x += fRadius; + CVector posPrevious = posInit; + for (uint i=1; i(primitive); + const CPrimZoneEditor *zone = dynamic_cast(primitive); + if (path || zone) + { + // Get the pointer on the points + uint pointsCount = path?path->VPoints.size ():zone->VPoints.size (); + if (pointsCount) + { + const CPrimVector *points = path?&(path->VPoints[0]):&(zone->VPoints[0]); + + // Clipped ? + if (!isClipped (points, pointsCount)) + { + // Is a zone ? + if (zone) + { + // + vector vRef; + vRef.resize(pointsCount); + + uint32 nStart; + + uint i; + for(i = 0; i < vRef.size(); ++i) + vRef[i] = i; + + nStart = 0; + while (vRef.size() > 2) + { + // Is triangle (nStart, nStart+1, nStart+2) back face ? + sint32 nP1 = vRef[nStart]; + sint32 nP2 = vRef[(nStart+1)%vRef.size()]; + sint32 nP3 = vRef[(nStart+2)%vRef.size()]; + const CVector &pos1 = points[nP1]; + const CVector &pos2 = points[nP2]; + const CVector &pos3 = points[nP3]; + if (((pos2.x-pos1.x) * (pos3.y-pos1.y) - (pos2.y-pos1.y) * (pos3.x-pos1.x)) < 0.0f) + { + // Yes -> next triangle + nStart++; + + if (nStart == vRef.size()) + break; + continue; + } + + // Is triangle (nStart, nStart+1, nStart+2) contains the other point ? + bool bInside = false; + for (i = 0; i < vRef.size(); ++i) + { + if ((vRef[i] != nP1) && (vRef[i] != nP2) && (vRef[i] != nP3)) + { + if (isInTriangleOrEdge( points[vRef[i]].x, points[vRef[i]].y, + pos1.x, pos1.y, + pos2.x, pos2.y, + pos3.x, pos3.y )) + { + bInside = true; + break; + } + } + } + + if (bInside) + { + // Yes -> next triangle + nStart++; + + if (nStart == vRef.size()) + break; + continue; + } + + // Draw the triangle + triRenderProxy (mainColor, pos1, pos2, pos3, selected?2:0); + + // Erase the point in the middle + for (i = 1+((nStart+1)%vRef.size()); i < vRef.size(); ++i) + vRef[i-1] = vRef[i]; + vRef.resize (vRef.size()-1); + nStart = 0; + } + } + + // Draw the lines + uint pt; + const CPrimVector *previous = path ? &(points[0]) : &(points[pointsCount-1]); + for (pt=path?1:0; ptisSelectionLocked ()) + { + // Draw points + for (pt=0; ptshowDetails () && (pointsCount>=2)) + { + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*path); + if (primClass != NULL) + { + if (primClass->ShowArrow) + { + // Position in world + CVector center = points[pointsCount-1]; + CVector i = center - points[pointsCount-2]; + i.z = 0; + i.normalize (); + CVector j = CVector::K ^ i; + j.normalize (); + worldToPixel (center); + CVector arrow0 = center; + CVector arrow1 = center; + CVector arrow2 = center; + arrow0 += i*POINT_ARROW_HEAD_SIZE; + arrow1 += j*POINT_ARROW_HEAD_SIZE; + arrow2 -= j*POINT_ARROW_HEAD_SIZE; + + // In world space + pixelToWorld (arrow0); + pixelToWorld (arrow1); + pixelToWorld (arrow2); + + // Draw it + triRenderProxy (arrowColor, arrow0, arrow1, arrow2, selected?2:0); + } + } + } + } + } + } + } + } + } +} + +// *************************************************************************** + +void CDisplay::drawLink (const NLLIGO::IPrimitive *first, const NLLIGO::IPrimitive *second) +{ + // Is shown ? + if (_MainFrame->showDetails () && isPrimitiveVisible (first) && isPrimitiveVisible (second)) + { + // Is a point ? + const CPrimPointEditor *pointFirst = dynamic_cast(first); + const CPrimPointEditor *pointSecond = dynamic_cast(second); + if (pointFirst && pointSecond) + { + CVector v[4]; + v[0] = pointFirst->Point; + v[1] = pointFirst->Point; + v[2] = pointSecond->Point; + v[3] = pointSecond->Point; + + uint i; + for (i=0; i<4; i++) + worldToPixel (v[i]); + + // Get the width direction + CVector dir = v[0] - v[2]; + dir.z = 0; + dir.normalize (); + dir *= (float)LINK_LINE_SIZE; + float temp = dir.x; + dir.x = dir.y; + dir.y = -temp; + v[0] -= dir; + v[1] += dir; + v[2] -= dir; + v[3] += dir; + + for (i=0; i<4; i++) + pixelToWorld (v[i]); + + // Draw a line + triRenderProxy (LINK_LINE_COLOR, v[0], v[2], v[3], 0); + triRenderProxy (LINK_LINE_COLOR, v[3], v[1], v[0], 0); + } + } +} + +// *************************************************************************** + +void CDisplay::OnDraw (CDC* pDC) +{ + if (DontUse3D) + { + // just fill the window client ara witha white brush + RECT client; + GetClientRect(&client); + pDC->SelectObject(GetStockObject(WHITE_BRUSH)); + pDC->Rectangle(&client); + return; + } + + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; + + CNELU::clearBuffers (_BackgroundColor); + + // Display the grid + calcCurView (); + + // Document + CWorldEditorDoc *doc = getDocument (); + + if (_MainFrame->showLandscape ()) + _MainFrame->_ZoneBuilder->render (_CurViewMin, _CurViewMax); + + if (_MainFrame->showLayers ()) + { + initRenderProxy (); + // Setup matrix + setupWorldMatrixAndFrustum (); + + // For each database elements + for (uint i=0; igetNumDatabaseElement (); i++) + { + // Is a landscape ? + if (doc->isLandscape (i)) + { + // Get the region + const NLLIGO::CZoneRegion ®ion = doc->getZoneRegionAbsolute (i); + float minx = (float)region.getMinX () * theApp.Config.CellSize; + float maxx = (float)(region.getMaxX ()+1) * theApp.Config.CellSize; + float miny = (float)region.getMinY () * theApp.Config.CellSize; + float maxy = (float)(region.getMaxY ()+1) * theApp.Config.CellSize; + + // Get the primitive + const NLLIGO::CPrimitives &primitives = doc->getDatabaseElements (i); + + // For each child + uint numChildren = primitives.RootNode->getNumChildren (); + for (uint j=0; jgetChild (child, j)); + + // Is it a bitmap ? + const CPrimBitmap *bitmap = dynamic_cast (child); + if (bitmap) + { + // Is shown ? + if (isPrimitiveVisible (bitmap)) + { + // Create a material + CMaterial material; + material.initUnlit (); + material.setTexture (0, bitmap->getTexture ()); + material.setZFunc (CMaterial::always); + material.setZWrite (false); + + // Blend function + string blendFunc; + if (bitmap->getPropertyByName ("blend_type", blendFunc)) + { + if (blendFunc == "additif") + { + material.setBlend (true); + material.setBlendFunc (CMaterial::one, CMaterial::one); + } + else if (blendFunc == "blend") + { + material.setBlend (true); + material.setBlendFunc (CMaterial::srcalpha, CMaterial::invsrcalpha); + } + else if (blendFunc == "blend additif") + { + material.setBlend (true); + material.setBlendFunc (CMaterial::srcalpha, CMaterial::one); + } + else if (blendFunc == "mix") + { + material.setBlend (true); + material.setBlendFunc (CMaterial::srcalpha, CMaterial::invsrcalpha); + material.texEnvArg0Alpha (0, CMaterial::Constant, CMaterial::SrcAlpha); + material.texConstantColor (0, CRGBA(0,0,0, 128)); + } + } + + // Create the vertices + std::vector vertices (2); + vertices[0].V0.x = minx; + vertices[0].V0.y = maxy; + vertices[0].V0.z = 0; + vertices[0].Uv0.U = 0; + vertices[0].Uv0.V = 0; + vertices[0].V1.x = minx; + vertices[0].V1.y = miny; + vertices[0].V1.z = 0; + vertices[0].Uv1.U = 0; + vertices[0].Uv1.V = 1; + vertices[0].V2.x = maxx; + vertices[0].V2.y = miny; + vertices[0].V2.z = 0; + vertices[0].Uv2.U = 1; + vertices[0].Uv2.V = 1; + vertices[1].V0.x = maxx; + vertices[1].V0.y = miny; + vertices[1].V0.z = 0; + vertices[1].Uv0.U = 1; + vertices[1].Uv0.V = 1; + vertices[1].V1.x = maxx; + vertices[1].V1.y = maxy; + vertices[1].V1.z = 0; + vertices[1].Uv1.U = 1; + vertices[1].Uv1.V = 0; + vertices[1].V2.x = minx; + vertices[1].V2.y = maxy; + vertices[1].V2.z = 0; + vertices[1].Uv2.U = 0; + vertices[1].Uv2.V = 0; + + + // Display it + CDRU::drawTrianglesUnlit (vertices, material, *CNELU::Driver); + } + } + } + } + } + flushRenderProxy (); + } + + if (_MainFrame->showCollisions()) + { + sint32 i; + sint32 dx, dy; + sint32 fx, fy; + i = 0; + double rx = fmod(_CurPos.x, _CellSize); + double ry = fabs(fmod(_CurPos.y, _CellSize)); + sint32 sy; + sy = 0; + + if (rx*2 < _CellSize) + { + fx = -1; + } + else + { + fx = 0; + } + + if (ry*2 < _CellSize) + { + fy = 0; + sy = 1; + } + else + { + fy = -1; + sy = 1; + } + + initRenderProxy (); + for (dy = fy;dy<=fy+sy;++dy) + { + for (dx = fx;dx<=fx+1;++dx) + { + DrawCollisionTexture(i, _CurPos.x+dx*_CellSize, _CurPos.y+dy*_CellSize); + ++i; + } + } + flushRenderProxy (); + } + + if (_MainFrame->showPACS ()) + { + initRenderProxy (); + + // Setup matrix + setupWorldMatrixAndFrustum (); + + // Draw pacs + PacsManager.displayPacs(*this); + + // Flush primitives + flushRenderProxy (); + } + + if (_MainFrame->showGrid ()) + _MainFrame->_ZoneBuilder->displayGrid (_CurViewMin, _CurViewMax); + + if (_MainFrame->showPrimitives ()) + { + // Render the primitives + + // Accelerate rendering with vertex buffer + initRenderProxy (); + + // Select the visible primitive in the quad grid + PrimitiveQuadGrid.select (_CurViewMin, _CurViewMax); + + // Parse + TPrimQuadGrid::CIterator ite = PrimitiveQuadGrid.begin(); + while (ite != PrimitiveQuadGrid.end ()) + { + // Is it a primitive or a link ? + if ((*ite).Second) + drawLink ((*ite).First, (*ite).Second); + else + drawPrimitive ((*ite).First); + ite++; + } + + // Flush primitives + flushRenderProxy (); + } + + if (!theApp.Plugins.empty()) + { + initRenderProxy (); + // plugins post render + for(uint k = 0; k < theApp.Plugins.size(); ++k) + { + theApp.Plugins[k]->postRender(*this); + } + flushRenderProxy (); + } + + + if (_MainFrame->showPoints ()) + displayPoints (); + + if (_MainFrame->_Mode == 2) // If we are in transition mode + _MainFrame->_ZoneBuilder->renderTransition (_CurViewMin, _CurViewMax); + + CNELU::Scene->render (); + + if (_MainFrame->_Mode == 3) // Disply the plugin position control ? + renderPluginPosition(); + + CNELU::swapBuffers (); + + if (_DrawSelection) + drawSelection (); +} + +// *************************************************************************** +int CDisplay::OnCreate (LPCREATESTRUCT lpCreateStruct) +{ + if (CView::OnCreate (lpCreateStruct) == -1) + return -1; + SetTimer (1, 200, NULL); + return 0; +} + +// *************************************************************************** +void CDisplay::OnDestroy () +{ + KillTimer (1); + CView::OnDestroy (); +} + +// *************************************************************************** +/*void*/BOOL CDisplay::OnMouseWheel (UINT nFlags, short zDelta, CPoint point) +{ + if (!Interactif) + return FALSE; + + if (DontUse3D) + return FALSE; + + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return FALSE; + float newFactor = _Factor; + if (zDelta < 0) + newFactor *= 2.0f; + else + newFactor /= 2.0f; + + setFactor (newFactor, true, _CurPos); + + return TRUE; +} + +// *************************************************************************** +void CDisplay::OnMButtonDown (UINT nFlags, CPoint point) +{ + if (!Interactif) + return; + + if (DontUse3D) + return; + + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; + _LastMousePos = point; + + nlassert (!_MouseMidDown); + _MouseMidDown = true; + + // Mouse capture On ! + if (!_MouseLeftDown && !_MouseRightDown) + SetCapture (); + + // Update mouse mode + updateMouseMode (nFlags); + + // Invalidate cursor + invalidateCursor (); + + // Update data + _MainFrame->updateData (); +} + +// *************************************************************************** +void CDisplay::OnMButtonUp (UINT nFlags, CPoint point) +{ + if (!Interactif) + return; + + if (DontUse3D) + return; + + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; + + // Release capture + if (_MouseMidDown && !_MouseLeftDown && !_MouseRightDown) + ReleaseCapture (); + + _MouseMidDown = false; + + // Update mouse mode + updateMouseMode (nFlags); + + // Invalidate cursor + invalidateCursor (); + + // Update data + _MainFrame->updateData (); +} + +// *************************************************************************** + +inline bool CDisplay::pickPoint (const CVector &pickPos, const CVector &point, float bias) +{ + CVector delta = pickPos; + delta -= point; + delta.z = 0; + return delta.sqrnorm () <= (bias*bias); +} + +// *************************************************************************** + +inline bool CDisplay::pickRect (const CVector &pickPosMin, const CVector &pickPosMax, const CVector &point) +{ + return ( (point.x >= pickPosMin.x) && (point.y >= pickPosMin.y) && (point.x <= pickPosMax.x) && (point.y <= pickPosMax.y)); +} + +// *************************************************************************** + +inline bool CDisplay::pickPoint (const CVector &pickPos, const CVector &v0, const CVector &v1, float bias) +{ + + // Segment vector + CVector segment = v1; + segment -= v0; + float vectorNorm = segment.norm (); + + // Segment NULL ? + if (vectorNorm == 0) + return false; + + // Normalize + segment /= vectorNorm; + + // Project + CVector tmp = pickPos; + tmp -= v0; + float dist = segment * tmp; + + // Clip + if ( (dist > -bias) && (dist < vectorNorm + bias) ) + { + // Pos on the seg + segment *= dist; + segment += v0; + segment -= pickPos; + return segment.sqrnorm () <= (bias*bias); + } + return false; +} + +// *************************************************************************** + +inline bool testValue (float t0, float t1, float v0, float v1, float t, float vMin, float vMax) +{ + if ( ((t0 < t) && (t1 >= t)) || ((t1 < t) && (t0 >= t))) + { + float v = v0 + (v1 - v0) * (t - t0) / (t1 - t0); + return (v >= vMin) && (v <= vMax); + } + return false; +} + +// *************************************************************************** + +inline bool CDisplay::pickRect (const CVector &pickPosMin, const CVector &pickPosMax, const CVector &v0, const CVector &v1) +{ + // Point inside ? + if (pickRect (pickPosMin, pickPosMax, v0) || pickRect (pickPosMin, pickPosMax, v1)) + return true; + + // Test segment + return ((testValue (v0.x, v1.x, v0.y, v1.y, pickPosMin.x, pickPosMin.y, pickPosMax.y)) || + (testValue (v0.x, v1.x, v0.y, v1.y, pickPosMax.x, pickPosMin.y, pickPosMax.y)) || + (testValue (v0.y, v1.y, v0.x, v1.x, pickPosMin.y, pickPosMin.x, pickPosMax.x)) || + (testValue (v0.y, v1.y, v0.x, v1.x, pickPosMax.y, pickPosMin.x, pickPosMax.x))); +} + +// *************************************************************************** + +bool CDisplay::getSelectedAverage (CVector &average) +{ + // Update data + UpdateSelection (); + + // Reset average + average = CVector::Null; + uint averageCount = 0; + + // Locked ? + bool locked = _MainFrame->isSelectionLocked (); + + // For each selected primitive + CWorldEditorDoc *doc = getDocument (); + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Is there a primitive at this node ? + if (locator.Primitive) + { + // Hidden ? + if (isPrimitiveVisible (locator.Primitive)) + { + // Selected ? + if (getPrimitiveEditor(locator.Primitive)->getSelected()) + { + // For each point + uint numVector = locator.Primitive->getNumVector (); + const CPrimVector *primVector = locator.Primitive->getPrimVector (); + for (uint vect=0; vect(locator.Primitive)) + { + average += primVector[vect]; + averageCount++; + } + } + } + } + } + + ite++; + } + + if (averageCount) + average /= (float)averageCount; + + return averageCount != 0; +} + +// *************************************************************************** + +bool CDisplay::pickPoint (const CVector &pickPos, std::vector &result, bool pickOnlySelected) +{ + // Clear result + result.clear (); + + float worldPickDotSize = intToWorld (PICK_DOT_SIZE); + float worldPickPathSize = intToWorld (PICK_PATH_SIZE); + + // The selection coordinate + const float maxDelta = std::max (worldPickPathSize, worldPickDotSize); + CVector minPos = pickPos - CVector (maxDelta, maxDelta, maxDelta); + CVector maxPos = pickPos + CVector (maxDelta, maxDelta, maxDelta); + + // Select the primitives + PrimitiveQuadGrid.select (minPos, maxPos); + + // Locked ? + CWorldEditorDoc *doc = getDocument (); + if (_MainFrame->isSelectionLocked ()) + { + TPrimQuadGrid::CIterator ite = PrimitiveQuadGrid.begin (); + while (ite != PrimitiveQuadGrid.end ()) + { + // Skip links + if ((*ite).Second == NULL) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, (*ite).First); + + // Selected ? + if (getPrimitiveEditor((*ite).First)->getSelected()) + { + // Hidden ? + if (isPrimitiveVisible ((*ite).First)) + { + // Pick it + const CPrimPointEditor *point = dynamic_cast ((*ite).First); + if (point) + { + // Pick it ? + if (pickPoint (pickPos, point->Point, worldPickDotSize) && (!pickOnlySelected || getPrimitiveEditor((*ite).First)->getSelected())) + { + // Add this point + result.push_back (locator); + result.back ().XSubPrim = 0; + } + } + else + { + // Pick it + const CPrimPathEditor *path = dynamic_cast ((*ite).First); + if (path) + { + // For each vertex + const uint numPt = path->VPoints.size (); + for (uint i=0; iVPoints[i], worldPickDotSize) && (!pickOnlySelected || path->VPoints[i].Selected)) + { + // Add this path + result.push_back (locator); + result.back ().XSubPrim = i; + } + } + } + else + { + // Pick it + const CPrimZoneEditor *zone = dynamic_cast ((*ite).First); + if (zone) + { + // For each vertex + const uint numPt = zone->VPoints.size (); + for (uint i=0; iVPoints[i], worldPickDotSize) && (!pickOnlySelected || zone->VPoints[i].Selected)) + { + // Add this zone + result.push_back (locator); + result.back ().XSubPrim = i; + } + } + } + } + } + } + } + } + + // Next primitive + ite++; + } + } + else + { + TPrimQuadGrid::CIterator ite = PrimitiveQuadGrid.begin (); + while (ite != PrimitiveQuadGrid.end ()) + { + // Skip links + if ((*ite).Second == NULL) + { + // Is there a primitive at this node ? + CDatabaseLocatorPointer locator; + doc->getLocator (locator, (*ite).First); + { + // Hidden ? + if (isPrimitiveVisible ((*ite).First)) + { + // Pick it + const CPrimPointEditor *point = dynamic_cast ((*ite).First); + if (point) + { + // Pick it ? + if (pickPoint (pickPos, point->Point, worldPickDotSize) && (!pickOnlySelected || getPrimitiveEditor((*ite).First)->getSelected())) + { + // Add this point + result.push_back (locator); + } + } + else + { + // Pick it + const CPrimPathEditor *path = dynamic_cast ((*ite).First); + if (path) + { + // For each segment + const uint numPt = path->VPoints.size (); + if (numPt>1) + { + for (uint i=0; iVPoints[i], path->VPoints[i+1], worldPickPathSize) && (!pickOnlySelected || getPrimitiveEditor((*ite).First)->getSelected())) + { + // Add this path + result.push_back (locator); + } + } + } + } + else + { + // Pick it + const CPrimZoneEditor *zone = dynamic_cast ((*ite).First); + if (zone) + { + // Pick it ? + if (zone->contains (pickPos) && (!pickOnlySelected || getPrimitiveEditor((*ite).First)->getSelected())) + { + // Add this path + result.push_back (locator); + } + } + } + } + } + } + } + + // Next primitive + ite++; + } + } + + return !result.empty(); +} + +// *************************************************************************** + +bool CDisplay::pickEdgePoint (const CVector &pickPos, std::vector &result) +{ + // Clear result + result.clear (); + + float worldPickPathSize = intToWorld (PICK_PATH_SIZE); + + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // The selection coordinate + CVector minPos = pickPos - CVector (worldPickPathSize, worldPickPathSize, worldPickPathSize); + CVector maxPos = pickPos + CVector (worldPickPathSize, worldPickPathSize, worldPickPathSize); + + // Select the primitives + PrimitiveQuadGrid.select (minPos, maxPos); + + TPrimQuadGrid::CIterator ite = PrimitiveQuadGrid.begin (); + while (ite != PrimitiveQuadGrid.end ()) + { + // Skip links + if ((*ite).Second == NULL) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, (*ite).First); + + // Hidden ? + if (isPrimitiveVisible ((*ite).First)) + { + // Selected ? + if (getPrimitiveEditor((*ite).First)->getSelected()) + { + // Pick it + const CPrimPathEditor *path = dynamic_cast ((*ite).First); + if (path) + { + // For each vertex + const uint numPt = path->VPoints.size (); + if (numPt > 1) + { + for (uint i=0; iVPoints[i], path->VPoints[i+1], worldPickPathSize)) + { + // Add this path + result.push_back (locator); + result.back ().XSubPrim = i; + } + } + } + } + else + { + // Pick it + const CPrimZoneEditor *zone = dynamic_cast ((*ite).First); + if (zone) + { + // For each vertex + const uint numPt = zone->VPoints.size (); + if (numPt > 1) + { + uint previous = numPt-1; + for (uint i=0; iVPoints[previous], zone->VPoints[i], worldPickPathSize)) + { + // Add this zone + result.push_back (locator); + result.back ().XSubPrim = previous; + } + + // Nex previous + previous = i; + } + } + } + } + } + } + } + + // Next primitive + ite++; + } + + return !result.empty(); +} + +// *************************************************************************** + +bool CDisplay::pickRect (const CVector &pickPosMin, const CVector &pickPosMax, std::vector &result, bool pickOnlyShown) +{ + // Clear result + result.clear (); + + // Select the primitives + PrimitiveQuadGrid.select (pickPosMin, pickPosMax); + + // Locked ? + CWorldEditorDoc *doc = getDocument (); + if (_MainFrame->isSelectionLocked ()) + { + TPrimQuadGrid::CIterator ite = PrimitiveQuadGrid.begin (); + while (ite != PrimitiveQuadGrid.end ()) + { + // Skip links + if ((*ite).Second == NULL) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, (*ite).First); + + // Selected ? + if (getPrimitiveEditor((*ite).First)->getSelected()) + { + // Hidden ? + if ((!pickOnlyShown) || (isPrimitiveVisible ((*ite).First))) + { + // Pick it + const CPrimPointEditor *point = dynamic_cast ((*ite).First); + if (point) + { + // Pick it ? + if (pickRect (pickPosMin, pickPosMax, point->Point)) + { + // Add this point + result.push_back (locator); + result.back ().XSubPrim = 0; + } + } + else + { + // Pick it + const CPrimPathEditor *path = dynamic_cast ((*ite).First); + if (path) + { + // For each vertex + const uint numPt = path->VPoints.size (); + for (uint i=0; iVPoints[i])) + { + // Add this path + result.push_back (locator); + result.back ().XSubPrim = i; + } + } + } + else + { + // Pick it + const CPrimZoneEditor *zone = dynamic_cast ((*ite).First); + if (zone) + { + // For each vertex + const uint numPt = zone->VPoints.size (); + for (uint i=0; iVPoints[i])) + { + // Add this zone + result.push_back (locator); + result.back ().XSubPrim = i; + } + } + } + } + } + } + } + } + + // Next primitive + ite++; + } + } + else + { + TPrimQuadGrid::CIterator ite = PrimitiveQuadGrid.begin (); + while (ite != PrimitiveQuadGrid.end ()) + { + // Skip links + if ((*ite).Second == NULL) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, (*ite).First); + { + // Hidden ? + if ((!pickOnlyShown) || (isPrimitiveVisible ((*ite).First))) + { + // Pick it + const CPrimPointEditor *point = dynamic_cast ((*ite).First); + if (point) + { + // Pick it ? + if (pickRect (pickPosMin, pickPosMax, point->Point)) + { + // Add this point + result.push_back (locator); + } + } + else + { + // Pick it + const CPrimPathEditor *path = dynamic_cast ((*ite).First); + if (path) + { + // For each segment + const uint numPt = path->VPoints.size (); + if (numPt>1) + { + for (uint i=0; iVPoints[i], path->VPoints[i+1])) + { + // Add this path + result.push_back (locator); + } + } + } + } + else + { + // Pick it + const CPrimZoneEditor *zone = dynamic_cast ((*ite).First); + if (zone) + { + // For each segment + const uint numPt = zone->VPoints.size (); + if (numPt>1) + { + // Last point + uint lastPt = numPt-1; + for (uint i=0; iVPoints[i], zone->VPoints[lastPt])) + { + // Add this zone + result.push_back (locator); + } + + // Next segment + lastPt = i; + } + } + } + } + } + } + } + } + + // Next primitive + ite++; + } + } + return !result.empty(); +} + +// *************************************************************************** + +void CDisplay::OnLButtonDown (UINT nFlags, CPoint point) +{ + if (!Interactif) + return; + + if (DontUse3D) + return; + + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; + + nlassert (!_MouseLeftDown); + _MouseLeftDown = true; + + // Mouse capture On ! + if (!_MouseMidDown && !_MouseRightDown) + SetCapture (); + + // Update mouse mode + updateMouseMode (nFlags); + + buttonDown (Left, nFlags, point); + + invalidateCursor (); + + // Update data + _MainFrame->updateData (); +} + +// *************************************************************************** + +void CDisplay::OnRButtonDown (UINT nFlags, CPoint point) +{ + if (!Interactif) + return; + + if (DontUse3D) + return; + + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; + + nlassert (!_MouseRightDown); + _MouseRightDown = true; + + // Mouse capture On ! + if (!_MouseMidDown && !_MouseLeftDown) + SetCapture (); + + // Update mouse mode + updateMouseMode (nFlags); + + buttonDown (Right, nFlags, point); + + invalidateCursor (); + + // Update data + _MainFrame->updateData (); +} + +// *************************************************************************** + +void CDisplay::buttonDown (TButton button, UINT nFlags, CPoint point) +{ + // this bool is used to fix a nasty bug: when a popup window appears, the message pump is called + bool EndModification = false; + _ClickedSelected = false; + CWorldEditorDoc *doc = getDocument (); + _CurPos = convertToWorld (point); + + // Begin of an undo stack element + doc->beginModification (); + + // Mode Zone + if ((_MouseMode == DrawTiles) || (_MouseMode == RemoveTiles)) + { + if (_MouseMode == DrawTiles) + _MainFrame->_ZoneBuilder->add (_CurPos); + if (_MouseMode == RemoveTiles) + _MainFrame->_ZoneBuilder->del (_CurPos); + + _LastX = (sint32)floor (_CurPos.x / _CellSize); + _LastY = (sint32)floor (_CurPos.y / _CellSize); + } + + // Cancel tranform ? + if (_TranformAction && (_MouseMode != TransformPrimitive)) + { + _TranformAction->undo (); + _TranformAction = NULL; + } + + // Mode Logic + if ((_MouseMode == TransformPrimitive) || (_MouseMode == MenuPrimitive)) + { + _SelectionMin = point; + _SelectionMax = point; + + CVector pickPosMin ((float)_SelectionMin.x, (float)(_WindowHeight-_SelectionMin.y-1), 0); + pixelToWorld (pickPosMin); + + // Left or right only + if ((button == Left) || (button == Right)) + { + // Add sub element vertex mode ? + bool addPointSub = (_MainFrame->getTransformMode () == CMainFrame::AddPoint) && (_MainFrame->isSelectionLocked ()); + if ( !addPointSub || (button == Right) ) + { + // Pick a primitive that exist + std::vector result; + if (pickPoint (pickPosMin, result, false)) + { + if ((nFlags & MK_CONTROL) != 0) + { + // Next primitives + _LastPickedPrimitiveId++; + _LastPickedPrimitiveId %= result.size (); + + // Array + std::vector selectPrimitive; + selectPrimitive.push_back (result[_LastPickedPrimitiveId]); + selectPrimitives (selectPrimitive, true); + } + else + { + // Over something selected ? + uint prim; + for (prim=0; primisSelectionLocked ()) + { + // Is selected ? + nlassert ((uint)result[prim].XSubPrim < result[prim].Primitive->getNumVector ()); + if (result[prim].Primitive->getPrimVector ()[result[prim].XSubPrim].Selected) + break; + } + else + { + // Selected ? + if (getPrimitiveEditor(result[prim].Primitive)->getSelected()) + break; + } + } + + // Over something selected ? + if (prim < result.size ()) + { + _ClickedSelected = true; + } + else + { + // Next primitives + _LastPickedPrimitiveId++; + _LastPickedPrimitiveId %= result.size (); + + // Select the primitive + std::vector selectPrimitive; + selectPrimitive.push_back (result[_LastPickedPrimitiveId]); + selectPrimitives (selectPrimitive, false); + } + } + } + + // Update selection + UpdateSelection (); + + // Over something selected ? + result.clear (); + if (pickPoint (pickPosMin, result, true) && (button == Left)) + { + // Translate or rotate ? + switch (_MainFrame->getTransformMode ()) + { + case CMainFrame::Move: + { + nlassert (_TranformAction == NULL); + + // Add a new action + CActionMove *moveAction = new CActionMove (_MainFrame->isSelectionLocked ()); + _TranformAction = moveAction; + moveAction->setTranslation (CVector::Null); + moveAction->redo (); + } + break; + case CMainFrame::Rotate: + case CMainFrame::Turn: + { + nlassert (_TranformAction == NULL); + + // Get the pivot + CVector pivot; + if (getSelectedAverage (pivot)) + { + // Add a new action + CActionRotate *moveAction = new CActionRotate (_MainFrame->isSelectionLocked (), pivot); + _TranformAction = moveAction; + moveAction->setAngle (0, false, false); + moveAction->redo (); + } + } + break; + case CMainFrame::Scale: + case CMainFrame::Radius: + { + nlassert (_TranformAction == NULL); + + // Get the pivot + CVector pivot; + if (getSelectedAverage (pivot)) + { + // Add a new action + CActionScale *moveAction = new CActionScale (_MainFrame->isSelectionLocked (), pivot); + _TranformAction = moveAction; + moveAction->setScale (1, false, false); + moveAction->redo (); + } + } + break; + } + } + } + else + { + if (_MainFrame->isSelectionLocked ()) + { + nlassert (_TranformAction == NULL); + + // Update selection + UpdateSelection (); + + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Primitive ? + if (locator.Primitive) + { + // Hidden ? + if (isPrimitiveVisible (locator.Primitive)) + { + // Path or zone ? + if (dynamic_cast(locator.Primitive) || dynamic_cast(locator.Primitive)) + { + // The locator + locator.XSubPrim = locator.Primitive->getNumVector ()-1; + + // Add a new action + doc->addModification (new CActionAddVertex (locator, pickPosMin)); + + // Select it + locator.XSubPrim++; + doc->addModification (new CActionUnselectAllSub ()); + doc->addModification (new CActionSelectSub (locator)); + } + } + } + ite++; + } + + // Set the transform mode + nlassert (_TranformAction == NULL); + + // Add a new action + CActionMove *moveAction = new CActionMove (_MainFrame->isSelectionLocked ()); + _TranformAction = moveAction; + moveAction->setTranslation (CVector::Null); + moveAction->redo (); + } + } + + // Left click ? + if (button == Left) + { + // No action actived ? + if (!_TranformAction && (_MainFrame->getTransformMode () != CMainFrame::Select) ) + { + // *** Try to add vertices in sub mode + + // Are we in sub mode ? + if (_MainFrame->isSelectionLocked ()) + { + // Pick the vertex before the clicked edge + std::vector result; + if (pickEdgePoint (pickPosMin, result)) + { + // Add a vertex in the first segment + doc->addModification (new CActionAddVertex (result[0], pickPosMin)); + + // Select it + result[0].XSubPrim++; + doc->addModification (new CActionUnselectAllSub ()); + doc->addModification (new CActionSelectSub (result[0])); + + // Set the transform mode + nlassert (_TranformAction == NULL); + + // Add a new action + CActionMove *moveAction = new CActionMove (_MainFrame->isSelectionLocked ()); + _TranformAction = moveAction; + moveAction->setTranslation (CVector::Null); + moveAction->redo (); + } + } + } + + // No action performed ? + if (!_TranformAction) + { + // Remove old selection + drawSelection (); + _DrawSelection = true; + } + } + else + { + // Update selection + UpdateSelection (); + // we stop the modifications before opening the popupmenu (otherwise, it crashes on the plugin !) + EndModification = true; + doc->endModification (); + + // Right + CPoint point2 = point; + ClientToScreen (&point2); + _MainFrame->createContextMenu (_MainFrame, point2, true); + + // No more button + _MouseRightDown = false; + _MouseLeftDown = false; + _MouseMidDown = false; + updateMouseMode (nFlags); + } + } + } + + // Mode Transition + if (_MouseMode == DrawTransition) + { + _MainFrame->_ZoneBuilder->addTransition (_CurPos); + _LastX = (sint32)floor (_CurPos.x / _CellSize); + _LastY = (sint32)floor (_CurPos.y / _CellSize); + } + + // Plugin position control + if (_MouseMode == PluginMove) + { + _MainFrame->_PositionControl = _CurPos; + if (_MainFrame->_CurrentPlugin) + { + _MainFrame->_CurrentPlugin->positionMoved(_CurPos); + // invalide display to update cursor position + _MainFrame->Invalidate(FALSE); + } + } + + // End of an undo stack element + if (!EndModification) + { + doc->endModification (); + } + + _MouseMoved = false; + _LastMousePos = point; + + // Update data + _MainFrame->updateData (); +} + +// *************************************************************************** +void CDisplay::OnLButtonDblClk (UINT nFlags, CPoint point) +{ + if (!Interactif) + return; + + if (DontUse3D) + return; + + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; + if (_MouseRightDown || _MouseMidDown) + return; + + _CurPos = convertToWorld (point); + + // Begin of an undo stack element + getDocument ()->beginModification (); + + if (_MainFrame->_Mode == 2) // Mode Transition + { + _MainFrame->_ZoneBuilder->addTransition (_CurPos); + _LastX = (sint32)floor (_CurPos.x / _CellSize); + _LastY = (sint32)floor (_CurPos.y / _CellSize); + } + + if (_MainFrame->_Mode == 1) // Mode Logic + { + } + + // End of an undo stack element + getDocument ()->endModification (); + + _LastMousePos = point; + + // Update data + _MainFrame->updateData (); +} + +// *************************************************************************** + +void CDisplay::selectPrimitives (const std::vector &result, bool addSelection) +{ + // The docmuent + CWorldEditorDoc *doc = getDocument (); + + // Ctrl ? + if (!addSelection) + { + if (_MainFrame->isSelectionLocked ()) + { + // Unselect + doc->addModification (new CActionUnselectAllSub ()); + } + else + { + // Unselect + doc->addModification (new CActionUnselectAll ()); + } + } + + // Backup selected flag + std::vector selected (result.size ()); + + // For each primitive + uint i; + for (i=0; iisSelectionLocked ()) + { + // Check the vertex flag + nlassert ((uint)result[i].XSubPrim < result[i].Primitive->getNumVector ()); + selected[i] = result[i].Primitive->getPrimVector ()[result[i].XSubPrim].Selected; + } + else + { + // Get selection property +// IProperty *prop; + selected[i] = getPrimitiveEditor(result[i].Primitive)->getSelected(); + } + } + + // For each primitive + for (i=0; iisSelectionLocked ()) + { + // Select it + doc->addModification (new CActionUnselectSub (result[i])); + } + else + { + // Select it + doc->addModification (new CActionUnselect (result[i])); + } + } + } + else + { + // Select it + if (_MainFrame->isSelectionLocked ()) + { + doc->addModification (new CActionSelectSub (result[i])); + } + else + { + doc->addModification (new CActionSelect (result[i])); + } + } + } +} + +// *************************************************************************** + +void CDisplay::OnLButtonUp (UINT nFlags, CPoint point) +{ + if (!Interactif) + return; + + if (DontUse3D) + return; + + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; + + // Release capture + if (!_MouseMidDown && _MouseLeftDown && !_MouseRightDown) + ReleaseCapture (); + + // Mouse was down ? + if (_MouseMode == TransformPrimitive) + { + // Get the document + CWorldEditorDoc *doc = getDocument (); + + _CurPos = convertToWorld (point); + + // Begin of an undo stack element + getDocument ()->beginModification (); + + // Transform ? + if (_SelectionMin != _SelectionMax) + { + if (_TranformAction) + { + // Add the action + _TranformAction->undo (); + doc->addModification (_TranformAction); + + // Reset action + _TranformAction = NULL; + } + else + { + // Erase selection + drawSelection (); + _DrawSelection = false; + + // Pick position + CVector pickPosMin ((float)_SelectionMin.x, (float)(_WindowHeight-_SelectionMin.y-1), 0); + CVector pickPosMax ((float)_SelectionMax.x, (float)(_WindowHeight-_SelectionMax.y-1), 0); + if (pickPosMin.x > pickPosMax.x) + { + float temp = pickPosMin.x; + pickPosMin.x = pickPosMax.x; + pickPosMax.x = temp; + } + if (pickPosMin.y > pickPosMax.y) + { + float temp = pickPosMin.y; + pickPosMin.y = pickPosMax.y; + pickPosMax.y = temp; + } + + // In world + pixelToWorld (pickPosMin); + pixelToWorld (pickPosMax); + + std::vector result; + if (pickRect (pickPosMin, pickPosMax, result, true)) + { + // Select it + selectPrimitives (result, (nFlags & MK_CONTROL) != 0); + } + else + { + // No ctrl ? + if ((nFlags & MK_CONTROL) == 0) + { + // Unselect all + if (_MainFrame->isSelectionLocked ()) + { + doc->addModification (new CActionUnselectAllSub ()); + } + else + { + doc->addModification (new CActionUnselectAll ()); + } + } + } + } + } + else + { + if (_TranformAction) + { + // Reset action + delete _TranformAction; + _TranformAction = NULL; + } + else + { + // Erase selection + drawSelection (); + _DrawSelection = false; + } + + // Pick position + CVector pickPosMin ((float)_SelectionMin.x, (float)(_WindowHeight-_SelectionMin.y-1), 0); + CVector pickPosMax ((float)_SelectionMax.x, (float)(_WindowHeight-_SelectionMax.y-1), 0); + if (pickPosMin.x > pickPosMax.x) + { + float temp = pickPosMin.x; + pickPosMin.x = pickPosMax.x; + pickPosMax.x = temp; + } + if (pickPosMin.y > pickPosMax.y) + { + float temp = pickPosMin.y; + pickPosMin.y = pickPosMax.y; + pickPosMax.y = temp; + } + + // In world + pixelToWorld (pickPosMin); + + // Pick + std::vector result; + bool picked = pickPoint (pickPosMin, result, false); + + + // Pick a primitive that exist + if (_ClickedSelected) + { + // Should e something under the mouse + nlassert (picked); + + // Look for a non selected primitive +// IProperty *prop; + uint prim; + for (prim=0; primgetSelected()) + break; + } + + // Should be over a selected primitive + nlassert (_LastPickedPrimitiveId != result.size ()); + + // Array + std::vector selectPrimitive; + selectPrimitive.push_back (result[_LastPickedPrimitiveId]); + selectPrimitives (selectPrimitive, false); + } + + // Something under the mouse ? + if (!picked) + { + // No ctrl ? + if ((nFlags & MK_CONTROL) == 0) + { + // Unselect all + if (_MainFrame->isSelectionLocked ()) + { + doc->addModification (new CActionUnselectAllSub ()); + } + else + { + doc->addModification (new CActionUnselectAll ()); + } + } + } + } + + // End of an undo stack element + getDocument ()->endModification (); + } + + _MouseLeftDown = false; + + // Update mouse mode + updateMouseMode (nFlags); + + // Invalidate cursor + invalidateCursor (); + + // Update data + _MainFrame->updateData (); + nlassert (_DrawSelection == false); +} + +// *************************************************************************** + +void CDisplay::OnRButtonUp (UINT nFlags, CPoint point) +{ + if (DontUse3D) + return; + + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; + _MouseRightDown = false; + + // Release capture + if (!_MouseMidDown && !_MouseLeftDown && _MouseRightDown) + ReleaseCapture (); + + // Update mouse mode + updateMouseMode (nFlags); + + // Invalidate cursor + invalidateCursor (); + + // Update data + _MainFrame->updateData (); +} + +// *************************************************************************** + +void CDisplay::drawSelection () +{ + // Get the DC + CDC *pDC = GetDC (); + + // Rect + RECT rect; + rect.left = std::min (_SelectionMin.x, _SelectionMax.x); + rect.top = std::min (_SelectionMin.y, _SelectionMax.y); + rect.right = std::max (_SelectionMin.x, _SelectionMax.x); + rect.bottom = std::max (_SelectionMin.y, _SelectionMax.y); + + // Draw a xor focus rect + pDC->DrawFocusRect (&rect); + + // Release the DC + ReleaseDC (pDC); +} + +// *************************************************************************** +void CDisplay::OnMouseMove (UINT nFlags, CPoint point) +{ + if (!Interactif) + return; + + if (DontUse3D) + return; + + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; + + if (_MainFrame->GetActiveWindow() == _MainFrame) + SetFocus(); + + if ((_LastMousePos.x == point.x) && (_LastMousePos.y == point.y)) + return; + + _MouseMoving = true; + + // Begin of an undo stack element + CWorldEditorDoc *doc = getDocument (); + if (doc) + { + doc->beginModification (); + } + + // Get the current position in world + _CurPos = convertToWorld (point); + _MouseMoved = true; + + const bool shiftPushed = (nFlags & MK_SHIFT) != 0; + const bool altPushed = (GetAsyncKeyState (VK_MENU) & 0x8000) != 0; + const bool ctrlPushed = ( ( GetAsyncKeyState (VK_LCONTROL) | GetAsyncKeyState (VK_RCONTROL) ) & 0x8000 ) != 0; + switch (_MouseMode) + { + // Mode Zone + case DrawTiles: + { + sint32 x = (sint32)floor (_CurPos.x / _CellSize); + sint32 y = (sint32)floor (_CurPos.y / _CellSize); + if ((x!=_LastX)||(y!=_LastY)) + { + _LastX = x; + _LastY = y; + _MainFrame->_ZoneBuilder->add (_CurPos); + } + } + break; + case RemoveTiles: + { + sint32 x = (sint32)floor (_CurPos.x / _CellSize); + sint32 y = (sint32)floor (_CurPos.y / _CellSize); + if ((x!=_LastX)||(y!=_LastY)) + { + _LastX = x; + _LastY = y; + _MainFrame->_ZoneBuilder->del (_CurPos); + } + } + break; + case TransformPrimitive: + { + // Tranform mode ? + if (_TranformAction) + { + // New position + _SelectionMax = point; + + switch (_MainFrame->getTransformMode ()) + { + case CMainFrame::Move: + { + // Get the action + CActionMove *moveAction = dynamic_cast (_TranformAction); + if (moveAction) + { + CVector pickPosMin ((float)_SelectionMin.x, (float)(_WindowHeight-_SelectionMin.y-1), 0); + CVector pickPosMax ((float)_SelectionMax.x, (float)(_WindowHeight-_SelectionMax.y-1), 0); + pixelToWorld (pickPosMin); + pixelToWorld (pickPosMax); + + // Set the new translation + CVector translation = pickPosMax; + translation -= pickPosMin; + translation.z = 0; + + // Undo the action + moveAction->undo (); + + // Set the new translation + moveAction->setTranslation (translation); + + // Redo the action + moveAction->redo (); + } + } + break; + case CMainFrame::Rotate: + case CMainFrame::Turn: + { + CActionRotate *moveAction = dynamic_cast (_TranformAction); + if (moveAction) + { + // Set the new rotation + float angle = (_SelectionMin.x - _SelectionMax.x + _SelectionMax.y - _SelectionMin.y) * ROTATE_PER_PIXEL; + + // Undo the action + moveAction->undo (); + + // Set the new translation + const bool turn = _MainFrame->getTransformMode () == CMainFrame::Turn || ctrlPushed || altPushed || shiftPushed; + moveAction->setAngle (angle, _MainFrame->getTransformMode ()==CMainFrame::Rotate, turn); + + // Redo the action + moveAction->redo (); + } + } + break; + case CMainFrame::Scale: + case CMainFrame::Radius: + { + // Get the action + CActionScale *moveAction = dynamic_cast (_TranformAction); + if (moveAction) + { + // Set the new scale + float scale = (_SelectionMin.x - _SelectionMax.x + _SelectionMax.y - _SelectionMin.y) * SCALE_PER_PIXEL + 1.f; + + // Undo the action + moveAction->undo (); + + // Set the new translation + const bool radius = _MainFrame->getTransformMode () == CMainFrame::Radius || ctrlPushed || altPushed || shiftPushed; + moveAction->setScale (std::max (0.001f, scale), _MainFrame->getTransformMode ()==CMainFrame::Scale, radius); + + // Redo the action + moveAction->redo (); + } + } + break; + } + } + else + { + // Remove old selection + nlassert (_DrawSelection); + drawSelection (); + + // New position + _SelectionMax = point; + + // Draw new selection + drawSelection (); + } + } + break; + // Plugin position control + case PluginMove: + { + _MainFrame->_PositionControl = _CurPos; + if (_MainFrame->_CurrentPlugin) + { + _MainFrame->_CurrentPlugin->positionMoved(_CurPos); + _MainFrame->Invalidate(FALSE); + } + } + break; + // View displacement + case DragView: + { + ::CRect rect; + GetClientRect (rect); + + float dx = ((float)(point.x-_LastMousePos.x)) / ((float)rect.Width()); + float dy = -((float)(point.y-_LastMousePos.y)) / ((float)rect.Height()); + + _Offset.x -= dx * (_InitViewMax.x-_InitViewMin.x) * _Factor; + _Offset.y -= dy * (_InitViewMax.y-_InitViewMin.y) * _Factor; + + invalidateLeftView (); + } + break; + case ZoomView: + { + ::CRect rect; + GetClientRect (rect); + + float dx = ((float)(point.x-_LastMousePos.x)) / ((float)rect.Width()); + float dy = -((float)(point.y-_LastMousePos.y)) / ((float)rect.Height()); + if (DontUse3D) + return; + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; + setFactor (_Factor*(float)pow(4.0f, dx+dy), true, _OrigineZoom); + } + break; + } + + // End of an undo stack element + if (doc) + doc->endModification (); + + // Nothing pushed ? + bool displayInfo = false; + if (_MouseMode == Nothing) + { + if (_MainFrame->_Mode == 1) // Mode Logic + { + // Pick pos + CVector pickPos ((float)point.x, (float)(_WindowHeight-point.y-1), 0); + pixelToWorld (pickPos); + + // Pick something.. + std::vector result; + if (pickPoint (pickPos, result, false)) + { + // Point ? + uint i; + for (i=0; i (result[i].Primitive) || dynamic_cast (result[i].Primitive)) + break; + } + + // Not found ? + if (i == result.size ()) + i = 0; + + // Set the name + _MainFrame->displayInfo (result[i].getPathName ().c_str ()); + displayInfo = true; + } + } + } + + // if we have to show the Collisions map, we simply Invalidate the window + if (_MainFrame->showCollisions()) + { + sint32 x, y; + x = (sint32)floor(2*_CurPos.x / _CellSize); + y = (sint32)floor(2*_CurPos.y / _CellSize); + + if (x != _lastXCollisionTextureMove || y != _lastYCollisionTextureMove) + { + _lastXCollisionTextureMove = x; + _lastYCollisionTextureMove = y; + Invalidate(FALSE); + } + } + + // No display info ? + if (!displayInfo) + _MainFrame->displayInfo (""); + + _LastMousePos = point; + + // Invalidate mouse cursor + invalidateCursor (); + + // Display the current position in the world in the status bar + _MainFrame->displayStatusBarInfo (); + + // Update data + _MainFrame->updateData (); +} + +// *************************************************************************** +void CDisplay::OnChar (UINT nChar, UINT nRepCnt, UINT nFlags) +{ + /* todo remov all this and set normal accelerator */ + if (DontUse3D) + return; + + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; + + if (nChar == 32) // Space bar == middle mouse button + { + _MouseMidDown = true; + updateMouseMode (nFlags); + } + + /* if ((nChar == 'g') || (nChar == 'G')) + { + _MainFrame->onMenuViewGrid (); + } */ + + if ((nChar == 't') || (nChar == 'T')) + { + if (_MainFrame->_Mode == 2) + _MainFrame->onMenuModeZone (); + else if (_MainFrame->_Mode == 0) + _MainFrame->onMenuModeTransition (); + /* else if (_MainFrame->_Mode == 1) + _MainFrame->transfert (_MainFrame->_PRegionBuilder.getSelPBName()); */ + } + + // Georges binds + if ((nChar == 'l') || (nChar == 'L')) + { + /* if (_MainFrame->_Mode == 1) + _MainFrame->lineDown (); */ + } + if ((nChar == 'o') || (nChar == 'O')) + { + /* if (_MainFrame->_Mode == 1) + _MainFrame->lineUp (); */ + } + + // Escape stop plugin position control. + if (nChar == 27 && _MainFrame->_Mode == 3) + { + if (_MainFrame->_CurrentPlugin != 0) + { + _MainFrame->_CurrentPlugin->lostPositionControl(); + _MainFrame->_CurrentPlugin = 0; + } + _MainFrame->_Mode = _MainFrame->_LastMode; + _MainFrame->Invalidate(FALSE); + } +} + +// *************************************************************************** +void CDisplay::OnKeyUp (UINT nChar, UINT nRepCnt, UINT nFlags) +{ + if (DontUse3D) + return; + + if ((CNELU::Driver == NULL)||(_MainFrame == NULL)) return; + if (nChar == 32) + { + _MouseMidDown = false; + updateMouseMode (nFlags); + } + + // Invalidate cursor + invalidateCursor (); + + // Update data + _MainFrame->updateData (); +} + +// *************************************************************************** +void CDisplay::OnSize (UINT nType, int cx, int cy) +{ + if (nType == SIZE_RESTORED) + { + if ((cx > 25) && (cy > 25)) + { + float xRatio = (float)(cx) / 800.0f; + float yRatio = (float)(cy) / 800.0f; + + _InitViewMax = CVector (5.5f*xRatio*_CellSize, 5.5f*yRatio*_CellSize, 0.0f); + _InitViewMin = CVector (-5.5f*xRatio*_CellSize, -5.5f*yRatio*_CellSize, 0.0f); + } + } + invalidateLeftView (); +} + +// *************************************************************************** +LRESULT CDisplay::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + // TODO: Add your specialized code here and/or call the base class + if (!DontUse3D && CNELU::Driver) + { + typedef void (*winProc)(NL3D::IDriver *drv, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + winProc drvWndProc= (winProc)CNELU::Driver->getWindowProc(); + drvWndProc (CNELU::Driver, m_hWnd, message, wParam, lParam); + } + + return CView::WindowProc(message, wParam, lParam); +} + +// *************************************************************************** + +BOOL CDisplay::OnEraseBkgnd (CDC *pC) +{ + return TRUE; +} + +// *************************************************************************** + +CDisplay *getDisplay () +{ + CMainFrame *mainFrame = getMainFrame (); + if (mainFrame) + return dynamic_cast(getMainFrame ()->m_wndSplitter.GetPane(0,0)); + else + return NULL; +} + + +// *************************************************************************** +BOOL CDisplay::PreTranslateMessage(MSG *pmsg) +{ + if (pmsg->message == WM_KEYDOWN) + { + if (pmsg->wParam >= VK_LEFT && pmsg->wParam <=VK_DOWN) + { + CToolsLogic *toolWnd = dynamic_cast(getMainFrame ()->m_wndSplitter.GetPane(0,1)); + + if (toolWnd) + { + toolWnd->GetTreeCtrl()->SendMessage(WM_KEYDOWN, pmsg->wParam, 0); + } + + return TRUE; + + } + } + + return CView::PreTranslateMessage(pmsg); +} + +// *************************************************************************** + +void CDisplay::updateCursor () +{ + if (!_ValidMouse) + { + // Choose a cursor + HCURSOR cursor = LoadCursor (NULL, IDC_ARROW); + + bool ctrlPushed = ( ( GetAsyncKeyState (VK_LCONTROL) | GetAsyncKeyState (VK_RCONTROL) ) & 0x8000 ) != 0; + + // No click + switch (_MouseMode) + { + case Nothing: + { + // Mode prim ? + if (_MainFrame->_Mode == 1) + { + CVector pickPosMin ((float)_LastMousePos.x, (float)(_WindowHeight-_LastMousePos.y-1), 0); + pixelToWorld (pickPosMin); + + bool actionActived = false; + + // Add sub element vertex mode ? + bool addPointSub = (_MainFrame->getTransformMode () == CMainFrame::AddPoint) && (_MainFrame->isSelectionLocked ()); + if ( !addPointSub ) + { + if (ctrlPushed) + { + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_COPY)); + } + else + { + // Pick a primitive that exist + std::vector result; + if (pickPoint (pickPosMin, result, false)) + { + if (_MainFrame->getTransformMode () != CMainFrame::Select) + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_MOVE + _MainFrame->getTransformMode () - 1)); + actionActived = true; + } + } + + // Over something selected ? + /*result.clear (); + if (pickPoint (pickPosMin, result, true)) + { + // Translate or rotate ? + switch (_MainFrame->getTransformMode ()) + { + case CMainFrame::Move: + { + } + break; + case CMainFrame::Rotate: + { + } + break; + case CMainFrame::Turn: + { + } + break; + case CMainFrame::Scale: + { + } + break; + } + actionActived = true; + }*/ + } + else + { + if (_MainFrame->isSelectionLocked ()) + { + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_ADD_POINT)); + } + } + + // No action actived ? + if (!actionActived) + { + // *** Try to add vertices in sub mode + + // Are we in sub mode ? + if (_MainFrame->isSelectionLocked ()) + { + // Pick the vertex before the clicked edge + std::vector result; + if (pickEdgePoint (pickPosMin, result)) + { + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_INSERT_POINT)); + } + } + } + } + } + break; + + // Moved with middle click ? + case DragView: + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_HAND)); + break; + + // Moved with left click ? + case TransformPrimitive: + { + if (_TranformAction) + { + switch (_MainFrame->getTransformMode ()) + { + case CMainFrame::Move: + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_MOVE)); + break; + case CMainFrame::Rotate: + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_ROTATE)); + break; + case CMainFrame::Turn: + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_TURN)); + break; + case CMainFrame::Scale: + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_SCALE)); + break; + case CMainFrame::Radius: + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_RADIUS)); + break; + } + } + else + { + if (ctrlPushed) + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_SELECT_COPY)); + else + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_SELECT)); + } + } + break; + + // Zoom ? + case ZoomView: + cursor = theApp.LoadCursor (MAKEINTRESOURCE(IDC_ZOOM)); + break; + } + + _ValidMouse = true; + + // Set the cursor + SetCursor (cursor); + } +} + +// *************************************************************************** + +void CDisplay::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + // Invalidate cursor + invalidateCursor (); + + // Update data + _MainFrame->updateData (); +} + +// *************************************************************************** + +void CDisplay::setDisplayRegion (const CVector &min, const CVector &max) +{ + // Set the new offset + _Offset = (min+max)/2; + + // Clac new factor + _Factor = std::max ((min.x-_Offset.x)/_InitViewMin.x, (min.y-_Offset.y)/_InitViewMin.y); + NLMISC::clamp (_Factor, 0.015625f, 8.0f); + + // Recalc view parameters + calcCurView(); + + // Invalidate + invalidateCursor (); + + // Invalidate left view + invalidateLeftView (); +} + +// *************************************************************************** + +void CDisplay::setDisplayCenter (const CVector ¢er, bool zoom) +{ + // Set the new offset + _Offset = center; + + if (zoom) + { + // set min view factor + _Factor = 0.015625f; + } + + // Recalc view parameters + calcCurView(); + + // Invalidate + invalidateCursor (); + + // Invalidate left view + invalidateLeftView (); +} + + +// *************************************************************************** + +void CDisplay::DrawCollisionTexture(sint32 count, float x1, float y1) +{ + if (DontUse3D) + return; + + if ((x1 >= 0) && (x1 <= 255*_CellSize) && (y1 <= 0) && (y1 >= -255*_CellSize)) + { + sint32 x2, y2; + x2 = (sint32)floor(x1 / _CellSize); + y2 = (sint32)floor(y1 / _CellSize); + + if (x2 != _lastXCollisionTexture[count] || y2 != _lastYCollisionTexture[count]) + { + // lookup in cache to see if the texture is already there + std::list::iterator first(_collisionTextureCache.begin()), last(_collisionTextureCache.end()); + CTextureFile *tex = 0; + for (; first != last; ++first) + { + if (first->PosX == x2 && first->PosY == y2) + { + // we found it, bring it in first place in the vector + tex = first->Texture; + + _collisionTextureCache.push_front(*first); + _collisionTextureCache.erase(first); + break; + } + } + + // load the texture + _lastXCollisionTexture[count] = x2; + _lastYCollisionTexture[count] = y2; + string Name; + getZoneNameFromXY(x2, y2, Name); + _collisionTexture[count] = NULL; + if (tex != NULL) + { + _collisionTexture[count] = tex; + } + else + { + string sDirBackup = NLMISC::CPath::getCurrentPath(); + + string dir = getDocument ()->getDataDir (); + if (dir.empty()) dir = _MainFrame->_ExeDir; + dir += "\\collisionmap\\"; + SetCurrentDirectory (dir.c_str()); + + if(NLMISC::CFile::fileExists(Name+".tga") || NLMISC::CFile::fileExists(Name+".png")) + { + string filename = getTextureFile(Name); + + _collisionTexture[count] = new CTextureFile; + _collisionTexture[count]->setUploadFormat(ITexture::RGB565); + // we don't want compression + _collisionTexture[count]->setAllowDegradation(false); + _collisionTexture[count]->setFilterMode(ITexture::Nearest,ITexture::NearestMipMapOff); + + _collisionTexture[count]->setFileName (filename); + _collisionTexture[count]->setReleasable (true); + _collisionTexture[count]->generate (); + + // store the texture in cache + if (_collisionTextureCache.size() > COLLISION_TEXTURE_CACHE_SIZE) + _collisionTextureCache.pop_back(); + TCollisionTextureCache ctc; + ctc.PosX = x2; + ctc.PosY = y2; + ctc.Texture = _collisionTexture[count]; + + _collisionTextureCache.push_front(ctc); + } + + NLMISC::CPath::setCurrentPath(sDirBackup); + } + } + + // Create a material + CMaterial material; + material.initUnlit (); + material.setTexture (0, _collisionTexture[count]); + material.setZFunc (CMaterial::always); + material.setZWrite (false); + + // Blend function + material.setBlend (true); + //material.setBlendFunc (CMaterial::srcalpha, CMaterial::invsrcalpha); + //material.setBlendFunc (CMaterial::srcalpha, CMaterial::one); + material.setBlendFunc (CMaterial::one, CMaterial::one); + + float minx = x2*_CellSize -0.5f; + float miny = y2*_CellSize - 0.5f; + float maxx = minx + _CellSize; + float maxy = miny + _CellSize; + +#define PIXEL_RATIO (160.0/256.0) + + // Create the vertices + std::vector vertices (2); + vertices[0].V0.x = minx; + vertices[0].V0.y = maxy; + vertices[0].V0.z = 0; + vertices[0].Uv0.U = 0; + vertices[0].Uv0.V = 0; + vertices[0].V1.x = minx; + vertices[0].V1.y = miny; + vertices[0].V1.z = 0; + vertices[0].Uv1.U = 0; + vertices[0].Uv1.V = PIXEL_RATIO; + vertices[0].V2.x = maxx; + vertices[0].V2.y = miny; + vertices[0].V2.z = 0; + vertices[0].Uv2.U = PIXEL_RATIO; + vertices[0].Uv2.V = PIXEL_RATIO; + vertices[1].V0.x = maxx; + vertices[1].V0.y = miny; + vertices[1].V0.z = 0; + vertices[1].Uv0.U = PIXEL_RATIO; + vertices[1].Uv0.V = PIXEL_RATIO; + vertices[1].V1.x = maxx; + vertices[1].V1.y = maxy; + vertices[1].V1.z = 0; + vertices[1].Uv1.U = PIXEL_RATIO; + vertices[1].Uv1.V = 0; + vertices[1].V2.x = minx; + vertices[1].V2.y = maxy; + vertices[1].V2.z = 0; + vertices[1].Uv2.U = 0; + vertices[1].Uv2.V = 0; + + // Display it + CDRU::drawTrianglesUnlit (vertices, material, *CNELU::Driver); + } +} + +// *************************************************************************** + +void CDisplay::updateMouseMode (UINT nFlags) +{ + // Zoom ? + if (_MouseMidDown || ((_MouseLeftDown) && ((GetAsyncKeyState (VK_MENU) ) & 0x8000))) + { + _MouseMode = DragView; + return; + } + + if ((_MouseLeftDown) && (nFlags&MK_SHIFT)) + { + _MouseMode = ZoomView; + _OrigineZoom = _CurPos; + return; + } + + if (_MouseRightDown) + { + // Choose the mode + switch (_MainFrame->_Mode) + { + case 0: + _MouseMode = RemoveTiles; + return; + case 1: + _MouseMode = MenuPrimitive; + return; + case 3: + _MouseMode = PluginMove; + return; + } + } + + if (_MouseLeftDown) + { + // Choose the mode + switch (_MainFrame->_Mode) + { + case 0: + _MouseMode = DrawTiles; + return; + case 1: + _MouseMode = TransformPrimitive; + return; + case 2: + _MouseMode = DrawTransition; + return; + case 3: + _MouseMode = PluginMove; + return; + } + } + + _MouseMode = Nothing; +} + +// *************************************************************************** + +void CDisplay::setFactor (float newFactor, bool follow, const CVector &position) +{ + static const float factorMin = 0.015625f; + static const float factorMax = 8.0f; + static const float logFactorMin = 0.015625f; //(float)log(0.015625f); + static const float logFactorMax = 8.0f; //(float)log(8.0f); + NLMISC::clamp (newFactor, factorMin, factorMax); + + // Follow the zoom with a drag ? + if (follow) + { + // Position delta + /*float oldPos = ((float)log(_Factor) - logFactorMin) / (logFactorMax-logFactorMin); + float newPos = ((float)log(newFactor) - logFactorMin) / (logFactorMax-logFactorMin);*/ + float oldPos = (_Factor - logFactorMin) / (logFactorMax-logFactorMin); + float newPos = (newFactor - logFactorMin) / (logFactorMax-logFactorMin); + + // Source position + if (oldPos == 0) + { + _Offset = position; + } + else + { + CVector src = (_Offset - position) / oldPos + position; + + _Offset = (position - src) * (1.f-newPos) + src; + } + } + + _Factor = newFactor; + + invalidateLeftView (); +} + +// *************************************************************************** + +void CDisplay::displayPoints () +{ + if (DontUse3D) + return; + + if (CNELU::Driver) + { + // Size of the pixel, must be > 0.5 meter + uint32 width, height; + sint32 step = 1; + float xsize = 1.0f; + CNELU::Driver->getWindowSize (width, height); + if (width == 0) + return; + if ( (_CurViewMax.x-_CurViewMin.x)/(float)width > 0.25f*16*16 ) + return; + if ( (_CurViewMax.x-_CurViewMin.x)/(float)width > 0.25f*16 ) + { + step = 256; + xsize = 64.0f; + } + else if ( (_CurViewMax.x-_CurViewMin.x)/(float)width > 0.25f ) + { + step = 16; + xsize = 4.0f; + } + + { + initRenderProxy (); + // Setup matrix + setupWorldMatrixAndFrustum (); + + sint startX = (sint)(_CurViewMin.x) & (~(step-1)); + sint startY = (sint)(_CurViewMin.y) & (~(step-1)); + sint endX = (sint)(_CurViewMax.x) & (~(step-1)); + sint endY = (sint)(_CurViewMax.y) & (~(step-1)); + if (startX > endX) swap(startX, endX); + if (startY > endY) swap(startY, endY); + endX++; + endY++; + sint x, y; + for (y=startY; ygetText (text); + return false; +} + +// *************************************************************************** + +bool CDisplay::getActionHelp (string &text) +{ + if (_TranformAction) + return _TranformAction->getHelp (text); + return false; +} + +// *************************************************************************** + +void CDisplay::setLayerTexture(uint primitiveLayer, CPrimTexture *tex) +{ + nlassert(primitiveLayer < NUM_PRIM_LAYER); + _ProxyTexture[primitiveLayer] = tex; +} + + +// *************************************************************************** + +void CPrimTexture::buildFromFile(const std::string &filename) +{ + // Load tex size + std::string path = CPath::lookup(filename, false, false); + _Width = _Height = 0; + if (!path.empty()) + { + try + { + uint32 width, height; + NLMISC::CBitmap::loadSize(path, width, height); + _Width = (uint) width; + _Height = (uint) height; + } + catch (NLMISC::EStream) + { + nlwarning("Couldn't retrieve size for %s", filename.c_str()); + } + } + NL3D::CTextureFile *tex = new NL3D::CTextureFile(filename); + _Texture = tex; + _Texture->setFilterMode(NL3D::ITexture::Nearest, NL3D::ITexture::NearestMipMapOff); +} + + +// *************************************************************************** + +void CPrimTexture::buildFromNLBitmap(const NLMISC::CBitmap &bm) +{ + _Width = _Height = 0; + class CTextureFromNLBitmap : public NL3D::ITexture + { + public: + NLMISC_DECLARE_CLASS(CTextureFromNLBitmap); + NLMISC::CBitmap _SrcBM; + virtual void doGenerate(bool async = false) + { + (NLMISC::CBitmap &) *this = _SrcBM; + } + }; + CTextureFromNLBitmap *tfbm = new CTextureFromNLBitmap; + tfbm->_SrcBM = bm; + _Texture = tfbm; + _Texture->setFilterMode(NL3D::ITexture::Nearest, NL3D::ITexture::NearestMipMapOff); + _Width = bm.getWidth(); + _Height = bm.getHeight(); +} + + + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/display.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/display.h index 44fdf4208..38939cef0 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/display.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/display.h @@ -1,389 +1,389 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef DISPLAY_H -#define DISPLAY_H - -#include "nel/misc/smart_ptr.h" -#include "nel/misc/matrix.h" -#include "nel/misc/geom_ext.h" -#include -#include -#include -#include -#include -#include "world_editor_doc.h" - - -namespace NL3D -{ - class CFontManager; - class CFontGenerator; -} - - -class CMainFrame; - - -// a texture to be used with CDisplay -// NB : virtual are there for plugin access (no lib included) -class CPrimTexture : public NLMISC::CRefCount -{ -public: - CPrimTexture() : _Width(0), _Height(0) {} - virtual ~CPrimTexture() {} - // Build texture from a file - virtual void buildFromFile(const std::string &filename); - // Build from a CBitmap object (content is copied) - virtual void buildFromNLBitmap(const NLMISC::CBitmap &bm); - // get width of texture. 'setFile' should have been called - uint getWidth() const { return _Width; } - // get height of texture. 'setFile' should have been called - uint getHeight() const { return _Height; } -private: - friend class CDisplay; - NLMISC::CSmartPtr _Texture; - uint _Width, _Height; -}; - -class CDisplay : public CView -{ - // number of primitives layers - enum { NUM_PRIM_LAYER = 4 }; - - - DECLARE_DYNCREATE(CDisplay) - - CMainFrame *_MainFrame; - -public: - - bool Interactif; - - bool _MouseLeftDown; - bool _MouseRightDown; - bool _MouseMidDown; - bool _MouseMoved; - bool _MouseMoving; - CPoint _LastMousePos; - CPoint _SelectionMin, _SelectionMax; - bool _ClickedSelected; - - // World infos - float _Factor; - NLMISC::CVector _Offset; - NLMISC::CVector _InitViewMin, _InitViewMax; - float _CellSize; - bool _DisplayGrid; - bool _DisplayZone; - // This is the inworld coordinate of the bounding square - NLMISC::CVector _CurViewMin, _CurViewMax; - NLMISC::CVector _CurPos; - NLMISC::CVector _OrigineZoom; - sint32 _LastX, _LastY; - - bool _CtrlKeyDown; - NLMISC::CRGBA _BackgroundColor; - - uint32 getWidth () - { - return _WindowWidth; - } - uint32 getHeight () - { - return _WindowHeight; - } - - // Cursor - void invalidateCursor () - { - _ValidMouse = false; - } - void updateCursor (); - - BOOL PreTranslateMessage(MSG *pmsg); - -private: - bool _ValidMouse; - - // pointers to store 2*2 collision textures - NLMISC::CSmartPtr _collisionTexture[2*2]; - sint32 _lastXCollisionTextureMove; - sint32 _lastYCollisionTextureMove; - sint32 _lastXCollisionTexture[2*2]; - sint32 _lastYCollisionTexture[2*2]; - // pointers to store some collision texture in cache (really speed up small movement on map) - struct TCollisionTextureCache - { - NLMISC::CSmartPtr Texture; - sint32 PosX; - sint32 PosY; - }; - enum - { - // Each texture is 256*256 in 16 bits, 128Kb - COLLISION_TEXTURE_CACHE_SIZE = 32 // 4Mo texture cache - }; - std::list _collisionTextureCache; - void DrawCollisionTexture(sint32 count, float x1, float y1); - - // Pick variable -private: - uint32 _WindowWidth; - uint32 _WindowHeight; - - // Last id of the picked primitive - uint _LastPickedPrimitiveId; - - // Last primitives picked - std::vector _LastPickedPrimitive; - - // Draw the pick rect - bool _DrawSelection; - void drawSelection (); - - // Select the primtives - void selectPrimitives (const std::vector &result, bool addSelection); - - // \name Transform - - // Current transform action - class IActionInteractive *_TranformAction; - - // Mouse zoom ? - enum TMouseMoveMode - { - Nothing, - DrawTiles, // In mode 0 : left click in primitive in tile mode - RemoveTiles, // In mode 0 : right click in primitive in tile mode - TransformPrimitive, // In mode 1 : left click in primitive mode - MenuPrimitive, // In mode 1 : right click in primitive mode - DrawTransition, // In mode 2 : left click in transition mode - PluginMove, // In mode 3 : left / right click in plugin mode - ZoomView, // All mode : shift + left click - DragView, // All mode : middle click - }; - TMouseMoveMode _MouseMode; - -public: - // Get the average position of selected items - bool getSelectedAverage (NLMISC::CVector &average); - - // Pick methods with a point - static bool pickPoint (const NLMISC::CVector &pickPos, const NLMISC::CVector &v0, const NLMISC::CVector &v1, float bias); - static bool pickPoint (const NLMISC::CVector &pickPos, const NLMISC::CVector &point, float bias); - - // Pick some primitives with a point - bool pickPoint (const NLMISC::CVector &pickPos, std::vector &result, bool pickOnlySelected); - - // Pick a primitive edge from selected primitive. Return the locator on the first edge vertex. - bool pickEdgePoint (const NLMISC::CVector &pickPos, std::vector &result); - - // Pick methods with a rect - static bool pickRect (const NLMISC::CVector &pickPosMin, const NLMISC::CVector &pickPosMax, const NLMISC::CVector &v0, const NLMISC::CVector &v1); - static bool pickRect (const NLMISC::CVector &pickPosMin, const NLMISC::CVector &pickPosMax, const NLMISC::CVector &point); - - // Pick some primitives with a rect - bool pickRect (const NLMISC::CVector &pickPosMin, const NLMISC::CVector &pickPosMax, std::vector &result, bool pickOnlyShown); - - // Set the display region - void setDisplayRegion (const NLMISC::CVector &min, const NLMISC::CVector &max); - - // center the display on a position (keep the same scale) - void setDisplayCenter (const NLMISC::CVector ¢er, bool zoom); - -private: - - // Proxy methods - void setupWorldMatrixAndFrustum (); - void initRenderProxy (); - void flushRenderProxy (); -public: - - // HOTSPOTS - enum THotSpot - { - BottomLeft=0, - MiddleLeft, - TopLeft, - MiddleBottom, - MiddleMiddle, - MiddleTop, - BottomRight, - MiddleRight, - TopRight, - HotSpotCount - }; - - - // CONVERSIONS - virtual void pixelToWorld (NLMISC::CVector &pixels); - virtual void pixelVectorToWorld (NLMISC::CVector &pixels); - // convert world unit to pixel units (integer precision) - virtual void worldToPixel (NLMISC::CVector &pixels); - // convert world unit to pixel units (float precision) - virtual void worldToFloatPixel(NLMISC::CVector &pixels); - // convert world unit to pixel units for a vector (integer precision) - virtual void worldVectorToPixelVector(NLMISC::CVector &pixels); - // convert world unit to pixel units for a vector (float precision) - virtual void worldVectorToFloatPixelVector(NLMISC::CVector &pixels); - virtual bool isClipped (const NLLIGO::CPrimVector *pVec, uint32 nNbVec); - - // UNTEXTURED PRIMITIVES - - virtual void lineRenderProxy (NLMISC::CRGBA color, const NLMISC::CVector& pos0, const NLMISC::CVector& pos1, uint primitiveLayer); - virtual void triRenderProxy (NLMISC::CRGBA color, const NLMISC::CVector& pos0, const NLMISC::CVector& pos1, const NLMISC::CVector& pos2, uint primitiveLayer); - virtual void pointRenderProxy (NLMISC::CRGBA color, const NLMISC::CVector& pos0); - virtual void primitiveRenderProxy(const NLLIGO::IPrimitive &primitive); - - // TEXT - // NB : rendering is done instantly, it is not buffered & delayed to the next flush as with the xxxxRenderProxy functions - // NB : coordinates are expressed in pixels - virtual void print(const ucstring &text, float x, float y, uint32 fontSize, NLMISC::CRGBA color, THotSpot hotspot); - virtual void print(const std::string &text, float x, float y, uint32 fontSize, NLMISC::CRGBA color, THotSpot hotspot); - - - - // TEXTURED PRIMITIVES - - // TODO nico : for now, using several textures is not convenient, because one has to call 'flush' before changing the texture, which is slow, - // This is not a good idea if a custom primitive displayer is used (because there's potentially one flush per primitive) - // intended usage is at post render time (in the 'postRender' method of plugins), in that way : - // call 'flush' - // set the wanted texture - // draw all quads with that texture - // and repeat for each new texture - // ideally, all quad texture should be packed in another bigger texture to avoid too much texture switching & flushs - // - // NB : no need to call 'flush' in the end, because the framework does it. - // NB : because of primitive layers, up to NUM_PRIM_LAYER textures can be set at once - - - - // Assign a texture to a primitive layer. Only the last set texture is used at render time, and affect all primitives of that layer - virtual void setLayerTexture(uint primitiveLayer, CPrimTexture *tex); - // Draw a textured quad. - virtual void texQuadRenderProxy(const NLMISC::CQuadColorUV &quad, uint primitiveLayer); - // flush render. Use it before changing texture for a layer - virtual void flush(); -private: - - // Draw a primitive - void drawPrimitive (const NLLIGO::IPrimitive *primitive, bool forceDefaultDisplay = false); - float intToWorld (uint value) const; - void drawLink (const NLLIGO::IPrimitive *first, const NLLIGO::IPrimitive *second); - - - - // Display meter grid points - void displayPoints (); - static bool isInTriangleOrEdge( double x, double y, - double xt1, double yt1, - double xt2, double yt2, - double xt3, double yt3 ); - - // Proxy primitive render - NLMISC::CMatrix _View2World; - NLMISC::CMatrix _World2View; - NL3D::CVertexBuffer _ProxyVB[NUM_PRIM_LAYER]; - NL3D::CVertexBufferReadWrite _ProxyVBAccess[NUM_PRIM_LAYER]; - NL3D::CVertexBuffer _ProxyVBPoints; - NL3D::CVertexBufferReadWrite _ProxyVBPointsAccess; - NL3D::CVertexBuffer _ProxyVBTexQuads[NUM_PRIM_LAYER]; - NL3D::CVertexBufferReadWrite _ProxyVBTexQuadsAccess[NUM_PRIM_LAYER]; - NL3D::CIndexBuffer _ProxyPBTri[NUM_PRIM_LAYER]; - NL3D::CIndexBufferReadWrite _ProxyPBTriAccess[NUM_PRIM_LAYER]; - NL3D::CIndexBuffer _ProxyPBLine[NUM_PRIM_LAYER]; - NL3D::CIndexBufferReadWrite _ProxyPBLineAccess[NUM_PRIM_LAYER]; - NL3D::CMaterial _ProxyMaterial; - NLMISC::CRefPtr _ProxyTexture[NUM_PRIM_LAYER]; - - - NL3D::CFontManager *_FontManager; - NL3D::CTextContext *_TextContext; - -public: - - CDisplay(); - ~CDisplay(); - - void init (CMainFrame *pMF); // pMF For update of the statusbar - void setCellSize (float size); - - void setBackgroundColor (NLMISC::CRGBA &col); - NLMISC::CRGBA getBackgroundColor (); - - void setDisplayGrid (bool bDisp); - bool getDisplayGrid (); - void calcCurView(); - void setFactor (float newFactor, bool follow, const NLMISC::CVector &position); - - NLMISC::CVector convertToWorld(CPoint &p); - - void renderSelection (); - void renderPluginPosition(); - - virtual void OnDraw (CDC* pDC); - - // Get interactif texts - bool getActionText (std::string &text); - bool getActionHelp (std::string &text); - -private: - - // Mouse handlers - enum TButton { Left, Middle, Right }; - - void buttonDown (TButton button, UINT nFlags, CPoint point); - void updateMouseMode (UINT nFlags); - - - afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct); - afx_msg void OnDestroy (); - - afx_msg BOOL OnMouseWheel (UINT nFlags, short zDelta, CPoint point); - afx_msg void OnMButtonDown (UINT nFlags, CPoint point); - afx_msg void OnMButtonUp (UINT nFlags, CPoint point); - afx_msg void OnLButtonDown (UINT nFlags, CPoint point); - afx_msg void OnLButtonDblClk (UINT nFlags, CPoint point); - afx_msg void OnLButtonUp (UINT nFlags, CPoint point); - afx_msg void OnRButtonDown (UINT nFlags, CPoint point); - afx_msg void OnRButtonUp (UINT nFlags, CPoint point); - afx_msg void OnMouseMove (UINT nFlags, CPoint point); - afx_msg void OnChar (UINT nChar, UINT nRepCnt, UINT nFlags); - afx_msg void OnKeyUp (UINT nChar, UINT nRepCnt, UINT nFlags); - afx_msg void OnSize (UINT nType, int cx, int cy); - afx_msg BOOL OnEraseBkgnd (CDC *pC); - afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); - - DECLARE_MESSAGE_MAP() - -private: - - //void displayGrid(); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CDisplay) - protected: - virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); - //}}AFX_VIRTUAL -}; - -CDisplay *getDisplay (); - -#endif // DISPLAY_H -///////////////////////////////////////////////////////////////////////////// +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef DISPLAY_H +#define DISPLAY_H + +#include "nel/misc/smart_ptr.h" +#include "nel/misc/matrix.h" +#include "nel/misc/geom_ext.h" +#include +#include +#include +#include +#include +#include "world_editor_doc.h" + + +namespace NL3D +{ + class CFontManager; + class CFontGenerator; +} + + +class CMainFrame; + + +// a texture to be used with CDisplay +// NB : virtual are there for plugin access (no lib included) +class CPrimTexture : public NLMISC::CRefCount +{ +public: + CPrimTexture() : _Width(0), _Height(0) {} + virtual ~CPrimTexture() {} + // Build texture from a file + virtual void buildFromFile(const std::string &filename); + // Build from a CBitmap object (content is copied) + virtual void buildFromNLBitmap(const NLMISC::CBitmap &bm); + // get width of texture. 'setFile' should have been called + uint getWidth() const { return _Width; } + // get height of texture. 'setFile' should have been called + uint getHeight() const { return _Height; } +private: + friend class CDisplay; + NLMISC::CSmartPtr _Texture; + uint _Width, _Height; +}; + +class CDisplay : public CView +{ + // number of primitives layers + enum { NUM_PRIM_LAYER = 4 }; + + + DECLARE_DYNCREATE(CDisplay) + + CMainFrame *_MainFrame; + +public: + + bool Interactif; + + bool _MouseLeftDown; + bool _MouseRightDown; + bool _MouseMidDown; + bool _MouseMoved; + bool _MouseMoving; + CPoint _LastMousePos; + CPoint _SelectionMin, _SelectionMax; + bool _ClickedSelected; + + // World infos + float _Factor; + NLMISC::CVector _Offset; + NLMISC::CVector _InitViewMin, _InitViewMax; + float _CellSize; + bool _DisplayGrid; + bool _DisplayZone; + // This is the inworld coordinate of the bounding square + NLMISC::CVector _CurViewMin, _CurViewMax; + NLMISC::CVector _CurPos; + NLMISC::CVector _OrigineZoom; + sint32 _LastX, _LastY; + + bool _CtrlKeyDown; + NLMISC::CRGBA _BackgroundColor; + + uint32 getWidth () + { + return _WindowWidth; + } + uint32 getHeight () + { + return _WindowHeight; + } + + // Cursor + void invalidateCursor () + { + _ValidMouse = false; + } + void updateCursor (); + + BOOL PreTranslateMessage(MSG *pmsg); + +private: + bool _ValidMouse; + + // pointers to store 2*2 collision textures + NLMISC::CSmartPtr _collisionTexture[2*2]; + sint32 _lastXCollisionTextureMove; + sint32 _lastYCollisionTextureMove; + sint32 _lastXCollisionTexture[2*2]; + sint32 _lastYCollisionTexture[2*2]; + // pointers to store some collision texture in cache (really speed up small movement on map) + struct TCollisionTextureCache + { + NLMISC::CSmartPtr Texture; + sint32 PosX; + sint32 PosY; + }; + enum + { + // Each texture is 256*256 in 16 bits, 128Kb + COLLISION_TEXTURE_CACHE_SIZE = 32 // 4Mo texture cache + }; + std::list _collisionTextureCache; + void DrawCollisionTexture(sint32 count, float x1, float y1); + + // Pick variable +private: + uint32 _WindowWidth; + uint32 _WindowHeight; + + // Last id of the picked primitive + uint _LastPickedPrimitiveId; + + // Last primitives picked + std::vector _LastPickedPrimitive; + + // Draw the pick rect + bool _DrawSelection; + void drawSelection (); + + // Select the primtives + void selectPrimitives (const std::vector &result, bool addSelection); + + // \name Transform + + // Current transform action + class IActionInteractive *_TranformAction; + + // Mouse zoom ? + enum TMouseMoveMode + { + Nothing, + DrawTiles, // In mode 0 : left click in primitive in tile mode + RemoveTiles, // In mode 0 : right click in primitive in tile mode + TransformPrimitive, // In mode 1 : left click in primitive mode + MenuPrimitive, // In mode 1 : right click in primitive mode + DrawTransition, // In mode 2 : left click in transition mode + PluginMove, // In mode 3 : left / right click in plugin mode + ZoomView, // All mode : shift + left click + DragView, // All mode : middle click + }; + TMouseMoveMode _MouseMode; + +public: + // Get the average position of selected items + bool getSelectedAverage (NLMISC::CVector &average); + + // Pick methods with a point + static bool pickPoint (const NLMISC::CVector &pickPos, const NLMISC::CVector &v0, const NLMISC::CVector &v1, float bias); + static bool pickPoint (const NLMISC::CVector &pickPos, const NLMISC::CVector &point, float bias); + + // Pick some primitives with a point + bool pickPoint (const NLMISC::CVector &pickPos, std::vector &result, bool pickOnlySelected); + + // Pick a primitive edge from selected primitive. Return the locator on the first edge vertex. + bool pickEdgePoint (const NLMISC::CVector &pickPos, std::vector &result); + + // Pick methods with a rect + static bool pickRect (const NLMISC::CVector &pickPosMin, const NLMISC::CVector &pickPosMax, const NLMISC::CVector &v0, const NLMISC::CVector &v1); + static bool pickRect (const NLMISC::CVector &pickPosMin, const NLMISC::CVector &pickPosMax, const NLMISC::CVector &point); + + // Pick some primitives with a rect + bool pickRect (const NLMISC::CVector &pickPosMin, const NLMISC::CVector &pickPosMax, std::vector &result, bool pickOnlyShown); + + // Set the display region + void setDisplayRegion (const NLMISC::CVector &min, const NLMISC::CVector &max); + + // center the display on a position (keep the same scale) + void setDisplayCenter (const NLMISC::CVector ¢er, bool zoom); + +private: + + // Proxy methods + void setupWorldMatrixAndFrustum (); + void initRenderProxy (); + void flushRenderProxy (); +public: + + // HOTSPOTS + enum THotSpot + { + BottomLeft=0, + MiddleLeft, + TopLeft, + MiddleBottom, + MiddleMiddle, + MiddleTop, + BottomRight, + MiddleRight, + TopRight, + HotSpotCount + }; + + + // CONVERSIONS + virtual void pixelToWorld (NLMISC::CVector &pixels); + virtual void pixelVectorToWorld (NLMISC::CVector &pixels); + // convert world unit to pixel units (integer precision) + virtual void worldToPixel (NLMISC::CVector &pixels); + // convert world unit to pixel units (float precision) + virtual void worldToFloatPixel(NLMISC::CVector &pixels); + // convert world unit to pixel units for a vector (integer precision) + virtual void worldVectorToPixelVector(NLMISC::CVector &pixels); + // convert world unit to pixel units for a vector (float precision) + virtual void worldVectorToFloatPixelVector(NLMISC::CVector &pixels); + virtual bool isClipped (const NLLIGO::CPrimVector *pVec, uint32 nNbVec); + + // UNTEXTURED PRIMITIVES + + virtual void lineRenderProxy (NLMISC::CRGBA color, const NLMISC::CVector& pos0, const NLMISC::CVector& pos1, uint primitiveLayer); + virtual void triRenderProxy (NLMISC::CRGBA color, const NLMISC::CVector& pos0, const NLMISC::CVector& pos1, const NLMISC::CVector& pos2, uint primitiveLayer); + virtual void pointRenderProxy (NLMISC::CRGBA color, const NLMISC::CVector& pos0); + virtual void primitiveRenderProxy(const NLLIGO::IPrimitive &primitive); + + // TEXT + // NB : rendering is done instantly, it is not buffered & delayed to the next flush as with the xxxxRenderProxy functions + // NB : coordinates are expressed in pixels + virtual void print(const ucstring &text, float x, float y, uint32 fontSize, NLMISC::CRGBA color, THotSpot hotspot); + virtual void print(const std::string &text, float x, float y, uint32 fontSize, NLMISC::CRGBA color, THotSpot hotspot); + + + + // TEXTURED PRIMITIVES + + // TODO nico : for now, using several textures is not convenient, because one has to call 'flush' before changing the texture, which is slow, + // This is not a good idea if a custom primitive displayer is used (because there's potentially one flush per primitive) + // intended usage is at post render time (in the 'postRender' method of plugins), in that way : + // call 'flush' + // set the wanted texture + // draw all quads with that texture + // and repeat for each new texture + // ideally, all quad texture should be packed in another bigger texture to avoid too much texture switching & flushs + // + // NB : no need to call 'flush' in the end, because the framework does it. + // NB : because of primitive layers, up to NUM_PRIM_LAYER textures can be set at once + + + + // Assign a texture to a primitive layer. Only the last set texture is used at render time, and affect all primitives of that layer + virtual void setLayerTexture(uint primitiveLayer, CPrimTexture *tex); + // Draw a textured quad. + virtual void texQuadRenderProxy(const NLMISC::CQuadColorUV &quad, uint primitiveLayer); + // flush render. Use it before changing texture for a layer + virtual void flush(); +private: + + // Draw a primitive + void drawPrimitive (const NLLIGO::IPrimitive *primitive, bool forceDefaultDisplay = false); + float intToWorld (uint value) const; + void drawLink (const NLLIGO::IPrimitive *first, const NLLIGO::IPrimitive *second); + + + + // Display meter grid points + void displayPoints (); + static bool isInTriangleOrEdge( double x, double y, + double xt1, double yt1, + double xt2, double yt2, + double xt3, double yt3 ); + + // Proxy primitive render + NLMISC::CMatrix _View2World; + NLMISC::CMatrix _World2View; + NL3D::CVertexBuffer _ProxyVB[NUM_PRIM_LAYER]; + NL3D::CVertexBufferReadWrite _ProxyVBAccess[NUM_PRIM_LAYER]; + NL3D::CVertexBuffer _ProxyVBPoints; + NL3D::CVertexBufferReadWrite _ProxyVBPointsAccess; + NL3D::CVertexBuffer _ProxyVBTexQuads[NUM_PRIM_LAYER]; + NL3D::CVertexBufferReadWrite _ProxyVBTexQuadsAccess[NUM_PRIM_LAYER]; + NL3D::CIndexBuffer _ProxyPBTri[NUM_PRIM_LAYER]; + NL3D::CIndexBufferReadWrite _ProxyPBTriAccess[NUM_PRIM_LAYER]; + NL3D::CIndexBuffer _ProxyPBLine[NUM_PRIM_LAYER]; + NL3D::CIndexBufferReadWrite _ProxyPBLineAccess[NUM_PRIM_LAYER]; + NL3D::CMaterial _ProxyMaterial; + NLMISC::CRefPtr _ProxyTexture[NUM_PRIM_LAYER]; + + + NL3D::CFontManager *_FontManager; + NL3D::CTextContext *_TextContext; + +public: + + CDisplay(); + ~CDisplay(); + + void init (CMainFrame *pMF); // pMF For update of the statusbar + void setCellSize (float size); + + void setBackgroundColor (NLMISC::CRGBA &col); + NLMISC::CRGBA getBackgroundColor (); + + void setDisplayGrid (bool bDisp); + bool getDisplayGrid (); + void calcCurView(); + void setFactor (float newFactor, bool follow, const NLMISC::CVector &position); + + NLMISC::CVector convertToWorld(CPoint &p); + + void renderSelection (); + void renderPluginPosition(); + + virtual void OnDraw (CDC* pDC); + + // Get interactif texts + bool getActionText (std::string &text); + bool getActionHelp (std::string &text); + +private: + + // Mouse handlers + enum TButton { Left, Middle, Right }; + + void buttonDown (TButton button, UINT nFlags, CPoint point); + void updateMouseMode (UINT nFlags); + + + afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct); + afx_msg void OnDestroy (); + + afx_msg BOOL OnMouseWheel (UINT nFlags, short zDelta, CPoint point); + afx_msg void OnMButtonDown (UINT nFlags, CPoint point); + afx_msg void OnMButtonUp (UINT nFlags, CPoint point); + afx_msg void OnLButtonDown (UINT nFlags, CPoint point); + afx_msg void OnLButtonDblClk (UINT nFlags, CPoint point); + afx_msg void OnLButtonUp (UINT nFlags, CPoint point); + afx_msg void OnRButtonDown (UINT nFlags, CPoint point); + afx_msg void OnRButtonUp (UINT nFlags, CPoint point); + afx_msg void OnMouseMove (UINT nFlags, CPoint point); + afx_msg void OnChar (UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnKeyUp (UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnSize (UINT nType, int cx, int cy); + afx_msg BOOL OnEraseBkgnd (CDC *pC); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + + DECLARE_MESSAGE_MAP() + +private: + + //void displayGrid(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDisplay) + protected: + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL +}; + +CDisplay *getDisplay (); + +#endif // DISPLAY_H +///////////////////////////////////////////////////////////////////////////// diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/editor_primitive.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/editor_primitive.cpp index cc3547121..896cd1aee 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/editor_primitive.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/editor_primitive.cpp @@ -1,1179 +1,1179 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" - -#include "editor_primitive.h" -#include "world_editor.h" -#include "tools_logic.h" -#include "dialog_properties.h" - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; -using namespace NL3D; -using namespace NLGEORGES; - -// *************************************************************************** - -/* - -Implementation notes: ---------------------- - -- Quad tree channels - - - Thoses actions must update the primitives quad grid iterator : - + Load project file (loadDocument) - + Import primitive file (CActionImportPrimitive) - + Load primitive file (CActionLoadPrimitive) - + New primitive file (CActionNewPrimitive) - + Clear primitive files (CActionClearPrimitives) - + Delete primitive file (CActionDeleteDatabaseElement) - + New primitive (CActionAddPrimitiveByClass) - + Delete prim (CActionDelete) - + Modify a primitive - + Move (CActionMove) - + Rotate (CActionRotate) - + Scale (CActionScale) - + Move points (CActionMove) - + Rotate points (CActionRotate) - + Scale points (CActionScale) - + Add points (CActionAddVertex) - + Delete points (CActionDeleteSub) - + Generate primitive (CActionAddPrimitive) - + Paste primitives (CActionAddPrimitive) - + Move primitive (CActionAddPrimitive) - - Show primitive - - Hide primitive - - - So, thoses actions classes must update the primitives quad grid iterator in there undo / redo methods : - - + CActionMove - InvalidatePrimitive / InvalidatePrimitive - + CActionRotate - InvalidatePrimitive / ModifiedPrimitive - + CActionScale - ModifiedPrimitive / ModifiedPrimitive - + CActionAddVertex - ModifiedPrimitive / ModifiedPrimitive - + CActionDeleteSub - ModifiedPrimitive / ModifiedPrimitive - + CActionDelete - ~IPrimitiveEditor / ModifiedPrimitive - + CActionAddPrimitiveByClass - ModifiedPrimitive / ~IPrimitiveEditor - + CActionAddPrimitive - ModifiedPrimitive / ~IPrimitiveEditor - - + CActionDeleteDatabaseElement - ~IPrimitiveEditor / InvalidatePrimitiveQuadGridRec - + CActionClearPrimitives - ~IPrimitiveEditor / InvalidatePrimitiveQuadGridRec - + CActionNewPrimitive - InvalidatePrimitiveQuadGridRec / ~IPrimitiveEditor - + CActionImportPrimitive - InvalidatePrimitiveQuadGridRec / ~IPrimitiveEditor - + CActionLoadPrimitive - InvalidatePrimitiveQuadGridRec / ~IPrimitiveEditor - - - Those methods must invalidate primitive quad grid too - - - loadDocument - InvalidatePrimitiveQuadGridRec - - - Those methods use the quad grid to select primitives - - - CDisplay::OnDraw - - CDisplay::pickPoint - - CDisplay::pickRect - -- Logic tree structure channel - - - Thoses actions must update the primitives logic tree structure : - - Load project file (loadDocument) - - Import primitive file (CActionImportPrimitive) - - Load primitive file (CActionLoadPrimitive) - - New primitive file (CActionNewPrimitive) - - Clear primitive files (CActionClearPrimitives) - - Delete primitive file (CActionDeleteDatabaseElement) - - New primitive (CActionAddPrimitiveByClass) - - Delete prim (CActionDelete) - - Generate primitive (CActionAddPrimitive) - - Paste primitives (CActionAddPrimitive) - - Move primitive (CActionAddPrimitive) - -- Logic tree parameters channel - - - Thoses actions must update the primitives logic tree parameters : - - Modify a primitive - - Modify properties () - - Show primitive - - Hide primitive - - -A modified primitive linked list is used to invalid primitive quad grid iterator only once. -In the global update, a call to UpdateQuadGrid () is done to update primitive in the linked list. -*/ - -// *************************************************************************** -// The primitive quad grid -// *************************************************************************** - -TPrimQuadGrid PrimitiveQuadGrid; - -// *************************************************************************** - -// Linked list of modified primitive -std::list ModifiedPrimitive; - -// *************************************************************************** - -// Linked list of selected primitive -std::list Selection; - -// *************************************************************************** - -void InitQuadGrid () -{ - // todo : Put those hard coded quadtree values in parameters - PrimitiveQuadGrid.create (256, 100.f); -} - -// *************************************************************************** - -//inline IPrimitiveEditor *getPrimitiveEditor (const IPrimitive *primitive) -//{ -////#ifdef NL_DEBUG -// return dynamic_cast (const_cast (primitive)); -////#else -//// return (IPrimitiveEditor*)(CPrimNodeEditor*)primitive; -////#endif -//} - -// *************************************************************************** - -void AddPrimitivesLogicTree (const CDatabaseLocatorPointer &locator, IPrimitiveEditor *primitiveEditor, CToolsLogic *toolWnd) -{ - if (toolWnd) - { - // My child id - HTREEITEM parentItem = TVI_ROOT; - HTREEITEM lastBrother = TVI_LAST; - - // Get its parent - const IPrimitive *parent = locator.Primitive->getParent (); - if (parent) - { - // Parent locator - IPrimitiveEditor *parentEditor = getPrimitiveEditor (const_cast(parent)); - - // Parent must be in the tree - parentItem = parentEditor->_TreeItem; - nlassert (parentEditor->_TreeItem); - - // Insert brothers - uint childId; - nlverify (parent->getChildId (childId, locator.Primitive)); - - // *** Insert after my first previous & visible brother - - lastBrother = TVI_FIRST; - while (childId > 0) - { - // Previous brother - const IPrimitive *brother; - nlverify (parent->getChild (brother, childId-1)); - - // Get the brother primitive editor - const IPrimitiveEditor *brotherEditor = getPrimitiveEditor (brother); - - // Last brother - if (brotherEditor->_TreeItem) - { - lastBrother = brotherEditor->_TreeItem; - break; - } - childId--; - } - } - else - { - uint childId = locator.getDatabaseIndex (); - - // *** Insert first my previous brothers - - if (childId == 0) - lastBrother = TVI_FIRST; - else if (childId > 0) - { - // Get the brother - CDatabaseLocatorPointer brotherLocator; - brotherLocator.getRoot (childId-1); - - // Get the brother primitive editor - const IPrimitiveEditor *brotherEditor = getPrimitiveEditor (brotherLocator.Primitive); - - // Last brother - lastBrother = brotherEditor->_TreeItem; - nlassert (lastBrother); - } - } - - // Add it - nlassert (primitiveEditor->_TreeItem == NULL); - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*locator.Primitive); - if (!primClass || primClass->Visible) - primitiveEditor->_TreeItem = toolWnd->addPrimitive (parentItem, lastBrother, locator); - - // Update tree item parameters - toolWnd->updatePrimitive (primitiveEditor->_TreeItem, locator); - } - - // Validate - primitiveEditor->_Channels &= ~(LogicTreeStruct|LogicTreeParam); -} - -// *************************************************************************** - -void UpdatePrimitiveSelection (IPrimitiveEditor *primitiveEditor, CDatabaseLocatorPointer &locator, bool &modified) -{ - // Is selected ? -// IProperty *prop; - if (getPrimitiveEditor(locator.Primitive)->getSelected()) -// if (locator.Primitive->getPropertyByName ("selected", prop)) - { - // In the list ? - if (primitiveEditor->_SelectionIterator == Selection.end ()) - { - // Add it to the selection list - Selection.push_front (const_cast (locator.Primitive)); - - // Get the iterator - primitiveEditor->_SelectionIterator = Selection.begin (); - modified = true; - } - } - else - { - // In the list ? - if (primitiveEditor->_SelectionIterator != Selection.end ()) - { - // Remove it - primitiveEditor->removeFromSelection (); - modified = true; - } - } -} - -// *************************************************************************** - -void UpdatePrimitives () -{ - // Get the tools window - CMainFrame *mainWnd = getMainFrame (); - if (mainWnd) - { - CToolsLogic *toolWnd = dynamic_cast(getMainFrame ()->m_wndSplitter.GetPane(0,1)); - - // Sort the list - static vector toSort; - toSort.clear (); - - CWorldEditorDoc *doc = getDocument (); - std::list::iterator ite = ModifiedPrimitive.begin (); - while (ite != ModifiedPrimitive.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - toSort.push_back (locator); - ite++; - } - sort (toSort.begin (), toSort.end ()); - - // For each modified primitive - sint i; - sint count = (sint)toSort.size (); - for (i=count-1; i>=0; i--) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, toSort[i].Primitive); - IPrimitiveEditor *primitiveEditor = getPrimitiveEditor (const_cast(toSort[i].Primitive)); - - // Logic tree structure modified ? - if (primitiveEditor->_Channels & LogicTreeStruct) - { - // Remove from the tree - primitiveEditor->removeFromLogicTree (); - } - } - - // Selection is changed ? - bool selectionChanged = false; - - // For each modified primitive - for (i=0; igetLocator (locator, primitive); - IPrimitiveEditor *primitiveEditor = getPrimitiveEditor (const_cast(primitive)); - - // Quad grid ? - if (primitiveEditor->_Channels & QuadTree) - { - // Remove from the container - primitiveEditor->removeFromQuadGrid (); - - // Num points - uint pointCount = (primitive)->getNumVector (); - if (pointCount > 0) - { - // Point pointer - const CPrimVector *points = (primitive)->getPrimVector (); - - // BBox - CAABBox bbox; - bbox.setCenter (points[0]); - - // Extend the bbox - uint j; - for (j=1; j_QuadIterator = PrimitiveQuadGrid.insert (bbox.getMin (), bbox.getMax (), const_cast (primitive)); - - // Get the linked primitives - const IPrimitive* linkedPrimitive = theApp.Config.getLinkedPrimitive (*primitive); - - // Is this primitive linked with another one ? - if (linkedPrimitive) - { - IPrimitiveEditor *primitiveEditorLinked = getPrimitiveEditor (const_cast(linkedPrimitive)); - if (linkedPrimitive->getNumVector () > 0) - { - bbox.setCenter (points[0]); - bbox.extend (linkedPrimitive->getPrimVector ()[0]); - - // Insert in the quadtree - primitiveEditor->_QuadIteratorLink = PrimitiveQuadGrid.insert (bbox.getMin (), bbox.getMax (), CQuadGridEntry - (const_cast (primitive), const_cast (linkedPrimitive))); - } - } - } - - // Validate - primitiveEditor->_Channels &= ~QuadTree; - } - - // Logic tree structure ? - if (primitiveEditor->_Channels & LogicTreeStruct) - { - // Add the primitive - AddPrimitivesLogicTree (locator, primitiveEditor, toolWnd); - - // The flag is validated by AddPrimitivesLogicTree - } - - // Logic tree parameters ? - if (primitiveEditor->_Channels & LogicTreeParam) - { - // Update tree item parameters - if (toolWnd) - toolWnd->updatePrimitive (primitiveEditor->_TreeItem, locator); - - // Validate - primitiveEditor->_Channels &= ~LogicTreeParam; - } - - // Selection ? - if (primitiveEditor->_Channels & _SelectionSelectState) - { - // Update the selection - UpdatePrimitiveSelection (primitiveEditor, locator, selectionChanged); - - // Validate - primitiveEditor->_Channels &= ~_SelectionSelectState; - } - - // Remove from the modified list - nlassert (primitiveEditor->_Channels == 0); - ModifiedPrimitive.erase (primitiveEditor->_ModifiedIterator); - primitiveEditor->_ModifiedIterator = ModifiedPrimitive.end (); - } - - /*// Change dialog selection ? - if (selectionChanged) - { - if ( pDlg ) - pDlg->changeSelection (Selection); - } -*/ - nlassert (ModifiedPrimitive.size ()==0); - } -} - -// *************************************************************************** - -void UpdateSelection () -{ - // Get the tools window - CToolsLogic *toolWnd = dynamic_cast(getMainFrame ()->m_wndSplitter.GetPane(0,1)); - - // Selection is changed ? - bool selectionChanged = false; - - // For each modified primitive - CWorldEditorDoc *doc = getDocument (); - std::list::iterator ite = ModifiedPrimitive.begin (); - while (ite != ModifiedPrimitive.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - IPrimitiveEditor *primitiveEditor = getPrimitiveEditor (*ite); - - // Selection ? - if (primitiveEditor->_Channels & _SelectionSelectState) - { - // Update the selection - UpdatePrimitiveSelection (primitiveEditor, locator, selectionChanged); - - // Validate - primitiveEditor->_Channels &= ~_SelectionSelectState; - } - - // Next primitive to update - ite++; - } - - /*// Change dialog selection ? - if (selectionChanged) - { - PropertyDialog.changeSelection (Selection); - }*/ -} - -// *************************************************************************** - -void InvalidatePrimitive (const CDatabaseLocatorPointer &locator, uint channels) -{ - if (locator.Primitive) - { - IPrimitiveEditor *primitiveEditor = getPrimitiveEditor (const_cast(locator.Primitive)); - - // No, link it - if (primitiveEditor->_ModifiedIterator == ModifiedPrimitive.end ()) - { - ModifiedPrimitive.push_front (const_cast (locator.Primitive)); - primitiveEditor->_ModifiedIterator = ModifiedPrimitive.begin (); - } - - // Add the channel flags - primitiveEditor->_Channels |= channels; - - // If invalidate QuadTree, check if the primitive is linked and if so, invalidate the linked primitives - if (channels & QuadTree) - { - // Next primitive - const IPrimitive* linkedPrimitive = theApp.Config.getLinkedPrimitive (*locator.Primitive); - if (linkedPrimitive) - { - IPrimitiveEditor *linkedPrimitiveEditor = getPrimitiveEditor (const_cast(linkedPrimitive)); - if (linkedPrimitiveEditor->_ModifiedIterator == ModifiedPrimitive.end ()) - { - ModifiedPrimitive.push_front (const_cast (linkedPrimitive)); - linkedPrimitiveEditor->_ModifiedIterator = ModifiedPrimitive.begin (); - } - linkedPrimitiveEditor->_Channels |= QuadTree; - } - - // Previous primitive - linkedPrimitive = theApp.Config.getPreviousLinkedPrimitive (*locator.Primitive); - if (linkedPrimitive) - { - IPrimitiveEditor *linkedPrimitiveEditor = getPrimitiveEditor (const_cast(linkedPrimitive)); - if (linkedPrimitiveEditor->_ModifiedIterator == ModifiedPrimitive.end ()) - { - ModifiedPrimitive.push_front (const_cast (linkedPrimitive)); - linkedPrimitiveEditor->_ModifiedIterator = ModifiedPrimitive.begin (); - } - linkedPrimitiveEditor->_Channels |= QuadTree; - } - } - } -} - -// *************************************************************************** - -void InvalidatePrimitiveRec (const CDatabaseLocatorPointer &locator, uint channels) -{ - // Invalidate this one - InvalidatePrimitive (locator, channels); - - // For each child - CDatabaseLocatorPointer myLocator = locator; - if (myLocator.firstChild ()) - { - do - { - InvalidatePrimitiveRec (myLocator, channels); - } - while (myLocator.nextChild ()); - } -} - -// *************************************************************************** - -void InvalidateAllPrimitives () -{ - // Erase all caches -/* Selection.clear (); - PrimitiveQuadGrid.clear (); - ModifiedPrimitive.clear ();*/ - - // Invalidate quad grid - CWorldEditorDoc *doc = getDocument (); - if (doc) - { - uint i; - uint count = doc->getNumDatabaseElement (); - for (i=0; igetNumDatabaseElement (); - for (i=0; igetDatabaseElements (i) == &primitives) - break; - } - - // If found, modify it - - if (i < count) - { - doc->modifyDatabase (i); - } -} - -// *************************************************************************** -// IPrimitiveEditor -// *************************************************************************** - -IPrimitiveEditor::~IPrimitiveEditor () -{ - removeFromQuadGrid (); - removeFromSelection (); - removeFromModified (); -} - -// *************************************************************************** - -void IPrimitiveEditor::postReadCallback(const NLLIGO::IPrimitive *thePrim) -{ - // hidden / selected / expanded flags are not readed anymore - _Hidden = false; - _Selected = false; - _Expanded = false; - - /* - // code to read flags from file - const std::string props = thePrim->getUnparsedProperties(); - - if (props.find("@selected") != string::npos) - _Selected = true; - else - _Selected = false; - - if (props.find("@expanded") != string::npos) - _Expanded = true; - else - _Expanded = false; - - if (props.find("@hidden") != string::npos) - _Hidden = true; - else - _Hidden = false; - */ -} - -// *************************************************************************** - -void IPrimitiveEditor::preWriteCallback(const NLLIGO::IPrimitive *thePrim) const -{ - /* - // code to write flags from file - string props; - if (_Selected) - props += "@selected"; - if (_Expanded) - props += "@expanded"; - if (_Hidden) - props += "@hidden"; - - thePrim->setUnparsedProperties(props); - */ -} - - -// *************************************************************************** - -void IPrimitiveEditor::removeFromQuadGrid () -{ - // Already inserted ? - if (_QuadIterator != PrimitiveQuadGrid.end ()) - { - // Remove from the container - PrimitiveQuadGrid.erase (_QuadIterator); - - // Clear it - _QuadIterator = PrimitiveQuadGrid.end (); - } - - // Link already inserted ? - if (_QuadIteratorLink != PrimitiveQuadGrid.end ()) - { - // Remove from the container - PrimitiveQuadGrid.erase (_QuadIteratorLink); - - // Clear it - _QuadIteratorLink = PrimitiveQuadGrid.end (); - } -} - -// *************************************************************************** - -void IPrimitiveEditor::resetTreeItemRec () -{ - _TreeItem = NULL; -} - -// *************************************************************************** - -void IPrimitiveEditor::removeFromLogicTree () -{ - // Already inserted ? - if (_TreeItem) - { - // Remove from the tree - CMainFrame *mainFrame = getMainFrame (); - if (mainFrame) - { - CToolsLogic *toolWnd = dynamic_cast(mainFrame->m_wndSplitter.GetPane(0,1)); - if (toolWnd) - toolWnd->GetTreeCtrl ()->DeleteItem (_TreeItem); - } - - // Null - resetTreeItemRec (); - } -} - -// *************************************************************************** - -void IPrimitiveEditor::removeFromSelection () -{ - // Already inserted ? - if (_SelectionIterator != Selection.end ()) - { - // Remove from the container - Selection.erase (_SelectionIterator); - - // Clear it - _SelectionIterator = Selection.end (); - } -} - -// *************************************************************************** - -void IPrimitiveEditor::removeFromModified () -{ - // Already inserted ? - if (_ModifiedIterator != ModifiedPrimitive.end ()) - { - // Remove from the container - ModifiedPrimitive.erase (_ModifiedIterator); - - // Clear it - _ModifiedIterator = ModifiedPrimitive.end (); - } -} - -// *************************************************************************** -// CPrimNodeEditor -// *************************************************************************** - -IPrimitive *CPrimNodeEditor::copy () const -{ - return new CPrimNodeEditor (*this); -} - -bool CPrimNodeEditor::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config) -{ - bool ret = CPrimNode::read(xmlNode, filename, version, config); - IPrimitiveEditor::postReadCallback(this); - return ret; -} - -void CPrimNodeEditor::write (xmlNodePtr xmlNode, const char *filename) const -{ - IPrimitiveEditor::preWriteCallback(this); - CPrimNode::write(xmlNode, filename); -} - -void CPrimNodeEditor::onModifyPrimitive (CPrimitives &primitives) const -{ - OnModifyPrimitive (primitives); -} - - -// *************************************************************************** -// CPrimPointEditor -// *************************************************************************** - -IPrimitive *CPrimPointEditor::copy () const -{ - return new CPrimPointEditor (*this); -} - -bool CPrimPointEditor::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config) -{ - bool ret = CPrimPoint::read(xmlNode, filename, version, config); - IPrimitiveEditor::postReadCallback(this); - return ret; -} - -void CPrimPointEditor::write (xmlNodePtr xmlNode, const char *filename) const -{ - IPrimitiveEditor::preWriteCallback(this); - CPrimPoint::write(xmlNode, filename); -} - -void CPrimPointEditor::onModifyPrimitive (CPrimitives &primitives) const -{ - OnModifyPrimitive (primitives); -} - -// *************************************************************************** -// CPrimPathEditor -// *************************************************************************** - -IPrimitive *CPrimPathEditor::copy () const -{ - return new CPrimPathEditor (*this); -} - -bool CPrimPathEditor::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config) -{ - bool ret = CPrimPath::read(xmlNode, filename, version, config); - IPrimitiveEditor::postReadCallback(this); - return ret; -} - -void CPrimPathEditor::write (xmlNodePtr xmlNode, const char *filename) const -{ - IPrimitiveEditor::preWriteCallback(this); - CPrimPath::write(xmlNode, filename); -} - -void CPrimPathEditor::onModifyPrimitive (CPrimitives &primitives) const -{ - OnModifyPrimitive (primitives); -} - - -// *************************************************************************** -// CPrimZoneEditor -// *************************************************************************** - -IPrimitive *CPrimZoneEditor::copy () const -{ - return new CPrimZoneEditor (*this); -} - -bool CPrimZoneEditor::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config) -{ - bool ret = CPrimZone::read(xmlNode, filename, version, config); - IPrimitiveEditor::postReadCallback(this); - return ret; -} - -void CPrimZoneEditor::write (xmlNodePtr xmlNode, const char *filename) const -{ - IPrimitiveEditor::preWriteCallback(this); - CPrimZone::write(xmlNode, filename); -} - -void CPrimZoneEditor::onModifyPrimitive (CPrimitives &primitives) const -{ - OnModifyPrimitive (primitives); -} - -// *************************************************************************** -// CPrimAliasEditor -// *************************************************************************** - -NLMISC::IClassable *CPrimAliasEditor::creator() -{ - return new CPrimAliasEditor; -} - -NLLIGO::IPrimitive *CPrimAliasEditor::copy () const -{ - return new CPrimAliasEditor(*this); -} - -bool CPrimAliasEditor::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config) -{ - bool ret = CPrimAlias::read(xmlNode, filename, version, config); - IPrimitiveEditor::postReadCallback(this); - return ret; -} - -void CPrimAliasEditor::write (xmlNodePtr xmlNode, const char *filename) const -{ - IPrimitiveEditor::preWriteCallback(this); - CPrimAlias::write(xmlNode, filename); -} - -void CPrimAliasEditor::onModifyPrimitive (CPrimitives &primitives) const -{ - OnModifyPrimitive (primitives); -} - -// *************************************************************************** -// CPrimBitmap -// *************************************************************************** - -CPrimBitmap::CPrimBitmap () -{ - _Loaded = false; -} - -// *************************************************************************** - -void CPrimBitmap::init (const char *filename) -{ - // Set the name - removePropertyByName ("filename"); - addPropertyByName ("filename", new CPropertyString (filename)); -} - -// *************************************************************************** - -NL3D::CTextureBlank *CPrimBitmap::getTexture () const -{ - // Not loaded - if (!_Loaded) - { - // Get the filename - string filename; - if (getPropertyByName ("filename", filename)) - { - _Texture = new CTextureBlank (); - _Texture->setWrapS (ITexture::Clamp); - _Texture->setWrapT (ITexture::Clamp); - _Texture->setReleasable (false); - try - { - CIFile iFile; - if (iFile.open (filename)) - { - // Load the texture - _Texture->load (iFile); - - // Power of 2 texture - uint width = raiseToNextPowerOf2 (_Texture->getWidth ()); - uint height = raiseToNextPowerOf2 (_Texture->getHeight()); - if ((width != _Texture->getWidth ()) || (height != _Texture->getHeight ())) - { - _Texture->resample (width, height); - } - } - else - { - theApp.errorMessage ("Can't read bitmap %s", filename.c_str ()); - } - } - catch (Exception &e) - { - theApp.errorMessage ("Error reading bitmap %s : %s", filename.c_str (), e.what ()); - } - } - } - _Loaded = true; - - return _Texture; -} - -// *************************************************************************** - -void VerifyPrimitivesStructures() -{ - getMainFrame()->launchLoadingDialog("checking primitives structures"); - // Invalidate quad grid - CWorldEditorDoc *doc = getDocument (); - if (doc) - { - // Begin modifications - doc->beginModification (); - - string path; - string errors; - uint i; - uint count = doc->getNumDatabaseElement (); - IPrimitiveEditor::StructureError error = IPrimitiveEditor::NoError; - for (i=0; iprogressLoadingDialog(float(i+0.0001f)/count); - if (doc->isEditable (i)) - { - // Is a primtive ? - CDatabaseLocatorPointer locator; - locator.getRoot (i); - error = (IPrimitiveEditor::StructureError)((sint)VerifyPrimitiveRec (locator, path, errors) | (sint)error); - //VerifyPrimitiveRec (locator); - - // auto generate missing ID - doc->resetUniqueID(*(doc->getDatabaseElements(i).RootNode), true); - } - } - // End modifications - doc->endModification (); - - if (error != IPrimitiveEditor::NoError) - { - errors = "Found errors in the tree structure:\n"+errors; - int first = errors.find_first_not_of ("\n"); - int end = errors.find_first_of ("\n"); - while (first != string::npos) - { - nlwarning (errors.substr(first, end-first).c_str()); - first = end; - end = errors.find_first_of ("\n", end+1); - } - - theApp.errorMessage (errors.c_str()); - } - } - getMainFrame()->terminateLoadingDialog(); -} - -IPrimitiveEditor::StructureError VerifyPrimitiveRec (const CDatabaseLocatorPointer &locator, const string &path, string &errors) -{ - IPrimitiveEditor::StructureError error = IPrimitiveEditor::NoError; - // For every child, we check the errors - CDatabaseLocatorPointer myLocator = locator; - - const IPrimitive *primitive = locator.Primitive; - string newPath = "?"; - if (primitive) - { - if (primitive->getParent()) - { - primitive->getPropertyByName ("name", newPath); - newPath = ":"+newPath; - } - else - { - CWorldEditorDoc *doc = getDocument (); - uint databaseIndex = locator.getDatabaseIndex (); - newPath = doc->getDatabaseElement (databaseIndex); - } - } - newPath = path + newPath; - - // we parse the tree recursively, collection errors, and propagating to the parent - if (myLocator.firstChild ()) - { - do - { - // not very elegant, but we need to set bit fields - error = (IPrimitiveEditor::StructureError)((sint)VerifyPrimitiveRec (myLocator, newPath, errors) | (sint)error); - } - while (myLocator.nextChild ()); - } - // when we finished to recurse the tree, we simply check if the StaticChildren are all here - // all other children MUST be either Dynamic or Generated - - if (primitive) - { - string className; - bool Success; - Success = primitive->getPropertyByName ("class", className); - - if (!Success) - { - // is this the root node ? - const IPrimitive *parent = primitive->getParent(); - if (!parent) - { - // if no parent, we have a root node - className = "root"; - Success = true; - } - } - if (Success) - { - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (className.c_str ()); - if (primClass) - { - uint CountStaticChildren = 0; - uint MissingChildren = 0; - myLocator = locator; - // we parse the tree recursively, collection errors, and propagating to the parent - if (myLocator.firstChild ()) - { - do - { - const IPrimitive *primitive2 = myLocator.Primitive; - if (primitive2) - { - string ClassName2; - nlverify (primitive2->getPropertyByName ("class", ClassName2)); - string name; - if (primitive2->getPropertyByName ("name", name)) - { - uint c; - bool Found = false; - for (c=0; cStaticChildren.size (); c++) - { - if (primClass->StaticChildren[c].ClassName == ClassName2 && - primClass->StaticChildren[c].Name == name) - { - Found = true; - ++CountStaticChildren; - break; - } - } - - for (c=0; cGeneratedChildren.size (); c++) - { - if (primClass->GeneratedChildren[c].ClassName == ClassName2) - { - Found = true; - break; - } - } - - for (c=0; cDynamicChildren.size (); c++) - { - if (primClass->DynamicChildren[c].ClassName == ClassName2) - { - Found = true; - break; - } - } - if (!Found) - { - ++MissingChildren; - - // Mark the child as error - IPrimitiveEditor *childPrimitiveEditor = getPrimitiveEditor (const_cast(primitive2)); - childPrimitiveEditor->_Error = IPrimitiveEditor::InExcessField; - InvalidatePrimitive (myLocator, LogicTreeParam); - - string childName; - primitive2->getPropertyByName ("name", childName); - errors += newPath + " : " + "The child \"" + childName + "\" (class \"" + ClassName2 + "\") is not declared in class \"" + className + "\".\n"; - } - } - } - } - while (myLocator.nextChild ()); - } - if (MissingChildren) - { - error = IPrimitiveEditor::InExcessField; - } - if (CountStaticChildren != primClass->StaticChildren.size()) - { - error = IPrimitiveEditor::InExcessField; - errors += newPath+" : "+"Missing static children.\n"; - } - } - } - } - - if (locator.Primitive) - { - IPrimitiveEditor *primitiveEditor = getPrimitiveEditor (const_cast(locator.Primitive)); - - // set the error message - primitiveEditor->_Error = error; - InvalidatePrimitive (locator, LogicTreeParam); - } - return error; -} - - -const IPrimitiveEditor *getPrimitiveEditor(const NLLIGO::IPrimitive *primitive) -{ - if (primitive == NULL) - return NULL; - - const CPrimNodeEditor *pne = dynamic_cast(primitive); - if (pne) - { - return pne; - } - const CPrimPathEditor *ppe = dynamic_cast(primitive); - if (ppe) - { - return ppe; - } - const CPrimZoneEditor *pze = dynamic_cast(primitive); - if (pze) - { - return pze; - } - const CPrimPointEditor *ppte = dynamic_cast(primitive); - if (ppte) - { - return ppte; - } - const CPrimAliasEditor *pae = dynamic_cast(primitive); - if (pae) - { - return pae; - } - - nlassert(false); - return NULL; - -} - -IPrimitiveEditor *getPrimitiveEditor(NLLIGO::IPrimitive *primitive) -{ - return const_cast(getPrimitiveEditor(const_cast(primitive))); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" + +#include "editor_primitive.h" +#include "world_editor.h" +#include "tools_logic.h" +#include "dialog_properties.h" + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; +using namespace NL3D; +using namespace NLGEORGES; + +// *************************************************************************** + +/* + +Implementation notes: +--------------------- + +- Quad tree channels + + - Thoses actions must update the primitives quad grid iterator : + + Load project file (loadDocument) + + Import primitive file (CActionImportPrimitive) + + Load primitive file (CActionLoadPrimitive) + + New primitive file (CActionNewPrimitive) + + Clear primitive files (CActionClearPrimitives) + + Delete primitive file (CActionDeleteDatabaseElement) + + New primitive (CActionAddPrimitiveByClass) + + Delete prim (CActionDelete) + + Modify a primitive + + Move (CActionMove) + + Rotate (CActionRotate) + + Scale (CActionScale) + + Move points (CActionMove) + + Rotate points (CActionRotate) + + Scale points (CActionScale) + + Add points (CActionAddVertex) + + Delete points (CActionDeleteSub) + + Generate primitive (CActionAddPrimitive) + + Paste primitives (CActionAddPrimitive) + + Move primitive (CActionAddPrimitive) + - Show primitive + - Hide primitive + + - So, thoses actions classes must update the primitives quad grid iterator in there undo / redo methods : + + + CActionMove + InvalidatePrimitive / InvalidatePrimitive + + CActionRotate + InvalidatePrimitive / ModifiedPrimitive + + CActionScale + ModifiedPrimitive / ModifiedPrimitive + + CActionAddVertex + ModifiedPrimitive / ModifiedPrimitive + + CActionDeleteSub + ModifiedPrimitive / ModifiedPrimitive + + CActionDelete + ~IPrimitiveEditor / ModifiedPrimitive + + CActionAddPrimitiveByClass + ModifiedPrimitive / ~IPrimitiveEditor + + CActionAddPrimitive + ModifiedPrimitive / ~IPrimitiveEditor + + + CActionDeleteDatabaseElement + ~IPrimitiveEditor / InvalidatePrimitiveQuadGridRec + + CActionClearPrimitives + ~IPrimitiveEditor / InvalidatePrimitiveQuadGridRec + + CActionNewPrimitive + InvalidatePrimitiveQuadGridRec / ~IPrimitiveEditor + + CActionImportPrimitive + InvalidatePrimitiveQuadGridRec / ~IPrimitiveEditor + + CActionLoadPrimitive + InvalidatePrimitiveQuadGridRec / ~IPrimitiveEditor + + - Those methods must invalidate primitive quad grid too + + - loadDocument + InvalidatePrimitiveQuadGridRec + + - Those methods use the quad grid to select primitives + + - CDisplay::OnDraw + - CDisplay::pickPoint + - CDisplay::pickRect + +- Logic tree structure channel + + - Thoses actions must update the primitives logic tree structure : + - Load project file (loadDocument) + - Import primitive file (CActionImportPrimitive) + - Load primitive file (CActionLoadPrimitive) + - New primitive file (CActionNewPrimitive) + - Clear primitive files (CActionClearPrimitives) + - Delete primitive file (CActionDeleteDatabaseElement) + - New primitive (CActionAddPrimitiveByClass) + - Delete prim (CActionDelete) + - Generate primitive (CActionAddPrimitive) + - Paste primitives (CActionAddPrimitive) + - Move primitive (CActionAddPrimitive) + +- Logic tree parameters channel + + - Thoses actions must update the primitives logic tree parameters : + - Modify a primitive + - Modify properties () + - Show primitive + - Hide primitive + + +A modified primitive linked list is used to invalid primitive quad grid iterator only once. +In the global update, a call to UpdateQuadGrid () is done to update primitive in the linked list. +*/ + +// *************************************************************************** +// The primitive quad grid +// *************************************************************************** + +TPrimQuadGrid PrimitiveQuadGrid; + +// *************************************************************************** + +// Linked list of modified primitive +std::list ModifiedPrimitive; + +// *************************************************************************** + +// Linked list of selected primitive +std::list Selection; + +// *************************************************************************** + +void InitQuadGrid () +{ + // todo : Put those hard coded quadtree values in parameters + PrimitiveQuadGrid.create (256, 100.f); +} + +// *************************************************************************** + +//inline IPrimitiveEditor *getPrimitiveEditor (const IPrimitive *primitive) +//{ +////#ifdef NL_DEBUG +// return dynamic_cast (const_cast (primitive)); +////#else +//// return (IPrimitiveEditor*)(CPrimNodeEditor*)primitive; +////#endif +//} + +// *************************************************************************** + +void AddPrimitivesLogicTree (const CDatabaseLocatorPointer &locator, IPrimitiveEditor *primitiveEditor, CToolsLogic *toolWnd) +{ + if (toolWnd) + { + // My child id + HTREEITEM parentItem = TVI_ROOT; + HTREEITEM lastBrother = TVI_LAST; + + // Get its parent + const IPrimitive *parent = locator.Primitive->getParent (); + if (parent) + { + // Parent locator + IPrimitiveEditor *parentEditor = getPrimitiveEditor (const_cast(parent)); + + // Parent must be in the tree + parentItem = parentEditor->_TreeItem; + nlassert (parentEditor->_TreeItem); + + // Insert brothers + uint childId; + nlverify (parent->getChildId (childId, locator.Primitive)); + + // *** Insert after my first previous & visible brother + + lastBrother = TVI_FIRST; + while (childId > 0) + { + // Previous brother + const IPrimitive *brother; + nlverify (parent->getChild (brother, childId-1)); + + // Get the brother primitive editor + const IPrimitiveEditor *brotherEditor = getPrimitiveEditor (brother); + + // Last brother + if (brotherEditor->_TreeItem) + { + lastBrother = brotherEditor->_TreeItem; + break; + } + childId--; + } + } + else + { + uint childId = locator.getDatabaseIndex (); + + // *** Insert first my previous brothers + + if (childId == 0) + lastBrother = TVI_FIRST; + else if (childId > 0) + { + // Get the brother + CDatabaseLocatorPointer brotherLocator; + brotherLocator.getRoot (childId-1); + + // Get the brother primitive editor + const IPrimitiveEditor *brotherEditor = getPrimitiveEditor (brotherLocator.Primitive); + + // Last brother + lastBrother = brotherEditor->_TreeItem; + nlassert (lastBrother); + } + } + + // Add it + nlassert (primitiveEditor->_TreeItem == NULL); + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*locator.Primitive); + if (!primClass || primClass->Visible) + primitiveEditor->_TreeItem = toolWnd->addPrimitive (parentItem, lastBrother, locator); + + // Update tree item parameters + toolWnd->updatePrimitive (primitiveEditor->_TreeItem, locator); + } + + // Validate + primitiveEditor->_Channels &= ~(LogicTreeStruct|LogicTreeParam); +} + +// *************************************************************************** + +void UpdatePrimitiveSelection (IPrimitiveEditor *primitiveEditor, CDatabaseLocatorPointer &locator, bool &modified) +{ + // Is selected ? +// IProperty *prop; + if (getPrimitiveEditor(locator.Primitive)->getSelected()) +// if (locator.Primitive->getPropertyByName ("selected", prop)) + { + // In the list ? + if (primitiveEditor->_SelectionIterator == Selection.end ()) + { + // Add it to the selection list + Selection.push_front (const_cast (locator.Primitive)); + + // Get the iterator + primitiveEditor->_SelectionIterator = Selection.begin (); + modified = true; + } + } + else + { + // In the list ? + if (primitiveEditor->_SelectionIterator != Selection.end ()) + { + // Remove it + primitiveEditor->removeFromSelection (); + modified = true; + } + } +} + +// *************************************************************************** + +void UpdatePrimitives () +{ + // Get the tools window + CMainFrame *mainWnd = getMainFrame (); + if (mainWnd) + { + CToolsLogic *toolWnd = dynamic_cast(getMainFrame ()->m_wndSplitter.GetPane(0,1)); + + // Sort the list + static vector toSort; + toSort.clear (); + + CWorldEditorDoc *doc = getDocument (); + std::list::iterator ite = ModifiedPrimitive.begin (); + while (ite != ModifiedPrimitive.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + toSort.push_back (locator); + ite++; + } + sort (toSort.begin (), toSort.end ()); + + // For each modified primitive + sint i; + sint count = (sint)toSort.size (); + for (i=count-1; i>=0; i--) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, toSort[i].Primitive); + IPrimitiveEditor *primitiveEditor = getPrimitiveEditor (const_cast(toSort[i].Primitive)); + + // Logic tree structure modified ? + if (primitiveEditor->_Channels & LogicTreeStruct) + { + // Remove from the tree + primitiveEditor->removeFromLogicTree (); + } + } + + // Selection is changed ? + bool selectionChanged = false; + + // For each modified primitive + for (i=0; igetLocator (locator, primitive); + IPrimitiveEditor *primitiveEditor = getPrimitiveEditor (const_cast(primitive)); + + // Quad grid ? + if (primitiveEditor->_Channels & QuadTree) + { + // Remove from the container + primitiveEditor->removeFromQuadGrid (); + + // Num points + uint pointCount = (primitive)->getNumVector (); + if (pointCount > 0) + { + // Point pointer + const CPrimVector *points = (primitive)->getPrimVector (); + + // BBox + CAABBox bbox; + bbox.setCenter (points[0]); + + // Extend the bbox + uint j; + for (j=1; j_QuadIterator = PrimitiveQuadGrid.insert (bbox.getMin (), bbox.getMax (), const_cast (primitive)); + + // Get the linked primitives + const IPrimitive* linkedPrimitive = theApp.Config.getLinkedPrimitive (*primitive); + + // Is this primitive linked with another one ? + if (linkedPrimitive) + { + IPrimitiveEditor *primitiveEditorLinked = getPrimitiveEditor (const_cast(linkedPrimitive)); + if (linkedPrimitive->getNumVector () > 0) + { + bbox.setCenter (points[0]); + bbox.extend (linkedPrimitive->getPrimVector ()[0]); + + // Insert in the quadtree + primitiveEditor->_QuadIteratorLink = PrimitiveQuadGrid.insert (bbox.getMin (), bbox.getMax (), CQuadGridEntry + (const_cast (primitive), const_cast (linkedPrimitive))); + } + } + } + + // Validate + primitiveEditor->_Channels &= ~QuadTree; + } + + // Logic tree structure ? + if (primitiveEditor->_Channels & LogicTreeStruct) + { + // Add the primitive + AddPrimitivesLogicTree (locator, primitiveEditor, toolWnd); + + // The flag is validated by AddPrimitivesLogicTree + } + + // Logic tree parameters ? + if (primitiveEditor->_Channels & LogicTreeParam) + { + // Update tree item parameters + if (toolWnd) + toolWnd->updatePrimitive (primitiveEditor->_TreeItem, locator); + + // Validate + primitiveEditor->_Channels &= ~LogicTreeParam; + } + + // Selection ? + if (primitiveEditor->_Channels & _SelectionSelectState) + { + // Update the selection + UpdatePrimitiveSelection (primitiveEditor, locator, selectionChanged); + + // Validate + primitiveEditor->_Channels &= ~_SelectionSelectState; + } + + // Remove from the modified list + nlassert (primitiveEditor->_Channels == 0); + ModifiedPrimitive.erase (primitiveEditor->_ModifiedIterator); + primitiveEditor->_ModifiedIterator = ModifiedPrimitive.end (); + } + + /*// Change dialog selection ? + if (selectionChanged) + { + if ( pDlg ) + pDlg->changeSelection (Selection); + } +*/ + nlassert (ModifiedPrimitive.size ()==0); + } +} + +// *************************************************************************** + +void UpdateSelection () +{ + // Get the tools window + CToolsLogic *toolWnd = dynamic_cast(getMainFrame ()->m_wndSplitter.GetPane(0,1)); + + // Selection is changed ? + bool selectionChanged = false; + + // For each modified primitive + CWorldEditorDoc *doc = getDocument (); + std::list::iterator ite = ModifiedPrimitive.begin (); + while (ite != ModifiedPrimitive.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + IPrimitiveEditor *primitiveEditor = getPrimitiveEditor (*ite); + + // Selection ? + if (primitiveEditor->_Channels & _SelectionSelectState) + { + // Update the selection + UpdatePrimitiveSelection (primitiveEditor, locator, selectionChanged); + + // Validate + primitiveEditor->_Channels &= ~_SelectionSelectState; + } + + // Next primitive to update + ite++; + } + + /*// Change dialog selection ? + if (selectionChanged) + { + PropertyDialog.changeSelection (Selection); + }*/ +} + +// *************************************************************************** + +void InvalidatePrimitive (const CDatabaseLocatorPointer &locator, uint channels) +{ + if (locator.Primitive) + { + IPrimitiveEditor *primitiveEditor = getPrimitiveEditor (const_cast(locator.Primitive)); + + // No, link it + if (primitiveEditor->_ModifiedIterator == ModifiedPrimitive.end ()) + { + ModifiedPrimitive.push_front (const_cast (locator.Primitive)); + primitiveEditor->_ModifiedIterator = ModifiedPrimitive.begin (); + } + + // Add the channel flags + primitiveEditor->_Channels |= channels; + + // If invalidate QuadTree, check if the primitive is linked and if so, invalidate the linked primitives + if (channels & QuadTree) + { + // Next primitive + const IPrimitive* linkedPrimitive = theApp.Config.getLinkedPrimitive (*locator.Primitive); + if (linkedPrimitive) + { + IPrimitiveEditor *linkedPrimitiveEditor = getPrimitiveEditor (const_cast(linkedPrimitive)); + if (linkedPrimitiveEditor->_ModifiedIterator == ModifiedPrimitive.end ()) + { + ModifiedPrimitive.push_front (const_cast (linkedPrimitive)); + linkedPrimitiveEditor->_ModifiedIterator = ModifiedPrimitive.begin (); + } + linkedPrimitiveEditor->_Channels |= QuadTree; + } + + // Previous primitive + linkedPrimitive = theApp.Config.getPreviousLinkedPrimitive (*locator.Primitive); + if (linkedPrimitive) + { + IPrimitiveEditor *linkedPrimitiveEditor = getPrimitiveEditor (const_cast(linkedPrimitive)); + if (linkedPrimitiveEditor->_ModifiedIterator == ModifiedPrimitive.end ()) + { + ModifiedPrimitive.push_front (const_cast (linkedPrimitive)); + linkedPrimitiveEditor->_ModifiedIterator = ModifiedPrimitive.begin (); + } + linkedPrimitiveEditor->_Channels |= QuadTree; + } + } + } +} + +// *************************************************************************** + +void InvalidatePrimitiveRec (const CDatabaseLocatorPointer &locator, uint channels) +{ + // Invalidate this one + InvalidatePrimitive (locator, channels); + + // For each child + CDatabaseLocatorPointer myLocator = locator; + if (myLocator.firstChild ()) + { + do + { + InvalidatePrimitiveRec (myLocator, channels); + } + while (myLocator.nextChild ()); + } +} + +// *************************************************************************** + +void InvalidateAllPrimitives () +{ + // Erase all caches +/* Selection.clear (); + PrimitiveQuadGrid.clear (); + ModifiedPrimitive.clear ();*/ + + // Invalidate quad grid + CWorldEditorDoc *doc = getDocument (); + if (doc) + { + uint i; + uint count = doc->getNumDatabaseElement (); + for (i=0; igetNumDatabaseElement (); + for (i=0; igetDatabaseElements (i) == &primitives) + break; + } + + // If found, modify it + + if (i < count) + { + doc->modifyDatabase (i); + } +} + +// *************************************************************************** +// IPrimitiveEditor +// *************************************************************************** + +IPrimitiveEditor::~IPrimitiveEditor () +{ + removeFromQuadGrid (); + removeFromSelection (); + removeFromModified (); +} + +// *************************************************************************** + +void IPrimitiveEditor::postReadCallback(const NLLIGO::IPrimitive *thePrim) +{ + // hidden / selected / expanded flags are not readed anymore + _Hidden = false; + _Selected = false; + _Expanded = false; + + /* + // code to read flags from file + const std::string props = thePrim->getUnparsedProperties(); + + if (props.find("@selected") != string::npos) + _Selected = true; + else + _Selected = false; + + if (props.find("@expanded") != string::npos) + _Expanded = true; + else + _Expanded = false; + + if (props.find("@hidden") != string::npos) + _Hidden = true; + else + _Hidden = false; + */ +} + +// *************************************************************************** + +void IPrimitiveEditor::preWriteCallback(const NLLIGO::IPrimitive *thePrim) const +{ + /* + // code to write flags from file + string props; + if (_Selected) + props += "@selected"; + if (_Expanded) + props += "@expanded"; + if (_Hidden) + props += "@hidden"; + + thePrim->setUnparsedProperties(props); + */ +} + + +// *************************************************************************** + +void IPrimitiveEditor::removeFromQuadGrid () +{ + // Already inserted ? + if (_QuadIterator != PrimitiveQuadGrid.end ()) + { + // Remove from the container + PrimitiveQuadGrid.erase (_QuadIterator); + + // Clear it + _QuadIterator = PrimitiveQuadGrid.end (); + } + + // Link already inserted ? + if (_QuadIteratorLink != PrimitiveQuadGrid.end ()) + { + // Remove from the container + PrimitiveQuadGrid.erase (_QuadIteratorLink); + + // Clear it + _QuadIteratorLink = PrimitiveQuadGrid.end (); + } +} + +// *************************************************************************** + +void IPrimitiveEditor::resetTreeItemRec () +{ + _TreeItem = NULL; +} + +// *************************************************************************** + +void IPrimitiveEditor::removeFromLogicTree () +{ + // Already inserted ? + if (_TreeItem) + { + // Remove from the tree + CMainFrame *mainFrame = getMainFrame (); + if (mainFrame) + { + CToolsLogic *toolWnd = dynamic_cast(mainFrame->m_wndSplitter.GetPane(0,1)); + if (toolWnd) + toolWnd->GetTreeCtrl ()->DeleteItem (_TreeItem); + } + + // Null + resetTreeItemRec (); + } +} + +// *************************************************************************** + +void IPrimitiveEditor::removeFromSelection () +{ + // Already inserted ? + if (_SelectionIterator != Selection.end ()) + { + // Remove from the container + Selection.erase (_SelectionIterator); + + // Clear it + _SelectionIterator = Selection.end (); + } +} + +// *************************************************************************** + +void IPrimitiveEditor::removeFromModified () +{ + // Already inserted ? + if (_ModifiedIterator != ModifiedPrimitive.end ()) + { + // Remove from the container + ModifiedPrimitive.erase (_ModifiedIterator); + + // Clear it + _ModifiedIterator = ModifiedPrimitive.end (); + } +} + +// *************************************************************************** +// CPrimNodeEditor +// *************************************************************************** + +IPrimitive *CPrimNodeEditor::copy () const +{ + return new CPrimNodeEditor (*this); +} + +bool CPrimNodeEditor::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config) +{ + bool ret = CPrimNode::read(xmlNode, filename, version, config); + IPrimitiveEditor::postReadCallback(this); + return ret; +} + +void CPrimNodeEditor::write (xmlNodePtr xmlNode, const char *filename) const +{ + IPrimitiveEditor::preWriteCallback(this); + CPrimNode::write(xmlNode, filename); +} + +void CPrimNodeEditor::onModifyPrimitive (CPrimitives &primitives) const +{ + OnModifyPrimitive (primitives); +} + + +// *************************************************************************** +// CPrimPointEditor +// *************************************************************************** + +IPrimitive *CPrimPointEditor::copy () const +{ + return new CPrimPointEditor (*this); +} + +bool CPrimPointEditor::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config) +{ + bool ret = CPrimPoint::read(xmlNode, filename, version, config); + IPrimitiveEditor::postReadCallback(this); + return ret; +} + +void CPrimPointEditor::write (xmlNodePtr xmlNode, const char *filename) const +{ + IPrimitiveEditor::preWriteCallback(this); + CPrimPoint::write(xmlNode, filename); +} + +void CPrimPointEditor::onModifyPrimitive (CPrimitives &primitives) const +{ + OnModifyPrimitive (primitives); +} + +// *************************************************************************** +// CPrimPathEditor +// *************************************************************************** + +IPrimitive *CPrimPathEditor::copy () const +{ + return new CPrimPathEditor (*this); +} + +bool CPrimPathEditor::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config) +{ + bool ret = CPrimPath::read(xmlNode, filename, version, config); + IPrimitiveEditor::postReadCallback(this); + return ret; +} + +void CPrimPathEditor::write (xmlNodePtr xmlNode, const char *filename) const +{ + IPrimitiveEditor::preWriteCallback(this); + CPrimPath::write(xmlNode, filename); +} + +void CPrimPathEditor::onModifyPrimitive (CPrimitives &primitives) const +{ + OnModifyPrimitive (primitives); +} + + +// *************************************************************************** +// CPrimZoneEditor +// *************************************************************************** + +IPrimitive *CPrimZoneEditor::copy () const +{ + return new CPrimZoneEditor (*this); +} + +bool CPrimZoneEditor::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config) +{ + bool ret = CPrimZone::read(xmlNode, filename, version, config); + IPrimitiveEditor::postReadCallback(this); + return ret; +} + +void CPrimZoneEditor::write (xmlNodePtr xmlNode, const char *filename) const +{ + IPrimitiveEditor::preWriteCallback(this); + CPrimZone::write(xmlNode, filename); +} + +void CPrimZoneEditor::onModifyPrimitive (CPrimitives &primitives) const +{ + OnModifyPrimitive (primitives); +} + +// *************************************************************************** +// CPrimAliasEditor +// *************************************************************************** + +NLMISC::IClassable *CPrimAliasEditor::creator() +{ + return new CPrimAliasEditor; +} + +NLLIGO::IPrimitive *CPrimAliasEditor::copy () const +{ + return new CPrimAliasEditor(*this); +} + +bool CPrimAliasEditor::read (xmlNodePtr xmlNode, const char *filename, uint version, CLigoConfig &config) +{ + bool ret = CPrimAlias::read(xmlNode, filename, version, config); + IPrimitiveEditor::postReadCallback(this); + return ret; +} + +void CPrimAliasEditor::write (xmlNodePtr xmlNode, const char *filename) const +{ + IPrimitiveEditor::preWriteCallback(this); + CPrimAlias::write(xmlNode, filename); +} + +void CPrimAliasEditor::onModifyPrimitive (CPrimitives &primitives) const +{ + OnModifyPrimitive (primitives); +} + +// *************************************************************************** +// CPrimBitmap +// *************************************************************************** + +CPrimBitmap::CPrimBitmap () +{ + _Loaded = false; +} + +// *************************************************************************** + +void CPrimBitmap::init (const char *filename) +{ + // Set the name + removePropertyByName ("filename"); + addPropertyByName ("filename", new CPropertyString (filename)); +} + +// *************************************************************************** + +NL3D::CTextureBlank *CPrimBitmap::getTexture () const +{ + // Not loaded + if (!_Loaded) + { + // Get the filename + string filename; + if (getPropertyByName ("filename", filename)) + { + _Texture = new CTextureBlank (); + _Texture->setWrapS (ITexture::Clamp); + _Texture->setWrapT (ITexture::Clamp); + _Texture->setReleasable (false); + try + { + CIFile iFile; + if (iFile.open (filename)) + { + // Load the texture + _Texture->load (iFile); + + // Power of 2 texture + uint width = raiseToNextPowerOf2 (_Texture->getWidth ()); + uint height = raiseToNextPowerOf2 (_Texture->getHeight()); + if ((width != _Texture->getWidth ()) || (height != _Texture->getHeight ())) + { + _Texture->resample (width, height); + } + } + else + { + theApp.errorMessage ("Can't read bitmap %s", filename.c_str ()); + } + } + catch (Exception &e) + { + theApp.errorMessage ("Error reading bitmap %s : %s", filename.c_str (), e.what ()); + } + } + } + _Loaded = true; + + return _Texture; +} + +// *************************************************************************** + +void VerifyPrimitivesStructures() +{ + getMainFrame()->launchLoadingDialog("checking primitives structures"); + // Invalidate quad grid + CWorldEditorDoc *doc = getDocument (); + if (doc) + { + // Begin modifications + doc->beginModification (); + + string path; + string errors; + uint i; + uint count = doc->getNumDatabaseElement (); + IPrimitiveEditor::StructureError error = IPrimitiveEditor::NoError; + for (i=0; iprogressLoadingDialog(float(i+0.0001f)/count); + if (doc->isEditable (i)) + { + // Is a primtive ? + CDatabaseLocatorPointer locator; + locator.getRoot (i); + error = (IPrimitiveEditor::StructureError)((sint)VerifyPrimitiveRec (locator, path, errors) | (sint)error); + //VerifyPrimitiveRec (locator); + + // auto generate missing ID + doc->resetUniqueID(*(doc->getDatabaseElements(i).RootNode), true); + } + } + // End modifications + doc->endModification (); + + if (error != IPrimitiveEditor::NoError) + { + errors = "Found errors in the tree structure:\n"+errors; + int first = errors.find_first_not_of ("\n"); + int end = errors.find_first_of ("\n"); + while (first != string::npos) + { + nlwarning (errors.substr(first, end-first).c_str()); + first = end; + end = errors.find_first_of ("\n", end+1); + } + + theApp.errorMessage (errors.c_str()); + } + } + getMainFrame()->terminateLoadingDialog(); +} + +IPrimitiveEditor::StructureError VerifyPrimitiveRec (const CDatabaseLocatorPointer &locator, const string &path, string &errors) +{ + IPrimitiveEditor::StructureError error = IPrimitiveEditor::NoError; + // For every child, we check the errors + CDatabaseLocatorPointer myLocator = locator; + + const IPrimitive *primitive = locator.Primitive; + string newPath = "?"; + if (primitive) + { + if (primitive->getParent()) + { + primitive->getPropertyByName ("name", newPath); + newPath = ":"+newPath; + } + else + { + CWorldEditorDoc *doc = getDocument (); + uint databaseIndex = locator.getDatabaseIndex (); + newPath = doc->getDatabaseElement (databaseIndex); + } + } + newPath = path + newPath; + + // we parse the tree recursively, collection errors, and propagating to the parent + if (myLocator.firstChild ()) + { + do + { + // not very elegant, but we need to set bit fields + error = (IPrimitiveEditor::StructureError)((sint)VerifyPrimitiveRec (myLocator, newPath, errors) | (sint)error); + } + while (myLocator.nextChild ()); + } + // when we finished to recurse the tree, we simply check if the StaticChildren are all here + // all other children MUST be either Dynamic or Generated + + if (primitive) + { + string className; + bool Success; + Success = primitive->getPropertyByName ("class", className); + + if (!Success) + { + // is this the root node ? + const IPrimitive *parent = primitive->getParent(); + if (!parent) + { + // if no parent, we have a root node + className = "root"; + Success = true; + } + } + if (Success) + { + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (className.c_str ()); + if (primClass) + { + uint CountStaticChildren = 0; + uint MissingChildren = 0; + myLocator = locator; + // we parse the tree recursively, collection errors, and propagating to the parent + if (myLocator.firstChild ()) + { + do + { + const IPrimitive *primitive2 = myLocator.Primitive; + if (primitive2) + { + string ClassName2; + nlverify (primitive2->getPropertyByName ("class", ClassName2)); + string name; + if (primitive2->getPropertyByName ("name", name)) + { + uint c; + bool Found = false; + for (c=0; cStaticChildren.size (); c++) + { + if (primClass->StaticChildren[c].ClassName == ClassName2 && + primClass->StaticChildren[c].Name == name) + { + Found = true; + ++CountStaticChildren; + break; + } + } + + for (c=0; cGeneratedChildren.size (); c++) + { + if (primClass->GeneratedChildren[c].ClassName == ClassName2) + { + Found = true; + break; + } + } + + for (c=0; cDynamicChildren.size (); c++) + { + if (primClass->DynamicChildren[c].ClassName == ClassName2) + { + Found = true; + break; + } + } + if (!Found) + { + ++MissingChildren; + + // Mark the child as error + IPrimitiveEditor *childPrimitiveEditor = getPrimitiveEditor (const_cast(primitive2)); + childPrimitiveEditor->_Error = IPrimitiveEditor::InExcessField; + InvalidatePrimitive (myLocator, LogicTreeParam); + + string childName; + primitive2->getPropertyByName ("name", childName); + errors += newPath + " : " + "The child \"" + childName + "\" (class \"" + ClassName2 + "\") is not declared in class \"" + className + "\".\n"; + } + } + } + } + while (myLocator.nextChild ()); + } + if (MissingChildren) + { + error = IPrimitiveEditor::InExcessField; + } + if (CountStaticChildren != primClass->StaticChildren.size()) + { + error = IPrimitiveEditor::InExcessField; + errors += newPath+" : "+"Missing static children.\n"; + } + } + } + } + + if (locator.Primitive) + { + IPrimitiveEditor *primitiveEditor = getPrimitiveEditor (const_cast(locator.Primitive)); + + // set the error message + primitiveEditor->_Error = error; + InvalidatePrimitive (locator, LogicTreeParam); + } + return error; +} + + +const IPrimitiveEditor *getPrimitiveEditor(const NLLIGO::IPrimitive *primitive) +{ + if (primitive == NULL) + return NULL; + + const CPrimNodeEditor *pne = dynamic_cast(primitive); + if (pne) + { + return pne; + } + const CPrimPathEditor *ppe = dynamic_cast(primitive); + if (ppe) + { + return ppe; + } + const CPrimZoneEditor *pze = dynamic_cast(primitive); + if (pze) + { + return pze; + } + const CPrimPointEditor *ppte = dynamic_cast(primitive); + if (ppte) + { + return ppte; + } + const CPrimAliasEditor *pae = dynamic_cast(primitive); + if (pae) + { + return pae; + } + + nlassert(false); + return NULL; + +} + +IPrimitiveEditor *getPrimitiveEditor(NLLIGO::IPrimitive *primitive) +{ + return const_cast(getPrimitiveEditor(const_cast(primitive))); +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/editor_primitive.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/editor_primitive.h index 06a0ef0f6..5939a0ece 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/editor_primitive.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/editor_primitive.h @@ -1,480 +1,480 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_EDITOR_PRIMITIVE_H -#define NL_EDITOR_PRIMITIVE_H - -#include "world_editor_doc.h" - -// *************************************************************************** -// The primitive quad grid -// *************************************************************************** - -// Type for the primitive quad grid -class CQuadGridEntry -{ -public: - CQuadGridEntry () - { - First = NULL; - Second = NULL; - } - CQuadGridEntry (NLLIGO::IPrimitive *first, NLLIGO::IPrimitive *second = NULL) - { - First = first; - Second = second; - } - - NLLIGO::IPrimitive *First; - NLLIGO::IPrimitive *Second; // If second is NULL, it is only a primitive, if not, it is a link between two primitives -}; -typedef NL3D::CQuadGrid TPrimQuadGrid; - -// *************************************************************************** - -extern TPrimQuadGrid PrimitiveQuadGrid; - -// *************************************************************************** - -// Linked list of modified primitive -extern std::list ModifiedPrimitive; - -// *************************************************************************** - -// Linked list of selected primitive -extern std::list Selection; - -// *************************************************************************** - -void InitQuadGrid (); - -// *************************************************************************** - -// Update modified primitives -void UpdatePrimitives (); - -// *************************************************************************** - -// Update modified primitives for selection -void UpdateSelection (); - -// *************************************************************************** - -// Put the primitive in the modified primitive to update in the quad grid -void InvalidatePrimitive (const CDatabaseLocatorPointer &locator, uint channels); - -// Same but recursive -void InvalidatePrimitiveRec (const CDatabaseLocatorPointer &locator, uint channels); - -// Invalidate primitive pointers -void InvalidateAllPrimitives (); -// verify the structures of the primitives, if they conform to the XML -void VerifyPrimitivesStructures(); - -// *************************************************************************** -// IPrimitiveEditor -// *************************************************************************** - -class IPrimitiveEditor -{ - friend void UpdatePrimitives (); - friend void InvalidatePrimitive (const CDatabaseLocatorPointer &locator, uint channels); - friend void AddPrimitivesLogicTree (const CDatabaseLocatorPointer &locator, IPrimitiveEditor *primitiveEditor, class CToolsLogic *toolWnd); - friend void UpdatePrimitiveSelection (IPrimitiveEditor *primitiveEditor, CDatabaseLocatorPointer &locator, bool &); - friend void UpdateSelection (); - friend void InvalidatePrimitive (const CDatabaseLocatorPointer &locator, uint channels); - friend class CToolsLogic; - friend class CMainFrame; -public: - // used to mark errors in structures of the tree - enum StructureError - { - NoError = 0, - MissingField = (1<<0), - InExcessField = (1<<1) - }; - IPrimitiveEditor () - { - _QuadIterator = PrimitiveQuadGrid.end (); - _QuadIteratorLink = PrimitiveQuadGrid.end (); - _SelectionIterator = Selection.end (); - _TreeItem = NULL; - _Channels = 0; - _ModifiedIterator = ModifiedPrimitive.end (); - _Error = NoError; - - _Expanded = true; - _Hidden = false; - _Selected = false; - - } - - IPrimitiveEditor (const IPrimitiveEditor &other) - { - _QuadIterator = PrimitiveQuadGrid.end (); - _QuadIteratorLink = PrimitiveQuadGrid.end (); - _SelectionIterator = Selection.end (); - _TreeItem = NULL; - _Channels = 0; - _ModifiedIterator = ModifiedPrimitive.end (); - _Error = NoError; - - _Expanded = other._Expanded; - _Hidden = other._Hidden; - _Selected = false; - } - - virtual ~IPrimitiveEditor (); - - friend IPrimitiveEditor::StructureError VerifyPrimitiveRec (const CDatabaseLocatorPointer &locator, const std::string &path, std::string &errors); - -public: - // Use by removeFromLogicTree (); - virtual void resetTreeItemRec (); - - // Remove the primitive from the logic tree - void removeFromLogicTree (); - - void setHidden(bool hidden) const - { - _Hidden = hidden; - } - bool getHidden() const - { - return _Hidden; - } - void setExpanded(bool expanded) const - { - _Expanded = expanded; - } - bool getExpanded() const - { - return _Expanded; - } - void setSelected(bool selected) const - { - _Selected = selected; - } - bool getSelected() const - { - return _Selected; - } - -protected: - // callback used to read the editor properties - void postReadCallback(const NLLIGO::IPrimitive *thePrim); - // callback used to write the editor properties - void preWriteCallback(const NLLIGO::IPrimitive *thePrim) const; -private: - - /* Remove the primitive from the quad grid. - * This method removes the link to the other primitive if it exists. - */ - void removeFromQuadGrid (); - - // Remove the primitive from the selection - void removeFromSelection (); - - // Remove the primitive from modified primitive - void removeFromModified (); - - // Invalidated channels - uint _Channels; - - // Index in the tree - std::list::iterator _ModifiedIterator; - HTREEITEM _TreeItem; - - // Iterator on the quad grid - TPrimQuadGrid::CIterator _QuadIterator; - TPrimQuadGrid::CIterator _QuadIteratorLink; - - // Iterator on the quad grid - std::list::iterator _SelectionIterator; - - // - mutable bool _Expanded; - mutable bool _Hidden; - mutable bool _Selected; - - StructureError _Error; -}; - - -// *************************************************************************** -// CPrimNodeEditor -// *************************************************************************** - -class CPrimNodeEditor : public NLLIGO::CPrimNode, public IPrimitiveEditor -{ -public: - CPrimNodeEditor () - { - } - - ~CPrimNodeEditor () - { - removeFromLogicTree (); - } - - // From IPrimitiveEditor - virtual void resetTreeItemRec () - { - IPrimitiveEditor::resetTreeItemRec (); - uint i; - for (i=0; i (child); - if (childEditor) - childEditor->resetTreeItemRec (); - } - } - - // From IPrimitive - virtual NLLIGO::IPrimitive *copy () const; - // Read the primitive, to post call the CPrimitiveEditor load method - virtual bool read (xmlNodePtr xmlNode, const char *filename, uint version, NLLIGO::CLigoConfig &config); - // Write the primitive, to pre call the CPrimitiveEditor load method - virtual void write (xmlNodePtr xmlNode, const char *filename) const; - // Callback called when the primitive is updated, giving a chance to track the primitive's modifications during the loading - virtual void onModifyPrimitive (NLLIGO::CPrimitives &primitives) const; - - // From IClassable - virtual std::string getClassName() {return "CPrimNode";} - static NLMISC::IClassable *creator() {return new CPrimNodeEditor;} -}; - -// *************************************************************************** -// CPrimPointEditor -// *************************************************************************** - -class CPrimPointEditor : public NLLIGO::CPrimPoint, public IPrimitiveEditor -{ -public: - CPrimPointEditor () - { - } - - ~CPrimPointEditor () - { - removeFromLogicTree (); - } - - // From IPrimitiveEditor - virtual void resetTreeItemRec () - { - IPrimitiveEditor::resetTreeItemRec (); - uint i; - for (i=0; i (child); - if (childEditor) - childEditor->resetTreeItemRec (); - } - } - - // From IClassable - virtual NLLIGO::IPrimitive *copy () const; - // Read the primitive, to post call the CPrimitiveEditor load method - virtual bool read (xmlNodePtr xmlNode, const char *filename, uint version, NLLIGO::CLigoConfig &config); - // Write the primitive, to pre call the CPrimitiveEditor load method - virtual void write (xmlNodePtr xmlNode, const char *filename) const; - // Callback called when the primitive is updated, giving a chance to track the primitive's modifications during the loading - virtual void onModifyPrimitive (NLLIGO::CPrimitives &primitives) const; - - // From IClassable - virtual std::string getClassName() {return "CPrimPoint";} - static NLMISC::IClassable *creator() {return new CPrimPointEditor;} -}; - -// *************************************************************************** -// CPrimPathEditor -// *************************************************************************** - -class CPrimPathEditor : public NLLIGO::CPrimPath, public IPrimitiveEditor -{ -public: - CPrimPathEditor () - { - } - - ~CPrimPathEditor () - { - removeFromLogicTree (); - } - - // From IPrimitiveEditor - virtual void resetTreeItemRec () - { - IPrimitiveEditor::resetTreeItemRec (); - uint i; - for (i=0; i (child); - if (childEditor) - childEditor->resetTreeItemRec (); - } - } - - // From IPrimitive - virtual NLLIGO::IPrimitive *copy () const; - // Read the primitive, to post call the CPrimitiveEditor load method - virtual bool read (xmlNodePtr xmlNode, const char *filename, uint version, NLLIGO::CLigoConfig &config); - // Write the primitive, to pre call the CPrimitiveEditor load method - virtual void write (xmlNodePtr xmlNode, const char *filename) const; - // Callback called when the primitive is updated, giving a chance to track the primitive's modifications during the loading - virtual void onModifyPrimitive (NLLIGO::CPrimitives &primitives) const; - - // From IClassable - virtual std::string getClassName() {return "CPrimPath";} - static NLMISC::IClassable *creator() {return new CPrimPathEditor;} - - -}; - -// *************************************************************************** -// CPrimZoneEditor -// *************************************************************************** - -class CPrimZoneEditor : public NLLIGO::CPrimZone, public IPrimitiveEditor -{ -public: - CPrimZoneEditor () - { - } - - ~CPrimZoneEditor () - { - removeFromLogicTree (); - } - - // From IPrimitiveEditor - virtual void resetTreeItemRec () - { - IPrimitiveEditor::resetTreeItemRec (); - uint i; - for (i=0; i (child); - if (childEditor) - childEditor->resetTreeItemRec (); - } - } - - // From IPrimitive - virtual NLLIGO::IPrimitive *copy () const; - // Read the primitive, to post call the CPrimitiveEditor load method - virtual bool read (xmlNodePtr xmlNode, const char *filename, uint version, NLLIGO::CLigoConfig &config); - // Write the primitive, to pre call the CPrimitiveEditor load method - virtual void write (xmlNodePtr xmlNode, const char *filename) const; - // Callback called when the primitive is updated, giving a chance to track the primitive's modifications during the loading - virtual void onModifyPrimitive (NLLIGO::CPrimitives &primitives) const; - - // From IClassable - virtual std::string getClassName() {return "CPrimZone";} - static NLMISC::IClassable *creator() {return new CPrimZoneEditor;} -}; - -// *************************************************************************** -// CPrimAliasEditor -// *************************************************************************** - -class CPrimAliasEditor : public NLLIGO::CPrimAlias, public IPrimitiveEditor -{ -public: - CPrimAliasEditor () - { - } - - ~CPrimAliasEditor () - { - removeFromLogicTree (); - } - - // From IPrimitiveEditor - virtual void resetTreeItemRec () - { - IPrimitiveEditor::resetTreeItemRec (); - uint i; - for (i=0; i (child); - if (childEditor) - childEditor->resetTreeItemRec (); - } - } - - // From IPrimitive - virtual NLLIGO::IPrimitive *copy () const; - // Read the primitive, to post call the CPrimitiveEditor load method - virtual bool read (xmlNodePtr xmlNode, const char *filename, uint version, NLLIGO::CLigoConfig &config); - // Write the primitive, to pre call the CPrimitiveEditor load method - virtual void write (xmlNodePtr xmlNode, const char *filename) const; - // Callback called when the primitive is updated, giving a chance to track the primitive's modifications during the loading - virtual void onModifyPrimitive (NLLIGO::CPrimitives &primitives) const; - - // From IClassable - virtual std::string getClassName() {return "CPrimAlias";} - static NLMISC::IClassable *creator(); -}; - -// *************************************************************************** -// CPrimBitmap -// *************************************************************************** - -// A new primitive for files -class CPrimBitmap : public CPrimNodeEditor -{ -public: - CPrimBitmap (); - - // Init - void init (const char *filename); - - // \name From IClassable - NLMISC_DECLARE_CLASS (CPrimBitmap) - - // Get the texture - NL3D::CTextureBlank *getTexture () const; - -private: - - // Loaded - mutable bool _Loaded; - - // The texture - mutable NLMISC::CSmartPtr _Texture; -}; - -IPrimitiveEditor::StructureError VerifyPrimitiveRec (const CDatabaseLocatorPointer &locator, const std::string &path, std::string &errors); - - -const IPrimitiveEditor *getPrimitiveEditor(const NLLIGO::IPrimitive *primitive); -IPrimitiveEditor *getPrimitiveEditor(NLLIGO::IPrimitive *primitive); - -#endif // NL_EDITOR_PRIMITIVE_H - -/* End of editor_primitive.h */ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef NL_EDITOR_PRIMITIVE_H +#define NL_EDITOR_PRIMITIVE_H + +#include "world_editor_doc.h" + +// *************************************************************************** +// The primitive quad grid +// *************************************************************************** + +// Type for the primitive quad grid +class CQuadGridEntry +{ +public: + CQuadGridEntry () + { + First = NULL; + Second = NULL; + } + CQuadGridEntry (NLLIGO::IPrimitive *first, NLLIGO::IPrimitive *second = NULL) + { + First = first; + Second = second; + } + + NLLIGO::IPrimitive *First; + NLLIGO::IPrimitive *Second; // If second is NULL, it is only a primitive, if not, it is a link between two primitives +}; +typedef NL3D::CQuadGrid TPrimQuadGrid; + +// *************************************************************************** + +extern TPrimQuadGrid PrimitiveQuadGrid; + +// *************************************************************************** + +// Linked list of modified primitive +extern std::list ModifiedPrimitive; + +// *************************************************************************** + +// Linked list of selected primitive +extern std::list Selection; + +// *************************************************************************** + +void InitQuadGrid (); + +// *************************************************************************** + +// Update modified primitives +void UpdatePrimitives (); + +// *************************************************************************** + +// Update modified primitives for selection +void UpdateSelection (); + +// *************************************************************************** + +// Put the primitive in the modified primitive to update in the quad grid +void InvalidatePrimitive (const CDatabaseLocatorPointer &locator, uint channels); + +// Same but recursive +void InvalidatePrimitiveRec (const CDatabaseLocatorPointer &locator, uint channels); + +// Invalidate primitive pointers +void InvalidateAllPrimitives (); +// verify the structures of the primitives, if they conform to the XML +void VerifyPrimitivesStructures(); + +// *************************************************************************** +// IPrimitiveEditor +// *************************************************************************** + +class IPrimitiveEditor +{ + friend void UpdatePrimitives (); + friend void InvalidatePrimitive (const CDatabaseLocatorPointer &locator, uint channels); + friend void AddPrimitivesLogicTree (const CDatabaseLocatorPointer &locator, IPrimitiveEditor *primitiveEditor, class CToolsLogic *toolWnd); + friend void UpdatePrimitiveSelection (IPrimitiveEditor *primitiveEditor, CDatabaseLocatorPointer &locator, bool &); + friend void UpdateSelection (); + friend void InvalidatePrimitive (const CDatabaseLocatorPointer &locator, uint channels); + friend class CToolsLogic; + friend class CMainFrame; +public: + // used to mark errors in structures of the tree + enum StructureError + { + NoError = 0, + MissingField = (1<<0), + InExcessField = (1<<1) + }; + IPrimitiveEditor () + { + _QuadIterator = PrimitiveQuadGrid.end (); + _QuadIteratorLink = PrimitiveQuadGrid.end (); + _SelectionIterator = Selection.end (); + _TreeItem = NULL; + _Channels = 0; + _ModifiedIterator = ModifiedPrimitive.end (); + _Error = NoError; + + _Expanded = true; + _Hidden = false; + _Selected = false; + + } + + IPrimitiveEditor (const IPrimitiveEditor &other) + { + _QuadIterator = PrimitiveQuadGrid.end (); + _QuadIteratorLink = PrimitiveQuadGrid.end (); + _SelectionIterator = Selection.end (); + _TreeItem = NULL; + _Channels = 0; + _ModifiedIterator = ModifiedPrimitive.end (); + _Error = NoError; + + _Expanded = other._Expanded; + _Hidden = other._Hidden; + _Selected = false; + } + + virtual ~IPrimitiveEditor (); + + friend IPrimitiveEditor::StructureError VerifyPrimitiveRec (const CDatabaseLocatorPointer &locator, const std::string &path, std::string &errors); + +public: + // Use by removeFromLogicTree (); + virtual void resetTreeItemRec (); + + // Remove the primitive from the logic tree + void removeFromLogicTree (); + + void setHidden(bool hidden) const + { + _Hidden = hidden; + } + bool getHidden() const + { + return _Hidden; + } + void setExpanded(bool expanded) const + { + _Expanded = expanded; + } + bool getExpanded() const + { + return _Expanded; + } + void setSelected(bool selected) const + { + _Selected = selected; + } + bool getSelected() const + { + return _Selected; + } + +protected: + // callback used to read the editor properties + void postReadCallback(const NLLIGO::IPrimitive *thePrim); + // callback used to write the editor properties + void preWriteCallback(const NLLIGO::IPrimitive *thePrim) const; +private: + + /* Remove the primitive from the quad grid. + * This method removes the link to the other primitive if it exists. + */ + void removeFromQuadGrid (); + + // Remove the primitive from the selection + void removeFromSelection (); + + // Remove the primitive from modified primitive + void removeFromModified (); + + // Invalidated channels + uint _Channels; + + // Index in the tree + std::list::iterator _ModifiedIterator; + HTREEITEM _TreeItem; + + // Iterator on the quad grid + TPrimQuadGrid::CIterator _QuadIterator; + TPrimQuadGrid::CIterator _QuadIteratorLink; + + // Iterator on the quad grid + std::list::iterator _SelectionIterator; + + // + mutable bool _Expanded; + mutable bool _Hidden; + mutable bool _Selected; + + StructureError _Error; +}; + + +// *************************************************************************** +// CPrimNodeEditor +// *************************************************************************** + +class CPrimNodeEditor : public NLLIGO::CPrimNode, public IPrimitiveEditor +{ +public: + CPrimNodeEditor () + { + } + + ~CPrimNodeEditor () + { + removeFromLogicTree (); + } + + // From IPrimitiveEditor + virtual void resetTreeItemRec () + { + IPrimitiveEditor::resetTreeItemRec (); + uint i; + for (i=0; i (child); + if (childEditor) + childEditor->resetTreeItemRec (); + } + } + + // From IPrimitive + virtual NLLIGO::IPrimitive *copy () const; + // Read the primitive, to post call the CPrimitiveEditor load method + virtual bool read (xmlNodePtr xmlNode, const char *filename, uint version, NLLIGO::CLigoConfig &config); + // Write the primitive, to pre call the CPrimitiveEditor load method + virtual void write (xmlNodePtr xmlNode, const char *filename) const; + // Callback called when the primitive is updated, giving a chance to track the primitive's modifications during the loading + virtual void onModifyPrimitive (NLLIGO::CPrimitives &primitives) const; + + // From IClassable + virtual std::string getClassName() {return "CPrimNode";} + static NLMISC::IClassable *creator() {return new CPrimNodeEditor;} +}; + +// *************************************************************************** +// CPrimPointEditor +// *************************************************************************** + +class CPrimPointEditor : public NLLIGO::CPrimPoint, public IPrimitiveEditor +{ +public: + CPrimPointEditor () + { + } + + ~CPrimPointEditor () + { + removeFromLogicTree (); + } + + // From IPrimitiveEditor + virtual void resetTreeItemRec () + { + IPrimitiveEditor::resetTreeItemRec (); + uint i; + for (i=0; i (child); + if (childEditor) + childEditor->resetTreeItemRec (); + } + } + + // From IClassable + virtual NLLIGO::IPrimitive *copy () const; + // Read the primitive, to post call the CPrimitiveEditor load method + virtual bool read (xmlNodePtr xmlNode, const char *filename, uint version, NLLIGO::CLigoConfig &config); + // Write the primitive, to pre call the CPrimitiveEditor load method + virtual void write (xmlNodePtr xmlNode, const char *filename) const; + // Callback called when the primitive is updated, giving a chance to track the primitive's modifications during the loading + virtual void onModifyPrimitive (NLLIGO::CPrimitives &primitives) const; + + // From IClassable + virtual std::string getClassName() {return "CPrimPoint";} + static NLMISC::IClassable *creator() {return new CPrimPointEditor;} +}; + +// *************************************************************************** +// CPrimPathEditor +// *************************************************************************** + +class CPrimPathEditor : public NLLIGO::CPrimPath, public IPrimitiveEditor +{ +public: + CPrimPathEditor () + { + } + + ~CPrimPathEditor () + { + removeFromLogicTree (); + } + + // From IPrimitiveEditor + virtual void resetTreeItemRec () + { + IPrimitiveEditor::resetTreeItemRec (); + uint i; + for (i=0; i (child); + if (childEditor) + childEditor->resetTreeItemRec (); + } + } + + // From IPrimitive + virtual NLLIGO::IPrimitive *copy () const; + // Read the primitive, to post call the CPrimitiveEditor load method + virtual bool read (xmlNodePtr xmlNode, const char *filename, uint version, NLLIGO::CLigoConfig &config); + // Write the primitive, to pre call the CPrimitiveEditor load method + virtual void write (xmlNodePtr xmlNode, const char *filename) const; + // Callback called when the primitive is updated, giving a chance to track the primitive's modifications during the loading + virtual void onModifyPrimitive (NLLIGO::CPrimitives &primitives) const; + + // From IClassable + virtual std::string getClassName() {return "CPrimPath";} + static NLMISC::IClassable *creator() {return new CPrimPathEditor;} + + +}; + +// *************************************************************************** +// CPrimZoneEditor +// *************************************************************************** + +class CPrimZoneEditor : public NLLIGO::CPrimZone, public IPrimitiveEditor +{ +public: + CPrimZoneEditor () + { + } + + ~CPrimZoneEditor () + { + removeFromLogicTree (); + } + + // From IPrimitiveEditor + virtual void resetTreeItemRec () + { + IPrimitiveEditor::resetTreeItemRec (); + uint i; + for (i=0; i (child); + if (childEditor) + childEditor->resetTreeItemRec (); + } + } + + // From IPrimitive + virtual NLLIGO::IPrimitive *copy () const; + // Read the primitive, to post call the CPrimitiveEditor load method + virtual bool read (xmlNodePtr xmlNode, const char *filename, uint version, NLLIGO::CLigoConfig &config); + // Write the primitive, to pre call the CPrimitiveEditor load method + virtual void write (xmlNodePtr xmlNode, const char *filename) const; + // Callback called when the primitive is updated, giving a chance to track the primitive's modifications during the loading + virtual void onModifyPrimitive (NLLIGO::CPrimitives &primitives) const; + + // From IClassable + virtual std::string getClassName() {return "CPrimZone";} + static NLMISC::IClassable *creator() {return new CPrimZoneEditor;} +}; + +// *************************************************************************** +// CPrimAliasEditor +// *************************************************************************** + +class CPrimAliasEditor : public NLLIGO::CPrimAlias, public IPrimitiveEditor +{ +public: + CPrimAliasEditor () + { + } + + ~CPrimAliasEditor () + { + removeFromLogicTree (); + } + + // From IPrimitiveEditor + virtual void resetTreeItemRec () + { + IPrimitiveEditor::resetTreeItemRec (); + uint i; + for (i=0; i (child); + if (childEditor) + childEditor->resetTreeItemRec (); + } + } + + // From IPrimitive + virtual NLLIGO::IPrimitive *copy () const; + // Read the primitive, to post call the CPrimitiveEditor load method + virtual bool read (xmlNodePtr xmlNode, const char *filename, uint version, NLLIGO::CLigoConfig &config); + // Write the primitive, to pre call the CPrimitiveEditor load method + virtual void write (xmlNodePtr xmlNode, const char *filename) const; + // Callback called when the primitive is updated, giving a chance to track the primitive's modifications during the loading + virtual void onModifyPrimitive (NLLIGO::CPrimitives &primitives) const; + + // From IClassable + virtual std::string getClassName() {return "CPrimAlias";} + static NLMISC::IClassable *creator(); +}; + +// *************************************************************************** +// CPrimBitmap +// *************************************************************************** + +// A new primitive for files +class CPrimBitmap : public CPrimNodeEditor +{ +public: + CPrimBitmap (); + + // Init + void init (const char *filename); + + // \name From IClassable + NLMISC_DECLARE_CLASS (CPrimBitmap) + + // Get the texture + NL3D::CTextureBlank *getTexture () const; + +private: + + // Loaded + mutable bool _Loaded; + + // The texture + mutable NLMISC::CSmartPtr _Texture; +}; + +IPrimitiveEditor::StructureError VerifyPrimitiveRec (const CDatabaseLocatorPointer &locator, const std::string &path, std::string &errors); + + +const IPrimitiveEditor *getPrimitiveEditor(const NLLIGO::IPrimitive *primitive); +IPrimitiveEditor *getPrimitiveEditor(NLLIGO::IPrimitive *primitive); + +#endif // NL_EDITOR_PRIMITIVE_H + +/* End of editor_primitive.h */ diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/export_cb_dlg.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/export_cb_dlg.cpp index 825874589..293964183 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/export_cb_dlg.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/export_cb_dlg.cpp @@ -1,173 +1,173 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// ExportCBDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -// #include "export_cb_dlg.h" - -///////////////////////////////////////////////////////////////////////////// -// CExportCB - -///////////////////////////////////////////////////////////////////////////// -CExportCB::CExportCB() -{ - _Canceled = false; -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::setExportCBDlg (CExportCBDlg *dlg) -{ - _Dialog = dlg; -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::cancel () -{ - _Canceled = true; -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::pump() -{ - MSG msg; - while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage (&msg); - DispatchMessage (&msg); - } -} - -///////////////////////////////////////////////////////////////////////////// -bool CExportCB::isCanceled () -{ - pump(); - return _Canceled; -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::dispPass (const std::string &Text) -{ - _Dialog->PassText = Text.c_str(); - _Dialog->ProgressBar.SetPos (0); - _Dialog->UpdateData (FALSE); // Upload - _Dialog->Invalidate(); - pump(); -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::dispPassProgress (float percentage) -{ - _Dialog->ProgressBar.SetPos ((sint32)(100*percentage)); - _Dialog->UpdateData (FALSE); // Upload - pump(); -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::dispInfo (const std::string &Text) -{ - _Dialog->InfoText = CString(Text.c_str()) + "\r\n" + _Dialog->InfoText; - _Dialog->UpdateData (FALSE); // Upload - pump(); -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::dispWarning (const std::string &Text) -{ - _Dialog->InfoText = CString("WARNING : ") + CString(Text.c_str()) + "\r\n" + _Dialog->InfoText; - _Dialog->UpdateData (FALSE); // Upload - pump(); -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCB::dispError (const std::string &Text) -{ - _Dialog->InfoText = CString("ERROR : ") + CString(Text.c_str()) + "\r\n" + _Dialog->InfoText; - _Dialog->UpdateData (FALSE); // Upload - pump(); -} - -///////////////////////////////////////////////////////////////////////////// -// CExportCBDlg dialog - - -///////////////////////////////////////////////////////////////////////////// -CExportCBDlg::CExportCBDlg(CWnd* pParent /*=NULL*/) - : CDialog(CExportCBDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CExportCBDlg) - InfoText = _T(""); - PassText = _T(""); - _Finished = false; - //}}AFX_DATA_INIT -} - -///////////////////////////////////////////////////////////////////////////// -void CExportCBDlg::setFinishedButton () -{ - CButton *but = (CButton*)GetDlgItem (IDCANCEL); - but->SetWindowText ("FINISHED"); - Invalidate (); - pump (); -} - - -///////////////////////////////////////////////////////////////////////////// -void CExportCBDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CExportCBDlg) - DDX_Control(pDX, IDC_PROGRESS, ProgressBar); - DDX_Text(pDX, IDC_EDIT_INFO, InfoText); - DDX_Text(pDX, IDC_PASSTEXT, PassText); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CExportCBDlg, CDialog) - //{{AFX_MSG_MAP(CExportCBDlg) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CExportCBDlg message handlers - -///////////////////////////////////////////////////////////////////////////// -void CExportCBDlg::OnCancel() -{ - // TODO: Add extra cleanup here - CButton *but = (CButton*)GetDlgItem (IDCANCEL); - CString zeText; - getWindowTextUTF8 (*but, zeText); - if (zeText == "Cancel") - _ExportCB.cancel (); - else - _Finished = true; -} - -///////////////////////////////////////////////////////////////////////////// -BOOL CExportCBDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - _ExportCB.setExportCBDlg (this); - ProgressBar.SetRange (0, 100); - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// ExportCBDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +// #include "export_cb_dlg.h" + +///////////////////////////////////////////////////////////////////////////// +// CExportCB + +///////////////////////////////////////////////////////////////////////////// +CExportCB::CExportCB() +{ + _Canceled = false; +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::setExportCBDlg (CExportCBDlg *dlg) +{ + _Dialog = dlg; +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::cancel () +{ + _Canceled = true; +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::pump() +{ + MSG msg; + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } +} + +///////////////////////////////////////////////////////////////////////////// +bool CExportCB::isCanceled () +{ + pump(); + return _Canceled; +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::dispPass (const std::string &Text) +{ + _Dialog->PassText = Text.c_str(); + _Dialog->ProgressBar.SetPos (0); + _Dialog->UpdateData (FALSE); // Upload + _Dialog->Invalidate(); + pump(); +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::dispPassProgress (float percentage) +{ + _Dialog->ProgressBar.SetPos ((sint32)(100*percentage)); + _Dialog->UpdateData (FALSE); // Upload + pump(); +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::dispInfo (const std::string &Text) +{ + _Dialog->InfoText = CString(Text.c_str()) + "\r\n" + _Dialog->InfoText; + _Dialog->UpdateData (FALSE); // Upload + pump(); +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::dispWarning (const std::string &Text) +{ + _Dialog->InfoText = CString("WARNING : ") + CString(Text.c_str()) + "\r\n" + _Dialog->InfoText; + _Dialog->UpdateData (FALSE); // Upload + pump(); +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCB::dispError (const std::string &Text) +{ + _Dialog->InfoText = CString("ERROR : ") + CString(Text.c_str()) + "\r\n" + _Dialog->InfoText; + _Dialog->UpdateData (FALSE); // Upload + pump(); +} + +///////////////////////////////////////////////////////////////////////////// +// CExportCBDlg dialog + + +///////////////////////////////////////////////////////////////////////////// +CExportCBDlg::CExportCBDlg(CWnd* pParent /*=NULL*/) + : CDialog(CExportCBDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CExportCBDlg) + InfoText = _T(""); + PassText = _T(""); + _Finished = false; + //}}AFX_DATA_INIT +} + +///////////////////////////////////////////////////////////////////////////// +void CExportCBDlg::setFinishedButton () +{ + CButton *but = (CButton*)GetDlgItem (IDCANCEL); + but->SetWindowText ("FINISHED"); + Invalidate (); + pump (); +} + + +///////////////////////////////////////////////////////////////////////////// +void CExportCBDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CExportCBDlg) + DDX_Control(pDX, IDC_PROGRESS, ProgressBar); + DDX_Text(pDX, IDC_EDIT_INFO, InfoText); + DDX_Text(pDX, IDC_PASSTEXT, PassText); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CExportCBDlg, CDialog) + //{{AFX_MSG_MAP(CExportCBDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CExportCBDlg message handlers + +///////////////////////////////////////////////////////////////////////////// +void CExportCBDlg::OnCancel() +{ + // TODO: Add extra cleanup here + CButton *but = (CButton*)GetDlgItem (IDCANCEL); + CString zeText; + getWindowTextUTF8 (*but, zeText); + if (zeText == "Cancel") + _ExportCB.cancel (); + else + _Finished = true; +} + +///////////////////////////////////////////////////////////////////////////// +BOOL CExportCBDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + _ExportCB.setExportCBDlg (this); + ProgressBar.SetRange (0, 100); + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/export_cb_dlg.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/export_cb_dlg.h index c7f43c96e..20d80bb7f 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/export_cb_dlg.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/export_cb_dlg.h @@ -1,109 +1,109 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_EXPORTCBDLG_H__FEC3B28E_60BC_4D70_862B_4A24AC2037B8__INCLUDED_) -#define AFX_EXPORTCBDLG_H__FEC3B28E_60BC_4D70_862B_4A24AC2037B8__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// ExportCBDlg.h : header file -// - -///////////////////////////////////////////////////////////////////////////// - -// #include "../land_export_lib/export.h" -#include "resource.h" - -///////////////////////////////////////////////////////////////////////////// - -class CExportCBDlg; - -///////////////////////////////////////////////////////////////////////////// -// CExportCB - -class CExportCB : public IExportCB -{ - CExportCBDlg *_Dialog; - bool _Canceled; - -public: - CExportCB(); - - void setExportCBDlg (CExportCBDlg *dlg); - void cancel (); - void pump (); - - // Interface - - virtual bool isCanceled (); // Tell the exporter if it must end as quick as possible - // Display callbacks - virtual void dispPass (const std::string &Text); // Pass (generate land, vegetable, etc...) - virtual void dispPassProgress (float percentage); // [ 0.0 , 1.0 ] - virtual void dispInfo (const std::string &Text); // Verbose - virtual void dispWarning (const std::string &Text); // Error but not critical - virtual void dispError (const std::string &Text); // Should block (misfunction) -}; - -///////////////////////////////////////////////////////////////////////////// -// CExportCBDlg dialog - -class CExportCBDlg : public CDialog -{ - - CExportCB _ExportCB; - bool _Finished; - -// Construction -public: - CExportCBDlg(CWnd* pParent = NULL); // standard constructor - CExportCB *getExportCB () { return &_ExportCB; } - - void setFinishedButton (); - bool getFinished () { return _Finished; } - void pump () { _ExportCB.pump (); } - -// Dialog Data - //{{AFX_DATA(CExportCBDlg) - enum { IDD = IDD_EXPORTCB }; - CProgressCtrl ProgressBar; - CString InfoText; - CString PassText; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CExportCBDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CExportCBDlg) - virtual void OnCancel(); - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_EXPORTCBDLG_H__FEC3B28E_60BC_4D70_862B_4A24AC2037B8__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_EXPORTCBDLG_H__FEC3B28E_60BC_4D70_862B_4A24AC2037B8__INCLUDED_) +#define AFX_EXPORTCBDLG_H__FEC3B28E_60BC_4D70_862B_4A24AC2037B8__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ExportCBDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// + +// #include "../land_export_lib/export.h" +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// + +class CExportCBDlg; + +///////////////////////////////////////////////////////////////////////////// +// CExportCB + +class CExportCB : public IExportCB +{ + CExportCBDlg *_Dialog; + bool _Canceled; + +public: + CExportCB(); + + void setExportCBDlg (CExportCBDlg *dlg); + void cancel (); + void pump (); + + // Interface + + virtual bool isCanceled (); // Tell the exporter if it must end as quick as possible + // Display callbacks + virtual void dispPass (const std::string &Text); // Pass (generate land, vegetable, etc...) + virtual void dispPassProgress (float percentage); // [ 0.0 , 1.0 ] + virtual void dispInfo (const std::string &Text); // Verbose + virtual void dispWarning (const std::string &Text); // Error but not critical + virtual void dispError (const std::string &Text); // Should block (misfunction) +}; + +///////////////////////////////////////////////////////////////////////////// +// CExportCBDlg dialog + +class CExportCBDlg : public CDialog +{ + + CExportCB _ExportCB; + bool _Finished; + +// Construction +public: + CExportCBDlg(CWnd* pParent = NULL); // standard constructor + CExportCB *getExportCB () { return &_ExportCB; } + + void setFinishedButton (); + bool getFinished () { return _Finished; } + void pump () { _ExportCB.pump (); } + +// Dialog Data + //{{AFX_DATA(CExportCBDlg) + enum { IDD = IDD_EXPORTCB }; + CProgressCtrl ProgressBar; + CString InfoText; + CString PassText; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CExportCBDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CExportCBDlg) + virtual void OnCancel(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_EXPORTCBDLG_H__FEC3B28E_60BC_4D70_862B_4A24AC2037B8__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/export_dlg.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/export_dlg.cpp index f5bf1938c..b12f145a6 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/export_dlg.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/export_dlg.cpp @@ -1,308 +1,308 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// ExportDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "export_dlg.h" -#include "file_dialog_ex.h" - -///////////////////////////////////////////////////////////////////////////// -// CExportDlg dialog - - -// --------------------------------------------------------------------------- -CExportDlg::CExportDlg(CWnd* pParent /*=NULL*/) - : CDialog(CExportDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CExportDlg) - OutZoneDir = _T(""); - RefZoneDir = _T(""); - OutIGDir = _T(""); - RefIGDir = _T(""); - OutCMBDir = _T(""); - RefCMBDir = _T(""); - OutAdditionnalIGDir = _T(""); - RefAdditionnalIGDir = _T(""); - TileBankFile = _T(""); - ColorMapFile = _T(""); - HeightMapFile = _T(""); - ZFactor = _T(""); - Lighting = 0; - ZoneMin = _T(""); - ZoneMax = _T(""); - DFNDir = _T(""); - ContinentFile = _T(""); - ContinentsDir = _T(""); - ExportCollision = FALSE; - ExportAdditionnalIGs = FALSE; - //}}AFX_DATA_INIT -} - - -// --------------------------------------------------------------------------- -void CExportDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CExportDlg) - DDX_Text(pDX, IDC_EDIT_OUTZONEDIR, OutZoneDir); - DDX_Text(pDX, IDC_EDIT_REFZONEDIR, RefZoneDir); - DDX_Text(pDX, IDC_EDIT_OUTIGDIR, OutIGDir); - DDX_Text(pDX, IDC_EDIT_REFIGDIR, RefIGDir); - DDX_Text(pDX, IDC_EDIT_OUTCMBDIR, OutCMBDir); - DDX_Text(pDX, IDC_EDIT_REFCMBDIR, RefCMBDir); - DDX_Text(pDX, IDC_EDIT_OUTADDITIONNALIGDIR, OutAdditionnalIGDir); - DDX_Text(pDX, IDC_EDIT_REFADDITIONNALIGDIR, RefAdditionnalIGDir); - DDX_Text(pDX, IDC_EDIT_DFNDIR, DFNDir); - DDX_Text(pDX, IDC_EDIT_CONTINENTSDIR, ContinentsDir); - DDX_Text(pDX, IDC_EDIT_CONTINENTFILE, ContinentFile); - DDX_Text(pDX, IDC_EDIT_TILEBANKFILE, TileBankFile); - DDX_Text(pDX, IDC_EDIT_COLORMAPFILE, ColorMapFile); - DDX_Text(pDX, IDC_EDIT_HEIGHTMAPFILE, HeightMapFile); - DDX_Text(pDX, IDC_EDIT_ZFACTOR, ZFactor); - DDX_Text(pDX, IDC_EDIT_HEIGHTMAPFILE2, HeightMapFile2); - DDX_Text(pDX, IDC_EDIT_ZFACTOR2, ZFactor2); - DDX_Text(pDX, IDC_EDIT_ZONEMIN, ZoneMin); - DDX_Text(pDX, IDC_EDIT_ZONEMAX, ZoneMax); - DDX_Check(pDX, IDC_EXPORT_COLLISIONS, ExportCollision); - DDX_Check(pDX, IDC_EXPORT_ADDITIONNAL_IGS, ExportAdditionnalIGs); - - - if (pDX->m_bSaveAndValidate) - { - // Download - if (GetCheckedRadioButton (IDC_RADIOLIGHTNOISE, IDC_RADIOLIGHTNO) == IDC_RADIOLIGHTNOISE) - Lighting = 2; - else - if (GetCheckedRadioButton (IDC_RADIOLIGHTNOISE, IDC_RADIOLIGHTNO) == IDC_RADIOLIGHTPATCH) - Lighting = 1; - else - if (GetCheckedRadioButton (IDC_RADIOLIGHTNOISE, IDC_RADIOLIGHTNO) == IDC_RADIOLIGHTNO) - Lighting = 0; - } - else - { - // Upload - if (Lighting == 0) - CheckRadioButton (IDC_RADIOLIGHTNOISE, IDC_RADIOLIGHTNO, IDC_RADIOLIGHTNO); - else - if (Lighting == 1) - CheckRadioButton (IDC_RADIOLIGHTNOISE, IDC_RADIOLIGHTNO, IDC_RADIOLIGHTPATCH); - else - if (Lighting == 2) - CheckRadioButton (IDC_RADIOLIGHTNOISE, IDC_RADIOLIGHTNO, IDC_RADIOLIGHTNOISE); - } - //}}AFX_DATA_MAP -} - - -// --------------------------------------------------------------------------- -BEGIN_MESSAGE_MAP(CExportDlg, CDialog) - //{{AFX_MSG_MAP(CExportDlg) - ON_BN_CLICKED(IDC_BUTTON_REFZONEDIR, OnButtonRefzonedir) - ON_BN_CLICKED(IDC_BUTTON_OUTZONEDIR, OnButtonOutzonedir) - ON_BN_CLICKED(IDC_BUTTON_REFIGDIR, OnButtonRefIGdir) - ON_BN_CLICKED(IDC_BUTTON_OUTIGDIR, OnButtonOutIGdir) - ON_BN_CLICKED(IDC_BUTTON_REFCMBDIR, OnButtonRefCMBdir) - ON_BN_CLICKED(IDC_BUTTON_OUTCMBDIR, OnButtonOutCMBdir) - ON_BN_CLICKED(IDC_BUTTON_DFNDIR, OnButtonDFNDir) - ON_BN_CLICKED(IDC_BUTTON_CONTINENTSDIR, OnButtonContinentsDir) - ON_BN_CLICKED(IDC_BUTTON_CONTINENTFILE, OnButtonContinentFile) - ON_BN_CLICKED(IDC_BUTTON_REFADDITIONNALIGDIR, OnButtonRefAdditionnalIGdir) - ON_BN_CLICKED(IDC_BUTTON_OUTADDITIONNALIGDIR, OnButtonOutAdditionnalIGdir) - ON_BN_CLICKED(IDC_BUTTON_TILEBANKFILE, OnButtonTilebankfile) - ON_BN_CLICKED(IDC_BUTTON_COLORMAPFILE, OnButtonColormapfile) - ON_BN_CLICKED(IDC_BUTTON_HEIGHTMAPFILE, OnButtonHeightmapfile) - ON_BN_CLICKED(IDC_BUTTON_HEIGHTMAPFILE2, OnButtonHeightmapfile2) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CExportDlg message handlers - -void CExportDlg::OnOK() -{ - // TODO: Add extra validation here - - CDialog::OnOK(); -} - -// --------------------------------------------------------------------------- -// This function serve to initiate the browsing dialog box to the good position in the tree -int CALLBACK expBrowseCallbackProc (HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) -{ - switch(uMsg) - { - case BFFM_INITIALIZED: - SendMessage (hwnd, BFFM_SETSELECTION, TRUE, pData); - break; - default: - break; - } - return 0; -} - -// --------------------------------------------------------------------------- -// This open a dialog to choose a path, then put the result in the given string if it hasn't been cancel -// \return true if not canceled -bool CExportDlg::callChoosePathDlg(CString &dest) const -{ - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp;; - bi.lpszTitle = "Choose the path"; - bi.ulFlags = 0; - bi.lpfn = expBrowseCallbackProc; - - char sDir[512]; - strcpy(sDir, (LPCSTR)RefZoneDir); - bi.lParam = (LPARAM)sDir; - - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (!SHGetPathFromIDList(pidl, str)) - { - return false; - } - dest = str; - return true; -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonRefzonedir() -{ - if (callChoosePathDlg(RefZoneDir)) UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonOutzonedir() -{ - if (callChoosePathDlg(OutZoneDir)) UpdateData (FALSE); // Upload -} - - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonRefIGdir() -{ - if (callChoosePathDlg(RefIGDir)) UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonOutIGdir() -{ - if (callChoosePathDlg(OutIGDir)) UpdateData (FALSE); // Upload -} - - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonTilebankfile() -{ - CFileDialogEx dialog (BASE_REGISTRY_KEY, "bank", true, "smallbank", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "SmallBank (*.smallbank)|*.smallbank||", this); - if (dialog.DoModal() == IDOK) - { - TileBankFile = dialog.GetPathName (); - } - UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonColormapfile() -{ - CFileDialogEx dialog (BASE_REGISTRY_KEY, "image", true, "tga", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Tga Files (*.tga)|*.tga|All Files (*.*)|*.*||", this); - if (dialog.DoModal() == IDOK) - { - ColorMapFile = dialog.GetPathName (); - } - UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonHeightmapfile() -{ - CFileDialogEx dialog (BASE_REGISTRY_KEY, "image", true, "tga", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Grayscale Tga (*.tga)|*.tga||", this); - if (dialog.DoModal() == IDOK) - { - HeightMapFile = dialog.GetPathName (); - } - UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonHeightmapfile2() -{ - CFileDialogEx dialog (BASE_REGISTRY_KEY, "image", true, "tga", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Grayscale Tga (*.tga)|*.tga||", this); - if (dialog.DoModal() == IDOK) - { - HeightMapFile2 = dialog.GetPathName (); - } - UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonRefAdditionnalIGdir() -{ - if (callChoosePathDlg(RefAdditionnalIGDir)) UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonOutAdditionnalIGdir() -{ - if (callChoosePathDlg(OutAdditionnalIGDir)) UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonRefCMBdir() -{ - if (callChoosePathDlg(RefCMBDir)) UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonOutCMBdir() -{ - if (callChoosePathDlg(OutCMBDir)) UpdateData (FALSE); // Upload -} - - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonDFNDir() -{ - if (callChoosePathDlg(DFNDir)) UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonContinentsDir() -{ - if (callChoosePathDlg(ContinentsDir)) UpdateData (FALSE); // Upload -} - -// --------------------------------------------------------------------------- -void CExportDlg::OnButtonContinentFile() -{ - CFileDialogEx dialog (BASE_REGISTRY_KEY, "continent", true, "continent", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Continent file (*.continent)|*.continent||", this); - if (dialog.DoModal() == IDOK) - { - ContinentFile = dialog.GetPathName (); - } - UpdateData (FALSE); // Upload -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// ExportDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "export_dlg.h" +#include "file_dialog_ex.h" + +///////////////////////////////////////////////////////////////////////////// +// CExportDlg dialog + + +// --------------------------------------------------------------------------- +CExportDlg::CExportDlg(CWnd* pParent /*=NULL*/) + : CDialog(CExportDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CExportDlg) + OutZoneDir = _T(""); + RefZoneDir = _T(""); + OutIGDir = _T(""); + RefIGDir = _T(""); + OutCMBDir = _T(""); + RefCMBDir = _T(""); + OutAdditionnalIGDir = _T(""); + RefAdditionnalIGDir = _T(""); + TileBankFile = _T(""); + ColorMapFile = _T(""); + HeightMapFile = _T(""); + ZFactor = _T(""); + Lighting = 0; + ZoneMin = _T(""); + ZoneMax = _T(""); + DFNDir = _T(""); + ContinentFile = _T(""); + ContinentsDir = _T(""); + ExportCollision = FALSE; + ExportAdditionnalIGs = FALSE; + //}}AFX_DATA_INIT +} + + +// --------------------------------------------------------------------------- +void CExportDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CExportDlg) + DDX_Text(pDX, IDC_EDIT_OUTZONEDIR, OutZoneDir); + DDX_Text(pDX, IDC_EDIT_REFZONEDIR, RefZoneDir); + DDX_Text(pDX, IDC_EDIT_OUTIGDIR, OutIGDir); + DDX_Text(pDX, IDC_EDIT_REFIGDIR, RefIGDir); + DDX_Text(pDX, IDC_EDIT_OUTCMBDIR, OutCMBDir); + DDX_Text(pDX, IDC_EDIT_REFCMBDIR, RefCMBDir); + DDX_Text(pDX, IDC_EDIT_OUTADDITIONNALIGDIR, OutAdditionnalIGDir); + DDX_Text(pDX, IDC_EDIT_REFADDITIONNALIGDIR, RefAdditionnalIGDir); + DDX_Text(pDX, IDC_EDIT_DFNDIR, DFNDir); + DDX_Text(pDX, IDC_EDIT_CONTINENTSDIR, ContinentsDir); + DDX_Text(pDX, IDC_EDIT_CONTINENTFILE, ContinentFile); + DDX_Text(pDX, IDC_EDIT_TILEBANKFILE, TileBankFile); + DDX_Text(pDX, IDC_EDIT_COLORMAPFILE, ColorMapFile); + DDX_Text(pDX, IDC_EDIT_HEIGHTMAPFILE, HeightMapFile); + DDX_Text(pDX, IDC_EDIT_ZFACTOR, ZFactor); + DDX_Text(pDX, IDC_EDIT_HEIGHTMAPFILE2, HeightMapFile2); + DDX_Text(pDX, IDC_EDIT_ZFACTOR2, ZFactor2); + DDX_Text(pDX, IDC_EDIT_ZONEMIN, ZoneMin); + DDX_Text(pDX, IDC_EDIT_ZONEMAX, ZoneMax); + DDX_Check(pDX, IDC_EXPORT_COLLISIONS, ExportCollision); + DDX_Check(pDX, IDC_EXPORT_ADDITIONNAL_IGS, ExportAdditionnalIGs); + + + if (pDX->m_bSaveAndValidate) + { + // Download + if (GetCheckedRadioButton (IDC_RADIOLIGHTNOISE, IDC_RADIOLIGHTNO) == IDC_RADIOLIGHTNOISE) + Lighting = 2; + else + if (GetCheckedRadioButton (IDC_RADIOLIGHTNOISE, IDC_RADIOLIGHTNO) == IDC_RADIOLIGHTPATCH) + Lighting = 1; + else + if (GetCheckedRadioButton (IDC_RADIOLIGHTNOISE, IDC_RADIOLIGHTNO) == IDC_RADIOLIGHTNO) + Lighting = 0; + } + else + { + // Upload + if (Lighting == 0) + CheckRadioButton (IDC_RADIOLIGHTNOISE, IDC_RADIOLIGHTNO, IDC_RADIOLIGHTNO); + else + if (Lighting == 1) + CheckRadioButton (IDC_RADIOLIGHTNOISE, IDC_RADIOLIGHTNO, IDC_RADIOLIGHTPATCH); + else + if (Lighting == 2) + CheckRadioButton (IDC_RADIOLIGHTNOISE, IDC_RADIOLIGHTNO, IDC_RADIOLIGHTNOISE); + } + //}}AFX_DATA_MAP +} + + +// --------------------------------------------------------------------------- +BEGIN_MESSAGE_MAP(CExportDlg, CDialog) + //{{AFX_MSG_MAP(CExportDlg) + ON_BN_CLICKED(IDC_BUTTON_REFZONEDIR, OnButtonRefzonedir) + ON_BN_CLICKED(IDC_BUTTON_OUTZONEDIR, OnButtonOutzonedir) + ON_BN_CLICKED(IDC_BUTTON_REFIGDIR, OnButtonRefIGdir) + ON_BN_CLICKED(IDC_BUTTON_OUTIGDIR, OnButtonOutIGdir) + ON_BN_CLICKED(IDC_BUTTON_REFCMBDIR, OnButtonRefCMBdir) + ON_BN_CLICKED(IDC_BUTTON_OUTCMBDIR, OnButtonOutCMBdir) + ON_BN_CLICKED(IDC_BUTTON_DFNDIR, OnButtonDFNDir) + ON_BN_CLICKED(IDC_BUTTON_CONTINENTSDIR, OnButtonContinentsDir) + ON_BN_CLICKED(IDC_BUTTON_CONTINENTFILE, OnButtonContinentFile) + ON_BN_CLICKED(IDC_BUTTON_REFADDITIONNALIGDIR, OnButtonRefAdditionnalIGdir) + ON_BN_CLICKED(IDC_BUTTON_OUTADDITIONNALIGDIR, OnButtonOutAdditionnalIGdir) + ON_BN_CLICKED(IDC_BUTTON_TILEBANKFILE, OnButtonTilebankfile) + ON_BN_CLICKED(IDC_BUTTON_COLORMAPFILE, OnButtonColormapfile) + ON_BN_CLICKED(IDC_BUTTON_HEIGHTMAPFILE, OnButtonHeightmapfile) + ON_BN_CLICKED(IDC_BUTTON_HEIGHTMAPFILE2, OnButtonHeightmapfile2) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CExportDlg message handlers + +void CExportDlg::OnOK() +{ + // TODO: Add extra validation here + + CDialog::OnOK(); +} + +// --------------------------------------------------------------------------- +// This function serve to initiate the browsing dialog box to the good position in the tree +int CALLBACK expBrowseCallbackProc (HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) +{ + switch(uMsg) + { + case BFFM_INITIALIZED: + SendMessage (hwnd, BFFM_SETSELECTION, TRUE, pData); + break; + default: + break; + } + return 0; +} + +// --------------------------------------------------------------------------- +// This open a dialog to choose a path, then put the result in the given string if it hasn't been cancel +// \return true if not canceled +bool CExportDlg::callChoosePathDlg(CString &dest) const +{ + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp;; + bi.lpszTitle = "Choose the path"; + bi.ulFlags = 0; + bi.lpfn = expBrowseCallbackProc; + + char sDir[512]; + strcpy(sDir, (LPCSTR)RefZoneDir); + bi.lParam = (LPARAM)sDir; + + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (!SHGetPathFromIDList(pidl, str)) + { + return false; + } + dest = str; + return true; +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonRefzonedir() +{ + if (callChoosePathDlg(RefZoneDir)) UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonOutzonedir() +{ + if (callChoosePathDlg(OutZoneDir)) UpdateData (FALSE); // Upload +} + + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonRefIGdir() +{ + if (callChoosePathDlg(RefIGDir)) UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonOutIGdir() +{ + if (callChoosePathDlg(OutIGDir)) UpdateData (FALSE); // Upload +} + + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonTilebankfile() +{ + CFileDialogEx dialog (BASE_REGISTRY_KEY, "bank", true, "smallbank", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "SmallBank (*.smallbank)|*.smallbank||", this); + if (dialog.DoModal() == IDOK) + { + TileBankFile = dialog.GetPathName (); + } + UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonColormapfile() +{ + CFileDialogEx dialog (BASE_REGISTRY_KEY, "image", true, "tga", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Tga Files (*.tga)|*.tga|All Files (*.*)|*.*||", this); + if (dialog.DoModal() == IDOK) + { + ColorMapFile = dialog.GetPathName (); + } + UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonHeightmapfile() +{ + CFileDialogEx dialog (BASE_REGISTRY_KEY, "image", true, "tga", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Grayscale Tga (*.tga)|*.tga||", this); + if (dialog.DoModal() == IDOK) + { + HeightMapFile = dialog.GetPathName (); + } + UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonHeightmapfile2() +{ + CFileDialogEx dialog (BASE_REGISTRY_KEY, "image", true, "tga", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Grayscale Tga (*.tga)|*.tga||", this); + if (dialog.DoModal() == IDOK) + { + HeightMapFile2 = dialog.GetPathName (); + } + UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonRefAdditionnalIGdir() +{ + if (callChoosePathDlg(RefAdditionnalIGDir)) UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonOutAdditionnalIGdir() +{ + if (callChoosePathDlg(OutAdditionnalIGDir)) UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonRefCMBdir() +{ + if (callChoosePathDlg(RefCMBDir)) UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonOutCMBdir() +{ + if (callChoosePathDlg(OutCMBDir)) UpdateData (FALSE); // Upload +} + + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonDFNDir() +{ + if (callChoosePathDlg(DFNDir)) UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonContinentsDir() +{ + if (callChoosePathDlg(ContinentsDir)) UpdateData (FALSE); // Upload +} + +// --------------------------------------------------------------------------- +void CExportDlg::OnButtonContinentFile() +{ + CFileDialogEx dialog (BASE_REGISTRY_KEY, "continent", true, "continent", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Continent file (*.continent)|*.continent||", this); + if (dialog.DoModal() == IDOK) + { + ContinentFile = dialog.GetPathName (); + } + UpdateData (FALSE); // Upload +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/export_dlg.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/export_dlg.h index 264659f1f..e7058818b 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/export_dlg.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/export_dlg.h @@ -1,101 +1,101 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_EXPORTDLG_H__F0E3FA13_0D4B_4A26_8CFA_1C315EAA1CBE__INCLUDED_) -#define AFX_EXPORTDLG_H__F0E3FA13_0D4B_4A26_8CFA_1C315EAA1CBE__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// ExportDlg.h : header file -// -#include "resource.h" -///////////////////////////////////////////////////////////////////////////// -// CExportDlg dialog - -class CExportDlg : public CDialog -{ -// Construction -public: - CExportDlg(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CExportDlg) - enum { IDD = IDD_EXPORT }; - CString OutZoneDir; - CString RefZoneDir; - CString OutIGDir; - CString RefIGDir; - CString OutCMBDir; - CString RefCMBDir; - CString OutAdditionnalIGDir; - CString RefAdditionnalIGDir; - CString DFNDir; - CString ContinentsDir; - CString ContinentFile; - CString TileBankFile; - CString ColorMapFile; - CString HeightMapFile; - CString ZFactor; - CString HeightMapFile2; - CString ZFactor2; - uint8 Lighting; - CString ZoneMin; - CString ZoneMax; - BOOL ExportCollision; - BOOL ExportAdditionnalIGs; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CExportDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CExportDlg) - virtual void OnOK (); - afx_msg void OnButtonRefzonedir (); - afx_msg void OnButtonOutzonedir (); - afx_msg void OnButtonRefIGdir (); - afx_msg void OnButtonOutIGdir (); - afx_msg void OnButtonRefAdditionnalIGdir (); - afx_msg void OnButtonOutAdditionnalIGdir (); - afx_msg void OnButtonRefCMBdir (); - afx_msg void OnButtonOutCMBdir (); - afx_msg void OnButtonDFNDir (); - afx_msg void OnButtonContinentsDir (); - afx_msg void OnButtonContinentFile (); - afx_msg void OnButtonTilebankfile (); - afx_msg void OnButtonColormapfile (); - afx_msg void OnButtonHeightmapfile (); - afx_msg void OnButtonHeightmapfile2 (); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -private: - // tool method to choose a path - bool callChoosePathDlg(CString &dest) const; -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_EXPORTDLG_H__F0E3FA13_0D4B_4A26_8CFA_1C315EAA1CBE__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_EXPORTDLG_H__F0E3FA13_0D4B_4A26_8CFA_1C315EAA1CBE__INCLUDED_) +#define AFX_EXPORTDLG_H__F0E3FA13_0D4B_4A26_8CFA_1C315EAA1CBE__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// ExportDlg.h : header file +// +#include "resource.h" +///////////////////////////////////////////////////////////////////////////// +// CExportDlg dialog + +class CExportDlg : public CDialog +{ +// Construction +public: + CExportDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CExportDlg) + enum { IDD = IDD_EXPORT }; + CString OutZoneDir; + CString RefZoneDir; + CString OutIGDir; + CString RefIGDir; + CString OutCMBDir; + CString RefCMBDir; + CString OutAdditionnalIGDir; + CString RefAdditionnalIGDir; + CString DFNDir; + CString ContinentsDir; + CString ContinentFile; + CString TileBankFile; + CString ColorMapFile; + CString HeightMapFile; + CString ZFactor; + CString HeightMapFile2; + CString ZFactor2; + uint8 Lighting; + CString ZoneMin; + CString ZoneMax; + BOOL ExportCollision; + BOOL ExportAdditionnalIGs; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CExportDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CExportDlg) + virtual void OnOK (); + afx_msg void OnButtonRefzonedir (); + afx_msg void OnButtonOutzonedir (); + afx_msg void OnButtonRefIGdir (); + afx_msg void OnButtonOutIGdir (); + afx_msg void OnButtonRefAdditionnalIGdir (); + afx_msg void OnButtonOutAdditionnalIGdir (); + afx_msg void OnButtonRefCMBdir (); + afx_msg void OnButtonOutCMBdir (); + afx_msg void OnButtonDFNDir (); + afx_msg void OnButtonContinentsDir (); + afx_msg void OnButtonContinentFile (); + afx_msg void OnButtonTilebankfile (); + afx_msg void OnButtonColormapfile (); + afx_msg void OnButtonHeightmapfile (); + afx_msg void OnButtonHeightmapfile2 (); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +private: + // tool method to choose a path + bool callChoosePathDlg(CString &dest) const; +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_EXPORTDLG_H__F0E3FA13_0D4B_4A26_8CFA_1C315EAA1CBE__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/external_editor.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/external_editor.cpp index 709b00f72..42598a6a2 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/external_editor.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/external_editor.cpp @@ -1,96 +1,96 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// dialog_properties.cpp : implementation file -// - -#include "stdafx.h" -#include - -using namespace std; -using namespace NLLIGO; -using namespace NLMISC; - -// *************************************************************************** - -bool EditExternalText (const std::string &editor, std::string &text, const std::string &ext) -{ - bool status = false; - // Create a temporary file - char dir[512]; - if (getcwd (dir, 512)) - { - // Build a temporary filename - string tempFilename; - uint i = 0; - do - tempFilename = string(dir)+"/~tmp"+toString (i++)+"."+ext; - while (NLMISC::CFile::isExists(tempFilename)); - - // Fill the temp file - bool saved = false; - FILE *file = fopen (tempFilename.c_str(), "w"); - if (file) - { - saved = fputs (text.c_str(), file) != EOF; - fclose (file); - } - - // Hide the file - SetFileAttributes (tempFilename.c_str(), FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM); - - // Open the temp file with a text editor - if (saved) - { - STARTUPINFO si; - PROCESS_INFORMATION pi; - memset(&si, 0, sizeof(si)); - memset(&pi, 0, sizeof(pi)); - si.cb = sizeof(si); - char cmdLine[1024]; - strncpy (cmdLine, ("\""+editor+"\" \""+tempFilename+"\"").c_str(), sizeof(cmdLine)-1); - if (CreateProcess(editor.c_str (), cmdLine, NULL, NULL, FALSE, 0, NULL, dir, &si, &pi)) - { - if (WaitForSingleObject (pi.hProcess, INFINITE) == WAIT_OBJECT_0) - { - // Open the file.. - std::string tempText; - FILE *file = fopen (tempFilename.c_str(), "r"); - if (file) - { - // Read the new file - char buffer[513]; - int red; - while (red=fread (buffer, 1, 512, file)) - { - buffer[red] = 0; - tempText += buffer; - } - fclose (file); - - // Return the text - text = tempText; - status = true; - } - } - } - } - - // Delete the file - NLMISC::CFile::deleteFile (tempFilename); - } - return status; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// dialog_properties.cpp : implementation file +// + +#include "stdafx.h" +#include + +using namespace std; +using namespace NLLIGO; +using namespace NLMISC; + +// *************************************************************************** + +bool EditExternalText (const std::string &editor, std::string &text, const std::string &ext) +{ + bool status = false; + // Create a temporary file + char dir[512]; + if (getcwd (dir, 512)) + { + // Build a temporary filename + string tempFilename; + uint i = 0; + do + tempFilename = string(dir)+"/~tmp"+toString (i++)+"."+ext; + while (NLMISC::CFile::isExists(tempFilename)); + + // Fill the temp file + bool saved = false; + FILE *file = fopen (tempFilename.c_str(), "w"); + if (file) + { + saved = fputs (text.c_str(), file) != EOF; + fclose (file); + } + + // Hide the file + SetFileAttributes (tempFilename.c_str(), FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM); + + // Open the temp file with a text editor + if (saved) + { + STARTUPINFO si; + PROCESS_INFORMATION pi; + memset(&si, 0, sizeof(si)); + memset(&pi, 0, sizeof(pi)); + si.cb = sizeof(si); + char cmdLine[1024]; + strncpy (cmdLine, ("\""+editor+"\" \""+tempFilename+"\"").c_str(), sizeof(cmdLine)-1); + if (CreateProcess(editor.c_str (), cmdLine, NULL, NULL, FALSE, 0, NULL, dir, &si, &pi)) + { + if (WaitForSingleObject (pi.hProcess, INFINITE) == WAIT_OBJECT_0) + { + // Open the file.. + std::string tempText; + FILE *file = fopen (tempFilename.c_str(), "r"); + if (file) + { + // Read the new file + char buffer[513]; + int red; + while (red=fread (buffer, 1, 512, file)) + { + buffer[red] = 0; + tempText += buffer; + } + fclose (file); + + // Return the text + text = tempText; + status = true; + } + } + } + } + + // Delete the file + NLMISC::CFile::deleteFile (tempFilename); + } + return status; +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/external_editor.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/external_editor.h index 4639dbdf3..22bf2f225 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/external_editor.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/external_editor.h @@ -1,29 +1,29 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_EXTERNAL_EDITOR_H -#define NL_EXTERNAL_EDITOR_H - -/* Launch an external text editor to edit the string passed in parameter. - * Returns true if the editing is successful and text is filled with the new text - * Returns false else. - * ext is the extension of the temporary file ("txt"); - */ -bool EditExternalText (const std::string &editor, std::string &text, const std::string &ext); - -#endif // NL_EXTERNAL_EDITOR_H - -/* End of external_editor.h */ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef NL_EXTERNAL_EDITOR_H +#define NL_EXTERNAL_EDITOR_H + +/* Launch an external text editor to edit the string passed in parameter. + * Returns true if the editing is successful and text is filled with the new text + * Returns false else. + * ext is the extension of the temporary file ("txt"); + */ +bool EditExternalText (const std::string &editor, std::string &text, const std::string &ext); + +#endif // NL_EXTERNAL_EDITOR_H + +/* End of external_editor.h */ diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/file_dialog_ex.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/file_dialog_ex.cpp index 311ab8046..7bf850817 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/file_dialog_ex.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/file_dialog_ex.cpp @@ -1,176 +1,176 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" -#include "world_editor.h" -#include "file_dialog_ex.h" - -#include - -using namespace std; -using namespace NLMISC; - -#define PATH_REMEBERED_SIZE 15 - -// *************************************************************************** -// CFileDialogEx -// *************************************************************************** - -IMPLEMENT_DYNAMIC(CFileDialogEx, CFileDialog) - -// *************************************************************************** - -CFileDialogEx::CFileDialogEx(LPCTSTR lpszRegistryPath, LPCTSTR lpszFileType,BOOL bOpenFileDialog, - LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) : - CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd) -{ - _RegistryPath = lpszRegistryPath; - _RegistryPath += "\\CFileDialogEx"; - _FileType = lpszFileType; -} - -// *************************************************************************** - -BEGIN_MESSAGE_MAP(CFileDialogEx, CFileDialog) - //{{AFX_MSG_MAP(CFileDialogEx) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// *************************************************************************** - -int CFileDialogEx::DoModal () -{ - // Get the path - char path[512]; - path[0] = 0; - HKEY hKey; - DWORD type = REG_SZ; - DWORD size = 512; - if (RegCreateKey (HKEY_CURRENT_USER, _RegistryPath.c_str (), &hKey) == ERROR_SUCCESS) - { - if (RegQueryValueEx (hKey, _FileType.c_str (), 0, &type, (LPBYTE)path, &size) == ERROR_SUCCESS) - m_ofn.lpstrInitialDir = path; - } - - // Template - m_ofn.Flags |= OFN_ENABLETEMPLATE|OFN_EXPLORER; - m_ofn.lpTemplateName = MAKEINTRESOURCE (IDD_DIRECTORY_SELECTOR); - - int result; - if ((result = CFileDialog::DoModal ()) == IDOK) - { - // Update the path - std::string newPath = (const char *)GetPathName (); - newPath = NLMISC::CFile::getPath (newPath); - RegSetValueEx (hKey, _FileType.c_str (), 0, REG_SZ, (LPBYTE)newPath.c_str (), newPath.size ()+1); - - // Update the path list - set oldPath; - uint i; - for (i=0; i::const_iterator ite = oldPath.begin (); - uint index = 0; - while (ite != oldPath.end ()) - { - RegSetValueEx (hKey, toString (index).c_str (), 0, REG_SZ, (LPBYTE)ite->c_str (), ite->size ()+1); - ite++; - index++; - } - } - return result; -} - -// *************************************************************************** - -BOOL CFileDialogEx::OnCommand( WPARAM wParam, LPARAM lParam ) -{ - if (HIWORD (wParam) == CBN_SELCHANGE) - { - if (LOWORD (wParam) == IDC_DIRLIST) - { - // The combo box - CString text; - CComboBox combo; - combo.Attach (::GetDlgItem (*this, IDC_DIRLIST)); - combo.GetWindowText (text); - combo.Detach (); - - // Set the new directory - TCHAR s[MAX_PATH]; - - // Backup contents of 'edt1' - HWND parent = *GetParent (); - ::GetDlgItemText (parent, edt1, s, MAX_PATH); - - // Replace with the directory name - ::SendMessage (parent, CDM_SETCONTROLTEXT, edt1, (LPARAM)(const char*)text); - - // Click on the OK button - ::SendMessage (parent, WM_COMMAND, IDOK, 0); - - // Restore contents of 'edt1' - ::SendMessage (parent, CDM_SETCONTROLTEXT, edt1, (LPARAM)s); - } - } - return CFileDialog::OnCommand (wParam, lParam); -} - -// *************************************************************************** - -BOOL CFileDialogEx::OnInitDialog() -{ - CFileDialog::OnInitDialog(); - - // The edit box - HWND editBox = ::GetDlgItem (*(this->GetParent ()), edt1); - - // The combo box - CComboBox combo; - combo.Attach (::GetDlgItem (*this, IDC_DIRLIST)); - - // Insert the strings - char text[512]; - text[0] = 0; - HKEY hKey; - DWORD type = REG_SZ; - DWORD size; - if (RegCreateKey (HKEY_CURRENT_USER, _RegistryPath.c_str (), &hKey) == ERROR_SUCCESS) - { - uint i; - for (i=0; i +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" +#include "world_editor.h" +#include "file_dialog_ex.h" + +#include + +using namespace std; +using namespace NLMISC; + +#define PATH_REMEBERED_SIZE 15 + +// *************************************************************************** +// CFileDialogEx +// *************************************************************************** + +IMPLEMENT_DYNAMIC(CFileDialogEx, CFileDialog) + +// *************************************************************************** + +CFileDialogEx::CFileDialogEx(LPCTSTR lpszRegistryPath, LPCTSTR lpszFileType,BOOL bOpenFileDialog, + LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) : + CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd) +{ + _RegistryPath = lpszRegistryPath; + _RegistryPath += "\\CFileDialogEx"; + _FileType = lpszFileType; +} + +// *************************************************************************** + +BEGIN_MESSAGE_MAP(CFileDialogEx, CFileDialog) + //{{AFX_MSG_MAP(CFileDialogEx) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// *************************************************************************** + +int CFileDialogEx::DoModal () +{ + // Get the path + char path[512]; + path[0] = 0; + HKEY hKey; + DWORD type = REG_SZ; + DWORD size = 512; + if (RegCreateKey (HKEY_CURRENT_USER, _RegistryPath.c_str (), &hKey) == ERROR_SUCCESS) + { + if (RegQueryValueEx (hKey, _FileType.c_str (), 0, &type, (LPBYTE)path, &size) == ERROR_SUCCESS) + m_ofn.lpstrInitialDir = path; + } + + // Template + m_ofn.Flags |= OFN_ENABLETEMPLATE|OFN_EXPLORER; + m_ofn.lpTemplateName = MAKEINTRESOURCE (IDD_DIRECTORY_SELECTOR); + + int result; + if ((result = CFileDialog::DoModal ()) == IDOK) + { + // Update the path + std::string newPath = (const char *)GetPathName (); + newPath = NLMISC::CFile::getPath (newPath); + RegSetValueEx (hKey, _FileType.c_str (), 0, REG_SZ, (LPBYTE)newPath.c_str (), newPath.size ()+1); + + // Update the path list + set oldPath; + uint i; + for (i=0; i::const_iterator ite = oldPath.begin (); + uint index = 0; + while (ite != oldPath.end ()) + { + RegSetValueEx (hKey, toString (index).c_str (), 0, REG_SZ, (LPBYTE)ite->c_str (), ite->size ()+1); + ite++; + index++; + } + } + return result; +} + +// *************************************************************************** + +BOOL CFileDialogEx::OnCommand( WPARAM wParam, LPARAM lParam ) +{ + if (HIWORD (wParam) == CBN_SELCHANGE) + { + if (LOWORD (wParam) == IDC_DIRLIST) + { + // The combo box + CString text; + CComboBox combo; + combo.Attach (::GetDlgItem (*this, IDC_DIRLIST)); + combo.GetWindowText (text); + combo.Detach (); + + // Set the new directory + TCHAR s[MAX_PATH]; + + // Backup contents of 'edt1' + HWND parent = *GetParent (); + ::GetDlgItemText (parent, edt1, s, MAX_PATH); + + // Replace with the directory name + ::SendMessage (parent, CDM_SETCONTROLTEXT, edt1, (LPARAM)(const char*)text); + + // Click on the OK button + ::SendMessage (parent, WM_COMMAND, IDOK, 0); + + // Restore contents of 'edt1' + ::SendMessage (parent, CDM_SETCONTROLTEXT, edt1, (LPARAM)s); + } + } + return CFileDialog::OnCommand (wParam, lParam); +} + +// *************************************************************************** + +BOOL CFileDialogEx::OnInitDialog() +{ + CFileDialog::OnInitDialog(); + + // The edit box + HWND editBox = ::GetDlgItem (*(this->GetParent ()), edt1); + + // The combo box + CComboBox combo; + combo.Attach (::GetDlgItem (*this, IDC_DIRLIST)); + + // Insert the strings + char text[512]; + text[0] = 0; + HKEY hKey; + DWORD type = REG_SZ; + DWORD size; + if (RegCreateKey (HKEY_CURRENT_USER, _RegistryPath.c_str (), &hKey) == ERROR_SUCCESS) + { + uint i; + for (i=0; i -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_FILE_DIALOG_EX_H__8301EBF3_1A27_4BAA_9A08_5DD3FD7A6D7D__INCLUDED_) -#define AFX_FILE_DIALOG_EX_H__8301EBF3_1A27_4BAA_9A08_5DD3FD7A6D7D__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// file_dialog_ex.h : header file -// - -// *************************************************************************** -// CFileDialogEx dialog -// *************************************************************************** - -class CFileDialogEx : public CFileDialog -{ - DECLARE_DYNAMIC(CFileDialogEx) - -public: - CFileDialogEx(LPCTSTR lpszRegistryPath, - LPCTSTR lpszFileType, - BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs - LPCTSTR lpszDefExt = NULL, - LPCTSTR lpszFileName = NULL, - DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, - LPCTSTR lpszFilter = NULL, - CWnd* pParentWnd = NULL); - - virtual int DoModal( ); - - virtual BOOL OnCommand( WPARAM wParam, LPARAM lParam ); - -protected: - - std::string _RegistryPath; - std::string _RegistryList; - std::string _FileType; - - //{{AFX_MSG(CFileDialogEx) - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_FILE_DIALOG_EX_H__8301EBF3_1A27_4BAA_9A08_5DD3FD7A6D7D__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_FILE_DIALOG_EX_H__8301EBF3_1A27_4BAA_9A08_5DD3FD7A6D7D__INCLUDED_) +#define AFX_FILE_DIALOG_EX_H__8301EBF3_1A27_4BAA_9A08_5DD3FD7A6D7D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// file_dialog_ex.h : header file +// + +// *************************************************************************** +// CFileDialogEx dialog +// *************************************************************************** + +class CFileDialogEx : public CFileDialog +{ + DECLARE_DYNAMIC(CFileDialogEx) + +public: + CFileDialogEx(LPCTSTR lpszRegistryPath, + LPCTSTR lpszFileType, + BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs + LPCTSTR lpszDefExt = NULL, + LPCTSTR lpszFileName = NULL, + DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, + LPCTSTR lpszFilter = NULL, + CWnd* pParentWnd = NULL); + + virtual int DoModal( ); + + virtual BOOL OnCommand( WPARAM wParam, LPARAM lParam ); + +protected: + + std::string _RegistryPath; + std::string _RegistryList; + std::string _FileType; + + //{{AFX_MSG(CFileDialogEx) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_FILE_DIALOG_EX_H__8301EBF3_1A27_4BAA_9A08_5DD3FD7A6D7D__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/find_primitive_dlg.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/find_primitive_dlg.cpp index 4ffde0338..c15fbf4b9 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/find_primitive_dlg.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/find_primitive_dlg.cpp @@ -1,353 +1,353 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// find_primitive_dlg.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "find_primitive_dlg.h" -#include "action.h" -#include "main_frm.h" -#include "editor_primitive.h" - -using namespace NLLIGO; - -CString CFindPrimitiveDlg::Property = _T(""); -CString CFindPrimitiveDlg::Value = _T(""); -CString CFindPrimitiveDlg::ReplaceText = _T(""); -int CFindPrimitiveDlg::SelectionOnly=0; // false; - -// *************************************************************************** -// CFindPrimitiveDlg dialog -// *************************************************************************** - -CFindPrimitiveDlg::CFindPrimitiveDlg(CWnd* pParent /*=NULL*/) - : CDialog(CFindPrimitiveDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CFindPrimitiveDlg) - PrimitiveName = _T(""); - SelectionOnly=0; // false; - //}}AFX_DATA_INIT -} - -// *************************************************************************** - -void CFindPrimitiveDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CFindPrimitiveDlg) - DDX_Text(pDX, IDC_PROPERTY, Property); - DDX_Text(pDX, IDC_VALUE, Value); - DDX_Text(pDX, IDC_PRIMITIVE_NAME, PrimitiveName); - DDX_Text(pDX, IDC_REPLACE_TEXT, ReplaceText); - DDX_Check(pDX, IDC_SELECTION, SelectionOnly); - //}}AFX_DATA_MAP -} - -// *************************************************************************** - -BEGIN_MESSAGE_MAP(CFindPrimitiveDlg, CDialog) - //{{AFX_MSG_MAP(CFindPrimitiveDlg) - ON_BN_CLICKED(ID_FIND_NEXT, OnFindNext) - ON_BN_CLICKED(ID_REPLACE, OnReplace) - ON_BN_CLICKED(ID_REPLACE_ALL, OnReplaceAll) -// ON_BN_CLICKED(IDC_SELECTION, SetSelection) - ON_WM_DESTROY() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// *************************************************************************** -// CFindPrimitiveDlg message handlers -// *************************************************************************** - -void CFindPrimitiveDlg::SetSelection() -{ - SelectionOnly=1-SelectionOnly; - _Locator.getRoot(0); - UpdateData (); -} - -void CFindPrimitiveDlg::OnFindNext() -{ - CDatabaseLocatorPointer TmpLocator; - UpdateData (); - - // Find the primitive - TmpLocator.getRoot(0); - if (_Locator == TmpLocator) - { - _End = false; - } - else - { - _End = !_Locator.next (); - } - bool found = false; - while (!_End) - { - // Primitive here ? - if (_Locator.Primitive) - { - // Property here ? - const IProperty *property; - if ( ( !SelectionOnly -// || ( _Locator.Primitive->getPropertyByName ("selected", property) - || ( getPrimitiveEditor(_Locator.Primitive)->getSelected())) -// && property) ) - && _Locator.Primitive->getPropertyByName ((const char*)Property, property) - && property) - { - // Kind of primitive ? - const CPropertyString *propString = dynamic_cast(property); - if (propString) - { - // Good value ? - if (propString->String.find(Value)!=std::string::npos) - { - found = true; - } - - } - else - { - const CPropertyStringArray *propStringArray = dynamic_cast(property); - if (propStringArray) - { - // For all the values - uint i; - for (i=0; iStringArray.size (); i++) - { - if (propStringArray->StringArray[i].find(Value)!=std::string::npos) - { - found = true; - } - - } - - } - - } - - } - - } - - if (found) break; - // Last one ? - _End = !_Locator.next (); - } - - // Found ? - if (found) - { - // Primitive name - PrimitiveName = ("Found : " + _Locator.getPathName ()).c_str (); - - // Get the document - CWorldEditorDoc *doc = getDocument (); - - doc->beginModification (); - // Unselect all - doc->addModification (new CActionUnselectAll ()); - - // Select the primitive - doc->addModification (new CActionSelect (_Locator)); - doc->endModification (); - - // Update view - getMainFrame ()->updateData (); - getMainFrame ()->OnViewLocateselectedprimitives (); - getMainFrame ()->OnViewLocateselectedprimitivesTree (); - } - else - { - MessageBox ("End of the document", "Find a primitive...", MB_OK|MB_ICONEXCLAMATION); - - // Init locator - _Locator.getRoot (0); - PrimitiveName = ""; - } - UpdateData (FALSE); -} - -void CFindPrimitiveDlg::OnReplaceAll() -{ - replace(true); -} - -void CFindPrimitiveDlg::OnReplace() -{ - replace(false); -} - - -void CFindPrimitiveDlg::replace(bool all) -{ - CDatabaseLocatorPointer TmpLocator; - UpdateData (); - - if (all) - _Locator.getRoot(0); // starts at top of document. - - // Find the primitive - TmpLocator.getRoot(0); - if (_Locator == TmpLocator) - { - _End = false; - } - - CWorldEditorDoc *doc = getDocument (); - doc->beginModification (); - - bool firstTime=true; - - while (!_End) - { - // Primitive here ? - if (_Locator.Primitive) - { - // Property here ? - const IProperty *property; - if ( ( !SelectionOnly -// || ( _Locator.Primitive->getPropertyByName ("selected", property) - || ( getPrimitiveEditor(_Locator.Primitive)->getSelected())) -// && property) ) - && _Locator.Primitive->getPropertyByName ((const char*)Property, property) - && property ) - { - // Kind of primitive ? - const CPropertyString *propString = dynamic_cast(property); - if (propString) - { - // Good value ? - if (propString->String.find(Value)!=std::string::npos) - { - if (!firstTime && !all) - break; - - CString tmp(propString->String.c_str()); - tmp.Replace(Value, ReplaceText); - doc->addModification (new CActionSetPrimitivePropertyString (_Locator,(const char*)Property,(const char*)tmp,false)); - doc->addModification (new CActionSelect (_Locator)); - - firstTime=false; - } - - } - else - { - const CPropertyStringArray *propStringArray = dynamic_cast(property); - if (propStringArray) - { - bool firstChange=true; - std::vector newStrings; - - // For all the values - uint i; - for (i=0; iStringArray.size (); i++) - { - // todo. - if (propStringArray->StringArray[i].find(Value)!=std::string::npos) - { - if ( !firstTime - && !all) - break; - - CString tmp(propStringArray->StringArray[i].c_str()); - const int nbChange=tmp.Replace(Value, ReplaceText); - - if (nbChange>0) - { - if (firstChange) - { - newStrings=propStringArray->StringArray; - firstChange=false; - } - newStrings[i]=std::string((const char*)tmp); - } - firstTime=false; - } - - } - - if (!firstChange) // have to make a change - { - doc->addModification (new CActionSetPrimitivePropertyStringArray (_Locator,(const char*)Property,newStrings,false)); - doc->addModification (new CActionSelect (_Locator)); - } - - } - - } - - } - - } -// // Last one ? - _End = !_Locator.next (); - } - - if (!_End) - { - doc->addModification (new CActionSelect (_Locator)); - } - - doc->endModification (); - - // Update view - getMainFrame ()->updateData (); - getMainFrame ()->OnViewLocateselectedprimitives (); - getMainFrame ()->OnViewLocateselectedprimitivesTree (); - - UpdateData (FALSE); - - if (_End) - { - MessageBox ("End of the document", "Find a primitive...", MB_OK|MB_ICONEXCLAMATION); - _Locator.getRoot (0); - } - -} - -// *************************************************************************** - -BOOL CFindPrimitiveDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // Init locator - - _Locator.getRoot (0); - - // Get the document - //CWorldEditorDoc *doc = getDocument (); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -// *************************************************************************** - -void CFindPrimitiveDlg::OnDestroy() -{ - CDialog::OnDestroy(); - - // Get the document - //CWorldEditorDoc *doc = getDocument (); -} - -// *************************************************************************** +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// find_primitive_dlg.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "find_primitive_dlg.h" +#include "action.h" +#include "main_frm.h" +#include "editor_primitive.h" + +using namespace NLLIGO; + +CString CFindPrimitiveDlg::Property = _T(""); +CString CFindPrimitiveDlg::Value = _T(""); +CString CFindPrimitiveDlg::ReplaceText = _T(""); +int CFindPrimitiveDlg::SelectionOnly=0; // false; + +// *************************************************************************** +// CFindPrimitiveDlg dialog +// *************************************************************************** + +CFindPrimitiveDlg::CFindPrimitiveDlg(CWnd* pParent /*=NULL*/) + : CDialog(CFindPrimitiveDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CFindPrimitiveDlg) + PrimitiveName = _T(""); + SelectionOnly=0; // false; + //}}AFX_DATA_INIT +} + +// *************************************************************************** + +void CFindPrimitiveDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CFindPrimitiveDlg) + DDX_Text(pDX, IDC_PROPERTY, Property); + DDX_Text(pDX, IDC_VALUE, Value); + DDX_Text(pDX, IDC_PRIMITIVE_NAME, PrimitiveName); + DDX_Text(pDX, IDC_REPLACE_TEXT, ReplaceText); + DDX_Check(pDX, IDC_SELECTION, SelectionOnly); + //}}AFX_DATA_MAP +} + +// *************************************************************************** + +BEGIN_MESSAGE_MAP(CFindPrimitiveDlg, CDialog) + //{{AFX_MSG_MAP(CFindPrimitiveDlg) + ON_BN_CLICKED(ID_FIND_NEXT, OnFindNext) + ON_BN_CLICKED(ID_REPLACE, OnReplace) + ON_BN_CLICKED(ID_REPLACE_ALL, OnReplaceAll) +// ON_BN_CLICKED(IDC_SELECTION, SetSelection) + ON_WM_DESTROY() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// *************************************************************************** +// CFindPrimitiveDlg message handlers +// *************************************************************************** + +void CFindPrimitiveDlg::SetSelection() +{ + SelectionOnly=1-SelectionOnly; + _Locator.getRoot(0); + UpdateData (); +} + +void CFindPrimitiveDlg::OnFindNext() +{ + CDatabaseLocatorPointer TmpLocator; + UpdateData (); + + // Find the primitive + TmpLocator.getRoot(0); + if (_Locator == TmpLocator) + { + _End = false; + } + else + { + _End = !_Locator.next (); + } + bool found = false; + while (!_End) + { + // Primitive here ? + if (_Locator.Primitive) + { + // Property here ? + const IProperty *property; + if ( ( !SelectionOnly +// || ( _Locator.Primitive->getPropertyByName ("selected", property) + || ( getPrimitiveEditor(_Locator.Primitive)->getSelected())) +// && property) ) + && _Locator.Primitive->getPropertyByName ((const char*)Property, property) + && property) + { + // Kind of primitive ? + const CPropertyString *propString = dynamic_cast(property); + if (propString) + { + // Good value ? + if (propString->String.find(Value)!=std::string::npos) + { + found = true; + } + + } + else + { + const CPropertyStringArray *propStringArray = dynamic_cast(property); + if (propStringArray) + { + // For all the values + uint i; + for (i=0; iStringArray.size (); i++) + { + if (propStringArray->StringArray[i].find(Value)!=std::string::npos) + { + found = true; + } + + } + + } + + } + + } + + } + + if (found) break; + // Last one ? + _End = !_Locator.next (); + } + + // Found ? + if (found) + { + // Primitive name + PrimitiveName = ("Found : " + _Locator.getPathName ()).c_str (); + + // Get the document + CWorldEditorDoc *doc = getDocument (); + + doc->beginModification (); + // Unselect all + doc->addModification (new CActionUnselectAll ()); + + // Select the primitive + doc->addModification (new CActionSelect (_Locator)); + doc->endModification (); + + // Update view + getMainFrame ()->updateData (); + getMainFrame ()->OnViewLocateselectedprimitives (); + getMainFrame ()->OnViewLocateselectedprimitivesTree (); + } + else + { + MessageBox ("End of the document", "Find a primitive...", MB_OK|MB_ICONEXCLAMATION); + + // Init locator + _Locator.getRoot (0); + PrimitiveName = ""; + } + UpdateData (FALSE); +} + +void CFindPrimitiveDlg::OnReplaceAll() +{ + replace(true); +} + +void CFindPrimitiveDlg::OnReplace() +{ + replace(false); +} + + +void CFindPrimitiveDlg::replace(bool all) +{ + CDatabaseLocatorPointer TmpLocator; + UpdateData (); + + if (all) + _Locator.getRoot(0); // starts at top of document. + + // Find the primitive + TmpLocator.getRoot(0); + if (_Locator == TmpLocator) + { + _End = false; + } + + CWorldEditorDoc *doc = getDocument (); + doc->beginModification (); + + bool firstTime=true; + + while (!_End) + { + // Primitive here ? + if (_Locator.Primitive) + { + // Property here ? + const IProperty *property; + if ( ( !SelectionOnly +// || ( _Locator.Primitive->getPropertyByName ("selected", property) + || ( getPrimitiveEditor(_Locator.Primitive)->getSelected())) +// && property) ) + && _Locator.Primitive->getPropertyByName ((const char*)Property, property) + && property ) + { + // Kind of primitive ? + const CPropertyString *propString = dynamic_cast(property); + if (propString) + { + // Good value ? + if (propString->String.find(Value)!=std::string::npos) + { + if (!firstTime && !all) + break; + + CString tmp(propString->String.c_str()); + tmp.Replace(Value, ReplaceText); + doc->addModification (new CActionSetPrimitivePropertyString (_Locator,(const char*)Property,(const char*)tmp,false)); + doc->addModification (new CActionSelect (_Locator)); + + firstTime=false; + } + + } + else + { + const CPropertyStringArray *propStringArray = dynamic_cast(property); + if (propStringArray) + { + bool firstChange=true; + std::vector newStrings; + + // For all the values + uint i; + for (i=0; iStringArray.size (); i++) + { + // todo. + if (propStringArray->StringArray[i].find(Value)!=std::string::npos) + { + if ( !firstTime + && !all) + break; + + CString tmp(propStringArray->StringArray[i].c_str()); + const int nbChange=tmp.Replace(Value, ReplaceText); + + if (nbChange>0) + { + if (firstChange) + { + newStrings=propStringArray->StringArray; + firstChange=false; + } + newStrings[i]=std::string((const char*)tmp); + } + firstTime=false; + } + + } + + if (!firstChange) // have to make a change + { + doc->addModification (new CActionSetPrimitivePropertyStringArray (_Locator,(const char*)Property,newStrings,false)); + doc->addModification (new CActionSelect (_Locator)); + } + + } + + } + + } + + } +// // Last one ? + _End = !_Locator.next (); + } + + if (!_End) + { + doc->addModification (new CActionSelect (_Locator)); + } + + doc->endModification (); + + // Update view + getMainFrame ()->updateData (); + getMainFrame ()->OnViewLocateselectedprimitives (); + getMainFrame ()->OnViewLocateselectedprimitivesTree (); + + UpdateData (FALSE); + + if (_End) + { + MessageBox ("End of the document", "Find a primitive...", MB_OK|MB_ICONEXCLAMATION); + _Locator.getRoot (0); + } + +} + +// *************************************************************************** + +BOOL CFindPrimitiveDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Init locator + + _Locator.getRoot (0); + + // Get the document + //CWorldEditorDoc *doc = getDocument (); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +// *************************************************************************** + +void CFindPrimitiveDlg::OnDestroy() +{ + CDialog::OnDestroy(); + + // Get the document + //CWorldEditorDoc *doc = getDocument (); +} + +// *************************************************************************** diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/find_primitive_dlg.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/find_primitive_dlg.h index 24ab19fd3..3d96c5027 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/find_primitive_dlg.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/find_primitive_dlg.h @@ -1,81 +1,81 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_FIND_PRIMITIVE_DLG_H__CBD80497_7501_4021_97EB_64ADD1C65146__INCLUDED_) -#define AFX_FIND_PRIMITIVE_DLG_H__CBD80497_7501_4021_97EB_64ADD1C65146__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// find_primitive_dlg.h : header file -// - -#include "world_editor_doc.h" - -///////////////////////////////////////////////////////////////////////////// -// CFindPrimitiveDlg dialog - -class CFindPrimitiveDlg : public CDialog -{ -// Construction -public: - CFindPrimitiveDlg(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CFindPrimitiveDlg) - enum { IDD = IDD_FIND_PRIMITIVE }; - - static CString Property; - static CString Value; - static CString ReplaceText; - static int SelectionOnly; - - CString PrimitiveName; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CFindPrimitiveDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // The locator - CDatabaseLocatorPointer _Locator; - bool _End; - - void replace(bool all); - - // Generated message map functions - //{{AFX_MSG(CFindPrimitiveDlg) - afx_msg void OnFindNext(); - afx_msg void OnReplace(); - afx_msg void OnReplaceAll(); - virtual BOOL OnInitDialog(); - afx_msg void OnDestroy(); - afx_msg void SetSelection(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_FIND_PRIMITIVE_DLG_H__CBD80497_7501_4021_97EB_64ADD1C65146__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_FIND_PRIMITIVE_DLG_H__CBD80497_7501_4021_97EB_64ADD1C65146__INCLUDED_) +#define AFX_FIND_PRIMITIVE_DLG_H__CBD80497_7501_4021_97EB_64ADD1C65146__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// find_primitive_dlg.h : header file +// + +#include "world_editor_doc.h" + +///////////////////////////////////////////////////////////////////////////// +// CFindPrimitiveDlg dialog + +class CFindPrimitiveDlg : public CDialog +{ +// Construction +public: + CFindPrimitiveDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CFindPrimitiveDlg) + enum { IDD = IDD_FIND_PRIMITIVE }; + + static CString Property; + static CString Value; + static CString ReplaceText; + static int SelectionOnly; + + CString PrimitiveName; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CFindPrimitiveDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // The locator + CDatabaseLocatorPointer _Locator; + bool _End; + + void replace(bool all); + + // Generated message map functions + //{{AFX_MSG(CFindPrimitiveDlg) + afx_msg void OnFindNext(); + afx_msg void OnReplace(); + afx_msg void OnReplaceAll(); + virtual BOOL OnInitDialog(); + afx_msg void OnDestroy(); + afx_msg void SetSelection(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_FIND_PRIMITIVE_DLG_H__CBD80497_7501_4021_97EB_64ADD1C65146__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_dlg.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_dlg.cpp index 2f5a53df7..71e2465f9 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_dlg.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_dlg.cpp @@ -1,98 +1,98 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// Generate.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "resource.h" -#include "generate_dlg.h" - -///////////////////////////////////////////////////////////////////////////// -// CGenerateDlg dialog - - -CGenerateDlg::CGenerateDlg(CWnd* pParent /*=NULL*/) - : CDialog(CGenerateDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CGenerateDlg) - MinX = 0; - MinY = 0; - MaxY = 0; - MaxX = 0; - ZoneBaseX = 0; - ZoneBaseY = 0; - ComboMaterialString = _T(""); - //}}AFX_DATA_INIT -} - - -void CGenerateDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CGenerateDlg) - DDX_Control(pDX, IDC_COMBOMATERIAL, ComboMaterial); - DDX_Text(pDX, IDC_EDITMINX, MinX); - DDX_Text(pDX, IDC_EDITMINY, MinY); - DDX_Text(pDX, IDC_EDITMAXY, MaxY); - DDX_Text(pDX, IDC_EDITMAXX, MaxX); - DDX_Text(pDX, IDC_EDITZONEBASEX, ZoneBaseX); - DDX_Text(pDX, IDC_EDITZONEBASEY, ZoneBaseY); - DDX_CBString(pDX, IDC_COMBOMATERIAL, ComboMaterialString); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CGenerateDlg, CDialog) - //{{AFX_MSG_MAP(CGenerateDlg) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CGenerateDlg message handlers - -BOOL CGenerateDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - for (uint32 i = 0; i < AllMaterials.size(); ++i) - ComboMaterial.InsertString(-1, AllMaterials[i].c_str()); - - ComboMaterial.SetCurSel (0); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -void CGenerateDlg::OnOK() -{ - // TODO: Add extra validation here - UpdateData (TRUE); - - if (MinX > MaxX) - { - MessageBox ("MinX > MaxX", "Error", MB_OK|MB_ICONSTOP); - return; - } - if (MinY > MaxY) - { - MessageBox ("MinY > MaxY", "Error", MB_OK|MB_ICONSTOP); - return; - } - CDialog::OnOK(); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// Generate.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "resource.h" +#include "generate_dlg.h" + +///////////////////////////////////////////////////////////////////////////// +// CGenerateDlg dialog + + +CGenerateDlg::CGenerateDlg(CWnd* pParent /*=NULL*/) + : CDialog(CGenerateDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CGenerateDlg) + MinX = 0; + MinY = 0; + MaxY = 0; + MaxX = 0; + ZoneBaseX = 0; + ZoneBaseY = 0; + ComboMaterialString = _T(""); + //}}AFX_DATA_INIT +} + + +void CGenerateDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CGenerateDlg) + DDX_Control(pDX, IDC_COMBOMATERIAL, ComboMaterial); + DDX_Text(pDX, IDC_EDITMINX, MinX); + DDX_Text(pDX, IDC_EDITMINY, MinY); + DDX_Text(pDX, IDC_EDITMAXY, MaxY); + DDX_Text(pDX, IDC_EDITMAXX, MaxX); + DDX_Text(pDX, IDC_EDITZONEBASEX, ZoneBaseX); + DDX_Text(pDX, IDC_EDITZONEBASEY, ZoneBaseY); + DDX_CBString(pDX, IDC_COMBOMATERIAL, ComboMaterialString); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CGenerateDlg, CDialog) + //{{AFX_MSG_MAP(CGenerateDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGenerateDlg message handlers + +BOOL CGenerateDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + for (uint32 i = 0; i < AllMaterials.size(); ++i) + ComboMaterial.InsertString(-1, AllMaterials[i].c_str()); + + ComboMaterial.SetCurSel (0); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CGenerateDlg::OnOK() +{ + // TODO: Add extra validation here + UpdateData (TRUE); + + if (MinX > MaxX) + { + MessageBox ("MinX > MaxX", "Error", MB_OK|MB_ICONSTOP); + return; + } + if (MinY > MaxY) + { + MessageBox ("MinY > MaxY", "Error", MB_OK|MB_ICONSTOP); + return; + } + CDialog::OnOK(); +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_dlg.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_dlg.h index cd657919f..cf4334b7b 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_dlg.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_dlg.h @@ -1,73 +1,73 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_GENERATE_H__40A5DE91_9FB6_44AC_BE31_839844ED999A__INCLUDED_) -#define AFX_GENERATE_H__40A5DE91_9FB6_44AC_BE31_839844ED999A__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// GenerateDlg.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CGenerateDlg dialog - -class CGenerateDlg : public CDialog -{ -// Construction -public: - CGenerateDlg(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CGenerateDlg) - enum { IDD = IDD_GENERATE }; - CComboBox ComboMaterial; - int MinX; - int MinY; - int MaxY; - int MaxX; - int ZoneBaseX; - int ZoneBaseY; - CString ComboMaterialString; - //}}AFX_DATA - - - std::vector AllMaterials; - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CGenerateDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CGenerateDlg) - virtual BOOL OnInitDialog(); - virtual void OnOK(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_GENERATE_H__40A5DE91_9FB6_44AC_BE31_839844ED999A__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_GENERATE_H__40A5DE91_9FB6_44AC_BE31_839844ED999A__INCLUDED_) +#define AFX_GENERATE_H__40A5DE91_9FB6_44AC_BE31_839844ED999A__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// GenerateDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CGenerateDlg dialog + +class CGenerateDlg : public CDialog +{ +// Construction +public: + CGenerateDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CGenerateDlg) + enum { IDD = IDD_GENERATE }; + CComboBox ComboMaterial; + int MinX; + int MinY; + int MaxY; + int MaxX; + int ZoneBaseX; + int ZoneBaseY; + CString ComboMaterialString; + //}}AFX_DATA + + + std::vector AllMaterials; + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGenerateDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CGenerateDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_GENERATE_H__40A5DE91_9FB6_44AC_BE31_839844ED999A__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_primitive.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_primitive.cpp index 4e31e1a79..a7364a60e 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_primitive.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_primitive.cpp @@ -1,1120 +1,1120 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" - -#include "editor_primitive.h" -#include "generate_primitive.h" -#include "world_editor.h" -#include "world_editor_doc.h" - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; -using namespace NL3D; -using namespace NLGEORGES; - -// *************************************************************************** - -/* - -Implementation notes: ---------------------- - -- Load all the "landscape zones" overlapped by the source zone -- Build a quad tree with all primitives to check overlapping -- List all the plants used the source zone -- Sort them by size (Place first the biggest one) -- For each plants in the sorted list - - Compute a grid position depending the plant size and the plant density - - Jitter it with a random function - - Test if the final position is valid - - Check the primitive doesn't overlappe another primitive (using the quad tree) - - Check the final position is posed over the landscape, not in a hole - - Make some Z samples (Z_SAMPLE_COUNT, hard coded) around the position with the collision radius - - For each check if the delta z is behind a fixed (Z_THRESHOLD, hard coded) threshold -*/ - -// *** Features - -// Enable / disable z position test -#define TEST_Z_POSITION - -// *** todo : pass this as generation parameters - -// Test N time max to place a point -#define GENERATE_PRIMITIVE_TEST_COUNT 4 - -// Small epsilon for triangle selection -#define SELECTION_EPSILON (0.1f) - -// Z sample to do around the position to check Z -#define Z_SAMPLE_COUNT 8 - -// Z threshold used to validate each sample -#define Z_THRESHOLD (0.8f) - -// *************************************************************************** - -CGeneratePrimitive::CGeneratePrimitive () -{ - _Landscape = NULL; - /* todo COL_USING_VISUAL_COLLISION_MANAGER - _VCM = NULL; - _VCE = NULL; */ -} - -// *************************************************************************** - -// Flora plant class, used by the flora class to reference the plants -class CFloraPlant -{ -public: - string Name; - float Density; - float Falloff; - - // Data duplicated from the plant form to avoid a map lookup - float BoundingRadius; - float CollisionRadius; -}; - -// *************************************************************************** - -// Flora class, filled with the flora form -class CFlora -{ -public: - // The plants references - vector Plants; - - // Excludes primitives - vector ExcludePrimitives; - - // Generation parameters - float JitterPos; - float ScaleMin; - float ScaleMax; - bool PutOnWater; - float WaterHeight; - uint32 RandomSeed; - - // *** Precalculation - - // Bounding min - CVector VMin; - - // Bounding max - CVector VMax; - - // *** Variables - uint NewPrimitiveCount; -}; - -// *************************************************************************** - -/* Sort plant - * This struct is used to sort plants by radius - */ -class CSortPlant -{ -public: - // Contructor - CSortPlant (uint floraId, uint plantId, const vector *floraVector) - { - FloraId = floraId; - PlantId = plantId; - FloraVector = floraVector; - } - - // Comparison - bool operator< (const CSortPlant &other) const - { - return (*FloraVector)[FloraId].Plants[PlantId].BoundingRadius < (*FloraVector)[other.FloraId].Plants[other.PlantId].BoundingRadius; - } - - // The flora id - uint FloraId; - - // The plant id - uint PlantId; - - // The flora vector - const vector *FloraVector; -}; - -// *************************************************************************** - -bool CGeneratePrimitive::generate (std::vector< std::vector > &dest, const std::vector &source, - NLMISC::IProgressCallback &callback, const CLigoConfig &config, const char *dataDirectory, - const char *primClassToGenerate) -{ - // Get the doc - CWorldEditorDoc *doc = getDocument (); - - // Erase dest - dest.clear (); - dest.resize (source.size ()); - - // Clear - clear (); - - // Create a landscape - _Landscape = new CLandscape (); - _Landscape->init (); - - // Get the prim class to generate - const CPrimitiveClass *genPrimClass = theApp.Config.getPrimitiveClass (primClassToGenerate); - nlassert (genPrimClass); - - // Visual collision manager - /* todo COL_USING_VISUAL_COLLISION_MANAGER - _VCM = new CVisualCollisionManager; - _VCE = _VCM->createEntity (); - _VCM->setLandscape (_Landscape); - _VCE->setSnapToRenderedTesselation (false); - */ - - // Load the landscape - if (loadLandscape (source, callback, config, dataDirectory)) - { - // Generate vegetation - uint i, j; - - // Load the .Flora file (georges file) and load all associated .plant - vector flora (source.size ()); - - // Create a loader - UFormLoader *loader = UFormLoader::createLoader (); - - // Keep last form alive - CSmartPtr form; - CSmartPtr form2; - - // For each source primitives - for (i=0; igetPropertyByName ("form", floraName)) - { - // Progress bar - callback.DisplayString = "Reading "+(floraName+".flora")+"..."; - callback.progress ((float)i/(float)source.size ()); - callback.pushCropedValues ((float)i/(float)source.size (), (float)(i+1)/(float)source.size ()); - - // Get the path name - string filename = CPath::lookup (floraName+".flora", false, false, false); - if (!filename.empty ()) - { - // Load the form - form = loader->loadForm (filename.c_str ()); - if (form == NULL) - { - // One more error - _FileNotFound.push_back (filename); - } - else - { - // Get the root node - UFormElm &rootNode = form->getRootNode (); - - // Read the Plants field - UFormElm *pElt; - if (rootNode.getNodeByName (&pElt, "Plants") && pElt) - { - uint size; - nlverify (pElt->getArraySize (size)); - for (j=0; jgetArrayNode (&pArrayElt, j) && pArrayElt) - { - // Read the plant values - CFloraPlant plant; - pArrayElt->getValueByName (plant.Name, "File name"); - pArrayElt->getValueByName (plant.Density, "Density"); - pArrayElt->getValueByName (plant.Falloff, "Falloff"); - plant.CollisionRadius = 0.f; - plant.BoundingRadius = 1; - plant.Name = NLMISC::CFile::getFilenameWithoutExtension (plant.Name); - - // Progress bar - callback.DisplayString = "Reading "+plant.Name+"..."; - callback.progress ((float)j/(float)size); - - // Get the path name - string filename = CPath::lookup (plant.Name+".plant", false, false, false); - if (!filename.empty ()) - { - // Read the plant file - form2 = loader->loadForm (filename.c_str()); - if (form2) - { - // Read the plant - float CollisionRadius = 0; - float BoundingRadius = 1; - - // Get root node - UFormElm &rootNode2 = form2->getRootNode (); - - rootNode2.getValueByName (plant.CollisionRadius, "3D.Collision Radius"); - rootNode2.getValueByName (plant.BoundingRadius, "3D.Bounding Radius"); - - // Add it - flora[i].Plants.push_back (plant); - } - else - { - _FileNotFound.push_back (filename); - } - } - else - { - _FileNotFound.push_back (plant.Name); - } - } - } - } - - // Read the flora values - flora[i].NewPrimitiveCount = 0; - rootNode.getValueByName (flora[i].JitterPos, "Jitter_Pos"); - rootNode.getValueByName (flora[i].ScaleMin, "Scale_Min"); - rootNode.getValueByName (flora[i].ScaleMax, "Scale_Max"); - rootNode.getValueByName (flora[i].PutOnWater, "Put_On_Water"); - rootNode.getValueByName (flora[i].WaterHeight, "Water_Height"); - rootNode.getValueByName (flora[i].RandomSeed, "Random_Seed"); - - // For each vertices - uint numVertices = source[i]->getNumVector (); - if (numVertices) - { - // Get the vector position - const CPrimVector *pos = source[i]->getPrimVector (); - - // Get the bounding of the zone - flora[i].VMin = flora[i].VMax = pos[0]; - for (j = 0; j < numVertices; ++j) - { - // Get the vector position - if (flora[i].VMin.x > pos[j].x) - flora[i].VMin.x = pos[j].x; - if (flora[i].VMin.y > pos[j].y) - flora[i].VMin.y = pos[j].y; - if (flora[i].VMin.z > pos[j].z) - flora[i].VMin.z = pos[j].z; - if (flora[i].VMax.x < pos[j].x) - flora[i].VMax.x = pos[j].x; - if (flora[i].VMax.y < pos[j].y) - flora[i].VMax.y = pos[j].y; - if (flora[i].VMax.z < pos[j].z) - flora[i].VMax.z = pos[j].z; - } - } - - // ** Get exclude zone - uint numFloraChildren = source[i]->getNumChildren (); - for (uint k=0; kgetChild (child, k)); - - // Is it a zone ? - const CPrimZoneEditor *zone = dynamic_cast (child); - if (zone) - { - // Is it an explude zone ? - string className; - if (zone->getPropertyByName ("class", className) && (className == "flora_exclude")) - { - // Add it - flora[i].ExcludePrimitives.push_back (zone); - } - } - } - } - } - else - { - _FileNotFound.push_back (floraName+".flora"); - } - - // Progress bar - callback.popCropedValues (); - } - } - - // Error ? - if (!_FileNotFound.empty ()) - { - // Continue ? - char message[2048]; - message[0] = 0; - for (uint i=0; i<_FileNotFound.size (); i++) - { - strcat (message, _FileNotFound[i].c_str ()); - strcat (message, "\n"); - } - - if (!theApp.yesNoMessage ("Can't load some files:\n%s\nContinue ?", message)) - { - return false; - } - } - - // Insert plants - vector sortedPlants; - for (i=0; i quadGrid; - quadGrid.create (256, 10.f); - - // Progress bar - callback.DisplayString = "Build quad grid"; - - // Insert all the primitive found - uint numPrimitive = doc->getNumDatabaseElement (); - for (i=0; igetDatabaseElements (i).RootNode), &callback); - - // Progress bar - callback.popCropedValues (); - } - - // ** Take a srand found in selected primitives - - uint randSeed = 0; - for (i=0; i= 0; sortedPlant--) - { - // Progress bar - callback.progress ((float)(sortedPlants.size ()-sortedPlant-1)/(float)(sortedPlants.size ())); - callback.pushCropedValues ((float)(sortedPlants.size ()-sortedPlant-1)/(float)sortedPlants.size (), (float)(sortedPlants.size ()-sortedPlant)/(float)sortedPlants.size ()); - - // Ref on the flora - CFlora &theFlora = flora[sortedPlants[sortedPlant].FloraId]; - - // Ref on the plant - const CFloraPlant &thePlant = theFlora.Plants[sortedPlants[sortedPlant].PlantId]; - - // Get a valid jitter - float jitter = theFlora.JitterPos; - clamp (jitter, 0.0f, 1.0f); - - // Is it a non empty zone or path ? - const CPrimZoneEditor *zone = dynamic_cast (source[sortedPlants[sortedPlant].FloraId]); - if (zone) - { - // Some vector - if (((const IPrimitive*)zone)->getNumVector ()) - { - // Distance between primitives - float squareLength = (float)sqrt (Pi*thePlant.BoundingRadius*thePlant.BoundingRadius / thePlant.Density); - - // Number of primitive on X and Y axis to try to place - uint32 nNbPlantX = 1+(int)floor ((theFlora.VMax.x-theFlora.VMin.x) / squareLength); - uint32 nNbPlantY = 1+(int)floor ((theFlora.VMax.y-theFlora.VMin.y) / squareLength); - - // Pose plants - uint k, l; - for (l = 0; l < nNbPlantY; ++l) - for (k = 0; k < nNbPlantX; ++k) - { - // Progress bar - callback.progress ((float)(l*nNbPlantX+k)/(float)(nNbPlantY*nNbPlantX)); - - // Try sveral times times - uint m; - for (m = 0; m < GENERATE_PRIMITIVE_TEST_COUNT; ++m) - { - // Generate a position - CVector pos; - pos.x = theFlora.VMin.x + squareLength * k + (frand(2.0f)-1.0f) * jitter * 0.5f * squareLength; - pos.y = theFlora.VMin.y + squareLength * l + (frand(2.0f)-1.0f) * jitter * 0.5f * squareLength; - pos.z = 0.0f; - - // Does the zone contains the position generated ? - if (zone->contains(pos)) - { - // Add the primitive - if (addPrimitive (dest[sortedPlants[sortedPlant].FloraId], pos, primClassToGenerate, *zone, theFlora, thePlant, quadGrid, config)) - { - theFlora.NewPrimitiveCount++; - break; - } - } - } - } - } - } - else - { - // Is it a path ? - const CPrimPathEditor *path = dynamic_cast (source[sortedPlants[sortedPlant].FloraId]); - if (path) - { - // Total length of the broken line - float length = 0.0f; - for (j = 0; j < path->VPoints.size()-1; ++j) - length += (path->VPoints[j]-path->VPoints[j+1]).norm(); - - // Number of primitives on this path - float squareLength = (float)(2*thePlant.BoundingRadius / thePlant.Density); - uint nNbPlant = 1+(int)floor (length / squareLength); - - // Pose plants - uint k; - for (k = 0; k < nNbPlant; ++k) - { - // Progress bar - callback.progress ((float)(k)/(float)(nNbPlant)); - - bool bExists = false; - CVector pos; - - // Try sveral times times - uint m; - for (m = 0; m < GENERATE_PRIMITIVE_TEST_COUNT; ++m) - { - // Calculate the curviline abscisse - float curvAbs = squareLength * k + (frand(2.0f)-1.0f) * jitter * 0.5f * squareLength; - if ((curvAbs>=0) && (curvAbsVPoints.size()-1; ++l) - { - float newSize = (path->VPoints[l]-path->VPoints[l+1]).norm(); - if (curvAbs < (TempLength+newSize)) - { - curvAbs -= TempLength; - break; - } - TempLength += newSize; - } - - // Placed ? - if (l != (path->VPoints.size()-1)) - { - // Calculate the coord - curvAbs = curvAbs / (path->VPoints[l]-path->VPoints[l+1]).norm(); - pos = path->VPoints[l] + (path->VPoints[l+1]-path->VPoints[l])*curvAbs; - pos.z = 0.0f; - - // Add the primitive - if (addPrimitive (dest[sortedPlants[sortedPlant].FloraId], pos, primClassToGenerate, *path, theFlora, thePlant,quadGrid, config)) - { - theFlora.NewPrimitiveCount++; - break; - } - } - } - } - } - } - } - - // Progress bar - callback.popCropedValues (); - } - } - - // Done - return true; - } - - // Failed - return false; -} - -// *************************************************************************** - -bool CGeneratePrimitive::loadLandscape (const std::vector &source, NLMISC::IProgressCallback &callback, - const NLLIGO::CLigoConfig &config, const char *dataDirectory) -{ - // Get the bbox of the primitives - CAABBox bbox; - bool firstPoint = true; - for (uint i=0; igetNumVector (); - if (nbVert) - { - // Get the vectors - const CPrimVector *vectors = source[i]->getPrimVector (); - for (uint j=0; jaddZone (zone); - } - } - } - } - - // Done - return true; -} - -// *************************************************************************** - -void CGeneratePrimitive::clear () -{ - /* todo COL_USING_VISUAL_COLLISION_MANAGER - // Delete the entity - if (_VCE) - { - nlassert (_VCM); - _VCM->deleteEntity; - _VCE = NULL; - } - - // Delete the manager - if (_VCM) - { - delete _VCM; - _VCM = NULL; - } - */ - - // Delete the landscape - if (_Landscape) - { - delete (_Landscape); - _Landscape = NULL; - } - - _FileNotFound.clear (); -} - -// *************************************************************************** - -CGeneratePrimitive::~CGeneratePrimitive () -{ - clear (); -} - -// *************************************************************************** - -void CGeneratePrimitive::insertPrimitive (CQuadGrid &quadGrid, const IPrimitive &primitive, NLMISC::IProgressCallback *callback) -{ - // is it a point ? - const CPrimPointEditor *point = dynamic_cast (&primitive); - if (point) - { - // Insert it - CQuadGridElement element; - - // * Is it collisionnable ? - - // Get the primitive class - string className; - nlverify (primitive.getPropertyByName ("class", className)); - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (className.c_str ()); - if (primClass) - { - // Get the position - element.Position = point->Point; - element.Position.z = 0; - - // Default radius - element.Radius = 0; - - // This class make collision during generation ? - if (primClass->Collision) - { - // Get the radius - string radius; - if (point->getPropertyByName ("radius", radius)) - { - // Get the value - sscanf (radius.c_str (), "%f", &element.Radius); - } - - // Insert BB - NLMISC::CVector bboxmin = element.Position - CVector (element.Radius, element.Radius, element.Radius); - NLMISC::CVector bboxmax = element.Position + CVector (element.Radius, element.Radius, element.Radius); - - // Insert it - quadGrid.insert (bboxmin, bboxmax, element); - } - } - } - - // Scan children - uint numChildren = primitive.getNumChildren (); - for (uint i=0; iprogress ((float)i/(float)numChildren); - callback->pushCropedValues ((float)i/(float)numChildren, (float)(i+1)/(float)numChildren); - } - - // Insert child - const IPrimitive *child; - nlverify (primitive.getChild (child, i)); - insertPrimitive (quadGrid, *child, callback); - - // Progress bar - if (callback) - callback->popCropedValues (); - } -} - -// *************************************************************************** - -bool CGeneratePrimitive::addPrimitive (std::vector &dest, const NLMISC::CVector &pos, - const char *primClassToGenerate, const NLLIGO::IPrimitive &parent, - const class CFlora &flora, const class CFloraPlant &plant, - NL3D::CQuadGrid &quadGrid, const CLigoConfig &config) -{ - // Generate a scale - float scale = (flora.ScaleMax-flora.ScaleMin)*frand(1.0)+flora.ScaleMin; - - // Test collision - // note : i'm not sure the layer is really usefull here because primitive are always generated on the layer 0 - if (testPosition (pos, plant, flora, scale, 0, quadGrid, config)) - { - // Test finally with the exclude primitive - uint m; - for (m = 0; m < flora.ExcludePrimitives.size(); m++) - { - // Contains in the exclude primitive ? - if (flora.ExcludePrimitives[m]->contains(pos)) - break; - } - - // No collision ? - if (m == flora.ExcludePrimitives.size()) - { - // Create a new primitive - CPrimPointEditor *newPoint = new CPrimPointEditor; - - // Position and angle - newPoint->Point = pos; - newPoint->Angle = (float)Pi * frand (2.0); - - // Add its class - newPoint->addPropertyByName ("class", new CPropertyString (primClassToGenerate)); - - // * Add a name - - // Get its parent name - string parentName; - parent.getPropertyByName ("name", parentName); - - // Get number of brothers - uint numBrother = parent.getNumChildren () + flora.NewPrimitiveCount; - - // Set the name - newPoint->addPropertyByName ("name", new CPropertyString ((parentName+" "+toString (numBrother)).c_str ())); - - // Set the form - newPoint->addPropertyByName ("form", new CPropertyString (plant.Name.c_str ())); - - // Set the radius - newPoint->addPropertyByName ("radius", new CPropertyString ((toString (scale*plant.BoundingRadius).c_str ()))); - - // Set the scale - newPoint->addPropertyByName ("scale", new CPropertyString ((toString (scale).c_str ()))); - - // Set the layer - newPoint->addPropertyByName ("layer", new CPropertyString ("0")); - - // Put on water ? - if (flora.PutOnWater) - { - // Unset the flag to don't snap over the landscape - newPoint->addPropertyByName ("snap", new CPropertyString ("false")); - - // - newPoint->addPropertyByName ("height", new CPropertyString (toString(flora.WaterHeight).c_str())); - - // Align position - if (newPoint->Point.z < flora.WaterHeight) - newPoint->Point.z = flora.WaterHeight; - } - - // Add the primitive - dest.push_back (newPoint); - - // Add it in the grid - insertPrimitive (quadGrid, *newPoint, NULL); - - // Posed - return true; - } - } - - // Not posed - return false; -} - -// *************************************************************************** - -bool CGeneratePrimitive::testPosition (const CVector &pos, const CFloraPlant &plant, const CFlora &flora, float scale, uint layer, - NL3D::CQuadGrid &quadGrid, const CLigoConfig &config) -{ - // Clear the selection - quadGrid.clearSelection (); - - // Selection BB - CVector pos2 = pos; - pos2.z = 0; - CVector bboxmin = pos2 - CVector (plant.BoundingRadius, plant.BoundingRadius, plant.BoundingRadius); - CVector bboxmax = pos2 + CVector (plant.BoundingRadius, plant.BoundingRadius, plant.BoundingRadius); - - // Select - quadGrid.select (bboxmin, bboxmax); - - // Test selection - CQuadGrid::CIterator ite = quadGrid.begin(); - while (ite != quadGrid.end()) - { - // Distance between the 2 primitives - CVector dist = pos - (*ite).Position; - dist.z = 0; - - // Distance max - float distMax = (*ite).Radius + plant.BoundingRadius; - - // Test - if (dist.sqrnorm () < (distMax*distMax)) - return false; - - // Next - ite++; - } - -#ifdef TEST_Z_POSITION - // *** Check the position is good, ie, the collision circle is over the landscape at a small delta Z of the center - - // Approximate the z with patch bounding boxes - sint32 zoneX = (sint32)floor (pos.x/config.CellSize); - sint32 zoneY = (sint32)floor (-pos.y/config.CellSize); - sint32 zoneId = zoneY * 256 + zoneX; - CZone *zone = _Landscape->getZone (zoneId); - - // Zone exist ? - if (zone) - { - // Get the zone bbox - CAABBoxExt zoneBBox = zone->getZoneBB (); - - // The bbox used to select triangles - CAABBox bbox; - bbox.setCenter (CVector (pos.x + SELECTION_EPSILON, pos.y + SELECTION_EPSILON, zoneBBox.getMax ().z + SELECTION_EPSILON)); - bbox.extend (CVector (pos.x - SELECTION_EPSILON, pos.y - SELECTION_EPSILON, zoneBBox.getMin ().z - SELECTION_EPSILON)); - - // *** Extend the box - - // Get some Z around to see if we can put the Flora on the ground - vector base; - base.resize (Z_SAMPLE_COUNT); - uint i; - for (i = 0; i < Z_SAMPLE_COUNT; ++i) - { - // Ref on the new position - CVector &destPos = base[i]; - - destPos = pos; - destPos.x += scale * plant.CollisionRadius * cosf((2.0f*(float)Pi*i)/(float)Z_SAMPLE_COUNT); - destPos.y += scale * plant.CollisionRadius * sinf((2.0f*(float)Pi*i)/(float)Z_SAMPLE_COUNT); - - // Extend the bbox - bbox.extend (CVector (destPos.x - SELECTION_EPSILON, destPos.y - SELECTION_EPSILON, 0)); - bbox.extend (CVector (destPos.x + SELECTION_EPSILON, destPos.y + SELECTION_EPSILON, 0)); - } - - // Min and max - float zMin = bbox.getMin ().z; - float zMax = bbox.getMax ().z; - - // Select some triangles - vector triangles; - _Landscape->buildTrianglesInBBox (bbox, triangles, 0); - - // *** Get the real Z - float centerZ; - if (!getZFromXY (centerZ, pos.x, pos.y, zMin, zMax, layer, config, triangles)) - { - // Primitive placed in a hole - return false; - } - - // Get some Z around to see if we can put the Flora on the ground - for (i = 0; i < Z_SAMPLE_COUNT; ++i) - { - // Ref on the new position - CVector &destPos = base[i]; - - // Z under us ? - if (!getZFromXY (destPos.z, destPos.x, destPos.y, zMin, zMax, layer, config, triangles)) - { - // Primitive placed in a hole - return false; - } - - // todo : pass this threshold in parameter. hard coded delta z here.. - if (fabs(destPos.z - centerZ) > Z_THRESHOLD) - { - return false; - } - } - } -#endif // TEST_Z_POSITION - - // All good - return true; -} - -// *************************************************************************** - -bool triangleIntersect2DGround (const CTriangle &tri, const CVector &pos0) -{ - const CVector &p0= tri.V0; - const CVector &p1= tri.V1; - const CVector &p2= tri.V2; - - // Test if the face enclose the pos in X/Y plane. - // NB: compute and using a BBox to do a rapid test is not a very good idea, since it will - // add an overhead which is NOT negligeable compared to the following test. - float a,b,c; // 2D cartesian coefficients of line in plane X/Y. - // Line p0-p1. - a= -(p1.y-p0.y); - b= (p1.x-p0.x); - c= -(p0.x*a + p0.y*b); - if( (a*pos0.x + b*pos0.y + c) < 0) return false; - // Line p1-p2. - a= -(p2.y-p1.y); - b= (p2.x-p1.x); - c= -(p1.x*a + p1.y*b); - if( (a*pos0.x + b*pos0.y + c) < 0) return false; - // Line p2-p0. - a= -(p0.y-p2.y); - b= (p0.x-p2.x); - c= -(p2.x*a + p2.y*b); - if( (a*pos0.x + b*pos0.y + c) < 0) return false; - - return true; -} - -// *************************************************************************** - -bool CGeneratePrimitive::getZFromXY (float &result, float x, float y, float zMin, float zMax, uint layer, - const NLLIGO::CLigoConfig &config, const vector &triangles) -{ - /* todo COL_USING_VISUAL_COLLISION_MANAGER - // The position - CVector pos = CVector(x, y, 0); - float z, zmin, zmax; - - // Zone BBox - CAABBoxExt bb = pZone->getZoneBB(); - zmin = bb.getMin().z; - zmax = bb.getMax().z; - pos.z = zmin; - z = zmin; - - // Hulud: I'm not sure to understand that code.. - // I don't chage anything because, i need the same result - { - while (z < zmax) - { - // Result normal - CVector normal; - if (_VCE->snapToGround(pos, normal)) - break; - - // Super sampling due to max frequency on radiosity - z += CVisualCollisionEntity::BBoxRadiusZ / 2.0f; - pos.z = z; - } - - if (z >= zmax) - return false; - } - - // Done - result = pos.z; - return true; - */ - - // The position - CVector position (x, y, 0); - - // Ray trace triangles - set selectedHeight; - uint j; - for (j=0; j::iterator ite = selectedHeight.begin (); - while (ite != selectedHeight.end ()) - { - // Good layer ? - if (currentLayer == layer) - break; - - // Next layer - currentLayer++; - ite++; - } - - // Should be found - nlassert (ite != selectedHeight.end ()); - - // Get the final height - result = *ite; - - // Collision found - return true; - } - - // Not found - return false; -} - -// *************************************************************************** - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" + +#include "editor_primitive.h" +#include "generate_primitive.h" +#include "world_editor.h" +#include "world_editor_doc.h" + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; +using namespace NL3D; +using namespace NLGEORGES; + +// *************************************************************************** + +/* + +Implementation notes: +--------------------- + +- Load all the "landscape zones" overlapped by the source zone +- Build a quad tree with all primitives to check overlapping +- List all the plants used the source zone +- Sort them by size (Place first the biggest one) +- For each plants in the sorted list + - Compute a grid position depending the plant size and the plant density + - Jitter it with a random function + - Test if the final position is valid + - Check the primitive doesn't overlappe another primitive (using the quad tree) + - Check the final position is posed over the landscape, not in a hole + - Make some Z samples (Z_SAMPLE_COUNT, hard coded) around the position with the collision radius + - For each check if the delta z is behind a fixed (Z_THRESHOLD, hard coded) threshold +*/ + +// *** Features + +// Enable / disable z position test +#define TEST_Z_POSITION + +// *** todo : pass this as generation parameters + +// Test N time max to place a point +#define GENERATE_PRIMITIVE_TEST_COUNT 4 + +// Small epsilon for triangle selection +#define SELECTION_EPSILON (0.1f) + +// Z sample to do around the position to check Z +#define Z_SAMPLE_COUNT 8 + +// Z threshold used to validate each sample +#define Z_THRESHOLD (0.8f) + +// *************************************************************************** + +CGeneratePrimitive::CGeneratePrimitive () +{ + _Landscape = NULL; + /* todo COL_USING_VISUAL_COLLISION_MANAGER + _VCM = NULL; + _VCE = NULL; */ +} + +// *************************************************************************** + +// Flora plant class, used by the flora class to reference the plants +class CFloraPlant +{ +public: + string Name; + float Density; + float Falloff; + + // Data duplicated from the plant form to avoid a map lookup + float BoundingRadius; + float CollisionRadius; +}; + +// *************************************************************************** + +// Flora class, filled with the flora form +class CFlora +{ +public: + // The plants references + vector Plants; + + // Excludes primitives + vector ExcludePrimitives; + + // Generation parameters + float JitterPos; + float ScaleMin; + float ScaleMax; + bool PutOnWater; + float WaterHeight; + uint32 RandomSeed; + + // *** Precalculation + + // Bounding min + CVector VMin; + + // Bounding max + CVector VMax; + + // *** Variables + uint NewPrimitiveCount; +}; + +// *************************************************************************** + +/* Sort plant + * This struct is used to sort plants by radius + */ +class CSortPlant +{ +public: + // Contructor + CSortPlant (uint floraId, uint plantId, const vector *floraVector) + { + FloraId = floraId; + PlantId = plantId; + FloraVector = floraVector; + } + + // Comparison + bool operator< (const CSortPlant &other) const + { + return (*FloraVector)[FloraId].Plants[PlantId].BoundingRadius < (*FloraVector)[other.FloraId].Plants[other.PlantId].BoundingRadius; + } + + // The flora id + uint FloraId; + + // The plant id + uint PlantId; + + // The flora vector + const vector *FloraVector; +}; + +// *************************************************************************** + +bool CGeneratePrimitive::generate (std::vector< std::vector > &dest, const std::vector &source, + NLMISC::IProgressCallback &callback, const CLigoConfig &config, const char *dataDirectory, + const char *primClassToGenerate) +{ + // Get the doc + CWorldEditorDoc *doc = getDocument (); + + // Erase dest + dest.clear (); + dest.resize (source.size ()); + + // Clear + clear (); + + // Create a landscape + _Landscape = new CLandscape (); + _Landscape->init (); + + // Get the prim class to generate + const CPrimitiveClass *genPrimClass = theApp.Config.getPrimitiveClass (primClassToGenerate); + nlassert (genPrimClass); + + // Visual collision manager + /* todo COL_USING_VISUAL_COLLISION_MANAGER + _VCM = new CVisualCollisionManager; + _VCE = _VCM->createEntity (); + _VCM->setLandscape (_Landscape); + _VCE->setSnapToRenderedTesselation (false); + */ + + // Load the landscape + if (loadLandscape (source, callback, config, dataDirectory)) + { + // Generate vegetation + uint i, j; + + // Load the .Flora file (georges file) and load all associated .plant + vector flora (source.size ()); + + // Create a loader + UFormLoader *loader = UFormLoader::createLoader (); + + // Keep last form alive + CSmartPtr form; + CSmartPtr form2; + + // For each source primitives + for (i=0; igetPropertyByName ("form", floraName)) + { + // Progress bar + callback.DisplayString = "Reading "+(floraName+".flora")+"..."; + callback.progress ((float)i/(float)source.size ()); + callback.pushCropedValues ((float)i/(float)source.size (), (float)(i+1)/(float)source.size ()); + + // Get the path name + string filename = CPath::lookup (floraName+".flora", false, false, false); + if (!filename.empty ()) + { + // Load the form + form = loader->loadForm (filename.c_str ()); + if (form == NULL) + { + // One more error + _FileNotFound.push_back (filename); + } + else + { + // Get the root node + UFormElm &rootNode = form->getRootNode (); + + // Read the Plants field + UFormElm *pElt; + if (rootNode.getNodeByName (&pElt, "Plants") && pElt) + { + uint size; + nlverify (pElt->getArraySize (size)); + for (j=0; jgetArrayNode (&pArrayElt, j) && pArrayElt) + { + // Read the plant values + CFloraPlant plant; + pArrayElt->getValueByName (plant.Name, "File name"); + pArrayElt->getValueByName (plant.Density, "Density"); + pArrayElt->getValueByName (plant.Falloff, "Falloff"); + plant.CollisionRadius = 0.f; + plant.BoundingRadius = 1; + plant.Name = NLMISC::CFile::getFilenameWithoutExtension (plant.Name); + + // Progress bar + callback.DisplayString = "Reading "+plant.Name+"..."; + callback.progress ((float)j/(float)size); + + // Get the path name + string filename = CPath::lookup (plant.Name+".plant", false, false, false); + if (!filename.empty ()) + { + // Read the plant file + form2 = loader->loadForm (filename.c_str()); + if (form2) + { + // Read the plant + float CollisionRadius = 0; + float BoundingRadius = 1; + + // Get root node + UFormElm &rootNode2 = form2->getRootNode (); + + rootNode2.getValueByName (plant.CollisionRadius, "3D.Collision Radius"); + rootNode2.getValueByName (plant.BoundingRadius, "3D.Bounding Radius"); + + // Add it + flora[i].Plants.push_back (plant); + } + else + { + _FileNotFound.push_back (filename); + } + } + else + { + _FileNotFound.push_back (plant.Name); + } + } + } + } + + // Read the flora values + flora[i].NewPrimitiveCount = 0; + rootNode.getValueByName (flora[i].JitterPos, "Jitter_Pos"); + rootNode.getValueByName (flora[i].ScaleMin, "Scale_Min"); + rootNode.getValueByName (flora[i].ScaleMax, "Scale_Max"); + rootNode.getValueByName (flora[i].PutOnWater, "Put_On_Water"); + rootNode.getValueByName (flora[i].WaterHeight, "Water_Height"); + rootNode.getValueByName (flora[i].RandomSeed, "Random_Seed"); + + // For each vertices + uint numVertices = source[i]->getNumVector (); + if (numVertices) + { + // Get the vector position + const CPrimVector *pos = source[i]->getPrimVector (); + + // Get the bounding of the zone + flora[i].VMin = flora[i].VMax = pos[0]; + for (j = 0; j < numVertices; ++j) + { + // Get the vector position + if (flora[i].VMin.x > pos[j].x) + flora[i].VMin.x = pos[j].x; + if (flora[i].VMin.y > pos[j].y) + flora[i].VMin.y = pos[j].y; + if (flora[i].VMin.z > pos[j].z) + flora[i].VMin.z = pos[j].z; + if (flora[i].VMax.x < pos[j].x) + flora[i].VMax.x = pos[j].x; + if (flora[i].VMax.y < pos[j].y) + flora[i].VMax.y = pos[j].y; + if (flora[i].VMax.z < pos[j].z) + flora[i].VMax.z = pos[j].z; + } + } + + // ** Get exclude zone + uint numFloraChildren = source[i]->getNumChildren (); + for (uint k=0; kgetChild (child, k)); + + // Is it a zone ? + const CPrimZoneEditor *zone = dynamic_cast (child); + if (zone) + { + // Is it an explude zone ? + string className; + if (zone->getPropertyByName ("class", className) && (className == "flora_exclude")) + { + // Add it + flora[i].ExcludePrimitives.push_back (zone); + } + } + } + } + } + else + { + _FileNotFound.push_back (floraName+".flora"); + } + + // Progress bar + callback.popCropedValues (); + } + } + + // Error ? + if (!_FileNotFound.empty ()) + { + // Continue ? + char message[2048]; + message[0] = 0; + for (uint i=0; i<_FileNotFound.size (); i++) + { + strcat (message, _FileNotFound[i].c_str ()); + strcat (message, "\n"); + } + + if (!theApp.yesNoMessage ("Can't load some files:\n%s\nContinue ?", message)) + { + return false; + } + } + + // Insert plants + vector sortedPlants; + for (i=0; i quadGrid; + quadGrid.create (256, 10.f); + + // Progress bar + callback.DisplayString = "Build quad grid"; + + // Insert all the primitive found + uint numPrimitive = doc->getNumDatabaseElement (); + for (i=0; igetDatabaseElements (i).RootNode), &callback); + + // Progress bar + callback.popCropedValues (); + } + + // ** Take a srand found in selected primitives + + uint randSeed = 0; + for (i=0; i= 0; sortedPlant--) + { + // Progress bar + callback.progress ((float)(sortedPlants.size ()-sortedPlant-1)/(float)(sortedPlants.size ())); + callback.pushCropedValues ((float)(sortedPlants.size ()-sortedPlant-1)/(float)sortedPlants.size (), (float)(sortedPlants.size ()-sortedPlant)/(float)sortedPlants.size ()); + + // Ref on the flora + CFlora &theFlora = flora[sortedPlants[sortedPlant].FloraId]; + + // Ref on the plant + const CFloraPlant &thePlant = theFlora.Plants[sortedPlants[sortedPlant].PlantId]; + + // Get a valid jitter + float jitter = theFlora.JitterPos; + clamp (jitter, 0.0f, 1.0f); + + // Is it a non empty zone or path ? + const CPrimZoneEditor *zone = dynamic_cast (source[sortedPlants[sortedPlant].FloraId]); + if (zone) + { + // Some vector + if (((const IPrimitive*)zone)->getNumVector ()) + { + // Distance between primitives + float squareLength = (float)sqrt (Pi*thePlant.BoundingRadius*thePlant.BoundingRadius / thePlant.Density); + + // Number of primitive on X and Y axis to try to place + uint32 nNbPlantX = 1+(int)floor ((theFlora.VMax.x-theFlora.VMin.x) / squareLength); + uint32 nNbPlantY = 1+(int)floor ((theFlora.VMax.y-theFlora.VMin.y) / squareLength); + + // Pose plants + uint k, l; + for (l = 0; l < nNbPlantY; ++l) + for (k = 0; k < nNbPlantX; ++k) + { + // Progress bar + callback.progress ((float)(l*nNbPlantX+k)/(float)(nNbPlantY*nNbPlantX)); + + // Try sveral times times + uint m; + for (m = 0; m < GENERATE_PRIMITIVE_TEST_COUNT; ++m) + { + // Generate a position + CVector pos; + pos.x = theFlora.VMin.x + squareLength * k + (frand(2.0f)-1.0f) * jitter * 0.5f * squareLength; + pos.y = theFlora.VMin.y + squareLength * l + (frand(2.0f)-1.0f) * jitter * 0.5f * squareLength; + pos.z = 0.0f; + + // Does the zone contains the position generated ? + if (zone->contains(pos)) + { + // Add the primitive + if (addPrimitive (dest[sortedPlants[sortedPlant].FloraId], pos, primClassToGenerate, *zone, theFlora, thePlant, quadGrid, config)) + { + theFlora.NewPrimitiveCount++; + break; + } + } + } + } + } + } + else + { + // Is it a path ? + const CPrimPathEditor *path = dynamic_cast (source[sortedPlants[sortedPlant].FloraId]); + if (path) + { + // Total length of the broken line + float length = 0.0f; + for (j = 0; j < path->VPoints.size()-1; ++j) + length += (path->VPoints[j]-path->VPoints[j+1]).norm(); + + // Number of primitives on this path + float squareLength = (float)(2*thePlant.BoundingRadius / thePlant.Density); + uint nNbPlant = 1+(int)floor (length / squareLength); + + // Pose plants + uint k; + for (k = 0; k < nNbPlant; ++k) + { + // Progress bar + callback.progress ((float)(k)/(float)(nNbPlant)); + + bool bExists = false; + CVector pos; + + // Try sveral times times + uint m; + for (m = 0; m < GENERATE_PRIMITIVE_TEST_COUNT; ++m) + { + // Calculate the curviline abscisse + float curvAbs = squareLength * k + (frand(2.0f)-1.0f) * jitter * 0.5f * squareLength; + if ((curvAbs>=0) && (curvAbsVPoints.size()-1; ++l) + { + float newSize = (path->VPoints[l]-path->VPoints[l+1]).norm(); + if (curvAbs < (TempLength+newSize)) + { + curvAbs -= TempLength; + break; + } + TempLength += newSize; + } + + // Placed ? + if (l != (path->VPoints.size()-1)) + { + // Calculate the coord + curvAbs = curvAbs / (path->VPoints[l]-path->VPoints[l+1]).norm(); + pos = path->VPoints[l] + (path->VPoints[l+1]-path->VPoints[l])*curvAbs; + pos.z = 0.0f; + + // Add the primitive + if (addPrimitive (dest[sortedPlants[sortedPlant].FloraId], pos, primClassToGenerate, *path, theFlora, thePlant,quadGrid, config)) + { + theFlora.NewPrimitiveCount++; + break; + } + } + } + } + } + } + } + + // Progress bar + callback.popCropedValues (); + } + } + + // Done + return true; + } + + // Failed + return false; +} + +// *************************************************************************** + +bool CGeneratePrimitive::loadLandscape (const std::vector &source, NLMISC::IProgressCallback &callback, + const NLLIGO::CLigoConfig &config, const char *dataDirectory) +{ + // Get the bbox of the primitives + CAABBox bbox; + bool firstPoint = true; + for (uint i=0; igetNumVector (); + if (nbVert) + { + // Get the vectors + const CPrimVector *vectors = source[i]->getPrimVector (); + for (uint j=0; jaddZone (zone); + } + } + } + } + + // Done + return true; +} + +// *************************************************************************** + +void CGeneratePrimitive::clear () +{ + /* todo COL_USING_VISUAL_COLLISION_MANAGER + // Delete the entity + if (_VCE) + { + nlassert (_VCM); + _VCM->deleteEntity; + _VCE = NULL; + } + + // Delete the manager + if (_VCM) + { + delete _VCM; + _VCM = NULL; + } + */ + + // Delete the landscape + if (_Landscape) + { + delete (_Landscape); + _Landscape = NULL; + } + + _FileNotFound.clear (); +} + +// *************************************************************************** + +CGeneratePrimitive::~CGeneratePrimitive () +{ + clear (); +} + +// *************************************************************************** + +void CGeneratePrimitive::insertPrimitive (CQuadGrid &quadGrid, const IPrimitive &primitive, NLMISC::IProgressCallback *callback) +{ + // is it a point ? + const CPrimPointEditor *point = dynamic_cast (&primitive); + if (point) + { + // Insert it + CQuadGridElement element; + + // * Is it collisionnable ? + + // Get the primitive class + string className; + nlverify (primitive.getPropertyByName ("class", className)); + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (className.c_str ()); + if (primClass) + { + // Get the position + element.Position = point->Point; + element.Position.z = 0; + + // Default radius + element.Radius = 0; + + // This class make collision during generation ? + if (primClass->Collision) + { + // Get the radius + string radius; + if (point->getPropertyByName ("radius", radius)) + { + // Get the value + sscanf (radius.c_str (), "%f", &element.Radius); + } + + // Insert BB + NLMISC::CVector bboxmin = element.Position - CVector (element.Radius, element.Radius, element.Radius); + NLMISC::CVector bboxmax = element.Position + CVector (element.Radius, element.Radius, element.Radius); + + // Insert it + quadGrid.insert (bboxmin, bboxmax, element); + } + } + } + + // Scan children + uint numChildren = primitive.getNumChildren (); + for (uint i=0; iprogress ((float)i/(float)numChildren); + callback->pushCropedValues ((float)i/(float)numChildren, (float)(i+1)/(float)numChildren); + } + + // Insert child + const IPrimitive *child; + nlverify (primitive.getChild (child, i)); + insertPrimitive (quadGrid, *child, callback); + + // Progress bar + if (callback) + callback->popCropedValues (); + } +} + +// *************************************************************************** + +bool CGeneratePrimitive::addPrimitive (std::vector &dest, const NLMISC::CVector &pos, + const char *primClassToGenerate, const NLLIGO::IPrimitive &parent, + const class CFlora &flora, const class CFloraPlant &plant, + NL3D::CQuadGrid &quadGrid, const CLigoConfig &config) +{ + // Generate a scale + float scale = (flora.ScaleMax-flora.ScaleMin)*frand(1.0)+flora.ScaleMin; + + // Test collision + // note : i'm not sure the layer is really usefull here because primitive are always generated on the layer 0 + if (testPosition (pos, plant, flora, scale, 0, quadGrid, config)) + { + // Test finally with the exclude primitive + uint m; + for (m = 0; m < flora.ExcludePrimitives.size(); m++) + { + // Contains in the exclude primitive ? + if (flora.ExcludePrimitives[m]->contains(pos)) + break; + } + + // No collision ? + if (m == flora.ExcludePrimitives.size()) + { + // Create a new primitive + CPrimPointEditor *newPoint = new CPrimPointEditor; + + // Position and angle + newPoint->Point = pos; + newPoint->Angle = (float)Pi * frand (2.0); + + // Add its class + newPoint->addPropertyByName ("class", new CPropertyString (primClassToGenerate)); + + // * Add a name + + // Get its parent name + string parentName; + parent.getPropertyByName ("name", parentName); + + // Get number of brothers + uint numBrother = parent.getNumChildren () + flora.NewPrimitiveCount; + + // Set the name + newPoint->addPropertyByName ("name", new CPropertyString ((parentName+" "+toString (numBrother)).c_str ())); + + // Set the form + newPoint->addPropertyByName ("form", new CPropertyString (plant.Name.c_str ())); + + // Set the radius + newPoint->addPropertyByName ("radius", new CPropertyString ((toString (scale*plant.BoundingRadius).c_str ()))); + + // Set the scale + newPoint->addPropertyByName ("scale", new CPropertyString ((toString (scale).c_str ()))); + + // Set the layer + newPoint->addPropertyByName ("layer", new CPropertyString ("0")); + + // Put on water ? + if (flora.PutOnWater) + { + // Unset the flag to don't snap over the landscape + newPoint->addPropertyByName ("snap", new CPropertyString ("false")); + + // + newPoint->addPropertyByName ("height", new CPropertyString (toString(flora.WaterHeight).c_str())); + + // Align position + if (newPoint->Point.z < flora.WaterHeight) + newPoint->Point.z = flora.WaterHeight; + } + + // Add the primitive + dest.push_back (newPoint); + + // Add it in the grid + insertPrimitive (quadGrid, *newPoint, NULL); + + // Posed + return true; + } + } + + // Not posed + return false; +} + +// *************************************************************************** + +bool CGeneratePrimitive::testPosition (const CVector &pos, const CFloraPlant &plant, const CFlora &flora, float scale, uint layer, + NL3D::CQuadGrid &quadGrid, const CLigoConfig &config) +{ + // Clear the selection + quadGrid.clearSelection (); + + // Selection BB + CVector pos2 = pos; + pos2.z = 0; + CVector bboxmin = pos2 - CVector (plant.BoundingRadius, plant.BoundingRadius, plant.BoundingRadius); + CVector bboxmax = pos2 + CVector (plant.BoundingRadius, plant.BoundingRadius, plant.BoundingRadius); + + // Select + quadGrid.select (bboxmin, bboxmax); + + // Test selection + CQuadGrid::CIterator ite = quadGrid.begin(); + while (ite != quadGrid.end()) + { + // Distance between the 2 primitives + CVector dist = pos - (*ite).Position; + dist.z = 0; + + // Distance max + float distMax = (*ite).Radius + plant.BoundingRadius; + + // Test + if (dist.sqrnorm () < (distMax*distMax)) + return false; + + // Next + ite++; + } + +#ifdef TEST_Z_POSITION + // *** Check the position is good, ie, the collision circle is over the landscape at a small delta Z of the center + + // Approximate the z with patch bounding boxes + sint32 zoneX = (sint32)floor (pos.x/config.CellSize); + sint32 zoneY = (sint32)floor (-pos.y/config.CellSize); + sint32 zoneId = zoneY * 256 + zoneX; + CZone *zone = _Landscape->getZone (zoneId); + + // Zone exist ? + if (zone) + { + // Get the zone bbox + CAABBoxExt zoneBBox = zone->getZoneBB (); + + // The bbox used to select triangles + CAABBox bbox; + bbox.setCenter (CVector (pos.x + SELECTION_EPSILON, pos.y + SELECTION_EPSILON, zoneBBox.getMax ().z + SELECTION_EPSILON)); + bbox.extend (CVector (pos.x - SELECTION_EPSILON, pos.y - SELECTION_EPSILON, zoneBBox.getMin ().z - SELECTION_EPSILON)); + + // *** Extend the box + + // Get some Z around to see if we can put the Flora on the ground + vector base; + base.resize (Z_SAMPLE_COUNT); + uint i; + for (i = 0; i < Z_SAMPLE_COUNT; ++i) + { + // Ref on the new position + CVector &destPos = base[i]; + + destPos = pos; + destPos.x += scale * plant.CollisionRadius * cosf((2.0f*(float)Pi*i)/(float)Z_SAMPLE_COUNT); + destPos.y += scale * plant.CollisionRadius * sinf((2.0f*(float)Pi*i)/(float)Z_SAMPLE_COUNT); + + // Extend the bbox + bbox.extend (CVector (destPos.x - SELECTION_EPSILON, destPos.y - SELECTION_EPSILON, 0)); + bbox.extend (CVector (destPos.x + SELECTION_EPSILON, destPos.y + SELECTION_EPSILON, 0)); + } + + // Min and max + float zMin = bbox.getMin ().z; + float zMax = bbox.getMax ().z; + + // Select some triangles + vector triangles; + _Landscape->buildTrianglesInBBox (bbox, triangles, 0); + + // *** Get the real Z + float centerZ; + if (!getZFromXY (centerZ, pos.x, pos.y, zMin, zMax, layer, config, triangles)) + { + // Primitive placed in a hole + return false; + } + + // Get some Z around to see if we can put the Flora on the ground + for (i = 0; i < Z_SAMPLE_COUNT; ++i) + { + // Ref on the new position + CVector &destPos = base[i]; + + // Z under us ? + if (!getZFromXY (destPos.z, destPos.x, destPos.y, zMin, zMax, layer, config, triangles)) + { + // Primitive placed in a hole + return false; + } + + // todo : pass this threshold in parameter. hard coded delta z here.. + if (fabs(destPos.z - centerZ) > Z_THRESHOLD) + { + return false; + } + } + } +#endif // TEST_Z_POSITION + + // All good + return true; +} + +// *************************************************************************** + +bool triangleIntersect2DGround (const CTriangle &tri, const CVector &pos0) +{ + const CVector &p0= tri.V0; + const CVector &p1= tri.V1; + const CVector &p2= tri.V2; + + // Test if the face enclose the pos in X/Y plane. + // NB: compute and using a BBox to do a rapid test is not a very good idea, since it will + // add an overhead which is NOT negligeable compared to the following test. + float a,b,c; // 2D cartesian coefficients of line in plane X/Y. + // Line p0-p1. + a= -(p1.y-p0.y); + b= (p1.x-p0.x); + c= -(p0.x*a + p0.y*b); + if( (a*pos0.x + b*pos0.y + c) < 0) return false; + // Line p1-p2. + a= -(p2.y-p1.y); + b= (p2.x-p1.x); + c= -(p1.x*a + p1.y*b); + if( (a*pos0.x + b*pos0.y + c) < 0) return false; + // Line p2-p0. + a= -(p0.y-p2.y); + b= (p0.x-p2.x); + c= -(p2.x*a + p2.y*b); + if( (a*pos0.x + b*pos0.y + c) < 0) return false; + + return true; +} + +// *************************************************************************** + +bool CGeneratePrimitive::getZFromXY (float &result, float x, float y, float zMin, float zMax, uint layer, + const NLLIGO::CLigoConfig &config, const vector &triangles) +{ + /* todo COL_USING_VISUAL_COLLISION_MANAGER + // The position + CVector pos = CVector(x, y, 0); + float z, zmin, zmax; + + // Zone BBox + CAABBoxExt bb = pZone->getZoneBB(); + zmin = bb.getMin().z; + zmax = bb.getMax().z; + pos.z = zmin; + z = zmin; + + // Hulud: I'm not sure to understand that code.. + // I don't chage anything because, i need the same result + { + while (z < zmax) + { + // Result normal + CVector normal; + if (_VCE->snapToGround(pos, normal)) + break; + + // Super sampling due to max frequency on radiosity + z += CVisualCollisionEntity::BBoxRadiusZ / 2.0f; + pos.z = z; + } + + if (z >= zmax) + return false; + } + + // Done + result = pos.z; + return true; + */ + + // The position + CVector position (x, y, 0); + + // Ray trace triangles + set selectedHeight; + uint j; + for (j=0; j::iterator ite = selectedHeight.begin (); + while (ite != selectedHeight.end ()) + { + // Good layer ? + if (currentLayer == layer) + break; + + // Next layer + currentLayer++; + ite++; + } + + // Should be found + nlassert (ite != selectedHeight.end ()); + + // Get the final height + result = *ite; + + // Collision found + return true; + } + + // Not found + return false; +} + +// *************************************************************************** + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_primitive.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_primitive.h index 90d8a74b4..fc7cf655c 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_primitive.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/generate_primitive.h @@ -1,109 +1,109 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_GENERATE_PRIMITIVE_H -#define NL_GENERATE_PRIMITIVE_H - - -// Element to insert in the quad grid -class CQuadGridElement -{ -public: - NLMISC::CVector Position; - float Radius; -}; - -// *************************************************************************** - -/** - * Generate primitives - */ -class CGeneratePrimitive -{ -public: - - // Constructor - CGeneratePrimitive (); - - // Destructor - ~CGeneratePrimitive (); - - /** - * Generate - * - * Select the root primitive - * Load the landscape - */ - bool generate (std::vector< std::vector > &dest, const std::vector &source, - NLMISC::IProgressCallback &callback, const NLLIGO::CLigoConfig &config, const char *dataDirectory, - const char *primClassToGenerate); - -private: - - /** - * Clear all the container - */ - void clear (); - - /** - * Load landscape - */ - bool loadLandscape (const std::vector &source, NLMISC::IProgressCallback &callback, - const NLLIGO::CLigoConfig &config, const char *dataDirectory); - - /** - * Insert primitive in a quad grid - */ - static void insertPrimitive (NL3D::CQuadGrid &quadGrid, const NLLIGO::IPrimitive &primitive, NLMISC::IProgressCallback *callback); - - /** - * Add a primitive in a primitive pointer vector - */ - bool addPrimitive (std::vector &dest, const NLMISC::CVector &pos, - const char *primClassToGenerate, const NLLIGO::IPrimitive &parent, - const class CFlora &flora, const class CFloraPlant &plant, - NL3D::CQuadGrid &quadGrid, const NLLIGO::CLigoConfig &config); - - /** - * Test a primitive position with others primitives and landscape - */ - bool testPosition (const NLMISC::CVector &pos, const class CFloraPlant &thePlant, const class CFlora &flora, float scale, uint layer, - NL3D::CQuadGrid &quadGrid, const NLLIGO::CLigoConfig &config); - - /** - * Get z on the landscape - */ - bool getZFromXY (float &result, float x, float y, float zMin, float zMax, uint layer, - const NLLIGO::CLigoConfig &config, const std::vector &triangles); - - /// *** Data - - // The landscape - NL3D::CLandscape *_Landscape; - - // Visual collision manager - /* todo COL_USING_VISUAL_COLLISION_MANAGER - NL3D::CVisualCollisionManager *_VCM; - NL3D::CVisualCollisionEntity *_VCE; */ - - // *** Errors report - std::vector _FileNotFound; -}; - - -#endif // NL_GENERATE_PRIMITIVE_H - -/* End of generate_primitive.h */ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef NL_GENERATE_PRIMITIVE_H +#define NL_GENERATE_PRIMITIVE_H + + +// Element to insert in the quad grid +class CQuadGridElement +{ +public: + NLMISC::CVector Position; + float Radius; +}; + +// *************************************************************************** + +/** + * Generate primitives + */ +class CGeneratePrimitive +{ +public: + + // Constructor + CGeneratePrimitive (); + + // Destructor + ~CGeneratePrimitive (); + + /** + * Generate + * + * Select the root primitive + * Load the landscape + */ + bool generate (std::vector< std::vector > &dest, const std::vector &source, + NLMISC::IProgressCallback &callback, const NLLIGO::CLigoConfig &config, const char *dataDirectory, + const char *primClassToGenerate); + +private: + + /** + * Clear all the container + */ + void clear (); + + /** + * Load landscape + */ + bool loadLandscape (const std::vector &source, NLMISC::IProgressCallback &callback, + const NLLIGO::CLigoConfig &config, const char *dataDirectory); + + /** + * Insert primitive in a quad grid + */ + static void insertPrimitive (NL3D::CQuadGrid &quadGrid, const NLLIGO::IPrimitive &primitive, NLMISC::IProgressCallback *callback); + + /** + * Add a primitive in a primitive pointer vector + */ + bool addPrimitive (std::vector &dest, const NLMISC::CVector &pos, + const char *primClassToGenerate, const NLLIGO::IPrimitive &parent, + const class CFlora &flora, const class CFloraPlant &plant, + NL3D::CQuadGrid &quadGrid, const NLLIGO::CLigoConfig &config); + + /** + * Test a primitive position with others primitives and landscape + */ + bool testPosition (const NLMISC::CVector &pos, const class CFloraPlant &thePlant, const class CFlora &flora, float scale, uint layer, + NL3D::CQuadGrid &quadGrid, const NLLIGO::CLigoConfig &config); + + /** + * Get z on the landscape + */ + bool getZFromXY (float &result, float x, float y, float zMin, float zMax, uint layer, + const NLLIGO::CLigoConfig &config, const std::vector &triangles); + + /// *** Data + + // The landscape + NL3D::CLandscape *_Landscape; + + // Visual collision manager + /* todo COL_USING_VISUAL_COLLISION_MANAGER + NL3D::CVisualCollisionManager *_VCM; + NL3D::CVisualCollisionEntity *_VCE; */ + + // *** Errors report + std::vector _FileNotFound; +}; + + +#endif // NL_GENERATE_PRIMITIVE_H + +/* End of generate_primitive.h */ diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/goto_dialog.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/goto_dialog.cpp index b51151f0a..388e1f489 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/goto_dialog.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/goto_dialog.cpp @@ -1,84 +1,84 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// GotoDialog.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "goto_dialog.h" -#include "display.h" - -using namespace NLMISC; - -///////////////////////////////////////////////////////////////////////////// -// CGotoDialog dialog - - -CGotoDialog::CGotoDialog(CWnd* pParent /*=NULL*/) - : CDialog(CGotoDialog::IDD, pParent) -{ - //{{AFX_DATA_INIT(CGotoDialog) - m_gotoX = 0.0f; - m_gotoY = 0.0f; - m_ZoomAtPosition = FALSE; - //}}AFX_DATA_INIT -} - - -void CGotoDialog::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CGotoDialog) - DDX_Control(pDX, IDC_GOTO_POS_X, m_posXCtrl); - DDX_Text(pDX, IDC_GOTO_POS_X, m_gotoX); - DDX_Text(pDX, IDC_GOTO_POS_Y, m_gotoY); - DDX_Check(pDX, IDC_CHECK_POS_ZOMM, m_ZoomAtPosition); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CGotoDialog, CDialog) - //{{AFX_MSG_MAP(CGotoDialog) - ON_WM_SHOWWINDOW() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CGotoDialog message handlers - -void CGotoDialog::OnOK() -{ - // center the 3D view on the coord - - UpdateData(); - CVector center(m_gotoX, m_gotoY, 0.0f); - - getDisplay()->setDisplayCenter(center, m_ZoomAtPosition == TRUE); - - CDialog::OnOK(); -} - -void CGotoDialog::OnShowWindow(BOOL bShow, UINT nStatus) -{ - CDialog::OnShowWindow(bShow, nStatus); - - if (bShow) - { - m_posXCtrl.SetFocus(); - m_posXCtrl.SetSel(0, -1); - } -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// GotoDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "goto_dialog.h" +#include "display.h" + +using namespace NLMISC; + +///////////////////////////////////////////////////////////////////////////// +// CGotoDialog dialog + + +CGotoDialog::CGotoDialog(CWnd* pParent /*=NULL*/) + : CDialog(CGotoDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CGotoDialog) + m_gotoX = 0.0f; + m_gotoY = 0.0f; + m_ZoomAtPosition = FALSE; + //}}AFX_DATA_INIT +} + + +void CGotoDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CGotoDialog) + DDX_Control(pDX, IDC_GOTO_POS_X, m_posXCtrl); + DDX_Text(pDX, IDC_GOTO_POS_X, m_gotoX); + DDX_Text(pDX, IDC_GOTO_POS_Y, m_gotoY); + DDX_Check(pDX, IDC_CHECK_POS_ZOMM, m_ZoomAtPosition); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CGotoDialog, CDialog) + //{{AFX_MSG_MAP(CGotoDialog) + ON_WM_SHOWWINDOW() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CGotoDialog message handlers + +void CGotoDialog::OnOK() +{ + // center the 3D view on the coord + + UpdateData(); + CVector center(m_gotoX, m_gotoY, 0.0f); + + getDisplay()->setDisplayCenter(center, m_ZoomAtPosition == TRUE); + + CDialog::OnOK(); +} + +void CGotoDialog::OnShowWindow(BOOL bShow, UINT nStatus) +{ + CDialog::OnShowWindow(bShow, nStatus); + + if (bShow) + { + m_posXCtrl.SetFocus(); + m_posXCtrl.SetSel(0, -1); + } +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/goto_dialog.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/goto_dialog.h index 09238246b..5a40ce6c4 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/goto_dialog.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/goto_dialog.h @@ -1,66 +1,66 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_GOTODIALOG_H__7D4B49C5_093A_42A0_B9F9_D072D1109A57__INCLUDED_) -#define AFX_GOTODIALOG_H__7D4B49C5_093A_42A0_B9F9_D072D1109A57__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// goto_dialog.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CGotoDialog dialog - -class CGotoDialog : public CDialog -{ -// Construction -public: - CGotoDialog(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CGotoDialog) - enum { IDD = IDD_GOTO_POS }; - CEdit m_posXCtrl; - float m_gotoX; - float m_gotoY; - BOOL m_ZoomAtPosition; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CGotoDialog) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CGotoDialog) - virtual void OnOK(); - afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_GOTODIALOG_H__7D4B49C5_093A_42A0_B9F9_D072D1109A57__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_GOTODIALOG_H__7D4B49C5_093A_42A0_B9F9_D072D1109A57__INCLUDED_) +#define AFX_GOTODIALOG_H__7D4B49C5_093A_42A0_B9F9_D072D1109A57__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// goto_dialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CGotoDialog dialog + +class CGotoDialog : public CDialog +{ +// Construction +public: + CGotoDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CGotoDialog) + enum { IDD = IDD_GOTO_POS }; + CEdit m_posXCtrl; + float m_gotoX; + float m_gotoY; + BOOL m_ZoomAtPosition; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CGotoDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CGotoDialog) + virtual void OnOK(); + afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_GOTODIALOG_H__7D4B49C5_093A_42A0_B9F9_D072D1109A57__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/imagelist_ex.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/imagelist_ex.cpp index bc4b1518f..513abe109 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/imagelist_ex.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/imagelist_ex.cpp @@ -1,142 +1,142 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" -#include "nel/misc/types_nl.h" -#include "nel/misc/common.h" -#include "resource.h" -#include "imagelist_ex.h" - -#include "set" - -using namespace std; -using namespace NLMISC; - -#pragma warning (disable : 4786) - -BOOL CALLBACK EnumResLangProc(HINSTANCE hModule, LPCTSTR lpszType, LPCTSTR lpszName, WORD wIDLanguage, - LONG lParam) -{ - set *iconNames = (set*)lParam; - - HRSRC hResInfo = FindResourceEx(hModule, lpszType, lpszName, wIDLanguage); - - iconNames->insert (hResInfo); - - return FALSE; -} - -BOOL CALLBACK EnumResNameProc (HINSTANCE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam) -{ - - EnumResourceLanguages (hModule, lpszType, lpszName, EnumResLangProc, lParam); - - return TRUE; -} - -void CImageListEx::addResourceIcon (HINSTANCE hinst, int resource) -{ - // Image index - int index = ImageList.GetImageCount (); - - // Resize the list - ImageList.SetImageCount (index+1); - - // Get the size - IMAGEINFO imageInfo; - if (ImageList.GetImageInfo( index, &imageInfo)) - { - // Size - int width = imageInfo.rcImage.right - imageInfo.rcImage.left; - int height = imageInfo.rcImage.bottom - imageInfo.rcImage.top; - - // Load the icon - HICON handle = (HICON) LoadImage (hinst, MAKEINTRESOURCE(resource), IMAGE_ICON, width, height, LR_COLOR); - if (handle) - { - // Copy the icon - index = ImageList.Replace( index, handle); - - // Add in the map - _IconMapInt.insert (std::map::value_type (resource, index)); - - // Release the icon - DestroyIcon (handle); - } - } -} - -void CImageListEx::addResourceIcon (const char *filename) -{ - // Image index - int index = ImageList.GetImageCount (); - - // Resize the list - ImageList.SetImageCount (index+1); - - // Get the size - IMAGEINFO imageInfo; - if (ImageList.GetImageInfo( index, &imageInfo)) - { - // Size - int width = imageInfo.rcImage.right - imageInfo.rcImage.left; - int height = imageInfo.rcImage.bottom - imageInfo.rcImage.top; - - // Load the icon - HICON handle = (HICON) LoadImage (NULL, filename, IMAGE_ICON, width, height, LR_COLOR|LR_LOADFROMFILE); - if (handle) - { - // Copy the icon - index = ImageList.Replace( index, handle); - - // Add in the map - char name[MAX_PATH]; - _splitpath (filename, NULL, NULL, name, NULL); - string llwr = strlwr (string (name)); - _IconMapString.insert (std::map::value_type (llwr, index)); - - // Release the icon - DestroyIcon (handle); - } - } -} - -void CImageListEx::create (int width, int height) -{ - ImageList.Create (16, 16, TRUE, 6, 10); - ImageList.SetBkColor( CLR_NONE ); -} - -int CImageListEx::getImage (int resource) const -{ - std::map::const_iterator ite = _IconMapInt.find (resource); - if (ite == _IconMapInt.end()) - return -1; - else - return ite->second; -} - -int CImageListEx::getImage (const char *filename) const -{ - char name[MAX_PATH]; - _splitpath (filename, NULL, NULL, name, NULL); - string llwr = strlwr (string (name)); - std::map::const_iterator ite = _IconMapString.find (llwr); - if (ite == _IconMapString.end()) - return -1; - else - return ite->second; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" +#include "nel/misc/types_nl.h" +#include "nel/misc/common.h" +#include "resource.h" +#include "imagelist_ex.h" + +#include "set" + +using namespace std; +using namespace NLMISC; + +#pragma warning (disable : 4786) + +BOOL CALLBACK EnumResLangProc(HINSTANCE hModule, LPCTSTR lpszType, LPCTSTR lpszName, WORD wIDLanguage, + LONG lParam) +{ + set *iconNames = (set*)lParam; + + HRSRC hResInfo = FindResourceEx(hModule, lpszType, lpszName, wIDLanguage); + + iconNames->insert (hResInfo); + + return FALSE; +} + +BOOL CALLBACK EnumResNameProc (HINSTANCE hModule, LPCTSTR lpszType, LPTSTR lpszName, LONG lParam) +{ + + EnumResourceLanguages (hModule, lpszType, lpszName, EnumResLangProc, lParam); + + return TRUE; +} + +void CImageListEx::addResourceIcon (HINSTANCE hinst, int resource) +{ + // Image index + int index = ImageList.GetImageCount (); + + // Resize the list + ImageList.SetImageCount (index+1); + + // Get the size + IMAGEINFO imageInfo; + if (ImageList.GetImageInfo( index, &imageInfo)) + { + // Size + int width = imageInfo.rcImage.right - imageInfo.rcImage.left; + int height = imageInfo.rcImage.bottom - imageInfo.rcImage.top; + + // Load the icon + HICON handle = (HICON) LoadImage (hinst, MAKEINTRESOURCE(resource), IMAGE_ICON, width, height, LR_COLOR); + if (handle) + { + // Copy the icon + index = ImageList.Replace( index, handle); + + // Add in the map + _IconMapInt.insert (std::map::value_type (resource, index)); + + // Release the icon + DestroyIcon (handle); + } + } +} + +void CImageListEx::addResourceIcon (const char *filename) +{ + // Image index + int index = ImageList.GetImageCount (); + + // Resize the list + ImageList.SetImageCount (index+1); + + // Get the size + IMAGEINFO imageInfo; + if (ImageList.GetImageInfo( index, &imageInfo)) + { + // Size + int width = imageInfo.rcImage.right - imageInfo.rcImage.left; + int height = imageInfo.rcImage.bottom - imageInfo.rcImage.top; + + // Load the icon + HICON handle = (HICON) LoadImage (NULL, filename, IMAGE_ICON, width, height, LR_COLOR|LR_LOADFROMFILE); + if (handle) + { + // Copy the icon + index = ImageList.Replace( index, handle); + + // Add in the map + char name[MAX_PATH]; + _splitpath (filename, NULL, NULL, name, NULL); + string llwr = strlwr (string (name)); + _IconMapString.insert (std::map::value_type (llwr, index)); + + // Release the icon + DestroyIcon (handle); + } + } +} + +void CImageListEx::create (int width, int height) +{ + ImageList.Create (16, 16, TRUE, 6, 10); + ImageList.SetBkColor( CLR_NONE ); +} + +int CImageListEx::getImage (int resource) const +{ + std::map::const_iterator ite = _IconMapInt.find (resource); + if (ite == _IconMapInt.end()) + return -1; + else + return ite->second; +} + +int CImageListEx::getImage (const char *filename) const +{ + char name[MAX_PATH]; + _splitpath (filename, NULL, NULL, name, NULL); + string llwr = strlwr (string (name)); + std::map::const_iterator ite = _IconMapString.find (llwr); + if (ite == _IconMapString.end()) + return -1; + else + return ite->second; +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/imagelist_ex.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/imagelist_ex.h index de5c8ef4b..77edc0a69 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/imagelist_ex.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/imagelist_ex.h @@ -1,52 +1,52 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef IMAGELIST_H_INCLUDED -#define IMAGELIST_H_INCLUDED - -// Super Imagelist class -class CImageListEx -{ -public: - - // Interface - - // Create the image list - void create (int width, int height); - - // Add resource icon - void addResourceIcon (HINSTANCE hinst, int resource); - - // Add resource icon - void addResourceIcon (const char *filename); - - // Get an icon resource image by icon name - int getImage (int resource) const; - - // Get an icon resource image by icon name - int getImage (const char *name) const; - -public: - // The image list - CImageList ImageList; - -private: - // The second icon map - std::map _IconMapInt; - std::map _IconMapString; -}; - -#endif // IMAGELIST_H_INCLUDED +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef IMAGELIST_H_INCLUDED +#define IMAGELIST_H_INCLUDED + +// Super Imagelist class +class CImageListEx +{ +public: + + // Interface + + // Create the image list + void create (int width, int height); + + // Add resource icon + void addResourceIcon (HINSTANCE hinst, int resource); + + // Add resource icon + void addResourceIcon (const char *filename); + + // Get an icon resource image by icon name + int getImage (int resource) const; + + // Get an icon resource image by icon name + int getImage (const char *name) const; + +public: + // The image list + CImageList ImageList; + +private: + // The second icon map + std::map _IconMapInt; + std::map _IconMapString; +}; + +#endif // IMAGELIST_H_INCLUDED diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/main_frm.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/main_frm.cpp index 5971c648f..df79db226 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/main_frm.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/main_frm.cpp @@ -1,4386 +1,4386 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// main_frm.cpp : implementation of the CMainFrame class -// - -#include "stdafx.h" - -#include "action.h" -#include "world_editor.h" -#include "world_editor_doc.h" -#include "display.h" -#include "primitive_view.h" -#include "tools_logic.h" -#include "tools_zone.h" -#include "main_frm.h" -#include "resource.h" -#include "generate_dlg.h" -#include "type_manager_dlg.h" -#include "move_dlg.h" -#include "name_dlg.h" -#include "custom_snapshot.h" -#include "export_dlg.h" -// #include "export_cb_dlg.h" -#include "project_settings.h" -#include "dialog_properties.h" -#include "generate_primitive.h" -#include "editor_primitive.h" -#include "select_by_location.h" -#include "find_primitive_dlg.h" -#include "primitive_configuration_dlg.h" -#include "pacs.h" -#include "editor_primitive.h" -#include "file_dialog_ex.h" -#include "nel/misc/mem_stream.h" - -#include - -using namespace NLLIGO; -using namespace std; -using namespace NLMISC; -using namespace NL3D; - -extern bool DontUse3D; - -#define TIMER_UPDATE_FILES 666 -#define TIMER_PLUGINS 667 -#define LOCATE_BORDER 50 - -uint32 getUniqueId (); - - -// *************************************************************************** -// CMainFrame - -IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) - -BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) - //{{AFX_MSG_MAP(CMainFrame) - ON_WM_CREATE() - ON_WM_CLOSE() - ON_WM_SIZE() - ON_COMMAND(ID_APP_EXIT, onMenuFileExit) - ON_COMMAND(ID_EDIT_LOGIC, onMenuModeLogic) - ON_COMMAND(ID_EDIT_ZONE, onMenuModeZone) - ON_COMMAND(ID_EDIT_TRANSITION, onMenuModeTransition) - ON_COMMAND(ID_EDIT_UNDO, onMenuModeUndo) - ON_COMMAND(ID_EDIT_REDO, onMenuModeRedo) - ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, onUpdateModeUndo) - ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, onUpdateModeRedo) - ON_COMMAND(ID_PROJECT_NEWLANDSCAPE, onProjectNewlandscape) - ON_COMMAND(ID_PROJECT_ADDLANDSCAPE, onProjectAddlandscape) - ON_COMMAND(ID_PROJECT_SETTINGS, onProjectSettings) - ON_UPDATE_COMMAND_UI(ID_EDIT_TRANSITION, OnUpdateEditTransition) - ON_UPDATE_COMMAND_UI(ID_EDIT_ZONE, OnUpdateEditZone) - ON_UPDATE_COMMAND_UI(ID_EDIT_LOGIC, OnUpdateEditLogic) - ON_COMMAND(ID_PROJECT_IMPORT_PRIM, OnProjectImportPrim) - ON_COMMAND(ID_PROJECT_ADDPRIMITIVE, OnProjectAddPrimitive) - ON_COMMAND(ID_PROJECT_CLEARALLPRIMITIVE, OnProjectClearallprimitive) - ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll) - ON_COMMAND(ID_EDIT_LOCK, OnEditLock) - ON_COMMAND(ID_EDIT_SELECT, OnEditSelect) - ON_COMMAND(ID_EDIT_DETAILS, OnEditDetails) - ON_COMMAND(ID_VIEW_LANDSCAPE, OnViewLandscape) - ON_COMMAND(ID_VIEW_LAYERS, OnViewLayers) - ON_COMMAND(ID_VIEW_GRID, OnViewGrid) - ON_COMMAND(ID_VIEW_POINTS, OnViewPoints) - ON_COMMAND(ID_VIEW_PACS, OnViewPACS) - ON_COMMAND(ID_VIEW_PRIMITIVES, OnViewPrimitives) - ON_COMMAND(ID_EDIT_TRANSLATE, OnEditTranslate) - ON_COMMAND(ID_EDIT_ROTATE, OnEditRotate) - ON_COMMAND(ID_EDIT_TURN, OnEditTurn) - ON_COMMAND(ID_EDIT_RADIUS, OnEditRadius) - ON_COMMAND(ID_EDIT_SCALE, OnEditScale) - ON_COMMAND(ID_EDIT_ADD_POINT, OnEditAddPoint) - ON_COMMAND(ID_EDIT_DELETE, OnEditDelete) - ON_COMMAND(ID_PROJECT_NEWPRIMITIVE, OnProjectNewPrimitive) - ON_COMMAND(ID_EDIT_PROPERTIES, OnEditProperties) - ON_UPDATE_COMMAND_UI(ID_EDIT_ADD_POINT, OnUpdateEditAddPoint) - ON_UPDATE_COMMAND_UI(ID_EDIT_LOCK, OnUpdateEditLock) - ON_UPDATE_COMMAND_UI(ID_EDIT_PROPERTIES, OnUpdateEditProperties) - ON_UPDATE_COMMAND_UI(ID_EDIT_ROTATE, OnUpdateEditRotate) - ON_UPDATE_COMMAND_UI(ID_EDIT_SCALE, OnUpdateEditScale) - ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateEditSelectAll) - ON_UPDATE_COMMAND_UI(ID_EDIT_TRANSLATE, OnUpdateEditTranslate) - ON_UPDATE_COMMAND_UI(ID_EDIT_TURN, OnUpdateEditTurn) - ON_UPDATE_COMMAND_UI(ID_EDIT_RADIUS, OnUpdateEditRadius) - ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT, OnUpdateEditSelect) - ON_UPDATE_COMMAND_UI(ID_EDIT_DETAILS, OnUpdateEditDetails) - ON_UPDATE_COMMAND_UI(ID_VIEW_LANDSCAPE, OnUpdateViewLandscape) - ON_COMMAND(ID_EDIT_COPY, OnEditCopy) - ON_COMMAND(ID_EDIT_CUT, OnEditCut) - ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy) - ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut) - ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) - ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste) - ON_UPDATE_COMMAND_UI(ID_VIEW_HIDE, OnUpdateViewHide) - ON_COMMAND(ID_VIEW_HIDE, OnViewHide) - ON_COMMAND(ID_VIEW_SHOW, OnViewShow) - ON_UPDATE_COMMAND_UI(ID_VIEW_SHOW, OnUpdateViewShow) - ON_UPDATE_COMMAND_UI(ID_EDIT_EXPAND, OnUpdateEditExpand) - ON_UPDATE_COMMAND_UI(ID_EDIT_COLLAPSE, OnUpdateEditCollapse) - ON_COMMAND(ID_EDIT_SELECT_CHILDREN, OnEditSelectChildren) - ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_CHILDREN, OnUpdateEditSelectChildren) - ON_WM_TIMER() - ON_COMMAND(ID_EDIT_EXPAND, OnEditExpand) - ON_COMMAND(ID_EDIT_COLLAPSE, OnEditCollapse) - ON_COMMAND(ID_HELP_FINDER, OnHelpFinder) - ON_COMMAND(ID_VIEW_LOCATESELECTEDPRIMITIVES, OnViewLocateselectedprimitives) - ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATESELECTEDPRIMITIVES, OnUpdateViewLocateselectedprimitives) - ON_COMMAND(ID_VIEW_LOCATESELECTEDPRIMITIVES_TREE, OnViewLocateselectedprimitivesTree) - ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATESELECTEDPRIMITIVES_TREE, OnUpdateViewLocateselectedprimitivesTree) - ON_COMMAND(ID_EDIT_SELECT_BY_LOCATION, OnEditSelectByLocation) - ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_BY_LOCATION, OnUpdateEditSelectByLocation) - ON_COMMAND(ID_PROJECT_RESETUNIQUEID, OnProjectResetuniqueid) - ON_COMMAND(ID_PROJECT_GENERATENULLID, OnProjectGeneratenullid) - ON_COMMAND(ID_PROJECT_CORRECT_ID, OnProjectForceiduniqueness) - ON_COMMAND(ID_FIND, OnEditFind) - ON_COMMAND(ID_GOTO, OnEditGoto) - ON_UPDATE_COMMAND_UI(ID_FIND, OnUpdateFind) - ON_COMMAND(ID_VIEW_COLLISIONS, OnViewCollisions) - ON_COMMAND(ID_HELP_HISTORY, OnHelpHistory) - ON_COMMAND(ID_EXPORT_SNAPSHOT, OnExportSnapshot) - ON_COMMAND(ID_WINDOWS_PRIMITIVECONFIGURATION, OnWindowsPrimitiveconfiguration) - ON_UPDATE_COMMAND_UI(ID_WINDOWS_PRIMITIVECONFIGURATION, OnUpdateWindowsPrimitiveconfiguration) - ON_COMMAND(ID_PROJECT_RESET_PRIMITIVE_CONFIGURATION, OnProjectResetPrimitiveConfiguration) - ON_WM_DESTROY() - ON_COMMAND(ID_EDIT_EXPAND, OnEditExpand) - ON_COMMAND(ID_EDIT_COLLAPSE, OnEditCollapse) - ON_WM_PAINT() - ON_WM_MENUSELECT() - ON_COMMAND(ID_SAVPOS, OnSavePosition) - ON_WM_DROPFILES() - ON_COMMAND(ID_MISSION_COMPILER, OnMissionCompiler) - ON_COMMAND(ID_NAME_DLG, OnNameDlg) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - - -static UINT indicators[] = -{ - ID_INDICATOR_ZONENAMENEL, - ID_INDICATOR_ZONENAMEREF, - ID_INDICATOR_COORDINATES, - ID_INDICATOR_ZONEROT, - ID_INDICATOR_ZONEFLIP, - ID_INDICATOR_SELECTION, - ID_INDICATOR_INFO, -}; - -// *************************************************************************** -// CMainFrame construction/destruction - -CMainFrame::CMainFrame() - : - _Mode(0), - _SplitterCreated(false), - _MasterCB(0), - _CurrentPlugin(0) -{ - CreateX = CreateY = CreateCX = CreateCY = 0; - _ZoneBuilder = NULL; - _SelectionLocked = false; - _TransformModes[0] = Select; - _TransformModes[1] = Select; - _ShowDetails = false; - _ShowLandscape = true; - _ShowGrid = true; - _ShowPoints = true; - _ShowPACS = false; - _ShowPrimitives = true; - _ShowLayers = true; - _ValidLandscape = true; - _ShowCollisions = false; - m_FindPrimitiveDlg = NULL; - _MustRefreshPropertyDialog = false; -} - -CMainFrame::~CMainFrame() -{ - if (_ZoneBuilder) - delete _ZoneBuilder; - - if (m_FindPrimitiveDlg) - { - if (::IsWindow(m_FindPrimitiveDlg->GetSafeHwnd())) - m_FindPrimitiveDlg->EndDialog(IDCANCEL); - delete m_FindPrimitiveDlg; - m_FindPrimitiveDlg = NULL; - } - - // Free the clipboard - deletePrimitiveClipboard (); -} - -int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) -{ - if (CFrameWnd::OnCreate(lpCreateStruct) == -1) - return -1; - - if (!m_wndToolBar.CreateEx(this) || - !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) - { - TRACE0("Failed to create toolbar\n"); - return -1; // fail to create - } -/* if (!m_wndDlgBar.Create(this, IDR_MAINFRAME, - CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR)) - { - TRACE0("Failed to create dialogbar\n"); - return -1; // fail to create - }*/ - - if (!m_wndReBar.Create(this) || - !m_wndReBar.AddBar(&m_wndToolBar) /*|| - !m_wndReBar.AddBar(&m_wndDlgBar)*/) - { - TRACE0("Failed to create rebar\n"); - return -1; // fail to create - } - - if (!m_wndStatusBar.Create(this) || - !m_wndStatusBar.SetIndicators(indicators, - sizeof(indicators)/sizeof(UINT))) - { - TRACE0("Failed to create status bar\n"); - return -1; // fail to create - } - - // TODO: Remove this if you don't want tool tips - CMenu *menu = GetMenu (); - m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_ZONE), TBBS_CHECKGROUP); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_TRANSITION), TBBS_CHECKGROUP); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_LOGIC), TBBS_CHECKGROUP); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_LOCK), TBBS_CHECKBOX); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_DETAILS), TBBS_CHECKBOX); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_SELECT), TBBS_CHECKGROUP); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_TRANSLATE), TBBS_CHECKGROUP); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_ROTATE), TBBS_CHECKGROUP); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_TURN), TBBS_CHECKGROUP); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_SCALE), TBBS_CHECKGROUP); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_RADIUS), TBBS_CHECKGROUP); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_ADD_POINT), TBBS_CHECKGROUP); - m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_VIEW_LANDSCAPE), TBBS_CHECKBOX); - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_LANDSCAPE); - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_LAYERS); - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_GRID); - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_POINTS); - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_PRIMITIVES); - menu->CheckMenuItem (ID_VIEW_LANDSCAPE, MF_CHECKED|MF_BYCOMMAND); - menu->CheckMenuItem (ID_VIEW_LAYERS, MF_CHECKED|MF_BYCOMMAND); - menu->CheckMenuItem (ID_VIEW_GRID, MF_CHECKED|MF_BYCOMMAND); - menu->CheckMenuItem (ID_VIEW_POINTS, MF_CHECKED|MF_BYCOMMAND); - menu->CheckMenuItem (ID_VIEW_PRIMITIVES, MF_CHECKED|MF_BYCOMMAND); - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_ZONE); - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_SELECT); - - CDocument *pNewDoc = new CWorldEditorDoc;//CDocument; - InitialUpdateFrame(pNewDoc, TRUE); - - // Default tool column size - _ToolColumnSize = 300; - - // Init display - SetActiveView((CView*)m_wndSplitter.GetPane (0,0)); - DispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); - - // Timer - CFrameWnd::SetTimer (TIMER_UPDATE_FILES, 5000, NULL); - CFrameWnd::SetTimer (TIMER_PLUGINS, 1000/10, NULL); - - // Init the main frame - if (init ()) - { - // Disable events - CNoInteraction nointeraction; - - launchLoadingDialog("init display"); - DispWnd->setCellSize (theApp.Config.CellSize); - DispWnd->init (this); - terminateLoadingDialog(); - return 0; - } - else - return -1; -} - -BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, - CCreateContext* pContext) -{ -// AFX_MANAGE_STATE (AfxGetStaticModuleState()); - // create a splitter with 1 row, 2 columns - if (!m_wndSplitter.CreateStatic(this, 1, 2)) - { - TRACE0("Failed to CreateStaticSplitter\n"); - return FALSE; - } - - // add the first splitter pane - the default view in column 0 - if (!m_wndSplitter.CreateView(0, 0, - RUNTIME_CLASS(CDisplay), CSize(640, 512), pContext)) - { - TRACE0("Failed to create first pane\n"); - return FALSE; - } - - // add the second splitter pane - the default view in column 0 - if (!m_wndSplitter.CreateView(0, 1, - RUNTIME_CLASS(CPrimitiveView), CSize(200, 100), pContext)) - { - TRACE0("Failed to create first pane\n"); - return FALSE; - } - - _SplitterCreated = true; - - return TRUE; -} - -// *************************************************************************** - -BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) -{ - //AFX_MANAGE_STATE (AfxGetStaticModuleState()); - - if ((CreateCX != 0)&&(CreateCY != 0)) - { - cs.x = CreateX; - cs.y = CreateY; - cs.cx = CreateCX; - cs.cy = CreateCY; - } - - if (!CFrameWnd::PreCreateWindow(cs)) - return FALSE; - return TRUE; -} - -// *************************************************************************** - -// CMainFrame diagnostics - -#ifdef _DEBUG -void CMainFrame::AssertValid() const -{ - CFrameWnd::AssertValid(); -} - -void CMainFrame::Dump(CDumpContext& dc) const -{ - CFrameWnd::Dump(dc); -} - -#endif //_DEBUG - -// *************************************************************************** - -// CMainFrame message handlers - - - - - - - - -/* Old Trap begin */ - -// *************************************************************************** - -// CType - -// *************************************************************************** - -void SType::serial (NLMISC::IStream&f) -{ - int version = f.serialVersion(0); - f.serial (Name); - f.serial (Color); -} - -// *************************************************************************** - -// CType - -// *************************************************************************** - -SEnvironnement::SEnvironnement () -{ -} - -// *************************************************************************** - -void SEnvironnement::serial (NLMISC::IStream&f) -{ - int version = f.serialVersion (1); - - f.serialCont (Types); - f.serial (BackgroundColor); - // f.serial (ExportOptions); - - if (version > 0) - f.serial (DataDir); -} - -// *************************************************************************** -// CMainFrame - -// *************************************************************************** - -NLMISC::CConfigFile &CMainFrame::getConfigFile() -{ -// AFX_MANAGE_STATE(AfxGetStaticModuleState()); - AFX_MANAGE_STATE(AfxGetAppModuleState()); - // Old Trap return IWorldEditor::getInterface()->getConfigFile(); - CWinApp *theApp = AfxGetApp(); - CWorldEditorApp* wea = static_cast(theApp); - - return wea->PluginConfig; -} - -void CMainFrame::onLogicChanged(const std::vector ®ions) -{ - /* const std::vector &plugins = IWorldEditor::getInterface()->getPlugins(); - std::vector::const_iterator first(plugins.begin()), last(plugins.end()); - - for (; first != last; ++first) - { - (*first)->primRegionChanged(regions); - } */ -} - -// *************************************************************************** - -bool CMainFrame::yesNoMessage (const char *format, ... ) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - return theApp.yesNoMessage (buffer); -} - -// *************************************************************************** - -void CMainFrame::errorMessage (const char *format, ... ) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - theApp.errorMessage (buffer); -} - -// *************************************************************************** - -void CMainFrame::infoMessage (const char *format, ... ) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - theApp.infoMessage (buffer); -} - -// *************************************************************************** - -void CMainFrame::startPositionControl(IPluginCallback *plugin, const CVector &initPos) -{ - AFX_MANAGE_STATE(AfxGetAppModuleState()); - if (_CurrentPlugin != 0) - _CurrentPlugin->lostPositionControl(); - - _CurrentPlugin = plugin; - _PositionControl = initPos; - - if (_Mode != 3) - { - _LastMode = _Mode; -// uninitTools(); - _Mode = 3; -// initTools(); - } - - DispWnd->Invalidate(); -} - -// *************************************************************************** - -void CMainFrame::stopPositionControl(IPluginCallback *plugin) -{ - AFX_MANAGE_STATE(AfxGetAppModuleState()); - if (_CurrentPlugin == plugin) - { - _CurrentPlugin = 0; - if (_Mode == 3) - { - // uninitTools(); - _Mode = _LastMode; - // initTools(); - } - } - DispWnd->Invalidate(); -} - -// *************************************************************************** -void CMainFrame::setExeDir (const char* str) -{ -// AFX_MANAGE_STATE (AfxGetStaticModuleState()); - _ExeDir = str; - if ((str[strlen(str)-1] != '\\') || (str[strlen(str)-1] != '/')) - _ExeDir += "\\"; -} - -// *************************************************************************** - -void CMainFrame::uninitTools() -{ - if (_Mode == 0) // Mode Zone - { - CToolsZone *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); - toolWnd->uninit (); - } - if (_Mode == 1) // Mode Logic - { - // Invalidate primitives - CWorldEditorDoc *doc = getDocument (); - uint i; - uint count = doc->getNumDatabaseElement (); - for (i=0; ilostPositionControl(); - _CurrentPlugin = 0; - } - } -} - -// *************************************************************************** - -void CMainFrame::initTools() -{ - if (_Mode == 0) // Mode Zone - { - m_wndSplitter.DeleteView (0, 1); - m_wndSplitter.CreateView (0, 1, RUNTIME_CLASS(CToolsZone), CSize(100, 100), NULL); - SetActiveView ((CView*)m_wndSplitter.GetPane(0,1)); - CToolsZone *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); - toolWnd->init (this); - adjustSplitter (); - } - if (_Mode == 1) // Mode Logic - { - m_wndSplitter.DeleteView (0, 1); - m_wndSplitter.CreateView (0, 1, RUNTIME_CLASS(CToolsLogic), CSize(200, 100), NULL); - SetActiveView ((CView*)m_wndSplitter.GetPane(0,1)); - CToolsLogic *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); - toolWnd->init (this); - adjustSplitter (); - - // Invalidate primitives - CWorldEditorDoc *doc = getDocument (); - uint i; - uint count = doc->getNumDatabaseElement (); - for (i=0; ipositionMoved(_PositionControl); - - } - SetActiveView ((CView*)m_wndSplitter.GetPane(0,0)); - -} - -// *************************************************************************** - -void CMainFrame::invalidateTools () -{ - if (_Mode == 1) // Mode Logic - { - CToolsLogic *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); - } -} - -// *************************************************************************** - -void CMainFrame::invalidateLandscape () -{ - _ValidLandscape = false; -} - -// *************************************************************************** - -void CMainFrame::invalidateToolsParam () -{ - if (_Mode == 1) // Mode Logic - { - CToolsLogic *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); - toolWnd->Invalidate(FALSE); - } -} - -// *************************************************************************** - -void CMainFrame::invalidateModification () -{ - if (_Mode == 1) // Mode Logic - { - CToolsLogic *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); - } -} - -// *************************************************************************** - -void CMainFrame::updateData () -{ - // Disable events - CNoInteraction nointeraction; - - // Update primitive quad grid - UpdatePrimitives (); - - // Update the landscape - if (!_ValidLandscape) - { - // Init the landscape manager - _ZoneBuilder->refresh (); - - _ValidLandscape = true; - } - - if (_Mode == 1) // Mode Logic - { - CToolsLogic *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); - } - - // Update the cursor - getDisplay ()->updateCursor (); - - // Update status bar info - displayStatusBarInfo (); -} - -// *************************************************************************** -void CMainFrame::primZoneModified () -{ - if (_MasterCB != NULL) - { - vector allNames; - } -} - -// *************************************************************************** - -void CMainFrame::displayStatusBarInfo () -{ - std::string sTmp; - - // Position - const CVector &v = DispWnd->_CurPos; - - // Write the zone name in NeL protocol - sint32 x, y; - - CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); - x = (sint32)floor(v.x / dispWnd->_CellSize); - y = (sint32)floor(v.y / dispWnd->_CellSize); - if ((v.x >= 0) && (x <= 255) && (v.y <= 0) && (y >= -255)) - { - getZoneNameFromXY(x, y, sTmp); - } - else - { - sTmp = "NOT A VALID ZONE"; - } - - string text; - if (dispWnd->getActionHelp (text)) - { - m_wndStatusBar.SetPaneText (0, text.c_str()); - } - else - { - m_wndStatusBar.SetPaneText (0, sTmp.c_str()); - } - //for (uint32 i = sTmp.size(); i < 10; ++i) - // sTmp += " "; - - // Write zone reference name - if (dispWnd->getActionText (text)) - { - m_wndStatusBar.SetPaneText (1, text.c_str()); - } - else - { - sTmp = _ZoneBuilder->getZoneName (x, y); - m_wndStatusBar.SetPaneText (1, sTmp.c_str()); - } - - // Write coordinates - char temp[1024]; - sprintf(temp, "(%.3f , %.3f)", v.x, v.y); - sTmp = temp; -// sTmp = "( " + toString(v.x) + " , " + toString(v.y) + " )"; - m_wndStatusBar.SetPaneText (2, sTmp.c_str()); - - // Write rot - sTmp = "Rot(" + toString(_ZoneBuilder->getRot(x, y)) + ")"; - m_wndStatusBar.SetPaneText (3, sTmp.c_str()); - - // Write flip - sTmp = "Flip(" + toString(_ZoneBuilder->getFlip(x, y)) + ")"; - m_wndStatusBar.SetPaneText (4, sTmp.c_str()); - - // Write selection - if (Selection.size ()) - { - if (Selection.size ()>1) - sTmp = toString (Selection.size ()) + " selected primitives"; - else - sTmp = toString (Selection.size ()) + " selected primitive"; - } - else - sTmp = "No selected primitive"; - m_wndStatusBar.SetPaneText (5, sTmp.c_str()); - - // Write path of selected primitive - if (Selection.size()) - sTmp = getDocument()->getPathOfSelectedPrimitive(); - else - sTmp = ""; - - m_wndStatusBar.SetPaneText (6, sTmp.c_str()); -} - -// *************************************************************************** - -void CMainFrame::displayInfo (const char *info) -{ - m_wndStatusBar.SetPaneText (6, info); -} - -// *************************************************************************** -// *************************************************************************** -// CMainFrame diagnostics - - -// *************************************************************************** -bool CMainFrame::init (bool bMakeAZone) -{ - // Initialize the zoneBuilder (load bank and this kind of stuff) - if (initLandscapeData ()) - { - // Mode zone - _Mode = 0; - return true; - } - else - { - return false; - } -} - -// *************************************************************************** -void CMainFrame::uninit () -{ - // Save the WorldEditor.cfg - try - { - COFile fileOut; - string sWorldEdCfg = _ExeDir; - sWorldEdCfg += "WorldEditor.cfg"; - fileOut.open (sWorldEdCfg.c_str(), false, false, true); - fileOut.serial(_Environnement); - fileOut.close(); - } - catch (Exception& e) - { - MessageBox (e.what(), "Warning"); - } -} - -// ****************** -// MESSAGES FROM MENU -// ****************** - -// *************************************************************************** -void CMainFrame::onMenuFileOpenLogic () -{ - CFileDialogEx dialog (BASE_REGISTRY_KEY, "prim", TRUE, "prim", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Primitives Files (*.prim)|*.prim||", this); - if (dialog.DoModal() == IDOK) - { - launchLoadingDialog(string("loading prim zone ") + (LPCSTR)dialog.GetFileName()); - // todo primitive load - primZoneModified (); - terminateLoadingDialog(); - } -} - -// *************************************************************************** - -void CMainFrame::onMenuFileExit () -{ - OnClose(); -} - -// *************************************************************************** -void CMainFrame::onMenuModeZone () -{ - CMenu *menu = GetMenu(); - menu->CheckMenuRadioItem( ID_EDIT_ZONE, ID_EDIT_LOGIC, ID_EDIT_ZONE, MF_BYCOMMAND); - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_ZONE); - - if (_Mode == 1) // if we were in Logic mode switch - { - // store the width of the logic tool panel - if (_SplitterCreated) - { - RECT r; - int cxCur, cxMin; - GetClientRect (&r); - m_wndSplitter.GetColumnInfo(0, cxCur, cxMin); - _ToolColumnSize = r.right-r.left-cxCur; - } - - uninitTools (); - _Mode = 0; - initTools (); - } - _Mode = 0; - CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); - - // Update data - updateData (); -} - -// *************************************************************************** -void CMainFrame::onMenuModeTransition () -{ - CMenu *menu = GetMenu(); - menu->CheckMenuRadioItem( ID_EDIT_ZONE, ID_EDIT_LOGIC, ID_EDIT_TRANSITION, MF_BYCOMMAND); - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_TRANSITION); - - if (_Mode == 1) // if we were in Logic mode switch - { - // store the width of the logic tool panel - if (_SplitterCreated) - { - RECT r; - int cxCur, cxMin; - GetClientRect (&r); - m_wndSplitter.GetColumnInfo(0, cxCur, cxMin); - _ToolColumnSize = r.right-r.left-cxCur; - } - - uninitTools (); - _Mode = 0; - initTools (); - } - _Mode = 2; - CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); - - // Update data - updateData (); -} - -// *************************************************************************** -void CMainFrame::onMenuModeLogic () -{ - CMenu *menu = GetMenu(); - menu->CheckMenuRadioItem( ID_EDIT_ZONE, ID_EDIT_LOGIC, ID_EDIT_LOGIC, MF_BYCOMMAND); - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_LOGIC); - - if (_Mode != 1) // Mode Logic - { - uninitTools(); - _Mode = 1; - initTools(); - } - CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); - - // Update data - updateData (); -} - -// *************************************************************************** - -void CMainFrame::onMenuModeUndo () -{ - getDocument ()->undo (); - - // Update data - updateData (); -} - -// *************************************************************************** -void CMainFrame::onMenuModeRedo () -{ - getDocument ()->redo (); - - // Update data - updateData (); -} - -// *************************************************************************** -#if 0 -void CMainFrame::onMenuModeMove () -{ - CMoveDlg dialog; - if (dialog.DoModal() == IDOK) - if (getDocument ()->getNumLandscape ()) - { - // Select the size - const CZoneRegion ®ion = getDocument ()->getZoneRegion (_ZoneBuilder->_ZoneRegionSelected); - - _ZoneBuilder->move (dialog.XOffset, dialog.YOffset); - CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); - } -} -#endif -// *************************************************************************** -/* -void CMainFrame::onMenuModeCountZones () -{ - if (getDocument ()->getNumLandscape ()) - { - uint32 nNbZones = _ZoneBuilder->countZones (); - string tmp = "There are " + toString(nNbZones) + " zones"; - MessageBox(tmp.c_str(), "Information", MB_ICONINFORMATION|MB_OK); - } -} -*/ -// *************************************************************************** -void CMainFrame::onMenuViewGrid () -{ -// AFX_MANAGE_STATE(AfxGetStaticModuleState()); - CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); - dispWnd->setDisplayGrid (!dispWnd->getDisplayGrid()); - CMenu *menu = GetMenu(); - menu->CheckMenuItem (ID_VIEW_GRID, dispWnd->getDisplayGrid()?MF_CHECKED|MF_BYCOMMAND:MF_UNCHECKED|MF_BYCOMMAND); -} - -// *************************************************************************** -void CMainFrame::onMenuViewBackground () -{ - CColorDialog colDial; - - if (colDial.DoModal() == IDOK) - { - int r = GetRValue(colDial.GetColor()); - int g = GetGValue(colDial.GetColor()); - int b = GetBValue(colDial.GetColor()); - _Environnement.BackgroundColor = CRGBA(r,g,b,255); - CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); - dispWnd->setBackgroundColor (_Environnement.BackgroundColor); - } -} - -// *************************************************************************** -void CMainFrame::OnClose () -{ - _Exit = true; - CFrameWnd::OnClose (); -} - -// *************************************************************************** -void CMainFrame::OnSize (UINT nType, int cx, int cy) -{ - if (nType != SIZE_MINIMIZED) - { - if (cx < 100) - cx = 100; - if (cy < 100) - cy = 100; - } - - // store the width of the logic tool panel - if (_SplitterCreated && _Mode == 1) - { - int cxCur, cxMin; - m_wndSplitter.GetColumnInfo(0, cxCur, cxMin); - _ToolColumnSize = cx - cxCur; - } - - CFrameWnd::OnSize (nType, cx, cy); - if (nType != SIZE_MINIMIZED) - adjustSplitter (); -} - -// *************************************************************************** -void CMainFrame::adjustSplitter () -{ - if (_SplitterCreated) - { - RECT r; - GetClientRect (&r); - - // Mode Zone - if ((_Mode == 0) || (_Mode == 2) && (r.right-r.left > 380)) - m_wndSplitter.SetColumnInfo (0, r.right-r.left-380, 100); // 380 really experimental value - - // Mode Logic - if (_Mode == 1) - if (r.right-r.left > _ToolColumnSize) - m_wndSplitter.SetColumnInfo (0, r.right-r.left-_ToolColumnSize, 10); - else - m_wndSplitter.SetColumnInfo (0, 0, 10); - - - m_wndSplitter.RecalcLayout (); - } -} - -// *************************************************************************** -void CMainFrame::launchLoadingDialog (const std::string &sText) -{ - LoadingDialog = new CLoadingDialog(this); - LoadingDialog->ShowWindow(SW_SHOW); - LoadingDialog->setText(sText); - LoadingDialog->setProgress (0); - CWnd *wnd = LoadingDialog->GetDlgItem (IDC_PROGRESS1); - nlassert (wnd); - wnd->ShowWindow (SW_HIDE); -} - -// *************************************************************************** - -void CMainFrame::progressLoadingDialog (float progress, bool _flushMessages) -{ - nlassert (LoadingDialog); - LoadingDialog->setProgress (progress); - - // Flush current messages - if (_flushMessages) - { - flushMessages (); - } -} - -// *************************************************************************** - -void CMainFrame::flushMessages () -{ - // Pump others message for the windows - MSG msg; - while (PeekMessage(&msg, *LoadingDialog, 0, 0, PM_REMOVE)) - { - TranslateMessage (&msg); - DispatchMessage (&msg); - } -} - -// *************************************************************************** - -void CMainFrame::terminateLoadingDialog () -{ - delete LoadingDialog; -} - -// *************************************************************************** - -LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) -{ - // TODO: Add your specialized code here and/or call the base class - if (!DontUse3D && CNELU::Driver) - { - typedef void (*winProc)(NL3D::IDriver *drv, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); - winProc drvWndProc= (winProc)CNELU::Driver->getWindowProc(); - drvWndProc (CNELU::Driver, m_hWnd, message, wParam, lParam); - } - - return CFrameWnd::WindowProc(message, wParam, lParam); -} - -// *************************************************************************** -// *************************************************************************** -// CLoadingDialog -// *************************************************************************** -// *************************************************************************** - - -// *************************************************************************** - -CLoadingDialog::CLoadingDialog (CWnd *pParent) -{ - Create (IDD_LOADING, pParent); -} - -// *************************************************************************** - -void CLoadingDialog::setText (const std::string &text) -{ - CStatic *pS = (CStatic*)GetDlgItem (IDC_STATIC_TEXT_LOADING); - string sTmp = string("Please wait while ") + text; - setWindowTextUTF8 (*pS, sTmp.c_str()); - - MSG msg; - while (PeekMessage(&msg, *this, 0, 0, PM_REMOVE)) - { - TranslateMessage (&msg); - DispatchMessage (&msg); - } -} - -// *************************************************************************** - -void CLoadingDialog::setProgress (float progress) -{ - CProgressCtrl *progressDlg = (CProgressCtrl *)GetDlgItem (IDC_PROGRESS1); - nlassert (progressDlg); - - progressDlg->ShowWindow (SW_SHOW); - progressDlg->SetRange (0, 32767); - - clamp (progress, 0.f, 1.f); - progressDlg->SetPos ((int)(progress * 32767.f)); -} - -// *************************************************************************** - -/* -void CMainFrame::onMenuFileView () -{ - viewLand(false); -} -*/ - -// *************************************************************************** - -/* -void CMainFrame::onMenuFileViewWithIG() -{ - viewLand(true); -} -*/ - -// *************************************************************************** - -struct CViewerConfig -{ - bool Windowed; - uint Width; - uint Height; - uint Depth; - CVector Position; - CVector Heading; - CVector EyesHeight; - CRGBA Background; - - // Landscape - bool AutoLight; - CVector LightDir; - string ZonesPath; - string BanksPath; - string TilesPath; - bool UseDDS; - bool AllPathRelative; - - string IgPath; - string ShapePath; - string MapsPath; - string Bank; - string FontPath; - //CTextContext TextContext; - //CFontManager FontManager; - float ZFar; - float LandscapeTileNear; - float LandscapeThreshold; - vector Zones; - vector Igs; - - // HeightField. - string HeightFieldName; - float HeightFieldMaxZ; - float HeightFieldOriginX; - float HeightFieldOriginY; - float HeightFieldSizeX; - float HeightFieldSizeY; - - // StaticLight - CRGBA LandAmbient; - CRGBA LandDiffuse; - - // ----------------------------------------------------------------------- - - CViewerConfig() - { - Windowed = true; - Width = 800; - Height = 600; - Depth = 32; - Position = CVector( 1088.987793f, -925.732178f, 0.0f ); - Heading = CVector(0,1,0); - EyesHeight = CVector(0,0,1.8f); - Background = CRGBA(100,100,255); - AutoLight = false; - LightDir = CVector (1, 0, 0); - ZonesPath = "./"; - BanksPath = "./"; - TilesPath = "./"; - UseDDS = false; - AllPathRelative = false; - IgPath = "./"; - ShapePath = "./"; - MapsPath = "./"; - Bank = "bank.bank"; - FontPath = "\\\\server\\code\\fonts\\arialuni.ttf"; - ZFar = 1000; - LandscapeTileNear = 50.0f; - LandscapeThreshold = 0.001f; - - HeightFieldName= ""; - HeightFieldMaxZ= 100; - HeightFieldOriginX= 16000; - HeightFieldOriginY= -24000; - HeightFieldSizeX= 160; - HeightFieldSizeY= 160; - - CRGBA diffuse (241, 226, 244); - CRGBA ambiant (17, 54, 100); - LandDiffuse= diffuse; - LandAmbient= ambiant; - - } - - // ----------------------------------------------------------------------- - void load (const string & configFileName) - { - FILE * f = fopen (configFileName.c_str(), "rt"); - if(f==NULL) - { - nlwarning("'%s' not found, default values used", configFileName.c_str()); - save (configFileName); - } - else fclose (f); - - try - { - CConfigFile cf; - - cf.load(configFileName); - - CConfigFile::CVar &cvFullScreen = cf.getVar("FullScreen"); - this->Windowed = cvFullScreen.asInt() ? false : true; - - CConfigFile::CVar &cvWidth = cf.getVar("Width"); - this->Width = cvWidth.asInt(); - - CConfigFile::CVar &cvHeight = cf.getVar("Height"); - this->Height = cvHeight.asInt(); - - CConfigFile::CVar &cvDepth = cf.getVar("Depth"); - this->Depth = cvDepth.asInt(); - - CConfigFile::CVar &cvPosition = cf.getVar("Position"); - nlassert(cvPosition.size()==3); - this->Position.x = cvPosition.asFloat(0); - this->Position.y = cvPosition.asFloat(1); - this->Position.z = cvPosition.asFloat(2); - - CConfigFile::CVar &cvEyesHeight = cf.getVar("EyesHeight"); - this->EyesHeight = CVector(0,0,cvEyesHeight.asFloat()); - - CConfigFile::CVar &cvBackColor = cf.getVar("Background"); - nlassert(cvBackColor.size()==3); - this->Background.R = cvBackColor.asInt(0); - this->Background.G = cvBackColor.asInt(1); - this->Background.B = cvBackColor.asInt(2); - - CConfigFile::CVar &cvZFar = cf.getVar("ZFar"); - this->ZFar = cvZFar.asFloat(); - - CConfigFile::CVar &cvAutoLight = cf.getVar("AutoLight"); - this->AutoLight = cvAutoLight.asInt() ? true : false; - - CConfigFile::CVar &cvLightDir = cf.getVar("LightDir"); - nlassert(cvLightDir.size()==3); - this->LightDir.x = cvLightDir.asFloat(0); - this->LightDir.y = cvLightDir.asFloat(1); - this->LightDir.z = cvLightDir.asFloat(2); - - CConfigFile::CVar &cvLandscapeTileNear = cf.getVar("LandscapeTileNear"); - this->LandscapeTileNear = cvLandscapeTileNear.asFloat(); - - CConfigFile::CVar &cvLandscapeThreshold = cf.getVar("LandscapeThreshold"); - this->LandscapeThreshold = cvLandscapeThreshold.asFloat(); - - CConfigFile::CVar &cvBanksPath = cf.getVar("BanksPath"); - this->BanksPath = cvBanksPath.asString(); - - CConfigFile::CVar &cvTilesPath = cf.getVar("TilesPath"); - this->TilesPath = cvTilesPath.asString(); - - CConfigFile::CVar &cvUseDDS = cf.getVar("UseDDS"); - this->UseDDS = cvUseDDS.asInt() ? true : false; - - CConfigFile::CVar &cvAllPathRelative = cf.getVar("AllPathRelative"); - this->AllPathRelative = cvAllPathRelative.asInt() ? true : false; - - CConfigFile::CVar &cvBank = cf.getVar("Bank"); - this->Bank = cvBank.asString(); - - CConfigFile::CVar &cvZonesPath = cf.getVar("ZonesPath"); - this->ZonesPath = cvZonesPath.asString(); - - CConfigFile::CVar &cvIgPath = cf.getVar("IgPath"); - this->IgPath = cvIgPath.asString(); - - CConfigFile::CVar &cvShapePath = cf.getVar("ShapePath"); - this->ShapePath = cvShapePath.asString(); - - CConfigFile::CVar &cvMapsPath = cf.getVar("MapsPath"); - this->MapsPath = cvMapsPath.asString(); - - CConfigFile::CVar &cvHeightFieldName = cf.getVar("HeightFieldName"); - this->HeightFieldName = cvHeightFieldName.asString(); - - CConfigFile::CVar &cvHeightFieldMaxZ = cf.getVar("HeightFieldMaxZ"); - this->HeightFieldMaxZ = cvHeightFieldMaxZ.asFloat(); - - CConfigFile::CVar &cvHeightFieldOriginX = cf.getVar("HeightFieldOriginX"); - this->HeightFieldOriginX = cvHeightFieldOriginX.asFloat(); - - CConfigFile::CVar &cvHeightFieldOriginY = cf.getVar("HeightFieldOriginY"); - this->HeightFieldOriginY = cvHeightFieldOriginY.asFloat(); - - CConfigFile::CVar &cvHeightFieldSizeX = cf.getVar("HeightFieldSizeX"); - this->HeightFieldSizeX = cvHeightFieldSizeX.asFloat(); - - CConfigFile::CVar &cvHeightFieldSizeY = cf.getVar("HeightFieldSizeY"); - this->HeightFieldSizeY = cvHeightFieldSizeY.asFloat(); - - - CConfigFile::CVar &cvLandAmb = cf.getVar("LandAmbient"); - nlassert(cvLandAmb.size()==3); - this->LandAmbient.R = cvLandAmb.asInt(0); - this->LandAmbient.G = cvLandAmb.asInt(1); - this->LandAmbient.B = cvLandAmb.asInt(2); - - CConfigFile::CVar &cvLandDiff = cf.getVar("LandDiffuse"); - nlassert(cvLandDiff.size()==3); - this->LandDiffuse.R = cvLandDiff.asInt(0); - this->LandDiffuse.G = cvLandDiff.asInt(1); - this->LandDiffuse.B = cvLandDiff.asInt(2); - - - CConfigFile::CVar &cvZones = cf.getVar("Zones"); - for(uint i=0; iZones.push_back(cvZones.asString(i)); - } - - CConfigFile::CVar &cvIgs = cf.getVar("Ig"); - for(uint i=0; iIgs.push_back(cvIgs.asString(i)); - } - - } - catch (EConfigFile &e) - { - printf ("Problem in config file : %s\n", e.what ()); - } - } - - // ----------------------------------------------------------------------- - void save (const string &configFileName) - { - FILE * f = fopen (configFileName.c_str(), "wt"); - - if(f==NULL) - { - fprintf(stderr,"can't open file '%s'\n",configFileName); - } - - fprintf(f,"FullScreen = %d;\n",this->Windowed?0:1); - fprintf(f,"Width = %d;\n",this->Width); - fprintf(f,"Height = %d;\n",this->Height); - fprintf(f,"Depth = %d;\n",this->Depth); - fprintf(f,"Position = { %f, %f, %f };\n", this->Position.x,this->Position.y,this->Position.z); - fprintf(f,"EyesHeight = %f;\n", this->EyesHeight.z); - fprintf(f,"Background = { %d, %d, %d };\n", this->Background.R,this->Background.G,this->Background.B); - fprintf(f,"ZFar = %f;\n", this->ZFar); - - fprintf(f,"AutoLight = %d;\n", this->AutoLight?1:0); - fprintf(f,"LightDir = { %f, %f, %f };\n", this->LightDir.x, this->LightDir.y, this->LightDir.z); - fprintf(f,"LandscapeTileNear = %f;\n", this->LandscapeTileNear); - fprintf(f,"LandscapeThreshold = %f;\n", this->LandscapeThreshold); - fprintf(f,"BanksPath = \"%s\";\n",this->BanksPath.c_str()); - fprintf(f,"TilesPath = \"%s\";\n",this->TilesPath.c_str()); - fprintf(f,"UseDDS = \"%d\";\n",this->UseDDS?1:0); - fprintf(f,"AllPathRelative = \"%d\";\n",this->AllPathRelative?1:0); - fprintf(f,"Bank = \"%s\";\n",this->Bank.c_str()); - fprintf(f,"ZonesPath = \"%s\";\n",this->ZonesPath.c_str()); - fprintf(f,"IgPath = \"%s\";\n",this->IgPath.c_str()); - fprintf(f,"ShapePath = \"%s\";\n",this->ShapePath.c_str()); - fprintf(f,"MapsPath = \"%s\";\n",this->MapsPath.c_str()); - - - - fprintf(f,"HeightFieldName = \"%s\";\n", this->HeightFieldName.c_str()); - fprintf(f,"HeightFieldMaxZ = %f;\n", this->HeightFieldMaxZ); - fprintf(f,"HeightFieldOriginX = %f;\n", this->HeightFieldOriginX); - fprintf(f,"HeightFieldOriginY = %f;\n", this->HeightFieldOriginY); - fprintf(f,"HeightFieldSizeX = %f;\n", this->HeightFieldSizeX); - fprintf(f,"HeightFieldSizeY = %f;\n", this->HeightFieldSizeY); - - fprintf(f,"LandAmbient = { %d, %d, %d };\n", this->LandAmbient.R,this->LandAmbient.G,this->LandAmbient.B); - fprintf(f,"LandDiffuse = { %d, %d, %d };\n", this->LandDiffuse.R,this->LandDiffuse.G,this->LandDiffuse.B); - - uint32 i; - fprintf(f,"Zones = {\n"); - for (i = 0; i < Zones.size(); ++i) - if (i < (Zones.size()-1)) - fprintf(f,"\"%s\",\n", Zones[i]); - else - fprintf(f,"\"%s\"\n", Zones[i]); - fprintf(f,"};\n"); - - fprintf(f,"Ig = {\n"); - for (i = 0; i < Igs.size(); ++i) - if (i < (Igs.size()-1)) - fprintf(f,"\"%s\",\n", Igs[i]); - else - fprintf(f,"\"%s\"\n", Igs[i]); - fprintf(f,"};\n"); - - fclose(f); - } -}; - -// *************************************************************************** - -/* -void CMainFrame::viewLand(bool withIgs) -{ - // Modify the zviewer.cfg - CViewerConfig cfgFile; - SetCurrentDirectory (_ExeDir.c_str()); - string cfgFileName = "zviewer.cfg"; - cfgFile.load (cfgFileName); - cfgFile.Zones.clear (); - cfgFile.Igs.clear (); - - // Select the size - const CZoneRegion ®ion = getDocument ()->getZoneRegion (_ZoneBuilder->_ZoneRegionSelected); - - sint32 nMinX = region.getMinX() < 0 ? 0 : region.getMinX(); - sint32 nMaxX = region.getMaxX() > 255 ? 255 : region.getMaxX(); - sint32 nMinY = region.getMinY() > 0 ? 0 : region.getMinY(); - sint32 nMaxY = region.getMaxY() < -255 ? -255 : region.getMaxY(); - - if ((_Environnement.ExportOptions.ZoneMin != "") && (_Environnement.ExportOptions.ZoneMax != "")) - { - _Environnement.ExportOptions.ZoneMin = strupr (_Environnement.ExportOptions.ZoneMin); - _Environnement.ExportOptions.ZoneMax = strupr (_Environnement.ExportOptions.ZoneMax); - sint32 nNewMinX = CExport::getXFromZoneName (_Environnement.ExportOptions.ZoneMin); - sint32 nNewMinY = CExport::getYFromZoneName (_Environnement.ExportOptions.ZoneMin); - sint32 nNewMaxX = CExport::getXFromZoneName (_Environnement.ExportOptions.ZoneMax); - sint32 nNewMaxY = CExport::getYFromZoneName (_Environnement.ExportOptions.ZoneMax); - - if (nNewMinX > nNewMaxX) - swap (nNewMinX, nNewMaxX); - if (nNewMinY > nNewMaxY) - swap (nNewMinY, nNewMaxY); - - if (nNewMinX > nMinX) - nMinX = nNewMinX; - if (nNewMinY > nMinY) - nMinY = nNewMinY; - - if (nNewMaxX < nMaxX) - nMaxX = nNewMaxX; - if (nNewMaxY < nMaxY) - nMaxY = nNewMaxY; - } - - - for (sint32 j = nMinY; j <= nMaxY; ++j) - for (sint32 i = nMinX; i <= nMaxX; ++i) - { - const string &SrcZoneName = region.getName (i,j); - - if ((SrcZoneName == STRING_OUT_OF_BOUND) || - (SrcZoneName == STRING_UNUSED)) - continue; - - string DstZoneFileName = CExport::getZoneNameFromXY (i,j); - if (withIgs) - { - cfgFile.Igs.push_back (DstZoneFileName + ".ig"); - } - cfgFile.Zones.push_back (DstZoneFileName + ".zonel"); - } - - cfgFile.ZonesPath = this->_Environnement.ExportOptions.OutZoneDir; - cfgFile.IgPath = this->_Environnement.ExportOptions.OutIGDir; - - - string sTmp = this->_Environnement.ExportOptions.TileBankFile; - string sBanksPath, sBankName; - int pos = sTmp.rfind('\\'); - for (int i = 0; i < pos; ++i) - sBanksPath += sTmp[i]; - ++i; - for (; i < (int)sTmp.size(); ++i) - sBankName += sTmp[i]; - - cfgFile.BanksPath = sBanksPath; - cfgFile.TilesPath = sBanksPath; - cfgFile.Bank = sBankName; - - - - - // - cfgFile.save (cfgFileName); - - // Launch the zviewer program - const char *exeFileName = "zviewer.exe"; - if (NLMISC::CFile::fileExists(exeFileName)) - { - _spawnl (_P_WAIT, exeFileName, "aze", NULL); - } - else - { - MessageBox((std::string("unable to find ") + exeFileName).c_str(), "WorldEditor", MB_OK | MB_ICONEXCLAMATION); - } -} -*/ - -// *************************************************************************** - -/* Old Trap End */ - -void CMainFrame::onProjectAddlandscape() -{ - CFileDialogEx dialog (BASE_REGISTRY_KEY, "land", TRUE, "land", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "NeL Ligo Landscape Files (*.land)|*.land|All Files (*.*)|*.*||", this); - if (dialog.DoModal() == IDOK) - { - // Add the landscape in the project - getDocument ()->beginModification (); - getDocument ()->addModification (new CActionAddLandscape (dialog.GetPathName())); - getDocument ()->endModification (); - - // Update data - updateData (); - - // If data direcrory is empty, auto-assign it to landscape directory - if (getDocument()->getDataDir() != "") - return; - - string path = dialog.GetPathName(); - - uint pos = path.rfind("\\"); - if (pos == string::npos) - return; - - path.erase(pos, path.size()); - getDocument()->setDataDir(path.c_str()); - - // Init the landscape - initLandscapeData(); - } -} - -// *************************************************************************** - -void CMainFrame::onProjectNewlandscape() -{ - // Add the landscape in the project - getDocument ()->beginModification (); - getDocument ()->addModification (new CActionNewLandscape ()); - getDocument ()->endModification (); - - // Update data - updateData (); -} - -// *************************************************************************** - -bool CMainFrame::initLandscapeData () -{ - // Disable events - CNoInteraction nointeraction; - - const string &dataDir = getDocument ()->getDataDir (); - - _Environnement.DataDir = dataDir; - launchLoadingDialog ("loading ligo zones"); - if (_ZoneBuilder) - delete _ZoneBuilder; - _ZoneBuilder = new CBuilderZone (theApp.Config.ZoneSnapShotRes); - _ZoneBuilder->init (dataDir, false, DispWnd); - terminateLoadingDialog(); - - // Get pointer on the document - CWorldEditorDoc *doc = getDocument (); - if (doc) - { - // For each landscape - uint count = doc->getNumDatabaseElement (); - for (uint land = 0; land < count; land++) - { - // Is a landscape - if (doc->isLandscape (land)) - { - // Get the landscape name - const string &name = doc->getDatabaseElement (land); - - launchLoadingDialog (("loading landscape " + NLMISC::CFile::getFilename (name)).c_str ()); - - // Load it - _ZoneBuilder->refresh (); - - terminateLoadingDialog(); - } - } - } - - // Reinit the tools - initTools(); - - // Release and reload pacs if needed - PacsManager.releasePacs(); - string dir; - dir = getDocument ()->getDataDir (); - if (dir == "") - { - if (_ExeDir == "") - { - dir = NLMISC::CPath::getCurrentPath(); - } - else - { - dir = _ExeDir; - } - } - dir += "/pacs"; - PacsManager.setDir(dir); - // load PACS only if they are visible - if (_ShowPACS) - { - launchLoadingDialog ("loading PACS"); - PacsManager.loadPacs(); - terminateLoadingDialog(); - } - - return true; -} - -// *************************************************************************** - -CWorldEditorDoc *CMainFrame::getDocument () -{ - return (CWorldEditorDoc *)(GetActiveDocument ()); -} - -// *************************************************************************** - -void CMainFrame::onProjectSettings() -{ - CProjectSettings projectSettings; - if (projectSettings.DoModal () == IDOK) - { - bool initLandscape = false; - - // Get the new data path - std::string oldDataDir = standardizePath (getDocument ()->getDataDir ().c_str ()); - std::string newDataDir = standardizePath (projectSettings.DataDirectory); - initLandscape |= (oldDataDir != newDataDir); - getDocument ()->setDataDir (projectSettings.DataDirectory); - - // Init the landscape - if (initLandscape) - initLandscapeData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditTransition(CCmdUI* pCmdUI) -{ - // TODO: Add your command update UI handler code here - -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditZone(CCmdUI* pCmdUI) -{ - // TODO: Add your command update UI handler code here - -} - -// *************************************************************************** - -void CMainFrame::onUpdateModeUndo(CCmdUI* pCmdUI) -{ - pCmdUI->Enable (getDocument ()->undoAvailable () ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::onUpdateModeRedo(CCmdUI* pCmdUI) -{ - pCmdUI->Enable (getDocument ()->redoAvailable () ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditLogic(CCmdUI* pCmdUI) -{ - // TODO: Add your command update UI handler code here - -} - -// *************************************************************************** - -void CMainFrame::OnProjectImportPrim() -{ - CFileDialogEx dialog (BASE_REGISTRY_KEY, "prim", TRUE, "prim", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Old NeL Ligo Prim Files (*.prim)|*.prim|All Files (*.*)|*.*||", this); - if (dialog.DoModal() == IDOK) - { - // Add the landscape in the project - getDocument ()->beginModification (); - getDocument ()->addModification (new CActionImportPrimitive (dialog.GetPathName())); - getDocument ()->endModification (); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnProjectAddPrimitive() -{ - static char buffer[32000]; - CFileDialogEx dialog (BASE_REGISTRY_KEY, "primitive", TRUE, "primitive", NULL, OFN_ALLOWMULTISELECT|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "NeL Ligo Primitive Files (*.primitive)|*.primitive|All Files (*.*)|*.*||", this); - // increase result buffer size (for multi select) - memset(buffer, 0, 32000); - dialog.m_ofn.lpstrFile = buffer; - dialog.m_ofn.nMaxFile = 32000; - if (dialog.DoModal() == IDOK) - { - // Add the landscape in the project - getDocument ()->beginModification (); - { - POSITION pos; - pos = dialog.GetStartPosition(); - - while (pos!=NULL) - { - string path = dialog.GetNextPathName(pos); - if (!getDocument()->isPrimitiveLoaded(path)) - getDocument ()->addModification (new CActionLoadPrimitive (path.c_str())); - else - infoMessage("Primitive already existing: %s", path.c_str()); - } - } - getDocument ()->endModification (); - - // Verify primitive structures - VerifyPrimitivesStructures(); - - // Update data - updateData (); - } - -} - -// *************************************************************************** - -void CMainFrame::OnProjectClearallprimitive() -{ - // Add the landscape in the project - getDocument ()->beginModification (); - getDocument ()->addModification (new CActionClearPrimitives ()); - getDocument ()->endModification (); - - // Update data - updateData (); -} - -// *************************************************************************** - -void CMainFrame::setSelectionLocked (bool lock) -{ - if (_SelectionLocked != lock) - { - CMenu *menu = GetMenu(); - _SelectionLocked = lock; - if (_SelectionLocked) - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_LOCK); - menu->CheckMenuItem (ID_EDIT_LOCK, MF_CHECKED|MF_BYCOMMAND); - } - else - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_LOCK, FALSE); - menu->CheckMenuItem (ID_EDIT_LOCK, MF_UNCHECKED|MF_BYCOMMAND); - } - - // Set the current mode - setTransformMode (_TransformModes[(uint)_SelectionLocked]); - - // Invaludate view - invalidateLeftView (); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnEditSelectAll() -{ - if (_Mode == 1) // Mode Logic - { - // Add the landscape in the project - getDocument ()->beginModification (); - getDocument ()->addModification (new CActionSelectAll ()); - getDocument ()->endModification (); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnEditLock() -{ - if (_Mode == 1) // Mode Logic - { - // Toggle lock - _SelectionLocked ^= true; - CMenu *menu = GetMenu(); - if (_SelectionLocked) - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_LOCK); - menu->CheckMenuItem (ID_EDIT_LOCK, MF_CHECKED|MF_BYCOMMAND); - } - else - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_LOCK, FALSE); - menu->CheckMenuItem (ID_EDIT_LOCK, MF_UNCHECKED|MF_BYCOMMAND); - } - - // Set the current mode - setTransformMode (_TransformModes[(uint)_SelectionLocked]); - - // Invalidate left view - invalidateLeftView (); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnEditDetails() -{ - if (_Mode == 1) // Mode Logic - { - // Toggle lock - _ShowDetails ^= true; - CMenu *menu = GetMenu(); - if (_ShowDetails) - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_DETAILS); - menu->CheckMenuItem (ID_EDIT_DETAILS, MF_CHECKED|MF_BYCOMMAND); - } - else - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_DETAILS, FALSE); - menu->CheckMenuItem (ID_EDIT_DETAILS, MF_UNCHECKED|MF_BYCOMMAND); - } - - // Invalidate left view - invalidateLeftView (); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnViewLandscape() -{ - // Toggle lock - _ShowLandscape ^= true; - CMenu *menu = GetMenu(); - if (_ShowLandscape) - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_LANDSCAPE); - menu->CheckMenuItem (ID_VIEW_LANDSCAPE, MF_CHECKED|MF_BYCOMMAND); - } - else - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_LANDSCAPE, FALSE); - menu->CheckMenuItem (ID_VIEW_LANDSCAPE, MF_UNCHECKED|MF_BYCOMMAND); - } - - // Invalidate left view - invalidateLeftView (); - - // Update data - updateData (); -} - -// *************************************************************************** - -void CMainFrame::OnViewGrid() -{ - // Toggle lock - _ShowGrid ^= true; - CMenu *menu = GetMenu(); - if (_ShowGrid) - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_GRID); - menu->CheckMenuItem (ID_VIEW_GRID, MF_CHECKED|MF_BYCOMMAND); - } - else - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_GRID, FALSE); - menu->CheckMenuItem (ID_VIEW_GRID, MF_UNCHECKED|MF_BYCOMMAND); - } - - // Invalidate left view - invalidateLeftView (); - - // Update data - updateData (); -} - -// *************************************************************************** - -void CMainFrame::OnViewPoints() -{ - // Toggle lock - _ShowPoints ^= true; - CMenu *menu = GetMenu(); - if (_ShowPoints) - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_POINTS); - menu->CheckMenuItem (ID_VIEW_POINTS, MF_CHECKED|MF_BYCOMMAND); - } - else - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_POINTS, FALSE); - menu->CheckMenuItem (ID_VIEW_POINTS, MF_UNCHECKED|MF_BYCOMMAND); - } - - // Invalidate left view - invalidateLeftView (); - - // Update data - updateData (); -} - -// *************************************************************************** - -void CMainFrame::OnViewPACS() -{ - // Toggle lock - _ShowPACS ^= true; - CMenu *menu = GetMenu(); - if (_ShowPACS) - { - // load PACS if it's not already done - if(!PacsManager.areLoaded()) - { - launchLoadingDialog ("loading PACS"); - PacsManager.loadPacs(); - terminateLoadingDialog(); - } - - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_PACS); - menu->CheckMenuItem (ID_VIEW_PACS, MF_CHECKED|MF_BYCOMMAND); - } - else - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_PACS, FALSE); - menu->CheckMenuItem (ID_VIEW_PACS, MF_UNCHECKED|MF_BYCOMMAND); - } - - // Invalidate left view - invalidateLeftView (); - - // Update data - updateData (); -} - -// *************************************************************************** - -void CMainFrame::OnViewLayers() -{ - // Toggle lock - _ShowLayers ^= true; - CMenu *menu = GetMenu(); - if (_ShowLayers) - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_LAYERS); - menu->CheckMenuItem (ID_VIEW_LAYERS, MF_CHECKED|MF_BYCOMMAND); - } - else - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_LAYERS, FALSE); - menu->CheckMenuItem (ID_VIEW_LAYERS, MF_UNCHECKED|MF_BYCOMMAND); - } - - // Invalidate left view - invalidateLeftView (); - - // Update data - updateData (); -} - -// *************************************************************************** - -void CMainFrame::OnViewPrimitives () -{ - // Toggle lock - _ShowPrimitives ^= true; - CMenu *menu = GetMenu(); - if (_ShowPrimitives) - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_PRIMITIVES); - menu->CheckMenuItem (ID_VIEW_PRIMITIVES, MF_CHECKED|MF_BYCOMMAND); - } - else - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_PRIMITIVES, FALSE); - menu->CheckMenuItem (ID_VIEW_PRIMITIVES, MF_UNCHECKED|MF_BYCOMMAND); - } - - // Invalidate left view - invalidateLeftView (); - - // Update data - updateData (); -} - -// *************************************************************************** - -void CMainFrame::OnEditTranslate() -{ - setTransformMode (Move); -} - -// *************************************************************************** - -void CMainFrame::OnEditRotate() -{ - setTransformMode (Rotate); -} - -// *************************************************************************** - -void CMainFrame::OnEditTurn() -{ - setTransformMode (Turn); -} - -// *************************************************************************** - -void CMainFrame::OnEditRadius() -{ - setTransformMode (Radius); -} - -// *************************************************************************** - -void CMainFrame::OnEditScale() -{ - setTransformMode (Scale); -} - -// *************************************************************************** - -void CMainFrame::OnEditAddPoint() -{ - setTransformMode (AddPoint); -} - -// *************************************************************************** - -void CMainFrame::OnEditSelect() -{ - setTransformMode (Select); -} - -// *************************************************************************** - -void CMainFrame::setTransformMode (TTransformMode mode) -{ - CMenu *menu = GetMenu(); - menu->CheckMenuRadioItem( ID_EDIT_SELECT, ID_EDIT_ADD_POINT, ID_EDIT_SELECT+mode, MF_BYCOMMAND); - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_SELECT+mode); - - _TransformModes[(uint)_SelectionLocked] = mode; -} - -// *************************************************************************** - -void CMainFrame::deletePrimitive (bool subDelete, const char *actionName) -{ - list oldSelection; - - list::iterator it = PropertiesDialogs.begin(); - while ( it != PropertiesDialogs.end() ) - { - bool closeDialog = false; - if ( (*it)->containsSelection( Selection ) ) - { - closeDialog = (*it)->removePrimitives( Selection ); - } - - if ( closeDialog ) - it = PropertiesDialogs.begin(); // iterator became invalid - else - it++; - } - - // Get pointer on the document - CWorldEditorDoc *doc = getDocument (); - - // Begin modification - doc->beginModification (); - - if (_Mode == 1) // Mode Logic - { - // Next primitive to select - bool locatorValid = false; - CDatabaseLocatorPointer locatorNext; - - // Delete - if (subDelete) - { - // For all the selection - list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Point primitive ? - const CPrimPointEditor *point = dynamic_cast (locator.Primitive); - if (point) - { - } - else - { - // Path - const CPrimPathEditor *path = dynamic_cast (locator.Primitive); - const CPrimZoneEditor *zone = dynamic_cast (locator.Primitive); - if (path || zone) - { - while (1) - { - // Get the good primitive - const IPrimitive *primitive = (const IPrimitive *)path ? (const IPrimitive *)path : (const IPrimitive *)zone; - uint count = primitive->getNumVector (); - if (count) - { - const CPrimVector *primVector = primitive->getPrimVector (); - uint i; - for (i=0; iaddModification (new CActionDeleteSub (locator)); - break; - } - } - - // Done ? - if (i == count) - { - break; - } - } - else - break; - } - } - } - - ite++; - } - } - else - { - // For all the selection - list::iterator ite; - ite = Selection.begin (); - while (ite != Selection.end ()) - { - bool deleted = false; - - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Node or prim file ? - if (locator.Primitive->getParent ()) - { - // Primitive deletable ? - if (theApp.Config.isPrimitiveDeletable (*(locator.Primitive))) - { - // Select the next primitive after delete - CDatabaseLocatorPointer locatorNext2 = locator; - if (locatorNext2.nextChild ()) - locatorNext = locator; - else - { - // Get previous node - locatorNext2 = locator; - locatorNext2.previousChild (); - locatorNext = locatorNext2; - } - locatorValid = true; - - doc->addModification (new CActionDelete (locator)); - deleted = true; - } - } - else - { - // Editable ? - uint index = locator.getDatabaseIndex (); - if (doc->_DataHierarchy[index].Editable) - { - // Select the next primitive after delete - locatorValid = false; - - doc->addModification (new CActionDeleteDatabaseElement (locator.getDatabaseIndex ())); - deleted = true; - } - } - - // Update selection, restart to the beginning - if (deleted) - { - UpdateSelection (); - ite = Selection.begin (); - } - else - ite++; - } - } - - // Select a new primitive ? - if (locatorValid) - doc->addModification (new CActionSelect (locatorNext)); - } - - // End modification - doc->endModification (); - - // Update data - updateData (); -} - -// *************************************************************************** - -void CMainFrame::OnEditDelete() -{ - deletePrimitive (isSelectionLocked (), "Delete"); -} - -// *************************************************************************** - -void CMainFrame::OnProjectNewPrimitive() -{ - // Get pointer on the document - CWorldEditorDoc *doc = getDocument (); - - // Add the landscape in the project - doc->beginModification (); - doc->addModification (new CActionNewPrimitive ()); - - // Select it - doc->addModification (new CActionUnselectAll ()); - - // Locator - CDatabaseLocatorPointer locator; - locator.getRoot (doc->getNumDatabaseElement ()-1); - doc->addModification (new CActionSelect (locator)); - - doc->endModification (); - - // Update data - updateData (); -} - -// *************************************************************************** - -void CMainFrame::OnEditProperties() -{ - list::iterator it = PropertiesDialogs.begin(); - bool ok = false; - ::CRect dlgPos(0, 0, 0, 0); - - while ( !ok && ( it != PropertiesDialogs.end() ) ) - { - if ( (*it)->equalsSelection( Selection ) ) - { - (*it)->ShowWindow( SW_SHOW ); - (*it)->SetFocus(); - - ok = true; - } - - it++; - } - - if ( !ok ) - { - CDialogProperties *pDlg = new CDialogProperties( Selection ); - pDlg->Create( IDD_PROPERTIES ); - - pDlg->GetWindowRect( &dlgPos ); - - CPoint point = CDialogProperties::getLastPosition(); - - if ( point != CPoint(-1, -1) ) - { - int diffX = point.x - dlgPos.left; - int diffY = point.y - dlgPos.top; - dlgPos.OffsetRect( diffX, diffY ); - - pDlg->MoveWindow( &dlgPos ); - } - - pDlg->ShowWindow( SW_SHOW ); - pDlg->SetFocus(); - - PropertiesDialogs.push_back( pDlg ); - } -} - -// *************************************************************************** - -void CMainFrame::OnAddPrimitive (UINT nID) -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Begin modification - doc->beginModification (); - - // Only one selection ? - nlassert (Selection.size () == 1); - nlassert (Selection.front ()); - - // What class is it ? - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*(Selection.front ())); - nlassert (primClass); - uint childId = nID - ID_EDIT_CREATE_BEGIN; - - // Get the child class - CDatabaseLocatorPointer insert; - doc->getLocator (insert, Selection.front ()); - CDatabaseLocator dest; - insert.appendChild (dest); - - // Position on the Display - CDisplay *display = getDisplay (); - float delta = (float)DELTA_POS_ADD_PRIMITIVE * (display->_CurViewMax.x - display->_CurViewMin.x) / (float)display->getWidth (); - if (doc->addModification (new CActionAddPrimitiveByClass (dest, primClass->DynamicChildren[childId].ClassName.c_str (), getDisplay ()->_CurPos, - delta, primClass->DynamicChildren[childId].Parameters))) - { - // Unselect all - doc->addModification (new CActionUnselectAll ()); - - // Select it - doc->addModification (new CActionSelect (dest)); - } - - // End modification - doc->endModification (); - - // Update the data - updateData (); -} - -// *************************************************************************** - -void CMainFrame::OnGeneratePrimitive (UINT nID) -{ - // Disable events - CNoInteraction nointeraction; - - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Begin modification - doc->beginModification (); - - // Primitive generator - CGeneratePrimitive generatePrimitive; - - // Load in primitive - if (!Selection.empty ()) - { - // Progress bar - CWorldEditorProgressCallback callback; - - // In / out primitives - std::vector< std::vector > out; - std::vector in; - - // Add primitives - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - in.push_back (locator.Primitive); - ite++; - } - - // What class is it ? - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*(Selection.front ())); - nlassert (primClass); - - // Should exist - nlassert ( (nID - ID_EDIT_GENERATE_BEGIN) < primClass->GeneratedChildren.size ()); - - // Generate it - if (generatePrimitive.generate (out, in, callback, theApp.Config, doc->getDataDir ().c_str (), - primClass->GeneratedChildren[nID-ID_EDIT_GENERATE_BEGIN].ClassName.c_str () )) - { - // Checks - nlassert (out.size () == Selection.size ()); - - // Add primitives - uint i=0; - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - for (uint j=0;jaddModification (new CActionAddPrimitive (out[i][j], newLocator)); - } - - ite++; - i++; - } - } - } - - // End modification - doc->endModification (); - - // Update the data - updateData (); -} - -// *************************************************************************** - -void CMainFrame::buildFilenameVector (const IPrimitive &primitive, std::vector &dest) -{ - // What class is it ? - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (primitive); - nlassert (primClass); - - // Look for files - uint i; - for (i=0; iParameters.size (); i++) - { - // File ? - if (primClass->Parameters[i].Filename) - { - // Exist ? - string name; - if (primitive.getPropertyByName (primClass->Parameters[i].Name.c_str (), name) && !name.empty ()) - { - // Add the file - string ext; - - // Build an extension - if (!primClass->Parameters[i].FileExtension.empty ()) - ext = "."+primClass->Parameters[i].FileExtension; - - // Lookup - string filename = name+ext; - if (primClass->Parameters[i].Lookup) - filename = CPath::lookup (filename, false, false, false); - if (!filename.empty ()) - { - dest.push_back (filename); - } - } - } - } -} - -// *************************************************************************** - -void CMainFrame::OnOpenFile (UINT nID) -{ - // Single selection - nlassert (Selection.size () == 1); - - // Good id - nID -= ID_EDIT_OPEN_FILE_BEGIN; - - // Filenames - std::vector files; - buildFilenameVector (*Selection.front (), files); - - // File name must exist - nlassert (nIDCreatePopupMenu (); - - // Tranform mode ? - if (transformMode) - { - if (_Mode == 1) - { - // Add commands - pMenu->AppendMenu (MF_STRING, ID_EDIT_SELECT, "&Select\tF5"); - pMenu->AppendMenu (MF_STRING, ID_EDIT_TRANSLATE, "&Move\tF6"); - pMenu->AppendMenu (MF_STRING, ID_EDIT_ROTATE, "&Rotate\tF7"); - pMenu->AppendMenu (MF_STRING, ID_EDIT_TURN, "&Turn\tF8"); - pMenu->AppendMenu (MF_STRING, ID_EDIT_SCALE, "&Scale\tF9"); - pMenu->AppendMenu (MF_STRING, ID_EDIT_RADIUS, "&Radius\tF10"); - if (isSelectionLocked ()) - pMenu->AppendMenu (MF_STRING, ID_EDIT_ADD_POINT, "&Add points\tF11"); - - // Check the good one - pMenu->CheckMenuRadioItem (ID_EDIT_SELECT, isSelectionLocked ()?ID_EDIT_ADD_POINT:ID_EDIT_SCALE, ID_EDIT_SELECT+getTransformMode (), - MF_BYCOMMAND); - - // Add separator - pMenu->AppendMenu (MF_SEPARATOR); - } - } - - // Always a delete menu - pMenu->AppendMenu (MF_STRING, ID_EDIT_DELETE, "&Delete\tDel"); - - // Add properties menu - pMenu->AppendMenu (MF_STRING, ID_EDIT_PROPERTIES, "&Properties\tAlt+Enter"); - - // Select Children - pMenu->AppendMenu (MF_STRING, ID_EDIT_SELECT_CHILDREN, "&Select Children\tC"); - - // Tree help - pMenu->AppendMenu (MF_STRING, ID_HELP_FINDER, "&Help\tF1"); - - // Add separator - pMenu->AppendMenu (MF_SEPARATOR); - pMenu->AppendMenu (MF_STRING, ID_RENAME_SELECTED, "&Rename All Selected"); - pMenu->AppendMenu (MF_STRING, ID_REPAIR_SELECTED, "&Repair All Selected"); - - // Add separator - pMenu->AppendMenu (MF_SEPARATOR); - - // Add properties menu - pMenu->AppendMenu (MF_STRING, ID_VIEW_SHOW, "&Show\tS"); - pMenu->AppendMenu (MF_STRING, ID_VIEW_HIDE, "&Hide\tH"); - - // Add separator - pMenu->AppendMenu (MF_SEPARATOR); - - // Add expand / collapse menu - pMenu->AppendMenu (MF_STRING, ID_EDIT_EXPAND, "&Expand\tE"); - pMenu->AppendMenu (MF_STRING, ID_EDIT_COLLAPSE, "&Collapse\tR"); - - // Only one selection ? - if (Selection.size () == 1) - { - // Primitive ? - if (Selection.front ()) - { - // What class is it ? - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*(Selection.front ())); - if (primClass && primClass->DynamicChildren.size ()) - { - // Add separator - pMenu->AppendMenu (MF_SEPARATOR); - - // For each child, add a create method - for (uint i=0; iDynamicChildren.size (); i++) - { - pMenu->AppendMenu (MF_STRING, ID_EDIT_CREATE_BEGIN+i, ("Add "+primClass->DynamicChildren[i].ClassName).c_str ()); - } - } - - // What class is it ? - if (primClass && primClass->GeneratedChildren.size ()) - { - // Add separator - pMenu->AppendMenu (MF_SEPARATOR); - - // For each child, add a create method - for (uint i=0; iGeneratedChildren.size (); i++) - { - pMenu->AppendMenu (MF_STRING, ID_EDIT_GENERATE_BEGIN+i, ("Generate "+primClass->GeneratedChildren[i].ClassName).c_str ()); - } - } - - // What class is it ? - if (primClass) - { - // Look for files - vector filenames; - - // Filenames - buildFilenameVector (*Selection.front (), filenames); - - // File names ? - if (!filenames.empty ()) - { - // Add separator - pMenu->AppendMenu (MF_SEPARATOR); - - // Found ? - uint i; - for (i=0; iAppendMenu (MF_STRING, ID_EDIT_OPEN_FILE_BEGIN+i, ("Open "+NLMISC::CFile::getFilename (filenames[i])).c_str ()); - } - } - } - } - } - - pMenu->TrackPopupMenu (TPM_LEFTALIGN | TPM_LEFTBUTTON, point.x, point.y, parent); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditAddPoint(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ((_SelectionLocked && (_Mode==1)) ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditLock(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditProperties(CCmdUI* pCmdUI) -{ - pCmdUI->Enable (isInteraction () && (_Mode==1) ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditRotate(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditScale(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditSelectAll(CCmdUI* pCmdUI) -{ - pCmdUI->Enable (isInteraction () && (_Mode==1) ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditTranslate(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditTurn(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditRadius(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditSelect(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditDetails(CCmdUI* pCmdUI) -{ -} - -// *************************************************************************** - -void CMainFrame::OnUpdateViewLandscape(CCmdUI* pCmdUI) -{ -} - -// *************************************************************************** - -void CMainFrame::deletePrimitiveClipboard () -{ - // Delete each clipboard entry - for (uint i=0; i<_PrimitiveClipboard.size (); i++) - delete _PrimitiveClipboard[i]; - _PrimitiveClipboard.clear (); -} - -// *************************************************************************** - -void CMainFrame::OnEditCopy() -{ - // Only if one node selected - if (!Selection.empty ()) - { - // Free the clipboard - deletePrimitiveClipboard (); - - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Add primitives - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Copy it - _PrimitiveClipboard.push_back (locator.Primitive->copy ()); - - // Unselect it - getPrimitiveEditor(_PrimitiveClipboard.back ())->setSelected(false); -// _PrimitiveClipboard.back ()->removePropertyByName ("selected"); - - ite++; - } - - // Update data - updateData (); - } -} -// *************************************************************************** - -void CMainFrame::OnEditCut() -{ - // Only if one node selected - if (!Selection.empty ()) - { - // Copy - OnEditCopy(); - - // Delete - deletePrimitive (false, "Cut"); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditCopy(CCmdUI* pCmdUI) -{ - // Something selected ? - pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) -{ - // Something selected ? - pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); -} - -// *************************************************************************** - -void CMainFrame::OnEditPaste() -{ - // Only if one node selected - if ((!Selection.empty ()) && (!_PrimitiveClipboard.empty ())) - { - // Get the document - CWorldEditorDoc *doc = getDocument (); - sint lastChildPos = -1; // position of the last child of the selection - - // Begin modification - doc->beginModification (); - - for (uint i=0; i<_PrimitiveClipboard.size (); i++) - { - // Paste it ? - CDatabaseLocatorPointer locator; - bool paste = false; - - // Is this a root ? - if (Selection.front ()->getParent ()) - { - // Try to add it as children of the selection - if (theApp.Config.canBeChild (*(_PrimitiveClipboard[i]), *(Selection.front ()))) - { - // Get last children index (before insertion) - if ( lastChildPos == -1 ) - lastChildPos = Selection.front()->getNumChildren()-1; - - if ( lastChildPos >= 0 ) - { - IPrimitive* prim; - Selection.front()->getChild( prim, lastChildPos ); - doc->getLocator ( locator, prim ); - - if ( ! locator.nextChild() ) - locator.appendChild ( locator ); - } - else - { - doc->getLocator ( locator, Selection.front() ); - locator.appendChild ( locator ); - } - - - paste = true; - } - else - { - // Can be a child ? - if (theApp.Config.canBeChild (*(_PrimitiveClipboard[i]), *(Selection.front ()->getParent ()))) - { - // Paste after this locator - doc->getLocator ( locator, Selection.front() ); - if ( !locator.nextChild () ) - locator.appendChild ( locator ); - paste = true; - } - } - } - else - { - // Try to add it as children of the selection - if (theApp.Config.canBeRoot (*(_PrimitiveClipboard[i]))) - { - // Get first children - doc->getLocator (locator, Selection.front ()); - locator.appendChild (locator); - paste = true; - } - } - - // Paste it ? - if (paste) - { - // Add the primitive - doc->addModification (new CActionAddPrimitive (*(_PrimitiveClipboard[i]), locator)); - - // New locator - CDatabaseLocator newLocator = locator; - doc->getLocator (locator, newLocator); - - // Change its name - string name; - if (locator.Primitive->getPropertyByName ("name", name)) - { - // Get children count - if (locator.Primitive->getParent ()) - { - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*locator.Primitive); - if ((primClass == NULL) || primClass->Numberize) - { - // Set the number to the number of brothers (-1 because the node has just been created) - name = numberize (name.c_str (), locator.Primitive->getParent ()->getNumChildren ()); - - // Change the name - doc->addModification (new CActionSetPrimitivePropertyString (locator, "name", name.c_str (), false)); - } - } - } - } - else - { - // special case. - if ( _PrimitiveClipboard[i] - && _PrimitiveClipboard[i]->getClassName()=="CPrimZone" - && Selection.front () - && Selection.front ()->getClassName()=="CPrimZone" - && Selection.front ()->getParent() ) - { - // Get the child class - CDatabaseLocatorPointer insert; - doc->getLocator (insert, Selection.front ()->getParent()); - CDatabaseLocator dest; - insert.appendChild (dest); - - // Position on the Display - CDisplay *display = getDisplay (); - float delta = (float)DELTA_POS_ADD_PRIMITIVE * (display->_CurViewMax.x - display->_CurViewMin.x) / (float)display->getWidth (); - - string className; - if (Selection.front ()->getPropertyByName ("class", className)) - { - std::vector empty; - doc->addModification (new CActionAddPrimitiveByClass (dest, className.c_str (), getDisplay ()->_CurPos, - delta, empty)); - } - - // Now copy the shape .. - sint nbVert=_PrimitiveClipboard[i]->getNumVector(); - const CPrimVector *vectors = _PrimitiveClipboard[i]->getPrimVector (); - for (sint j=nbVert-1; j>=0; j--) - doc->addModification (new CActionAddVertex(dest, vectors[j])); - } - - } - - } - - // Begin modification - doc->endModification (); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditPaste(CCmdUI* pCmdUI) -{ - // Only if one node selected and clipboard not empty - pCmdUI->Enable (isInteraction () && ((!Selection.empty()) && (!_PrimitiveClipboard.empty ())) ? TRUE : FALSE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateViewHide(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); -} - -// *************************************************************************** - -void CMainFrame::OnViewHide() -{ - // Only if one node selected - if (!Selection.empty ()) - { - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Begin modifications - doc->beginModification (); - - // Copy selected primitives - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Add the modification - doc->addModification (new CActionShowHide (locator, false)); - - ite++; - } - - // End modifications - doc->endModification (); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnViewShow() -{ - // Only if one node selected - if (!Selection.empty ()) - { - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Begin modifications - doc->beginModification (); - - // Copy selected primitives - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Add the modification - doc->addModification (new CActionShowHide (locator, true)); - - ite++; - } - - // End modifications - doc->endModification (); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnEditExpand() -{ - // Only if one node selected - if (!Selection.empty ()) - { - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Copy selected primitives - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Add the modification - getPrimitiveEditor(locator.Primitive)->setExpanded(true); -// locator.Primitive-> -// const_cast (locator.Primitive)->Expanded = true; - InvalidatePrimitiveRec (locator, LogicTreeStruct); - - ite++; - } - - // Invalidate tools - invalidateTools (); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnEditCollapse() -{ - // Only if one node selected - if (!Selection.empty ()) - { - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Copy selected primitives - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Add the modification - getPrimitiveEditor(locator.Primitive)->setExpanded(false); -// const_cast (locator.Primitive)->Expanded = false; - InvalidatePrimitiveRec (locator, LogicTreeStruct); - - ite++; - } - - // Invalidate tools - invalidateTools (); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnUpdateViewShow (CCmdUI* pCmdUI) -{ - pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditExpand (CCmdUI* pCmdUI) -{ - pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditCollapse (CCmdUI* pCmdUI) -{ - pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); -} - -// *************************************************************************** - -void selectChildren (CWorldEditorDoc *doc, const CDatabaseLocatorPointer &locator) -{ - // Fopr each children - CDatabaseLocatorPointer myLocator = locator; - if (myLocator.firstChild ()) - { - do - { - // Select it - doc->addModification (new CActionSelect (myLocator)); - - // Select its children - selectChildren (doc, myLocator); - } - while (myLocator.nextChild ()); - } -} - -// *************************************************************************** - -void CMainFrame::OnEditSelectChildren() -{ - // Only if one node selected - if (!Selection.empty ()) - { - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Begin modifications - doc->beginModification (); - - // Unselect all - doc->addModification (new CActionUnselectAll ()); - - // Copy selected primitives - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite); - - // Select children - selectChildren (doc, locator); - - ite++; - } - - // End modifications - doc->endModification (); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditSelectChildren(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); -} - -// *************************************************************************** - -void CMainFrame::OnTimer(UINT nIDEvent) -{ - if (nIDEvent == TIMER_UPDATE_FILES) - { - if (TimerEnabled) - { - TimerEnabled = false; - // Check file modification - getDocument ()->updateFiles (); - TimerEnabled = true; - } - } - if (nIDEvent == TIMER_PLUGINS) - { - for (uint i=0; ionIdle(); - } - // check if plugin querried to refresh the property dialog - if (_MustRefreshPropertyDialog) - { - std::list::iterator it = PropertiesDialogs.begin(); - - while ( it != PropertiesDialogs.end() ) - { - (*it)->updateModification(); - it++; - } - - //PropertyDialog.changeSelection (Selection); - _MustRefreshPropertyDialog = false; - } - } - CFrameWnd::OnTimer(nIDEvent); -} - -// *************************************************************************** - -void CMainFrame::OnHelpFinder() -{ - if (Selection.size () == 1) - { - CWorldEditorDoc *doc = getDocument (); - - // For each selected primitives - std::list::iterator ite1 = Selection.begin (); - - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite1); - - const IPrimitive *primitive = locator.Primitive; - if (primitive) - { - string className; - bool Success; - Success = primitive->getPropertyByName ("class", className); - if (!Success) - { - // is this the root node ? - const IPrimitive *parent = primitive->getParent(); - if (!parent) - { - // if no parent, we have a root node - className = "root"; - Success = true; - } - } - if (Success) - { - //string filename = theApp.ExePath+"doc/"+className+".html"; - string filename = theApp.DocPath+"/"+className+".html"; - if (!NLMISC::CFile::fileExists(filename) || !openFile (filename.c_str ())) - { - //openFile ((theApp.ExePath+"world_editor.html").c_str ()); - theApp.errorMessage ("Can't open the file %s", filename.c_str ()); - } - } - } - } - else - { - openFile ((theApp.ExePath+"world_editor.html").c_str ()); - } -} - -// *************************************************************************** - -void CMainFrame::interaction (bool enable) -{ - CDisplay *display = getDisplay (); - if (display) - display->Interactif = enable; -} - -// *************************************************************************** - -bool CMainFrame::isInteraction () const -{ - CDisplay *display = getDisplay (); - if (display) - return display->Interactif; - else - return false; -} - -// *************************************************************************** -// CWorldEditorProgressCallback -// *************************************************************************** - -CWorldEditorProgressCallback::CWorldEditorProgressCallback () -{ - getMainFrame ()->launchLoadingDialog (""); -} - -// *************************************************************************** - -CWorldEditorProgressCallback::~CWorldEditorProgressCallback () -{ - getMainFrame ()->terminateLoadingDialog (); -} - -// *************************************************************************** - -void CWorldEditorProgressCallback::progress (float value) -{ - getMainFrame ()->LoadingDialog->setText (this->DisplayString); - getMainFrame ()->progressLoadingDialog (value); -} - -// *************************************************************************** - -void CMainFrame::OnViewLocateselectedprimitives() -{ - // Not empty ? - if (!Selection.empty ()) - { - // Selection bbox - CAABBox box; - bool first = true; - - // For each selected primitives - std::list::iterator ite = Selection.begin (); - while (ite != Selection.end ()) - { - // Extend - uint vertices = (*ite)->getNumVector (); - if (vertices) - { - uint i; - const CPrimVector *v = (*ite)->getPrimVector (); - for (i=0; isetDisplayRegion (box.getMin (), box.getMax ()); - - // Add a border - CVector locateBorder (0, 0, 0); - CVector locateBorder2 (LOCATE_BORDER, LOCATE_BORDER, 0); - getDisplay ()->pixelToWorld (locateBorder); - getDisplay ()->pixelToWorld (locateBorder2); - locateBorder = locateBorder2 - locateBorder; - getDisplay ()->setDisplayRegion (box.getMin ()-locateBorder, box.getMax ()+locateBorder); - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnUpdateViewLocateselectedprimitives(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); -} - -// *************************************************************************** - -void CMainFrame::OnViewLocateselectedprimitivesTree() -{ - if (!Selection.empty ()) - { - CToolsLogic *const toolWnd = dynamic_cast(getMainFrame ()->m_wndSplitter.GetPane(0,1)); - if (toolWnd) - { - for (std::list::iterator it=Selection.begin(),itEnd=Selection.end();it!=itEnd;++it) - { - IPrimitiveEditor *const primEditor = dynamic_cast (*it); - toolWnd->ensureVisible (primEditor); - } - } - } -} - -// *************************************************************************** - -void CMainFrame::OnUpdateViewLocateselectedprimitivesTree(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); -} - -// *************************************************************************** - -void CMainFrame::OnEditSelectByLocation() -{ - // Only in primitive mode - if ( (_Mode==1) && !isSelectionLocked () ) - { - // Selection dialog - static CSelectByLocation select; - uint mode; - switch (mode=select.DoModal ()) - { - case IDOK: - case IDMORE: - { - // Begin modification - CWorldEditorDoc *doc = getDocument (); - doc->beginModification (); - - // Unselect others primitives ? - if (mode == IDOK) - doc->addModification (new CActionUnselectAll ()); - - // Make a bbox - const float threshold = (float) fabs (select.Threshold); - CVector min = CVector (select.X - threshold, select.Y - threshold, 0); - CVector max = CVector (select.X + threshold, select.Y + threshold, 0); - - // Get the locator - std::vector result; - getDisplay ()->pickRect (min, max, result, false); - - // Parse - uint i; - for (i=0; iaddModification (new CActionSelect (result[i])); - } - - // End modification - doc->endModification (); - } - } - - // Update data - updateData (); - } -} - -// *************************************************************************** - -void CMainFrame::OnUpdateEditSelectByLocation(CCmdUI* pCmdUI) -{ - pCmdUI->Enable ( (isInteraction () && (_Mode == 1)) ? TRUE : FALSE ); -} - -// *************************************************************************** - -void CMainFrame::OnProjectResetuniqueid() -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Begin modifications - doc->beginModification (); - - uint count = doc->getNumDatabaseElement (); - uint i; - for (i=0; iisPrimitive (i)) - { - const NLLIGO::CPrimitives &primitive = doc->getDatabaseElements (i); - doc->resetUniqueID (*primitive.RootNode); - } - } - - // End modifications - doc->endModification (); -} - -// *************************************************************************** - -void CMainFrame::OnProjectGeneratenullid() -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Begin modifications - doc->beginModification (); - - uint count = doc->getNumDatabaseElement (); - uint i; - for (i=0; iisPrimitive (i)) - { - const NLLIGO::CPrimitives &primitive = doc->getDatabaseElements (i); - doc->resetUniqueID (*primitive.RootNode, true); - } - } - - // End modifications - doc->endModification (); - -} - -// *************************************************************************** - -void CMainFrame::OnProjectForceiduniqueness() -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Begin modifications - doc->beginModification (); - - CHashSet ids; - std::vector nonUnique; -// uint32 regenCount = 0; - - uint count = doc->getNumDatabaseElement (); - uint i; - - // the operation is done in two step to avoid the assignation of already - // assigned ID to the first non unique ID found, generating more non - // unique ID when the loop reach the other primitives. - - // first loop to collect non properties with non unique ID - for (i=0; iisPrimitive (i)) - { - const NLLIGO::CPrimitives &primitive = doc->getDatabaseElements (i); - doc->forceIDUniqueness(*primitive.RootNode, ids, nonUnique); -// doc->forceIDUniqueness(*primitive.RootNode, ids, regenCount); - } - } - - // second loop to regen the non unique IDs - for (uint i=0; iParameters.size(); ++j) - { - if (_class->Parameters[j].Name == nu.PropertyName) - { - if (_class->Parameters[j].Type == CPrimitiveClass::CParameter::String) - { - CDatabaseLocatorPointer locator; - doc->getLocator(locator, nu.Primitive); - - doc->addModification (new CActionSetPrimitivePropertyString (locator, nu.PropertyName.c_str (), toString (getUniqueId ()).c_str (), false)); - } - else if (_class->Parameters[j].Type == CPrimitiveClass::CParameter::StringArray) - { - uint k; - for (k=0; j<_class->Parameters[j].DefaultValue.size (); j++) - { - // Unique Id ? - if (_class->Parameters[j].DefaultValue[k].GenID) - { - std::vector result; - std::vector *resultPtr = NULL; - nu.Primitive->getPropertyByName (nu.PropertyName.c_str (), resultPtr); - - // Copy - if (resultPtr) - result = *resultPtr; - - // Resize - if (result.size ()<=k) - result.resize (k+1); - - // Set the value - result[k] = toString (getUniqueId ()); - - CDatabaseLocatorPointer locator; - doc->getLocator (locator, nu.Primitive); - doc->addModification (new CActionSetPrimitivePropertyStringArray (locator, nu.PropertyName.c_str (), result, false)); - } - } - } - break; - } - } - } - } - - // End modifications - doc->endModification (); - - AfxMessageBox(NLMISC::toString("%u ids checked, %u non unique ID regenerated", ids.size()+nonUnique.size(), nonUnique.size()).c_str(), MB_OK); -} - -// *************************************************************************** - -void CMainFrame::OnEditFind () -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - if (doc->getNumDatabaseElement ()) - { - // Find dialog -#if 0 - CFindPrimitiveDlg dlg; - dlg.DoModal (); -#else - if (!m_FindPrimitiveDlg) - m_FindPrimitiveDlg = new CFindPrimitiveDlg; - - if (!::IsWindow(m_FindPrimitiveDlg->GetSafeHwnd())) - m_FindPrimitiveDlg->Create(IDD_FIND_PRIMITIVE, this); - - m_FindPrimitiveDlg->ShowWindow(SW_SHOW); -#endif - } -} - - -// *************************************************************************** - -void CMainFrame::OnEditGoto () -{ - // goto dialog - - m_GotoDlg.DoModal(); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateFind(CCmdUI* pCmdUI) -{ - CWorldEditorDoc *doc = getDocument (); - pCmdUI->Enable ( (isInteraction () && (_Mode == 1) && doc->getNumDatabaseElement ()) ? TRUE : FALSE ); -} - -// *************************************************************************** - -void CMainFrame::OnViewCollisions() -{ - // Toggle Collisions View - _ShowCollisions ^= true; - CMenu *menu = GetMenu(); - if (_ShowCollisions) - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_COLLISIONS); - menu->CheckMenuItem (ID_VIEW_COLLISIONS, MF_CHECKED|MF_BYCOMMAND); - } - else - { - // Update UI - m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_COLLISIONS, FALSE); - menu->CheckMenuItem (ID_VIEW_COLLISIONS, MF_UNCHECKED|MF_BYCOMMAND); - } - - // Invalidate left view - invalidateLeftView (); - - // Update data - updateData (); -} - -// *************************************************************************** - -// routines for the plugin -NLLIGO::IPrimitive *CMainFrame::createRootPluginPrimitive (const char *name) -{ - AFX_MANAGE_STATE(AfxGetAppModuleState()); - - // Add the landscape in the project - CWorldEditorDoc *doc = getDocument (); - - // Push back the primitive - doc->_DataHierarchy.push_back (CWorldEditorDoc::CDatabaseElement (CWorldEditorDoc::CDatabaseElement::Primitive)); - - // This primitive is not editable - doc->_DataHierarchy.back().Editable = false; - doc->_DataHierarchy.back().Filename = name; - - doc->_DataHierarchy.recomputePointerArray (); - - // Invalidate tools - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); - - // Modify files - uint index = doc->_DataHierarchy.size ()-1; - doc->modifyDatabase (index); - - // Update data - updateData (); - - return doc->_DataHierarchy[index].Primitives.RootNode; -} - -// *************************************************************************** - -void CMainFrame::deleteRootPluginPrimitive (void) -{ - -} - -// *************************************************************************** -void CMainFrame::getAllRootPluginPrimitive (std::vector &prims) -{ - AFX_MANAGE_STATE(AfxGetAppModuleState()); - - prims.clear(); - - // Add the landscape in the project - CWorldEditorDoc *doc = getDocument (); - nlassert(doc); - - // For all editable primitive only - for (uint j=0; j_DataHierarchy.size(); ++j) - { - if (doc->_DataHierarchy[j].Editable) - { - if (doc->_DataHierarchy[j].Type == CWorldEditorDoc::CDatabaseElement::Primitive) - prims.push_back(doc->_DataHierarchy[j].Primitives.RootNode); - } - } - -} - -// *************************************************************************** - -const NLLIGO::IPrimitive *CMainFrame::createPluginPrimitive -( - const char *className, - const char *primName, - const NLMISC::CVector &initPos, - float deltaPos, - const std::vector &initParameters, - NLLIGO::IPrimitive *parent - ) -{ - AFX_MANAGE_STATE(AfxGetAppModuleState()); - CWorldEditorDoc *doc = getDocument (); - - // What class is it ? - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass(className); - if (primClass) - { - // Begin modification - nlassert (primClass); - - // Get the child class - CDatabaseLocatorPointer insert; - doc->getLocator (insert, parent); - - // Locator for the child - CDatabaseLocator child; - insert.appendChild (child); - - // Get the class primitive - IPrimitive *primitive = const_cast (doc->createPrimitive (child, className, "", initPos, deltaPos, initParameters)); - if (primitive != NULL) - { - // Invalidate left view - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Modify files - doc->modifyDatabase (child.getDatabaseIndex ()); - - // Get a pointer on the new primitive - primitive->removePropertyByName ("name"); - primitive->addPropertyByName ("name",new CPropertyString (primName)); - - // Invalidate quad grid - CDatabaseLocatorPointer childPtr; - doc->getLocator (childPtr, child); - InvalidatePrimitiveRec (childPtr, QuadTree|LogicTreeStruct|SelectionState); - } - - // Update the data - updateData (); - return primitive; - } - else - return NULL; -} - -// *************************************************************************** - -// delete a plugin primitive -void CMainFrame::deletePluginPrimitive (const NLLIGO::IPrimitive *primitive) -{ - AFX_MANAGE_STATE(AfxGetAppModuleState()); - // Get the parent - IPrimitive *parent = const_cast(primitive)->getParent (); - nlassert (parent); - - // Get the child id - uint childId; - nlverify (parent->getChildId (childId, primitive)); - - // Delete the child - nlverify (parent->removeChild (childId)); - invalidateLeftView (); -} - -// *************************************************************************** - -// indicates to the WorldEditor that the primitive has changed -void CMainFrame::invalidatePluginPrimitive (const NLLIGO::IPrimitive *primitive, uint channels) -{ - AFX_MANAGE_STATE(AfxGetAppModuleState()); - if (primitive) - { - IPrimitiveEditor *primitiveEditor = dynamic_cast (const_cast (primitive)); - - // No, link it - if (primitiveEditor->_ModifiedIterator == ModifiedPrimitive.end ()) - { - ModifiedPrimitive.push_front (const_cast (primitive)); - primitiveEditor->_ModifiedIterator = ModifiedPrimitive.begin (); - } - - // Add the channel flags - primitiveEditor->_Channels |= channels; - } - if (channels | QuadTree) - { - invalidateLeftView (); - } -} - -// *************************************************************************** -void CMainFrame::invalidateLeftView() -{ - AFX_MANAGE_STATE(AfxGetAppModuleState()); - ::invalidateLeftView(); -} - -// *************************************************************************** - -// indicates to the WorldEditor that the primitive has changed -void CMainFrame::getWindowCoordinates(NLMISC::CVector &vmin, NLMISC::CVector &vmax) -{ - vmin = DispWnd->_CurViewMin; - vmax = DispWnd->_CurViewMax; -} - -// *************************************************************************** - -void CMainFrame::OnHelpHistory() -{ - string filename = theApp.ExePath+"history.txt"; - if (!openFile (filename.c_str())) - { - theApp.errorMessage ("Can't open the file %s", filename.c_str ()); - } -} - -// *************************************************************************** - -void CMainFrame::OnExportSnapshot() -{ - CCustomSnapshot snapShot (this); - if (snapShot.DoModal () == IDOK) - { - CFileDialogEx dialog (BASE_REGISTRY_KEY, "image", FALSE, "tga", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Targa Files (*.tga)|*.tga|All Files (*.*)|*.*||", this); - if (dialog.DoModal() == IDOK) - { - if (snapShot.FixedSize == 0) - _ZoneBuilder->snapshot (dialog.GetPathName(), (uint)theApp.Config.CellSize, snapShot.OutputRGB == 1); - else - _ZoneBuilder->snapshotCustom (dialog.GetPathName(), snapShot.Width, snapShot.Height, snapShot.KeepRatio != FALSE, - (uint)theApp.Config.CellSize, snapShot.OutputRGB == 1); - } - } -} - -// *************************************************************************** - -void CMainFrame::OnWindowsPrimitiveconfiguration() -{ - PrimitiveConfigurationDlg.ShowWindow (PrimitiveConfigurationDlg.IsWindowVisible()?SW_HIDE:SW_SHOW); -} - -// *************************************************************************** - -void CMainFrame::OnUpdateWindowsPrimitiveconfiguration(CCmdUI* pCmdUI) -{ - pCmdUI->SetCheck(PrimitiveConfigurationDlg.IsWindowVisible()?1:0); -} - -// *************************************************************************** - -void CMainFrame::OnProjectResetPrimitiveConfiguration() -{ - theApp.reloadPrimitiveConfiguration (); -} - -// *************************************************************************** - -const std::list &CMainFrame::getCurrentSelection() -{ - return Selection; -} - -// *************************************************************************** -// Allow a plugin to modify the primitive selection - -void CMainFrame::setCurrentSelection(std::vector& newSelection) -{ - CWorldEditorDoc *doc=getDocument(); - list::iterator iteSelection; - doc->beginModification(); - //unselect the curent list - for (std::list::iterator it=Selection.begin(),itEnd=Selection.end();it!=itEnd;++it) - { - CDatabaseLocatorPointer locatorCurrent; - doc->getLocator (locatorCurrent, (*it) ); - doc->addModification (new CActionUnselect (locatorCurrent)); - } - - //select the new selection - for(uint i=0;igetLocator (locatorCurrent, newSelection.at(i)); - - doc->addModification (new CActionSelect (locatorCurrent)); - } - doc->endModification(); - - getMainFrame()->updateData (); - getMainFrame()->OnViewLocateselectedprimitives (); - getMainFrame()->OnViewLocateselectedprimitivesTree (); -} - -// *************************************************************************** -// use the root file name in order to retrieve the correct root node -const NLLIGO::IPrimitive* CMainFrame::getRootNode(const std::string& rootFileName) -{ - - CDatabaseLocatorPointer locator; - CWorldEditorDoc *doc=getDocument(); - doc->getFirstLocator(locator); - - locator.getRoot(rootFileName); - - return locator.Primitive; -} - -// *************************************************************************** -// retrieve the file name associated with the primitive of the root node -// it must be the root node -std::string& CMainFrame::getRootFileName(NLLIGO::IPrimitive* rootNode) -{ - - CDatabaseLocatorPointer locator; - CWorldEditorDoc *doc=getDocument(); - doc->getLocator(locator,rootNode); - - - return locator.getRootFileName(rootNode); -} - -// *************************************************************************** - - -void CMainFrame::registerPrimitiveDisplayer(IPrimitiveDisplayer *displayer, const std::vector &primClassNames) -{ - for (uint i=0; i &CMainFrame::getCurrentSelection() const -{ - return Selection; -} - -// *************************************************************************** -bool CMainFrame::isSelected(const NLLIGO::IPrimitive &prim) const -{ - const IPrimitiveEditor *pe = dynamic_cast(&prim); - nlassert(pe); - return pe->getSelected(); -} - -// *************************************************************************** -void CMainFrame::setPrimitiveHideFlag(NLLIGO::IPrimitive &prim, bool hidden) -{ - getPrimitiveEditor (&prim)->setHidden(hidden); -} - -// *************************************************************************** - -CPrimTexture *CMainFrame::createTexture() -{ - return new CPrimTexture; -} - -// *************************************************************************** - -void CMainFrame::deleteTexture(CPrimTexture *tex) -{ - delete tex; -} - -// *************************************************************************** - -bool CMainFrame::buildNLBitmapFromTGARsc(HRSRC bm, HMODULE hm, NLMISC::CBitmap &dest) -{ - HGLOBAL rsc = LoadResource(hm, bm); - if (rsc == NULL) return false; - uint numBytes = SizeofResource(hm, bm); - if (numBytes == 0) return false; - LPVOID dataPtr = LockResource(rsc); - if (!dataPtr) return false; - NLMISC::CMemStream ms; - ms.serialBuffer((uint8 *) dataPtr, numBytes); - NLMISC::CBitmap tmpBitmap; - ms.invert(); - try - { - ms.seek(0, NLMISC::IStream::begin); - tmpBitmap.load(ms); - } - catch(EStream &) - { - return false; - } - dest.swap(tmpBitmap); - return true; -} - - - -// *************************************************************************** - -void CMainFrame::OnDestroy() -{ - theApp.deletePlugins(); - CFrameWnd::OnDestroy(); -} - -// *************************************************************************** - -bool CMainFrame::CanDrop() -{ - for (uint i=0; i<_PrimitiveClipboard.size (); i++) - { - bool paste = false; - - // Is this a root ? - if ( Selection.front() ) - { - if ( Selection.front()->getParent() ) - { - // Try to add it has children of the selection - if (theApp.Config.canBeChild (*(_PrimitiveClipboard[i]), *(Selection.front ()))) - { - paste = true; - } - else - { - // Can be a child ? - if (theApp.Config.canBeChild (*(_PrimitiveClipboard[i]), *(Selection.front ()->getParent ()))) - { - paste = true; - } - } - } - else - { - // Try to add it has children of the selection - if (theApp.Config.canBeRoot (*(_PrimitiveClipboard[i]))) - { - paste = true; - } - } - } - - if ( !paste ) - return false; - } - - return true; -} - -// *************************************************************************** - -void CMainFrame::OnSavePosition() -{ - ::CStdioFile file; - ::CString str; - ::CTime t = ::CTime::GetCurrentTime(); - - const CVector &v = DispWnd->_CurPos; - - // Write the zone name in NeL protocol - sint32 x, y; - - CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); - x = (sint32)floor(v.x / dispWnd->_CellSize); - y = (sint32)floor(v.y / dispWnd->_CellSize); - - str.Format( "[%s] X = %.3f, Y = %.3f\r\n", t.Format( "%m/%d/%y, %H:%M:%S" ), v.x, v.y ); - - file.Open( "position.txt", ::CFile::modeCreate|::CFile::modeNoTruncate|::CFile::modeWrite|::CFile::typeText ); - file.SeekToEnd(); - file.WriteString( str ); - file.Close(); - - MessageBox( "Current coordinates saved in file position.txt", "Position saved", MB_OK ); -} - -// *************************************************************************** - -void CMainFrame::OnDropFiles(HDROP hDropInfo) -{ - // hDropInfo contains infos about dropped files - if (hDropInfo) - { - CString Filename; - - // Get the number of files dropped - uint numFiles = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0); - - for (uint i=0 ; ibeginModification (); - - if (!getDocument()->isPrimitiveLoaded(path)) - getDocument ()->addModification (new CActionLoadPrimitive (path.c_str())); - else - infoMessage("Primitive already existing: %s", path.c_str()); - - getDocument()->endModification (); - - // Verify primitive structures - VerifyPrimitivesStructures(); - - // Update data - updateData (); - } - // Can be extended to support more file types - else - { - errorMessage("File not supported: %s", pFilename); - } - } - } - - // Release memory - DragFinish(hDropInfo); -} - -// *************************************************************************** - -void CMainFrame::OnMissionCompiler() -{ - // list of selected primitives - list sel = getCurrentSelection(); - - // list of primitive files to compile - vector files; - - // store selected primitive files : no duplicate file - for (list::iterator itSel=sel.begin() ; itSel!=sel.end() ; ++itSel) - { - // Get file path of selected primitive - string path; - CDatabaseLocatorPointer locator; - CWorldEditorDoc *doc = getDocument(); - doc->getLocator(locator, *itSel); - doc->getFilePath(locator.getDatabaseIndex(), path); - - // Check if already inserted - vector::iterator it = find(files.begin(), files.end(), path); - if (it == files.end()) - files.push_back(path); - } - - // write filenames to a temp file for the mission compiler - if (files.size() > 0) - { - // use system temp directory - char tmpPath[MAX_PATH]; - GetEnvironmentVariable("TMP", tmpPath, MAX_PATH); - strcat(tmpPath, "\\tmptool.txt"); - - FILE *f = fopen(tmpPath, "w"); - if (f==NULL) - infoMessage("Can't open file for writing !\n%s", tmpPath); - - for (uint i=0 ; igetConfigFile().getVarPtr ("MissionCompilerPath"); - if (!var) - { - errorMessage("Can't find variable : ""MissionCompilerPath"" in world_editor_plugin.cfg"); - return; - } - - char path[MAX_PATH]; - strcpy(path, var->asString().c_str()); - - SHELLEXECUTEINFO ExecuteInfo; - memset(&ExecuteInfo, 0, sizeof(ExecuteInfo)); - - ExecuteInfo.cbSize = sizeof(ExecuteInfo); - ExecuteInfo.fMask = 0; - ExecuteInfo.hwnd = 0; - ExecuteInfo.lpVerb = "open"; - ExecuteInfo.lpFile = "mission_compiler_fe_r.exe"; - ExecuteInfo.lpParameters = 0; - ExecuteInfo.lpDirectory = path; - ExecuteInfo.nShow = SW_SHOW; - ExecuteInfo.hInstApp = 0; - - if(ShellExecuteEx(&ExecuteInfo) == FALSE) - errorMessage("File not found : mission_compiler_fe_r.exe !"); -} - -// *************************************************************************** - -void CMainFrame::OnNameDlg() -{ - CNameDlg dlg; - dlg.setSelection(getCurrentSelection()); - int nResponse = dlg.DoModal(); - if (nResponse == IDOK) - infoMessage("Files saved !"); -} - -// *************************************************************************** +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// main_frm.cpp : implementation of the CMainFrame class +// + +#include "stdafx.h" + +#include "action.h" +#include "world_editor.h" +#include "world_editor_doc.h" +#include "display.h" +#include "primitive_view.h" +#include "tools_logic.h" +#include "tools_zone.h" +#include "main_frm.h" +#include "resource.h" +#include "generate_dlg.h" +#include "type_manager_dlg.h" +#include "move_dlg.h" +#include "name_dlg.h" +#include "custom_snapshot.h" +#include "export_dlg.h" +// #include "export_cb_dlg.h" +#include "project_settings.h" +#include "dialog_properties.h" +#include "generate_primitive.h" +#include "editor_primitive.h" +#include "select_by_location.h" +#include "find_primitive_dlg.h" +#include "primitive_configuration_dlg.h" +#include "pacs.h" +#include "editor_primitive.h" +#include "file_dialog_ex.h" +#include "nel/misc/mem_stream.h" + +#include + +using namespace NLLIGO; +using namespace std; +using namespace NLMISC; +using namespace NL3D; + +extern bool DontUse3D; + +#define TIMER_UPDATE_FILES 666 +#define TIMER_PLUGINS 667 +#define LOCATE_BORDER 50 + +uint32 getUniqueId (); + + +// *************************************************************************** +// CMainFrame + +IMPLEMENT_DYNCREATE(CMainFrame, CFrameWnd) + +BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) + //{{AFX_MSG_MAP(CMainFrame) + ON_WM_CREATE() + ON_WM_CLOSE() + ON_WM_SIZE() + ON_COMMAND(ID_APP_EXIT, onMenuFileExit) + ON_COMMAND(ID_EDIT_LOGIC, onMenuModeLogic) + ON_COMMAND(ID_EDIT_ZONE, onMenuModeZone) + ON_COMMAND(ID_EDIT_TRANSITION, onMenuModeTransition) + ON_COMMAND(ID_EDIT_UNDO, onMenuModeUndo) + ON_COMMAND(ID_EDIT_REDO, onMenuModeRedo) + ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, onUpdateModeUndo) + ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, onUpdateModeRedo) + ON_COMMAND(ID_PROJECT_NEWLANDSCAPE, onProjectNewlandscape) + ON_COMMAND(ID_PROJECT_ADDLANDSCAPE, onProjectAddlandscape) + ON_COMMAND(ID_PROJECT_SETTINGS, onProjectSettings) + ON_UPDATE_COMMAND_UI(ID_EDIT_TRANSITION, OnUpdateEditTransition) + ON_UPDATE_COMMAND_UI(ID_EDIT_ZONE, OnUpdateEditZone) + ON_UPDATE_COMMAND_UI(ID_EDIT_LOGIC, OnUpdateEditLogic) + ON_COMMAND(ID_PROJECT_IMPORT_PRIM, OnProjectImportPrim) + ON_COMMAND(ID_PROJECT_ADDPRIMITIVE, OnProjectAddPrimitive) + ON_COMMAND(ID_PROJECT_CLEARALLPRIMITIVE, OnProjectClearallprimitive) + ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll) + ON_COMMAND(ID_EDIT_LOCK, OnEditLock) + ON_COMMAND(ID_EDIT_SELECT, OnEditSelect) + ON_COMMAND(ID_EDIT_DETAILS, OnEditDetails) + ON_COMMAND(ID_VIEW_LANDSCAPE, OnViewLandscape) + ON_COMMAND(ID_VIEW_LAYERS, OnViewLayers) + ON_COMMAND(ID_VIEW_GRID, OnViewGrid) + ON_COMMAND(ID_VIEW_POINTS, OnViewPoints) + ON_COMMAND(ID_VIEW_PACS, OnViewPACS) + ON_COMMAND(ID_VIEW_PRIMITIVES, OnViewPrimitives) + ON_COMMAND(ID_EDIT_TRANSLATE, OnEditTranslate) + ON_COMMAND(ID_EDIT_ROTATE, OnEditRotate) + ON_COMMAND(ID_EDIT_TURN, OnEditTurn) + ON_COMMAND(ID_EDIT_RADIUS, OnEditRadius) + ON_COMMAND(ID_EDIT_SCALE, OnEditScale) + ON_COMMAND(ID_EDIT_ADD_POINT, OnEditAddPoint) + ON_COMMAND(ID_EDIT_DELETE, OnEditDelete) + ON_COMMAND(ID_PROJECT_NEWPRIMITIVE, OnProjectNewPrimitive) + ON_COMMAND(ID_EDIT_PROPERTIES, OnEditProperties) + ON_UPDATE_COMMAND_UI(ID_EDIT_ADD_POINT, OnUpdateEditAddPoint) + ON_UPDATE_COMMAND_UI(ID_EDIT_LOCK, OnUpdateEditLock) + ON_UPDATE_COMMAND_UI(ID_EDIT_PROPERTIES, OnUpdateEditProperties) + ON_UPDATE_COMMAND_UI(ID_EDIT_ROTATE, OnUpdateEditRotate) + ON_UPDATE_COMMAND_UI(ID_EDIT_SCALE, OnUpdateEditScale) + ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_ALL, OnUpdateEditSelectAll) + ON_UPDATE_COMMAND_UI(ID_EDIT_TRANSLATE, OnUpdateEditTranslate) + ON_UPDATE_COMMAND_UI(ID_EDIT_TURN, OnUpdateEditTurn) + ON_UPDATE_COMMAND_UI(ID_EDIT_RADIUS, OnUpdateEditRadius) + ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT, OnUpdateEditSelect) + ON_UPDATE_COMMAND_UI(ID_EDIT_DETAILS, OnUpdateEditDetails) + ON_UPDATE_COMMAND_UI(ID_VIEW_LANDSCAPE, OnUpdateViewLandscape) + ON_COMMAND(ID_EDIT_COPY, OnEditCopy) + ON_COMMAND(ID_EDIT_CUT, OnEditCut) + ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy) + ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut) + ON_COMMAND(ID_EDIT_PASTE, OnEditPaste) + ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste) + ON_UPDATE_COMMAND_UI(ID_VIEW_HIDE, OnUpdateViewHide) + ON_COMMAND(ID_VIEW_HIDE, OnViewHide) + ON_COMMAND(ID_VIEW_SHOW, OnViewShow) + ON_UPDATE_COMMAND_UI(ID_VIEW_SHOW, OnUpdateViewShow) + ON_UPDATE_COMMAND_UI(ID_EDIT_EXPAND, OnUpdateEditExpand) + ON_UPDATE_COMMAND_UI(ID_EDIT_COLLAPSE, OnUpdateEditCollapse) + ON_COMMAND(ID_EDIT_SELECT_CHILDREN, OnEditSelectChildren) + ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_CHILDREN, OnUpdateEditSelectChildren) + ON_WM_TIMER() + ON_COMMAND(ID_EDIT_EXPAND, OnEditExpand) + ON_COMMAND(ID_EDIT_COLLAPSE, OnEditCollapse) + ON_COMMAND(ID_HELP_FINDER, OnHelpFinder) + ON_COMMAND(ID_VIEW_LOCATESELECTEDPRIMITIVES, OnViewLocateselectedprimitives) + ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATESELECTEDPRIMITIVES, OnUpdateViewLocateselectedprimitives) + ON_COMMAND(ID_VIEW_LOCATESELECTEDPRIMITIVES_TREE, OnViewLocateselectedprimitivesTree) + ON_UPDATE_COMMAND_UI(ID_VIEW_LOCATESELECTEDPRIMITIVES_TREE, OnUpdateViewLocateselectedprimitivesTree) + ON_COMMAND(ID_EDIT_SELECT_BY_LOCATION, OnEditSelectByLocation) + ON_UPDATE_COMMAND_UI(ID_EDIT_SELECT_BY_LOCATION, OnUpdateEditSelectByLocation) + ON_COMMAND(ID_PROJECT_RESETUNIQUEID, OnProjectResetuniqueid) + ON_COMMAND(ID_PROJECT_GENERATENULLID, OnProjectGeneratenullid) + ON_COMMAND(ID_PROJECT_CORRECT_ID, OnProjectForceiduniqueness) + ON_COMMAND(ID_FIND, OnEditFind) + ON_COMMAND(ID_GOTO, OnEditGoto) + ON_UPDATE_COMMAND_UI(ID_FIND, OnUpdateFind) + ON_COMMAND(ID_VIEW_COLLISIONS, OnViewCollisions) + ON_COMMAND(ID_HELP_HISTORY, OnHelpHistory) + ON_COMMAND(ID_EXPORT_SNAPSHOT, OnExportSnapshot) + ON_COMMAND(ID_WINDOWS_PRIMITIVECONFIGURATION, OnWindowsPrimitiveconfiguration) + ON_UPDATE_COMMAND_UI(ID_WINDOWS_PRIMITIVECONFIGURATION, OnUpdateWindowsPrimitiveconfiguration) + ON_COMMAND(ID_PROJECT_RESET_PRIMITIVE_CONFIGURATION, OnProjectResetPrimitiveConfiguration) + ON_WM_DESTROY() + ON_COMMAND(ID_EDIT_EXPAND, OnEditExpand) + ON_COMMAND(ID_EDIT_COLLAPSE, OnEditCollapse) + ON_WM_PAINT() + ON_WM_MENUSELECT() + ON_COMMAND(ID_SAVPOS, OnSavePosition) + ON_WM_DROPFILES() + ON_COMMAND(ID_MISSION_COMPILER, OnMissionCompiler) + ON_COMMAND(ID_NAME_DLG, OnNameDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +static UINT indicators[] = +{ + ID_INDICATOR_ZONENAMENEL, + ID_INDICATOR_ZONENAMEREF, + ID_INDICATOR_COORDINATES, + ID_INDICATOR_ZONEROT, + ID_INDICATOR_ZONEFLIP, + ID_INDICATOR_SELECTION, + ID_INDICATOR_INFO, +}; + +// *************************************************************************** +// CMainFrame construction/destruction + +CMainFrame::CMainFrame() + : + _Mode(0), + _SplitterCreated(false), + _MasterCB(0), + _CurrentPlugin(0) +{ + CreateX = CreateY = CreateCX = CreateCY = 0; + _ZoneBuilder = NULL; + _SelectionLocked = false; + _TransformModes[0] = Select; + _TransformModes[1] = Select; + _ShowDetails = false; + _ShowLandscape = true; + _ShowGrid = true; + _ShowPoints = true; + _ShowPACS = false; + _ShowPrimitives = true; + _ShowLayers = true; + _ValidLandscape = true; + _ShowCollisions = false; + m_FindPrimitiveDlg = NULL; + _MustRefreshPropertyDialog = false; +} + +CMainFrame::~CMainFrame() +{ + if (_ZoneBuilder) + delete _ZoneBuilder; + + if (m_FindPrimitiveDlg) + { + if (::IsWindow(m_FindPrimitiveDlg->GetSafeHwnd())) + m_FindPrimitiveDlg->EndDialog(IDCANCEL); + delete m_FindPrimitiveDlg; + m_FindPrimitiveDlg = NULL; + } + + // Free the clipboard + deletePrimitiveClipboard (); +} + +int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CFrameWnd::OnCreate(lpCreateStruct) == -1) + return -1; + + if (!m_wndToolBar.CreateEx(this) || + !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) + { + TRACE0("Failed to create toolbar\n"); + return -1; // fail to create + } +/* if (!m_wndDlgBar.Create(this, IDR_MAINFRAME, + CBRS_ALIGN_TOP, AFX_IDW_DIALOGBAR)) + { + TRACE0("Failed to create dialogbar\n"); + return -1; // fail to create + }*/ + + if (!m_wndReBar.Create(this) || + !m_wndReBar.AddBar(&m_wndToolBar) /*|| + !m_wndReBar.AddBar(&m_wndDlgBar)*/) + { + TRACE0("Failed to create rebar\n"); + return -1; // fail to create + } + + if (!m_wndStatusBar.Create(this) || + !m_wndStatusBar.SetIndicators(indicators, + sizeof(indicators)/sizeof(UINT))) + { + TRACE0("Failed to create status bar\n"); + return -1; // fail to create + } + + // TODO: Remove this if you don't want tool tips + CMenu *menu = GetMenu (); + m_wndToolBar.SetBarStyle(m_wndToolBar.GetBarStyle() | CBRS_TOOLTIPS | CBRS_FLYBY); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_ZONE), TBBS_CHECKGROUP); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_TRANSITION), TBBS_CHECKGROUP); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_LOGIC), TBBS_CHECKGROUP); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_LOCK), TBBS_CHECKBOX); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_DETAILS), TBBS_CHECKBOX); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_SELECT), TBBS_CHECKGROUP); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_TRANSLATE), TBBS_CHECKGROUP); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_ROTATE), TBBS_CHECKGROUP); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_TURN), TBBS_CHECKGROUP); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_SCALE), TBBS_CHECKGROUP); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_RADIUS), TBBS_CHECKGROUP); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_EDIT_ADD_POINT), TBBS_CHECKGROUP); + m_wndToolBar.SetButtonStyle (m_wndToolBar.CommandToIndex(ID_VIEW_LANDSCAPE), TBBS_CHECKBOX); + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_LANDSCAPE); + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_LAYERS); + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_GRID); + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_POINTS); + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_PRIMITIVES); + menu->CheckMenuItem (ID_VIEW_LANDSCAPE, MF_CHECKED|MF_BYCOMMAND); + menu->CheckMenuItem (ID_VIEW_LAYERS, MF_CHECKED|MF_BYCOMMAND); + menu->CheckMenuItem (ID_VIEW_GRID, MF_CHECKED|MF_BYCOMMAND); + menu->CheckMenuItem (ID_VIEW_POINTS, MF_CHECKED|MF_BYCOMMAND); + menu->CheckMenuItem (ID_VIEW_PRIMITIVES, MF_CHECKED|MF_BYCOMMAND); + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_ZONE); + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_SELECT); + + CDocument *pNewDoc = new CWorldEditorDoc;//CDocument; + InitialUpdateFrame(pNewDoc, TRUE); + + // Default tool column size + _ToolColumnSize = 300; + + // Init display + SetActiveView((CView*)m_wndSplitter.GetPane (0,0)); + DispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); + + // Timer + CFrameWnd::SetTimer (TIMER_UPDATE_FILES, 5000, NULL); + CFrameWnd::SetTimer (TIMER_PLUGINS, 1000/10, NULL); + + // Init the main frame + if (init ()) + { + // Disable events + CNoInteraction nointeraction; + + launchLoadingDialog("init display"); + DispWnd->setCellSize (theApp.Config.CellSize); + DispWnd->init (this); + terminateLoadingDialog(); + return 0; + } + else + return -1; +} + +BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT /*lpcs*/, + CCreateContext* pContext) +{ +// AFX_MANAGE_STATE (AfxGetStaticModuleState()); + // create a splitter with 1 row, 2 columns + if (!m_wndSplitter.CreateStatic(this, 1, 2)) + { + TRACE0("Failed to CreateStaticSplitter\n"); + return FALSE; + } + + // add the first splitter pane - the default view in column 0 + if (!m_wndSplitter.CreateView(0, 0, + RUNTIME_CLASS(CDisplay), CSize(640, 512), pContext)) + { + TRACE0("Failed to create first pane\n"); + return FALSE; + } + + // add the second splitter pane - the default view in column 0 + if (!m_wndSplitter.CreateView(0, 1, + RUNTIME_CLASS(CPrimitiveView), CSize(200, 100), pContext)) + { + TRACE0("Failed to create first pane\n"); + return FALSE; + } + + _SplitterCreated = true; + + return TRUE; +} + +// *************************************************************************** + +BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) +{ + //AFX_MANAGE_STATE (AfxGetStaticModuleState()); + + if ((CreateCX != 0)&&(CreateCY != 0)) + { + cs.x = CreateX; + cs.y = CreateY; + cs.cx = CreateCX; + cs.cy = CreateCY; + } + + if (!CFrameWnd::PreCreateWindow(cs)) + return FALSE; + return TRUE; +} + +// *************************************************************************** + +// CMainFrame diagnostics + +#ifdef _DEBUG +void CMainFrame::AssertValid() const +{ + CFrameWnd::AssertValid(); +} + +void CMainFrame::Dump(CDumpContext& dc) const +{ + CFrameWnd::Dump(dc); +} + +#endif //_DEBUG + +// *************************************************************************** + +// CMainFrame message handlers + + + + + + + + +/* Old Trap begin */ + +// *************************************************************************** + +// CType + +// *************************************************************************** + +void SType::serial (NLMISC::IStream&f) +{ + int version = f.serialVersion(0); + f.serial (Name); + f.serial (Color); +} + +// *************************************************************************** + +// CType + +// *************************************************************************** + +SEnvironnement::SEnvironnement () +{ +} + +// *************************************************************************** + +void SEnvironnement::serial (NLMISC::IStream&f) +{ + int version = f.serialVersion (1); + + f.serialCont (Types); + f.serial (BackgroundColor); + // f.serial (ExportOptions); + + if (version > 0) + f.serial (DataDir); +} + +// *************************************************************************** +// CMainFrame + +// *************************************************************************** + +NLMISC::CConfigFile &CMainFrame::getConfigFile() +{ +// AFX_MANAGE_STATE(AfxGetStaticModuleState()); + AFX_MANAGE_STATE(AfxGetAppModuleState()); + // Old Trap return IWorldEditor::getInterface()->getConfigFile(); + CWinApp *theApp = AfxGetApp(); + CWorldEditorApp* wea = static_cast(theApp); + + return wea->PluginConfig; +} + +void CMainFrame::onLogicChanged(const std::vector ®ions) +{ + /* const std::vector &plugins = IWorldEditor::getInterface()->getPlugins(); + std::vector::const_iterator first(plugins.begin()), last(plugins.end()); + + for (; first != last; ++first) + { + (*first)->primRegionChanged(regions); + } */ +} + +// *************************************************************************** + +bool CMainFrame::yesNoMessage (const char *format, ... ) +{ + char buffer[1024]; + + if (format) + { + va_list args; + va_start( args, format ); + sint ret = vsnprintf( buffer, 1024, format, args ); + va_end( args ); + } + else + { + strcpy(buffer, "Unknown error"); + } + + return theApp.yesNoMessage (buffer); +} + +// *************************************************************************** + +void CMainFrame::errorMessage (const char *format, ... ) +{ + char buffer[1024]; + + if (format) + { + va_list args; + va_start( args, format ); + sint ret = vsnprintf( buffer, 1024, format, args ); + va_end( args ); + } + else + { + strcpy(buffer, "Unknown error"); + } + + theApp.errorMessage (buffer); +} + +// *************************************************************************** + +void CMainFrame::infoMessage (const char *format, ... ) +{ + char buffer[1024]; + + if (format) + { + va_list args; + va_start( args, format ); + sint ret = vsnprintf( buffer, 1024, format, args ); + va_end( args ); + } + else + { + strcpy(buffer, "Unknown error"); + } + + theApp.infoMessage (buffer); +} + +// *************************************************************************** + +void CMainFrame::startPositionControl(IPluginCallback *plugin, const CVector &initPos) +{ + AFX_MANAGE_STATE(AfxGetAppModuleState()); + if (_CurrentPlugin != 0) + _CurrentPlugin->lostPositionControl(); + + _CurrentPlugin = plugin; + _PositionControl = initPos; + + if (_Mode != 3) + { + _LastMode = _Mode; +// uninitTools(); + _Mode = 3; +// initTools(); + } + + DispWnd->Invalidate(); +} + +// *************************************************************************** + +void CMainFrame::stopPositionControl(IPluginCallback *plugin) +{ + AFX_MANAGE_STATE(AfxGetAppModuleState()); + if (_CurrentPlugin == plugin) + { + _CurrentPlugin = 0; + if (_Mode == 3) + { + // uninitTools(); + _Mode = _LastMode; + // initTools(); + } + } + DispWnd->Invalidate(); +} + +// *************************************************************************** +void CMainFrame::setExeDir (const char* str) +{ +// AFX_MANAGE_STATE (AfxGetStaticModuleState()); + _ExeDir = str; + if ((str[strlen(str)-1] != '\\') || (str[strlen(str)-1] != '/')) + _ExeDir += "\\"; +} + +// *************************************************************************** + +void CMainFrame::uninitTools() +{ + if (_Mode == 0) // Mode Zone + { + CToolsZone *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); + toolWnd->uninit (); + } + if (_Mode == 1) // Mode Logic + { + // Invalidate primitives + CWorldEditorDoc *doc = getDocument (); + uint i; + uint count = doc->getNumDatabaseElement (); + for (i=0; ilostPositionControl(); + _CurrentPlugin = 0; + } + } +} + +// *************************************************************************** + +void CMainFrame::initTools() +{ + if (_Mode == 0) // Mode Zone + { + m_wndSplitter.DeleteView (0, 1); + m_wndSplitter.CreateView (0, 1, RUNTIME_CLASS(CToolsZone), CSize(100, 100), NULL); + SetActiveView ((CView*)m_wndSplitter.GetPane(0,1)); + CToolsZone *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); + toolWnd->init (this); + adjustSplitter (); + } + if (_Mode == 1) // Mode Logic + { + m_wndSplitter.DeleteView (0, 1); + m_wndSplitter.CreateView (0, 1, RUNTIME_CLASS(CToolsLogic), CSize(200, 100), NULL); + SetActiveView ((CView*)m_wndSplitter.GetPane(0,1)); + CToolsLogic *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); + toolWnd->init (this); + adjustSplitter (); + + // Invalidate primitives + CWorldEditorDoc *doc = getDocument (); + uint i; + uint count = doc->getNumDatabaseElement (); + for (i=0; ipositionMoved(_PositionControl); + + } + SetActiveView ((CView*)m_wndSplitter.GetPane(0,0)); + +} + +// *************************************************************************** + +void CMainFrame::invalidateTools () +{ + if (_Mode == 1) // Mode Logic + { + CToolsLogic *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); + } +} + +// *************************************************************************** + +void CMainFrame::invalidateLandscape () +{ + _ValidLandscape = false; +} + +// *************************************************************************** + +void CMainFrame::invalidateToolsParam () +{ + if (_Mode == 1) // Mode Logic + { + CToolsLogic *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); + toolWnd->Invalidate(FALSE); + } +} + +// *************************************************************************** + +void CMainFrame::invalidateModification () +{ + if (_Mode == 1) // Mode Logic + { + CToolsLogic *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); + } +} + +// *************************************************************************** + +void CMainFrame::updateData () +{ + // Disable events + CNoInteraction nointeraction; + + // Update primitive quad grid + UpdatePrimitives (); + + // Update the landscape + if (!_ValidLandscape) + { + // Init the landscape manager + _ZoneBuilder->refresh (); + + _ValidLandscape = true; + } + + if (_Mode == 1) // Mode Logic + { + CToolsLogic *toolWnd = dynamic_cast(m_wndSplitter.GetPane(0,1)); + } + + // Update the cursor + getDisplay ()->updateCursor (); + + // Update status bar info + displayStatusBarInfo (); +} + +// *************************************************************************** +void CMainFrame::primZoneModified () +{ + if (_MasterCB != NULL) + { + vector allNames; + } +} + +// *************************************************************************** + +void CMainFrame::displayStatusBarInfo () +{ + std::string sTmp; + + // Position + const CVector &v = DispWnd->_CurPos; + + // Write the zone name in NeL protocol + sint32 x, y; + + CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); + x = (sint32)floor(v.x / dispWnd->_CellSize); + y = (sint32)floor(v.y / dispWnd->_CellSize); + if ((v.x >= 0) && (x <= 255) && (v.y <= 0) && (y >= -255)) + { + getZoneNameFromXY(x, y, sTmp); + } + else + { + sTmp = "NOT A VALID ZONE"; + } + + string text; + if (dispWnd->getActionHelp (text)) + { + m_wndStatusBar.SetPaneText (0, text.c_str()); + } + else + { + m_wndStatusBar.SetPaneText (0, sTmp.c_str()); + } + //for (uint32 i = sTmp.size(); i < 10; ++i) + // sTmp += " "; + + // Write zone reference name + if (dispWnd->getActionText (text)) + { + m_wndStatusBar.SetPaneText (1, text.c_str()); + } + else + { + sTmp = _ZoneBuilder->getZoneName (x, y); + m_wndStatusBar.SetPaneText (1, sTmp.c_str()); + } + + // Write coordinates + char temp[1024]; + sprintf(temp, "(%.3f , %.3f)", v.x, v.y); + sTmp = temp; +// sTmp = "( " + toString(v.x) + " , " + toString(v.y) + " )"; + m_wndStatusBar.SetPaneText (2, sTmp.c_str()); + + // Write rot + sTmp = "Rot(" + toString(_ZoneBuilder->getRot(x, y)) + ")"; + m_wndStatusBar.SetPaneText (3, sTmp.c_str()); + + // Write flip + sTmp = "Flip(" + toString(_ZoneBuilder->getFlip(x, y)) + ")"; + m_wndStatusBar.SetPaneText (4, sTmp.c_str()); + + // Write selection + if (Selection.size ()) + { + if (Selection.size ()>1) + sTmp = toString (Selection.size ()) + " selected primitives"; + else + sTmp = toString (Selection.size ()) + " selected primitive"; + } + else + sTmp = "No selected primitive"; + m_wndStatusBar.SetPaneText (5, sTmp.c_str()); + + // Write path of selected primitive + if (Selection.size()) + sTmp = getDocument()->getPathOfSelectedPrimitive(); + else + sTmp = ""; + + m_wndStatusBar.SetPaneText (6, sTmp.c_str()); +} + +// *************************************************************************** + +void CMainFrame::displayInfo (const char *info) +{ + m_wndStatusBar.SetPaneText (6, info); +} + +// *************************************************************************** +// *************************************************************************** +// CMainFrame diagnostics + + +// *************************************************************************** +bool CMainFrame::init (bool bMakeAZone) +{ + // Initialize the zoneBuilder (load bank and this kind of stuff) + if (initLandscapeData ()) + { + // Mode zone + _Mode = 0; + return true; + } + else + { + return false; + } +} + +// *************************************************************************** +void CMainFrame::uninit () +{ + // Save the WorldEditor.cfg + try + { + COFile fileOut; + string sWorldEdCfg = _ExeDir; + sWorldEdCfg += "WorldEditor.cfg"; + fileOut.open (sWorldEdCfg.c_str(), false, false, true); + fileOut.serial(_Environnement); + fileOut.close(); + } + catch (Exception& e) + { + MessageBox (e.what(), "Warning"); + } +} + +// ****************** +// MESSAGES FROM MENU +// ****************** + +// *************************************************************************** +void CMainFrame::onMenuFileOpenLogic () +{ + CFileDialogEx dialog (BASE_REGISTRY_KEY, "prim", TRUE, "prim", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Primitives Files (*.prim)|*.prim||", this); + if (dialog.DoModal() == IDOK) + { + launchLoadingDialog(string("loading prim zone ") + (LPCSTR)dialog.GetFileName()); + // todo primitive load + primZoneModified (); + terminateLoadingDialog(); + } +} + +// *************************************************************************** + +void CMainFrame::onMenuFileExit () +{ + OnClose(); +} + +// *************************************************************************** +void CMainFrame::onMenuModeZone () +{ + CMenu *menu = GetMenu(); + menu->CheckMenuRadioItem( ID_EDIT_ZONE, ID_EDIT_LOGIC, ID_EDIT_ZONE, MF_BYCOMMAND); + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_ZONE); + + if (_Mode == 1) // if we were in Logic mode switch + { + // store the width of the logic tool panel + if (_SplitterCreated) + { + RECT r; + int cxCur, cxMin; + GetClientRect (&r); + m_wndSplitter.GetColumnInfo(0, cxCur, cxMin); + _ToolColumnSize = r.right-r.left-cxCur; + } + + uninitTools (); + _Mode = 0; + initTools (); + } + _Mode = 0; + CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); + + // Update data + updateData (); +} + +// *************************************************************************** +void CMainFrame::onMenuModeTransition () +{ + CMenu *menu = GetMenu(); + menu->CheckMenuRadioItem( ID_EDIT_ZONE, ID_EDIT_LOGIC, ID_EDIT_TRANSITION, MF_BYCOMMAND); + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_TRANSITION); + + if (_Mode == 1) // if we were in Logic mode switch + { + // store the width of the logic tool panel + if (_SplitterCreated) + { + RECT r; + int cxCur, cxMin; + GetClientRect (&r); + m_wndSplitter.GetColumnInfo(0, cxCur, cxMin); + _ToolColumnSize = r.right-r.left-cxCur; + } + + uninitTools (); + _Mode = 0; + initTools (); + } + _Mode = 2; + CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); + + // Update data + updateData (); +} + +// *************************************************************************** +void CMainFrame::onMenuModeLogic () +{ + CMenu *menu = GetMenu(); + menu->CheckMenuRadioItem( ID_EDIT_ZONE, ID_EDIT_LOGIC, ID_EDIT_LOGIC, MF_BYCOMMAND); + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_LOGIC); + + if (_Mode != 1) // Mode Logic + { + uninitTools(); + _Mode = 1; + initTools(); + } + CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); + + // Update data + updateData (); +} + +// *************************************************************************** + +void CMainFrame::onMenuModeUndo () +{ + getDocument ()->undo (); + + // Update data + updateData (); +} + +// *************************************************************************** +void CMainFrame::onMenuModeRedo () +{ + getDocument ()->redo (); + + // Update data + updateData (); +} + +// *************************************************************************** +#if 0 +void CMainFrame::onMenuModeMove () +{ + CMoveDlg dialog; + if (dialog.DoModal() == IDOK) + if (getDocument ()->getNumLandscape ()) + { + // Select the size + const CZoneRegion ®ion = getDocument ()->getZoneRegion (_ZoneBuilder->_ZoneRegionSelected); + + _ZoneBuilder->move (dialog.XOffset, dialog.YOffset); + CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); + } +} +#endif +// *************************************************************************** +/* +void CMainFrame::onMenuModeCountZones () +{ + if (getDocument ()->getNumLandscape ()) + { + uint32 nNbZones = _ZoneBuilder->countZones (); + string tmp = "There are " + toString(nNbZones) + " zones"; + MessageBox(tmp.c_str(), "Information", MB_ICONINFORMATION|MB_OK); + } +} +*/ +// *************************************************************************** +void CMainFrame::onMenuViewGrid () +{ +// AFX_MANAGE_STATE(AfxGetStaticModuleState()); + CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); + dispWnd->setDisplayGrid (!dispWnd->getDisplayGrid()); + CMenu *menu = GetMenu(); + menu->CheckMenuItem (ID_VIEW_GRID, dispWnd->getDisplayGrid()?MF_CHECKED|MF_BYCOMMAND:MF_UNCHECKED|MF_BYCOMMAND); +} + +// *************************************************************************** +void CMainFrame::onMenuViewBackground () +{ + CColorDialog colDial; + + if (colDial.DoModal() == IDOK) + { + int r = GetRValue(colDial.GetColor()); + int g = GetGValue(colDial.GetColor()); + int b = GetBValue(colDial.GetColor()); + _Environnement.BackgroundColor = CRGBA(r,g,b,255); + CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); + dispWnd->setBackgroundColor (_Environnement.BackgroundColor); + } +} + +// *************************************************************************** +void CMainFrame::OnClose () +{ + _Exit = true; + CFrameWnd::OnClose (); +} + +// *************************************************************************** +void CMainFrame::OnSize (UINT nType, int cx, int cy) +{ + if (nType != SIZE_MINIMIZED) + { + if (cx < 100) + cx = 100; + if (cy < 100) + cy = 100; + } + + // store the width of the logic tool panel + if (_SplitterCreated && _Mode == 1) + { + int cxCur, cxMin; + m_wndSplitter.GetColumnInfo(0, cxCur, cxMin); + _ToolColumnSize = cx - cxCur; + } + + CFrameWnd::OnSize (nType, cx, cy); + if (nType != SIZE_MINIMIZED) + adjustSplitter (); +} + +// *************************************************************************** +void CMainFrame::adjustSplitter () +{ + if (_SplitterCreated) + { + RECT r; + GetClientRect (&r); + + // Mode Zone + if ((_Mode == 0) || (_Mode == 2) && (r.right-r.left > 380)) + m_wndSplitter.SetColumnInfo (0, r.right-r.left-380, 100); // 380 really experimental value + + // Mode Logic + if (_Mode == 1) + if (r.right-r.left > _ToolColumnSize) + m_wndSplitter.SetColumnInfo (0, r.right-r.left-_ToolColumnSize, 10); + else + m_wndSplitter.SetColumnInfo (0, 0, 10); + + + m_wndSplitter.RecalcLayout (); + } +} + +// *************************************************************************** +void CMainFrame::launchLoadingDialog (const std::string &sText) +{ + LoadingDialog = new CLoadingDialog(this); + LoadingDialog->ShowWindow(SW_SHOW); + LoadingDialog->setText(sText); + LoadingDialog->setProgress (0); + CWnd *wnd = LoadingDialog->GetDlgItem (IDC_PROGRESS1); + nlassert (wnd); + wnd->ShowWindow (SW_HIDE); +} + +// *************************************************************************** + +void CMainFrame::progressLoadingDialog (float progress, bool _flushMessages) +{ + nlassert (LoadingDialog); + LoadingDialog->setProgress (progress); + + // Flush current messages + if (_flushMessages) + { + flushMessages (); + } +} + +// *************************************************************************** + +void CMainFrame::flushMessages () +{ + // Pump others message for the windows + MSG msg; + while (PeekMessage(&msg, *LoadingDialog, 0, 0, PM_REMOVE)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } +} + +// *************************************************************************** + +void CMainFrame::terminateLoadingDialog () +{ + delete LoadingDialog; +} + +// *************************************************************************** + +LRESULT CMainFrame::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + // TODO: Add your specialized code here and/or call the base class + if (!DontUse3D && CNELU::Driver) + { + typedef void (*winProc)(NL3D::IDriver *drv, HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); + winProc drvWndProc= (winProc)CNELU::Driver->getWindowProc(); + drvWndProc (CNELU::Driver, m_hWnd, message, wParam, lParam); + } + + return CFrameWnd::WindowProc(message, wParam, lParam); +} + +// *************************************************************************** +// *************************************************************************** +// CLoadingDialog +// *************************************************************************** +// *************************************************************************** + + +// *************************************************************************** + +CLoadingDialog::CLoadingDialog (CWnd *pParent) +{ + Create (IDD_LOADING, pParent); +} + +// *************************************************************************** + +void CLoadingDialog::setText (const std::string &text) +{ + CStatic *pS = (CStatic*)GetDlgItem (IDC_STATIC_TEXT_LOADING); + string sTmp = string("Please wait while ") + text; + setWindowTextUTF8 (*pS, sTmp.c_str()); + + MSG msg; + while (PeekMessage(&msg, *this, 0, 0, PM_REMOVE)) + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } +} + +// *************************************************************************** + +void CLoadingDialog::setProgress (float progress) +{ + CProgressCtrl *progressDlg = (CProgressCtrl *)GetDlgItem (IDC_PROGRESS1); + nlassert (progressDlg); + + progressDlg->ShowWindow (SW_SHOW); + progressDlg->SetRange (0, 32767); + + clamp (progress, 0.f, 1.f); + progressDlg->SetPos ((int)(progress * 32767.f)); +} + +// *************************************************************************** + +/* +void CMainFrame::onMenuFileView () +{ + viewLand(false); +} +*/ + +// *************************************************************************** + +/* +void CMainFrame::onMenuFileViewWithIG() +{ + viewLand(true); +} +*/ + +// *************************************************************************** + +struct CViewerConfig +{ + bool Windowed; + uint Width; + uint Height; + uint Depth; + CVector Position; + CVector Heading; + CVector EyesHeight; + CRGBA Background; + + // Landscape + bool AutoLight; + CVector LightDir; + string ZonesPath; + string BanksPath; + string TilesPath; + bool UseDDS; + bool AllPathRelative; + + string IgPath; + string ShapePath; + string MapsPath; + string Bank; + string FontPath; + //CTextContext TextContext; + //CFontManager FontManager; + float ZFar; + float LandscapeTileNear; + float LandscapeThreshold; + vector Zones; + vector Igs; + + // HeightField. + string HeightFieldName; + float HeightFieldMaxZ; + float HeightFieldOriginX; + float HeightFieldOriginY; + float HeightFieldSizeX; + float HeightFieldSizeY; + + // StaticLight + CRGBA LandAmbient; + CRGBA LandDiffuse; + + // ----------------------------------------------------------------------- + + CViewerConfig() + { + Windowed = true; + Width = 800; + Height = 600; + Depth = 32; + Position = CVector( 1088.987793f, -925.732178f, 0.0f ); + Heading = CVector(0,1,0); + EyesHeight = CVector(0,0,1.8f); + Background = CRGBA(100,100,255); + AutoLight = false; + LightDir = CVector (1, 0, 0); + ZonesPath = "./"; + BanksPath = "./"; + TilesPath = "./"; + UseDDS = false; + AllPathRelative = false; + IgPath = "./"; + ShapePath = "./"; + MapsPath = "./"; + Bank = "bank.bank"; + FontPath = "\\\\server\\code\\fonts\\arialuni.ttf"; + ZFar = 1000; + LandscapeTileNear = 50.0f; + LandscapeThreshold = 0.001f; + + HeightFieldName= ""; + HeightFieldMaxZ= 100; + HeightFieldOriginX= 16000; + HeightFieldOriginY= -24000; + HeightFieldSizeX= 160; + HeightFieldSizeY= 160; + + CRGBA diffuse (241, 226, 244); + CRGBA ambiant (17, 54, 100); + LandDiffuse= diffuse; + LandAmbient= ambiant; + + } + + // ----------------------------------------------------------------------- + void load (const string & configFileName) + { + FILE * f = fopen (configFileName.c_str(), "rt"); + if(f==NULL) + { + nlwarning("'%s' not found, default values used", configFileName.c_str()); + save (configFileName); + } + else fclose (f); + + try + { + CConfigFile cf; + + cf.load(configFileName); + + CConfigFile::CVar &cvFullScreen = cf.getVar("FullScreen"); + this->Windowed = cvFullScreen.asInt() ? false : true; + + CConfigFile::CVar &cvWidth = cf.getVar("Width"); + this->Width = cvWidth.asInt(); + + CConfigFile::CVar &cvHeight = cf.getVar("Height"); + this->Height = cvHeight.asInt(); + + CConfigFile::CVar &cvDepth = cf.getVar("Depth"); + this->Depth = cvDepth.asInt(); + + CConfigFile::CVar &cvPosition = cf.getVar("Position"); + nlassert(cvPosition.size()==3); + this->Position.x = cvPosition.asFloat(0); + this->Position.y = cvPosition.asFloat(1); + this->Position.z = cvPosition.asFloat(2); + + CConfigFile::CVar &cvEyesHeight = cf.getVar("EyesHeight"); + this->EyesHeight = CVector(0,0,cvEyesHeight.asFloat()); + + CConfigFile::CVar &cvBackColor = cf.getVar("Background"); + nlassert(cvBackColor.size()==3); + this->Background.R = cvBackColor.asInt(0); + this->Background.G = cvBackColor.asInt(1); + this->Background.B = cvBackColor.asInt(2); + + CConfigFile::CVar &cvZFar = cf.getVar("ZFar"); + this->ZFar = cvZFar.asFloat(); + + CConfigFile::CVar &cvAutoLight = cf.getVar("AutoLight"); + this->AutoLight = cvAutoLight.asInt() ? true : false; + + CConfigFile::CVar &cvLightDir = cf.getVar("LightDir"); + nlassert(cvLightDir.size()==3); + this->LightDir.x = cvLightDir.asFloat(0); + this->LightDir.y = cvLightDir.asFloat(1); + this->LightDir.z = cvLightDir.asFloat(2); + + CConfigFile::CVar &cvLandscapeTileNear = cf.getVar("LandscapeTileNear"); + this->LandscapeTileNear = cvLandscapeTileNear.asFloat(); + + CConfigFile::CVar &cvLandscapeThreshold = cf.getVar("LandscapeThreshold"); + this->LandscapeThreshold = cvLandscapeThreshold.asFloat(); + + CConfigFile::CVar &cvBanksPath = cf.getVar("BanksPath"); + this->BanksPath = cvBanksPath.asString(); + + CConfigFile::CVar &cvTilesPath = cf.getVar("TilesPath"); + this->TilesPath = cvTilesPath.asString(); + + CConfigFile::CVar &cvUseDDS = cf.getVar("UseDDS"); + this->UseDDS = cvUseDDS.asInt() ? true : false; + + CConfigFile::CVar &cvAllPathRelative = cf.getVar("AllPathRelative"); + this->AllPathRelative = cvAllPathRelative.asInt() ? true : false; + + CConfigFile::CVar &cvBank = cf.getVar("Bank"); + this->Bank = cvBank.asString(); + + CConfigFile::CVar &cvZonesPath = cf.getVar("ZonesPath"); + this->ZonesPath = cvZonesPath.asString(); + + CConfigFile::CVar &cvIgPath = cf.getVar("IgPath"); + this->IgPath = cvIgPath.asString(); + + CConfigFile::CVar &cvShapePath = cf.getVar("ShapePath"); + this->ShapePath = cvShapePath.asString(); + + CConfigFile::CVar &cvMapsPath = cf.getVar("MapsPath"); + this->MapsPath = cvMapsPath.asString(); + + CConfigFile::CVar &cvHeightFieldName = cf.getVar("HeightFieldName"); + this->HeightFieldName = cvHeightFieldName.asString(); + + CConfigFile::CVar &cvHeightFieldMaxZ = cf.getVar("HeightFieldMaxZ"); + this->HeightFieldMaxZ = cvHeightFieldMaxZ.asFloat(); + + CConfigFile::CVar &cvHeightFieldOriginX = cf.getVar("HeightFieldOriginX"); + this->HeightFieldOriginX = cvHeightFieldOriginX.asFloat(); + + CConfigFile::CVar &cvHeightFieldOriginY = cf.getVar("HeightFieldOriginY"); + this->HeightFieldOriginY = cvHeightFieldOriginY.asFloat(); + + CConfigFile::CVar &cvHeightFieldSizeX = cf.getVar("HeightFieldSizeX"); + this->HeightFieldSizeX = cvHeightFieldSizeX.asFloat(); + + CConfigFile::CVar &cvHeightFieldSizeY = cf.getVar("HeightFieldSizeY"); + this->HeightFieldSizeY = cvHeightFieldSizeY.asFloat(); + + + CConfigFile::CVar &cvLandAmb = cf.getVar("LandAmbient"); + nlassert(cvLandAmb.size()==3); + this->LandAmbient.R = cvLandAmb.asInt(0); + this->LandAmbient.G = cvLandAmb.asInt(1); + this->LandAmbient.B = cvLandAmb.asInt(2); + + CConfigFile::CVar &cvLandDiff = cf.getVar("LandDiffuse"); + nlassert(cvLandDiff.size()==3); + this->LandDiffuse.R = cvLandDiff.asInt(0); + this->LandDiffuse.G = cvLandDiff.asInt(1); + this->LandDiffuse.B = cvLandDiff.asInt(2); + + + CConfigFile::CVar &cvZones = cf.getVar("Zones"); + for(uint i=0; iZones.push_back(cvZones.asString(i)); + } + + CConfigFile::CVar &cvIgs = cf.getVar("Ig"); + for(uint i=0; iIgs.push_back(cvIgs.asString(i)); + } + + } + catch (EConfigFile &e) + { + printf ("Problem in config file : %s\n", e.what ()); + } + } + + // ----------------------------------------------------------------------- + void save (const string &configFileName) + { + FILE * f = fopen (configFileName.c_str(), "wt"); + + if(f==NULL) + { + fprintf(stderr,"can't open file '%s'\n",configFileName); + } + + fprintf(f,"FullScreen = %d;\n",this->Windowed?0:1); + fprintf(f,"Width = %d;\n",this->Width); + fprintf(f,"Height = %d;\n",this->Height); + fprintf(f,"Depth = %d;\n",this->Depth); + fprintf(f,"Position = { %f, %f, %f };\n", this->Position.x,this->Position.y,this->Position.z); + fprintf(f,"EyesHeight = %f;\n", this->EyesHeight.z); + fprintf(f,"Background = { %d, %d, %d };\n", this->Background.R,this->Background.G,this->Background.B); + fprintf(f,"ZFar = %f;\n", this->ZFar); + + fprintf(f,"AutoLight = %d;\n", this->AutoLight?1:0); + fprintf(f,"LightDir = { %f, %f, %f };\n", this->LightDir.x, this->LightDir.y, this->LightDir.z); + fprintf(f,"LandscapeTileNear = %f;\n", this->LandscapeTileNear); + fprintf(f,"LandscapeThreshold = %f;\n", this->LandscapeThreshold); + fprintf(f,"BanksPath = \"%s\";\n",this->BanksPath.c_str()); + fprintf(f,"TilesPath = \"%s\";\n",this->TilesPath.c_str()); + fprintf(f,"UseDDS = \"%d\";\n",this->UseDDS?1:0); + fprintf(f,"AllPathRelative = \"%d\";\n",this->AllPathRelative?1:0); + fprintf(f,"Bank = \"%s\";\n",this->Bank.c_str()); + fprintf(f,"ZonesPath = \"%s\";\n",this->ZonesPath.c_str()); + fprintf(f,"IgPath = \"%s\";\n",this->IgPath.c_str()); + fprintf(f,"ShapePath = \"%s\";\n",this->ShapePath.c_str()); + fprintf(f,"MapsPath = \"%s\";\n",this->MapsPath.c_str()); + + + + fprintf(f,"HeightFieldName = \"%s\";\n", this->HeightFieldName.c_str()); + fprintf(f,"HeightFieldMaxZ = %f;\n", this->HeightFieldMaxZ); + fprintf(f,"HeightFieldOriginX = %f;\n", this->HeightFieldOriginX); + fprintf(f,"HeightFieldOriginY = %f;\n", this->HeightFieldOriginY); + fprintf(f,"HeightFieldSizeX = %f;\n", this->HeightFieldSizeX); + fprintf(f,"HeightFieldSizeY = %f;\n", this->HeightFieldSizeY); + + fprintf(f,"LandAmbient = { %d, %d, %d };\n", this->LandAmbient.R,this->LandAmbient.G,this->LandAmbient.B); + fprintf(f,"LandDiffuse = { %d, %d, %d };\n", this->LandDiffuse.R,this->LandDiffuse.G,this->LandDiffuse.B); + + uint32 i; + fprintf(f,"Zones = {\n"); + for (i = 0; i < Zones.size(); ++i) + if (i < (Zones.size()-1)) + fprintf(f,"\"%s\",\n", Zones[i]); + else + fprintf(f,"\"%s\"\n", Zones[i]); + fprintf(f,"};\n"); + + fprintf(f,"Ig = {\n"); + for (i = 0; i < Igs.size(); ++i) + if (i < (Igs.size()-1)) + fprintf(f,"\"%s\",\n", Igs[i]); + else + fprintf(f,"\"%s\"\n", Igs[i]); + fprintf(f,"};\n"); + + fclose(f); + } +}; + +// *************************************************************************** + +/* +void CMainFrame::viewLand(bool withIgs) +{ + // Modify the zviewer.cfg + CViewerConfig cfgFile; + SetCurrentDirectory (_ExeDir.c_str()); + string cfgFileName = "zviewer.cfg"; + cfgFile.load (cfgFileName); + cfgFile.Zones.clear (); + cfgFile.Igs.clear (); + + // Select the size + const CZoneRegion ®ion = getDocument ()->getZoneRegion (_ZoneBuilder->_ZoneRegionSelected); + + sint32 nMinX = region.getMinX() < 0 ? 0 : region.getMinX(); + sint32 nMaxX = region.getMaxX() > 255 ? 255 : region.getMaxX(); + sint32 nMinY = region.getMinY() > 0 ? 0 : region.getMinY(); + sint32 nMaxY = region.getMaxY() < -255 ? -255 : region.getMaxY(); + + if ((_Environnement.ExportOptions.ZoneMin != "") && (_Environnement.ExportOptions.ZoneMax != "")) + { + _Environnement.ExportOptions.ZoneMin = strupr (_Environnement.ExportOptions.ZoneMin); + _Environnement.ExportOptions.ZoneMax = strupr (_Environnement.ExportOptions.ZoneMax); + sint32 nNewMinX = CExport::getXFromZoneName (_Environnement.ExportOptions.ZoneMin); + sint32 nNewMinY = CExport::getYFromZoneName (_Environnement.ExportOptions.ZoneMin); + sint32 nNewMaxX = CExport::getXFromZoneName (_Environnement.ExportOptions.ZoneMax); + sint32 nNewMaxY = CExport::getYFromZoneName (_Environnement.ExportOptions.ZoneMax); + + if (nNewMinX > nNewMaxX) + swap (nNewMinX, nNewMaxX); + if (nNewMinY > nNewMaxY) + swap (nNewMinY, nNewMaxY); + + if (nNewMinX > nMinX) + nMinX = nNewMinX; + if (nNewMinY > nMinY) + nMinY = nNewMinY; + + if (nNewMaxX < nMaxX) + nMaxX = nNewMaxX; + if (nNewMaxY < nMaxY) + nMaxY = nNewMaxY; + } + + + for (sint32 j = nMinY; j <= nMaxY; ++j) + for (sint32 i = nMinX; i <= nMaxX; ++i) + { + const string &SrcZoneName = region.getName (i,j); + + if ((SrcZoneName == STRING_OUT_OF_BOUND) || + (SrcZoneName == STRING_UNUSED)) + continue; + + string DstZoneFileName = CExport::getZoneNameFromXY (i,j); + if (withIgs) + { + cfgFile.Igs.push_back (DstZoneFileName + ".ig"); + } + cfgFile.Zones.push_back (DstZoneFileName + ".zonel"); + } + + cfgFile.ZonesPath = this->_Environnement.ExportOptions.OutZoneDir; + cfgFile.IgPath = this->_Environnement.ExportOptions.OutIGDir; + + + string sTmp = this->_Environnement.ExportOptions.TileBankFile; + string sBanksPath, sBankName; + int pos = sTmp.rfind('\\'); + for (int i = 0; i < pos; ++i) + sBanksPath += sTmp[i]; + ++i; + for (; i < (int)sTmp.size(); ++i) + sBankName += sTmp[i]; + + cfgFile.BanksPath = sBanksPath; + cfgFile.TilesPath = sBanksPath; + cfgFile.Bank = sBankName; + + + + + // + cfgFile.save (cfgFileName); + + // Launch the zviewer program + const char *exeFileName = "zviewer.exe"; + if (NLMISC::CFile::fileExists(exeFileName)) + { + _spawnl (_P_WAIT, exeFileName, "aze", NULL); + } + else + { + MessageBox((std::string("unable to find ") + exeFileName).c_str(), "WorldEditor", MB_OK | MB_ICONEXCLAMATION); + } +} +*/ + +// *************************************************************************** + +/* Old Trap End */ + +void CMainFrame::onProjectAddlandscape() +{ + CFileDialogEx dialog (BASE_REGISTRY_KEY, "land", TRUE, "land", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "NeL Ligo Landscape Files (*.land)|*.land|All Files (*.*)|*.*||", this); + if (dialog.DoModal() == IDOK) + { + // Add the landscape in the project + getDocument ()->beginModification (); + getDocument ()->addModification (new CActionAddLandscape (dialog.GetPathName())); + getDocument ()->endModification (); + + // Update data + updateData (); + + // If data direcrory is empty, auto-assign it to landscape directory + if (getDocument()->getDataDir() != "") + return; + + string path = dialog.GetPathName(); + + uint pos = path.rfind("\\"); + if (pos == string::npos) + return; + + path.erase(pos, path.size()); + getDocument()->setDataDir(path.c_str()); + + // Init the landscape + initLandscapeData(); + } +} + +// *************************************************************************** + +void CMainFrame::onProjectNewlandscape() +{ + // Add the landscape in the project + getDocument ()->beginModification (); + getDocument ()->addModification (new CActionNewLandscape ()); + getDocument ()->endModification (); + + // Update data + updateData (); +} + +// *************************************************************************** + +bool CMainFrame::initLandscapeData () +{ + // Disable events + CNoInteraction nointeraction; + + const string &dataDir = getDocument ()->getDataDir (); + + _Environnement.DataDir = dataDir; + launchLoadingDialog ("loading ligo zones"); + if (_ZoneBuilder) + delete _ZoneBuilder; + _ZoneBuilder = new CBuilderZone (theApp.Config.ZoneSnapShotRes); + _ZoneBuilder->init (dataDir, false, DispWnd); + terminateLoadingDialog(); + + // Get pointer on the document + CWorldEditorDoc *doc = getDocument (); + if (doc) + { + // For each landscape + uint count = doc->getNumDatabaseElement (); + for (uint land = 0; land < count; land++) + { + // Is a landscape + if (doc->isLandscape (land)) + { + // Get the landscape name + const string &name = doc->getDatabaseElement (land); + + launchLoadingDialog (("loading landscape " + NLMISC::CFile::getFilename (name)).c_str ()); + + // Load it + _ZoneBuilder->refresh (); + + terminateLoadingDialog(); + } + } + } + + // Reinit the tools + initTools(); + + // Release and reload pacs if needed + PacsManager.releasePacs(); + string dir; + dir = getDocument ()->getDataDir (); + if (dir == "") + { + if (_ExeDir == "") + { + dir = NLMISC::CPath::getCurrentPath(); + } + else + { + dir = _ExeDir; + } + } + dir += "/pacs"; + PacsManager.setDir(dir); + // load PACS only if they are visible + if (_ShowPACS) + { + launchLoadingDialog ("loading PACS"); + PacsManager.loadPacs(); + terminateLoadingDialog(); + } + + return true; +} + +// *************************************************************************** + +CWorldEditorDoc *CMainFrame::getDocument () +{ + return (CWorldEditorDoc *)(GetActiveDocument ()); +} + +// *************************************************************************** + +void CMainFrame::onProjectSettings() +{ + CProjectSettings projectSettings; + if (projectSettings.DoModal () == IDOK) + { + bool initLandscape = false; + + // Get the new data path + std::string oldDataDir = standardizePath (getDocument ()->getDataDir ().c_str ()); + std::string newDataDir = standardizePath (projectSettings.DataDirectory); + initLandscape |= (oldDataDir != newDataDir); + getDocument ()->setDataDir (projectSettings.DataDirectory); + + // Init the landscape + if (initLandscape) + initLandscapeData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditTransition(CCmdUI* pCmdUI) +{ + // TODO: Add your command update UI handler code here + +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditZone(CCmdUI* pCmdUI) +{ + // TODO: Add your command update UI handler code here + +} + +// *************************************************************************** + +void CMainFrame::onUpdateModeUndo(CCmdUI* pCmdUI) +{ + pCmdUI->Enable (getDocument ()->undoAvailable () ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::onUpdateModeRedo(CCmdUI* pCmdUI) +{ + pCmdUI->Enable (getDocument ()->redoAvailable () ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditLogic(CCmdUI* pCmdUI) +{ + // TODO: Add your command update UI handler code here + +} + +// *************************************************************************** + +void CMainFrame::OnProjectImportPrim() +{ + CFileDialogEx dialog (BASE_REGISTRY_KEY, "prim", TRUE, "prim", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Old NeL Ligo Prim Files (*.prim)|*.prim|All Files (*.*)|*.*||", this); + if (dialog.DoModal() == IDOK) + { + // Add the landscape in the project + getDocument ()->beginModification (); + getDocument ()->addModification (new CActionImportPrimitive (dialog.GetPathName())); + getDocument ()->endModification (); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnProjectAddPrimitive() +{ + static char buffer[32000]; + CFileDialogEx dialog (BASE_REGISTRY_KEY, "primitive", TRUE, "primitive", NULL, OFN_ALLOWMULTISELECT|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "NeL Ligo Primitive Files (*.primitive)|*.primitive|All Files (*.*)|*.*||", this); + // increase result buffer size (for multi select) + memset(buffer, 0, 32000); + dialog.m_ofn.lpstrFile = buffer; + dialog.m_ofn.nMaxFile = 32000; + if (dialog.DoModal() == IDOK) + { + // Add the landscape in the project + getDocument ()->beginModification (); + { + POSITION pos; + pos = dialog.GetStartPosition(); + + while (pos!=NULL) + { + string path = dialog.GetNextPathName(pos); + if (!getDocument()->isPrimitiveLoaded(path)) + getDocument ()->addModification (new CActionLoadPrimitive (path.c_str())); + else + infoMessage("Primitive already existing: %s", path.c_str()); + } + } + getDocument ()->endModification (); + + // Verify primitive structures + VerifyPrimitivesStructures(); + + // Update data + updateData (); + } + +} + +// *************************************************************************** + +void CMainFrame::OnProjectClearallprimitive() +{ + // Add the landscape in the project + getDocument ()->beginModification (); + getDocument ()->addModification (new CActionClearPrimitives ()); + getDocument ()->endModification (); + + // Update data + updateData (); +} + +// *************************************************************************** + +void CMainFrame::setSelectionLocked (bool lock) +{ + if (_SelectionLocked != lock) + { + CMenu *menu = GetMenu(); + _SelectionLocked = lock; + if (_SelectionLocked) + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_LOCK); + menu->CheckMenuItem (ID_EDIT_LOCK, MF_CHECKED|MF_BYCOMMAND); + } + else + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_LOCK, FALSE); + menu->CheckMenuItem (ID_EDIT_LOCK, MF_UNCHECKED|MF_BYCOMMAND); + } + + // Set the current mode + setTransformMode (_TransformModes[(uint)_SelectionLocked]); + + // Invaludate view + invalidateLeftView (); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnEditSelectAll() +{ + if (_Mode == 1) // Mode Logic + { + // Add the landscape in the project + getDocument ()->beginModification (); + getDocument ()->addModification (new CActionSelectAll ()); + getDocument ()->endModification (); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnEditLock() +{ + if (_Mode == 1) // Mode Logic + { + // Toggle lock + _SelectionLocked ^= true; + CMenu *menu = GetMenu(); + if (_SelectionLocked) + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_LOCK); + menu->CheckMenuItem (ID_EDIT_LOCK, MF_CHECKED|MF_BYCOMMAND); + } + else + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_LOCK, FALSE); + menu->CheckMenuItem (ID_EDIT_LOCK, MF_UNCHECKED|MF_BYCOMMAND); + } + + // Set the current mode + setTransformMode (_TransformModes[(uint)_SelectionLocked]); + + // Invalidate left view + invalidateLeftView (); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnEditDetails() +{ + if (_Mode == 1) // Mode Logic + { + // Toggle lock + _ShowDetails ^= true; + CMenu *menu = GetMenu(); + if (_ShowDetails) + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_DETAILS); + menu->CheckMenuItem (ID_EDIT_DETAILS, MF_CHECKED|MF_BYCOMMAND); + } + else + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_DETAILS, FALSE); + menu->CheckMenuItem (ID_EDIT_DETAILS, MF_UNCHECKED|MF_BYCOMMAND); + } + + // Invalidate left view + invalidateLeftView (); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnViewLandscape() +{ + // Toggle lock + _ShowLandscape ^= true; + CMenu *menu = GetMenu(); + if (_ShowLandscape) + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_LANDSCAPE); + menu->CheckMenuItem (ID_VIEW_LANDSCAPE, MF_CHECKED|MF_BYCOMMAND); + } + else + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_LANDSCAPE, FALSE); + menu->CheckMenuItem (ID_VIEW_LANDSCAPE, MF_UNCHECKED|MF_BYCOMMAND); + } + + // Invalidate left view + invalidateLeftView (); + + // Update data + updateData (); +} + +// *************************************************************************** + +void CMainFrame::OnViewGrid() +{ + // Toggle lock + _ShowGrid ^= true; + CMenu *menu = GetMenu(); + if (_ShowGrid) + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_GRID); + menu->CheckMenuItem (ID_VIEW_GRID, MF_CHECKED|MF_BYCOMMAND); + } + else + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_GRID, FALSE); + menu->CheckMenuItem (ID_VIEW_GRID, MF_UNCHECKED|MF_BYCOMMAND); + } + + // Invalidate left view + invalidateLeftView (); + + // Update data + updateData (); +} + +// *************************************************************************** + +void CMainFrame::OnViewPoints() +{ + // Toggle lock + _ShowPoints ^= true; + CMenu *menu = GetMenu(); + if (_ShowPoints) + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_POINTS); + menu->CheckMenuItem (ID_VIEW_POINTS, MF_CHECKED|MF_BYCOMMAND); + } + else + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_POINTS, FALSE); + menu->CheckMenuItem (ID_VIEW_POINTS, MF_UNCHECKED|MF_BYCOMMAND); + } + + // Invalidate left view + invalidateLeftView (); + + // Update data + updateData (); +} + +// *************************************************************************** + +void CMainFrame::OnViewPACS() +{ + // Toggle lock + _ShowPACS ^= true; + CMenu *menu = GetMenu(); + if (_ShowPACS) + { + // load PACS if it's not already done + if(!PacsManager.areLoaded()) + { + launchLoadingDialog ("loading PACS"); + PacsManager.loadPacs(); + terminateLoadingDialog(); + } + + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_PACS); + menu->CheckMenuItem (ID_VIEW_PACS, MF_CHECKED|MF_BYCOMMAND); + } + else + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_PACS, FALSE); + menu->CheckMenuItem (ID_VIEW_PACS, MF_UNCHECKED|MF_BYCOMMAND); + } + + // Invalidate left view + invalidateLeftView (); + + // Update data + updateData (); +} + +// *************************************************************************** + +void CMainFrame::OnViewLayers() +{ + // Toggle lock + _ShowLayers ^= true; + CMenu *menu = GetMenu(); + if (_ShowLayers) + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_LAYERS); + menu->CheckMenuItem (ID_VIEW_LAYERS, MF_CHECKED|MF_BYCOMMAND); + } + else + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_LAYERS, FALSE); + menu->CheckMenuItem (ID_VIEW_LAYERS, MF_UNCHECKED|MF_BYCOMMAND); + } + + // Invalidate left view + invalidateLeftView (); + + // Update data + updateData (); +} + +// *************************************************************************** + +void CMainFrame::OnViewPrimitives () +{ + // Toggle lock + _ShowPrimitives ^= true; + CMenu *menu = GetMenu(); + if (_ShowPrimitives) + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_PRIMITIVES); + menu->CheckMenuItem (ID_VIEW_PRIMITIVES, MF_CHECKED|MF_BYCOMMAND); + } + else + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_PRIMITIVES, FALSE); + menu->CheckMenuItem (ID_VIEW_PRIMITIVES, MF_UNCHECKED|MF_BYCOMMAND); + } + + // Invalidate left view + invalidateLeftView (); + + // Update data + updateData (); +} + +// *************************************************************************** + +void CMainFrame::OnEditTranslate() +{ + setTransformMode (Move); +} + +// *************************************************************************** + +void CMainFrame::OnEditRotate() +{ + setTransformMode (Rotate); +} + +// *************************************************************************** + +void CMainFrame::OnEditTurn() +{ + setTransformMode (Turn); +} + +// *************************************************************************** + +void CMainFrame::OnEditRadius() +{ + setTransformMode (Radius); +} + +// *************************************************************************** + +void CMainFrame::OnEditScale() +{ + setTransformMode (Scale); +} + +// *************************************************************************** + +void CMainFrame::OnEditAddPoint() +{ + setTransformMode (AddPoint); +} + +// *************************************************************************** + +void CMainFrame::OnEditSelect() +{ + setTransformMode (Select); +} + +// *************************************************************************** + +void CMainFrame::setTransformMode (TTransformMode mode) +{ + CMenu *menu = GetMenu(); + menu->CheckMenuRadioItem( ID_EDIT_SELECT, ID_EDIT_ADD_POINT, ID_EDIT_SELECT+mode, MF_BYCOMMAND); + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_EDIT_SELECT+mode); + + _TransformModes[(uint)_SelectionLocked] = mode; +} + +// *************************************************************************** + +void CMainFrame::deletePrimitive (bool subDelete, const char *actionName) +{ + list oldSelection; + + list::iterator it = PropertiesDialogs.begin(); + while ( it != PropertiesDialogs.end() ) + { + bool closeDialog = false; + if ( (*it)->containsSelection( Selection ) ) + { + closeDialog = (*it)->removePrimitives( Selection ); + } + + if ( closeDialog ) + it = PropertiesDialogs.begin(); // iterator became invalid + else + it++; + } + + // Get pointer on the document + CWorldEditorDoc *doc = getDocument (); + + // Begin modification + doc->beginModification (); + + if (_Mode == 1) // Mode Logic + { + // Next primitive to select + bool locatorValid = false; + CDatabaseLocatorPointer locatorNext; + + // Delete + if (subDelete) + { + // For all the selection + list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Point primitive ? + const CPrimPointEditor *point = dynamic_cast (locator.Primitive); + if (point) + { + } + else + { + // Path + const CPrimPathEditor *path = dynamic_cast (locator.Primitive); + const CPrimZoneEditor *zone = dynamic_cast (locator.Primitive); + if (path || zone) + { + while (1) + { + // Get the good primitive + const IPrimitive *primitive = (const IPrimitive *)path ? (const IPrimitive *)path : (const IPrimitive *)zone; + uint count = primitive->getNumVector (); + if (count) + { + const CPrimVector *primVector = primitive->getPrimVector (); + uint i; + for (i=0; iaddModification (new CActionDeleteSub (locator)); + break; + } + } + + // Done ? + if (i == count) + { + break; + } + } + else + break; + } + } + } + + ite++; + } + } + else + { + // For all the selection + list::iterator ite; + ite = Selection.begin (); + while (ite != Selection.end ()) + { + bool deleted = false; + + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Node or prim file ? + if (locator.Primitive->getParent ()) + { + // Primitive deletable ? + if (theApp.Config.isPrimitiveDeletable (*(locator.Primitive))) + { + // Select the next primitive after delete + CDatabaseLocatorPointer locatorNext2 = locator; + if (locatorNext2.nextChild ()) + locatorNext = locator; + else + { + // Get previous node + locatorNext2 = locator; + locatorNext2.previousChild (); + locatorNext = locatorNext2; + } + locatorValid = true; + + doc->addModification (new CActionDelete (locator)); + deleted = true; + } + } + else + { + // Editable ? + uint index = locator.getDatabaseIndex (); + if (doc->_DataHierarchy[index].Editable) + { + // Select the next primitive after delete + locatorValid = false; + + doc->addModification (new CActionDeleteDatabaseElement (locator.getDatabaseIndex ())); + deleted = true; + } + } + + // Update selection, restart to the beginning + if (deleted) + { + UpdateSelection (); + ite = Selection.begin (); + } + else + ite++; + } + } + + // Select a new primitive ? + if (locatorValid) + doc->addModification (new CActionSelect (locatorNext)); + } + + // End modification + doc->endModification (); + + // Update data + updateData (); +} + +// *************************************************************************** + +void CMainFrame::OnEditDelete() +{ + deletePrimitive (isSelectionLocked (), "Delete"); +} + +// *************************************************************************** + +void CMainFrame::OnProjectNewPrimitive() +{ + // Get pointer on the document + CWorldEditorDoc *doc = getDocument (); + + // Add the landscape in the project + doc->beginModification (); + doc->addModification (new CActionNewPrimitive ()); + + // Select it + doc->addModification (new CActionUnselectAll ()); + + // Locator + CDatabaseLocatorPointer locator; + locator.getRoot (doc->getNumDatabaseElement ()-1); + doc->addModification (new CActionSelect (locator)); + + doc->endModification (); + + // Update data + updateData (); +} + +// *************************************************************************** + +void CMainFrame::OnEditProperties() +{ + list::iterator it = PropertiesDialogs.begin(); + bool ok = false; + ::CRect dlgPos(0, 0, 0, 0); + + while ( !ok && ( it != PropertiesDialogs.end() ) ) + { + if ( (*it)->equalsSelection( Selection ) ) + { + (*it)->ShowWindow( SW_SHOW ); + (*it)->SetFocus(); + + ok = true; + } + + it++; + } + + if ( !ok ) + { + CDialogProperties *pDlg = new CDialogProperties( Selection ); + pDlg->Create( IDD_PROPERTIES ); + + pDlg->GetWindowRect( &dlgPos ); + + CPoint point = CDialogProperties::getLastPosition(); + + if ( point != CPoint(-1, -1) ) + { + int diffX = point.x - dlgPos.left; + int diffY = point.y - dlgPos.top; + dlgPos.OffsetRect( diffX, diffY ); + + pDlg->MoveWindow( &dlgPos ); + } + + pDlg->ShowWindow( SW_SHOW ); + pDlg->SetFocus(); + + PropertiesDialogs.push_back( pDlg ); + } +} + +// *************************************************************************** + +void CMainFrame::OnAddPrimitive (UINT nID) +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Begin modification + doc->beginModification (); + + // Only one selection ? + nlassert (Selection.size () == 1); + nlassert (Selection.front ()); + + // What class is it ? + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*(Selection.front ())); + nlassert (primClass); + uint childId = nID - ID_EDIT_CREATE_BEGIN; + + // Get the child class + CDatabaseLocatorPointer insert; + doc->getLocator (insert, Selection.front ()); + CDatabaseLocator dest; + insert.appendChild (dest); + + // Position on the Display + CDisplay *display = getDisplay (); + float delta = (float)DELTA_POS_ADD_PRIMITIVE * (display->_CurViewMax.x - display->_CurViewMin.x) / (float)display->getWidth (); + if (doc->addModification (new CActionAddPrimitiveByClass (dest, primClass->DynamicChildren[childId].ClassName.c_str (), getDisplay ()->_CurPos, + delta, primClass->DynamicChildren[childId].Parameters))) + { + // Unselect all + doc->addModification (new CActionUnselectAll ()); + + // Select it + doc->addModification (new CActionSelect (dest)); + } + + // End modification + doc->endModification (); + + // Update the data + updateData (); +} + +// *************************************************************************** + +void CMainFrame::OnGeneratePrimitive (UINT nID) +{ + // Disable events + CNoInteraction nointeraction; + + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Begin modification + doc->beginModification (); + + // Primitive generator + CGeneratePrimitive generatePrimitive; + + // Load in primitive + if (!Selection.empty ()) + { + // Progress bar + CWorldEditorProgressCallback callback; + + // In / out primitives + std::vector< std::vector > out; + std::vector in; + + // Add primitives + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + in.push_back (locator.Primitive); + ite++; + } + + // What class is it ? + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*(Selection.front ())); + nlassert (primClass); + + // Should exist + nlassert ( (nID - ID_EDIT_GENERATE_BEGIN) < primClass->GeneratedChildren.size ()); + + // Generate it + if (generatePrimitive.generate (out, in, callback, theApp.Config, doc->getDataDir ().c_str (), + primClass->GeneratedChildren[nID-ID_EDIT_GENERATE_BEGIN].ClassName.c_str () )) + { + // Checks + nlassert (out.size () == Selection.size ()); + + // Add primitives + uint i=0; + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + for (uint j=0;jaddModification (new CActionAddPrimitive (out[i][j], newLocator)); + } + + ite++; + i++; + } + } + } + + // End modification + doc->endModification (); + + // Update the data + updateData (); +} + +// *************************************************************************** + +void CMainFrame::buildFilenameVector (const IPrimitive &primitive, std::vector &dest) +{ + // What class is it ? + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (primitive); + nlassert (primClass); + + // Look for files + uint i; + for (i=0; iParameters.size (); i++) + { + // File ? + if (primClass->Parameters[i].Filename) + { + // Exist ? + string name; + if (primitive.getPropertyByName (primClass->Parameters[i].Name.c_str (), name) && !name.empty ()) + { + // Add the file + string ext; + + // Build an extension + if (!primClass->Parameters[i].FileExtension.empty ()) + ext = "."+primClass->Parameters[i].FileExtension; + + // Lookup + string filename = name+ext; + if (primClass->Parameters[i].Lookup) + filename = CPath::lookup (filename, false, false, false); + if (!filename.empty ()) + { + dest.push_back (filename); + } + } + } + } +} + +// *************************************************************************** + +void CMainFrame::OnOpenFile (UINT nID) +{ + // Single selection + nlassert (Selection.size () == 1); + + // Good id + nID -= ID_EDIT_OPEN_FILE_BEGIN; + + // Filenames + std::vector files; + buildFilenameVector (*Selection.front (), files); + + // File name must exist + nlassert (nIDCreatePopupMenu (); + + // Tranform mode ? + if (transformMode) + { + if (_Mode == 1) + { + // Add commands + pMenu->AppendMenu (MF_STRING, ID_EDIT_SELECT, "&Select\tF5"); + pMenu->AppendMenu (MF_STRING, ID_EDIT_TRANSLATE, "&Move\tF6"); + pMenu->AppendMenu (MF_STRING, ID_EDIT_ROTATE, "&Rotate\tF7"); + pMenu->AppendMenu (MF_STRING, ID_EDIT_TURN, "&Turn\tF8"); + pMenu->AppendMenu (MF_STRING, ID_EDIT_SCALE, "&Scale\tF9"); + pMenu->AppendMenu (MF_STRING, ID_EDIT_RADIUS, "&Radius\tF10"); + if (isSelectionLocked ()) + pMenu->AppendMenu (MF_STRING, ID_EDIT_ADD_POINT, "&Add points\tF11"); + + // Check the good one + pMenu->CheckMenuRadioItem (ID_EDIT_SELECT, isSelectionLocked ()?ID_EDIT_ADD_POINT:ID_EDIT_SCALE, ID_EDIT_SELECT+getTransformMode (), + MF_BYCOMMAND); + + // Add separator + pMenu->AppendMenu (MF_SEPARATOR); + } + } + + // Always a delete menu + pMenu->AppendMenu (MF_STRING, ID_EDIT_DELETE, "&Delete\tDel"); + + // Add properties menu + pMenu->AppendMenu (MF_STRING, ID_EDIT_PROPERTIES, "&Properties\tAlt+Enter"); + + // Select Children + pMenu->AppendMenu (MF_STRING, ID_EDIT_SELECT_CHILDREN, "&Select Children\tC"); + + // Tree help + pMenu->AppendMenu (MF_STRING, ID_HELP_FINDER, "&Help\tF1"); + + // Add separator + pMenu->AppendMenu (MF_SEPARATOR); + pMenu->AppendMenu (MF_STRING, ID_RENAME_SELECTED, "&Rename All Selected"); + pMenu->AppendMenu (MF_STRING, ID_REPAIR_SELECTED, "&Repair All Selected"); + + // Add separator + pMenu->AppendMenu (MF_SEPARATOR); + + // Add properties menu + pMenu->AppendMenu (MF_STRING, ID_VIEW_SHOW, "&Show\tS"); + pMenu->AppendMenu (MF_STRING, ID_VIEW_HIDE, "&Hide\tH"); + + // Add separator + pMenu->AppendMenu (MF_SEPARATOR); + + // Add expand / collapse menu + pMenu->AppendMenu (MF_STRING, ID_EDIT_EXPAND, "&Expand\tE"); + pMenu->AppendMenu (MF_STRING, ID_EDIT_COLLAPSE, "&Collapse\tR"); + + // Only one selection ? + if (Selection.size () == 1) + { + // Primitive ? + if (Selection.front ()) + { + // What class is it ? + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*(Selection.front ())); + if (primClass && primClass->DynamicChildren.size ()) + { + // Add separator + pMenu->AppendMenu (MF_SEPARATOR); + + // For each child, add a create method + for (uint i=0; iDynamicChildren.size (); i++) + { + pMenu->AppendMenu (MF_STRING, ID_EDIT_CREATE_BEGIN+i, ("Add "+primClass->DynamicChildren[i].ClassName).c_str ()); + } + } + + // What class is it ? + if (primClass && primClass->GeneratedChildren.size ()) + { + // Add separator + pMenu->AppendMenu (MF_SEPARATOR); + + // For each child, add a create method + for (uint i=0; iGeneratedChildren.size (); i++) + { + pMenu->AppendMenu (MF_STRING, ID_EDIT_GENERATE_BEGIN+i, ("Generate "+primClass->GeneratedChildren[i].ClassName).c_str ()); + } + } + + // What class is it ? + if (primClass) + { + // Look for files + vector filenames; + + // Filenames + buildFilenameVector (*Selection.front (), filenames); + + // File names ? + if (!filenames.empty ()) + { + // Add separator + pMenu->AppendMenu (MF_SEPARATOR); + + // Found ? + uint i; + for (i=0; iAppendMenu (MF_STRING, ID_EDIT_OPEN_FILE_BEGIN+i, ("Open "+NLMISC::CFile::getFilename (filenames[i])).c_str ()); + } + } + } + } + } + + pMenu->TrackPopupMenu (TPM_LEFTALIGN | TPM_LEFTBUTTON, point.x, point.y, parent); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditAddPoint(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ((_SelectionLocked && (_Mode==1)) ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditLock(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditProperties(CCmdUI* pCmdUI) +{ + pCmdUI->Enable (isInteraction () && (_Mode==1) ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditRotate(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditScale(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditSelectAll(CCmdUI* pCmdUI) +{ + pCmdUI->Enable (isInteraction () && (_Mode==1) ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditTranslate(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditTurn(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditRadius(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditSelect(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ((_Mode==1) ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditDetails(CCmdUI* pCmdUI) +{ +} + +// *************************************************************************** + +void CMainFrame::OnUpdateViewLandscape(CCmdUI* pCmdUI) +{ +} + +// *************************************************************************** + +void CMainFrame::deletePrimitiveClipboard () +{ + // Delete each clipboard entry + for (uint i=0; i<_PrimitiveClipboard.size (); i++) + delete _PrimitiveClipboard[i]; + _PrimitiveClipboard.clear (); +} + +// *************************************************************************** + +void CMainFrame::OnEditCopy() +{ + // Only if one node selected + if (!Selection.empty ()) + { + // Free the clipboard + deletePrimitiveClipboard (); + + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Add primitives + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Copy it + _PrimitiveClipboard.push_back (locator.Primitive->copy ()); + + // Unselect it + getPrimitiveEditor(_PrimitiveClipboard.back ())->setSelected(false); +// _PrimitiveClipboard.back ()->removePropertyByName ("selected"); + + ite++; + } + + // Update data + updateData (); + } +} +// *************************************************************************** + +void CMainFrame::OnEditCut() +{ + // Only if one node selected + if (!Selection.empty ()) + { + // Copy + OnEditCopy(); + + // Delete + deletePrimitive (false, "Cut"); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditCopy(CCmdUI* pCmdUI) +{ + // Something selected ? + pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI) +{ + // Something selected ? + pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); +} + +// *************************************************************************** + +void CMainFrame::OnEditPaste() +{ + // Only if one node selected + if ((!Selection.empty ()) && (!_PrimitiveClipboard.empty ())) + { + // Get the document + CWorldEditorDoc *doc = getDocument (); + sint lastChildPos = -1; // position of the last child of the selection + + // Begin modification + doc->beginModification (); + + for (uint i=0; i<_PrimitiveClipboard.size (); i++) + { + // Paste it ? + CDatabaseLocatorPointer locator; + bool paste = false; + + // Is this a root ? + if (Selection.front ()->getParent ()) + { + // Try to add it as children of the selection + if (theApp.Config.canBeChild (*(_PrimitiveClipboard[i]), *(Selection.front ()))) + { + // Get last children index (before insertion) + if ( lastChildPos == -1 ) + lastChildPos = Selection.front()->getNumChildren()-1; + + if ( lastChildPos >= 0 ) + { + IPrimitive* prim; + Selection.front()->getChild( prim, lastChildPos ); + doc->getLocator ( locator, prim ); + + if ( ! locator.nextChild() ) + locator.appendChild ( locator ); + } + else + { + doc->getLocator ( locator, Selection.front() ); + locator.appendChild ( locator ); + } + + + paste = true; + } + else + { + // Can be a child ? + if (theApp.Config.canBeChild (*(_PrimitiveClipboard[i]), *(Selection.front ()->getParent ()))) + { + // Paste after this locator + doc->getLocator ( locator, Selection.front() ); + if ( !locator.nextChild () ) + locator.appendChild ( locator ); + paste = true; + } + } + } + else + { + // Try to add it as children of the selection + if (theApp.Config.canBeRoot (*(_PrimitiveClipboard[i]))) + { + // Get first children + doc->getLocator (locator, Selection.front ()); + locator.appendChild (locator); + paste = true; + } + } + + // Paste it ? + if (paste) + { + // Add the primitive + doc->addModification (new CActionAddPrimitive (*(_PrimitiveClipboard[i]), locator)); + + // New locator + CDatabaseLocator newLocator = locator; + doc->getLocator (locator, newLocator); + + // Change its name + string name; + if (locator.Primitive->getPropertyByName ("name", name)) + { + // Get children count + if (locator.Primitive->getParent ()) + { + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*locator.Primitive); + if ((primClass == NULL) || primClass->Numberize) + { + // Set the number to the number of brothers (-1 because the node has just been created) + name = numberize (name.c_str (), locator.Primitive->getParent ()->getNumChildren ()); + + // Change the name + doc->addModification (new CActionSetPrimitivePropertyString (locator, "name", name.c_str (), false)); + } + } + } + } + else + { + // special case. + if ( _PrimitiveClipboard[i] + && _PrimitiveClipboard[i]->getClassName()=="CPrimZone" + && Selection.front () + && Selection.front ()->getClassName()=="CPrimZone" + && Selection.front ()->getParent() ) + { + // Get the child class + CDatabaseLocatorPointer insert; + doc->getLocator (insert, Selection.front ()->getParent()); + CDatabaseLocator dest; + insert.appendChild (dest); + + // Position on the Display + CDisplay *display = getDisplay (); + float delta = (float)DELTA_POS_ADD_PRIMITIVE * (display->_CurViewMax.x - display->_CurViewMin.x) / (float)display->getWidth (); + + string className; + if (Selection.front ()->getPropertyByName ("class", className)) + { + std::vector empty; + doc->addModification (new CActionAddPrimitiveByClass (dest, className.c_str (), getDisplay ()->_CurPos, + delta, empty)); + } + + // Now copy the shape .. + sint nbVert=_PrimitiveClipboard[i]->getNumVector(); + const CPrimVector *vectors = _PrimitiveClipboard[i]->getPrimVector (); + for (sint j=nbVert-1; j>=0; j--) + doc->addModification (new CActionAddVertex(dest, vectors[j])); + } + + } + + } + + // Begin modification + doc->endModification (); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditPaste(CCmdUI* pCmdUI) +{ + // Only if one node selected and clipboard not empty + pCmdUI->Enable (isInteraction () && ((!Selection.empty()) && (!_PrimitiveClipboard.empty ())) ? TRUE : FALSE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateViewHide(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); +} + +// *************************************************************************** + +void CMainFrame::OnViewHide() +{ + // Only if one node selected + if (!Selection.empty ()) + { + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Begin modifications + doc->beginModification (); + + // Copy selected primitives + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Add the modification + doc->addModification (new CActionShowHide (locator, false)); + + ite++; + } + + // End modifications + doc->endModification (); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnViewShow() +{ + // Only if one node selected + if (!Selection.empty ()) + { + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Begin modifications + doc->beginModification (); + + // Copy selected primitives + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Add the modification + doc->addModification (new CActionShowHide (locator, true)); + + ite++; + } + + // End modifications + doc->endModification (); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnEditExpand() +{ + // Only if one node selected + if (!Selection.empty ()) + { + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Copy selected primitives + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Add the modification + getPrimitiveEditor(locator.Primitive)->setExpanded(true); +// locator.Primitive-> +// const_cast (locator.Primitive)->Expanded = true; + InvalidatePrimitiveRec (locator, LogicTreeStruct); + + ite++; + } + + // Invalidate tools + invalidateTools (); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnEditCollapse() +{ + // Only if one node selected + if (!Selection.empty ()) + { + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Copy selected primitives + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Add the modification + getPrimitiveEditor(locator.Primitive)->setExpanded(false); +// const_cast (locator.Primitive)->Expanded = false; + InvalidatePrimitiveRec (locator, LogicTreeStruct); + + ite++; + } + + // Invalidate tools + invalidateTools (); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnUpdateViewShow (CCmdUI* pCmdUI) +{ + pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditExpand (CCmdUI* pCmdUI) +{ + pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditCollapse (CCmdUI* pCmdUI) +{ + pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); +} + +// *************************************************************************** + +void selectChildren (CWorldEditorDoc *doc, const CDatabaseLocatorPointer &locator) +{ + // Fopr each children + CDatabaseLocatorPointer myLocator = locator; + if (myLocator.firstChild ()) + { + do + { + // Select it + doc->addModification (new CActionSelect (myLocator)); + + // Select its children + selectChildren (doc, myLocator); + } + while (myLocator.nextChild ()); + } +} + +// *************************************************************************** + +void CMainFrame::OnEditSelectChildren() +{ + // Only if one node selected + if (!Selection.empty ()) + { + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Begin modifications + doc->beginModification (); + + // Unselect all + doc->addModification (new CActionUnselectAll ()); + + // Copy selected primitives + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite); + + // Select children + selectChildren (doc, locator); + + ite++; + } + + // End modifications + doc->endModification (); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditSelectChildren(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); +} + +// *************************************************************************** + +void CMainFrame::OnTimer(UINT nIDEvent) +{ + if (nIDEvent == TIMER_UPDATE_FILES) + { + if (TimerEnabled) + { + TimerEnabled = false; + // Check file modification + getDocument ()->updateFiles (); + TimerEnabled = true; + } + } + if (nIDEvent == TIMER_PLUGINS) + { + for (uint i=0; ionIdle(); + } + // check if plugin querried to refresh the property dialog + if (_MustRefreshPropertyDialog) + { + std::list::iterator it = PropertiesDialogs.begin(); + + while ( it != PropertiesDialogs.end() ) + { + (*it)->updateModification(); + it++; + } + + //PropertyDialog.changeSelection (Selection); + _MustRefreshPropertyDialog = false; + } + } + CFrameWnd::OnTimer(nIDEvent); +} + +// *************************************************************************** + +void CMainFrame::OnHelpFinder() +{ + if (Selection.size () == 1) + { + CWorldEditorDoc *doc = getDocument (); + + // For each selected primitives + std::list::iterator ite1 = Selection.begin (); + + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite1); + + const IPrimitive *primitive = locator.Primitive; + if (primitive) + { + string className; + bool Success; + Success = primitive->getPropertyByName ("class", className); + if (!Success) + { + // is this the root node ? + const IPrimitive *parent = primitive->getParent(); + if (!parent) + { + // if no parent, we have a root node + className = "root"; + Success = true; + } + } + if (Success) + { + //string filename = theApp.ExePath+"doc/"+className+".html"; + string filename = theApp.DocPath+"/"+className+".html"; + if (!NLMISC::CFile::fileExists(filename) || !openFile (filename.c_str ())) + { + //openFile ((theApp.ExePath+"world_editor.html").c_str ()); + theApp.errorMessage ("Can't open the file %s", filename.c_str ()); + } + } + } + } + else + { + openFile ((theApp.ExePath+"world_editor.html").c_str ()); + } +} + +// *************************************************************************** + +void CMainFrame::interaction (bool enable) +{ + CDisplay *display = getDisplay (); + if (display) + display->Interactif = enable; +} + +// *************************************************************************** + +bool CMainFrame::isInteraction () const +{ + CDisplay *display = getDisplay (); + if (display) + return display->Interactif; + else + return false; +} + +// *************************************************************************** +// CWorldEditorProgressCallback +// *************************************************************************** + +CWorldEditorProgressCallback::CWorldEditorProgressCallback () +{ + getMainFrame ()->launchLoadingDialog (""); +} + +// *************************************************************************** + +CWorldEditorProgressCallback::~CWorldEditorProgressCallback () +{ + getMainFrame ()->terminateLoadingDialog (); +} + +// *************************************************************************** + +void CWorldEditorProgressCallback::progress (float value) +{ + getMainFrame ()->LoadingDialog->setText (this->DisplayString); + getMainFrame ()->progressLoadingDialog (value); +} + +// *************************************************************************** + +void CMainFrame::OnViewLocateselectedprimitives() +{ + // Not empty ? + if (!Selection.empty ()) + { + // Selection bbox + CAABBox box; + bool first = true; + + // For each selected primitives + std::list::iterator ite = Selection.begin (); + while (ite != Selection.end ()) + { + // Extend + uint vertices = (*ite)->getNumVector (); + if (vertices) + { + uint i; + const CPrimVector *v = (*ite)->getPrimVector (); + for (i=0; isetDisplayRegion (box.getMin (), box.getMax ()); + + // Add a border + CVector locateBorder (0, 0, 0); + CVector locateBorder2 (LOCATE_BORDER, LOCATE_BORDER, 0); + getDisplay ()->pixelToWorld (locateBorder); + getDisplay ()->pixelToWorld (locateBorder2); + locateBorder = locateBorder2 - locateBorder; + getDisplay ()->setDisplayRegion (box.getMin ()-locateBorder, box.getMax ()+locateBorder); + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnUpdateViewLocateselectedprimitives(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); +} + +// *************************************************************************** + +void CMainFrame::OnViewLocateselectedprimitivesTree() +{ + if (!Selection.empty ()) + { + CToolsLogic *const toolWnd = dynamic_cast(getMainFrame ()->m_wndSplitter.GetPane(0,1)); + if (toolWnd) + { + for (std::list::iterator it=Selection.begin(),itEnd=Selection.end();it!=itEnd;++it) + { + IPrimitiveEditor *const primEditor = dynamic_cast (*it); + toolWnd->ensureVisible (primEditor); + } + } + } +} + +// *************************************************************************** + +void CMainFrame::OnUpdateViewLocateselectedprimitivesTree(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ( isInteraction () && (Selection.empty () || (_Mode != 1)) ? FALSE : TRUE); +} + +// *************************************************************************** + +void CMainFrame::OnEditSelectByLocation() +{ + // Only in primitive mode + if ( (_Mode==1) && !isSelectionLocked () ) + { + // Selection dialog + static CSelectByLocation select; + uint mode; + switch (mode=select.DoModal ()) + { + case IDOK: + case IDMORE: + { + // Begin modification + CWorldEditorDoc *doc = getDocument (); + doc->beginModification (); + + // Unselect others primitives ? + if (mode == IDOK) + doc->addModification (new CActionUnselectAll ()); + + // Make a bbox + const float threshold = (float) fabs (select.Threshold); + CVector min = CVector (select.X - threshold, select.Y - threshold, 0); + CVector max = CVector (select.X + threshold, select.Y + threshold, 0); + + // Get the locator + std::vector result; + getDisplay ()->pickRect (min, max, result, false); + + // Parse + uint i; + for (i=0; iaddModification (new CActionSelect (result[i])); + } + + // End modification + doc->endModification (); + } + } + + // Update data + updateData (); + } +} + +// *************************************************************************** + +void CMainFrame::OnUpdateEditSelectByLocation(CCmdUI* pCmdUI) +{ + pCmdUI->Enable ( (isInteraction () && (_Mode == 1)) ? TRUE : FALSE ); +} + +// *************************************************************************** + +void CMainFrame::OnProjectResetuniqueid() +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Begin modifications + doc->beginModification (); + + uint count = doc->getNumDatabaseElement (); + uint i; + for (i=0; iisPrimitive (i)) + { + const NLLIGO::CPrimitives &primitive = doc->getDatabaseElements (i); + doc->resetUniqueID (*primitive.RootNode); + } + } + + // End modifications + doc->endModification (); +} + +// *************************************************************************** + +void CMainFrame::OnProjectGeneratenullid() +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Begin modifications + doc->beginModification (); + + uint count = doc->getNumDatabaseElement (); + uint i; + for (i=0; iisPrimitive (i)) + { + const NLLIGO::CPrimitives &primitive = doc->getDatabaseElements (i); + doc->resetUniqueID (*primitive.RootNode, true); + } + } + + // End modifications + doc->endModification (); + +} + +// *************************************************************************** + +void CMainFrame::OnProjectForceiduniqueness() +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Begin modifications + doc->beginModification (); + + CHashSet ids; + std::vector nonUnique; +// uint32 regenCount = 0; + + uint count = doc->getNumDatabaseElement (); + uint i; + + // the operation is done in two step to avoid the assignation of already + // assigned ID to the first non unique ID found, generating more non + // unique ID when the loop reach the other primitives. + + // first loop to collect non properties with non unique ID + for (i=0; iisPrimitive (i)) + { + const NLLIGO::CPrimitives &primitive = doc->getDatabaseElements (i); + doc->forceIDUniqueness(*primitive.RootNode, ids, nonUnique); +// doc->forceIDUniqueness(*primitive.RootNode, ids, regenCount); + } + } + + // second loop to regen the non unique IDs + for (uint i=0; iParameters.size(); ++j) + { + if (_class->Parameters[j].Name == nu.PropertyName) + { + if (_class->Parameters[j].Type == CPrimitiveClass::CParameter::String) + { + CDatabaseLocatorPointer locator; + doc->getLocator(locator, nu.Primitive); + + doc->addModification (new CActionSetPrimitivePropertyString (locator, nu.PropertyName.c_str (), toString (getUniqueId ()).c_str (), false)); + } + else if (_class->Parameters[j].Type == CPrimitiveClass::CParameter::StringArray) + { + uint k; + for (k=0; j<_class->Parameters[j].DefaultValue.size (); j++) + { + // Unique Id ? + if (_class->Parameters[j].DefaultValue[k].GenID) + { + std::vector result; + std::vector *resultPtr = NULL; + nu.Primitive->getPropertyByName (nu.PropertyName.c_str (), resultPtr); + + // Copy + if (resultPtr) + result = *resultPtr; + + // Resize + if (result.size ()<=k) + result.resize (k+1); + + // Set the value + result[k] = toString (getUniqueId ()); + + CDatabaseLocatorPointer locator; + doc->getLocator (locator, nu.Primitive); + doc->addModification (new CActionSetPrimitivePropertyStringArray (locator, nu.PropertyName.c_str (), result, false)); + } + } + } + break; + } + } + } + } + + // End modifications + doc->endModification (); + + AfxMessageBox(NLMISC::toString("%u ids checked, %u non unique ID regenerated", ids.size()+nonUnique.size(), nonUnique.size()).c_str(), MB_OK); +} + +// *************************************************************************** + +void CMainFrame::OnEditFind () +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + if (doc->getNumDatabaseElement ()) + { + // Find dialog +#if 0 + CFindPrimitiveDlg dlg; + dlg.DoModal (); +#else + if (!m_FindPrimitiveDlg) + m_FindPrimitiveDlg = new CFindPrimitiveDlg; + + if (!::IsWindow(m_FindPrimitiveDlg->GetSafeHwnd())) + m_FindPrimitiveDlg->Create(IDD_FIND_PRIMITIVE, this); + + m_FindPrimitiveDlg->ShowWindow(SW_SHOW); +#endif + } +} + + +// *************************************************************************** + +void CMainFrame::OnEditGoto () +{ + // goto dialog + + m_GotoDlg.DoModal(); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateFind(CCmdUI* pCmdUI) +{ + CWorldEditorDoc *doc = getDocument (); + pCmdUI->Enable ( (isInteraction () && (_Mode == 1) && doc->getNumDatabaseElement ()) ? TRUE : FALSE ); +} + +// *************************************************************************** + +void CMainFrame::OnViewCollisions() +{ + // Toggle Collisions View + _ShowCollisions ^= true; + CMenu *menu = GetMenu(); + if (_ShowCollisions) + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_COLLISIONS); + menu->CheckMenuItem (ID_VIEW_COLLISIONS, MF_CHECKED|MF_BYCOMMAND); + } + else + { + // Update UI + m_wndToolBar.GetToolBarCtrl ().CheckButton (ID_VIEW_COLLISIONS, FALSE); + menu->CheckMenuItem (ID_VIEW_COLLISIONS, MF_UNCHECKED|MF_BYCOMMAND); + } + + // Invalidate left view + invalidateLeftView (); + + // Update data + updateData (); +} + +// *************************************************************************** + +// routines for the plugin +NLLIGO::IPrimitive *CMainFrame::createRootPluginPrimitive (const char *name) +{ + AFX_MANAGE_STATE(AfxGetAppModuleState()); + + // Add the landscape in the project + CWorldEditorDoc *doc = getDocument (); + + // Push back the primitive + doc->_DataHierarchy.push_back (CWorldEditorDoc::CDatabaseElement (CWorldEditorDoc::CDatabaseElement::Primitive)); + + // This primitive is not editable + doc->_DataHierarchy.back().Editable = false; + doc->_DataHierarchy.back().Filename = name; + + doc->_DataHierarchy.recomputePointerArray (); + + // Invalidate tools + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); + + // Modify files + uint index = doc->_DataHierarchy.size ()-1; + doc->modifyDatabase (index); + + // Update data + updateData (); + + return doc->_DataHierarchy[index].Primitives.RootNode; +} + +// *************************************************************************** + +void CMainFrame::deleteRootPluginPrimitive (void) +{ + +} + +// *************************************************************************** +void CMainFrame::getAllRootPluginPrimitive (std::vector &prims) +{ + AFX_MANAGE_STATE(AfxGetAppModuleState()); + + prims.clear(); + + // Add the landscape in the project + CWorldEditorDoc *doc = getDocument (); + nlassert(doc); + + // For all editable primitive only + for (uint j=0; j_DataHierarchy.size(); ++j) + { + if (doc->_DataHierarchy[j].Editable) + { + if (doc->_DataHierarchy[j].Type == CWorldEditorDoc::CDatabaseElement::Primitive) + prims.push_back(doc->_DataHierarchy[j].Primitives.RootNode); + } + } + +} + +// *************************************************************************** + +const NLLIGO::IPrimitive *CMainFrame::createPluginPrimitive +( + const char *className, + const char *primName, + const NLMISC::CVector &initPos, + float deltaPos, + const std::vector &initParameters, + NLLIGO::IPrimitive *parent + ) +{ + AFX_MANAGE_STATE(AfxGetAppModuleState()); + CWorldEditorDoc *doc = getDocument (); + + // What class is it ? + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass(className); + if (primClass) + { + // Begin modification + nlassert (primClass); + + // Get the child class + CDatabaseLocatorPointer insert; + doc->getLocator (insert, parent); + + // Locator for the child + CDatabaseLocator child; + insert.appendChild (child); + + // Get the class primitive + IPrimitive *primitive = const_cast (doc->createPrimitive (child, className, "", initPos, deltaPos, initParameters)); + if (primitive != NULL) + { + // Invalidate left view + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Modify files + doc->modifyDatabase (child.getDatabaseIndex ()); + + // Get a pointer on the new primitive + primitive->removePropertyByName ("name"); + primitive->addPropertyByName ("name",new CPropertyString (primName)); + + // Invalidate quad grid + CDatabaseLocatorPointer childPtr; + doc->getLocator (childPtr, child); + InvalidatePrimitiveRec (childPtr, QuadTree|LogicTreeStruct|SelectionState); + } + + // Update the data + updateData (); + return primitive; + } + else + return NULL; +} + +// *************************************************************************** + +// delete a plugin primitive +void CMainFrame::deletePluginPrimitive (const NLLIGO::IPrimitive *primitive) +{ + AFX_MANAGE_STATE(AfxGetAppModuleState()); + // Get the parent + IPrimitive *parent = const_cast(primitive)->getParent (); + nlassert (parent); + + // Get the child id + uint childId; + nlverify (parent->getChildId (childId, primitive)); + + // Delete the child + nlverify (parent->removeChild (childId)); + invalidateLeftView (); +} + +// *************************************************************************** + +// indicates to the WorldEditor that the primitive has changed +void CMainFrame::invalidatePluginPrimitive (const NLLIGO::IPrimitive *primitive, uint channels) +{ + AFX_MANAGE_STATE(AfxGetAppModuleState()); + if (primitive) + { + IPrimitiveEditor *primitiveEditor = dynamic_cast (const_cast (primitive)); + + // No, link it + if (primitiveEditor->_ModifiedIterator == ModifiedPrimitive.end ()) + { + ModifiedPrimitive.push_front (const_cast (primitive)); + primitiveEditor->_ModifiedIterator = ModifiedPrimitive.begin (); + } + + // Add the channel flags + primitiveEditor->_Channels |= channels; + } + if (channels | QuadTree) + { + invalidateLeftView (); + } +} + +// *************************************************************************** +void CMainFrame::invalidateLeftView() +{ + AFX_MANAGE_STATE(AfxGetAppModuleState()); + ::invalidateLeftView(); +} + +// *************************************************************************** + +// indicates to the WorldEditor that the primitive has changed +void CMainFrame::getWindowCoordinates(NLMISC::CVector &vmin, NLMISC::CVector &vmax) +{ + vmin = DispWnd->_CurViewMin; + vmax = DispWnd->_CurViewMax; +} + +// *************************************************************************** + +void CMainFrame::OnHelpHistory() +{ + string filename = theApp.ExePath+"history.txt"; + if (!openFile (filename.c_str())) + { + theApp.errorMessage ("Can't open the file %s", filename.c_str ()); + } +} + +// *************************************************************************** + +void CMainFrame::OnExportSnapshot() +{ + CCustomSnapshot snapShot (this); + if (snapShot.DoModal () == IDOK) + { + CFileDialogEx dialog (BASE_REGISTRY_KEY, "image", FALSE, "tga", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "Targa Files (*.tga)|*.tga|All Files (*.*)|*.*||", this); + if (dialog.DoModal() == IDOK) + { + if (snapShot.FixedSize == 0) + _ZoneBuilder->snapshot (dialog.GetPathName(), (uint)theApp.Config.CellSize, snapShot.OutputRGB == 1); + else + _ZoneBuilder->snapshotCustom (dialog.GetPathName(), snapShot.Width, snapShot.Height, snapShot.KeepRatio != FALSE, + (uint)theApp.Config.CellSize, snapShot.OutputRGB == 1); + } + } +} + +// *************************************************************************** + +void CMainFrame::OnWindowsPrimitiveconfiguration() +{ + PrimitiveConfigurationDlg.ShowWindow (PrimitiveConfigurationDlg.IsWindowVisible()?SW_HIDE:SW_SHOW); +} + +// *************************************************************************** + +void CMainFrame::OnUpdateWindowsPrimitiveconfiguration(CCmdUI* pCmdUI) +{ + pCmdUI->SetCheck(PrimitiveConfigurationDlg.IsWindowVisible()?1:0); +} + +// *************************************************************************** + +void CMainFrame::OnProjectResetPrimitiveConfiguration() +{ + theApp.reloadPrimitiveConfiguration (); +} + +// *************************************************************************** + +const std::list &CMainFrame::getCurrentSelection() +{ + return Selection; +} + +// *************************************************************************** +// Allow a plugin to modify the primitive selection + +void CMainFrame::setCurrentSelection(std::vector& newSelection) +{ + CWorldEditorDoc *doc=getDocument(); + list::iterator iteSelection; + doc->beginModification(); + //unselect the curent list + for (std::list::iterator it=Selection.begin(),itEnd=Selection.end();it!=itEnd;++it) + { + CDatabaseLocatorPointer locatorCurrent; + doc->getLocator (locatorCurrent, (*it) ); + doc->addModification (new CActionUnselect (locatorCurrent)); + } + + //select the new selection + for(uint i=0;igetLocator (locatorCurrent, newSelection.at(i)); + + doc->addModification (new CActionSelect (locatorCurrent)); + } + doc->endModification(); + + getMainFrame()->updateData (); + getMainFrame()->OnViewLocateselectedprimitives (); + getMainFrame()->OnViewLocateselectedprimitivesTree (); +} + +// *************************************************************************** +// use the root file name in order to retrieve the correct root node +const NLLIGO::IPrimitive* CMainFrame::getRootNode(const std::string& rootFileName) +{ + + CDatabaseLocatorPointer locator; + CWorldEditorDoc *doc=getDocument(); + doc->getFirstLocator(locator); + + locator.getRoot(rootFileName); + + return locator.Primitive; +} + +// *************************************************************************** +// retrieve the file name associated with the primitive of the root node +// it must be the root node +std::string& CMainFrame::getRootFileName(NLLIGO::IPrimitive* rootNode) +{ + + CDatabaseLocatorPointer locator; + CWorldEditorDoc *doc=getDocument(); + doc->getLocator(locator,rootNode); + + + return locator.getRootFileName(rootNode); +} + +// *************************************************************************** + + +void CMainFrame::registerPrimitiveDisplayer(IPrimitiveDisplayer *displayer, const std::vector &primClassNames) +{ + for (uint i=0; i &CMainFrame::getCurrentSelection() const +{ + return Selection; +} + +// *************************************************************************** +bool CMainFrame::isSelected(const NLLIGO::IPrimitive &prim) const +{ + const IPrimitiveEditor *pe = dynamic_cast(&prim); + nlassert(pe); + return pe->getSelected(); +} + +// *************************************************************************** +void CMainFrame::setPrimitiveHideFlag(NLLIGO::IPrimitive &prim, bool hidden) +{ + getPrimitiveEditor (&prim)->setHidden(hidden); +} + +// *************************************************************************** + +CPrimTexture *CMainFrame::createTexture() +{ + return new CPrimTexture; +} + +// *************************************************************************** + +void CMainFrame::deleteTexture(CPrimTexture *tex) +{ + delete tex; +} + +// *************************************************************************** + +bool CMainFrame::buildNLBitmapFromTGARsc(HRSRC bm, HMODULE hm, NLMISC::CBitmap &dest) +{ + HGLOBAL rsc = LoadResource(hm, bm); + if (rsc == NULL) return false; + uint numBytes = SizeofResource(hm, bm); + if (numBytes == 0) return false; + LPVOID dataPtr = LockResource(rsc); + if (!dataPtr) return false; + NLMISC::CMemStream ms; + ms.serialBuffer((uint8 *) dataPtr, numBytes); + NLMISC::CBitmap tmpBitmap; + ms.invert(); + try + { + ms.seek(0, NLMISC::IStream::begin); + tmpBitmap.load(ms); + } + catch(EStream &) + { + return false; + } + dest.swap(tmpBitmap); + return true; +} + + + +// *************************************************************************** + +void CMainFrame::OnDestroy() +{ + theApp.deletePlugins(); + CFrameWnd::OnDestroy(); +} + +// *************************************************************************** + +bool CMainFrame::CanDrop() +{ + for (uint i=0; i<_PrimitiveClipboard.size (); i++) + { + bool paste = false; + + // Is this a root ? + if ( Selection.front() ) + { + if ( Selection.front()->getParent() ) + { + // Try to add it has children of the selection + if (theApp.Config.canBeChild (*(_PrimitiveClipboard[i]), *(Selection.front ()))) + { + paste = true; + } + else + { + // Can be a child ? + if (theApp.Config.canBeChild (*(_PrimitiveClipboard[i]), *(Selection.front ()->getParent ()))) + { + paste = true; + } + } + } + else + { + // Try to add it has children of the selection + if (theApp.Config.canBeRoot (*(_PrimitiveClipboard[i]))) + { + paste = true; + } + } + } + + if ( !paste ) + return false; + } + + return true; +} + +// *************************************************************************** + +void CMainFrame::OnSavePosition() +{ + ::CStdioFile file; + ::CString str; + ::CTime t = ::CTime::GetCurrentTime(); + + const CVector &v = DispWnd->_CurPos; + + // Write the zone name in NeL protocol + sint32 x, y; + + CDisplay *dispWnd = dynamic_cast(m_wndSplitter.GetPane(0,0)); + x = (sint32)floor(v.x / dispWnd->_CellSize); + y = (sint32)floor(v.y / dispWnd->_CellSize); + + str.Format( "[%s] X = %.3f, Y = %.3f\r\n", t.Format( "%m/%d/%y, %H:%M:%S" ), v.x, v.y ); + + file.Open( "position.txt", ::CFile::modeCreate|::CFile::modeNoTruncate|::CFile::modeWrite|::CFile::typeText ); + file.SeekToEnd(); + file.WriteString( str ); + file.Close(); + + MessageBox( "Current coordinates saved in file position.txt", "Position saved", MB_OK ); +} + +// *************************************************************************** + +void CMainFrame::OnDropFiles(HDROP hDropInfo) +{ + // hDropInfo contains infos about dropped files + if (hDropInfo) + { + CString Filename; + + // Get the number of files dropped + uint numFiles = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0); + + for (uint i=0 ; ibeginModification (); + + if (!getDocument()->isPrimitiveLoaded(path)) + getDocument ()->addModification (new CActionLoadPrimitive (path.c_str())); + else + infoMessage("Primitive already existing: %s", path.c_str()); + + getDocument()->endModification (); + + // Verify primitive structures + VerifyPrimitivesStructures(); + + // Update data + updateData (); + } + // Can be extended to support more file types + else + { + errorMessage("File not supported: %s", pFilename); + } + } + } + + // Release memory + DragFinish(hDropInfo); +} + +// *************************************************************************** + +void CMainFrame::OnMissionCompiler() +{ + // list of selected primitives + list sel = getCurrentSelection(); + + // list of primitive files to compile + vector files; + + // store selected primitive files : no duplicate file + for (list::iterator itSel=sel.begin() ; itSel!=sel.end() ; ++itSel) + { + // Get file path of selected primitive + string path; + CDatabaseLocatorPointer locator; + CWorldEditorDoc *doc = getDocument(); + doc->getLocator(locator, *itSel); + doc->getFilePath(locator.getDatabaseIndex(), path); + + // Check if already inserted + vector::iterator it = find(files.begin(), files.end(), path); + if (it == files.end()) + files.push_back(path); + } + + // write filenames to a temp file for the mission compiler + if (files.size() > 0) + { + // use system temp directory + char tmpPath[MAX_PATH]; + GetEnvironmentVariable("TMP", tmpPath, MAX_PATH); + strcat(tmpPath, "\\tmptool.txt"); + + FILE *f = fopen(tmpPath, "w"); + if (f==NULL) + infoMessage("Can't open file for writing !\n%s", tmpPath); + + for (uint i=0 ; igetConfigFile().getVarPtr ("MissionCompilerPath"); + if (!var) + { + errorMessage("Can't find variable : ""MissionCompilerPath"" in world_editor_plugin.cfg"); + return; + } + + char path[MAX_PATH]; + strcpy(path, var->asString().c_str()); + + SHELLEXECUTEINFO ExecuteInfo; + memset(&ExecuteInfo, 0, sizeof(ExecuteInfo)); + + ExecuteInfo.cbSize = sizeof(ExecuteInfo); + ExecuteInfo.fMask = 0; + ExecuteInfo.hwnd = 0; + ExecuteInfo.lpVerb = "open"; + ExecuteInfo.lpFile = "mission_compiler_fe_r.exe"; + ExecuteInfo.lpParameters = 0; + ExecuteInfo.lpDirectory = path; + ExecuteInfo.nShow = SW_SHOW; + ExecuteInfo.hInstApp = 0; + + if(ShellExecuteEx(&ExecuteInfo) == FALSE) + errorMessage("File not found : mission_compiler_fe_r.exe !"); +} + +// *************************************************************************** + +void CMainFrame::OnNameDlg() +{ + CNameDlg dlg; + dlg.setSelection(getCurrentSelection()); + int nResponse = dlg.DoModal(); + if (nResponse == IDOK) + infoMessage("Files saved !"); +} + +// *************************************************************************** diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/main_frm.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/main_frm.h index 763c90c80..5c2173186 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/main_frm.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/main_frm.h @@ -1,533 +1,533 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// main_frm.h : interface of the CMainFrame class -// -// *************************************************************************** - - -#if !defined(AFX_MAIN_FRM_H__1647027B_EE0B_4857_B290_B87FB521A91C__INCLUDED_) -#define AFX_MAIN_FRM_H__1647027B_EE0B_4857_B290_B87FB521A91C__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#include "builder_zone.h" -#include "plugin_interface.h" -#include "world_editor_doc.h" -#include "find_primitive_dlg.h" -#include "goto_dialog.h" - -#define DELTA_POS_ADD_PRIMITIVE 20 - -// *************************************************************************** - -class IMasterCB; -class CLoadingDialog; -class CDisplay; - -// *************************************************************************** - -struct SType -{ - std::string Name; - NLMISC::CRGBA Color; - // ----------------------------- - void serial (NLMISC::IStream&f); -}; - -// *************************************************************************** - -struct SEnvironnement -{ - std::vector Types; - NLMISC::CRGBA BackgroundColor; - // SExportOptions ExportOptions; - std::string DataDir; - // ----------------------------- - SEnvironnement(); - void serial (NLMISC::IStream&f); -}; - -// *************************************************************************** - -class CMainFrame : public CFrameWnd, public IPluginAccess -{ - -protected: // create from serialization only - CMainFrame(); - DECLARE_DYNCREATE(CMainFrame) - -// Attributes -public: - - CSplitterWnd m_wndSplitter; - - // Transformation mode - enum TTransformMode - { - Select = 0, - Move, - Rotate, - Turn, - Scale, - Radius, - AddPoint - }; - -private: - TTransformMode _TransformModes[2]; - - // Width of the tool panel - LONG _ToolColumnSize; - - // Show landscape - bool _ShowLandscape; - - // Show layers - bool _ShowLayers; - - // Show grid - bool _ShowGrid; - - // Show points - bool _ShowPoints; - - // Show PACS - bool _ShowPACS; - - // Show primitives - bool _ShowPrimitives; - - // Show details - bool _ShowDetails; - - // Show collisions - bool _ShowCollisions; - -public: - - // Timer enabled - bool TimerEnabled; - -// Methods - - // Show landscape ? - bool showLandscape () const - { - return _ShowLandscape; - } - - // Show layers ? - bool showLayers () const - { - return _ShowLayers; - } - - // Show grid ? - bool showGrid () const - { - return _ShowGrid; - } - - // Show points ? - bool showPoints () const - { - return _ShowPoints; - } - - // Show PACS ? - bool showPACS () const - { - return _ShowPACS; - } - - // Show primitives ? - bool showPrimitives () const - { - return _ShowPrimitives; - } - - // Show details ? - bool showDetails () const - { - return _ShowDetails; - } - - // Show collisions ? - bool showCollisions () const - { - return _ShowCollisions; - } - - // Transform methods - inline TTransformMode getTransformMode () const - { - return _TransformModes[(uint)_SelectionLocked]; - } - void setTransformMode (TTransformMode mode); - - // Init the landscape data - bool initLandscapeData (); - class CWorldEditorDoc *getDocument (); - - // Flush current messages - void flushMessages (); - -private: - // Selection data - bool _ValidSelection; - bool _SelectionLocked; - - // Landscape validate - bool _ValidLandscape; -public: - - // Selection locked ? - bool isSelectionLocked () const - { - return _SelectionLocked; - } - - // Selection locked ? - void setSelectionLocked (bool lock); - - // Delete selected primitives - void deletePrimitive (bool subDelete, const char *actionName); - - // Create a context menu for selection - void createContextMenu (CWnd *parent, const CPoint &point, bool transformMode); - - // Display info in the status bar - void displayInfo (const char *info); - - // Disactive / enable interaction - void interaction (bool enable); - - // is interaction enabled, disactived ? - bool isInteraction () const; - - // Copy, cut, paste -private: - std::vector _PrimitiveClipboard; - - // Delete the primitive clipboard - void deletePrimitiveClipboard (); - - // Get the filenames openable in a primitive - void buildFilenameVector (const NLLIGO::IPrimitive &primitive, std::vector &dest); - -public: - - /* Old trap Start */ - - CLoadingDialog *LoadingDialog; - CDisplay *DispWnd; - - int CreateX, CreateY, CreateCX, CreateCY; - - bool _Exit; - bool _SplitterCreated; - CBuilderZone *_ZoneBuilder; - sint32 _Mode; // 0-Mode Zone, 1-Mode Logic 2-Mode Trans, 3-Plugin position control - /// Remenber mode when plugin take control. - sint32 _LastMode; - std::string _ExeDir; // WorldEditor directory - IMasterCB *_MasterCB; - - //std::vector _Types; - SEnvironnement _Environnement; - - /// The plugin that control the position editor (NULL is none) - IPluginCallback *_CurrentPlugin; - - /// The controled position - NLMISC::CVector _PositionControl; - - void setExeDir (const char* str); - void setDataDir (const char* str); - void uninitTools(); - void initTools(); - void invalidateLandscape (); - void invalidateTools(); - void invalidateToolsParam(); - void invalidateModification (); - void updateData (); - - void primZoneModified(); - - // Initialize the main frame (must be done before init of the tools) - bool init (bool bMakeAZone = true); - void uninit (); - - void displayStatusBarInfo (); - void adjustSplitter(); - - void launchLoadingDialog (const std::string &sText); - void progressLoadingDialog (float progress, bool flushMessages = true); - void terminateLoadingDialog (); - - // void viewLand(bool withIgs); - - NLMISC::CConfigFile &getConfigFile(); - CWnd *getMainWindow() { return this; } - - // from IPluginAccess - bool yesNoMessage (const char *format, ... ); - void errorMessage (const char *format, ... ); - void infoMessage (const char *format, ... ); - void startPositionControl(IPluginCallback *plugin, const NLMISC::CVector &initPos); - void stopPositionControl(IPluginCallback *plugin); - // functions to create/remove the Root Primitive for server actions - virtual NLLIGO::IPrimitive *createRootPluginPrimitive (const char *name); - virtual void deleteRootPluginPrimitive (void); - virtual void getAllRootPluginPrimitive (std::vector &prims); - /* - * The players or informations coming from the server are considered as primitives by the WorldEditor - * so we need to create/delete/modify these primitives - */ - // Create a plugin primitive - const NLLIGO::IPrimitive *createPluginPrimitive ( - const char *className, - const char *primName, - const NLMISC::CVector &initPos, - float deltaPos, - const std::vector &initParameters, - NLLIGO::IPrimitive *parent - ); - - // delete a plugin primitive - void deletePluginPrimitive (const NLLIGO::IPrimitive *primitive); - - // indicates to the WorldEditor that the primitive has changed - void invalidatePluginPrimitive (const NLLIGO::IPrimitive *primitive, uint channels); - - // invalidate the left view completely - virtual void invalidateLeftView(); - - - // get the display window coordinates - void getWindowCoordinates(NLMISC::CVector &vmin, NLMISC::CVector &vmax); - - virtual const std::list &getCurrentSelection(); - - virtual bool isSelected(const NLLIGO::IPrimitive &prim) const; - - void setCurrentSelection(std::vector& ); - - virtual const NLLIGO::IPrimitive* getRootNode(const std::string&); - - virtual std::string& getRootFileName(NLLIGO::IPrimitive*); - - virtual void registerPrimitiveDisplayer(IPrimitiveDisplayer *displayer, const std::vector &primClassNames); - - virtual const std::list &getCurrentSelection() const; - - virtual void refreshPropertyDialog() { _MustRefreshPropertyDialog = true; } - - - virtual std::string sheetIdToSheetName(NLMISC::CSheetId sheetID) const; - - virtual void setPrimitiveHideFlag(NLLIGO::IPrimitive &prim, bool hidden); - - virtual CPrimTexture *createTexture(); - - // Delete a texture object - virtual void deleteTexture(CPrimTexture *tex); - - // from IPluginAccess - virtual bool buildNLBitmapFromTGARsc(HRSRC bm,HMODULE hm,NLMISC::CBitmap &dest); - - bool CanDrop(); - - - /* Old Trap End */ - -// Operations -public: - -// Overrides -public: - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CMainFrame) - virtual BOOL PreCreateWindow(CREATESTRUCT& cs); - virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext); - virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); - //}}AFX_VIRTUAL - -// Implementation -public: - virtual ~CMainFrame(); -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - -protected: // control bar embedded members - CStatusBar m_wndStatusBar; - CToolBar m_wndToolBar; - CReBar m_wndReBar; - CDialogBar m_wndDlgBar; - CFindPrimitiveDlg *m_FindPrimitiveDlg; - - CGotoDialog m_GotoDlg; - - bool _MustRefreshPropertyDialog; - -// Generated message map functions -protected: - - void onLogicChanged(const std::vector ®ions); - -public: - - //{{AFX_MSG(CMainFrame) - afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); - afx_msg void OnClose (); - afx_msg void OnSize (UINT nType, int cx, int cy); - afx_msg void onMenuFileExit (); - afx_msg void onMenuFileNewLogic (); - afx_msg void onMenuFileUnloadLogic (); - afx_msg void onMenuFileOpenLogic (); - afx_msg void onMenuFileNewLandscape (); - afx_msg void onMenuFileUnloadLandscape (); - afx_msg void onMenuModeLogic (); - afx_msg void onMenuViewBackground (); - afx_msg void onMenuModeZone (); - afx_msg void onMenuModeTransition (); - afx_msg void onMenuViewGrid (); - afx_msg void onMenuModeUndo (); - afx_msg void onMenuModeRedo (); - afx_msg void onUpdateModeUndo (CCmdUI* pCmdUI); - afx_msg void onUpdateModeRedo (CCmdUI* pCmdUI); - afx_msg void onProjectNewlandscape(); - afx_msg void onProjectAddlandscape(); - afx_msg void onProjectSettings(); - afx_msg void OnUpdateEditTransition(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditZone(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditLogic(CCmdUI* pCmdUI); - afx_msg void OnProjectImportPrim(); - afx_msg void OnProjectAddPrimitive(); - afx_msg void OnProjectClearallprimitive(); - afx_msg void OnEditSelectAll(); - afx_msg void OnEditLock(); - afx_msg void OnEditSelect(); - afx_msg void OnEditDetails(); - afx_msg void OnViewLandscape(); - afx_msg void OnViewLayers(); - afx_msg void OnViewGrid(); - afx_msg void OnViewPoints(); - afx_msg void OnViewPACS(); - afx_msg void OnViewPrimitives(); - afx_msg void OnEditTranslate(); - afx_msg void OnEditRotate(); - afx_msg void OnEditTurn(); - afx_msg void OnEditRadius(); - afx_msg void OnEditScale(); - afx_msg void OnEditAddPoint(); - afx_msg void OnEditDelete(); - afx_msg void OnProjectNewPrimitive(); - afx_msg void OnEditProperties(); - afx_msg void OnAddPrimitive (UINT nID); - afx_msg void OnGeneratePrimitive (UINT nID); - afx_msg void OnUpdateEditAddPoint(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditLock(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditProperties(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditRotate(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditScale(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditSelectAll(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditTranslate(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditTurn(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditRadius(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditSelect(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditDetails(CCmdUI* pCmdUI); - afx_msg void OnUpdateViewLandscape(CCmdUI* pCmdUI); - afx_msg void OnEditCopy(); - afx_msg void OnEditCut(); - afx_msg void OnUpdateEditCopy(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditCut(CCmdUI* pCmdUI); - afx_msg void OnEditPaste(); - afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI); - afx_msg void OnUpdateViewHide(CCmdUI* pCmdUI); - afx_msg void OnViewHide(); - afx_msg void OnViewShow(); - afx_msg void OnUpdateViewShow(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditExpand(CCmdUI* pCmdUI); - afx_msg void OnUpdateEditCollapse(CCmdUI* pCmdUI); - afx_msg void OnEditSelectChildren(); - afx_msg void OnUpdateEditSelectChildren(CCmdUI* pCmdUI); - afx_msg void OnTimer(UINT nIDEvent); - afx_msg void OnEditExpand (); - afx_msg void OnEditCollapse (); - afx_msg void OnHelpFinder(); - afx_msg void OnOpenFile (UINT nID); - afx_msg void OnViewLocateselectedprimitives(); - afx_msg void OnUpdateViewLocateselectedprimitives(CCmdUI* pCmdUI); - afx_msg void OnViewLocateselectedprimitivesTree(); - afx_msg void OnUpdateViewLocateselectedprimitivesTree(CCmdUI* pCmdUI); - afx_msg void OnEditSelectByLocation(); - afx_msg void OnUpdateEditSelectByLocation(CCmdUI* pCmdUI); - afx_msg void OnProjectResetuniqueid(); - afx_msg void OnProjectGeneratenullid(); - afx_msg void OnProjectForceiduniqueness(); - afx_msg void OnEditFind(); - afx_msg void OnEditGoto(); - afx_msg void OnUpdateFind(CCmdUI* pCmdUI); - afx_msg void OnViewCollisions(); - afx_msg void OnHelpHistory(); - afx_msg void OnExportSnapshot(); - afx_msg void OnWindowsPrimitiveconfiguration(); - afx_msg void OnUpdateWindowsPrimitiveconfiguration(CCmdUI* pCmdUI); - afx_msg void OnProjectResetPrimitiveConfiguration(); - afx_msg void OnDestroy(); - afx_msg void OnSavePosition(); - afx_msg void OnDropFiles(HDROP hDropInfo); - afx_msg void OnMissionCompiler(); - afx_msg void OnNameDlg(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -// *************************************************************************** - -class CLoadingDialog : public CDialog -{ - -public: - - CLoadingDialog (CWnd*pParent); - - void setText (const std::string &text); - void setProgress (float progress); -}; - -// *************************************************************************** - -// Standard callback -class CWorldEditorProgressCallback : public NLMISC::IProgressCallback -{ -public: - CWorldEditorProgressCallback (); - ~CWorldEditorProgressCallback (); - void progress (float value); -}; - - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_MAIN_FRM_H__1647027B_EE0B_4857_B290_B87FB521A91C__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// main_frm.h : interface of the CMainFrame class +// +// *************************************************************************** + + +#if !defined(AFX_MAIN_FRM_H__1647027B_EE0B_4857_B290_B87FB521A91C__INCLUDED_) +#define AFX_MAIN_FRM_H__1647027B_EE0B_4857_B290_B87FB521A91C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#include "builder_zone.h" +#include "plugin_interface.h" +#include "world_editor_doc.h" +#include "find_primitive_dlg.h" +#include "goto_dialog.h" + +#define DELTA_POS_ADD_PRIMITIVE 20 + +// *************************************************************************** + +class IMasterCB; +class CLoadingDialog; +class CDisplay; + +// *************************************************************************** + +struct SType +{ + std::string Name; + NLMISC::CRGBA Color; + // ----------------------------- + void serial (NLMISC::IStream&f); +}; + +// *************************************************************************** + +struct SEnvironnement +{ + std::vector Types; + NLMISC::CRGBA BackgroundColor; + // SExportOptions ExportOptions; + std::string DataDir; + // ----------------------------- + SEnvironnement(); + void serial (NLMISC::IStream&f); +}; + +// *************************************************************************** + +class CMainFrame : public CFrameWnd, public IPluginAccess +{ + +protected: // create from serialization only + CMainFrame(); + DECLARE_DYNCREATE(CMainFrame) + +// Attributes +public: + + CSplitterWnd m_wndSplitter; + + // Transformation mode + enum TTransformMode + { + Select = 0, + Move, + Rotate, + Turn, + Scale, + Radius, + AddPoint + }; + +private: + TTransformMode _TransformModes[2]; + + // Width of the tool panel + LONG _ToolColumnSize; + + // Show landscape + bool _ShowLandscape; + + // Show layers + bool _ShowLayers; + + // Show grid + bool _ShowGrid; + + // Show points + bool _ShowPoints; + + // Show PACS + bool _ShowPACS; + + // Show primitives + bool _ShowPrimitives; + + // Show details + bool _ShowDetails; + + // Show collisions + bool _ShowCollisions; + +public: + + // Timer enabled + bool TimerEnabled; + +// Methods + + // Show landscape ? + bool showLandscape () const + { + return _ShowLandscape; + } + + // Show layers ? + bool showLayers () const + { + return _ShowLayers; + } + + // Show grid ? + bool showGrid () const + { + return _ShowGrid; + } + + // Show points ? + bool showPoints () const + { + return _ShowPoints; + } + + // Show PACS ? + bool showPACS () const + { + return _ShowPACS; + } + + // Show primitives ? + bool showPrimitives () const + { + return _ShowPrimitives; + } + + // Show details ? + bool showDetails () const + { + return _ShowDetails; + } + + // Show collisions ? + bool showCollisions () const + { + return _ShowCollisions; + } + + // Transform methods + inline TTransformMode getTransformMode () const + { + return _TransformModes[(uint)_SelectionLocked]; + } + void setTransformMode (TTransformMode mode); + + // Init the landscape data + bool initLandscapeData (); + class CWorldEditorDoc *getDocument (); + + // Flush current messages + void flushMessages (); + +private: + // Selection data + bool _ValidSelection; + bool _SelectionLocked; + + // Landscape validate + bool _ValidLandscape; +public: + + // Selection locked ? + bool isSelectionLocked () const + { + return _SelectionLocked; + } + + // Selection locked ? + void setSelectionLocked (bool lock); + + // Delete selected primitives + void deletePrimitive (bool subDelete, const char *actionName); + + // Create a context menu for selection + void createContextMenu (CWnd *parent, const CPoint &point, bool transformMode); + + // Display info in the status bar + void displayInfo (const char *info); + + // Disactive / enable interaction + void interaction (bool enable); + + // is interaction enabled, disactived ? + bool isInteraction () const; + + // Copy, cut, paste +private: + std::vector _PrimitiveClipboard; + + // Delete the primitive clipboard + void deletePrimitiveClipboard (); + + // Get the filenames openable in a primitive + void buildFilenameVector (const NLLIGO::IPrimitive &primitive, std::vector &dest); + +public: + + /* Old trap Start */ + + CLoadingDialog *LoadingDialog; + CDisplay *DispWnd; + + int CreateX, CreateY, CreateCX, CreateCY; + + bool _Exit; + bool _SplitterCreated; + CBuilderZone *_ZoneBuilder; + sint32 _Mode; // 0-Mode Zone, 1-Mode Logic 2-Mode Trans, 3-Plugin position control + /// Remenber mode when plugin take control. + sint32 _LastMode; + std::string _ExeDir; // WorldEditor directory + IMasterCB *_MasterCB; + + //std::vector _Types; + SEnvironnement _Environnement; + + /// The plugin that control the position editor (NULL is none) + IPluginCallback *_CurrentPlugin; + + /// The controled position + NLMISC::CVector _PositionControl; + + void setExeDir (const char* str); + void setDataDir (const char* str); + void uninitTools(); + void initTools(); + void invalidateLandscape (); + void invalidateTools(); + void invalidateToolsParam(); + void invalidateModification (); + void updateData (); + + void primZoneModified(); + + // Initialize the main frame (must be done before init of the tools) + bool init (bool bMakeAZone = true); + void uninit (); + + void displayStatusBarInfo (); + void adjustSplitter(); + + void launchLoadingDialog (const std::string &sText); + void progressLoadingDialog (float progress, bool flushMessages = true); + void terminateLoadingDialog (); + + // void viewLand(bool withIgs); + + NLMISC::CConfigFile &getConfigFile(); + CWnd *getMainWindow() { return this; } + + // from IPluginAccess + bool yesNoMessage (const char *format, ... ); + void errorMessage (const char *format, ... ); + void infoMessage (const char *format, ... ); + void startPositionControl(IPluginCallback *plugin, const NLMISC::CVector &initPos); + void stopPositionControl(IPluginCallback *plugin); + // functions to create/remove the Root Primitive for server actions + virtual NLLIGO::IPrimitive *createRootPluginPrimitive (const char *name); + virtual void deleteRootPluginPrimitive (void); + virtual void getAllRootPluginPrimitive (std::vector &prims); + /* + * The players or informations coming from the server are considered as primitives by the WorldEditor + * so we need to create/delete/modify these primitives + */ + // Create a plugin primitive + const NLLIGO::IPrimitive *createPluginPrimitive ( + const char *className, + const char *primName, + const NLMISC::CVector &initPos, + float deltaPos, + const std::vector &initParameters, + NLLIGO::IPrimitive *parent + ); + + // delete a plugin primitive + void deletePluginPrimitive (const NLLIGO::IPrimitive *primitive); + + // indicates to the WorldEditor that the primitive has changed + void invalidatePluginPrimitive (const NLLIGO::IPrimitive *primitive, uint channels); + + // invalidate the left view completely + virtual void invalidateLeftView(); + + + // get the display window coordinates + void getWindowCoordinates(NLMISC::CVector &vmin, NLMISC::CVector &vmax); + + virtual const std::list &getCurrentSelection(); + + virtual bool isSelected(const NLLIGO::IPrimitive &prim) const; + + void setCurrentSelection(std::vector& ); + + virtual const NLLIGO::IPrimitive* getRootNode(const std::string&); + + virtual std::string& getRootFileName(NLLIGO::IPrimitive*); + + virtual void registerPrimitiveDisplayer(IPrimitiveDisplayer *displayer, const std::vector &primClassNames); + + virtual const std::list &getCurrentSelection() const; + + virtual void refreshPropertyDialog() { _MustRefreshPropertyDialog = true; } + + + virtual std::string sheetIdToSheetName(NLMISC::CSheetId sheetID) const; + + virtual void setPrimitiveHideFlag(NLLIGO::IPrimitive &prim, bool hidden); + + virtual CPrimTexture *createTexture(); + + // Delete a texture object + virtual void deleteTexture(CPrimTexture *tex); + + // from IPluginAccess + virtual bool buildNLBitmapFromTGARsc(HRSRC bm,HMODULE hm,NLMISC::CBitmap &dest); + + bool CanDrop(); + + + /* Old Trap End */ + +// Operations +public: + +// Overrides +public: + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMainFrame) + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + virtual BOOL OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext); + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CMainFrame(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: // control bar embedded members + CStatusBar m_wndStatusBar; + CToolBar m_wndToolBar; + CReBar m_wndReBar; + CDialogBar m_wndDlgBar; + CFindPrimitiveDlg *m_FindPrimitiveDlg; + + CGotoDialog m_GotoDlg; + + bool _MustRefreshPropertyDialog; + +// Generated message map functions +protected: + + void onLogicChanged(const std::vector ®ions); + +public: + + //{{AFX_MSG(CMainFrame) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnClose (); + afx_msg void OnSize (UINT nType, int cx, int cy); + afx_msg void onMenuFileExit (); + afx_msg void onMenuFileNewLogic (); + afx_msg void onMenuFileUnloadLogic (); + afx_msg void onMenuFileOpenLogic (); + afx_msg void onMenuFileNewLandscape (); + afx_msg void onMenuFileUnloadLandscape (); + afx_msg void onMenuModeLogic (); + afx_msg void onMenuViewBackground (); + afx_msg void onMenuModeZone (); + afx_msg void onMenuModeTransition (); + afx_msg void onMenuViewGrid (); + afx_msg void onMenuModeUndo (); + afx_msg void onMenuModeRedo (); + afx_msg void onUpdateModeUndo (CCmdUI* pCmdUI); + afx_msg void onUpdateModeRedo (CCmdUI* pCmdUI); + afx_msg void onProjectNewlandscape(); + afx_msg void onProjectAddlandscape(); + afx_msg void onProjectSettings(); + afx_msg void OnUpdateEditTransition(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditZone(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditLogic(CCmdUI* pCmdUI); + afx_msg void OnProjectImportPrim(); + afx_msg void OnProjectAddPrimitive(); + afx_msg void OnProjectClearallprimitive(); + afx_msg void OnEditSelectAll(); + afx_msg void OnEditLock(); + afx_msg void OnEditSelect(); + afx_msg void OnEditDetails(); + afx_msg void OnViewLandscape(); + afx_msg void OnViewLayers(); + afx_msg void OnViewGrid(); + afx_msg void OnViewPoints(); + afx_msg void OnViewPACS(); + afx_msg void OnViewPrimitives(); + afx_msg void OnEditTranslate(); + afx_msg void OnEditRotate(); + afx_msg void OnEditTurn(); + afx_msg void OnEditRadius(); + afx_msg void OnEditScale(); + afx_msg void OnEditAddPoint(); + afx_msg void OnEditDelete(); + afx_msg void OnProjectNewPrimitive(); + afx_msg void OnEditProperties(); + afx_msg void OnAddPrimitive (UINT nID); + afx_msg void OnGeneratePrimitive (UINT nID); + afx_msg void OnUpdateEditAddPoint(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditLock(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditProperties(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditRotate(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditScale(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditSelectAll(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditTranslate(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditTurn(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditRadius(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditSelect(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditDetails(CCmdUI* pCmdUI); + afx_msg void OnUpdateViewLandscape(CCmdUI* pCmdUI); + afx_msg void OnEditCopy(); + afx_msg void OnEditCut(); + afx_msg void OnUpdateEditCopy(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditCut(CCmdUI* pCmdUI); + afx_msg void OnEditPaste(); + afx_msg void OnUpdateEditPaste(CCmdUI* pCmdUI); + afx_msg void OnUpdateViewHide(CCmdUI* pCmdUI); + afx_msg void OnViewHide(); + afx_msg void OnViewShow(); + afx_msg void OnUpdateViewShow(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditExpand(CCmdUI* pCmdUI); + afx_msg void OnUpdateEditCollapse(CCmdUI* pCmdUI); + afx_msg void OnEditSelectChildren(); + afx_msg void OnUpdateEditSelectChildren(CCmdUI* pCmdUI); + afx_msg void OnTimer(UINT nIDEvent); + afx_msg void OnEditExpand (); + afx_msg void OnEditCollapse (); + afx_msg void OnHelpFinder(); + afx_msg void OnOpenFile (UINT nID); + afx_msg void OnViewLocateselectedprimitives(); + afx_msg void OnUpdateViewLocateselectedprimitives(CCmdUI* pCmdUI); + afx_msg void OnViewLocateselectedprimitivesTree(); + afx_msg void OnUpdateViewLocateselectedprimitivesTree(CCmdUI* pCmdUI); + afx_msg void OnEditSelectByLocation(); + afx_msg void OnUpdateEditSelectByLocation(CCmdUI* pCmdUI); + afx_msg void OnProjectResetuniqueid(); + afx_msg void OnProjectGeneratenullid(); + afx_msg void OnProjectForceiduniqueness(); + afx_msg void OnEditFind(); + afx_msg void OnEditGoto(); + afx_msg void OnUpdateFind(CCmdUI* pCmdUI); + afx_msg void OnViewCollisions(); + afx_msg void OnHelpHistory(); + afx_msg void OnExportSnapshot(); + afx_msg void OnWindowsPrimitiveconfiguration(); + afx_msg void OnUpdateWindowsPrimitiveconfiguration(CCmdUI* pCmdUI); + afx_msg void OnProjectResetPrimitiveConfiguration(); + afx_msg void OnDestroy(); + afx_msg void OnSavePosition(); + afx_msg void OnDropFiles(HDROP hDropInfo); + afx_msg void OnMissionCompiler(); + afx_msg void OnNameDlg(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +// *************************************************************************** + +class CLoadingDialog : public CDialog +{ + +public: + + CLoadingDialog (CWnd*pParent); + + void setText (const std::string &text); + void setProgress (float progress); +}; + +// *************************************************************************** + +// Standard callback +class CWorldEditorProgressCallback : public NLMISC::IProgressCallback +{ +public: + CWorldEditorProgressCallback (); + ~CWorldEditorProgressCallback (); + void progress (float value); +}; + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MAIN_FRM_H__1647027B_EE0B_4857_B290_B87FB521A91C__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/move_dlg.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/move_dlg.cpp index cb8913621..c3e2dbfd6 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/move_dlg.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/move_dlg.cpp @@ -1,56 +1,56 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// MoveDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "resource.h" -#include "move_dlg.h" - -///////////////////////////////////////////////////////////////////////////// -// CMoveDlg dialog - - -CMoveDlg::CMoveDlg(CWnd* pParent /*=NULL*/) - : CDialog(CMoveDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CMoveDlg) - XOffset = 0; - YOffset = 0; - //}}AFX_DATA_INIT -} - - -void CMoveDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CMoveDlg) - DDX_Text(pDX, IDC_EDITXOFFSET, XOffset); - DDX_Text(pDX, IDC_EDITYOFFSET, YOffset); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CMoveDlg, CDialog) - //{{AFX_MSG_MAP(CMoveDlg) - // NOTE: the ClassWizard will add message map macros here - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CMoveDlg message handlers +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// MoveDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "resource.h" +#include "move_dlg.h" + +///////////////////////////////////////////////////////////////////////////// +// CMoveDlg dialog + + +CMoveDlg::CMoveDlg(CWnd* pParent /*=NULL*/) + : CDialog(CMoveDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CMoveDlg) + XOffset = 0; + YOffset = 0; + //}}AFX_DATA_INIT +} + + +void CMoveDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CMoveDlg) + DDX_Text(pDX, IDC_EDITXOFFSET, XOffset); + DDX_Text(pDX, IDC_EDITYOFFSET, YOffset); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CMoveDlg, CDialog) + //{{AFX_MSG_MAP(CMoveDlg) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CMoveDlg message handlers diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/move_dlg.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/move_dlg.h index 1e88ac337..bbdfb4991 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/move_dlg.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/move_dlg.h @@ -1,63 +1,63 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_MOVEDLG_H__C18719D1_9BB9_42EC_9CFF_ED4C16C1DF74__INCLUDED_) -#define AFX_MOVEDLG_H__C18719D1_9BB9_42EC_9CFF_ED4C16C1DF74__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// MoveDlg.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CMoveDlg dialog - -class CMoveDlg : public CDialog -{ -// Construction -public: - CMoveDlg(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CMoveDlg) - enum { IDD = IDD_MOVE }; - int XOffset; - int YOffset; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CMoveDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CMoveDlg) - // NOTE: the ClassWizard will add member functions here - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_MOVEDLG_H__C18719D1_9BB9_42EC_9CFF_ED4C16C1DF74__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_MOVEDLG_H__C18719D1_9BB9_42EC_9CFF_ED4C16C1DF74__INCLUDED_) +#define AFX_MOVEDLG_H__C18719D1_9BB9_42EC_9CFF_ED4C16C1DF74__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// MoveDlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CMoveDlg dialog + +class CMoveDlg : public CDialog +{ +// Construction +public: + CMoveDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CMoveDlg) + enum { IDD = IDD_MOVE }; + int XOffset; + int YOffset; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMoveDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CMoveDlg) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MOVEDLG_H__C18719D1_9BB9_42EC_9CFF_ED4C16C1DF74__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/my_list_box.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/my_list_box.cpp index 958fec23d..e75c5d712 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/my_list_box.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/my_list_box.cpp @@ -1,232 +1,232 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// my_list_box.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "my_list_box.h" - -#define COMBO_REAL_HEIGHT 300 - -// *************************************************************************** -// CMyListBox -// *************************************************************************** - -CMyListBox::CMyListBox() -{ -} - -// *************************************************************************** - -CMyListBox::~CMyListBox() -{ -} - -// *************************************************************************** - -BEGIN_MESSAGE_MAP(CMyListBox, CListBox) - //{{AFX_MSG_MAP(CMyListBox) - ON_CONTROL_REFLECT(LBN_DBLCLK, OnDblclk) - ON_WM_LBUTTONDBLCLK() - ON_WM_KEYDOWN() - ON_WM_LBUTTONDOWN() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// *************************************************************************** -// CMyListBox message handlers -// *************************************************************************** - -BOOL CMyListBox::OnCommand(WPARAM wParam, LPARAM lParam) -{ - WORD wNotifyCode = HIWORD(wParam); // notification code - - if (_EditingItem != LB_ERR) - { - switch (wNotifyCode) - { - case CBN_SELENDOK: - { - CString str; - getWindowTextUTF8 (StringSelectComboBox, str); - DeleteString(_EditingItem); - InsertString(_EditingItem, str); - SetCurSel (_SelectAfter); - _EditingItem = LB_ERR; - notifyParent (); - StringSelectComboBox.ShowWindow(SW_HIDE); - } - break; - case CBN_SELENDCANCEL: - { - if (_DeleteItIfCancel) - DeleteString (_EditingItem); - SetCurSel (_SelectAfter); - _EditingItem = LB_ERR; - StringSelectComboBox.ShowWindow(SW_HIDE); - } - break; - } - } - - return CListBox::OnCommand(wParam, lParam); -} - -// *************************************************************************** - -void CMyListBox::OnDblclk() -{ -} - -// *************************************************************************** - -BOOL CMyListBox::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, LPVOID lpParam) -{ - if (CWnd::CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, lpParam)) - { - CRect itemRect (0, 0, 100, 100); - nlverify (StringSelectComboBox.Create (CBS_DISABLENOSCROLL|WS_VSCROLL|CBS_DROPDOWNLIST|WS_TABSTOP, itemRect, - this, 0)); - return TRUE; - } - return FALSE; -} - -// *************************************************************************** - -void CMyListBox::OnLButtonDblClk(UINT nFlags, CPoint point) -{ - CListBox::OnLButtonDblClk(nFlags, point); - - BOOL bOutside; - _EditingItem = ItemFromPoint( point, bOutside ); - - // Get the selected item - _SelectAfter = GetCurSel(); - if ((_EditingItem == LB_ERR) || bOutside) - { - _EditingItem = InsertString (-1, ""); - _DeleteItIfCancel = true; - } - else - { - _DeleteItIfCancel = false; - _SelectAfter = _EditingItem; - } - - // Get the item rect - RECT itemRect; - GetItemRect(_EditingItem, &itemRect); - - // Show the combo box - itemRect.bottom = itemRect.top + COMBO_REAL_HEIGHT; - CString itemText; - GetText (_EditingItem, itemText); - StringSelectComboBox.SelectString (-1, itemText); - StringSelectComboBox.SetWindowPos (&wndTop, itemRect.left, itemRect.top, itemRect.right-itemRect.left, COMBO_REAL_HEIGHT, SWP_SHOWWINDOW); - StringSelectComboBox.ShowDropDown (TRUE); - - StringSelectComboBox.SetFocus(); - -} - -// *************************************************************************** - -void CMyListBox::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) -{ - int item = GetCurSel(); - CListBox::OnKeyDown(nChar, nRepCnt, nFlags); - - // Suppr ? - bool modified = false; - if (nChar == VK_DELETE) - { - if (item != LB_ERR) - { - DeleteString (item); - if ((item >= GetCount()) && (item != 0)) - item--; - if (item < GetCount()) - SetCurSel (item); - modified = true; - } - } - else if (nChar == VK_INSERT) - { - if (item != LB_ERR) - { - CString text; - GetText (item, text); - InsertString (item, text); - SetCurSel (item); - modified = true; - } - } - else if ( (nChar == VK_UP) && (GetAsyncKeyState (VK_CONTROL) & 0x8000)) - { - if ( (item != LB_ERR) && (item != 0)) - { - CString itemText; - GetText (item, itemText); - InsertString (item-1, itemText); - DeleteString (item+1); - SetCurSel (item-1); - modified = true; - } - } - else if ( (nChar == VK_DOWN) && (GetAsyncKeyState (VK_CONTROL) & 0x8000)) - { - if ( (item != LB_ERR) && (item != GetCount()-1)) - { - CString itemText; - GetText (item, itemText); - InsertString (item+2, itemText); - DeleteString (item); - SetCurSel (item+1); - modified = true; - } - } - - // Notify parent ? - if (modified) - notifyParent (); -} - -// *************************************************************************** - -void CMyListBox::OnLButtonDown(UINT nFlags, CPoint point) -{ - BOOL bOutside; - _EditingItem = ItemFromPoint( point, bOutside ); - - // Get the selected item - if ((_EditingItem == LB_ERR) || bOutside) - SetCurSel (-1); - - CListBox::OnLButtonDown(nFlags, point); -} - -// *************************************************************************** - -void CMyListBox::notifyParent () -{ - if (GetParent()) - GetParent()->SendMessage (LBN_CHANGE, GetDlgCtrlID(), 0); -} - -// *************************************************************************** +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// my_list_box.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "my_list_box.h" + +#define COMBO_REAL_HEIGHT 300 + +// *************************************************************************** +// CMyListBox +// *************************************************************************** + +CMyListBox::CMyListBox() +{ +} + +// *************************************************************************** + +CMyListBox::~CMyListBox() +{ +} + +// *************************************************************************** + +BEGIN_MESSAGE_MAP(CMyListBox, CListBox) + //{{AFX_MSG_MAP(CMyListBox) + ON_CONTROL_REFLECT(LBN_DBLCLK, OnDblclk) + ON_WM_LBUTTONDBLCLK() + ON_WM_KEYDOWN() + ON_WM_LBUTTONDOWN() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// *************************************************************************** +// CMyListBox message handlers +// *************************************************************************** + +BOOL CMyListBox::OnCommand(WPARAM wParam, LPARAM lParam) +{ + WORD wNotifyCode = HIWORD(wParam); // notification code + + if (_EditingItem != LB_ERR) + { + switch (wNotifyCode) + { + case CBN_SELENDOK: + { + CString str; + getWindowTextUTF8 (StringSelectComboBox, str); + DeleteString(_EditingItem); + InsertString(_EditingItem, str); + SetCurSel (_SelectAfter); + _EditingItem = LB_ERR; + notifyParent (); + StringSelectComboBox.ShowWindow(SW_HIDE); + } + break; + case CBN_SELENDCANCEL: + { + if (_DeleteItIfCancel) + DeleteString (_EditingItem); + SetCurSel (_SelectAfter); + _EditingItem = LB_ERR; + StringSelectComboBox.ShowWindow(SW_HIDE); + } + break; + } + } + + return CListBox::OnCommand(wParam, lParam); +} + +// *************************************************************************** + +void CMyListBox::OnDblclk() +{ +} + +// *************************************************************************** + +BOOL CMyListBox::CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, LPVOID lpParam) +{ + if (CWnd::CreateEx(dwExStyle, lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, lpParam)) + { + CRect itemRect (0, 0, 100, 100); + nlverify (StringSelectComboBox.Create (CBS_DISABLENOSCROLL|WS_VSCROLL|CBS_DROPDOWNLIST|WS_TABSTOP, itemRect, + this, 0)); + return TRUE; + } + return FALSE; +} + +// *************************************************************************** + +void CMyListBox::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + CListBox::OnLButtonDblClk(nFlags, point); + + BOOL bOutside; + _EditingItem = ItemFromPoint( point, bOutside ); + + // Get the selected item + _SelectAfter = GetCurSel(); + if ((_EditingItem == LB_ERR) || bOutside) + { + _EditingItem = InsertString (-1, ""); + _DeleteItIfCancel = true; + } + else + { + _DeleteItIfCancel = false; + _SelectAfter = _EditingItem; + } + + // Get the item rect + RECT itemRect; + GetItemRect(_EditingItem, &itemRect); + + // Show the combo box + itemRect.bottom = itemRect.top + COMBO_REAL_HEIGHT; + CString itemText; + GetText (_EditingItem, itemText); + StringSelectComboBox.SelectString (-1, itemText); + StringSelectComboBox.SetWindowPos (&wndTop, itemRect.left, itemRect.top, itemRect.right-itemRect.left, COMBO_REAL_HEIGHT, SWP_SHOWWINDOW); + StringSelectComboBox.ShowDropDown (TRUE); + + StringSelectComboBox.SetFocus(); + +} + +// *************************************************************************** + +void CMyListBox::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + int item = GetCurSel(); + CListBox::OnKeyDown(nChar, nRepCnt, nFlags); + + // Suppr ? + bool modified = false; + if (nChar == VK_DELETE) + { + if (item != LB_ERR) + { + DeleteString (item); + if ((item >= GetCount()) && (item != 0)) + item--; + if (item < GetCount()) + SetCurSel (item); + modified = true; + } + } + else if (nChar == VK_INSERT) + { + if (item != LB_ERR) + { + CString text; + GetText (item, text); + InsertString (item, text); + SetCurSel (item); + modified = true; + } + } + else if ( (nChar == VK_UP) && (GetAsyncKeyState (VK_CONTROL) & 0x8000)) + { + if ( (item != LB_ERR) && (item != 0)) + { + CString itemText; + GetText (item, itemText); + InsertString (item-1, itemText); + DeleteString (item+1); + SetCurSel (item-1); + modified = true; + } + } + else if ( (nChar == VK_DOWN) && (GetAsyncKeyState (VK_CONTROL) & 0x8000)) + { + if ( (item != LB_ERR) && (item != GetCount()-1)) + { + CString itemText; + GetText (item, itemText); + InsertString (item+2, itemText); + DeleteString (item); + SetCurSel (item+1); + modified = true; + } + } + + // Notify parent ? + if (modified) + notifyParent (); +} + +// *************************************************************************** + +void CMyListBox::OnLButtonDown(UINT nFlags, CPoint point) +{ + BOOL bOutside; + _EditingItem = ItemFromPoint( point, bOutside ); + + // Get the selected item + if ((_EditingItem == LB_ERR) || bOutside) + SetCurSel (-1); + + CListBox::OnLButtonDown(nFlags, point); +} + +// *************************************************************************** + +void CMyListBox::notifyParent () +{ + if (GetParent()) + GetParent()->SendMessage (LBN_CHANGE, GetDlgCtrlID(), 0); +} + +// *************************************************************************** diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/my_list_box.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/my_list_box.h index 9e2bd6529..9a1d23b4f 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/my_list_box.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/my_list_box.h @@ -1,85 +1,85 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_MY_LIST_BOX_H__24C857D7_CA96_42FE_86BC_38BBF134EA79__INCLUDED_) -#define AFX_MY_LIST_BOX_H__24C857D7_CA96_42FE_86BC_38BBF134EA79__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// my_list_box.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CMyListBox window - -#define LBN_CHANGE (WM_USER+10) - -class CMyListBox : public CListBox -{ -// Construction -public: - CMyListBox(); - -// Attributes -public: - -// Operations -public: - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CMyListBox) - protected: - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - //}}AFX_VIRTUAL - -// Implementation -public: - virtual ~CMyListBox(); - - // The string selection combo - CComboBox StringSelectComboBox; - - // Create - BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, LPVOID lpParam = NULL); - - // Generated message map functions -protected: - - void notifyParent (); - - // Item editing - int _EditingItem; - int _SelectAfter; - bool _DeleteItIfCancel; - - //{{AFX_MSG(CMyListBox) - afx_msg void OnDblclk(); - afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); - afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); - afx_msg void OnLButtonDown(UINT nFlags, CPoint point); - //}}AFX_MSG - - DECLARE_MESSAGE_MAP() -}; - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_MY_LIST_BOX_H__24C857D7_CA96_42FE_86BC_38BBF134EA79__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_MY_LIST_BOX_H__24C857D7_CA96_42FE_86BC_38BBF134EA79__INCLUDED_) +#define AFX_MY_LIST_BOX_H__24C857D7_CA96_42FE_86BC_38BBF134EA79__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// my_list_box.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CMyListBox window + +#define LBN_CHANGE (WM_USER+10) + +class CMyListBox : public CListBox +{ +// Construction +public: + CMyListBox(); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMyListBox) + protected: + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CMyListBox(); + + // The string selection combo + CComboBox StringSelectComboBox; + + // Create + BOOL CreateEx(DWORD dwExStyle, LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, LPVOID lpParam = NULL); + + // Generated message map functions +protected: + + void notifyParent (); + + // Item editing + int _EditingItem; + int _SelectAfter; + bool _DeleteItIfCancel; + + //{{AFX_MSG(CMyListBox) + afx_msg void OnDblclk(); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + //}}AFX_MSG + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MY_LIST_BOX_H__24C857D7_CA96_42FE_86BC_38BBF134EA79__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/name_dlg.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/name_dlg.cpp index 90bbb6bb1..c71ed31f5 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/name_dlg.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/name_dlg.cpp @@ -1,407 +1,407 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// name_dlg.cpp : implementation file -// - -#include "stdafx.h" -#include "resource.h" -#include "name_dlg.h" -#include "world_editor.h" -#include "main_frm.h" -#include "nel/misc/path.h" -#include "nel/misc/config_file.h" - - -///////////////////////////////////////////////////////////////////////////// -// CNameDlg dialog - - -CNameDlg::CNameDlg(CWnd* pParent /*=NULL*/) - : CDialog(CNameDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CNameDlg) - m_nameFilter = _T(""); - //}}AFX_DATA_INIT -} - - -void CNameDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CNameDlg) - DDX_Text(pDX, IDC_NAME_FILTER, m_nameFilter); - DDX_Text(pDX, IDC_NAME_EBOX_GN, m_assignGn); - DDX_Text(pDX, IDC_NAME_EBOX_IG, m_assignIg); - DDX_Control(pDX, IDC_NAME_SEARCH, m_searchList); - DDX_Control(pDX, IDC_NAME_ID, m_idList); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CNameDlg, CDialog) - //{{AFX_MSG_MAP(CNameDlg) - ON_EN_CHANGE(IDC_NAME_FILTER, OnChangeNameFilter) - ON_EN_CHANGE(IDC_NAME_EBOX_GN, OnChangeNameEboxGn) - ON_EN_CHANGE(IDC_NAME_EBOX_IG, OnChangeNameEboxIg) - ON_LBN_SELCHANGE(IDC_NAME_SEARCH, OnSelNameSearch) - ON_BN_CLICKED(ID_NAME_ASSIGN, OnBtnAssign) - ON_BN_CLICKED(ID_NAME_RESET, OnBtnReset) - ON_LBN_DBLCLK(IDC_NAME_ID, OnDblClkId) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CNameDlg message handlers - -BOOL CNameDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // read config var : "BotNamePath" - NLMISC::CConfigFile::CVar *var = getMainFrame()->getConfigFile().getVarPtr("BotNamePath"); - if (var) - { - m_dataDir = NLMISC::CPath::standardizePath(var->asString()); - } - else - { - getMainFrame()->errorMessage("Can't find variable BotNamePath in config file !\nPlease fill your config file."); - return FALSE; - } - - // print the data directory - CWnd* pWnd = GetDlgItem(IDC_NAME_DIR); - pWnd->SetWindowText(("Data directory: " + m_dataDir).c_str()); - - // tab stops to simulate multi-columns edit boxes - int tab_stop1[1] = {160}; - m_searchList.SetTabStops(1, tab_stop1); - int tab_stop2[2] = {160, 300}; - m_idList.SetTabStops(2, tab_stop2); - - // reload data - OnBtnReset(); - - return TRUE; -} - -void CNameDlg::OnOK() -{ - // write file to disk : "bot_names.txt" - ucstring s = STRING_MANAGER::prepareExcelSheet(m_botNames); - NLMISC::CI18N::writeTextFile(m_dataDir + "bot_names.txt", s, false); - - // write file to disk : "title_words_wk.txt" - s = STRING_MANAGER::prepareExcelSheet(m_fcts); - NLMISC::CI18N::writeTextFile(m_dataDir + "title_words_wk.txt", s, false); - - CDialog::OnOK(); -} - -void CNameDlg::OnChangeNameFilter() -{ - UpdateData(TRUE); - updateSearchList(); - updateAssignBox(); -} - -void CNameDlg::OnChangeNameEboxGn() -{ - UpdateData(TRUE); - m_searchList.SetCurSel(-1); - checkNewGn(); - checkAssignBtn(); -} - -void CNameDlg::OnChangeNameEboxIg() -{ - UpdateData(TRUE); - m_searchList.SetCurSel(-1); - checkAssignBtn(); -} - -void CNameDlg::updateSearchList() -{ - // clear containers - m_searchList.ResetContent(); - m_listToName.clear(); - - // Fill search list - uint i, j; - for (i=1, j=0 ; i::iterator it = m_sel.begin(); - for (uint i=0 ; it!=m_sel.end() ; ++it) - { - // Bad primitive selected : do nothing - std::string id = (*it)->getName(); - if (id == "") - continue; - - // try to remove "$" in name like : *$fct*$ - uint n = id.find("$"); - if (n != std::string::npos) - id.erase(n); - - // Check if id exist in files - std::string s = id; - uint row; - if (m_botNames.findRow(0, id, row)) - { - std::string gn = m_botNames.getData(row, 1).toString(); - - // remove $ - if (gn[0] == '$' && gn[gn.size()-1] == '$') - { - gn.erase(0, 1); - gn.erase(gn.size()-1, 1); - } - uint r; - s += ("\t" + gn); - if (m_fcts.findRow(0, gn, r)) - s += ("\t" + m_fcts.getData(r, 1).toString()); - - m_listToId.insert(std::make_pair(i, row)); - } - - m_idList.InsertString(i++, s.c_str()); - } -} - -void CNameDlg::OnSelNameSearch() -{ - updateAssignBox(); -} - -void CNameDlg::updateAssignBox() -{ - uint nameSel = m_searchList.GetCurSel(); - if (nameSel != -1) - { - uint row = m_listToName[nameSel]; - m_assignGn = m_fcts.getData(row, 0).toString().c_str(); - m_assignIg = m_fcts.getData(row, 1).toString().c_str(); - } - else - { - m_assignGn = ""; - m_assignIg = ""; - } - - checkNewGn(); - checkAssignBtn(); -} - -void CNameDlg::OnBtnAssign() -{ - // get selection - std::vector sel; - sel.resize(m_idList.GetSelCount()); - m_idList.GetSelItems(sel.size(), &sel[0]); - - // get strings - ucstring id; - std::string gn = m_assignGn; - std::string ig = m_assignIg; - - for (uint i=0 ; i::iterator it = m_sel.begin(); - for ( ; it!=m_sel.end() ; ++it) - { - std::string id = (*it)->getName(); - - // check if exist - uint rowIndex; - if (!m_botNames.findRow(0, id, rowIndex)) - { - rowIndex = m_botNames.size(); - m_botNames.resize(rowIndex+1); - m_botNames.setData(rowIndex, 0, id); - } - } - - updateSearchList(); - updateSelectList(); -} - - -void CNameDlg::setSelection(std::list sel) -{ - // get selected primitives : don't add duplicate because they reference the same bot name - - std::list::iterator it; - - for (it = sel.begin() ; it!=sel.end() ; ++it) - { - std::list::iterator itFind = m_sel.begin(); - - while(itFind != m_sel.end() && ((*it)->getName() != (*itFind)->getName())) - ++itFind; - - if (itFind == m_sel.end()) - m_sel.push_back(*it); - } -} - - -void CNameDlg::setName(const ucstring &id, const ucstring &gn, const ucstring &ig) -{ - // search if id exists in the file : we added missing ones at init - // so, it should never fail - uint rowIndex; - if (!m_botNames.findRow(0, id, rowIndex)) - { - nlassert(1); - } - m_botNames.setData(rowIndex, 1, "$" + gn + "$"); - - - // search if generic name exists in the file - // add an entry or modify it - if (!m_fcts.findRow(0, gn, rowIndex)) - { - rowIndex = m_fcts.size(); - m_fcts.resize(rowIndex+1); - m_fcts.setData(rowIndex, 0, gn); - } - m_fcts.setData(rowIndex, 1, ig); -} - -void CNameDlg::checkNewGn() -{ - // print a message if a new gn will be added to the list - CWnd* pWnd = GetDlgItem(IDC_NAME_NEWGN); - std::string s = m_assignGn; - uint rowIndex; - if (s == "") - { - pWnd->SetWindowText(" "); - } - else if (!m_fcts.findRow(0, s, rowIndex)) - { - pWnd->SetWindowText("new gn !"); - } - else - { - pWnd->SetWindowText(" "); - // auto-fill ig field - m_assignIg = m_fcts.getData(rowIndex, 1).toString().c_str(); - } - - UpdateData(FALSE); -} - -void CNameDlg::checkAssignBtn() -{ - // enable if both fields are filled - CWnd* pWnd = GetDlgItem(ID_NAME_ASSIGN); - if (m_assignIg == "" || m_assignGn == "") - pWnd->EnableWindow(FALSE); - else - pWnd->EnableWindow(TRUE); -} - -void CNameDlg::OnDblClkId() -{ - // get selection - std::vector sel; - sel.resize(m_idList.GetSelCount()); - m_idList.GetSelItems(sel.size(), &sel[0]); - - // assume that only the first item selected is valid - uint rowIndex = m_listToId[sel[0]]; - - // fill assign box - m_assignGn = ("gn_" + m_botNames.getData(rowIndex, 0).toString()).c_str(); - - // unselect in search list - m_searchList.SetCurSel(-1); - - // check for update - checkNewGn(); - checkAssignBtn(); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// name_dlg.cpp : implementation file +// + +#include "stdafx.h" +#include "resource.h" +#include "name_dlg.h" +#include "world_editor.h" +#include "main_frm.h" +#include "nel/misc/path.h" +#include "nel/misc/config_file.h" + + +///////////////////////////////////////////////////////////////////////////// +// CNameDlg dialog + + +CNameDlg::CNameDlg(CWnd* pParent /*=NULL*/) + : CDialog(CNameDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CNameDlg) + m_nameFilter = _T(""); + //}}AFX_DATA_INIT +} + + +void CNameDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CNameDlg) + DDX_Text(pDX, IDC_NAME_FILTER, m_nameFilter); + DDX_Text(pDX, IDC_NAME_EBOX_GN, m_assignGn); + DDX_Text(pDX, IDC_NAME_EBOX_IG, m_assignIg); + DDX_Control(pDX, IDC_NAME_SEARCH, m_searchList); + DDX_Control(pDX, IDC_NAME_ID, m_idList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CNameDlg, CDialog) + //{{AFX_MSG_MAP(CNameDlg) + ON_EN_CHANGE(IDC_NAME_FILTER, OnChangeNameFilter) + ON_EN_CHANGE(IDC_NAME_EBOX_GN, OnChangeNameEboxGn) + ON_EN_CHANGE(IDC_NAME_EBOX_IG, OnChangeNameEboxIg) + ON_LBN_SELCHANGE(IDC_NAME_SEARCH, OnSelNameSearch) + ON_BN_CLICKED(ID_NAME_ASSIGN, OnBtnAssign) + ON_BN_CLICKED(ID_NAME_RESET, OnBtnReset) + ON_LBN_DBLCLK(IDC_NAME_ID, OnDblClkId) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CNameDlg message handlers + +BOOL CNameDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // read config var : "BotNamePath" + NLMISC::CConfigFile::CVar *var = getMainFrame()->getConfigFile().getVarPtr("BotNamePath"); + if (var) + { + m_dataDir = NLMISC::CPath::standardizePath(var->asString()); + } + else + { + getMainFrame()->errorMessage("Can't find variable BotNamePath in config file !\nPlease fill your config file."); + return FALSE; + } + + // print the data directory + CWnd* pWnd = GetDlgItem(IDC_NAME_DIR); + pWnd->SetWindowText(("Data directory: " + m_dataDir).c_str()); + + // tab stops to simulate multi-columns edit boxes + int tab_stop1[1] = {160}; + m_searchList.SetTabStops(1, tab_stop1); + int tab_stop2[2] = {160, 300}; + m_idList.SetTabStops(2, tab_stop2); + + // reload data + OnBtnReset(); + + return TRUE; +} + +void CNameDlg::OnOK() +{ + // write file to disk : "bot_names.txt" + ucstring s = STRING_MANAGER::prepareExcelSheet(m_botNames); + NLMISC::CI18N::writeTextFile(m_dataDir + "bot_names.txt", s, false); + + // write file to disk : "title_words_wk.txt" + s = STRING_MANAGER::prepareExcelSheet(m_fcts); + NLMISC::CI18N::writeTextFile(m_dataDir + "title_words_wk.txt", s, false); + + CDialog::OnOK(); +} + +void CNameDlg::OnChangeNameFilter() +{ + UpdateData(TRUE); + updateSearchList(); + updateAssignBox(); +} + +void CNameDlg::OnChangeNameEboxGn() +{ + UpdateData(TRUE); + m_searchList.SetCurSel(-1); + checkNewGn(); + checkAssignBtn(); +} + +void CNameDlg::OnChangeNameEboxIg() +{ + UpdateData(TRUE); + m_searchList.SetCurSel(-1); + checkAssignBtn(); +} + +void CNameDlg::updateSearchList() +{ + // clear containers + m_searchList.ResetContent(); + m_listToName.clear(); + + // Fill search list + uint i, j; + for (i=1, j=0 ; i::iterator it = m_sel.begin(); + for (uint i=0 ; it!=m_sel.end() ; ++it) + { + // Bad primitive selected : do nothing + std::string id = (*it)->getName(); + if (id == "") + continue; + + // try to remove "$" in name like : *$fct*$ + uint n = id.find("$"); + if (n != std::string::npos) + id.erase(n); + + // Check if id exist in files + std::string s = id; + uint row; + if (m_botNames.findRow(0, id, row)) + { + std::string gn = m_botNames.getData(row, 1).toString(); + + // remove $ + if (gn[0] == '$' && gn[gn.size()-1] == '$') + { + gn.erase(0, 1); + gn.erase(gn.size()-1, 1); + } + uint r; + s += ("\t" + gn); + if (m_fcts.findRow(0, gn, r)) + s += ("\t" + m_fcts.getData(r, 1).toString()); + + m_listToId.insert(std::make_pair(i, row)); + } + + m_idList.InsertString(i++, s.c_str()); + } +} + +void CNameDlg::OnSelNameSearch() +{ + updateAssignBox(); +} + +void CNameDlg::updateAssignBox() +{ + uint nameSel = m_searchList.GetCurSel(); + if (nameSel != -1) + { + uint row = m_listToName[nameSel]; + m_assignGn = m_fcts.getData(row, 0).toString().c_str(); + m_assignIg = m_fcts.getData(row, 1).toString().c_str(); + } + else + { + m_assignGn = ""; + m_assignIg = ""; + } + + checkNewGn(); + checkAssignBtn(); +} + +void CNameDlg::OnBtnAssign() +{ + // get selection + std::vector sel; + sel.resize(m_idList.GetSelCount()); + m_idList.GetSelItems(sel.size(), &sel[0]); + + // get strings + ucstring id; + std::string gn = m_assignGn; + std::string ig = m_assignIg; + + for (uint i=0 ; i::iterator it = m_sel.begin(); + for ( ; it!=m_sel.end() ; ++it) + { + std::string id = (*it)->getName(); + + // check if exist + uint rowIndex; + if (!m_botNames.findRow(0, id, rowIndex)) + { + rowIndex = m_botNames.size(); + m_botNames.resize(rowIndex+1); + m_botNames.setData(rowIndex, 0, id); + } + } + + updateSearchList(); + updateSelectList(); +} + + +void CNameDlg::setSelection(std::list sel) +{ + // get selected primitives : don't add duplicate because they reference the same bot name + + std::list::iterator it; + + for (it = sel.begin() ; it!=sel.end() ; ++it) + { + std::list::iterator itFind = m_sel.begin(); + + while(itFind != m_sel.end() && ((*it)->getName() != (*itFind)->getName())) + ++itFind; + + if (itFind == m_sel.end()) + m_sel.push_back(*it); + } +} + + +void CNameDlg::setName(const ucstring &id, const ucstring &gn, const ucstring &ig) +{ + // search if id exists in the file : we added missing ones at init + // so, it should never fail + uint rowIndex; + if (!m_botNames.findRow(0, id, rowIndex)) + { + nlassert(1); + } + m_botNames.setData(rowIndex, 1, "$" + gn + "$"); + + + // search if generic name exists in the file + // add an entry or modify it + if (!m_fcts.findRow(0, gn, rowIndex)) + { + rowIndex = m_fcts.size(); + m_fcts.resize(rowIndex+1); + m_fcts.setData(rowIndex, 0, gn); + } + m_fcts.setData(rowIndex, 1, ig); +} + +void CNameDlg::checkNewGn() +{ + // print a message if a new gn will be added to the list + CWnd* pWnd = GetDlgItem(IDC_NAME_NEWGN); + std::string s = m_assignGn; + uint rowIndex; + if (s == "") + { + pWnd->SetWindowText(" "); + } + else if (!m_fcts.findRow(0, s, rowIndex)) + { + pWnd->SetWindowText("new gn !"); + } + else + { + pWnd->SetWindowText(" "); + // auto-fill ig field + m_assignIg = m_fcts.getData(rowIndex, 1).toString().c_str(); + } + + UpdateData(FALSE); +} + +void CNameDlg::checkAssignBtn() +{ + // enable if both fields are filled + CWnd* pWnd = GetDlgItem(ID_NAME_ASSIGN); + if (m_assignIg == "" || m_assignGn == "") + pWnd->EnableWindow(FALSE); + else + pWnd->EnableWindow(TRUE); +} + +void CNameDlg::OnDblClkId() +{ + // get selection + std::vector sel; + sel.resize(m_idList.GetSelCount()); + m_idList.GetSelItems(sel.size(), &sel[0]); + + // assume that only the first item selected is valid + uint rowIndex = m_listToId[sel[0]]; + + // fill assign box + m_assignGn = ("gn_" + m_botNames.getData(rowIndex, 0).toString()).c_str(); + + // unselect in search list + m_searchList.SetCurSel(-1); + + // check for update + checkNewGn(); + checkAssignBtn(); +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/name_dlg.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/name_dlg.h index 237f0175d..af5410866 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/name_dlg.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/name_dlg.h @@ -1,96 +1,96 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_NAME_DLG_H -#define NL_NAME_DLG_H - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include "nel/misc/diff_tool.h" - -class CNameDlg : public CDialog -{ -// Construction -public: - CNameDlg(CWnd* pParent = NULL); - -// Dialog Data - //{{AFX_DATA(CNameDlg) - enum { IDD = IDD_NAME }; - CString m_nameFilter; - CString m_assignGn; - CString m_assignIg; - CListBox m_searchList; - CListBox m_idList; - //}}AFX_DATA - - // list of selected primitives - std::list m_sel; - - // Worksheet : "bot_names.txt" - STRING_MANAGER::TWorksheet m_botNames; - - // Worksheet : "title_words_wk.txt" - STRING_MANAGER::TWorksheet m_fcts; - - // maps from edit boxes to data - std::map m_listToName; - std::map m_listToId; - - // data directory - std::string m_dataDir; - - -// Overrides - //{{AFX_VIRTUAL(CNameDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -public: - void setSelection(std::list sel); - -protected: - void updateSearchList(); - void updateSelectList(); - void updateAssignBox(); - void checkNewGn(); - void checkAssignBtn(); - void setName(const ucstring &id, const ucstring &gn, const ucstring &ig); - - - // Generated message map functions - //{{AFX_MSG(CNameDlg) - virtual BOOL OnInitDialog(); - virtual void OnOK(); - afx_msg void OnChangeNameFilter(); - afx_msg void OnChangeNameEboxGn(); - afx_msg void OnChangeNameEboxIg(); - afx_msg void OnSelNameSearch(); - afx_msg void OnBtnAssign(); - afx_msg void OnBtnReset(); - afx_msg void OnDblClkId(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // NL_NAME_DLG_H +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef NL_NAME_DLG_H +#define NL_NAME_DLG_H + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include "nel/misc/diff_tool.h" + +class CNameDlg : public CDialog +{ +// Construction +public: + CNameDlg(CWnd* pParent = NULL); + +// Dialog Data + //{{AFX_DATA(CNameDlg) + enum { IDD = IDD_NAME }; + CString m_nameFilter; + CString m_assignGn; + CString m_assignIg; + CListBox m_searchList; + CListBox m_idList; + //}}AFX_DATA + + // list of selected primitives + std::list m_sel; + + // Worksheet : "bot_names.txt" + STRING_MANAGER::TWorksheet m_botNames; + + // Worksheet : "title_words_wk.txt" + STRING_MANAGER::TWorksheet m_fcts; + + // maps from edit boxes to data + std::map m_listToName; + std::map m_listToId; + + // data directory + std::string m_dataDir; + + +// Overrides + //{{AFX_VIRTUAL(CNameDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +public: + void setSelection(std::list sel); + +protected: + void updateSearchList(); + void updateSelectList(); + void updateAssignBox(); + void checkNewGn(); + void checkAssignBtn(); + void setName(const ucstring &id, const ucstring &gn, const ucstring &ig); + + + // Generated message map functions + //{{AFX_MSG(CNameDlg) + virtual BOOL OnInitDialog(); + virtual void OnOK(); + afx_msg void OnChangeNameFilter(); + afx_msg void OnChangeNameEboxGn(); + afx_msg void OnChangeNameEboxIg(); + afx_msg void OnSelNameSearch(); + afx_msg void OnBtnAssign(); + afx_msg void OnBtnReset(); + afx_msg void OnDblClkId(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // NL_NAME_DLG_H diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/pacs.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/pacs.cpp index d96b40bc9..43cd7a8c7 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/pacs.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/pacs.cpp @@ -1,159 +1,159 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" - -#include "pacs.h" -#include "display.h" -#include "world_editor.h" -#include "main_frm.h" - -using namespace std; -using namespace NL3D; -using namespace NLMISC; -using namespace NLLIGO; -using namespace NLPACS; - -// *************************************************************************** - -CPacsManager PacsManager; - -// *************************************************************************** - -CPacsManager::~CPacsManager() -{ - releasePacs(); -} - -// *************************************************************************** - -void CPacsManager::loadPacs() -{ - // Set a current directory - string path = _Dir; - string currentPath = CPath::getCurrentPath(); - - // "Path" can be relative to the doc path so we have to be first in the doc path - string s2 = NLMISC::CFile::getPath ((LPCTSTR)getMainFrame()->getDocument()->GetPathName()); - CPath::setCurrentPath(s2.c_str()); - string ss = CPath::getFullPath(path); - CPath::setCurrentPath (ss.c_str()); - - // Load each rbank here... - std::vector files; - CPath::getPathContent (ss, false, false, true, files); - uint i; - for (i=0; i > edges; - CAABBox box; - box.setCenter (display._CurViewMin); - box.extend (display._CurViewMax); - _Retrievers[i].Retriever->getBorders(box, edges); - - // Draw the borders - uint j; - for(j=0; j +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" + +#include "pacs.h" +#include "display.h" +#include "world_editor.h" +#include "main_frm.h" + +using namespace std; +using namespace NL3D; +using namespace NLMISC; +using namespace NLLIGO; +using namespace NLPACS; + +// *************************************************************************** + +CPacsManager PacsManager; + +// *************************************************************************** + +CPacsManager::~CPacsManager() +{ + releasePacs(); +} + +// *************************************************************************** + +void CPacsManager::loadPacs() +{ + // Set a current directory + string path = _Dir; + string currentPath = CPath::getCurrentPath(); + + // "Path" can be relative to the doc path so we have to be first in the doc path + string s2 = NLMISC::CFile::getPath ((LPCTSTR)getMainFrame()->getDocument()->GetPathName()); + CPath::setCurrentPath(s2.c_str()); + string ss = CPath::getFullPath(path); + CPath::setCurrentPath (ss.c_str()); + + // Load each rbank here... + std::vector files; + CPath::getPathContent (ss, false, false, true, files); + uint i; + for (i=0; i > edges; + CAABBox box; + box.setCenter (display._CurViewMin); + box.extend (display._CurViewMax); + _Retrievers[i].Retriever->getBorders(box, edges); + + // Draw the borders + uint j; + for(j=0; j -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// pacs.g : implementation file -// - -#ifndef NL_PACS_H -#define NL_PACS_H - -class CPacsManager -{ -public: - // Destructor - ~CPacsManager(); - - // Load pacs data - void loadPacs(); - - // Release pacs data - void releasePacs(); - - // Display pacs data - void displayPacs(class CDisplay &display); - - // Are PACS loaded ? - bool areLoaded() { return _Loaded; } - - // Set PACS directory - void setDir(const std::string &path) { _Dir = path; } - -private: - class CRetriever - { - public: - class NLPACS::URetrieverBank *Bank; - class NLPACS::UGlobalRetriever *Retriever; - }; - std::vector _Retrievers; - bool _Loaded; - std::string _Dir; -}; - -extern CPacsManager PacsManager; - -#endif // NL_PACS_H +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// pacs.g : implementation file +// + +#ifndef NL_PACS_H +#define NL_PACS_H + +class CPacsManager +{ +public: + // Destructor + ~CPacsManager(); + + // Load pacs data + void loadPacs(); + + // Release pacs data + void releasePacs(); + + // Display pacs data + void displayPacs(class CDisplay &display); + + // Are PACS loaded ? + bool areLoaded() { return _Loaded; } + + // Set PACS directory + void setDir(const std::string &path) { _Dir = path; } + +private: + class CRetriever + { + public: + class NLPACS::URetrieverBank *Bank; + class NLPACS::UGlobalRetriever *Retriever; + }; + std::vector _Retrievers; + bool _Loaded; + std::string _Dir; +}; + +extern CPacsManager PacsManager; + +#endif // NL_PACS_H diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/plugin_interface.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/plugin_interface.h index 2bbe143c1..8496dab9f 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/plugin_interface.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/plugin_interface.h @@ -1,222 +1,222 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef NL_PLUGIN_INTERFACE_H -#define NL_PLUGIN_INTERFACE_H - -#include "nel/misc/vector.h" -#include "nel/ligo/primitive.h" -#include "nel/misc/config_file.h" -#include -#include "nel/net/callback_client.h" -#include "nel/misc/sheet_id.h" -#include "display.h" - -class IPluginCallback; -class IPrimitiveDisplayer; - -extern "C" -{ - /// Factory method for plugins. - //typedef void *(FCreateSoundPlugin)(); - typedef void *(FCreatePlugin)(); -} - -class CDipslay; - -enum TValidationChannel -{ - // Invalidate the primitive because its position has benn modified - QuadTree = 1, - - // Invalidate the primitive because its structure has changed - LogicTreeStruct = 2, - - // Invalidate the primitive because its name, visibility, expand state has changed - LogicTreeParam = 4, - - // Invalidate the selection for this primitive - _SelectionSelectState = 8, - - // Invalidate the selection for this primitive - SelectionState = (_SelectionSelectState|LogicTreeParam), -}; - -/** Interface to access the world editor from the plugin. - * This interface is implemented by the world editor and - * used by the sound plugin. - */ -class IPluginAccess -{ -public: - /// Retrieve the config file. - virtual NLMISC::CConfigFile &getConfigFile() = 0; - - /// Retrieve the main window handle. - virtual CWnd *getMainWindow() =0; - - /// Output error messages - virtual bool yesNoMessage (const char *format, ... ) =0; - virtual void errorMessage (const char *format, ... ) =0; - virtual void infoMessage (const char *format, ... ) =0; - - /// Add a toolbar in the main frame. -// virtual void addToolBar(CToolBar *ptoolBar) =0; - - /// Start the control of a position into the 2D view. Changed are reported throw IPluginCallback::positionMoved - virtual void startPositionControl(IPluginCallback *plugin, const NLMISC::CVector &initPos) =0; - /// Stop the control of a position. - virtual void stopPositionControl(IPluginCallback *plugin) =0; - - /* Functions to create/remove the Root Primitive for server actions - Returns the id of the root primitive - */ - virtual NLLIGO::IPrimitive *createRootPluginPrimitive (const char *name) = 0; - virtual void deleteRootPluginPrimitive (void) = 0; - /// get all the current root primitve in the world editor. only the editable one are returned - virtual void getAllRootPluginPrimitive (std::vector &prims) = 0; - /* - * The players or informations coming from the server are considered as primitives by the WorldEditor - * so we need to create/delete/modify these primitives - */ - // Create a plugin primitive - virtual const NLLIGO::IPrimitive *createPluginPrimitive ( - const char *className, - const char *primName, - const NLMISC::CVector &initPos, - float deltaPos, - const std::vector &initParameters, - NLLIGO::IPrimitive *parent - ) = 0; - - // delete a plugin primitive - virtual void deletePluginPrimitive (const NLLIGO::IPrimitive *primitive) = 0; - - // indicates to the WorldEditor that the primitive has changed - virtual void invalidatePluginPrimitive (const NLLIGO::IPrimitive *primitive, uint channels) = 0; - - // invalidate the left view completely - virtual void invalidateLeftView() = 0; - - // get the display window coordinates - virtual void getWindowCoordinates(NLMISC::CVector &vmin, NLMISC::CVector &vmax) = 0; - - // Get the current selection - virtual const std::list &getCurrentSelection()=0; - - virtual void setCurrentSelection(std::vector& )=0; - - virtual const NLLIGO::IPrimitive* getRootNode(const std::string&)=0; - - virtual std::string& getRootFileName(NLLIGO::IPrimitive*)=0; - - // Register a primitive displayer - virtual void registerPrimitiveDisplayer(IPrimitiveDisplayer *displayer, const std::vector &primClassNames) =0; - - // Get current selection of primitives - virtual const std::list &getCurrentSelection() const = 0; - - // helper to test if a primitive is selected - virtual bool isSelected(const NLLIGO::IPrimitive &prim) const = 0; - - // Refresh the current property dialog. - virtual void refreshPropertyDialog() = 0; - - // Hide / show a primitive - virtual void setPrimitiveHideFlag(NLLIGO::IPrimitive &prim, bool hidden) = 0; - - // Create a texture object - virtual CPrimTexture *createTexture() = 0; - - // Delete a texture object - virtual void deleteTexture(CPrimTexture *tex) = 0; - - /** Tool function : build a NLMISC CBitmap from a tga resource - * \return true if build was successful - */ - virtual bool buildNLBitmapFromTGARsc(HRSRC bm, HMODULE hm, NLMISC::CBitmap &dest) = 0; - -}; -/** Interface for plugin callback. - * This interface must be implemented by the plugin to receive - * notification about the edited document. - * \author Boris Boucher -* \author Nevrax - */ -class IPluginCallback -{ -public: - /// Init the plugin. The plugin receive the world editor interface. - virtual void init(IPluginAccess *pluginAccess) =0; - /// Delete the plugin. - virtual ~IPluginCallback() {} - - /// The current region has changed. -// virtual void primRegionChanged(const std::vector ®ions) = 0; - virtual void primitiveChanged(const NLLIGO::IPrimitive *root) = 0; - /// The region has been modifed. -// virtual void primRegionModifed() = 0; - - - /// The position has been moved on the map. - virtual void positionMoved(const NLMISC::CVector &position) = 0; - /// The plugin lost the control of the position - virtual void lostPositionControl() =0; - - // calling this routine manage the received data - virtual void onIdle()=0; - - // called after post render so that plugin can draw additionnal stuffs - virtual void postRender(CDisplay &display) {} - - //getting the name of the plugin - virtual std::string& getName()=0; - - //testing whether the plugin is active or not (currently in use or not) - virtual bool isActive()=0; - - - virtual bool activatePlugin()=0; - - virtual bool closePlugin()=0; -}; -// Interface for primitive display plusing -class IPrimitiveDisplayer -{ -public: - // a bunch of data to help pluging in drawing task - struct TRenderContext - { - // need to display detail information - bool ShowDetail; - // is the primitive selected ? - bool Selected; - // Some colors as defined by primitive state and configuration files - NLMISC::CRGBA MainColor; - NLMISC::CRGBA ArrowColor; - NLMISC::CRGBA DotColor; - NLMISC::CRGBA LineColor; - // The primitive class information - const NLLIGO::CPrimitiveClass *PrimitiveClass; - // The display - CDisplay *Display; - }; - - virtual void drawPrimitive(const NLLIGO::IPrimitive *primitive, const TRenderContext &renderContext) =0; -}; - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef NL_PLUGIN_INTERFACE_H +#define NL_PLUGIN_INTERFACE_H + +#include "nel/misc/vector.h" +#include "nel/ligo/primitive.h" +#include "nel/misc/config_file.h" +#include +#include "nel/net/callback_client.h" +#include "nel/misc/sheet_id.h" +#include "display.h" + +class IPluginCallback; +class IPrimitiveDisplayer; + +extern "C" +{ + /// Factory method for plugins. + //typedef void *(FCreateSoundPlugin)(); + typedef void *(FCreatePlugin)(); +} + +class CDipslay; + +enum TValidationChannel +{ + // Invalidate the primitive because its position has benn modified + QuadTree = 1, + + // Invalidate the primitive because its structure has changed + LogicTreeStruct = 2, + + // Invalidate the primitive because its name, visibility, expand state has changed + LogicTreeParam = 4, + + // Invalidate the selection for this primitive + _SelectionSelectState = 8, + + // Invalidate the selection for this primitive + SelectionState = (_SelectionSelectState|LogicTreeParam), +}; + +/** Interface to access the world editor from the plugin. + * This interface is implemented by the world editor and + * used by the sound plugin. + */ +class IPluginAccess +{ +public: + /// Retrieve the config file. + virtual NLMISC::CConfigFile &getConfigFile() = 0; + + /// Retrieve the main window handle. + virtual CWnd *getMainWindow() =0; + + /// Output error messages + virtual bool yesNoMessage (const char *format, ... ) =0; + virtual void errorMessage (const char *format, ... ) =0; + virtual void infoMessage (const char *format, ... ) =0; + + /// Add a toolbar in the main frame. +// virtual void addToolBar(CToolBar *ptoolBar) =0; + + /// Start the control of a position into the 2D view. Changed are reported throw IPluginCallback::positionMoved + virtual void startPositionControl(IPluginCallback *plugin, const NLMISC::CVector &initPos) =0; + /// Stop the control of a position. + virtual void stopPositionControl(IPluginCallback *plugin) =0; + + /* Functions to create/remove the Root Primitive for server actions + Returns the id of the root primitive + */ + virtual NLLIGO::IPrimitive *createRootPluginPrimitive (const char *name) = 0; + virtual void deleteRootPluginPrimitive (void) = 0; + /// get all the current root primitve in the world editor. only the editable one are returned + virtual void getAllRootPluginPrimitive (std::vector &prims) = 0; + /* + * The players or informations coming from the server are considered as primitives by the WorldEditor + * so we need to create/delete/modify these primitives + */ + // Create a plugin primitive + virtual const NLLIGO::IPrimitive *createPluginPrimitive ( + const char *className, + const char *primName, + const NLMISC::CVector &initPos, + float deltaPos, + const std::vector &initParameters, + NLLIGO::IPrimitive *parent + ) = 0; + + // delete a plugin primitive + virtual void deletePluginPrimitive (const NLLIGO::IPrimitive *primitive) = 0; + + // indicates to the WorldEditor that the primitive has changed + virtual void invalidatePluginPrimitive (const NLLIGO::IPrimitive *primitive, uint channels) = 0; + + // invalidate the left view completely + virtual void invalidateLeftView() = 0; + + // get the display window coordinates + virtual void getWindowCoordinates(NLMISC::CVector &vmin, NLMISC::CVector &vmax) = 0; + + // Get the current selection + virtual const std::list &getCurrentSelection()=0; + + virtual void setCurrentSelection(std::vector& )=0; + + virtual const NLLIGO::IPrimitive* getRootNode(const std::string&)=0; + + virtual std::string& getRootFileName(NLLIGO::IPrimitive*)=0; + + // Register a primitive displayer + virtual void registerPrimitiveDisplayer(IPrimitiveDisplayer *displayer, const std::vector &primClassNames) =0; + + // Get current selection of primitives + virtual const std::list &getCurrentSelection() const = 0; + + // helper to test if a primitive is selected + virtual bool isSelected(const NLLIGO::IPrimitive &prim) const = 0; + + // Refresh the current property dialog. + virtual void refreshPropertyDialog() = 0; + + // Hide / show a primitive + virtual void setPrimitiveHideFlag(NLLIGO::IPrimitive &prim, bool hidden) = 0; + + // Create a texture object + virtual CPrimTexture *createTexture() = 0; + + // Delete a texture object + virtual void deleteTexture(CPrimTexture *tex) = 0; + + /** Tool function : build a NLMISC CBitmap from a tga resource + * \return true if build was successful + */ + virtual bool buildNLBitmapFromTGARsc(HRSRC bm, HMODULE hm, NLMISC::CBitmap &dest) = 0; + +}; +/** Interface for plugin callback. + * This interface must be implemented by the plugin to receive + * notification about the edited document. + * \author Boris Boucher +* \author Nevrax + */ +class IPluginCallback +{ +public: + /// Init the plugin. The plugin receive the world editor interface. + virtual void init(IPluginAccess *pluginAccess) =0; + /// Delete the plugin. + virtual ~IPluginCallback() {} + + /// The current region has changed. +// virtual void primRegionChanged(const std::vector ®ions) = 0; + virtual void primitiveChanged(const NLLIGO::IPrimitive *root) = 0; + /// The region has been modifed. +// virtual void primRegionModifed() = 0; + + + /// The position has been moved on the map. + virtual void positionMoved(const NLMISC::CVector &position) = 0; + /// The plugin lost the control of the position + virtual void lostPositionControl() =0; + + // calling this routine manage the received data + virtual void onIdle()=0; + + // called after post render so that plugin can draw additionnal stuffs + virtual void postRender(CDisplay &display) {} + + //getting the name of the plugin + virtual std::string& getName()=0; + + //testing whether the plugin is active or not (currently in use or not) + virtual bool isActive()=0; + + + virtual bool activatePlugin()=0; + + virtual bool closePlugin()=0; +}; +// Interface for primitive display plusing +class IPrimitiveDisplayer +{ +public: + // a bunch of data to help pluging in drawing task + struct TRenderContext + { + // need to display detail information + bool ShowDetail; + // is the primitive selected ? + bool Selected; + // Some colors as defined by primitive state and configuration files + NLMISC::CRGBA MainColor; + NLMISC::CRGBA ArrowColor; + NLMISC::CRGBA DotColor; + NLMISC::CRGBA LineColor; + // The primitive class information + const NLLIGO::CPrimitiveClass *PrimitiveClass; + // The display + CDisplay *Display; + }; + + virtual void drawPrimitive(const NLLIGO::IPrimitive *primitive, const TRenderContext &renderContext) =0; +}; + #endif // NL_PLUGIN_INTERFACE_H \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_configuration_dlg.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_configuration_dlg.cpp index 9c87e6753..5ef186f7e 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_configuration_dlg.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_configuration_dlg.cpp @@ -1,270 +1,270 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// primitive_configuration_dlg.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "main_frm.h" -#include "action.h" -#include "primitive_configuration_dlg.h" - -using namespace NLLIGO; - -// *************************************************************************** -// CPrimitiveConfigurationDlg dialog -// *************************************************************************** - -uint CPrimitiveConfigurationDlg::LastId; - -// The configuration window -CPrimitiveConfigurationDlg PrimitiveConfigurationDlg; - -CPrimitiveConfigurationDlg::CPrimitiveConfigurationDlg(CWnd* pParent /*=NULL*/) - : CDialog(CPrimitiveConfigurationDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CPrimitiveConfigurationDlg) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT - _WidthMargin = 0; -} - -// *************************************************************************** - -void CPrimitiveConfigurationDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CPrimitiveConfigurationDlg) - DDX_Control(pDX, IDC_LIST, ListCtrl); - //}}AFX_DATA_MAP -} - -// *************************************************************************** - -BEGIN_MESSAGE_MAP(CPrimitiveConfigurationDlg, CDialog) - //{{AFX_MSG_MAP(CPrimitiveConfigurationDlg) - ON_WM_SIZE() - ON_NOTIFY(NM_CLICK, IDC_LIST, OnClickList) - ON_NOTIFY(NM_RCLICK, IDC_LIST, OnRclickList) - ON_NOTIFY(NM_DBLCLK, IDC_LIST, OnClickList) - ON_COMMAND(ID_PRIMITIVECONFIGURATION_HIDE, OnPrimitiveconfigurationHide) - ON_COMMAND(ID_PRIMITIVECONFIGURATION_SELECT, OnPrimitiveconfigurationSelect) - ON_COMMAND(ID_PRIMITIVECONFIGURATION_SHOW, OnPrimitiveconfigurationShow) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// *************************************************************************** -// CPrimitiveConfigurationDlg message handlers -// *************************************************************************** - -void CPrimitiveConfigurationDlg::OnSize(UINT nType, int cx, int cy) -{ - CDialog::OnSize(nType, cx, cy); - - // Resize the list - if (_WidthMargin != 0) - { - ListCtrl.SetWindowPos (NULL, 0, 0, cx - _WidthMargin, cy - _HeightMargin, SWP_NOMOVE|SWP_NOZORDER); - ListCtrl.UpdateData(FALSE); - } -} - -// *************************************************************************** - -BOOL CPrimitiveConfigurationDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // Backup list position for resize - RECT clientRect; - GetClientRect (&clientRect); - RECT listRect; - ListCtrl.GetWindowRect(&listRect); - ScreenToClient(&listRect); - _WidthMargin = clientRect.right - listRect.right + listRect.left; - _HeightMargin = clientRect.bottom - listRect.bottom + listRect.top; - - // Init list - ListView_SetExtendedListViewStyle (ListCtrl, LVS_EX_CHECKBOXES); - - // Add the list column - ListCtrl.InsertColumn (0, "Configuration name"); - ListCtrl.SetColumnWidth (0, 350); - - // Add configurations - const std::vector &configurations = theApp.Config.getPrimitiveConfiguration(); - uint i; - for (i=0; iiItem; - - // Get the click flags - UINT flags; - ListCtrl.HitTest (lpnmlv->ptAction, &flags); - - // Update the group flags - const std::vector &configurations = theApp.Config.getPrimitiveConfiguration(); - - nlassert (configurations.size() == theApp.Configurations.size()); - - // Flags must be over check box icon - if (flags & LVHT_ONITEMSTATEICON) - { - // Item must be a valid item id - if (item < theApp.Configurations.size()) - { - BOOL value = ListView_GetCheckState (ListCtrl, item); - theApp.Configurations[item].Activated = value == FALSE; - invalidateLeftView (); - } - } - - *pResult = 0; - UpdateData(FALSE); - - getMainFrame()->updateData(); -} - -// *************************************************************************** - -void CPrimitiveConfigurationDlg::OnRclickList(NMHDR* pNMHDR, LRESULT* pResult) -{ - LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW) pNMHDR; - - // The item clicked - uint item = lpnmlv->iItem; - - // Get the click flags - UINT flags; - ListCtrl.HitTest (lpnmlv->ptAction, &flags); - - // Flags must be over check box icon - if ((flags & LVHT_ONITEMSTATEICON) == 0) - { - // Item must be a valid item id - if (item < theApp.Configurations.size()) - { - // Save the last item selected - LastId = item; - - CMenu *pMenu = new CMenu; - - pMenu->LoadMenu (IDR_MENU1); - - CMenu *pSubMenu = pMenu->GetSubMenu (0); - CPoint point = lpnmlv->ptAction; - ClientToScreen(&point); - pSubMenu->TrackPopupMenu (TPM_LEFTALIGN | TPM_LEFTBUTTON, point.x, point.y, this); - } - } - - *pResult = 0; -} - -// *************************************************************************** - -void CPrimitiveConfigurationDlg::OnPrimitiveconfigurationHide() -{ - iteratePrimitives (Hide); -} - -// *************************************************************************** - -void CPrimitiveConfigurationDlg::OnPrimitiveconfigurationSelect() -{ - iteratePrimitives (Select); -} - -// *************************************************************************** - -void CPrimitiveConfigurationDlg::OnPrimitiveconfigurationShow() -{ - iteratePrimitives (Show); -} - -// *************************************************************************** - -void CPrimitiveConfigurationDlg::iteratePrimitives(TIterateAction iterateAction) -{ - // Get the configuration to test - nlassert (LastId < theApp.Config.getPrimitiveConfiguration().size()); - const CPrimitiveConfigurations &configuration = theApp.Config.getPrimitiveConfiguration()[LastId]; - - // Modification - CWorldEditorDoc *doc = getDocument (); - doc->beginModification(); - - // For each primitive - CDatabaseLocatorPointer locator; - doc->getFirstLocator (locator); - do - { - // Primitive ? - if (locator.Primitive) - { - // Belong to this configuration ? - if (configuration.belong (*locator.Primitive)) - { - switch (iterateAction) - { - case Show: - case Hide: - doc->addModification(new CActionShowHide (locator, iterateAction==Show)); - break; - case Select: - doc->addModification(new CActionSelect (locator)); - break; - } - } - } - } - while (locator.next ()); - - doc->endModification(); - - // Update - getMainFrame()->updateData(); -} - -// *************************************************************************** - -void CPrimitiveConfigurationDlg::destroy () -{ - if (IsWindow (*this)) - DestroyWindow (); - _WidthMargin = 0; -} - -// *************************************************************************** +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// primitive_configuration_dlg.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "main_frm.h" +#include "action.h" +#include "primitive_configuration_dlg.h" + +using namespace NLLIGO; + +// *************************************************************************** +// CPrimitiveConfigurationDlg dialog +// *************************************************************************** + +uint CPrimitiveConfigurationDlg::LastId; + +// The configuration window +CPrimitiveConfigurationDlg PrimitiveConfigurationDlg; + +CPrimitiveConfigurationDlg::CPrimitiveConfigurationDlg(CWnd* pParent /*=NULL*/) + : CDialog(CPrimitiveConfigurationDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CPrimitiveConfigurationDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + _WidthMargin = 0; +} + +// *************************************************************************** + +void CPrimitiveConfigurationDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CPrimitiveConfigurationDlg) + DDX_Control(pDX, IDC_LIST, ListCtrl); + //}}AFX_DATA_MAP +} + +// *************************************************************************** + +BEGIN_MESSAGE_MAP(CPrimitiveConfigurationDlg, CDialog) + //{{AFX_MSG_MAP(CPrimitiveConfigurationDlg) + ON_WM_SIZE() + ON_NOTIFY(NM_CLICK, IDC_LIST, OnClickList) + ON_NOTIFY(NM_RCLICK, IDC_LIST, OnRclickList) + ON_NOTIFY(NM_DBLCLK, IDC_LIST, OnClickList) + ON_COMMAND(ID_PRIMITIVECONFIGURATION_HIDE, OnPrimitiveconfigurationHide) + ON_COMMAND(ID_PRIMITIVECONFIGURATION_SELECT, OnPrimitiveconfigurationSelect) + ON_COMMAND(ID_PRIMITIVECONFIGURATION_SHOW, OnPrimitiveconfigurationShow) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// *************************************************************************** +// CPrimitiveConfigurationDlg message handlers +// *************************************************************************** + +void CPrimitiveConfigurationDlg::OnSize(UINT nType, int cx, int cy) +{ + CDialog::OnSize(nType, cx, cy); + + // Resize the list + if (_WidthMargin != 0) + { + ListCtrl.SetWindowPos (NULL, 0, 0, cx - _WidthMargin, cy - _HeightMargin, SWP_NOMOVE|SWP_NOZORDER); + ListCtrl.UpdateData(FALSE); + } +} + +// *************************************************************************** + +BOOL CPrimitiveConfigurationDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Backup list position for resize + RECT clientRect; + GetClientRect (&clientRect); + RECT listRect; + ListCtrl.GetWindowRect(&listRect); + ScreenToClient(&listRect); + _WidthMargin = clientRect.right - listRect.right + listRect.left; + _HeightMargin = clientRect.bottom - listRect.bottom + listRect.top; + + // Init list + ListView_SetExtendedListViewStyle (ListCtrl, LVS_EX_CHECKBOXES); + + // Add the list column + ListCtrl.InsertColumn (0, "Configuration name"); + ListCtrl.SetColumnWidth (0, 350); + + // Add configurations + const std::vector &configurations = theApp.Config.getPrimitiveConfiguration(); + uint i; + for (i=0; iiItem; + + // Get the click flags + UINT flags; + ListCtrl.HitTest (lpnmlv->ptAction, &flags); + + // Update the group flags + const std::vector &configurations = theApp.Config.getPrimitiveConfiguration(); + + nlassert (configurations.size() == theApp.Configurations.size()); + + // Flags must be over check box icon + if (flags & LVHT_ONITEMSTATEICON) + { + // Item must be a valid item id + if (item < theApp.Configurations.size()) + { + BOOL value = ListView_GetCheckState (ListCtrl, item); + theApp.Configurations[item].Activated = value == FALSE; + invalidateLeftView (); + } + } + + *pResult = 0; + UpdateData(FALSE); + + getMainFrame()->updateData(); +} + +// *************************************************************************** + +void CPrimitiveConfigurationDlg::OnRclickList(NMHDR* pNMHDR, LRESULT* pResult) +{ + LPNMLISTVIEW lpnmlv = (LPNMLISTVIEW) pNMHDR; + + // The item clicked + uint item = lpnmlv->iItem; + + // Get the click flags + UINT flags; + ListCtrl.HitTest (lpnmlv->ptAction, &flags); + + // Flags must be over check box icon + if ((flags & LVHT_ONITEMSTATEICON) == 0) + { + // Item must be a valid item id + if (item < theApp.Configurations.size()) + { + // Save the last item selected + LastId = item; + + CMenu *pMenu = new CMenu; + + pMenu->LoadMenu (IDR_MENU1); + + CMenu *pSubMenu = pMenu->GetSubMenu (0); + CPoint point = lpnmlv->ptAction; + ClientToScreen(&point); + pSubMenu->TrackPopupMenu (TPM_LEFTALIGN | TPM_LEFTBUTTON, point.x, point.y, this); + } + } + + *pResult = 0; +} + +// *************************************************************************** + +void CPrimitiveConfigurationDlg::OnPrimitiveconfigurationHide() +{ + iteratePrimitives (Hide); +} + +// *************************************************************************** + +void CPrimitiveConfigurationDlg::OnPrimitiveconfigurationSelect() +{ + iteratePrimitives (Select); +} + +// *************************************************************************** + +void CPrimitiveConfigurationDlg::OnPrimitiveconfigurationShow() +{ + iteratePrimitives (Show); +} + +// *************************************************************************** + +void CPrimitiveConfigurationDlg::iteratePrimitives(TIterateAction iterateAction) +{ + // Get the configuration to test + nlassert (LastId < theApp.Config.getPrimitiveConfiguration().size()); + const CPrimitiveConfigurations &configuration = theApp.Config.getPrimitiveConfiguration()[LastId]; + + // Modification + CWorldEditorDoc *doc = getDocument (); + doc->beginModification(); + + // For each primitive + CDatabaseLocatorPointer locator; + doc->getFirstLocator (locator); + do + { + // Primitive ? + if (locator.Primitive) + { + // Belong to this configuration ? + if (configuration.belong (*locator.Primitive)) + { + switch (iterateAction) + { + case Show: + case Hide: + doc->addModification(new CActionShowHide (locator, iterateAction==Show)); + break; + case Select: + doc->addModification(new CActionSelect (locator)); + break; + } + } + } + } + while (locator.next ()); + + doc->endModification(); + + // Update + getMainFrame()->updateData(); +} + +// *************************************************************************** + +void CPrimitiveConfigurationDlg::destroy () +{ + if (IsWindow (*this)) + DestroyWindow (); + _WidthMargin = 0; +} + +// *************************************************************************** diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_configuration_dlg.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_configuration_dlg.h index fae2acb55..aa099ef0f 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_configuration_dlg.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_configuration_dlg.h @@ -1,90 +1,90 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_PRIMITIVE_CONFIGURATION_DLG_H__91B0FD73_97BA_4A00_A664_2F0BE6D52573__INCLUDED_) -#define AFX_PRIMITIVE_CONFIGURATION_DLG_H__91B0FD73_97BA_4A00_A664_2F0BE6D52573__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// primitive_configuration_dlg.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CPrimitiveConfigurationDlg dialog - -class CPrimitiveConfigurationDlg : public CDialog -{ -// Construction -public: - CPrimitiveConfigurationDlg(CWnd* pParent = NULL); // standard constructor - - // Destroy - void destroy (); - -// Dialog Data - //{{AFX_DATA(CPrimitiveConfigurationDlg) - enum { IDD = IDD_PRIMITIVE_CONFIGURATION }; - CListCtrl ListCtrl; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CPrimitiveConfigurationDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - // The id of the last item selected for popup menu callbacks - static uint LastId; - -// Implementation -protected: - - // Backup list position for resize - uint _WidthMargin, _HeightMargin; - - // Iterate all the primitive - enum TIterateAction - { - Show = 0, - Hide, - Select - }; - - // Iterate each primitive and do the action. Update main frame at the end. - void iteratePrimitives(TIterateAction iterateAction); - - // Generated message map functions - //{{AFX_MSG(CPrimitiveConfigurationDlg) - afx_msg void OnSize(UINT nType, int cx, int cy); - virtual BOOL OnInitDialog(); - afx_msg void OnClickList(NMHDR* pNMHDR, LRESULT* pResult); - afx_msg void OnRclickList(NMHDR* pNMHDR, LRESULT* pResult); - afx_msg void OnPrimitiveconfigurationHide(); - afx_msg void OnPrimitiveconfigurationSelect(); - afx_msg void OnPrimitiveconfigurationShow(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -extern CPrimitiveConfigurationDlg PrimitiveConfigurationDlg; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_PRIMITIVE_CONFIGURATION_DLG_H__91B0FD73_97BA_4A00_A664_2F0BE6D52573__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_PRIMITIVE_CONFIGURATION_DLG_H__91B0FD73_97BA_4A00_A664_2F0BE6D52573__INCLUDED_) +#define AFX_PRIMITIVE_CONFIGURATION_DLG_H__91B0FD73_97BA_4A00_A664_2F0BE6D52573__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// primitive_configuration_dlg.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CPrimitiveConfigurationDlg dialog + +class CPrimitiveConfigurationDlg : public CDialog +{ +// Construction +public: + CPrimitiveConfigurationDlg(CWnd* pParent = NULL); // standard constructor + + // Destroy + void destroy (); + +// Dialog Data + //{{AFX_DATA(CPrimitiveConfigurationDlg) + enum { IDD = IDD_PRIMITIVE_CONFIGURATION }; + CListCtrl ListCtrl; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPrimitiveConfigurationDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + // The id of the last item selected for popup menu callbacks + static uint LastId; + +// Implementation +protected: + + // Backup list position for resize + uint _WidthMargin, _HeightMargin; + + // Iterate all the primitive + enum TIterateAction + { + Show = 0, + Hide, + Select + }; + + // Iterate each primitive and do the action. Update main frame at the end. + void iteratePrimitives(TIterateAction iterateAction); + + // Generated message map functions + //{{AFX_MSG(CPrimitiveConfigurationDlg) + afx_msg void OnSize(UINT nType, int cx, int cy); + virtual BOOL OnInitDialog(); + afx_msg void OnClickList(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnRclickList(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnPrimitiveconfigurationHide(); + afx_msg void OnPrimitiveconfigurationSelect(); + afx_msg void OnPrimitiveconfigurationShow(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +extern CPrimitiveConfigurationDlg PrimitiveConfigurationDlg; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PRIMITIVE_CONFIGURATION_DLG_H__91B0FD73_97BA_4A00_A664_2F0BE6D52573__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_view.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_view.cpp index d26c487ce..effbf43fb 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_view.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_view.cpp @@ -1,120 +1,120 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// primitive_view.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "primitive_view.h" - -// *************************************************************************** -// CPrimitiveView - -IMPLEMENT_DYNCREATE(CPrimitiveView, CTreeView) - -// *************************************************************************** - -CPrimitiveView::CPrimitiveView() -{ -} - -// *************************************************************************** - -CPrimitiveView::~CPrimitiveView() -{ -} - -// *************************************************************************** - -BEGIN_MESSAGE_MAP(CPrimitiveView, CTreeView) - //{{AFX_MSG_MAP(CPrimitiveView) - ON_WM_SIZE() - ON_WM_CREATE() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// *************************************************************************** -// CPrimitiveView drawing - -void CPrimitiveView::OnDraw(CDC* pDC) -{ - CDocument* pDoc = GetDocument(); - // TODO: add draw code here -} - -// *************************************************************************** -// CPrimitiveView diagnostics - -#ifdef _DEBUG -void CPrimitiveView::AssertValid() const -{ - CTreeView::AssertValid(); -} - -void CPrimitiveView::Dump(CDumpContext& dc) const -{ - CTreeView::Dump(dc); -} -#endif //_DEBUG - -// *************************************************************************** -// CPrimitiveView message handlers - -void CPrimitiveView::OnSize(UINT nType, int cx, int cy) -{ - CTreeView::OnSize(nType, cx, cy); - - // Resize list ctrl to fill the whole view. - /*CRect iniRect; - GetClientRect(&iniRect);*/ - - CRect iniRect; - iniRect.top = 0; - iniRect.left = 0; - iniRect.bottom = cy; - iniRect.right = cx; - MoveWindow (&iniRect, TRUE); - - // We commented this line because it generates infinite loops on some computers - // http://dev.ryzom.com/issues/show/310 - //GetTreeCtrl().MoveWindow (&iniRect); - - /* iniRect.top = 45; iniRect.left = 10; - iniRect.right -= 10; iniRect.bottom -= 10; */ -} - -// *************************************************************************** - -int CPrimitiveView::OnCreate(LPCREATESTRUCT lpCreateStruct) -{ - if (CTreeView::OnCreate(lpCreateStruct) == -1) - return -1; - - CRect iniRect; - GetClientRect (iniRect); - - ShowWindow (SW_SHOW); - // GetTreeCtrl().Create (TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS|TVS_DISABLEDRAGDROP, iniRect, this, 0); - GetTreeCtrl().ShowWindow (SW_SHOW); - - insertItemUTF8 (GetTreeCtrl(), "Root"); - - return 0; -} - -// *************************************************************************** - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// primitive_view.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "primitive_view.h" + +// *************************************************************************** +// CPrimitiveView + +IMPLEMENT_DYNCREATE(CPrimitiveView, CTreeView) + +// *************************************************************************** + +CPrimitiveView::CPrimitiveView() +{ +} + +// *************************************************************************** + +CPrimitiveView::~CPrimitiveView() +{ +} + +// *************************************************************************** + +BEGIN_MESSAGE_MAP(CPrimitiveView, CTreeView) + //{{AFX_MSG_MAP(CPrimitiveView) + ON_WM_SIZE() + ON_WM_CREATE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// *************************************************************************** +// CPrimitiveView drawing + +void CPrimitiveView::OnDraw(CDC* pDC) +{ + CDocument* pDoc = GetDocument(); + // TODO: add draw code here +} + +// *************************************************************************** +// CPrimitiveView diagnostics + +#ifdef _DEBUG +void CPrimitiveView::AssertValid() const +{ + CTreeView::AssertValid(); +} + +void CPrimitiveView::Dump(CDumpContext& dc) const +{ + CTreeView::Dump(dc); +} +#endif //_DEBUG + +// *************************************************************************** +// CPrimitiveView message handlers + +void CPrimitiveView::OnSize(UINT nType, int cx, int cy) +{ + CTreeView::OnSize(nType, cx, cy); + + // Resize list ctrl to fill the whole view. + /*CRect iniRect; + GetClientRect(&iniRect);*/ + + CRect iniRect; + iniRect.top = 0; + iniRect.left = 0; + iniRect.bottom = cy; + iniRect.right = cx; + MoveWindow (&iniRect, TRUE); + + // We commented this line because it generates infinite loops on some computers + // http://dev.ryzom.com/issues/show/310 + //GetTreeCtrl().MoveWindow (&iniRect); + + /* iniRect.top = 45; iniRect.left = 10; + iniRect.right -= 10; iniRect.bottom -= 10; */ +} + +// *************************************************************************** + +int CPrimitiveView::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CTreeView::OnCreate(lpCreateStruct) == -1) + return -1; + + CRect iniRect; + GetClientRect (iniRect); + + ShowWindow (SW_SHOW); + // GetTreeCtrl().Create (TVS_HASLINES|TVS_LINESATROOT|TVS_HASBUTTONS|TVS_SHOWSELALWAYS|TVS_DISABLEDRAGDROP, iniRect, this, 0); + GetTreeCtrl().ShowWindow (SW_SHOW); + + insertItemUTF8 (GetTreeCtrl(), "Root"); + + return 0; +} + +// *************************************************************************** + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_view.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_view.h index 2c133321a..2916096b2 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_view.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/primitive_view.h @@ -1,71 +1,71 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_PRIMITIVE_VIEW_H__1B70AF9F_9701_4484_88D6_407D2C64AC47__INCLUDED_) -#define AFX_PRIMITIVE_VIEW_H__1B70AF9F_9701_4484_88D6_407D2C64AC47__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// primitive_view.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CPrimitiveView view - -class CPrimitiveView : public CTreeView -{ -protected: - CPrimitiveView (); // protected constructor used by dynamic creation - DECLARE_DYNCREATE(CPrimitiveView) - -// Attributes -public: - -// Operations -public: - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CPrimitiveView) - protected: - virtual void OnDraw(CDC* pDC); // overridden to draw this view - //}}AFX_VIRTUAL - -// Implementation -protected: - - virtual ~CPrimitiveView(); -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - - // Generated message map functions -protected: - //{{AFX_MSG(CPrimitiveView) - afx_msg void OnSize(UINT nType, int cx, int cy); - afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_PRIMITIVE_VIEW_H__1B70AF9F_9701_4484_88D6_407D2C64AC47__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_PRIMITIVE_VIEW_H__1B70AF9F_9701_4484_88D6_407D2C64AC47__INCLUDED_) +#define AFX_PRIMITIVE_VIEW_H__1B70AF9F_9701_4484_88D6_407D2C64AC47__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// primitive_view.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CPrimitiveView view + +class CPrimitiveView : public CTreeView +{ +protected: + CPrimitiveView (); // protected constructor used by dynamic creation + DECLARE_DYNCREATE(CPrimitiveView) + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CPrimitiveView) + protected: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + //}}AFX_VIRTUAL + +// Implementation +protected: + + virtual ~CPrimitiveView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + + // Generated message map functions +protected: + //{{AFX_MSG(CPrimitiveView) + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PRIMITIVE_VIEW_H__1B70AF9F_9701_4484_88D6_407D2C64AC47__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/project_settings.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/project_settings.cpp index de7eaeeec..6bae07195 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/project_settings.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/project_settings.cpp @@ -1,147 +1,147 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// project_settings.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "world_editor_doc.h" -#include "main_frm.h" -#include "project_settings.h" - -using namespace std; - -// *************************************************************************** -// CProjectSettings dialog - - -CProjectSettings::CProjectSettings(CWnd* pParent /*=NULL*/) - : CDialog(CProjectSettings::IDD, pParent) -{ - //{{AFX_DATA_INIT(CProjectSettings) - DataDirectory = getDocument ()->getDataDir ().c_str (); - //}}AFX_DATA_INIT -} - - -void CProjectSettings::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CProjectSettings) - DDX_Control(pDX, IDC_CONTEXT, Context); - DDX_Text(pDX, IDC_DATA_DIRECTORY, DataDirectory); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CProjectSettings, CDialog) - //{{AFX_MSG_MAP(CProjectSettings) - ON_BN_CLICKED(IDC_BROWSE, OnBrowse) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// *************************************************************************** -int CALLBACK dataDirBrowseCallbackProc (HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) -{ - switch (uMsg) - { - case BFFM_INITIALIZED: - SendMessage (hwnd, BFFM_SETSELECTION, TRUE, pData); - break; - default: - break; - } - return 0; -} - -// *************************************************************************** -// CProjectSettings message handlers - -void CProjectSettings::OnBrowse() -{ - UpdateData (); - - BROWSEINFO bi; - char str[MAX_PATH]; - ITEMIDLIST* pidl; - char sTemp[1024]; - - bi.hwndOwner = this->m_hWnd; - bi.pidlRoot = NULL; - bi.pidlRoot = NULL; - bi.pszDisplayName = sTemp; - bi.lpszTitle = "Choose the data directory for this project"; - bi.ulFlags = 0; - bi.lpfn = dataDirBrowseCallbackProc; - - char sDir[512]; - strcpy(sDir, DataDirectory); - bi.lParam = (LPARAM)sDir; - - bi.iImage = 0; - pidl = SHBrowseForFolder (&bi); - if (SHGetPathFromIDList(pidl, str)) - { - DataDirectory = str; - - // Refresh data - UpdateData (FALSE); - } -} - -// *************************************************************************** - -void CProjectSettings::OnOK() -{ - CDialog::OnOK(); - - UpdateData (); - - // Get the document - CWorldEditorDoc *doc = getDocument (); - - CString str; - getWindowTextUTF8 (Context, str); - doc->setContext ((const char*)str); -} - -// *************************************************************************** - -BOOL CProjectSettings::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Init the combo box - const vector &contexts = theApp.Config.getContextString(); - for (uint i=0; igetContext ().c_str ()); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -// *************************************************************************** - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// project_settings.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "world_editor_doc.h" +#include "main_frm.h" +#include "project_settings.h" + +using namespace std; + +// *************************************************************************** +// CProjectSettings dialog + + +CProjectSettings::CProjectSettings(CWnd* pParent /*=NULL*/) + : CDialog(CProjectSettings::IDD, pParent) +{ + //{{AFX_DATA_INIT(CProjectSettings) + DataDirectory = getDocument ()->getDataDir ().c_str (); + //}}AFX_DATA_INIT +} + + +void CProjectSettings::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CProjectSettings) + DDX_Control(pDX, IDC_CONTEXT, Context); + DDX_Text(pDX, IDC_DATA_DIRECTORY, DataDirectory); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CProjectSettings, CDialog) + //{{AFX_MSG_MAP(CProjectSettings) + ON_BN_CLICKED(IDC_BROWSE, OnBrowse) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// *************************************************************************** +int CALLBACK dataDirBrowseCallbackProc (HWND hwnd,UINT uMsg,LPARAM lp, LPARAM pData) +{ + switch (uMsg) + { + case BFFM_INITIALIZED: + SendMessage (hwnd, BFFM_SETSELECTION, TRUE, pData); + break; + default: + break; + } + return 0; +} + +// *************************************************************************** +// CProjectSettings message handlers + +void CProjectSettings::OnBrowse() +{ + UpdateData (); + + BROWSEINFO bi; + char str[MAX_PATH]; + ITEMIDLIST* pidl; + char sTemp[1024]; + + bi.hwndOwner = this->m_hWnd; + bi.pidlRoot = NULL; + bi.pidlRoot = NULL; + bi.pszDisplayName = sTemp; + bi.lpszTitle = "Choose the data directory for this project"; + bi.ulFlags = 0; + bi.lpfn = dataDirBrowseCallbackProc; + + char sDir[512]; + strcpy(sDir, DataDirectory); + bi.lParam = (LPARAM)sDir; + + bi.iImage = 0; + pidl = SHBrowseForFolder (&bi); + if (SHGetPathFromIDList(pidl, str)) + { + DataDirectory = str; + + // Refresh data + UpdateData (FALSE); + } +} + +// *************************************************************************** + +void CProjectSettings::OnOK() +{ + CDialog::OnOK(); + + UpdateData (); + + // Get the document + CWorldEditorDoc *doc = getDocument (); + + CString str; + getWindowTextUTF8 (Context, str); + doc->setContext ((const char*)str); +} + +// *************************************************************************** + +BOOL CProjectSettings::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Init the combo box + const vector &contexts = theApp.Config.getContextString(); + for (uint i=0; igetContext ().c_str ()); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +// *************************************************************************** + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/project_settings.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/project_settings.h index 311dc8471..622287c07 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/project_settings.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/project_settings.h @@ -1,65 +1,65 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_PROJECT_SETTINGS_H__46037C23_5C2F_4724_9DC9_F05D54503B48__INCLUDED_) -#define AFX_PROJECT_SETTINGS_H__46037C23_5C2F_4724_9DC9_F05D54503B48__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// project_settings.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CProjectSettings dialog - -class CProjectSettings : public CDialog -{ -// Construction -public: - CProjectSettings(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CProjectSettings) - enum { IDD = IDD_PROJECT_SETTINGS }; - CComboBox Context; - CString DataDirectory; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CProjectSettings) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CProjectSettings) - afx_msg void OnBrowse(); - virtual void OnOK(); - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_PROJECT_SETTINGS_H__46037C23_5C2F_4724_9DC9_F05D54503B48__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_PROJECT_SETTINGS_H__46037C23_5C2F_4724_9DC9_F05D54503B48__INCLUDED_) +#define AFX_PROJECT_SETTINGS_H__46037C23_5C2F_4724_9DC9_F05D54503B48__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// project_settings.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CProjectSettings dialog + +class CProjectSettings : public CDialog +{ +// Construction +public: + CProjectSettings(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CProjectSettings) + enum { IDD = IDD_PROJECT_SETTINGS }; + CComboBox Context; + CString DataDirectory; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CProjectSettings) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CProjectSettings) + afx_msg void OnBrowse(); + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_PROJECT_SETTINGS_H__46037C23_5C2F_4724_9DC9_F05D54503B48__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/resource.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/resource.h index 48f1bb65b..ce7382e1d 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/resource.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/resource.h @@ -1,349 +1,349 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by world_editor.rc -// -#define IDC_BROWSE 3 -#define ID_OPEN 3 -#define IDMORE 3 -#define IDUPDATE 3 -#define ID_REPLACE 3 -#define ID_NAME_RESET 3 -#define ID_REPLACE_ALL 4 -#define ID_NAME_ASSIGN 4 -#define IDD_ABOUTBOX 100 -#define IDR_MAINFRAME 128 -#define IDR_DIALOG 129 -#define IDR_WORLDETYPE 129 -#define IDD_CREATE_ELEMENT 130 -#define IDR_MAINFREAME 130 -#define IDD_TOOLS_ZONE 131 -#define IDD_SELECTZONE 132 -#define IDD_GENERATE 133 -#define IDD_MOVE 134 -#define IDD_EXPORT 135 -#define IDD_TYPEMANAGER 136 -#define IDD_TYPE 137 -#define IDD_TYPESEL 138 -#define IDR_MAINFRAME_LIGHT 139 -#define IDD_PROJECT_SETTINGS 139 -#define IDD_PROPERTIES 140 -#define IDC_MOVE 141 -#define IDC_ROTATE 142 -#define IDD_EXPORTCB 143 -#define IDC_TURN 143 -#define IDI_FOLDER_CLOSED 143 -#define IDD_TOOLS_LOGIC 144 -#define IDI_PRIM 144 -#define IDC_SCALE 144 -#define IDI_GROUP 145 -#define IDD_EDIT_STRING 145 -#define IDC_RADIUS 145 -#define IDC_ADD_POINT 146 -#define IDI_POINT 146 -#define IDI_POINT_OPENED 146 -#define IDI_POINT_HIDE 147 -#define IDC_SELECT 147 -#define IDI_LINE 148 -#define IDC_SELECT_COPY 148 -#define IDI_LINE_OPENED 148 -#define IDI_LINE_HIDE 149 -#define IDC_INSERT_POINT 149 -#define IDI_ZONE_HIDE 150 -#define IDC_HAND 150 -#define IDI_ZONE 151 -#define IDI_ZONE_OPENED 151 -#define IDD_LOADING 152 -#define IDI_FOLDER_OPENED 152 -#define IDD_CUSTOM_SNAPSHOT 153 -#define IDI_PROPERTY_CLOSED 153 -#define IDI_MAIN_FRAME 154 -#define IDI_MAINFRAME 154 -#define IDI_ROOT_CLOSED 155 -#define IDI_PROPERTY_OPENED 156 -#define IDD_SELECT_PRIMITIVE_BY_LOCATION 156 -#define IDC_COPY 157 -#define IDI_LINE_CLOSED 157 -#define IDD_FIND_PRIMITIVE 157 -#define IDI_POINT_CLOSED 158 -#define IDI_ZONE_CLOSED 159 -#define IDI_ROOT_OPENED 160 -#define IDI_FOLDER_HIDDEN 161 -#define IDI_LINE_HIDDEN 162 -#define IDI_POINT_HIDDEN 163 -#define IDI_PROPERTY_HIDDEN 164 -#define IDI_ROOT_HIDDEN 165 -#define IDI_ZONE_HIDDEN 166 -#define IDI_ERROR_STRUCTURE 167 -#define IDD_PRIMITIVE_CONFIGURATION 169 -#define IDR_MENU1 171 -#define IDC_ZOOM 172 -#define IDD_GOTO_POS 174 -#define IDD_SPLASHSCREEN 175 -#define IDD_DIRECTORY_SELECTOR 176 -#define IDD_NAME 177 -#define IDC_EDIT_NAME 1000 -#define IDC_TITLE_VERSION 1000 -#define IDC_EDIT_LAYERNAME 1001 -#define IDC_PROGRESS1 1001 -#define IDC_CATTYPE1 1002 -#define IDC_COMBO1 1002 -#define IDC_CONTEXT 1002 -#define IDC_DIRLIST 1002 -#define IDC_CATVALUE1 1003 -#define ID_FIND_NEXT 1003 -#define IDC_CATTYPE2 1004 -#define IDC_PRIMITIVE_NAME 1004 -#define IDC_CATVALUE2 1005 -#define IDC_RGBA 1005 -#define IDC_CATTYPE3 1006 -#define IDC_GRAY_SCALE 1006 -#define IDC_CATVALUE3 1007 -#define IDC_FIXED_SIZE 1007 -#define IDC_LIST1 1007 -#define IDC_NAME_SEARCH 1007 -#define IDC_CATTYPE4 1008 -#define IDC_GRAY_SCALE2 1008 -#define IDC_RADIO1 1008 -#define IDC_SELECTION 1008 -#define IDC_CATVALUE4 1009 -#define IDC_AND2 1010 -#define IDC_EDIT2 1010 -#define IDC_NAME_EBOX_GN 1010 -#define IDC_OR2 1011 -#define IDC_CHECK_POS_ZOMM 1011 -#define IDC_AND3 1012 -#define IDC_STATIC_VIDEO_MEM 1012 -#define IDC_OR3 1013 -#define IDC_LOAD_WORLD_EDIT 1013 -#define IDC_AND4 1014 -#define IDC_NAME_ID 1014 -#define IDC_OR4 1015 -#define IDC_RANDOM 1018 -#define IDC_NAME_EBOX_IG 1018 -#define IDC_NOT_PROPAGATE 1019 -#define IDC_ROT0 1020 -#define IDC_NAME_DIR 1020 -#define IDC_ROT90 1021 -#define IDC_NAME_NEWGN 1021 -#define IDC_ROT180 1022 -#define IDC_ROT270 1023 -#define IDC_ROTRANDOM 1024 -#define IDC_ROTCYCLE 1025 -#define IDC_FLIPNO 1026 -#define IDC_FLIPYES 1027 -#define IDC_FLIPRANDOM 1028 -#define IDC_FLIPCYCLE 1029 -#define IDC_LISTZONE 1030 -#define IDC_FULL_CYCLE 1030 -#define IDC_BUTTON1 1031 -#define IDC_BUTTON_REFZONEDIR 1031 -#define IDC_FORCE 1031 -#define IDC_NEW_GROUP 1031 -#define IDC_EDITMINX 1032 -#define IDC_BUTTON_OUTZONEDIR 1032 -#define IDC_EDITMINY 1033 -#define IDC_BUTTON_TILEBANKFILE 1033 -#define IDC_EDITMAXX 1034 -#define IDC_BUTTON_HEIGHTMAPFILE 1034 -#define IDC_EDITMAXY 1035 -#define IDC_BUTTON_HEIGHTMAPFILE2 1035 -#define IDC_COMBOMATERIAL 1036 -#define IDC_BUTTON_REFIGDIR 1036 -#define IDC_EDITZONEBASEX 1037 -#define IDC_BUTTON_OUTIGDIR 1037 -#define IDC_EDITXOFFSET 1038 -#define IDC_BUTTON_REFCMBDIR 1038 -#define IDC_EDITYOFFSET 1039 -#define IDC_BUTTON_OUTCMBDIR 1039 -#define IDC_EDITZONEBASEY 1040 -#define IDC_BUTTON_REFADDITIONNALIGDIR 1040 -#define IDC_EDIT1 1041 -#define IDC_EDIT_REFZONEDIR 1041 -#define IDC_EDIT_INFO 1041 -#define IDC_WIDTH 1041 -#define IDC_DATA_DIRECTORY 1041 -#define IDC_X 1041 -#define IDC_PROPERTY 1041 -#define IDC_GOTO_POS_X 1041 -#define IDC_NAME_FILTER 1041 -#define IDC_EDIT_REFIGDIR 1042 -#define IDC_HEIGHT 1042 -#define IDC_Y 1042 -#define IDC_GOTO_POS_Y 1042 -#define IDC_EDIT_REFCMBDIR 1043 -#define IDC_THRESHOLD 1043 -#define IDC_VALUE 1043 -#define IDC_REPLACE_TEXT 1044 -#define IDC_EDIT_OUTZONEDIR 1044 -#define IDC_REMOVETYPE 1045 -#define IDC_EDIT_TILEBANKFILE 1045 -#define IDC_ADDTYPE 1046 -#define IDC_EDIT_HEIGHTMAPFILE 1046 -#define IDC_EDITTYPE 1047 -#define IDC_EDIT_HEIGHTMAPFILE2 1047 -#define IDC_BUTTONCOLOR 1048 -#define IDC_EDIT_OUTIGDIR 1048 -#define IDC_EDITNAME 1049 -#define IDC_EDIT_OUTCMBDIR 1049 -#define IDC_COMBOTYPE 1050 -#define IDC_EDIT_REFADDITIONNALIGDIR 1050 -#define IDC_LISTTYPE 1051 -#define IDC_EDIT_OUTADDITIONNALIGDIR 1051 -#define IDC_LIST 1052 -#define IDC_BUTTON_OUTADDITIONNALIGDIR 1052 -#define IDC_PROGRESS 1053 -#define IDC_PASSTEXT 1054 -#define IDC_EDIT_ZFACTOR 1055 -#define IDC_EDIT_ZFACTOR2 1056 -#define IDC_EDIT_ZONEMIN 1057 -#define IDC_EDIT_ZONEMAX 1058 -#define IDC_NEW_PATAT 1059 -#define IDC_EDIT_COLORMAPFILE 1059 -#define IDC_TYPE 1060 -#define IDC_BUTTON_COLORMAPFILE 1060 -#define IDC_STATIC_TEXT_LOADING 1061 -#define IDC_EDIT_DFNDIR 1061 -#define IDC_BUTTON_DFNDIR 1062 -#define IDC_EXPORT_COLLISIONS 1063 -#define IDC_EDIT_CONTINENTFILE 1064 -#define IDC_KEEPRATIO 1064 -#define IDC_BUTTON_CONTINENTFILE 1065 -#define IDC_EXPORT_ADDITIONNAL_IGS 1066 -#define IDC_EDIT_CONTINENTSDIR 1067 -#define IDC_BUTTON_CONTINENTSDIR 1068 -#define IDC_RADIOLIGHTNOISE 2042 -#define IDC_RADIOLIGHTPATCH 2043 -#define IDC_RADIOLIGHTNO 2044 -#define IDC_SCROLLBAR_PROP 2045 -#define IDC_PROPERTY_FRAME 2046 -#define IDC_FIRST_PROP 2047 -#define ID_VIEW_GRID 32771 -#define ID_FILE_EXIT 32772 -#define ID_MODE_LOGIC 32773 -#define ID_MODE_ZONE 32774 -#define ID_BUTTON32775 32775 -#define ID_BUTTON32776 32776 -#define ID_FILE_OPENLOGIC 32777 -#define ID_FILE_SAVELOGIC 32778 -#define ID_FILE_OPENLANDSCAPE 32779 -#define ID_FILE_SAVELANDSCAPE 32780 -#define ID_MODE_SELECT 32781 -#define ID_FILE_UNLOAD 32782 -#define ID_FILE_NEWLOGIC 32783 -#define ID_FILE_UNLOADLOGIC 32784 -#define ID_MODE_UNDO 32785 -#define ID_MODE_REDO 32786 -#define ID_FILE_GENERATE 32787 -#define ID_MODE_MOVE 32788 -#define ID_FILE_EXPORT 32789 -#define ID_MODE_TYPE 32790 -#define ID_VIEW_BACKGROUND 32792 -#define ID_BUTTON32795 32795 -#define ID_FILE_VIEW 32797 -#define ID_FILE_SETDATADIR 32798 -#define ID_MODE_TRANSITION 32799 -#define ID_MODE_COUNT_ZONES 32800 -#define ID_FILE_SNAPSHOT 32801 -#define ID_FILE_VIEWWITHIG 32802 -#define ID_FILE_COLORSNAPSHOT 32803 -#define ID_FILE_CUSTOMSNAPSHOT 32804 -#define ID_BUTTON32814 32814 -#define ID_PROJECT_ADDLANDSCAPE 32815 -#define ID_PROJECT_CLEARALLLANDSCAPE 32816 -#define ID_PROJECT_ADDPRIMITIVEFILE 32817 -#define ID_PROJECT_SETTINGS 32818 -#define ID_PROJECT_ADDPRIMITIVE 32821 -#define ID_PROJECT_CLEARALLPRIMITIVE 32822 -#define ID_PROJECT_IMPORT_PRIM 32823 -#define ID_EDIT_LOCK 32825 -#define ID_EDIT_ZONE 32826 -#define ID_EDIT_TRANSITION 32827 -#define ID_EDIT_LOGIC 32828 -#define ID_EDIT_SELECT 32829 -#define ID_EDIT_TRANSLATE 32830 -#define ID_EDIT_ROTATE 32831 -#define ID_EDIT_TURN 32832 -#define ID_EDIT_SCALE 32833 -#define ID_EDIT_RADIUS 32834 -#define ID_EDIT_ADD_POINT 32835 -#define ID_EDIT_DELETE 32836 -#define ID_PROJECT_NEWPRIMITIVE 32837 -#define ID_EDIT_PROPERTIES 32838 -#define ID_EDIT_CREATE_BEGIN 32839 -#define ID_EDIT_CREATE_END 33038 -#define ID_EDIT_DETAILS 33042 -#define ID_VIEW_SHOW 33043 -#define ID_VIEW_HIDE 33044 -#define ID_EDIT_SELECT_CHILDREN 33045 -#define ID_EDIT_EXPAND 33046 -#define ID_EDIT_COLLAPSE 33047 -#define ID_EDIT_GENERATE_BEGIN 33048 -#define ID_EDIT_GENERATE_END 33248 -#define ID_VIEW_LANDSCAPE 33249 -#define ID_EDIT_OPEN_FILE_BEGIN 33250 -#define ID_EDIT_OPEN_FILE_END 33450 -#define ID_VIEW_PRIMITIVES 33452 -#define ID_VIEW_LAYERS 33453 -#define ID_VIEW_GRIS 33454 -#define ID_EDIT_SELECT_BY_LOCATION 33456 -#define ID_BUTTON33457 33457 -#define ID_VIEW_LOCATESELECTEDPRIMITIVES 33458 -#define ID_VIEW_LOCATESELECTEDPRIMITIVES_TREE 33459 -#define ID_PROJECT_RESETUNIQUEID 33460 -#define ID_FIND 33461 -#define ID_VIEW_COLLISIONS 33462 -#define ID_RENAME_SELECTED 33463 -#define ID_REPAIR_SELECTED 33464 -#define ID_HELP_HISTORY 33465 -#define ID_PROJECT_NEWLANDSCAPE 33467 -#define ID_EXPORT_SNAPSHOT 33468 -#define ID_WINDOWS_PRIMITIVECONFIGURATION 33469 -#define ID_PRIMITIVECONFIGURATION_SELECT 33470 -#define ID_PRIMITIVECONFIGURATION_SHOW 33471 -#define ID_PRIMITIVECONFIGURATION_HIDE 33472 -#define ID_EDIT_PACS 33473 -#define ID_VIEW_PACS 33475 -#define ID_VIEW_POINTS 33476 -#define ID_PROJECT_GENERATENULLID 33477 -#define ID_PROJECT_CORRECT_ID 33478 -#define ID_GOTO 33479 -#define ID_PROJECT_RESET_PRIMITIVE_CONFIGURATION 33480 -#define ID_SAVPOS 33482 -#define ID_MISSION_COMPILER 33483 -#define ID_NAME_DLG 33484 -#define ID_INDICATOR_ZONENAMENEL 0xE710 -#define ID_INDICATOR_ZONENAMEREF 0xE711 -#define ID_INDICATOR_COORDINATES 0xE712 -#define ID_INDICATOR_ZONEROT 59155 -#define ID_INDICATOR_ZONEFLIP 59156 -#define ID_INDICATOR_INFO 59157 -#define ID_INDICATOR_SELECTION 59158 -#define ID_WINDOWS_PLUGINS 59170 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_3D_CONTROLS 1 -#define _APS_NEXT_RESOURCE_VALUE 178 -#define _APS_NEXT_COMMAND_VALUE 33485 -#define _APS_NEXT_CONTROL_VALUE 1022 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by world_editor.rc +// +#define IDC_BROWSE 3 +#define ID_OPEN 3 +#define IDMORE 3 +#define IDUPDATE 3 +#define ID_REPLACE 3 +#define ID_NAME_RESET 3 +#define ID_REPLACE_ALL 4 +#define ID_NAME_ASSIGN 4 +#define IDD_ABOUTBOX 100 +#define IDR_MAINFRAME 128 +#define IDR_DIALOG 129 +#define IDR_WORLDETYPE 129 +#define IDD_CREATE_ELEMENT 130 +#define IDR_MAINFREAME 130 +#define IDD_TOOLS_ZONE 131 +#define IDD_SELECTZONE 132 +#define IDD_GENERATE 133 +#define IDD_MOVE 134 +#define IDD_EXPORT 135 +#define IDD_TYPEMANAGER 136 +#define IDD_TYPE 137 +#define IDD_TYPESEL 138 +#define IDR_MAINFRAME_LIGHT 139 +#define IDD_PROJECT_SETTINGS 139 +#define IDD_PROPERTIES 140 +#define IDC_MOVE 141 +#define IDC_ROTATE 142 +#define IDD_EXPORTCB 143 +#define IDC_TURN 143 +#define IDI_FOLDER_CLOSED 143 +#define IDD_TOOLS_LOGIC 144 +#define IDI_PRIM 144 +#define IDC_SCALE 144 +#define IDI_GROUP 145 +#define IDD_EDIT_STRING 145 +#define IDC_RADIUS 145 +#define IDC_ADD_POINT 146 +#define IDI_POINT 146 +#define IDI_POINT_OPENED 146 +#define IDI_POINT_HIDE 147 +#define IDC_SELECT 147 +#define IDI_LINE 148 +#define IDC_SELECT_COPY 148 +#define IDI_LINE_OPENED 148 +#define IDI_LINE_HIDE 149 +#define IDC_INSERT_POINT 149 +#define IDI_ZONE_HIDE 150 +#define IDC_HAND 150 +#define IDI_ZONE 151 +#define IDI_ZONE_OPENED 151 +#define IDD_LOADING 152 +#define IDI_FOLDER_OPENED 152 +#define IDD_CUSTOM_SNAPSHOT 153 +#define IDI_PROPERTY_CLOSED 153 +#define IDI_MAIN_FRAME 154 +#define IDI_MAINFRAME 154 +#define IDI_ROOT_CLOSED 155 +#define IDI_PROPERTY_OPENED 156 +#define IDD_SELECT_PRIMITIVE_BY_LOCATION 156 +#define IDC_COPY 157 +#define IDI_LINE_CLOSED 157 +#define IDD_FIND_PRIMITIVE 157 +#define IDI_POINT_CLOSED 158 +#define IDI_ZONE_CLOSED 159 +#define IDI_ROOT_OPENED 160 +#define IDI_FOLDER_HIDDEN 161 +#define IDI_LINE_HIDDEN 162 +#define IDI_POINT_HIDDEN 163 +#define IDI_PROPERTY_HIDDEN 164 +#define IDI_ROOT_HIDDEN 165 +#define IDI_ZONE_HIDDEN 166 +#define IDI_ERROR_STRUCTURE 167 +#define IDD_PRIMITIVE_CONFIGURATION 169 +#define IDR_MENU1 171 +#define IDC_ZOOM 172 +#define IDD_GOTO_POS 174 +#define IDD_SPLASHSCREEN 175 +#define IDD_DIRECTORY_SELECTOR 176 +#define IDD_NAME 177 +#define IDC_EDIT_NAME 1000 +#define IDC_TITLE_VERSION 1000 +#define IDC_EDIT_LAYERNAME 1001 +#define IDC_PROGRESS1 1001 +#define IDC_CATTYPE1 1002 +#define IDC_COMBO1 1002 +#define IDC_CONTEXT 1002 +#define IDC_DIRLIST 1002 +#define IDC_CATVALUE1 1003 +#define ID_FIND_NEXT 1003 +#define IDC_CATTYPE2 1004 +#define IDC_PRIMITIVE_NAME 1004 +#define IDC_CATVALUE2 1005 +#define IDC_RGBA 1005 +#define IDC_CATTYPE3 1006 +#define IDC_GRAY_SCALE 1006 +#define IDC_CATVALUE3 1007 +#define IDC_FIXED_SIZE 1007 +#define IDC_LIST1 1007 +#define IDC_NAME_SEARCH 1007 +#define IDC_CATTYPE4 1008 +#define IDC_GRAY_SCALE2 1008 +#define IDC_RADIO1 1008 +#define IDC_SELECTION 1008 +#define IDC_CATVALUE4 1009 +#define IDC_AND2 1010 +#define IDC_EDIT2 1010 +#define IDC_NAME_EBOX_GN 1010 +#define IDC_OR2 1011 +#define IDC_CHECK_POS_ZOMM 1011 +#define IDC_AND3 1012 +#define IDC_STATIC_VIDEO_MEM 1012 +#define IDC_OR3 1013 +#define IDC_LOAD_WORLD_EDIT 1013 +#define IDC_AND4 1014 +#define IDC_NAME_ID 1014 +#define IDC_OR4 1015 +#define IDC_RANDOM 1018 +#define IDC_NAME_EBOX_IG 1018 +#define IDC_NOT_PROPAGATE 1019 +#define IDC_ROT0 1020 +#define IDC_NAME_DIR 1020 +#define IDC_ROT90 1021 +#define IDC_NAME_NEWGN 1021 +#define IDC_ROT180 1022 +#define IDC_ROT270 1023 +#define IDC_ROTRANDOM 1024 +#define IDC_ROTCYCLE 1025 +#define IDC_FLIPNO 1026 +#define IDC_FLIPYES 1027 +#define IDC_FLIPRANDOM 1028 +#define IDC_FLIPCYCLE 1029 +#define IDC_LISTZONE 1030 +#define IDC_FULL_CYCLE 1030 +#define IDC_BUTTON1 1031 +#define IDC_BUTTON_REFZONEDIR 1031 +#define IDC_FORCE 1031 +#define IDC_NEW_GROUP 1031 +#define IDC_EDITMINX 1032 +#define IDC_BUTTON_OUTZONEDIR 1032 +#define IDC_EDITMINY 1033 +#define IDC_BUTTON_TILEBANKFILE 1033 +#define IDC_EDITMAXX 1034 +#define IDC_BUTTON_HEIGHTMAPFILE 1034 +#define IDC_EDITMAXY 1035 +#define IDC_BUTTON_HEIGHTMAPFILE2 1035 +#define IDC_COMBOMATERIAL 1036 +#define IDC_BUTTON_REFIGDIR 1036 +#define IDC_EDITZONEBASEX 1037 +#define IDC_BUTTON_OUTIGDIR 1037 +#define IDC_EDITXOFFSET 1038 +#define IDC_BUTTON_REFCMBDIR 1038 +#define IDC_EDITYOFFSET 1039 +#define IDC_BUTTON_OUTCMBDIR 1039 +#define IDC_EDITZONEBASEY 1040 +#define IDC_BUTTON_REFADDITIONNALIGDIR 1040 +#define IDC_EDIT1 1041 +#define IDC_EDIT_REFZONEDIR 1041 +#define IDC_EDIT_INFO 1041 +#define IDC_WIDTH 1041 +#define IDC_DATA_DIRECTORY 1041 +#define IDC_X 1041 +#define IDC_PROPERTY 1041 +#define IDC_GOTO_POS_X 1041 +#define IDC_NAME_FILTER 1041 +#define IDC_EDIT_REFIGDIR 1042 +#define IDC_HEIGHT 1042 +#define IDC_Y 1042 +#define IDC_GOTO_POS_Y 1042 +#define IDC_EDIT_REFCMBDIR 1043 +#define IDC_THRESHOLD 1043 +#define IDC_VALUE 1043 +#define IDC_REPLACE_TEXT 1044 +#define IDC_EDIT_OUTZONEDIR 1044 +#define IDC_REMOVETYPE 1045 +#define IDC_EDIT_TILEBANKFILE 1045 +#define IDC_ADDTYPE 1046 +#define IDC_EDIT_HEIGHTMAPFILE 1046 +#define IDC_EDITTYPE 1047 +#define IDC_EDIT_HEIGHTMAPFILE2 1047 +#define IDC_BUTTONCOLOR 1048 +#define IDC_EDIT_OUTIGDIR 1048 +#define IDC_EDITNAME 1049 +#define IDC_EDIT_OUTCMBDIR 1049 +#define IDC_COMBOTYPE 1050 +#define IDC_EDIT_REFADDITIONNALIGDIR 1050 +#define IDC_LISTTYPE 1051 +#define IDC_EDIT_OUTADDITIONNALIGDIR 1051 +#define IDC_LIST 1052 +#define IDC_BUTTON_OUTADDITIONNALIGDIR 1052 +#define IDC_PROGRESS 1053 +#define IDC_PASSTEXT 1054 +#define IDC_EDIT_ZFACTOR 1055 +#define IDC_EDIT_ZFACTOR2 1056 +#define IDC_EDIT_ZONEMIN 1057 +#define IDC_EDIT_ZONEMAX 1058 +#define IDC_NEW_PATAT 1059 +#define IDC_EDIT_COLORMAPFILE 1059 +#define IDC_TYPE 1060 +#define IDC_BUTTON_COLORMAPFILE 1060 +#define IDC_STATIC_TEXT_LOADING 1061 +#define IDC_EDIT_DFNDIR 1061 +#define IDC_BUTTON_DFNDIR 1062 +#define IDC_EXPORT_COLLISIONS 1063 +#define IDC_EDIT_CONTINENTFILE 1064 +#define IDC_KEEPRATIO 1064 +#define IDC_BUTTON_CONTINENTFILE 1065 +#define IDC_EXPORT_ADDITIONNAL_IGS 1066 +#define IDC_EDIT_CONTINENTSDIR 1067 +#define IDC_BUTTON_CONTINENTSDIR 1068 +#define IDC_RADIOLIGHTNOISE 2042 +#define IDC_RADIOLIGHTPATCH 2043 +#define IDC_RADIOLIGHTNO 2044 +#define IDC_SCROLLBAR_PROP 2045 +#define IDC_PROPERTY_FRAME 2046 +#define IDC_FIRST_PROP 2047 +#define ID_VIEW_GRID 32771 +#define ID_FILE_EXIT 32772 +#define ID_MODE_LOGIC 32773 +#define ID_MODE_ZONE 32774 +#define ID_BUTTON32775 32775 +#define ID_BUTTON32776 32776 +#define ID_FILE_OPENLOGIC 32777 +#define ID_FILE_SAVELOGIC 32778 +#define ID_FILE_OPENLANDSCAPE 32779 +#define ID_FILE_SAVELANDSCAPE 32780 +#define ID_MODE_SELECT 32781 +#define ID_FILE_UNLOAD 32782 +#define ID_FILE_NEWLOGIC 32783 +#define ID_FILE_UNLOADLOGIC 32784 +#define ID_MODE_UNDO 32785 +#define ID_MODE_REDO 32786 +#define ID_FILE_GENERATE 32787 +#define ID_MODE_MOVE 32788 +#define ID_FILE_EXPORT 32789 +#define ID_MODE_TYPE 32790 +#define ID_VIEW_BACKGROUND 32792 +#define ID_BUTTON32795 32795 +#define ID_FILE_VIEW 32797 +#define ID_FILE_SETDATADIR 32798 +#define ID_MODE_TRANSITION 32799 +#define ID_MODE_COUNT_ZONES 32800 +#define ID_FILE_SNAPSHOT 32801 +#define ID_FILE_VIEWWITHIG 32802 +#define ID_FILE_COLORSNAPSHOT 32803 +#define ID_FILE_CUSTOMSNAPSHOT 32804 +#define ID_BUTTON32814 32814 +#define ID_PROJECT_ADDLANDSCAPE 32815 +#define ID_PROJECT_CLEARALLLANDSCAPE 32816 +#define ID_PROJECT_ADDPRIMITIVEFILE 32817 +#define ID_PROJECT_SETTINGS 32818 +#define ID_PROJECT_ADDPRIMITIVE 32821 +#define ID_PROJECT_CLEARALLPRIMITIVE 32822 +#define ID_PROJECT_IMPORT_PRIM 32823 +#define ID_EDIT_LOCK 32825 +#define ID_EDIT_ZONE 32826 +#define ID_EDIT_TRANSITION 32827 +#define ID_EDIT_LOGIC 32828 +#define ID_EDIT_SELECT 32829 +#define ID_EDIT_TRANSLATE 32830 +#define ID_EDIT_ROTATE 32831 +#define ID_EDIT_TURN 32832 +#define ID_EDIT_SCALE 32833 +#define ID_EDIT_RADIUS 32834 +#define ID_EDIT_ADD_POINT 32835 +#define ID_EDIT_DELETE 32836 +#define ID_PROJECT_NEWPRIMITIVE 32837 +#define ID_EDIT_PROPERTIES 32838 +#define ID_EDIT_CREATE_BEGIN 32839 +#define ID_EDIT_CREATE_END 33038 +#define ID_EDIT_DETAILS 33042 +#define ID_VIEW_SHOW 33043 +#define ID_VIEW_HIDE 33044 +#define ID_EDIT_SELECT_CHILDREN 33045 +#define ID_EDIT_EXPAND 33046 +#define ID_EDIT_COLLAPSE 33047 +#define ID_EDIT_GENERATE_BEGIN 33048 +#define ID_EDIT_GENERATE_END 33248 +#define ID_VIEW_LANDSCAPE 33249 +#define ID_EDIT_OPEN_FILE_BEGIN 33250 +#define ID_EDIT_OPEN_FILE_END 33450 +#define ID_VIEW_PRIMITIVES 33452 +#define ID_VIEW_LAYERS 33453 +#define ID_VIEW_GRIS 33454 +#define ID_EDIT_SELECT_BY_LOCATION 33456 +#define ID_BUTTON33457 33457 +#define ID_VIEW_LOCATESELECTEDPRIMITIVES 33458 +#define ID_VIEW_LOCATESELECTEDPRIMITIVES_TREE 33459 +#define ID_PROJECT_RESETUNIQUEID 33460 +#define ID_FIND 33461 +#define ID_VIEW_COLLISIONS 33462 +#define ID_RENAME_SELECTED 33463 +#define ID_REPAIR_SELECTED 33464 +#define ID_HELP_HISTORY 33465 +#define ID_PROJECT_NEWLANDSCAPE 33467 +#define ID_EXPORT_SNAPSHOT 33468 +#define ID_WINDOWS_PRIMITIVECONFIGURATION 33469 +#define ID_PRIMITIVECONFIGURATION_SELECT 33470 +#define ID_PRIMITIVECONFIGURATION_SHOW 33471 +#define ID_PRIMITIVECONFIGURATION_HIDE 33472 +#define ID_EDIT_PACS 33473 +#define ID_VIEW_PACS 33475 +#define ID_VIEW_POINTS 33476 +#define ID_PROJECT_GENERATENULLID 33477 +#define ID_PROJECT_CORRECT_ID 33478 +#define ID_GOTO 33479 +#define ID_PROJECT_RESET_PRIMITIVE_CONFIGURATION 33480 +#define ID_SAVPOS 33482 +#define ID_MISSION_COMPILER 33483 +#define ID_NAME_DLG 33484 +#define ID_INDICATOR_ZONENAMENEL 0xE710 +#define ID_INDICATOR_ZONENAMEREF 0xE711 +#define ID_INDICATOR_COORDINATES 0xE712 +#define ID_INDICATOR_ZONEROT 59155 +#define ID_INDICATOR_ZONEFLIP 59156 +#define ID_INDICATOR_INFO 59157 +#define ID_INDICATOR_SELECTION 59158 +#define ID_WINDOWS_PLUGINS 59170 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_3D_CONTROLS 1 +#define _APS_NEXT_RESOURCE_VALUE 178 +#define _APS_NEXT_COMMAND_VALUE 33485 +#define _APS_NEXT_CONTROL_VALUE 1022 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/select_by_location.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/select_by_location.cpp index aaa8c9c47..252dbc94a 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/select_by_location.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/select_by_location.cpp @@ -1,80 +1,80 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// select_by_location.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "select_by_location.h" - -///////////////////////////////////////////////////////////////////////////// -// CSelectByLocation dialog - - -CSelectByLocation::CSelectByLocation(CWnd* pParent /*=NULL*/) - : CDialog(CSelectByLocation::IDD, pParent) -{ - //{{AFX_DATA_INIT(CSelectByLocation) - X = 0.0f; - Y = 0.0f; - Threshold = 10.0f; - //}}AFX_DATA_INIT -} - - -void CSelectByLocation::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CSelectByLocation) - DDX_Text(pDX, IDC_X, X); - DDX_Text(pDX, IDC_Y, Y); - DDX_Text(pDX, IDC_THRESHOLD, Threshold); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CSelectByLocation, CDialog) - //{{AFX_MSG_MAP(CSelectByLocation) - ON_BN_CLICKED(IDMORE, OnMore) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CSelectByLocation message handlers - -void CSelectByLocation::OnOK() -{ - SelectMore = false; - - CDialog::OnOK(); -} - -void CSelectByLocation::OnMore() -{ - SelectMore = true; - - CDialog::OnOK(); -} - -BOOL CSelectByLocation::OnInitDialog() -{ - CDialog::OnInitDialog(); - - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// select_by_location.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "select_by_location.h" + +///////////////////////////////////////////////////////////////////////////// +// CSelectByLocation dialog + + +CSelectByLocation::CSelectByLocation(CWnd* pParent /*=NULL*/) + : CDialog(CSelectByLocation::IDD, pParent) +{ + //{{AFX_DATA_INIT(CSelectByLocation) + X = 0.0f; + Y = 0.0f; + Threshold = 10.0f; + //}}AFX_DATA_INIT +} + + +void CSelectByLocation::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSelectByLocation) + DDX_Text(pDX, IDC_X, X); + DDX_Text(pDX, IDC_Y, Y); + DDX_Text(pDX, IDC_THRESHOLD, Threshold); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CSelectByLocation, CDialog) + //{{AFX_MSG_MAP(CSelectByLocation) + ON_BN_CLICKED(IDMORE, OnMore) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSelectByLocation message handlers + +void CSelectByLocation::OnOK() +{ + SelectMore = false; + + CDialog::OnOK(); +} + +void CSelectByLocation::OnMore() +{ + SelectMore = true; + + CDialog::OnOK(); +} + +BOOL CSelectByLocation::OnInitDialog() +{ + CDialog::OnInitDialog(); + + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/select_by_location.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/select_by_location.h index c09aa9d8f..155d68f88 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/select_by_location.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/select_by_location.h @@ -1,68 +1,68 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_SELECT_BY_LOCATION_H__2DC6A9DF_4564_4572_B570_63A4CC9EFD51__INCLUDED_) -#define AFX_SELECT_BY_LOCATION_H__2DC6A9DF_4564_4572_B570_63A4CC9EFD51__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// select_by_location.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CSelectByLocation dialog - -class CSelectByLocation : public CDialog -{ -// Construction -public: - CSelectByLocation(CWnd* pParent = NULL); // standard constructor - - bool SelectMore; - -// Dialog Data - //{{AFX_DATA(CSelectByLocation) - enum { IDD = IDD_SELECT_PRIMITIVE_BY_LOCATION }; - float X; - float Y; - float Threshold; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CSelectByLocation) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CSelectByLocation) - virtual void OnOK(); - afx_msg void OnMore(); - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_SELECT_BY_LOCATION_H__2DC6A9DF_4564_4572_B570_63A4CC9EFD51__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_SELECT_BY_LOCATION_H__2DC6A9DF_4564_4572_B570_63A4CC9EFD51__INCLUDED_) +#define AFX_SELECT_BY_LOCATION_H__2DC6A9DF_4564_4572_B570_63A4CC9EFD51__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// select_by_location.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CSelectByLocation dialog + +class CSelectByLocation : public CDialog +{ +// Construction +public: + CSelectByLocation(CWnd* pParent = NULL); // standard constructor + + bool SelectMore; + +// Dialog Data + //{{AFX_DATA(CSelectByLocation) + enum { IDD = IDD_SELECT_PRIMITIVE_BY_LOCATION }; + float X; + float Y; + float Threshold; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSelectByLocation) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CSelectByLocation) + virtual void OnOK(); + afx_msg void OnMore(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SELECT_BY_LOCATION_H__2DC6A9DF_4564_4572_B570_63A4CC9EFD51__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/splash_screen.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/splash_screen.cpp index ac303bcab..2ba2e1de4 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/splash_screen.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/splash_screen.cpp @@ -1,79 +1,79 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// splash_screen.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "splash_screen.h" -#include - -using namespace std; - -///////////////////////////////////////////////////////////////////////////// -// CSplashScreen dialog - - -CSplashScreen::CSplashScreen(CWnd* pParent /*=NULL*/) - : CDialog(CSplashScreen::IDD, pParent) -{ - //{{AFX_DATA_INIT(CSplashScreen) - m_load_list = _T(""); - //}}AFX_DATA_INIT -} - - -void CSplashScreen::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CSplashScreen) - DDX_Text(pDX, IDC_LOAD_WORLD_EDIT, m_load_list); - //}}AFX_DATA_MAP -} - -void CSplashScreen::addLine(std::string newLine) -{ - m_load_list=m_load_list+"\n"+newLine.c_str(); - UpdateData(false); - ShowWindow(true); - RedrawWindow(); -} -void CSplashScreen::close() -{ - OnClose(); -} - - -void CSplashScreen::progress (float progressValue) -{ - MSG msg; - while ( PeekMessage(&msg,NULL,0,0,PM_REMOVE) ) - { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - -} - -BEGIN_MESSAGE_MAP(CSplashScreen, CDialog) - //{{AFX_MSG_MAP(CSplashScreen) - // NOTE: the ClassWizard will add message map macros here - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CSplashScreen message handlers +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// splash_screen.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "splash_screen.h" +#include + +using namespace std; + +///////////////////////////////////////////////////////////////////////////// +// CSplashScreen dialog + + +CSplashScreen::CSplashScreen(CWnd* pParent /*=NULL*/) + : CDialog(CSplashScreen::IDD, pParent) +{ + //{{AFX_DATA_INIT(CSplashScreen) + m_load_list = _T(""); + //}}AFX_DATA_INIT +} + + +void CSplashScreen::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CSplashScreen) + DDX_Text(pDX, IDC_LOAD_WORLD_EDIT, m_load_list); + //}}AFX_DATA_MAP +} + +void CSplashScreen::addLine(std::string newLine) +{ + m_load_list=m_load_list+"\n"+newLine.c_str(); + UpdateData(false); + ShowWindow(true); + RedrawWindow(); +} +void CSplashScreen::close() +{ + OnClose(); +} + + +void CSplashScreen::progress (float progressValue) +{ + MSG msg; + while ( PeekMessage(&msg,NULL,0,0,PM_REMOVE) ) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + +} + +BEGIN_MESSAGE_MAP(CSplashScreen, CDialog) + //{{AFX_MSG_MAP(CSplashScreen) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CSplashScreen message handlers diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/splash_screen.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/splash_screen.h index dca7da37f..a2222a36a 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/splash_screen.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/splash_screen.h @@ -1,65 +1,65 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_SPLASHSCREEN_H__9CC775DA_1173_415D_AC2C_D3CDF05265F6__INCLUDED_) -#define AFX_SPLASHSCREEN_H__9CC775DA_1173_415D_AC2C_D3CDF05265F6__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// splash_screen.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CSplashScreen dialog - -class CSplashScreen : public CDialog, public NLMISC::IProgressCallback -{ -// Construction -public: - CSplashScreen(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CSplashScreen) - enum { IDD = IDD_SPLASHSCREEN }; - CString m_load_list; - //}}AFX_DATA - - virtual void progress (float progressValue); - void addLine(std::string newLine); - void close(); -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CSplashScreen) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CSplashScreen) - // NOTE: the ClassWizard will add member functions here - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_SPLASHSCREEN_H__9CC775DA_1173_415D_AC2C_D3CDF05265F6__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_SPLASHSCREEN_H__9CC775DA_1173_415D_AC2C_D3CDF05265F6__INCLUDED_) +#define AFX_SPLASHSCREEN_H__9CC775DA_1173_415D_AC2C_D3CDF05265F6__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// splash_screen.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CSplashScreen dialog + +class CSplashScreen : public CDialog, public NLMISC::IProgressCallback +{ +// Construction +public: + CSplashScreen(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CSplashScreen) + enum { IDD = IDD_SPLASHSCREEN }; + CString m_load_list; + //}}AFX_DATA + + virtual void progress (float progressValue); + void addLine(std::string newLine); + void close(); +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CSplashScreen) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CSplashScreen) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_SPLASHSCREEN_H__9CC775DA_1173_415D_AC2C_D3CDF05265F6__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/stdafx.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/stdafx.cpp index 6b07b60bf..d3038efac 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/stdafx.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/stdafx.cpp @@ -1,21 +1,21 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.cpp : source file that includes just the standard includes -// world_editor.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.cpp : source file that includes just the standard includes +// world_editor.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/stdafx.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/stdafx.h index e8b4bda98..d57756cb8 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/stdafx.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/stdafx.h @@ -1,117 +1,117 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__E96DCAA4_6BCD_45D1_8188_DEB4E925DDDA__INCLUDED_) -#define AFX_STDAFX_H__E96DCAA4_6BCD_45D1_8188_DEB4E925DDDA__INCLUDED_ - -#pragma once - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#define NOMINMAX -#define _WIN32_WINNT 0x0500 - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC Automation classes - -#ifndef _AFX_NO_DB_SUPPORT -#include // MFC ODBC database classes -#endif // _AFX_NO_DB_SUPPORT - -#ifndef _AFX_NO_DAO_SUPPORT -#include // MFC DAO database classes -#endif // _AFX_NO_DAO_SUPPORT - -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -// Windows -#include - -// MFC -#include -#include - -// STL -#include -#include -#include -#include -#include - -// NLMISC -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// NL3D -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// NLGEORGES -#include -#include -#include - -// NLLIGO -#include -#include - -// NLPACS -#include -#include - -#include -#include - -extern bool DontUse3D; - - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__E96DCAA4_6BCD_45D1_8188_DEB4E925DDDA__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__E96DCAA4_6BCD_45D1_8188_DEB4E925DDDA__INCLUDED_) +#define AFX_STDAFX_H__E96DCAA4_6BCD_45D1_8188_DEB4E925DDDA__INCLUDED_ + +#pragma once + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#define NOMINMAX +#define _WIN32_WINNT 0x0500 + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes + +#ifndef _AFX_NO_DB_SUPPORT +#include // MFC ODBC database classes +#endif // _AFX_NO_DB_SUPPORT + +#ifndef _AFX_NO_DAO_SUPPORT +#include // MFC DAO database classes +#endif // _AFX_NO_DAO_SUPPORT + +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +// Windows +#include + +// MFC +#include +#include + +// STL +#include +#include +#include +#include +#include + +// NLMISC +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// NL3D +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// NLGEORGES +#include +#include +#include + +// NLLIGO +#include +#include + +// NLPACS +#include +#include + +#include +#include + +extern bool DontUse3D; + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__E96DCAA4_6BCD_45D1_8188_DEB4E925DDDA__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_logic.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_logic.cpp index 5f7a7296b..16fe17089 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_logic.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_logic.cpp @@ -1,2196 +1,2196 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" - -#include "tools_logic.h" -#include "world_editor.h" -#include "world_editor_doc.h" -#include "type_sel_dlg.h" -#include "main_frm.h" -#include "display.h" -#include "action.h" -#include "editor_primitive.h" -#include "dialog_properties.h" - -#include - -using namespace std; -using namespace NLLIGO; -using namespace NLMISC; - -// *************************************************************************** - -#define ID_MENU_REGION_CREATE_GROUP 0x10018 -#define ID_MENU_REGION_PROPERTIES 0x10019 -#define ID_MENU_REGION_HIDE_ALL 0x10020 -#define ID_MENU_REGION_UNHIDE_ALL 0x10021 -#define ID_MENU_REGION_HIDE_TYPE 0x10022 -#define ID_MENU_REGION_UNHIDE_TYPE 0x10023 - -#define ID_MENU_GROUP_CREATE_POINT 0x10024 -#define ID_MENU_GROUP_CREATE_PATH 0x10025 -#define ID_MENU_GROUP_CREATE_ZONE 0x10026 -#define ID_MENU_GROUP_DELETE 0x10027 -#define ID_MENU_GROUP_PROPERTIES 0x10028 -#define ID_MENU_GROUP_HIDE 0x10029 -#define ID_MENU_GROUP_UNHIDE 0x1002A -#define ID_MENU_GROUP_TRANSFERT_REPLACE 0x1002B -#define ID_MENU_GROUP_TRANSFERT_APPEND 0x1002C - -#define ID_MENU_PRIM_DELETE 0x10010 -#define ID_MENU_PRIM_PROPERTIES 0x10011 -#define ID_MENU_PRIM_HIDE 0x10012 - -// *************************************************************************** - -BEGIN_MESSAGE_MAP(CToolsLogicTree, CTreeCtrl) - ON_WM_LBUTTONDOWN () - ON_WM_LBUTTONUP () - ON_WM_LBUTTONDBLCLK () - ON_WM_RBUTTONDOWN () -/* - ON_COMMAND (ID_MENU_REGION_CREATE_GROUP,OnMenuRegionCreateGroup) - ON_COMMAND (ID_MENU_REGION_PROPERTIES, OnMenuRegionProperties) - ON_COMMAND (ID_MENU_REGION_HIDE_ALL, OnMenuRegionHideAll) - ON_COMMAND (ID_MENU_REGION_UNHIDE_ALL, OnMenuRegionUnhideAll) - ON_COMMAND (ID_MENU_REGION_HIDE_TYPE, OnMenuRegionHideType) - ON_COMMAND (ID_MENU_REGION_UNHIDE_TYPE, OnMenuRegionUnhideType) - - ON_COMMAND (ID_MENU_GROUP_CREATE_POINT, OnMenuGroupCreatePoint) - ON_COMMAND (ID_MENU_GROUP_CREATE_PATH, OnMenuGroupCreatePath) - ON_COMMAND (ID_MENU_GROUP_CREATE_ZONE, OnMenuGroupCreateZone) - ON_COMMAND (ID_MENU_GROUP_DELETE, OnMenuGroupDelete) - ON_COMMAND (ID_MENU_GROUP_PROPERTIES, OnMenuGroupProperties) - ON_COMMAND (ID_MENU_GROUP_HIDE, OnMenuGroupHide) - ON_COMMAND (ID_MENU_GROUP_UNHIDE, OnMenuGroupUnhide) - ON_COMMAND (ID_MENU_GROUP_TRANSFERT_APPEND, OnMenuGroupTransfertAppend) - ON_COMMAND (ID_MENU_GROUP_TRANSFERT_REPLACE, OnMenuGroupTransfertReplace) - - ON_COMMAND (ID_MENU_PRIM_DELETE, OnMenuPrimDelete) - ON_COMMAND (ID_MENU_PRIM_PROPERTIES, OnMenuPrimProperties) - ON_COMMAND (ID_MENU_PRIM_HIDE, OnMenuPrimHide) -*/ - ON_COMMAND (ID_EDIT_DELETE, OnMenuPrimDelete) - ON_COMMAND (ID_EDIT_PROPERTIES, OnMenuPrimProperties) - ON_COMMAND (ID_PROJECT_NEWPRIMITIVE, OnProjectNewPrimitive) - ON_COMMAND (ID_VIEW_SHOW, OnViewShow) - ON_COMMAND (ID_VIEW_HIDE, OnViewHide) - ON_COMMAND (ID_EDIT_SELECT_CHILDREN, OnEditSelectChildren) - ON_COMMAND_RANGE (ID_EDIT_CREATE_BEGIN, ID_EDIT_CREATE_END, OnAddPrimitive) - ON_COMMAND_RANGE (ID_EDIT_GENERATE_BEGIN, ID_EDIT_GENERATE_END, OnGeneratePrimitive) - ON_COMMAND_RANGE (ID_EDIT_OPEN_FILE_BEGIN, ID_EDIT_OPEN_FILE_END, OnOpenFile) - ON_COMMAND(ID_EDIT_EXPAND, OnEditExpand) - ON_COMMAND(ID_EDIT_COLLAPSE, OnEditCollapse) - ON_COMMAND(ID_RENAME_SELECTED, OnRenameSelected) - ON_COMMAND(ID_REPAIR_SELECTED, OnRepairSelected) - ON_COMMAND(ID_HELP_FINDER, OnTreeHelp) - - ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag) - ON_WM_MOUSEMOVE () - - //ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelChanged) -END_MESSAGE_MAP() - -// *************************************************************************** - -class CPrimitiveTreeData -{ -public: - CPrimitiveTreeData (const NLLIGO::CPrimitives *primitives, const IPrimitive *primitive) - { - Primitive = primitive; - Primitives = primitives; - } - - // The primitive - const NLLIGO::CPrimitives *Primitives; - const IPrimitive *Primitive; -}; - -// *************************************************************************** - -CToolsLogicTree::CToolsLogicTree () -{ - _MainFrame = NULL; - SelectMark = NULL; - m_boDragging = false; -} - -// *************************************************************************** -void CToolsLogicTree::init (CMainFrame *pMF) -{ - _MainFrame = pMF; -// pMF->_PRegionBuilder.setToolsLogic (this); - _RegionsInfo.resize (0); - // pMF->_PRegionBuilder.updateToolsLogic (); - - /*CImageList *pImgList = new CImageList; - pImgList->Create (16, 16, ILC_MASK, 0, 5); - pImgList->Add (AfxGetApp()->LoadIcon(IDI_PRIM)); // 0 - pImgList->Add (AfxGetApp()->LoadIcon(IDI_GROUP)); // 1 - pImgList->Add (AfxGetApp()->LoadIcon(IDI_POINT)); // 2 - pImgList->Add (AfxGetApp()->LoadIcon(IDI_POINT_HIDE)); // 3 - pImgList->Add (AfxGetApp()->LoadIcon(IDI_LINE)); // 4 - pImgList->Add (AfxGetApp()->LoadIcon(IDI_LINE_HIDE)); // 5 - pImgList->Add (AfxGetApp()->LoadIcon(IDI_ZONE)); // 6 - pImgList->Add (AfxGetApp()->LoadIcon(IDI_ZONE_HIDE)); // 7*/ - - // Add the image list - SetImageList (&(theApp.ImageList.ImageList), TVSIL_NORMAL); -} - -// *************************************************************************** -void CToolsLogicTree::reset () -{ -// GetTreeCtrl().DeleteAllItems(); - DeleteAllItems(); - _RegionsInfo.clear (); -} - -// *************************************************************************** -void CToolsLogicTree::uninit () -{ - _MainFrame = NULL; -} - -// *************************************************************************** -void CToolsLogicTree::setTool (CToolsLogic *pTools) -{ - _ToolLogic = pTools; -} - -// *************************************************************************** -uint32 CToolsLogicTree::createNewRegion (const string &name) -{ - SRegionInfo ri; - - if (_MainFrame == NULL) - return 0; - - ri.Name = name; - ri.RegionItem = insertItemUTF8 (*this, ri.Name.c_str(), 0, 0); - //ri.PointItem = insertItemUTF8 (*this, "Points", ri.RegionItem); - //ri.PathItem = insertItemUTF8 (*this, "Splines", ri.RegionItem); - //ri.ZoneItem = insertItemUTF8 (*this, "Patatoids", ri.RegionItem); - _RegionsInfo.push_back (ri); - - return _RegionsInfo.size()-1; -} - -// *************************************************************************** -uint32 CToolsLogicTree::createNewGroup (uint32 nRegion, const string &sGroupName) -{ - SRegionInfo &rRI = _RegionsInfo[nRegion]; - - if (_MainFrame == NULL) - return 0; - - HTREEITEM newItem = insertItemUTF8 (*this, sGroupName.c_str(), 1, 1, rRI.RegionItem); - rRI.Groups.push_back (newItem); - - return rRI.Groups.size()-1; -} - -// *************************************************************************** -HTREEITEM CToolsLogicTree::addPoint (uint32 nRegion, uint32 nGroup, const string &name, bool bHide) -{ - if (bHide) - return insertItemUTF8 (*this, name.c_str(), 3, 3, _RegionsInfo[nRegion].Groups[nGroup]); - return insertItemUTF8 (*this, name.c_str(), 2, 2, _RegionsInfo[nRegion].Groups[nGroup]); -} - -// *************************************************************************** -HTREEITEM CToolsLogicTree::addPath (uint32 nRegion, uint32 nGroup, const string &name, bool bHide) -{ - if (bHide) - return insertItemUTF8 (*this, name.c_str(), 5, 5, _RegionsInfo[nRegion].Groups[nGroup]); - return insertItemUTF8 (*this, name.c_str(), 4, 4, _RegionsInfo[nRegion].Groups[nGroup]); -} - -// *************************************************************************** -HTREEITEM CToolsLogicTree::addZone (uint32 nRegion, uint32 nGroup, const string &name, bool bHide) -{ - if (bHide) - return insertItemUTF8 (*this, name.c_str(), 7, 7, _RegionsInfo[nRegion].Groups[nGroup]); - return insertItemUTF8 (*this, name.c_str(), 6, 6, _RegionsInfo[nRegion].Groups[nGroup]); -} - -// *************************************************************************** -void CToolsLogicTree::expandAll (uint32 nPos) -{ - Expand (_RegionsInfo[nPos].RegionItem, TVE_EXPAND); - for(uint32 i = 0; i < _RegionsInfo[nPos].Groups.size(); ++i) - Expand (_RegionsInfo[nPos].Groups[i], TVE_EXPAND); -} - -// *************************************************************************** -BOOL CToolsLogicTree::PreCreateWindow (CREATESTRUCT& cs) -{ - cs.style |= TVS_SHOWSELALWAYS; - if (!CTreeCtrl::PreCreateWindow(cs)) - return FALSE; - return TRUE; -} - -// *************************************************************************** - -void CToolsLogicTree::OnLButtonDown (UINT nFlags, CPoint point) -{ - // Hit item test - UINT uFlags; - HTREEITEM hItem = HitTest(point, &uFlags); - - // Item found ? - if (hItem) - { - // Remove lock mode - getMainFrame ()->setSelectionLocked (false); - - // Select - SelectItem (hItem); - CPrimitiveTreeData *data = (CPrimitiveTreeData*)GetItemData (hItem); - CDatabaseLocatorPointer locator; - - // The document - CWorldEditorDoc *doc = getDocument (); - - doc->getLocator (locator, data->Primitive); - if (data) - { - - // Begin - doc->beginModification (); - - // Unselect - if (((nFlags & MK_CONTROL) == 0) && ((nFlags & MK_SHIFT) == 0)) - doc->addModification (new CActionUnselectAll ()); - - // Shift select - if ((nFlags & MK_SHIFT) != 0) - { - // Not the same node - if (SelectMark && (SelectMark != hItem)) - { - // Same parent ? - if (GetParentItem (SelectMark) == GetParentItem (hItem)) - { - // Find the hItem - HTREEITEM current = SelectMark; - do - { - current = GetNextSiblingItem (current); - } - while (current && (current != hItem)); - - // Found ? - if (current) - { - // Select all items - current = SelectMark; - current = GetNextSiblingItem (current); - nlassert (current); - while (current != hItem) - { - // Get current data - CPrimitiveTreeData *dataCurrent = (CPrimitiveTreeData*)GetItemData (current); - CDatabaseLocatorPointer locatorCurrent; - doc->getLocator (locatorCurrent, dataCurrent->Primitive); - - // Select -// IProperty *prop; - if ((getPrimitiveEditor(dataCurrent->Primitive)->getSelected() && (nFlags & MK_CONTROL) != 0)) -// if ((dataCurrent->Primitive->getPropertyByName ("selected", prop) && (nFlags & MK_CONTROL) != 0)) - doc->addModification (new CActionUnselect (locatorCurrent)); - else - doc->addModification (new CActionSelect (locatorCurrent)); - - // Next item - current = GetNextSiblingItem (current); - nlassert (current); - } - } - else - { - // Select all items - current = SelectMark; - current = GetPrevSiblingItem (current); - nlassert (current); - while (current != hItem) - { - // Get current data - CPrimitiveTreeData *dataCurrent = (CPrimitiveTreeData*)GetItemData (current); - CDatabaseLocatorPointer locatorCurrent; - doc->getLocator (locatorCurrent, dataCurrent->Primitive); - - // Select -// IProperty *prop; - if ((getPrimitiveEditor(dataCurrent->Primitive)->getSelected() && (nFlags & MK_CONTROL) != 0)) -// if ((dataCurrent->Primitive->getPropertyByName ("selected", prop) && (nFlags & MK_CONTROL) != 0)) - doc->addModification (new CActionUnselect (locatorCurrent)); - else - doc->addModification (new CActionSelect (locatorCurrent)); - - // Next item - current = GetPrevSiblingItem (current); - nlassert (current); - } - } - } - } - } - - // Select -// IProperty *prop; - if ((getPrimitiveEditor(data->Primitive)->getSelected() && (nFlags & MK_CONTROL) != 0)) -// if ((data->Primitive->getPropertyByName ("selected", prop) && (nFlags & MK_CONTROL) != 0)) - doc->addModification (new CActionUnselect (locator)); - else - { - // Get the path of selected primitive and store it - std::string path; - doc->getFilePath(locator.getDatabaseIndex(), path); - doc->setPathOfSelectedPrimitive(path); - doc->addModification (new CActionSelect (locator)); - } - - // End - doc->endModification (); - - - // we save the property dialog which was holding the old selection - CDialogProperties* pDlg = NULL; - list::iterator it = PropertiesDialogs.begin(); - bool ok = false; - - while ( !ok && ( it != PropertiesDialogs.end() ) ) - { - if ( (*it)->equalsSelection( Selection ) ) - { - pDlg = (*it); - ok = true; - } - - it++; - } - - // Update data - getMainFrame ()->updateData (); - - if ( ( pDlg ) && ! ( GetAsyncKeyState( VK_MENU ) & 0x8000 ) ) - { - // is there already a property dialog with the new selection ? - CDialogProperties *pNewSelectionDlg = NULL; - it = PropertiesDialogs.begin(); - bool ok = false; - - while ( !ok && ( it != PropertiesDialogs.end() ) ) - { - if ( (*it)->equalsSelection( Selection ) ) - { - pNewSelectionDlg = (*it); - ok = true; - } - - it++; - } - - if ( pNewSelectionDlg ) - pNewSelectionDlg->SetFocus(); - else - pDlg->changeSelection (Selection); - - } - } - - // No shift select - if ((nFlags & MK_SHIFT) == 0) - // New mark - SelectMark = hItem; - } - - // Call previous method - CTreeCtrl::OnLButtonDown (nFlags, point); -} - -// *************************************************************************** - -void CToolsLogicTree::OnLButtonDblClk(UINT nFlags, CPoint point) -{ - // Hit item test - UINT uFlags; - HTREEITEM hItem = HitTest(point, &uFlags); - - // Item found ? - if (hItem) - { - // Remove lock mode - getMainFrame ()->setSelectionLocked (false); - - // The docmuent - CWorldEditorDoc *doc = getDocument (); - - // Select - SelectItem (hItem); - CPrimitiveTreeData *data = (CPrimitiveTreeData*)GetItemData (hItem); - CDatabaseLocatorPointer locator; - doc->getLocator (locator, data->Primitive); - if (data) - { - // The docmuent - CWorldEditorDoc *doc = getDocument (); - - // Begin - doc->beginModification (); - - // Unselect - if ((nFlags & MK_CONTROL) == 0) - doc->addModification (new CActionUnselectAll ()); - - // Select - doc->addModification (new CActionSelect (locator)); - - // End - doc->endModification (); - - // Update data - getMainFrame ()->updateData (); - - // Call properties - _MainFrame->OnEditProperties(); - } - } - - // New mark - SelectMark = hItem; -} - -// *************************************************************************** -void CToolsLogicTree::OnRButtonDown (UINT nFlags, CPoint point) -{ - // Hit item test - UINT uFlags; - HTREEITEM hItem = HitTest(point, &uFlags); - - // The docmuent - CWorldEditorDoc *doc = getDocument (); - - // Item found ? - if (hItem) - { - SelectItem (hItem); - CPrimitiveTreeData *data = (CPrimitiveTreeData*)GetItemData (hItem); - CDatabaseLocatorPointer locator; - doc->getLocator (locator, data->Primitive); - if (data) - { - // The docmuent - CWorldEditorDoc *doc = getDocument (); - - // Begin - doc->beginModification (); - - // Unselect - nlassert (data->Primitive); -// IProperty *prop; - if (((nFlags & MK_CONTROL) == 0) && (!getPrimitiveEditor(data->Primitive)->getSelected())) -// if (((nFlags & MK_CONTROL) == 0) && (!data->Primitive->getPropertyByName ("selected", prop))) - doc->addModification (new CActionUnselectAll ()); - - // Select - doc->addModification (new CActionSelect (locator)); - - // End - doc->endModification (); - - // Update data - getMainFrame ()->updateData (); - } - } - - // New mark - SelectMark = hItem; - - // Menu creation - ClientToScreen (&point); - getMainFrame ()->createContextMenu (this, point, false); -} - -// *************************************************************************** -void CToolsLogicTree::OnSelChanged () -{ - HTREEITEM hItem = GetSelectedItem(); - HTREEITEM hParent = GetParentItem (hItem); - - if (hItem != NULL) - { - // Select the item - Select(hItem, TVGN_CARET); - } -} - -// *************************************************************************** -// Contextual Menu : Region -// *************************************************************************** - -// *************************************************************************** -void CToolsLogicTree::OnMenuRegionCreateGroup () -{ - HTREEITEM item = GetSelectedItem (); - HTREEITEM parent = GetParentItem (item); - - // Go to the Region Item - while (parent != NULL) - { - item = parent; - parent = GetParentItem (item); - } - - for (uint32 i = 0; i < _RegionsInfo.size(); ++i) - if (_RegionsInfo[i].RegionItem == item) - { - HTREEITEM newGroup = insertItemUTF8 (*this, "New Group", 1, 1, item); - Expand (item, TVE_EXPAND); - Expand (newGroup, TVE_EXPAND); - } - Invalidate (); -} - -// *************************************************************************** - -void CToolsLogicTree::OnMenuRegionHideAll () -{ - HTREEITEM itemRegion = GetSelectedItem (); - for (uint32 i = 0; i < _RegionsInfo.size(); ++i) - if (_RegionsInfo[i].RegionItem == itemRegion) - { - HTREEITEM itemGroup = GetChildItem (itemRegion); - while (itemGroup != NULL) - { - HTREEITEM itemPrim = GetChildItem (itemGroup); - while (itemPrim != NULL) - { - int nImg, nSelImg; - GetItemImage (itemPrim, nImg, nSelImg); - if ((nImg == 2) || (nImg == 4) || (nImg == 6)) - nImg = nImg + 1; - SetItemImage (itemPrim, nImg, nImg); - - itemPrim = GetNextItem (itemPrim, TVGN_NEXT); - } - itemGroup = GetNextItem (itemGroup, TVGN_NEXT); - } - - break; - } -} - -// *************************************************************************** -void CToolsLogicTree::OnMenuRegionUnhideAll () -{ - HTREEITEM itemRegion = GetSelectedItem (); - for (uint32 i = 0; i < _RegionsInfo.size(); ++i) - if (_RegionsInfo[i].RegionItem == itemRegion) - { - - HTREEITEM itemGroup = GetChildItem (itemRegion); - while (itemGroup != NULL) - { - HTREEITEM itemPrim = GetChildItem (itemGroup); - while (itemPrim != NULL) - { - int nImg, nSelImg; - GetItemImage (itemPrim, nImg, nSelImg); - if ((nImg == 3) || (nImg == 5) || (nImg == 7)) - nImg = nImg - 1; - SetItemImage (itemPrim, nImg, nImg); - - itemPrim = GetNextItem (itemPrim, TVGN_NEXT); - } - itemGroup = GetNextItem (itemGroup, TVGN_NEXT); - } - break; - } -} - -// *************************************************************************** -void CToolsLogicTree::OnMenuRegionHideType () -{ - HTREEITEM item = GetSelectedItem (); - for (uint32 i = 0; i < _RegionsInfo.size(); ++i) - if (_RegionsInfo[i].RegionItem == item) - { - CTypeSelDlg dial(this); - dial._TypesInit = &(_MainFrame->_Environnement.Types); - if (dial.DoModal() == IDOK) - { - } - break; - } -} - -// *************************************************************************** -void CToolsLogicTree::OnMenuRegionUnhideType () -{ - HTREEITEM item = GetSelectedItem (); - for (uint32 i = 0; i < _RegionsInfo.size(); ++i) - if (_RegionsInfo[i].RegionItem == item) - { - CTypeSelDlg dial(this); - dial._TypesInit = &(_MainFrame->_Environnement.Types); - if (dial.DoModal() == IDOK) - { - } - break; - } -} - -// *************************************************************************** -// Contextual Menu : Group -// *************************************************************************** - -// *************************************************************************** -void CToolsLogicTree::OnMenuGroupCreatePoint() -{ - HTREEITEM itemGroup = GetSelectedItem (); - HTREEITEM itemRegion = GetParentItem (itemGroup); - uint32 i; - CCreateDialog dialog (this); - dialog.TypesForInit = &_MainFrame->_Environnement.Types; - - for (i = 0; i < _RegionsInfo.size(); ++i) - if (_RegionsInfo[i].RegionItem == itemRegion) - { - dialog.setRegionName (_RegionsInfo[i].Name); - break; - } - - dialog.MainFrame = _MainFrame; - - if (dialog.DoModal () == IDOK) - if (strlen(dialog.Name) > 0) - { - HTREEITEM newItem = insertItemUTF8 (*this, dialog.Name, 2, 2, itemGroup); - Expand (itemGroup, TVE_EXPAND); - // Create the newItem - for (i = 0; i < _RegionsInfo.size(); ++i) - if (_RegionsInfo[i].RegionItem == itemRegion) - { - } - // Callback handling - _MainFrame->primZoneModified(); - } - Invalidate (); -} - -// *************************************************************************** -void CToolsLogicTree::OnMenuGroupCreatePath() -{ - HTREEITEM itemGroup = GetSelectedItem (); - HTREEITEM itemRegion = GetParentItem (itemGroup); - uint32 i; - CCreateDialog dialog (this); - dialog.TypesForInit = &_MainFrame->_Environnement.Types; - - for (i = 0; i < _RegionsInfo.size(); ++i) - if (_RegionsInfo[i].RegionItem == itemRegion) - { - dialog.setRegionName (_RegionsInfo[i].Name); - break; - } - - dialog.MainFrame = _MainFrame; - - if (dialog.DoModal () == IDOK) - if (strlen(dialog.Name) > 0) - { - HTREEITEM newItem = insertItemUTF8 (*this, dialog.Name, 4, 4, itemGroup); - Expand (itemGroup, TVE_EXPAND); - // Create the newItem - for (i = 0; i < _RegionsInfo.size(); ++i) - if (_RegionsInfo[i].RegionItem == itemRegion) - { - } - // Callback handling - _MainFrame->primZoneModified(); - } - Invalidate (); -} - -// *************************************************************************** -void CToolsLogicTree::OnMenuGroupCreateZone() -{ - HTREEITEM itemGroup = GetSelectedItem (); - HTREEITEM itemRegion = GetParentItem (itemGroup); - uint32 i; - CCreateDialog dialog (this); - dialog.TypesForInit = &_MainFrame->_Environnement.Types; - - for (i = 0; i < _RegionsInfo.size(); ++i) - if (_RegionsInfo[i].RegionItem == itemRegion) - { - dialog.setRegionName (_RegionsInfo[i].Name); - break; - } - - dialog.MainFrame = _MainFrame; - - if (dialog.DoModal () == IDOK) - if (strlen(dialog.Name) > 0) - { - HTREEITEM newItem = insertItemUTF8 (*this, dialog.Name, 6, 6, itemGroup); - Expand (itemGroup, TVE_EXPAND); - // Create the newItem - for (i = 0; i < _RegionsInfo.size(); ++i) - if (_RegionsInfo[i].RegionItem == itemRegion) - { - } - // Callback handling - _MainFrame->primZoneModified(); - } - Invalidate (); -} - -// *************************************************************************** -void CToolsLogicTree::OnMenuGroupDelete () -{ - HTREEITEM itemGroup = GetSelectedItem (); - HTREEITEM itemRegion; - HTREEITEM itemRoot; - - // Go to the Region Item - itemRegion = itemRoot = itemGroup; - while (itemRoot != NULL) - { - itemRegion = itemRoot; - itemRoot = GetParentItem (itemRegion); - } - - for (uint32 i = 0; i < _RegionsInfo.size(); ++i) - if (_RegionsInfo[i].RegionItem == itemRegion) - { - HTREEITEM hChildItem = GetChildItem (itemGroup); - while (hChildItem != NULL) - { - HTREEITEM hNextItem = GetNextItem (hChildItem, TVGN_NEXT); - - DeleteItem (hChildItem); - OnSelChanged (); - - hChildItem = hNextItem; - } - for (uint32 j = 0; j < _RegionsInfo[i].Groups.size(); ++j) - if (_RegionsInfo[i].Groups[j] == itemGroup) - { - for (uint32 k = j+1; k < _RegionsInfo[i].Groups.size(); ++k) - _RegionsInfo[i].Groups[k-1] = _RegionsInfo[i].Groups[k]; - _RegionsInfo[i].Groups.resize (_RegionsInfo[i].Groups.size()-1); - } - DeleteItem (itemGroup); - // Callback handling - _MainFrame->primZoneModified(); - } - -} - -// *************************************************************************** -void CToolsLogicTree::OnMenuGroupProperties() -{ - CEditStringDlg es(this); - HTREEITEM hItem = GetSelectedItem (); - es.Name = GetItemText (hItem); - if (es.DoModal() == IDOK) - { - setItemTextUTF8 (*this, hItem, es.Name); - - HTREEITEM hChildItem = GetChildItem(hItem); - while (hChildItem != NULL) - { - HTREEITEM hNextItem = GetNextItem (hChildItem, TVGN_NEXT); - hChildItem = hNextItem; - } - } -} - -// *************************************************************************** -void CToolsLogicTree::OnMenuGroupHide() -{ - HTREEITEM itemGroup = GetSelectedItem (); - HTREEITEM itemRegion = GetParentItem (itemGroup); - - HTREEITEM hChildItem = GetChildItem(itemGroup); - while (hChildItem != NULL) - { - HTREEITEM hNextItem = GetNextItem (hChildItem, TVGN_NEXT); - - int nImg, nSelImg; - GetItemImage (hChildItem, nImg, nSelImg); - if ((nImg == 2) || (nImg == 4) || (nImg == 6)) - nImg = nImg + 1; - SetItemImage (hChildItem, nImg, nImg); - - hChildItem = hNextItem; - } -} - -// *************************************************************************** -void CToolsLogicTree::OnMenuGroupUnhide() -{ - HTREEITEM itemGroup = GetSelectedItem (); - HTREEITEM itemRegion = GetParentItem (itemGroup); - - HTREEITEM hChildItem = GetChildItem(itemGroup); - while (hChildItem != NULL) - { - HTREEITEM hNextItem = GetNextItem (hChildItem, TVGN_NEXT); - - int nImg, nSelImg; - GetItemImage (hChildItem, nImg, nSelImg); - if ((nImg == 3) || (nImg == 5) || (nImg == 7)) - nImg = nImg - 1; - SetItemImage (hChildItem, nImg, nImg); - - hChildItem = hNextItem; - } -} - -// *************************************************************************** -void CToolsLogicTree::OnMenuGroupTransfertAppend () -{ - vector vTemp; - - HTREEITEM itemGroup = GetSelectedItem (); - HTREEITEM hChildItem = GetChildItem(itemGroup); - while (hChildItem != NULL) - { - HTREEITEM hNextItem = GetNextItem (hChildItem, TVGN_NEXT); - - vTemp.push_back((LPCSTR)GetItemText(hChildItem)); - - hChildItem = hNextItem; - } - - /* if (_MainFrame->_MasterCB != NULL) - _MainFrame->multiTransfert(vTemp, true); */ -} - -// *************************************************************************** -void CToolsLogicTree::OnMenuGroupTransfertReplace () -{ - vector vTemp; - - HTREEITEM itemGroup = GetSelectedItem (); - HTREEITEM hChildItem = GetChildItem(itemGroup); - while (hChildItem != NULL) - { - HTREEITEM hNextItem = GetNextItem (hChildItem, TVGN_NEXT); - - vTemp.push_back((LPCSTR)GetItemText(hChildItem)); - - hChildItem = hNextItem; - } - - /* if (_MainFrame->_MasterCB != NULL) - _MainFrame->multiTransfert(vTemp, false); */ -} - -// *************************************************************************** -// Contextual Menu : Prim -// *************************************************************************** - -void CToolsLogicTree::OnMenuPrimDelete() -{ - _MainFrame->deletePrimitive (false, "Delete"); -} - -// *************************************************************************** - -void CToolsLogicTree::OnProjectNewPrimitive () -{ - _MainFrame->OnProjectNewPrimitive (); -} - -// *************************************************************************** - -void CToolsLogicTree::OnViewShow () -{ - _MainFrame->OnViewShow (); -} - -// *************************************************************************** - -void CToolsLogicTree::OnViewHide () -{ - _MainFrame->OnViewHide (); -} - -// *************************************************************************** - -void CToolsLogicTree::OnEditExpand () -{ - _MainFrame->OnEditExpand (); -} - -// *************************************************************************** - -void CToolsLogicTree::OnEditCollapse () -{ - _MainFrame->OnEditCollapse (); -} - -// *************************************************************************** - -void CToolsLogicTree::OnEditSelectChildren () -{ - _MainFrame->OnEditSelectChildren (); -} - -// *************************************************************************** - -void CToolsLogicTree::OnMenuPrimProperties() -{ - // Open the property dialog - _MainFrame->OnEditProperties (); -} - -// *************************************************************************** - -void CToolsLogicTree::OnAddPrimitive (UINT nID) -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Begin modification - doc->beginModification (); - - // Only one selection ? - nlassert (Selection.size () == 1); - nlassert (Selection.front ()); - - // What class is it ? - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*(Selection.front ())); - nlassert (primClass); - uint childId = nID - ID_EDIT_CREATE_BEGIN; - - // Get the child class - CDatabaseLocatorPointer insert; - doc->getLocator (insert, Selection.front ()); - CDatabaseLocator dest; - insert.appendChild (dest); - - // Position on the Display - CDisplay *display = getDisplay (); - float delta = (float)DELTA_POS_ADD_PRIMITIVE * (display->_CurViewMax.x - display->_CurViewMin.x) / (float)display->getWidth (); - CVector pos = (display->_CurViewMin + display->_CurViewMax)/2; - if (doc->addModification (new CActionAddPrimitiveByClass (dest, primClass->DynamicChildren[childId].ClassName.c_str (), pos, delta, - primClass->DynamicChildren[childId].Parameters))) - { - // Unselect all - doc->addModification (new CActionUnselectAll ()); - - // Select it - doc->addModification (new CActionSelect (dest)); - } - - // End modification - doc->endModification (); - - // Update the data - _MainFrame->updateData (); -} - -// *************************************************************************** - -void CToolsLogicTree::OnGeneratePrimitive (UINT nID) -{ - _MainFrame->OnGeneratePrimitive (nID); -} - -// *************************************************************************** - -void CToolsLogicTree::OnOpenFile (UINT nID) -{ - _MainFrame->OnOpenFile (nID); -} - -// *************************************************************************** -// CToolsLogic -// *************************************************************************** - -// *************************************************************************** - -BEGIN_MESSAGE_MAP (CToolsLogic, CFormView) - ON_WM_CREATE() - ON_WM_SIZE () - ON_WM_PAINT () - ON_BN_CLICKED (IDC_NEW_PATAT, OnNewPatat) - ON_BN_CLICKED (IDC_NEW_GROUP, OnNewGroup) -END_MESSAGE_MAP() - -// *************************************************************************** - -IMPLEMENT_DYNCREATE(CToolsLogic, CFormView) - -// *************************************************************************** -CToolsLogic::CToolsLogic() : CFormView(IDD_TOOLS_LOGIC) -{ - _Tree = NULL; - _TreeCreated = false; -} - -// *************************************************************************** -CToolsLogicTree *CToolsLogic::GetTreeCtrl() -{ - if (_TreeCreated) - return _Tree; - return NULL; -} - -// *************************************************************************** -void CToolsLogic::init (CMainFrame *pMF) -{ - _MainFrame = pMF; - if (GetTreeCtrl() != NULL) - GetTreeCtrl()->init (pMF); -} - -// *************************************************************************** -void CToolsLogic::reset () -{ - if (GetTreeCtrl() != NULL) - GetTreeCtrl()->reset (); -} - -// *************************************************************************** -void CToolsLogic::uninit () -{ - if (GetTreeCtrl() != NULL) - GetTreeCtrl()->uninit (); -} - -// *************************************************************************** -uint32 CToolsLogic::createNewRegion (const string &sRegionName) -{ - if (_TreeCreated) - return GetTreeCtrl()->createNewRegion (sRegionName); - return 0; -} - -// *************************************************************************** -uint32 CToolsLogic::createNewGroup (uint32 nRegion, const string &sGroupName) -{ - if (_TreeCreated) - return GetTreeCtrl()->createNewGroup (nRegion, sGroupName); - return 0; -} - -// *************************************************************************** -HTREEITEM CToolsLogic::addPoint (uint32 nRegion, uint32 nGroup, const string &name, bool bHide) -{ - if (_TreeCreated) - return GetTreeCtrl()->addPoint (nRegion, nGroup, name, bHide); - return NULL; -} - -// *************************************************************************** -HTREEITEM CToolsLogic::addPath (uint32 nRegion, uint32 nGroup, const string &name, bool bHide) -{ - if (_TreeCreated) - return GetTreeCtrl()->addPath (nRegion, nGroup, name, bHide); - return NULL; -} - -// *************************************************************************** -HTREEITEM CToolsLogic::addZone (uint32 nRegion, uint32 nGroup, const string &name, bool bHide) -{ - if (_TreeCreated) - return GetTreeCtrl()->addZone (nRegion, nGroup, name, bHide); - return NULL; -} - -// *************************************************************************** -void CToolsLogic::expandAll (uint32 nRegion) -{ - if (_TreeCreated) - GetTreeCtrl()->expandAll (nRegion); -} - -#define TREE_TOP 0 -#define TREE_LEFT 0 -#define TREE_RIGHT 0 -#define TREE_BOTTOM 0 - -// *************************************************************************** -int CToolsLogic::OnCreate (LPCREATESTRUCT lpCreateStruct) -{ -// if (CFormView::OnCreate (lpCreateStruct) == -1) -// return -1; - if (CFormView::OnCreate (lpCreateStruct) == -1) - return -1; - - ::CRect iniRect; - GetClientRect(&iniRect); - iniRect.top = TREE_TOP; iniRect.left = TREE_LEFT; - iniRect.right += TREE_RIGHT; iniRect.bottom += TREE_BOTTOM; - _Tree = new CToolsLogicTree; - _Tree->Create ( WS_VISIBLE | WS_TABSTOP | WS_CHILD - | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES | TVS_SHOWSELALWAYS, - iniRect, this, 0x1) ; - - BOOL tIsUnicode; -#ifdef UNICODE -tIsUnicode = TreeView_SetUnicodeFormat(_Tree->m_hWnd, 1); -#else -tIsUnicode = TreeView_SetUnicodeFormat(_Tree->m_hWnd, 0); -#endif // UNICODE - - _Tree->setTool (this); - _TreeCreated = true; - - return 0; -} - -// *************************************************************************** -void CToolsLogic::OnSize (UINT nType, int cx, int cy) -{ - CFormView::OnSize (nType, cx, cy); - // Resize list ctrl to fill the whole view. - if (_TreeCreated) - { - ::CRect iniRect; - GetClientRect(&iniRect); - - iniRect.top += TREE_TOP; iniRect.left += TREE_LEFT; - iniRect.right += TREE_RIGHT; iniRect.bottom += TREE_BOTTOM; - - GetTreeCtrl()->MoveWindow (&iniRect); - } - -} - -// *************************************************************************** -void CToolsLogic::OnPaint () -{ - GetTreeCtrl()->ShowScrollBar(SB_VERT); - CFormView::OnPaint(); -} - -// *************************************************************************** -void CToolsLogic::OnNewGroup () -{ - GetTreeCtrl()->OnMenuRegionCreateGroup (); -} - -// *************************************************************************** -void CToolsLogic::OnNewPatat () -{ - CComboBox *pCB = (CComboBox*)GetDlgItem(IDC_TYPE); - CString str; - getWindowTextUTF8 (*pCB, str); - string sStr = (LPCSTR)str; -} - -// *************************************************************************** -// CCreateDialog -// *************************************************************************** - -// *************************************************************************** -BEGIN_MESSAGE_MAP(CCreateDialog, CDialog) - //{{AFX_MSG_MAP(CMainFrame) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code ! - ON_CBN_SELCHANGE(IDC_COMBOTYPE, OnSelChange) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - - -// *************************************************************************** -CCreateDialog::CCreateDialog (CWnd*pParent) : CDialog(IDD_CREATE_ELEMENT, pParent) -{ - Name[0] = 0; - LayerName[0] = 0; -} - -// *************************************************************************** -BOOL CCreateDialog::OnInitDialog () -{ - CDialog::OnInitDialog(); - - for (uint32 i = 0; i < TypesForInit->size(); ++i) - { - ComboType.InsertString (-1, TypesForInit->operator[](i).Name.c_str()); - } - - if (TypesForInit->size()>0) - { - if (ComboType.SelectString (0, LayerName) == CB_ERR) - ComboType.SetCurSel (0); - UpdateData(); - if (strlen(Name) == 0) - OnSelChange(); - } - - return true; -} - -// *************************************************************************** -void CCreateDialog::DoDataExchange (CDataExchange* pDX ) -{ - DDX_Control(pDX, IDC_COMBOTYPE, ComboType); - - DDX_Text(pDX, IDC_EDIT_NAME, (LPTSTR)Name, 128); - DDV_MaxChars(pDX, Name, 128); - - DDX_Text(pDX, IDC_COMBOTYPE, (LPTSTR)LayerName, 128); - DDV_MaxChars(pDX, LayerName, 128); -} - -// *************************************************************************** -void CCreateDialog::OnOK() -{ - UpdateData (); - - // If the "region_" do not exist add it - if (strncmp(RegionPost.c_str(), Name, strlen(RegionPost.c_str())) != 0) - { - char sTmp[128]; - strcpy (sTmp, RegionPost.c_str()); - strcat (sTmp, Name); - strcpy (Name, sTmp); - UpdateData (false); - } - - if (strcmp(PropName.c_str(), Name) == 0) - CDialog::OnOK(); - - CDialog::OnOK(); -} - -// *************************************************************************** -void CCreateDialog::setRegionName (const string &rn) -{ - for (uint32 i = 0; i < rn.size(); ++i) - { - if (rn[i] == '.') - { - RegionPost += '-'; - return; - } - RegionPost += rn[i]; - } - RegionPost += '-'; -} - -// *************************************************************************** -void CCreateDialog::OnSelChange () -{ - int cs = ComboType.GetCurSel(); - CString sTmp; - ComboType.GetLBText (cs, sTmp); - - if (PropType == (LPCSTR)sTmp) - { - strcpy (Name, PropName.c_str()); - } - else - { - strcpy (Name, RegionPost.c_str()); - strcat (Name, (LPCSTR)sTmp); - strcat (Name, "-"); - } - - UpdateData (false); - Invalidate (); -} - -// *************************************************************************** -// CEditStringDlg -// *************************************************************************** - -// *************************************************************************** -CEditStringDlg::CEditStringDlg(CWnd*pParent) : CDialog(IDD_EDIT_STRING, pParent) -{ - Name = _T(""); -} - -// *************************************************************************** -BOOL CEditStringDlg::OnInitDialog () -{ - CDialog::OnInitDialog(); - - UpdateData(); - - return TRUE; -} - -// *************************************************************************** -void CEditStringDlg::DoDataExchange (CDataExchange* pDX ) -{ - DDX_Text(pDX, IDC_EDIT_NAME, Name); -} - -// *************************************************************************** -void CEditStringDlg::OnOK() -{ - UpdateData (); - CDialog::OnOK(); -} - -// *************************************************************************** - -// Returns the index-th first level tree node -void selectItem (CTreeCtrl &tree, uint index) -{ - HTREEITEM item = tree.GetRootItem (); - while (index--) - { - item = tree.GetNextSiblingItem (item); - nlassert (item); - } - tree.SelectItem (item); -} - -// *************************************************************************** - -BOOL CToolsLogic::OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult ) -{ - int idCtrl = (int) wParam; - LPNMHDR pnmh = (LPNMHDR) lParam; - - // The document - CWorldEditorDoc *doc = getDocument (); - - switch (pnmh->code) - { - case TVN_SELCHANGED: - { - // Select the good item - LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) lParam; - - // By keyboard ? - - if ( pnmtv->action == TVC_BYKEYBOARD )// || - // ( ( GetAsyncKeyState( VK_L)) && !( GetAsyncKeyState( VK_MENU ) & 0x8000 ) ) ) - { - // we save the current properties dialog - CDialogProperties *pDlg = NULL; - - list::iterator it = PropertiesDialogs.begin(); - bool ok = false; - - while ( !ok && ( it != PropertiesDialogs.end() ) ) - { - if ( (*it)->equalsSelection( Selection ) ) - { - pDlg = (*it); - ok = true; - } - - it++; - } - - // Remove lock mode - getMainFrame ()->setSelectionLocked (false); - - // Get the item data - CPrimitiveTreeData *data = (CPrimitiveTreeData*)_Tree->GetItemData (pnmtv->itemNew.hItem); - CDatabaseLocatorPointer locator; - doc->getLocator (locator, data->Primitive); - - // Begin - doc->beginModification (); - - // Unselect - doc->addModification (new CActionUnselectAll ()); - - // Something to select ? - if (data) - { - // Select - doc->addModification (new CActionSelect (locator)); - } - - // End - doc->endModification (); - - // Update data - getMainFrame ()->updateData (); - - if ( pDlg ) - pDlg->changeSelection (Selection); - - // New mark - _Tree->SelectMark = pnmtv->itemNew.hItem; - - - SetFocus(); - } - } - break; - case TVN_ITEMEXPANDED: - { - // Take the item - LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) lParam; - - // Get the item data - CPrimitiveTreeData *data = (CPrimitiveTreeData*)_Tree->GetItemData (pnmtv->itemNew.hItem); - - // Don't make an action (don't modify the document) when expand / collapse the list.. - - // Unselect - - getPrimitiveEditor(data->Primitive)->setExpanded((pnmtv->action&TVE_EXPAND)!=0); -// const_cast (data->Primitive)->Expanded = (pnmtv->action&TVE_EXPAND)!=0; - } - break; - case TVN_KEYDOWN: - { - // Get selected item - HTREEITEM item = _Tree->GetSelectedItem (); - if (item) - { - // Take the item - LPNMTVKEYDOWN pnmtv = (LPNMTVKEYDOWN) lParam; - - // Key down + CTRL ? - if ( (pnmtv->wVKey == VK_UP) && (GetAsyncKeyState (VK_CONTROL) & 0x8000)) - { - // Get the item data - CPrimitiveTreeData *data = (CPrimitiveTreeData*)_Tree->GetItemData (item); - CDatabaseLocatorPointer locator; - CDatabaseLocatorPointer root; - doc->getLocator (locator, data->Primitive); - root.getRoot (locator.getDatabaseIndex()); - - // Get the previous locator - if (!(root == locator)) - { - // Get the previous locator - CDatabaseLocatorPointer previousLocator = locator; - if (previousLocator.previousChild ()) - { - // Begin - doc->beginModification (); - - // Copy the primitive - const IPrimitive *copy = data->Primitive->copy (); - - // Remove the primitive - doc->addModification (new CActionDelete (locator)); - - // Add the primitive at the previous position - doc->addModification (new CActionAddPrimitive (*copy, previousLocator)); - doc->addModification (new CActionSelect (previousLocator)); - delete copy; - - - - // End - doc->endModification (); - - // Update data - getMainFrame ()->updateData (); - - // Get selected item - doc->getLocator (previousLocator, locator); - nlverify (previousLocator.previousChild ()); - IPrimitiveEditor *primitiveEditor = dynamic_cast (const_cast (previousLocator.Primitive)); - _Tree->SelectItem (primitiveEditor->_TreeItem); - } - } - else - { - // Not the top primitive - uint index = locator.getDatabaseIndex (); - if (index > 0) - { - // Begin - doc->beginModification (); - - // Exchange the primitives - doc->addModification (new CActionXChgDatabaseElement (index-1)); - - // End - doc->endModification (); - - // Update data - getMainFrame ()->updateData (); - - selectItem (*_Tree, index-1); - } - } - } - // Key up + CTRL ? - else if ( (pnmtv->wVKey == VK_DOWN) && (GetAsyncKeyState (VK_CONTROL) & 0x8000)) - { - // Get the item data - CPrimitiveTreeData *data = (CPrimitiveTreeData*)_Tree->GetItemData (item); - CDatabaseLocatorPointer locator; - CDatabaseLocatorPointer root; - doc->getLocator (locator, data->Primitive); - root.getRoot (locator.getDatabaseIndex()); - - // Get the previous locator - if (!(root == locator)) - { - CDatabaseLocatorPointer nextLocator = locator; - if (nextLocator.nextChild ()) - { - // Begin - doc->beginModification (); - - // Copy the primitive - const IPrimitive *copy = data->Primitive->copy (); - - // Remove the primitive - doc->addModification (new CActionDelete (locator)); - - // Add the primitive at the previous position - doc->addModification (new CActionAddPrimitive (*copy, nextLocator)); - doc->addModification (new CActionSelect (nextLocator)); - delete copy; - - // End - doc->endModification (); - - // Update data - getMainFrame ()->updateData (); - - // Get selected item - doc->getLocator (nextLocator, locator); - nlverify (nextLocator.nextChild ()); - IPrimitiveEditor *primitiveEditor = dynamic_cast (const_cast (nextLocator.Primitive)); - _Tree->SelectItem (primitiveEditor->_TreeItem); - } - } - else - { - // Not the top primitive - uint index = locator.getDatabaseIndex (); - if (index+1 < doc->getNumDatabaseElement ()) - { - // Begin - doc->beginModification (); - - // Exchange the primitives - doc->addModification (new CActionXChgDatabaseElement (index)); - - // End - doc->endModification (); - - // Update data - getMainFrame ()->updateData (); - - selectItem (*_Tree, index+1); - } - } - } - } - } - break; - } - - return CFormView::OnNotify( wParam, lParam, pResult ); -} - -// *************************************************************************** - -HTREEITEM CToolsLogic::addPrimitive (HTREEITEM parentItem, HTREEITEM lastBrother, const CDatabaseLocatorPointer &locator) -{ - HTREEITEM treeItem = insertItemUTF8 (*_Tree, "", parentItem, lastBrother); - - // Get the primitives - CWorldEditorDoc *doc = getDocument (); - const NLLIGO::CPrimitives *primitives = &(doc->getDatabaseElements (locator.getDatabaseIndex ())); - - // Set the item data - _Tree->SetItemData (treeItem, (DWORD)new CPrimitiveTreeData (primitives, locator.Primitive)); - - // Expand parent ? - if (parentItem != TVI_ROOT) - { - CPrimitiveTreeData *parentData = (CPrimitiveTreeData *)_Tree->GetItemData (parentItem); - nlassert (parentData); - _Tree->Expand (parentItem, getPrimitiveEditor(parentData->Primitive)->getExpanded()?TVE_EXPAND:TVE_COLLAPSE); - } - - return treeItem; -} - -// *************************************************************************** - -void CToolsLogic::updatePrimitive (HTREEITEM item, const CDatabaseLocatorPointer &locator) -{ - if (locator.Primitive) - { - // Is selected ? -// IProperty *prop; - _Tree->SetItemState (item, getPrimitiveEditor(locator.Primitive)->getSelected()?TVIS_BOLD:0, TVIS_BOLD); -// _Tree->SetItemState (item, locator.Primitive->getPropertyByName ("selected", prop)?TVIS_BOLD:0, TVIS_BOLD); - - // Root ? - if (locator.Primitive->getParent ()) - { - // Set the name - string name; - string className; - locator.Primitive->getPropertyByName ("name", name); - locator.Primitive->getPropertyByName ("class", className); - const CPrimitiveClass *pc = theApp.Config.getPrimitiveClass(className.c_str()); - if (pc && pc->Type == CPrimitiveClass::Alias) - { - const CPrimAlias *pa = dynamic_cast(locator.Primitive); - nlassert(pa != NULL); - - name += " "+toString(pa->getAlias()); - } - setItemTextUTF8 (*_Tree, item, name.c_str ()); - } - else - { - // Set the primitive name - string name; - getDocument ()->getPrimitiveDisplayName (name, locator.getDatabaseIndex ()); - setItemTextUTF8 (*_Tree, item, name.c_str ()); - } - - // Expand / collapse it - _Tree->Expand (item, getPrimitiveEditor(locator.Primitive)->getExpanded()?TVE_EXPAND:TVE_COLLAPSE); - - // Hidden ? -// string temp; - bool hidden = getPrimitiveEditor(locator.Primitive)->getHidden(); -// bool hidden = locator.Primitive->getPropertyByName ("hidden", temp); - - // Class of primitive ? - bool imagesSets = false; - string className; - - if (locator.Primitive->getPropertyByName ("class", className)) - { - // Look for open / close icones.. - int _hidden = theApp.ImageList.getImage ((className+"_hidden").c_str ()); - int opened = theApp.ImageList.getImage ((className+"_opened").c_str ()); - int closed = theApp.ImageList.getImage ((className+"_closed").c_str ()); - if ((hidden && (_hidden != -1)) || ((opened != -1) && (closed != -1))) - { - // Set the images - _Tree->SetItemImage (item, hidden?_hidden:closed, hidden?_hidden:opened); - imagesSets = true; - } - else - { - // Look for open / close icones.. - int image = theApp.ImageList.getImage (className.c_str ()); - if (image != -1) - { - // Set the images - _Tree->SetItemImage (item, image, image); - imagesSets = true; - } - } - } - - // Icon sets or error ? - // Set the image, If there is an error, force to set an icon - const IPrimitiveEditor *node = dynamic_cast (locator.Primitive); - if (!imagesSets || (node && node->_Error != IPrimitiveEditor::NoError)) - { - // Root ? - if (locator.Primitive->getParent () == NULL) - { - if (node && node->_Error != IPrimitiveEditor::NoError) - { - _Tree->SetItemImage (item, theApp.ImageList.getImage (IDI_ERROR_STRUCTURE), theApp.ImageList.getImage (IDI_ERROR_STRUCTURE)); - } - else - { - _Tree->SetItemImage (item, theApp.ImageList.getImage (hidden?IDI_ROOT_HIDDEN:IDI_ROOT_CLOSED), theApp.ImageList.getImage (hidden?IDI_ROOT_HIDDEN:IDI_ROOT_OPENED)); - } - } - else - { - // What kind of class ? - if (node) - { - if (node->_Error != IPrimitiveEditor::NoError) - { - _Tree->SetItemImage (item, theApp.ImageList.getImage (IDI_ERROR_STRUCTURE), theApp.ImageList.getImage (IDI_ERROR_STRUCTURE)); - } - else - { - // Some children ? - if (locator.Primitive->getNumChildren ()) - _Tree->SetItemImage (item, theApp.ImageList.getImage (hidden?IDI_FOLDER_HIDDEN:IDI_FOLDER_CLOSED), theApp.ImageList.getImage (hidden?IDI_FOLDER_HIDDEN:IDI_FOLDER_OPENED)); - else - _Tree->SetItemImage (item, theApp.ImageList.getImage (hidden?IDI_PROPERTY_HIDDEN:IDI_PROPERTY_CLOSED), theApp.ImageList.getImage (hidden?IDI_PROPERTY_HIDDEN:IDI_PROPERTY_OPENED)); - } - } - else - { - const CPrimPointEditor *point = dynamic_cast (locator.Primitive); - if (point) - _Tree->SetItemImage (item, theApp.ImageList.getImage (hidden?IDI_POINT_HIDDEN:IDI_POINT_CLOSED), theApp.ImageList.getImage (hidden?IDI_POINT_HIDDEN:IDI_POINT_OPENED)); - else - { - const CPrimPathEditor *path = dynamic_cast (locator.Primitive); - if (path) - _Tree->SetItemImage (item, theApp.ImageList.getImage (hidden?IDI_LINE_HIDDEN:IDI_LINE_CLOSED), theApp.ImageList.getImage (hidden?IDI_LINE_HIDDEN:IDI_LINE_OPENED)); - else - { - const CPrimZoneEditor *node = dynamic_cast (locator.Primitive); - if (node && node->_Error != IPrimitiveEditor::NoError) - { - _Tree->SetItemImage (item, theApp.ImageList.getImage (IDI_ERROR_STRUCTURE), theApp.ImageList.getImage (IDI_ERROR_STRUCTURE)); - } - else - { - safe_cast (locator.Primitive); - _Tree->SetItemImage (item, theApp.ImageList.getImage (hidden?IDI_ZONE_HIDDEN:IDI_ZONE_CLOSED), theApp.ImageList.getImage (hidden?IDI_ZONE_HIDDEN:IDI_ZONE_OPENED)); - } - } - } - } - } - } - } - else - { - // Not bold - _Tree->SetItemState (item, 0, TVIS_BOLD); - } - - // Remove mark - _Tree->SelectMark = NULL; -} - -// *************************************************************************** - -void CToolsLogic::ensureVisible (IPrimitiveEditor *primitive) -{ - if (primitive->_TreeItem) - _Tree->EnsureVisible (primitive->_TreeItem); -} - -// *************************************************************************** - -void CToolsLogicTree::OnRenameSelected() -{ - // todo rebranch rename selection -/* // Not empty ? - if (!Selection.empty ()) - { - bool modified = false; - CWorldEditorDoc *doc = getDocument (); - - // For each selected primitives - std::list::iterator ite1 = Selection.begin (); - while (ite1 != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite1); - - // Primitive ? - const IPrimitive *primitive = locator.Primitive; - if (primitive) - { - // Get the class name - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*primitive); - // Does the class uses Autoname ? - if (primClass && primClass->Autoname != "") - { - // do we have a "name" field - const IProperty *propName; - if (primitive->getPropertyByName ("name", propName)) - { - // we collect all properties of the class in a parameter list - set parameterList; - for (uint p=0; pParameters.size (); p++) - { - // Is the parameter visible ? - if (primClass->Parameters[p].Visible) - { - // we avoid the reserved keywords - if (primClass->Parameters[p].Name != "name" && - primClass->Parameters[p].Name != "hidden" && - primClass->Parameters[p].Name != "selected" && - primClass->Parameters[p].Name != "class" && - primClass->Parameters[p].Name != "") - { - parameterList.insert (primClass->Parameters[p]); - } - } - } - // we rename the string in one pass - CString Name = primClass->Autoname.c_str(); - - set::iterator ite2 = parameterList.begin (); - while (ite2 != parameterList.end ()) - { - string result; - CString OriginalName = ite2->Name.c_str(); - if (ite2->Type == CPrimitiveClass::CParameter::String || - ite2->Type == CPrimitiveClass::CParameter::ConstString) - { - primitive->getPropertyByName (OriginalName, result); - } - else if (ite2->Type == CPrimitiveClass::CParameter::StringArray) - { - const IProperty *propName; - if (primitive->getPropertyByName (OriginalName, propName)) - { - const CPropertyStringArray *propStringString = dynamic_cast (propName); - result = propStringString->StringArray[0]; - } - else - { - result = "undefined"; - } - } - - OriginalName = "$"+OriginalName+"$"; - Name.Replace(OriginalName, result.c_str()); - ++ite2; - } - - // now, we overwrite the original name - // Create a default property - string value; - value = Name; - if (!modified) - { - doc->beginModification (); - modified = true; - } - doc->addModification (new CActionSetPrimitivePropertyString (locator, "name", value.c_str(), false)); - } - - } - } - ite1++; - } - if (modified) - { - doc->endModification (); - getMainFrame ()->updateData (); - } - }*/ -} - -// *************************************************************************** - -void CToolsLogicTree::OnRepairSelected() -{ - // Not empty ? - if (!Selection.empty ()) - { - bool modified = false; - CWorldEditorDoc *doc = getDocument (); - - // For each selected primitives - std::list::iterator ite1 = Selection.begin (); - while (ite1 != Selection.end ()) - { - CDatabaseLocatorPointer locator; - doc->getLocator (locator, *ite1); - - const IPrimitive *primitive = locator.Primitive; - if (primitive) - { - string className; - bool Success; - Success = primitive->getPropertyByName ("class", className); - - if (!Success) - { - // is this the root node ? - const IPrimitive *parent = primitive->getParent(); - if (!parent) - { - // if no parent, we have a root node - className = "root"; - Success = true; - } - } - if (Success) - { - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (className.c_str ()); - if (primClass) - { - uint CountStaticChildren = 0; - CDatabaseLocatorPointer myLocator; - - // FIRST PASS: - // we check if the Children belong to the original class - // if it's not the case, we remove the unknown Children -restart: - myLocator = locator; - if (myLocator.firstChild ()) - { - do - { - const IPrimitive *primitive2 = myLocator.Primitive; - if (primitive2) - { - string ClassName2; - nlverify (primitive2->getPropertyByName ("class", ClassName2)); - uint c; - bool Found = false; - for (c=0; cStaticChildren.size (); c++) - { - if (primClass->StaticChildren[c].ClassName == ClassName2) - { - Found = true; - ++CountStaticChildren; - break; - } - } - - for (c=0; cGeneratedChildren.size (); c++) - { - if (primClass->GeneratedChildren[c].ClassName == ClassName2) - { - Found = true; - break; - } - } - - for (c=0; cDynamicChildren.size (); c++) - { - if (primClass->DynamicChildren[c].ClassName == ClassName2) - { - Found = true; - break; - } - } - if (!Found) - { - // a useless child is here, we need to delete it - // Begin modification - if (!modified) - { - doc->beginModification (); - modified = true; - } - doc->deletePrimitive (myLocator); - doc->modifyDatabase (myLocator.getDatabaseIndex ()); - // since we deleted the child, we cannot point to the next one, so we restart the loop - // I don't think it's possible to use something better than this goto ! - goto restart; - } - } - } - while (myLocator.nextChild ()); - } - if (CountStaticChildren != primClass->StaticChildren.size()) - { - // SECOND PASS: - // if the number of static children of the class is different from the number of static children of the original class - // we have to add the missing class - uint child; - for (child=0; childStaticChildren.size (); ++child) - { - myLocator = locator; - bool Found = false; - // we parse the tree recursively, collection errors, and propagating to the parent - if (myLocator.firstChild ()) - { - do - { - const IPrimitive *primitive2 = myLocator.Primitive; - if (primitive2) - { - string ClassName2; - string name; - nlverify (primitive2->getPropertyByName ("class", ClassName2)); - if (primitive2->getPropertyByName ("name", name)) - { - if (primClass->StaticChildren[child].ClassName == ClassName2 && - primClass->StaticChildren[child].Name == name) - { - Found = true; - break; - } - } - } - } - while (myLocator.nextChild ()); - } - if (!Found) - { - // a child is missing, we need to create it - // Begin modification - if (!modified) - { - doc->beginModification (); - modified = true; - } - // What class is it ? - // Get the child class - CDatabaseLocatorPointer locator2 = locator; - locator2.firstChild(); - CDatabaseLocator dest = locator2; - - // Position on the Display - CDisplay *display = getDisplay (); - float delta = (float)DELTA_POS_ADD_PRIMITIVE * (display->_CurViewMax.x - display->_CurViewMin.x) / (float)display->getWidth (); - if (doc->addModification (new CActionAddPrimitiveByClass (dest, primClass->StaticChildren[child].ClassName.c_str (), getDisplay ()->_CurPos, - delta, primClass->StaticChildren[child].Parameters))) - { - CDatabaseLocatorPointer dest2; - doc->getLocator (dest2, dest); - - // Get a pointer on the new primitive - doc->addModification (new CActionSetPrimitivePropertyString (dest2, "name", primClass->StaticChildren[child].Name.c_str(), false)); - } - } - } - } - } - } - } - ite1++; - } - if (modified) - { - doc->endModification (); - // verify the structures, to get their status - VerifyPrimitivesStructures(); - InvalidateAllPrimitives (); - getMainFrame ()->updateData (); - } - } -} - -// *************************************************************************** - -void CToolsLogicTree::OnTreeHelp() -{ - getMainFrame ()->OnHelpFinder(); -} - -// *************************************************************************** - -void CToolsLogicTree::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) -{ - if ( GetAsyncKeyState( VK_MENU ) & 0x8000 ) - { - NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; - HTREEITEM hItem = pNMTreeView->itemNew.hItem; - if(!hItem) return; - SelectItem(hItem); - - CWorldEditorDoc *doc = getDocument (); - CDatabaseLocatorPointer locator; - doc->getLocator ( locator, Selection.front() ); - - if ( theApp.Config.isPrimitiveDeletable ( *( locator.Primitive ) ) ) - { - m_hDragItem = hItem; - m_pDragImgList = CreateDragImage(hItem); - if(!m_pDragImgList) return; - - m_pDragImgList->BeginDrag( 0, CPoint(0,0) ); - m_pDragImgList->DragEnter( this, pNMTreeView->ptDrag ); - m_boDragging = true; - - ShowCursor(false); - SetCapture(); - m_hDragTarget = NULL; - getMainFrame()->OnEditCut(); - } - - // m_nTimer = SetTimer(1,25,NULL); - *pResult = 0; - } -} - -// *************************************************************************** - -void CToolsLogicTree::OnMouseMove(UINT nFlags, CPoint point) -{ - if (m_boDragging) - { - // highlight target - - TVHITTESTINFO tvHit; - tvHit.pt = point; - HTREEITEM hTarget = HitTest(&tvHit); - - if ( hTarget ) - { - if(hTarget != m_hDragTarget) - { - // this test avoids flickering - m_pDragImgList->DragShowNolock(false); - SelectDropTarget(hTarget); - m_pDragImgList->DragShowNolock(true); - m_hDragTarget = hTarget; - } - } - - // move image being dragged - - m_pDragImgList->DragMove(point); - } - - CTreeCtrl::OnMouseMove( nFlags, point ); -} - -// *************************************************************************** - -void CToolsLogicTree::OnLButtonUp(UINT nFlags, CPoint point) -{ - if ( m_boDragging ) - { - KillTimer(1); - - ReleaseCapture(); - ShowCursor( true ); - m_boDragging = false; - - m_pDragImgList->DragLeave( this ); - m_pDragImgList->EndDrag(); - delete m_pDragImgList; - m_pDragImgList = NULL; - - TVHITTESTINFO tvHit; - tvHit.pt = point; - HTREEITEM hTarget = HitTest(&tvHit); - - OnLButtonDown( nFlags, point ); - - // Can be dropped ? - if ( GetDropHilightItem() && getMainFrame()->CanDrop() ) - { - getMainFrame()->OnEditPaste(); - } - else - { - // un-select - getMainFrame()->onMenuModeUndo(); - // un-cut - getMainFrame()->onMenuModeUndo(); - } - - OnLButtonDown( nFlags, point ); - SelectDropTarget( NULL ); - } - - CTreeCtrl::OnLButtonUp(nFlags, point); -} - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" + +#include "tools_logic.h" +#include "world_editor.h" +#include "world_editor_doc.h" +#include "type_sel_dlg.h" +#include "main_frm.h" +#include "display.h" +#include "action.h" +#include "editor_primitive.h" +#include "dialog_properties.h" + +#include + +using namespace std; +using namespace NLLIGO; +using namespace NLMISC; + +// *************************************************************************** + +#define ID_MENU_REGION_CREATE_GROUP 0x10018 +#define ID_MENU_REGION_PROPERTIES 0x10019 +#define ID_MENU_REGION_HIDE_ALL 0x10020 +#define ID_MENU_REGION_UNHIDE_ALL 0x10021 +#define ID_MENU_REGION_HIDE_TYPE 0x10022 +#define ID_MENU_REGION_UNHIDE_TYPE 0x10023 + +#define ID_MENU_GROUP_CREATE_POINT 0x10024 +#define ID_MENU_GROUP_CREATE_PATH 0x10025 +#define ID_MENU_GROUP_CREATE_ZONE 0x10026 +#define ID_MENU_GROUP_DELETE 0x10027 +#define ID_MENU_GROUP_PROPERTIES 0x10028 +#define ID_MENU_GROUP_HIDE 0x10029 +#define ID_MENU_GROUP_UNHIDE 0x1002A +#define ID_MENU_GROUP_TRANSFERT_REPLACE 0x1002B +#define ID_MENU_GROUP_TRANSFERT_APPEND 0x1002C + +#define ID_MENU_PRIM_DELETE 0x10010 +#define ID_MENU_PRIM_PROPERTIES 0x10011 +#define ID_MENU_PRIM_HIDE 0x10012 + +// *************************************************************************** + +BEGIN_MESSAGE_MAP(CToolsLogicTree, CTreeCtrl) + ON_WM_LBUTTONDOWN () + ON_WM_LBUTTONUP () + ON_WM_LBUTTONDBLCLK () + ON_WM_RBUTTONDOWN () +/* + ON_COMMAND (ID_MENU_REGION_CREATE_GROUP,OnMenuRegionCreateGroup) + ON_COMMAND (ID_MENU_REGION_PROPERTIES, OnMenuRegionProperties) + ON_COMMAND (ID_MENU_REGION_HIDE_ALL, OnMenuRegionHideAll) + ON_COMMAND (ID_MENU_REGION_UNHIDE_ALL, OnMenuRegionUnhideAll) + ON_COMMAND (ID_MENU_REGION_HIDE_TYPE, OnMenuRegionHideType) + ON_COMMAND (ID_MENU_REGION_UNHIDE_TYPE, OnMenuRegionUnhideType) + + ON_COMMAND (ID_MENU_GROUP_CREATE_POINT, OnMenuGroupCreatePoint) + ON_COMMAND (ID_MENU_GROUP_CREATE_PATH, OnMenuGroupCreatePath) + ON_COMMAND (ID_MENU_GROUP_CREATE_ZONE, OnMenuGroupCreateZone) + ON_COMMAND (ID_MENU_GROUP_DELETE, OnMenuGroupDelete) + ON_COMMAND (ID_MENU_GROUP_PROPERTIES, OnMenuGroupProperties) + ON_COMMAND (ID_MENU_GROUP_HIDE, OnMenuGroupHide) + ON_COMMAND (ID_MENU_GROUP_UNHIDE, OnMenuGroupUnhide) + ON_COMMAND (ID_MENU_GROUP_TRANSFERT_APPEND, OnMenuGroupTransfertAppend) + ON_COMMAND (ID_MENU_GROUP_TRANSFERT_REPLACE, OnMenuGroupTransfertReplace) + + ON_COMMAND (ID_MENU_PRIM_DELETE, OnMenuPrimDelete) + ON_COMMAND (ID_MENU_PRIM_PROPERTIES, OnMenuPrimProperties) + ON_COMMAND (ID_MENU_PRIM_HIDE, OnMenuPrimHide) +*/ + ON_COMMAND (ID_EDIT_DELETE, OnMenuPrimDelete) + ON_COMMAND (ID_EDIT_PROPERTIES, OnMenuPrimProperties) + ON_COMMAND (ID_PROJECT_NEWPRIMITIVE, OnProjectNewPrimitive) + ON_COMMAND (ID_VIEW_SHOW, OnViewShow) + ON_COMMAND (ID_VIEW_HIDE, OnViewHide) + ON_COMMAND (ID_EDIT_SELECT_CHILDREN, OnEditSelectChildren) + ON_COMMAND_RANGE (ID_EDIT_CREATE_BEGIN, ID_EDIT_CREATE_END, OnAddPrimitive) + ON_COMMAND_RANGE (ID_EDIT_GENERATE_BEGIN, ID_EDIT_GENERATE_END, OnGeneratePrimitive) + ON_COMMAND_RANGE (ID_EDIT_OPEN_FILE_BEGIN, ID_EDIT_OPEN_FILE_END, OnOpenFile) + ON_COMMAND(ID_EDIT_EXPAND, OnEditExpand) + ON_COMMAND(ID_EDIT_COLLAPSE, OnEditCollapse) + ON_COMMAND(ID_RENAME_SELECTED, OnRenameSelected) + ON_COMMAND(ID_REPAIR_SELECTED, OnRepairSelected) + ON_COMMAND(ID_HELP_FINDER, OnTreeHelp) + + ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBegindrag) + ON_WM_MOUSEMOVE () + + //ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelChanged) +END_MESSAGE_MAP() + +// *************************************************************************** + +class CPrimitiveTreeData +{ +public: + CPrimitiveTreeData (const NLLIGO::CPrimitives *primitives, const IPrimitive *primitive) + { + Primitive = primitive; + Primitives = primitives; + } + + // The primitive + const NLLIGO::CPrimitives *Primitives; + const IPrimitive *Primitive; +}; + +// *************************************************************************** + +CToolsLogicTree::CToolsLogicTree () +{ + _MainFrame = NULL; + SelectMark = NULL; + m_boDragging = false; +} + +// *************************************************************************** +void CToolsLogicTree::init (CMainFrame *pMF) +{ + _MainFrame = pMF; +// pMF->_PRegionBuilder.setToolsLogic (this); + _RegionsInfo.resize (0); + // pMF->_PRegionBuilder.updateToolsLogic (); + + /*CImageList *pImgList = new CImageList; + pImgList->Create (16, 16, ILC_MASK, 0, 5); + pImgList->Add (AfxGetApp()->LoadIcon(IDI_PRIM)); // 0 + pImgList->Add (AfxGetApp()->LoadIcon(IDI_GROUP)); // 1 + pImgList->Add (AfxGetApp()->LoadIcon(IDI_POINT)); // 2 + pImgList->Add (AfxGetApp()->LoadIcon(IDI_POINT_HIDE)); // 3 + pImgList->Add (AfxGetApp()->LoadIcon(IDI_LINE)); // 4 + pImgList->Add (AfxGetApp()->LoadIcon(IDI_LINE_HIDE)); // 5 + pImgList->Add (AfxGetApp()->LoadIcon(IDI_ZONE)); // 6 + pImgList->Add (AfxGetApp()->LoadIcon(IDI_ZONE_HIDE)); // 7*/ + + // Add the image list + SetImageList (&(theApp.ImageList.ImageList), TVSIL_NORMAL); +} + +// *************************************************************************** +void CToolsLogicTree::reset () +{ +// GetTreeCtrl().DeleteAllItems(); + DeleteAllItems(); + _RegionsInfo.clear (); +} + +// *************************************************************************** +void CToolsLogicTree::uninit () +{ + _MainFrame = NULL; +} + +// *************************************************************************** +void CToolsLogicTree::setTool (CToolsLogic *pTools) +{ + _ToolLogic = pTools; +} + +// *************************************************************************** +uint32 CToolsLogicTree::createNewRegion (const string &name) +{ + SRegionInfo ri; + + if (_MainFrame == NULL) + return 0; + + ri.Name = name; + ri.RegionItem = insertItemUTF8 (*this, ri.Name.c_str(), 0, 0); + //ri.PointItem = insertItemUTF8 (*this, "Points", ri.RegionItem); + //ri.PathItem = insertItemUTF8 (*this, "Splines", ri.RegionItem); + //ri.ZoneItem = insertItemUTF8 (*this, "Patatoids", ri.RegionItem); + _RegionsInfo.push_back (ri); + + return _RegionsInfo.size()-1; +} + +// *************************************************************************** +uint32 CToolsLogicTree::createNewGroup (uint32 nRegion, const string &sGroupName) +{ + SRegionInfo &rRI = _RegionsInfo[nRegion]; + + if (_MainFrame == NULL) + return 0; + + HTREEITEM newItem = insertItemUTF8 (*this, sGroupName.c_str(), 1, 1, rRI.RegionItem); + rRI.Groups.push_back (newItem); + + return rRI.Groups.size()-1; +} + +// *************************************************************************** +HTREEITEM CToolsLogicTree::addPoint (uint32 nRegion, uint32 nGroup, const string &name, bool bHide) +{ + if (bHide) + return insertItemUTF8 (*this, name.c_str(), 3, 3, _RegionsInfo[nRegion].Groups[nGroup]); + return insertItemUTF8 (*this, name.c_str(), 2, 2, _RegionsInfo[nRegion].Groups[nGroup]); +} + +// *************************************************************************** +HTREEITEM CToolsLogicTree::addPath (uint32 nRegion, uint32 nGroup, const string &name, bool bHide) +{ + if (bHide) + return insertItemUTF8 (*this, name.c_str(), 5, 5, _RegionsInfo[nRegion].Groups[nGroup]); + return insertItemUTF8 (*this, name.c_str(), 4, 4, _RegionsInfo[nRegion].Groups[nGroup]); +} + +// *************************************************************************** +HTREEITEM CToolsLogicTree::addZone (uint32 nRegion, uint32 nGroup, const string &name, bool bHide) +{ + if (bHide) + return insertItemUTF8 (*this, name.c_str(), 7, 7, _RegionsInfo[nRegion].Groups[nGroup]); + return insertItemUTF8 (*this, name.c_str(), 6, 6, _RegionsInfo[nRegion].Groups[nGroup]); +} + +// *************************************************************************** +void CToolsLogicTree::expandAll (uint32 nPos) +{ + Expand (_RegionsInfo[nPos].RegionItem, TVE_EXPAND); + for(uint32 i = 0; i < _RegionsInfo[nPos].Groups.size(); ++i) + Expand (_RegionsInfo[nPos].Groups[i], TVE_EXPAND); +} + +// *************************************************************************** +BOOL CToolsLogicTree::PreCreateWindow (CREATESTRUCT& cs) +{ + cs.style |= TVS_SHOWSELALWAYS; + if (!CTreeCtrl::PreCreateWindow(cs)) + return FALSE; + return TRUE; +} + +// *************************************************************************** + +void CToolsLogicTree::OnLButtonDown (UINT nFlags, CPoint point) +{ + // Hit item test + UINT uFlags; + HTREEITEM hItem = HitTest(point, &uFlags); + + // Item found ? + if (hItem) + { + // Remove lock mode + getMainFrame ()->setSelectionLocked (false); + + // Select + SelectItem (hItem); + CPrimitiveTreeData *data = (CPrimitiveTreeData*)GetItemData (hItem); + CDatabaseLocatorPointer locator; + + // The document + CWorldEditorDoc *doc = getDocument (); + + doc->getLocator (locator, data->Primitive); + if (data) + { + + // Begin + doc->beginModification (); + + // Unselect + if (((nFlags & MK_CONTROL) == 0) && ((nFlags & MK_SHIFT) == 0)) + doc->addModification (new CActionUnselectAll ()); + + // Shift select + if ((nFlags & MK_SHIFT) != 0) + { + // Not the same node + if (SelectMark && (SelectMark != hItem)) + { + // Same parent ? + if (GetParentItem (SelectMark) == GetParentItem (hItem)) + { + // Find the hItem + HTREEITEM current = SelectMark; + do + { + current = GetNextSiblingItem (current); + } + while (current && (current != hItem)); + + // Found ? + if (current) + { + // Select all items + current = SelectMark; + current = GetNextSiblingItem (current); + nlassert (current); + while (current != hItem) + { + // Get current data + CPrimitiveTreeData *dataCurrent = (CPrimitiveTreeData*)GetItemData (current); + CDatabaseLocatorPointer locatorCurrent; + doc->getLocator (locatorCurrent, dataCurrent->Primitive); + + // Select +// IProperty *prop; + if ((getPrimitiveEditor(dataCurrent->Primitive)->getSelected() && (nFlags & MK_CONTROL) != 0)) +// if ((dataCurrent->Primitive->getPropertyByName ("selected", prop) && (nFlags & MK_CONTROL) != 0)) + doc->addModification (new CActionUnselect (locatorCurrent)); + else + doc->addModification (new CActionSelect (locatorCurrent)); + + // Next item + current = GetNextSiblingItem (current); + nlassert (current); + } + } + else + { + // Select all items + current = SelectMark; + current = GetPrevSiblingItem (current); + nlassert (current); + while (current != hItem) + { + // Get current data + CPrimitiveTreeData *dataCurrent = (CPrimitiveTreeData*)GetItemData (current); + CDatabaseLocatorPointer locatorCurrent; + doc->getLocator (locatorCurrent, dataCurrent->Primitive); + + // Select +// IProperty *prop; + if ((getPrimitiveEditor(dataCurrent->Primitive)->getSelected() && (nFlags & MK_CONTROL) != 0)) +// if ((dataCurrent->Primitive->getPropertyByName ("selected", prop) && (nFlags & MK_CONTROL) != 0)) + doc->addModification (new CActionUnselect (locatorCurrent)); + else + doc->addModification (new CActionSelect (locatorCurrent)); + + // Next item + current = GetPrevSiblingItem (current); + nlassert (current); + } + } + } + } + } + + // Select +// IProperty *prop; + if ((getPrimitiveEditor(data->Primitive)->getSelected() && (nFlags & MK_CONTROL) != 0)) +// if ((data->Primitive->getPropertyByName ("selected", prop) && (nFlags & MK_CONTROL) != 0)) + doc->addModification (new CActionUnselect (locator)); + else + { + // Get the path of selected primitive and store it + std::string path; + doc->getFilePath(locator.getDatabaseIndex(), path); + doc->setPathOfSelectedPrimitive(path); + doc->addModification (new CActionSelect (locator)); + } + + // End + doc->endModification (); + + + // we save the property dialog which was holding the old selection + CDialogProperties* pDlg = NULL; + list::iterator it = PropertiesDialogs.begin(); + bool ok = false; + + while ( !ok && ( it != PropertiesDialogs.end() ) ) + { + if ( (*it)->equalsSelection( Selection ) ) + { + pDlg = (*it); + ok = true; + } + + it++; + } + + // Update data + getMainFrame ()->updateData (); + + if ( ( pDlg ) && ! ( GetAsyncKeyState( VK_MENU ) & 0x8000 ) ) + { + // is there already a property dialog with the new selection ? + CDialogProperties *pNewSelectionDlg = NULL; + it = PropertiesDialogs.begin(); + bool ok = false; + + while ( !ok && ( it != PropertiesDialogs.end() ) ) + { + if ( (*it)->equalsSelection( Selection ) ) + { + pNewSelectionDlg = (*it); + ok = true; + } + + it++; + } + + if ( pNewSelectionDlg ) + pNewSelectionDlg->SetFocus(); + else + pDlg->changeSelection (Selection); + + } + } + + // No shift select + if ((nFlags & MK_SHIFT) == 0) + // New mark + SelectMark = hItem; + } + + // Call previous method + CTreeCtrl::OnLButtonDown (nFlags, point); +} + +// *************************************************************************** + +void CToolsLogicTree::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + // Hit item test + UINT uFlags; + HTREEITEM hItem = HitTest(point, &uFlags); + + // Item found ? + if (hItem) + { + // Remove lock mode + getMainFrame ()->setSelectionLocked (false); + + // The docmuent + CWorldEditorDoc *doc = getDocument (); + + // Select + SelectItem (hItem); + CPrimitiveTreeData *data = (CPrimitiveTreeData*)GetItemData (hItem); + CDatabaseLocatorPointer locator; + doc->getLocator (locator, data->Primitive); + if (data) + { + // The docmuent + CWorldEditorDoc *doc = getDocument (); + + // Begin + doc->beginModification (); + + // Unselect + if ((nFlags & MK_CONTROL) == 0) + doc->addModification (new CActionUnselectAll ()); + + // Select + doc->addModification (new CActionSelect (locator)); + + // End + doc->endModification (); + + // Update data + getMainFrame ()->updateData (); + + // Call properties + _MainFrame->OnEditProperties(); + } + } + + // New mark + SelectMark = hItem; +} + +// *************************************************************************** +void CToolsLogicTree::OnRButtonDown (UINT nFlags, CPoint point) +{ + // Hit item test + UINT uFlags; + HTREEITEM hItem = HitTest(point, &uFlags); + + // The docmuent + CWorldEditorDoc *doc = getDocument (); + + // Item found ? + if (hItem) + { + SelectItem (hItem); + CPrimitiveTreeData *data = (CPrimitiveTreeData*)GetItemData (hItem); + CDatabaseLocatorPointer locator; + doc->getLocator (locator, data->Primitive); + if (data) + { + // The docmuent + CWorldEditorDoc *doc = getDocument (); + + // Begin + doc->beginModification (); + + // Unselect + nlassert (data->Primitive); +// IProperty *prop; + if (((nFlags & MK_CONTROL) == 0) && (!getPrimitiveEditor(data->Primitive)->getSelected())) +// if (((nFlags & MK_CONTROL) == 0) && (!data->Primitive->getPropertyByName ("selected", prop))) + doc->addModification (new CActionUnselectAll ()); + + // Select + doc->addModification (new CActionSelect (locator)); + + // End + doc->endModification (); + + // Update data + getMainFrame ()->updateData (); + } + } + + // New mark + SelectMark = hItem; + + // Menu creation + ClientToScreen (&point); + getMainFrame ()->createContextMenu (this, point, false); +} + +// *************************************************************************** +void CToolsLogicTree::OnSelChanged () +{ + HTREEITEM hItem = GetSelectedItem(); + HTREEITEM hParent = GetParentItem (hItem); + + if (hItem != NULL) + { + // Select the item + Select(hItem, TVGN_CARET); + } +} + +// *************************************************************************** +// Contextual Menu : Region +// *************************************************************************** + +// *************************************************************************** +void CToolsLogicTree::OnMenuRegionCreateGroup () +{ + HTREEITEM item = GetSelectedItem (); + HTREEITEM parent = GetParentItem (item); + + // Go to the Region Item + while (parent != NULL) + { + item = parent; + parent = GetParentItem (item); + } + + for (uint32 i = 0; i < _RegionsInfo.size(); ++i) + if (_RegionsInfo[i].RegionItem == item) + { + HTREEITEM newGroup = insertItemUTF8 (*this, "New Group", 1, 1, item); + Expand (item, TVE_EXPAND); + Expand (newGroup, TVE_EXPAND); + } + Invalidate (); +} + +// *************************************************************************** + +void CToolsLogicTree::OnMenuRegionHideAll () +{ + HTREEITEM itemRegion = GetSelectedItem (); + for (uint32 i = 0; i < _RegionsInfo.size(); ++i) + if (_RegionsInfo[i].RegionItem == itemRegion) + { + HTREEITEM itemGroup = GetChildItem (itemRegion); + while (itemGroup != NULL) + { + HTREEITEM itemPrim = GetChildItem (itemGroup); + while (itemPrim != NULL) + { + int nImg, nSelImg; + GetItemImage (itemPrim, nImg, nSelImg); + if ((nImg == 2) || (nImg == 4) || (nImg == 6)) + nImg = nImg + 1; + SetItemImage (itemPrim, nImg, nImg); + + itemPrim = GetNextItem (itemPrim, TVGN_NEXT); + } + itemGroup = GetNextItem (itemGroup, TVGN_NEXT); + } + + break; + } +} + +// *************************************************************************** +void CToolsLogicTree::OnMenuRegionUnhideAll () +{ + HTREEITEM itemRegion = GetSelectedItem (); + for (uint32 i = 0; i < _RegionsInfo.size(); ++i) + if (_RegionsInfo[i].RegionItem == itemRegion) + { + + HTREEITEM itemGroup = GetChildItem (itemRegion); + while (itemGroup != NULL) + { + HTREEITEM itemPrim = GetChildItem (itemGroup); + while (itemPrim != NULL) + { + int nImg, nSelImg; + GetItemImage (itemPrim, nImg, nSelImg); + if ((nImg == 3) || (nImg == 5) || (nImg == 7)) + nImg = nImg - 1; + SetItemImage (itemPrim, nImg, nImg); + + itemPrim = GetNextItem (itemPrim, TVGN_NEXT); + } + itemGroup = GetNextItem (itemGroup, TVGN_NEXT); + } + break; + } +} + +// *************************************************************************** +void CToolsLogicTree::OnMenuRegionHideType () +{ + HTREEITEM item = GetSelectedItem (); + for (uint32 i = 0; i < _RegionsInfo.size(); ++i) + if (_RegionsInfo[i].RegionItem == item) + { + CTypeSelDlg dial(this); + dial._TypesInit = &(_MainFrame->_Environnement.Types); + if (dial.DoModal() == IDOK) + { + } + break; + } +} + +// *************************************************************************** +void CToolsLogicTree::OnMenuRegionUnhideType () +{ + HTREEITEM item = GetSelectedItem (); + for (uint32 i = 0; i < _RegionsInfo.size(); ++i) + if (_RegionsInfo[i].RegionItem == item) + { + CTypeSelDlg dial(this); + dial._TypesInit = &(_MainFrame->_Environnement.Types); + if (dial.DoModal() == IDOK) + { + } + break; + } +} + +// *************************************************************************** +// Contextual Menu : Group +// *************************************************************************** + +// *************************************************************************** +void CToolsLogicTree::OnMenuGroupCreatePoint() +{ + HTREEITEM itemGroup = GetSelectedItem (); + HTREEITEM itemRegion = GetParentItem (itemGroup); + uint32 i; + CCreateDialog dialog (this); + dialog.TypesForInit = &_MainFrame->_Environnement.Types; + + for (i = 0; i < _RegionsInfo.size(); ++i) + if (_RegionsInfo[i].RegionItem == itemRegion) + { + dialog.setRegionName (_RegionsInfo[i].Name); + break; + } + + dialog.MainFrame = _MainFrame; + + if (dialog.DoModal () == IDOK) + if (strlen(dialog.Name) > 0) + { + HTREEITEM newItem = insertItemUTF8 (*this, dialog.Name, 2, 2, itemGroup); + Expand (itemGroup, TVE_EXPAND); + // Create the newItem + for (i = 0; i < _RegionsInfo.size(); ++i) + if (_RegionsInfo[i].RegionItem == itemRegion) + { + } + // Callback handling + _MainFrame->primZoneModified(); + } + Invalidate (); +} + +// *************************************************************************** +void CToolsLogicTree::OnMenuGroupCreatePath() +{ + HTREEITEM itemGroup = GetSelectedItem (); + HTREEITEM itemRegion = GetParentItem (itemGroup); + uint32 i; + CCreateDialog dialog (this); + dialog.TypesForInit = &_MainFrame->_Environnement.Types; + + for (i = 0; i < _RegionsInfo.size(); ++i) + if (_RegionsInfo[i].RegionItem == itemRegion) + { + dialog.setRegionName (_RegionsInfo[i].Name); + break; + } + + dialog.MainFrame = _MainFrame; + + if (dialog.DoModal () == IDOK) + if (strlen(dialog.Name) > 0) + { + HTREEITEM newItem = insertItemUTF8 (*this, dialog.Name, 4, 4, itemGroup); + Expand (itemGroup, TVE_EXPAND); + // Create the newItem + for (i = 0; i < _RegionsInfo.size(); ++i) + if (_RegionsInfo[i].RegionItem == itemRegion) + { + } + // Callback handling + _MainFrame->primZoneModified(); + } + Invalidate (); +} + +// *************************************************************************** +void CToolsLogicTree::OnMenuGroupCreateZone() +{ + HTREEITEM itemGroup = GetSelectedItem (); + HTREEITEM itemRegion = GetParentItem (itemGroup); + uint32 i; + CCreateDialog dialog (this); + dialog.TypesForInit = &_MainFrame->_Environnement.Types; + + for (i = 0; i < _RegionsInfo.size(); ++i) + if (_RegionsInfo[i].RegionItem == itemRegion) + { + dialog.setRegionName (_RegionsInfo[i].Name); + break; + } + + dialog.MainFrame = _MainFrame; + + if (dialog.DoModal () == IDOK) + if (strlen(dialog.Name) > 0) + { + HTREEITEM newItem = insertItemUTF8 (*this, dialog.Name, 6, 6, itemGroup); + Expand (itemGroup, TVE_EXPAND); + // Create the newItem + for (i = 0; i < _RegionsInfo.size(); ++i) + if (_RegionsInfo[i].RegionItem == itemRegion) + { + } + // Callback handling + _MainFrame->primZoneModified(); + } + Invalidate (); +} + +// *************************************************************************** +void CToolsLogicTree::OnMenuGroupDelete () +{ + HTREEITEM itemGroup = GetSelectedItem (); + HTREEITEM itemRegion; + HTREEITEM itemRoot; + + // Go to the Region Item + itemRegion = itemRoot = itemGroup; + while (itemRoot != NULL) + { + itemRegion = itemRoot; + itemRoot = GetParentItem (itemRegion); + } + + for (uint32 i = 0; i < _RegionsInfo.size(); ++i) + if (_RegionsInfo[i].RegionItem == itemRegion) + { + HTREEITEM hChildItem = GetChildItem (itemGroup); + while (hChildItem != NULL) + { + HTREEITEM hNextItem = GetNextItem (hChildItem, TVGN_NEXT); + + DeleteItem (hChildItem); + OnSelChanged (); + + hChildItem = hNextItem; + } + for (uint32 j = 0; j < _RegionsInfo[i].Groups.size(); ++j) + if (_RegionsInfo[i].Groups[j] == itemGroup) + { + for (uint32 k = j+1; k < _RegionsInfo[i].Groups.size(); ++k) + _RegionsInfo[i].Groups[k-1] = _RegionsInfo[i].Groups[k]; + _RegionsInfo[i].Groups.resize (_RegionsInfo[i].Groups.size()-1); + } + DeleteItem (itemGroup); + // Callback handling + _MainFrame->primZoneModified(); + } + +} + +// *************************************************************************** +void CToolsLogicTree::OnMenuGroupProperties() +{ + CEditStringDlg es(this); + HTREEITEM hItem = GetSelectedItem (); + es.Name = GetItemText (hItem); + if (es.DoModal() == IDOK) + { + setItemTextUTF8 (*this, hItem, es.Name); + + HTREEITEM hChildItem = GetChildItem(hItem); + while (hChildItem != NULL) + { + HTREEITEM hNextItem = GetNextItem (hChildItem, TVGN_NEXT); + hChildItem = hNextItem; + } + } +} + +// *************************************************************************** +void CToolsLogicTree::OnMenuGroupHide() +{ + HTREEITEM itemGroup = GetSelectedItem (); + HTREEITEM itemRegion = GetParentItem (itemGroup); + + HTREEITEM hChildItem = GetChildItem(itemGroup); + while (hChildItem != NULL) + { + HTREEITEM hNextItem = GetNextItem (hChildItem, TVGN_NEXT); + + int nImg, nSelImg; + GetItemImage (hChildItem, nImg, nSelImg); + if ((nImg == 2) || (nImg == 4) || (nImg == 6)) + nImg = nImg + 1; + SetItemImage (hChildItem, nImg, nImg); + + hChildItem = hNextItem; + } +} + +// *************************************************************************** +void CToolsLogicTree::OnMenuGroupUnhide() +{ + HTREEITEM itemGroup = GetSelectedItem (); + HTREEITEM itemRegion = GetParentItem (itemGroup); + + HTREEITEM hChildItem = GetChildItem(itemGroup); + while (hChildItem != NULL) + { + HTREEITEM hNextItem = GetNextItem (hChildItem, TVGN_NEXT); + + int nImg, nSelImg; + GetItemImage (hChildItem, nImg, nSelImg); + if ((nImg == 3) || (nImg == 5) || (nImg == 7)) + nImg = nImg - 1; + SetItemImage (hChildItem, nImg, nImg); + + hChildItem = hNextItem; + } +} + +// *************************************************************************** +void CToolsLogicTree::OnMenuGroupTransfertAppend () +{ + vector vTemp; + + HTREEITEM itemGroup = GetSelectedItem (); + HTREEITEM hChildItem = GetChildItem(itemGroup); + while (hChildItem != NULL) + { + HTREEITEM hNextItem = GetNextItem (hChildItem, TVGN_NEXT); + + vTemp.push_back((LPCSTR)GetItemText(hChildItem)); + + hChildItem = hNextItem; + } + + /* if (_MainFrame->_MasterCB != NULL) + _MainFrame->multiTransfert(vTemp, true); */ +} + +// *************************************************************************** +void CToolsLogicTree::OnMenuGroupTransfertReplace () +{ + vector vTemp; + + HTREEITEM itemGroup = GetSelectedItem (); + HTREEITEM hChildItem = GetChildItem(itemGroup); + while (hChildItem != NULL) + { + HTREEITEM hNextItem = GetNextItem (hChildItem, TVGN_NEXT); + + vTemp.push_back((LPCSTR)GetItemText(hChildItem)); + + hChildItem = hNextItem; + } + + /* if (_MainFrame->_MasterCB != NULL) + _MainFrame->multiTransfert(vTemp, false); */ +} + +// *************************************************************************** +// Contextual Menu : Prim +// *************************************************************************** + +void CToolsLogicTree::OnMenuPrimDelete() +{ + _MainFrame->deletePrimitive (false, "Delete"); +} + +// *************************************************************************** + +void CToolsLogicTree::OnProjectNewPrimitive () +{ + _MainFrame->OnProjectNewPrimitive (); +} + +// *************************************************************************** + +void CToolsLogicTree::OnViewShow () +{ + _MainFrame->OnViewShow (); +} + +// *************************************************************************** + +void CToolsLogicTree::OnViewHide () +{ + _MainFrame->OnViewHide (); +} + +// *************************************************************************** + +void CToolsLogicTree::OnEditExpand () +{ + _MainFrame->OnEditExpand (); +} + +// *************************************************************************** + +void CToolsLogicTree::OnEditCollapse () +{ + _MainFrame->OnEditCollapse (); +} + +// *************************************************************************** + +void CToolsLogicTree::OnEditSelectChildren () +{ + _MainFrame->OnEditSelectChildren (); +} + +// *************************************************************************** + +void CToolsLogicTree::OnMenuPrimProperties() +{ + // Open the property dialog + _MainFrame->OnEditProperties (); +} + +// *************************************************************************** + +void CToolsLogicTree::OnAddPrimitive (UINT nID) +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Begin modification + doc->beginModification (); + + // Only one selection ? + nlassert (Selection.size () == 1); + nlassert (Selection.front ()); + + // What class is it ? + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*(Selection.front ())); + nlassert (primClass); + uint childId = nID - ID_EDIT_CREATE_BEGIN; + + // Get the child class + CDatabaseLocatorPointer insert; + doc->getLocator (insert, Selection.front ()); + CDatabaseLocator dest; + insert.appendChild (dest); + + // Position on the Display + CDisplay *display = getDisplay (); + float delta = (float)DELTA_POS_ADD_PRIMITIVE * (display->_CurViewMax.x - display->_CurViewMin.x) / (float)display->getWidth (); + CVector pos = (display->_CurViewMin + display->_CurViewMax)/2; + if (doc->addModification (new CActionAddPrimitiveByClass (dest, primClass->DynamicChildren[childId].ClassName.c_str (), pos, delta, + primClass->DynamicChildren[childId].Parameters))) + { + // Unselect all + doc->addModification (new CActionUnselectAll ()); + + // Select it + doc->addModification (new CActionSelect (dest)); + } + + // End modification + doc->endModification (); + + // Update the data + _MainFrame->updateData (); +} + +// *************************************************************************** + +void CToolsLogicTree::OnGeneratePrimitive (UINT nID) +{ + _MainFrame->OnGeneratePrimitive (nID); +} + +// *************************************************************************** + +void CToolsLogicTree::OnOpenFile (UINT nID) +{ + _MainFrame->OnOpenFile (nID); +} + +// *************************************************************************** +// CToolsLogic +// *************************************************************************** + +// *************************************************************************** + +BEGIN_MESSAGE_MAP (CToolsLogic, CFormView) + ON_WM_CREATE() + ON_WM_SIZE () + ON_WM_PAINT () + ON_BN_CLICKED (IDC_NEW_PATAT, OnNewPatat) + ON_BN_CLICKED (IDC_NEW_GROUP, OnNewGroup) +END_MESSAGE_MAP() + +// *************************************************************************** + +IMPLEMENT_DYNCREATE(CToolsLogic, CFormView) + +// *************************************************************************** +CToolsLogic::CToolsLogic() : CFormView(IDD_TOOLS_LOGIC) +{ + _Tree = NULL; + _TreeCreated = false; +} + +// *************************************************************************** +CToolsLogicTree *CToolsLogic::GetTreeCtrl() +{ + if (_TreeCreated) + return _Tree; + return NULL; +} + +// *************************************************************************** +void CToolsLogic::init (CMainFrame *pMF) +{ + _MainFrame = pMF; + if (GetTreeCtrl() != NULL) + GetTreeCtrl()->init (pMF); +} + +// *************************************************************************** +void CToolsLogic::reset () +{ + if (GetTreeCtrl() != NULL) + GetTreeCtrl()->reset (); +} + +// *************************************************************************** +void CToolsLogic::uninit () +{ + if (GetTreeCtrl() != NULL) + GetTreeCtrl()->uninit (); +} + +// *************************************************************************** +uint32 CToolsLogic::createNewRegion (const string &sRegionName) +{ + if (_TreeCreated) + return GetTreeCtrl()->createNewRegion (sRegionName); + return 0; +} + +// *************************************************************************** +uint32 CToolsLogic::createNewGroup (uint32 nRegion, const string &sGroupName) +{ + if (_TreeCreated) + return GetTreeCtrl()->createNewGroup (nRegion, sGroupName); + return 0; +} + +// *************************************************************************** +HTREEITEM CToolsLogic::addPoint (uint32 nRegion, uint32 nGroup, const string &name, bool bHide) +{ + if (_TreeCreated) + return GetTreeCtrl()->addPoint (nRegion, nGroup, name, bHide); + return NULL; +} + +// *************************************************************************** +HTREEITEM CToolsLogic::addPath (uint32 nRegion, uint32 nGroup, const string &name, bool bHide) +{ + if (_TreeCreated) + return GetTreeCtrl()->addPath (nRegion, nGroup, name, bHide); + return NULL; +} + +// *************************************************************************** +HTREEITEM CToolsLogic::addZone (uint32 nRegion, uint32 nGroup, const string &name, bool bHide) +{ + if (_TreeCreated) + return GetTreeCtrl()->addZone (nRegion, nGroup, name, bHide); + return NULL; +} + +// *************************************************************************** +void CToolsLogic::expandAll (uint32 nRegion) +{ + if (_TreeCreated) + GetTreeCtrl()->expandAll (nRegion); +} + +#define TREE_TOP 0 +#define TREE_LEFT 0 +#define TREE_RIGHT 0 +#define TREE_BOTTOM 0 + +// *************************************************************************** +int CToolsLogic::OnCreate (LPCREATESTRUCT lpCreateStruct) +{ +// if (CFormView::OnCreate (lpCreateStruct) == -1) +// return -1; + if (CFormView::OnCreate (lpCreateStruct) == -1) + return -1; + + ::CRect iniRect; + GetClientRect(&iniRect); + iniRect.top = TREE_TOP; iniRect.left = TREE_LEFT; + iniRect.right += TREE_RIGHT; iniRect.bottom += TREE_BOTTOM; + _Tree = new CToolsLogicTree; + _Tree->Create ( WS_VISIBLE | WS_TABSTOP | WS_CHILD + | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_HASLINES | TVS_SHOWSELALWAYS, + iniRect, this, 0x1) ; + + BOOL tIsUnicode; +#ifdef UNICODE +tIsUnicode = TreeView_SetUnicodeFormat(_Tree->m_hWnd, 1); +#else +tIsUnicode = TreeView_SetUnicodeFormat(_Tree->m_hWnd, 0); +#endif // UNICODE + + _Tree->setTool (this); + _TreeCreated = true; + + return 0; +} + +// *************************************************************************** +void CToolsLogic::OnSize (UINT nType, int cx, int cy) +{ + CFormView::OnSize (nType, cx, cy); + // Resize list ctrl to fill the whole view. + if (_TreeCreated) + { + ::CRect iniRect; + GetClientRect(&iniRect); + + iniRect.top += TREE_TOP; iniRect.left += TREE_LEFT; + iniRect.right += TREE_RIGHT; iniRect.bottom += TREE_BOTTOM; + + GetTreeCtrl()->MoveWindow (&iniRect); + } + +} + +// *************************************************************************** +void CToolsLogic::OnPaint () +{ + GetTreeCtrl()->ShowScrollBar(SB_VERT); + CFormView::OnPaint(); +} + +// *************************************************************************** +void CToolsLogic::OnNewGroup () +{ + GetTreeCtrl()->OnMenuRegionCreateGroup (); +} + +// *************************************************************************** +void CToolsLogic::OnNewPatat () +{ + CComboBox *pCB = (CComboBox*)GetDlgItem(IDC_TYPE); + CString str; + getWindowTextUTF8 (*pCB, str); + string sStr = (LPCSTR)str; +} + +// *************************************************************************** +// CCreateDialog +// *************************************************************************** + +// *************************************************************************** +BEGIN_MESSAGE_MAP(CCreateDialog, CDialog) + //{{AFX_MSG_MAP(CMainFrame) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code ! + ON_CBN_SELCHANGE(IDC_COMBOTYPE, OnSelChange) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +// *************************************************************************** +CCreateDialog::CCreateDialog (CWnd*pParent) : CDialog(IDD_CREATE_ELEMENT, pParent) +{ + Name[0] = 0; + LayerName[0] = 0; +} + +// *************************************************************************** +BOOL CCreateDialog::OnInitDialog () +{ + CDialog::OnInitDialog(); + + for (uint32 i = 0; i < TypesForInit->size(); ++i) + { + ComboType.InsertString (-1, TypesForInit->operator[](i).Name.c_str()); + } + + if (TypesForInit->size()>0) + { + if (ComboType.SelectString (0, LayerName) == CB_ERR) + ComboType.SetCurSel (0); + UpdateData(); + if (strlen(Name) == 0) + OnSelChange(); + } + + return true; +} + +// *************************************************************************** +void CCreateDialog::DoDataExchange (CDataExchange* pDX ) +{ + DDX_Control(pDX, IDC_COMBOTYPE, ComboType); + + DDX_Text(pDX, IDC_EDIT_NAME, (LPTSTR)Name, 128); + DDV_MaxChars(pDX, Name, 128); + + DDX_Text(pDX, IDC_COMBOTYPE, (LPTSTR)LayerName, 128); + DDV_MaxChars(pDX, LayerName, 128); +} + +// *************************************************************************** +void CCreateDialog::OnOK() +{ + UpdateData (); + + // If the "region_" do not exist add it + if (strncmp(RegionPost.c_str(), Name, strlen(RegionPost.c_str())) != 0) + { + char sTmp[128]; + strcpy (sTmp, RegionPost.c_str()); + strcat (sTmp, Name); + strcpy (Name, sTmp); + UpdateData (false); + } + + if (strcmp(PropName.c_str(), Name) == 0) + CDialog::OnOK(); + + CDialog::OnOK(); +} + +// *************************************************************************** +void CCreateDialog::setRegionName (const string &rn) +{ + for (uint32 i = 0; i < rn.size(); ++i) + { + if (rn[i] == '.') + { + RegionPost += '-'; + return; + } + RegionPost += rn[i]; + } + RegionPost += '-'; +} + +// *************************************************************************** +void CCreateDialog::OnSelChange () +{ + int cs = ComboType.GetCurSel(); + CString sTmp; + ComboType.GetLBText (cs, sTmp); + + if (PropType == (LPCSTR)sTmp) + { + strcpy (Name, PropName.c_str()); + } + else + { + strcpy (Name, RegionPost.c_str()); + strcat (Name, (LPCSTR)sTmp); + strcat (Name, "-"); + } + + UpdateData (false); + Invalidate (); +} + +// *************************************************************************** +// CEditStringDlg +// *************************************************************************** + +// *************************************************************************** +CEditStringDlg::CEditStringDlg(CWnd*pParent) : CDialog(IDD_EDIT_STRING, pParent) +{ + Name = _T(""); +} + +// *************************************************************************** +BOOL CEditStringDlg::OnInitDialog () +{ + CDialog::OnInitDialog(); + + UpdateData(); + + return TRUE; +} + +// *************************************************************************** +void CEditStringDlg::DoDataExchange (CDataExchange* pDX ) +{ + DDX_Text(pDX, IDC_EDIT_NAME, Name); +} + +// *************************************************************************** +void CEditStringDlg::OnOK() +{ + UpdateData (); + CDialog::OnOK(); +} + +// *************************************************************************** + +// Returns the index-th first level tree node +void selectItem (CTreeCtrl &tree, uint index) +{ + HTREEITEM item = tree.GetRootItem (); + while (index--) + { + item = tree.GetNextSiblingItem (item); + nlassert (item); + } + tree.SelectItem (item); +} + +// *************************************************************************** + +BOOL CToolsLogic::OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult ) +{ + int idCtrl = (int) wParam; + LPNMHDR pnmh = (LPNMHDR) lParam; + + // The document + CWorldEditorDoc *doc = getDocument (); + + switch (pnmh->code) + { + case TVN_SELCHANGED: + { + // Select the good item + LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) lParam; + + // By keyboard ? + + if ( pnmtv->action == TVC_BYKEYBOARD )// || + // ( ( GetAsyncKeyState( VK_L)) && !( GetAsyncKeyState( VK_MENU ) & 0x8000 ) ) ) + { + // we save the current properties dialog + CDialogProperties *pDlg = NULL; + + list::iterator it = PropertiesDialogs.begin(); + bool ok = false; + + while ( !ok && ( it != PropertiesDialogs.end() ) ) + { + if ( (*it)->equalsSelection( Selection ) ) + { + pDlg = (*it); + ok = true; + } + + it++; + } + + // Remove lock mode + getMainFrame ()->setSelectionLocked (false); + + // Get the item data + CPrimitiveTreeData *data = (CPrimitiveTreeData*)_Tree->GetItemData (pnmtv->itemNew.hItem); + CDatabaseLocatorPointer locator; + doc->getLocator (locator, data->Primitive); + + // Begin + doc->beginModification (); + + // Unselect + doc->addModification (new CActionUnselectAll ()); + + // Something to select ? + if (data) + { + // Select + doc->addModification (new CActionSelect (locator)); + } + + // End + doc->endModification (); + + // Update data + getMainFrame ()->updateData (); + + if ( pDlg ) + pDlg->changeSelection (Selection); + + // New mark + _Tree->SelectMark = pnmtv->itemNew.hItem; + + + SetFocus(); + } + } + break; + case TVN_ITEMEXPANDED: + { + // Take the item + LPNMTREEVIEW pnmtv = (LPNMTREEVIEW) lParam; + + // Get the item data + CPrimitiveTreeData *data = (CPrimitiveTreeData*)_Tree->GetItemData (pnmtv->itemNew.hItem); + + // Don't make an action (don't modify the document) when expand / collapse the list.. + + // Unselect + + getPrimitiveEditor(data->Primitive)->setExpanded((pnmtv->action&TVE_EXPAND)!=0); +// const_cast (data->Primitive)->Expanded = (pnmtv->action&TVE_EXPAND)!=0; + } + break; + case TVN_KEYDOWN: + { + // Get selected item + HTREEITEM item = _Tree->GetSelectedItem (); + if (item) + { + // Take the item + LPNMTVKEYDOWN pnmtv = (LPNMTVKEYDOWN) lParam; + + // Key down + CTRL ? + if ( (pnmtv->wVKey == VK_UP) && (GetAsyncKeyState (VK_CONTROL) & 0x8000)) + { + // Get the item data + CPrimitiveTreeData *data = (CPrimitiveTreeData*)_Tree->GetItemData (item); + CDatabaseLocatorPointer locator; + CDatabaseLocatorPointer root; + doc->getLocator (locator, data->Primitive); + root.getRoot (locator.getDatabaseIndex()); + + // Get the previous locator + if (!(root == locator)) + { + // Get the previous locator + CDatabaseLocatorPointer previousLocator = locator; + if (previousLocator.previousChild ()) + { + // Begin + doc->beginModification (); + + // Copy the primitive + const IPrimitive *copy = data->Primitive->copy (); + + // Remove the primitive + doc->addModification (new CActionDelete (locator)); + + // Add the primitive at the previous position + doc->addModification (new CActionAddPrimitive (*copy, previousLocator)); + doc->addModification (new CActionSelect (previousLocator)); + delete copy; + + + + // End + doc->endModification (); + + // Update data + getMainFrame ()->updateData (); + + // Get selected item + doc->getLocator (previousLocator, locator); + nlverify (previousLocator.previousChild ()); + IPrimitiveEditor *primitiveEditor = dynamic_cast (const_cast (previousLocator.Primitive)); + _Tree->SelectItem (primitiveEditor->_TreeItem); + } + } + else + { + // Not the top primitive + uint index = locator.getDatabaseIndex (); + if (index > 0) + { + // Begin + doc->beginModification (); + + // Exchange the primitives + doc->addModification (new CActionXChgDatabaseElement (index-1)); + + // End + doc->endModification (); + + // Update data + getMainFrame ()->updateData (); + + selectItem (*_Tree, index-1); + } + } + } + // Key up + CTRL ? + else if ( (pnmtv->wVKey == VK_DOWN) && (GetAsyncKeyState (VK_CONTROL) & 0x8000)) + { + // Get the item data + CPrimitiveTreeData *data = (CPrimitiveTreeData*)_Tree->GetItemData (item); + CDatabaseLocatorPointer locator; + CDatabaseLocatorPointer root; + doc->getLocator (locator, data->Primitive); + root.getRoot (locator.getDatabaseIndex()); + + // Get the previous locator + if (!(root == locator)) + { + CDatabaseLocatorPointer nextLocator = locator; + if (nextLocator.nextChild ()) + { + // Begin + doc->beginModification (); + + // Copy the primitive + const IPrimitive *copy = data->Primitive->copy (); + + // Remove the primitive + doc->addModification (new CActionDelete (locator)); + + // Add the primitive at the previous position + doc->addModification (new CActionAddPrimitive (*copy, nextLocator)); + doc->addModification (new CActionSelect (nextLocator)); + delete copy; + + // End + doc->endModification (); + + // Update data + getMainFrame ()->updateData (); + + // Get selected item + doc->getLocator (nextLocator, locator); + nlverify (nextLocator.nextChild ()); + IPrimitiveEditor *primitiveEditor = dynamic_cast (const_cast (nextLocator.Primitive)); + _Tree->SelectItem (primitiveEditor->_TreeItem); + } + } + else + { + // Not the top primitive + uint index = locator.getDatabaseIndex (); + if (index+1 < doc->getNumDatabaseElement ()) + { + // Begin + doc->beginModification (); + + // Exchange the primitives + doc->addModification (new CActionXChgDatabaseElement (index)); + + // End + doc->endModification (); + + // Update data + getMainFrame ()->updateData (); + + selectItem (*_Tree, index+1); + } + } + } + } + } + break; + } + + return CFormView::OnNotify( wParam, lParam, pResult ); +} + +// *************************************************************************** + +HTREEITEM CToolsLogic::addPrimitive (HTREEITEM parentItem, HTREEITEM lastBrother, const CDatabaseLocatorPointer &locator) +{ + HTREEITEM treeItem = insertItemUTF8 (*_Tree, "", parentItem, lastBrother); + + // Get the primitives + CWorldEditorDoc *doc = getDocument (); + const NLLIGO::CPrimitives *primitives = &(doc->getDatabaseElements (locator.getDatabaseIndex ())); + + // Set the item data + _Tree->SetItemData (treeItem, (DWORD)new CPrimitiveTreeData (primitives, locator.Primitive)); + + // Expand parent ? + if (parentItem != TVI_ROOT) + { + CPrimitiveTreeData *parentData = (CPrimitiveTreeData *)_Tree->GetItemData (parentItem); + nlassert (parentData); + _Tree->Expand (parentItem, getPrimitiveEditor(parentData->Primitive)->getExpanded()?TVE_EXPAND:TVE_COLLAPSE); + } + + return treeItem; +} + +// *************************************************************************** + +void CToolsLogic::updatePrimitive (HTREEITEM item, const CDatabaseLocatorPointer &locator) +{ + if (locator.Primitive) + { + // Is selected ? +// IProperty *prop; + _Tree->SetItemState (item, getPrimitiveEditor(locator.Primitive)->getSelected()?TVIS_BOLD:0, TVIS_BOLD); +// _Tree->SetItemState (item, locator.Primitive->getPropertyByName ("selected", prop)?TVIS_BOLD:0, TVIS_BOLD); + + // Root ? + if (locator.Primitive->getParent ()) + { + // Set the name + string name; + string className; + locator.Primitive->getPropertyByName ("name", name); + locator.Primitive->getPropertyByName ("class", className); + const CPrimitiveClass *pc = theApp.Config.getPrimitiveClass(className.c_str()); + if (pc && pc->Type == CPrimitiveClass::Alias) + { + const CPrimAlias *pa = dynamic_cast(locator.Primitive); + nlassert(pa != NULL); + + name += " "+toString(pa->getAlias()); + } + setItemTextUTF8 (*_Tree, item, name.c_str ()); + } + else + { + // Set the primitive name + string name; + getDocument ()->getPrimitiveDisplayName (name, locator.getDatabaseIndex ()); + setItemTextUTF8 (*_Tree, item, name.c_str ()); + } + + // Expand / collapse it + _Tree->Expand (item, getPrimitiveEditor(locator.Primitive)->getExpanded()?TVE_EXPAND:TVE_COLLAPSE); + + // Hidden ? +// string temp; + bool hidden = getPrimitiveEditor(locator.Primitive)->getHidden(); +// bool hidden = locator.Primitive->getPropertyByName ("hidden", temp); + + // Class of primitive ? + bool imagesSets = false; + string className; + + if (locator.Primitive->getPropertyByName ("class", className)) + { + // Look for open / close icones.. + int _hidden = theApp.ImageList.getImage ((className+"_hidden").c_str ()); + int opened = theApp.ImageList.getImage ((className+"_opened").c_str ()); + int closed = theApp.ImageList.getImage ((className+"_closed").c_str ()); + if ((hidden && (_hidden != -1)) || ((opened != -1) && (closed != -1))) + { + // Set the images + _Tree->SetItemImage (item, hidden?_hidden:closed, hidden?_hidden:opened); + imagesSets = true; + } + else + { + // Look for open / close icones.. + int image = theApp.ImageList.getImage (className.c_str ()); + if (image != -1) + { + // Set the images + _Tree->SetItemImage (item, image, image); + imagesSets = true; + } + } + } + + // Icon sets or error ? + // Set the image, If there is an error, force to set an icon + const IPrimitiveEditor *node = dynamic_cast (locator.Primitive); + if (!imagesSets || (node && node->_Error != IPrimitiveEditor::NoError)) + { + // Root ? + if (locator.Primitive->getParent () == NULL) + { + if (node && node->_Error != IPrimitiveEditor::NoError) + { + _Tree->SetItemImage (item, theApp.ImageList.getImage (IDI_ERROR_STRUCTURE), theApp.ImageList.getImage (IDI_ERROR_STRUCTURE)); + } + else + { + _Tree->SetItemImage (item, theApp.ImageList.getImage (hidden?IDI_ROOT_HIDDEN:IDI_ROOT_CLOSED), theApp.ImageList.getImage (hidden?IDI_ROOT_HIDDEN:IDI_ROOT_OPENED)); + } + } + else + { + // What kind of class ? + if (node) + { + if (node->_Error != IPrimitiveEditor::NoError) + { + _Tree->SetItemImage (item, theApp.ImageList.getImage (IDI_ERROR_STRUCTURE), theApp.ImageList.getImage (IDI_ERROR_STRUCTURE)); + } + else + { + // Some children ? + if (locator.Primitive->getNumChildren ()) + _Tree->SetItemImage (item, theApp.ImageList.getImage (hidden?IDI_FOLDER_HIDDEN:IDI_FOLDER_CLOSED), theApp.ImageList.getImage (hidden?IDI_FOLDER_HIDDEN:IDI_FOLDER_OPENED)); + else + _Tree->SetItemImage (item, theApp.ImageList.getImage (hidden?IDI_PROPERTY_HIDDEN:IDI_PROPERTY_CLOSED), theApp.ImageList.getImage (hidden?IDI_PROPERTY_HIDDEN:IDI_PROPERTY_OPENED)); + } + } + else + { + const CPrimPointEditor *point = dynamic_cast (locator.Primitive); + if (point) + _Tree->SetItemImage (item, theApp.ImageList.getImage (hidden?IDI_POINT_HIDDEN:IDI_POINT_CLOSED), theApp.ImageList.getImage (hidden?IDI_POINT_HIDDEN:IDI_POINT_OPENED)); + else + { + const CPrimPathEditor *path = dynamic_cast (locator.Primitive); + if (path) + _Tree->SetItemImage (item, theApp.ImageList.getImage (hidden?IDI_LINE_HIDDEN:IDI_LINE_CLOSED), theApp.ImageList.getImage (hidden?IDI_LINE_HIDDEN:IDI_LINE_OPENED)); + else + { + const CPrimZoneEditor *node = dynamic_cast (locator.Primitive); + if (node && node->_Error != IPrimitiveEditor::NoError) + { + _Tree->SetItemImage (item, theApp.ImageList.getImage (IDI_ERROR_STRUCTURE), theApp.ImageList.getImage (IDI_ERROR_STRUCTURE)); + } + else + { + safe_cast (locator.Primitive); + _Tree->SetItemImage (item, theApp.ImageList.getImage (hidden?IDI_ZONE_HIDDEN:IDI_ZONE_CLOSED), theApp.ImageList.getImage (hidden?IDI_ZONE_HIDDEN:IDI_ZONE_OPENED)); + } + } + } + } + } + } + } + else + { + // Not bold + _Tree->SetItemState (item, 0, TVIS_BOLD); + } + + // Remove mark + _Tree->SelectMark = NULL; +} + +// *************************************************************************** + +void CToolsLogic::ensureVisible (IPrimitiveEditor *primitive) +{ + if (primitive->_TreeItem) + _Tree->EnsureVisible (primitive->_TreeItem); +} + +// *************************************************************************** + +void CToolsLogicTree::OnRenameSelected() +{ + // todo rebranch rename selection +/* // Not empty ? + if (!Selection.empty ()) + { + bool modified = false; + CWorldEditorDoc *doc = getDocument (); + + // For each selected primitives + std::list::iterator ite1 = Selection.begin (); + while (ite1 != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite1); + + // Primitive ? + const IPrimitive *primitive = locator.Primitive; + if (primitive) + { + // Get the class name + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*primitive); + // Does the class uses Autoname ? + if (primClass && primClass->Autoname != "") + { + // do we have a "name" field + const IProperty *propName; + if (primitive->getPropertyByName ("name", propName)) + { + // we collect all properties of the class in a parameter list + set parameterList; + for (uint p=0; pParameters.size (); p++) + { + // Is the parameter visible ? + if (primClass->Parameters[p].Visible) + { + // we avoid the reserved keywords + if (primClass->Parameters[p].Name != "name" && + primClass->Parameters[p].Name != "hidden" && + primClass->Parameters[p].Name != "selected" && + primClass->Parameters[p].Name != "class" && + primClass->Parameters[p].Name != "") + { + parameterList.insert (primClass->Parameters[p]); + } + } + } + // we rename the string in one pass + CString Name = primClass->Autoname.c_str(); + + set::iterator ite2 = parameterList.begin (); + while (ite2 != parameterList.end ()) + { + string result; + CString OriginalName = ite2->Name.c_str(); + if (ite2->Type == CPrimitiveClass::CParameter::String || + ite2->Type == CPrimitiveClass::CParameter::ConstString) + { + primitive->getPropertyByName (OriginalName, result); + } + else if (ite2->Type == CPrimitiveClass::CParameter::StringArray) + { + const IProperty *propName; + if (primitive->getPropertyByName (OriginalName, propName)) + { + const CPropertyStringArray *propStringString = dynamic_cast (propName); + result = propStringString->StringArray[0]; + } + else + { + result = "undefined"; + } + } + + OriginalName = "$"+OriginalName+"$"; + Name.Replace(OriginalName, result.c_str()); + ++ite2; + } + + // now, we overwrite the original name + // Create a default property + string value; + value = Name; + if (!modified) + { + doc->beginModification (); + modified = true; + } + doc->addModification (new CActionSetPrimitivePropertyString (locator, "name", value.c_str(), false)); + } + + } + } + ite1++; + } + if (modified) + { + doc->endModification (); + getMainFrame ()->updateData (); + } + }*/ +} + +// *************************************************************************** + +void CToolsLogicTree::OnRepairSelected() +{ + // Not empty ? + if (!Selection.empty ()) + { + bool modified = false; + CWorldEditorDoc *doc = getDocument (); + + // For each selected primitives + std::list::iterator ite1 = Selection.begin (); + while (ite1 != Selection.end ()) + { + CDatabaseLocatorPointer locator; + doc->getLocator (locator, *ite1); + + const IPrimitive *primitive = locator.Primitive; + if (primitive) + { + string className; + bool Success; + Success = primitive->getPropertyByName ("class", className); + + if (!Success) + { + // is this the root node ? + const IPrimitive *parent = primitive->getParent(); + if (!parent) + { + // if no parent, we have a root node + className = "root"; + Success = true; + } + } + if (Success) + { + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (className.c_str ()); + if (primClass) + { + uint CountStaticChildren = 0; + CDatabaseLocatorPointer myLocator; + + // FIRST PASS: + // we check if the Children belong to the original class + // if it's not the case, we remove the unknown Children +restart: + myLocator = locator; + if (myLocator.firstChild ()) + { + do + { + const IPrimitive *primitive2 = myLocator.Primitive; + if (primitive2) + { + string ClassName2; + nlverify (primitive2->getPropertyByName ("class", ClassName2)); + uint c; + bool Found = false; + for (c=0; cStaticChildren.size (); c++) + { + if (primClass->StaticChildren[c].ClassName == ClassName2) + { + Found = true; + ++CountStaticChildren; + break; + } + } + + for (c=0; cGeneratedChildren.size (); c++) + { + if (primClass->GeneratedChildren[c].ClassName == ClassName2) + { + Found = true; + break; + } + } + + for (c=0; cDynamicChildren.size (); c++) + { + if (primClass->DynamicChildren[c].ClassName == ClassName2) + { + Found = true; + break; + } + } + if (!Found) + { + // a useless child is here, we need to delete it + // Begin modification + if (!modified) + { + doc->beginModification (); + modified = true; + } + doc->deletePrimitive (myLocator); + doc->modifyDatabase (myLocator.getDatabaseIndex ()); + // since we deleted the child, we cannot point to the next one, so we restart the loop + // I don't think it's possible to use something better than this goto ! + goto restart; + } + } + } + while (myLocator.nextChild ()); + } + if (CountStaticChildren != primClass->StaticChildren.size()) + { + // SECOND PASS: + // if the number of static children of the class is different from the number of static children of the original class + // we have to add the missing class + uint child; + for (child=0; childStaticChildren.size (); ++child) + { + myLocator = locator; + bool Found = false; + // we parse the tree recursively, collection errors, and propagating to the parent + if (myLocator.firstChild ()) + { + do + { + const IPrimitive *primitive2 = myLocator.Primitive; + if (primitive2) + { + string ClassName2; + string name; + nlverify (primitive2->getPropertyByName ("class", ClassName2)); + if (primitive2->getPropertyByName ("name", name)) + { + if (primClass->StaticChildren[child].ClassName == ClassName2 && + primClass->StaticChildren[child].Name == name) + { + Found = true; + break; + } + } + } + } + while (myLocator.nextChild ()); + } + if (!Found) + { + // a child is missing, we need to create it + // Begin modification + if (!modified) + { + doc->beginModification (); + modified = true; + } + // What class is it ? + // Get the child class + CDatabaseLocatorPointer locator2 = locator; + locator2.firstChild(); + CDatabaseLocator dest = locator2; + + // Position on the Display + CDisplay *display = getDisplay (); + float delta = (float)DELTA_POS_ADD_PRIMITIVE * (display->_CurViewMax.x - display->_CurViewMin.x) / (float)display->getWidth (); + if (doc->addModification (new CActionAddPrimitiveByClass (dest, primClass->StaticChildren[child].ClassName.c_str (), getDisplay ()->_CurPos, + delta, primClass->StaticChildren[child].Parameters))) + { + CDatabaseLocatorPointer dest2; + doc->getLocator (dest2, dest); + + // Get a pointer on the new primitive + doc->addModification (new CActionSetPrimitivePropertyString (dest2, "name", primClass->StaticChildren[child].Name.c_str(), false)); + } + } + } + } + } + } + } + ite1++; + } + if (modified) + { + doc->endModification (); + // verify the structures, to get their status + VerifyPrimitivesStructures(); + InvalidateAllPrimitives (); + getMainFrame ()->updateData (); + } + } +} + +// *************************************************************************** + +void CToolsLogicTree::OnTreeHelp() +{ + getMainFrame ()->OnHelpFinder(); +} + +// *************************************************************************** + +void CToolsLogicTree::OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult) +{ + if ( GetAsyncKeyState( VK_MENU ) & 0x8000 ) + { + NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR; + HTREEITEM hItem = pNMTreeView->itemNew.hItem; + if(!hItem) return; + SelectItem(hItem); + + CWorldEditorDoc *doc = getDocument (); + CDatabaseLocatorPointer locator; + doc->getLocator ( locator, Selection.front() ); + + if ( theApp.Config.isPrimitiveDeletable ( *( locator.Primitive ) ) ) + { + m_hDragItem = hItem; + m_pDragImgList = CreateDragImage(hItem); + if(!m_pDragImgList) return; + + m_pDragImgList->BeginDrag( 0, CPoint(0,0) ); + m_pDragImgList->DragEnter( this, pNMTreeView->ptDrag ); + m_boDragging = true; + + ShowCursor(false); + SetCapture(); + m_hDragTarget = NULL; + getMainFrame()->OnEditCut(); + } + + // m_nTimer = SetTimer(1,25,NULL); + *pResult = 0; + } +} + +// *************************************************************************** + +void CToolsLogicTree::OnMouseMove(UINT nFlags, CPoint point) +{ + if (m_boDragging) + { + // highlight target + + TVHITTESTINFO tvHit; + tvHit.pt = point; + HTREEITEM hTarget = HitTest(&tvHit); + + if ( hTarget ) + { + if(hTarget != m_hDragTarget) + { + // this test avoids flickering + m_pDragImgList->DragShowNolock(false); + SelectDropTarget(hTarget); + m_pDragImgList->DragShowNolock(true); + m_hDragTarget = hTarget; + } + } + + // move image being dragged + + m_pDragImgList->DragMove(point); + } + + CTreeCtrl::OnMouseMove( nFlags, point ); +} + +// *************************************************************************** + +void CToolsLogicTree::OnLButtonUp(UINT nFlags, CPoint point) +{ + if ( m_boDragging ) + { + KillTimer(1); + + ReleaseCapture(); + ShowCursor( true ); + m_boDragging = false; + + m_pDragImgList->DragLeave( this ); + m_pDragImgList->EndDrag(); + delete m_pDragImgList; + m_pDragImgList = NULL; + + TVHITTESTINFO tvHit; + tvHit.pt = point; + HTREEITEM hTarget = HitTest(&tvHit); + + OnLButtonDown( nFlags, point ); + + // Can be dropped ? + if ( GetDropHilightItem() && getMainFrame()->CanDrop() ) + { + getMainFrame()->OnEditPaste(); + } + else + { + // un-select + getMainFrame()->onMenuModeUndo(); + // un-cut + getMainFrame()->onMenuModeUndo(); + } + + OnLButtonDown( nFlags, point ); + SelectDropTarget( NULL ); + } + + CTreeCtrl::OnLButtonUp(nFlags, point); +} + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_logic.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_logic.h index 47955e9b4..16cc4f4e6 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_logic.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_logic.h @@ -1,251 +1,251 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef TOOLSLOGIC_H -#define TOOLSLOGIC_H - -// *************************************************************************** - -#include -#include "resource.h" -#include "color_button.h" -#include "main_frm.h" - -// *************************************************************************** - -class CMainFrame; -class CToolsLogic; - -// *************************************************************************** - -class CToolsLogicTree : public CTreeCtrl -{ - struct SRegionInfo - { - std::string Name; - HTREEITEM RegionItem; - //HTREEITEM PointItem, PathItem, ZoneItem; - std::vector Groups; - }; - - CToolsLogic *_ToolLogic; - CMainFrame *_MainFrame; - std::vector _RegionsInfo; - - // for items drag-and-drop - bool m_boDragging; - HTREEITEM m_hDragItem; - HTREEITEM m_hDragTarget; - CImageList* m_pDragImgList; - -public: - - // Begin selection mark (select with SHIFT) - HTREEITEM SelectMark; - - // Old stuff - - CToolsLogicTree(); - - void init (CMainFrame *pMF); - void reset (); - void uninit (); - void setTool (CToolsLogic *pTools); - - uint32 createNewRegion (const std::string &sRegionName); - uint32 createNewGroup (uint32 nRegion, const std::string &sGroupName); - HTREEITEM addPoint (uint32 nRegion, uint32 nGroup, const std::string &sPointName, bool bHide=false); - HTREEITEM addPath (uint32 nRegion, uint32 nGroup, const std::string &sPathName, bool bHide=false); - HTREEITEM addZone (uint32 nRegion, uint32 nGroup, const std::string &sZoneName, bool bHide=false); - void expandAll (uint32 nRegion); - void SuccessfulDrag( HTREEITEM hDest,HTREEITEM hSrc ); - - HTREEITEM InsertItemAndSubtree( HTREEITEM hDest, HTREEITEM hSrc ); - void CopySubtree( HTREEITEM hDest, HTREEITEM hSrc ); - void CopyItem( HTREEITEM hDest, HTREEITEM hSrc ); - - virtual BOOL PreCreateWindow (CREATESTRUCT& cs); - - afx_msg void OnLButtonDown (UINT nFlags, CPoint point); - afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); - afx_msg void OnRButtonDown (UINT nFlags, CPoint point); - - afx_msg void OnSelChanged (); - - // Contextual menu handlers - afx_msg void OnMenuRegionCreateGroup (); - afx_msg void OnMenuRegionHideAll (); - afx_msg void OnMenuRegionUnhideAll (); - afx_msg void OnMenuRegionHideType (); - afx_msg void OnMenuRegionUnhideType (); - - afx_msg void OnMenuGroupCreatePoint (); - afx_msg void OnMenuGroupCreatePath (); - afx_msg void OnMenuGroupCreateZone (); - afx_msg void OnMenuGroupDelete (); - afx_msg void OnMenuGroupProperties (); - afx_msg void OnMenuGroupHide (); - afx_msg void OnMenuGroupUnhide (); - afx_msg void OnMenuGroupTransfertAppend (); - afx_msg void OnMenuGroupTransfertReplace (); - - afx_msg void OnMenuPrimDelete (); - afx_msg void OnMenuPrimProperties (); - afx_msg void OnProjectNewPrimitive (); - afx_msg void OnViewShow (); - afx_msg void OnViewHide (); - afx_msg void OnEditSelectChildren (); - afx_msg void OnAddPrimitive (UINT nID); - afx_msg void OnGeneratePrimitive (UINT nID); - afx_msg void OnOpenFile (UINT nID); - afx_msg void OnEditExpand (); - afx_msg void OnEditCollapse (); - afx_msg void OnRenameSelected(); - afx_msg void OnRepairSelected(); - afx_msg void OnTreeHelp(); - - afx_msg void OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult); - afx_msg void OnMouseMove(UINT nFlags, CPoint point); - afx_msg void OnLButtonUp(UINT nFlags, CPoint point); - - DECLARE_MESSAGE_MAP () -}; - -// *************************************************************************** - -class CToolsLogic : public CFormView -{ - DECLARE_DYNCREATE(CToolsLogic) - - CToolsLogicTree *_Tree; - bool _TreeCreated; - - CMainFrame *_MainFrame; - -public: - - // \name Modify tree functions - - // Add a primitive - HTREEITEM addPrimitive (HTREEITEM parentItem, HTREEITEM lastBrother, const CDatabaseLocatorPointer &locator); - - // Update primitive parameters - void updatePrimitive (HTREEITEM item, const CDatabaseLocatorPointer &locator); - - void ensureVisible (class IPrimitiveEditor *primitive); - -private: - - // Data are validated - bool _ValidStruct; - bool _ValidParam; - bool _ValidTitles; - -public: - - CToolsLogic(); - - CToolsLogicTree *GetTreeCtrl(); - - void init (CMainFrame *pMF); - void reset (); - void uninit (); - - uint32 createNewRegion (const std::string &sRegionName); - uint32 createNewGroup (uint32 nRegion, const std::string &sGroupName); - HTREEITEM addPoint (uint32 nRegion, uint32 nGroup, const std::string &name, bool bHide=false); - HTREEITEM addPath (uint32 nRegion, uint32 nGroup, const std::string &name, bool bHide=false); - HTREEITEM addZone (uint32 nRegion, uint32 nGroup, const std::string &name, bool bHide=false); - void expandAll (uint32 nRegion); - - // Event handlers - afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct); - afx_msg void OnSize (UINT nType, int cx, int cy); - afx_msg void OnPaint (); - - afx_msg void OnNewGroup (); - afx_msg void OnNewPatat (); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CToolsLogic) - protected: - virtual BOOL OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult ); - //}}AFX_VIRTUAL - - DECLARE_MESSAGE_MAP() -}; - -// *************************************************************************** - -class CCreateDialog : public CDialog -{ - -public: - - char Name[128], - LayerName[128]; - - std::vector *TypesForInit; - - std::string RegionPost; - CMainFrame *MainFrame; - - std::string PropName; - std::string PropType; - - - CComboBox ComboType; - -public: - - CCreateDialog(CWnd*pParent); - - virtual BOOL OnInitDialog (); - virtual void DoDataExchange (CDataExchange* pDX); - virtual void OnOK(); - - void setRegionName(const std::string &rn); - - afx_msg void OnSelChange(); - - - DECLARE_MESSAGE_MAP() - -}; - -// *************************************************************************** - -class CEditStringDlg : public CDialog -{ - -public: - - CString Name; - -public: - - CEditStringDlg (CWnd*pParent); - - virtual BOOL OnInitDialog (); - virtual void DoDataExchange (CDataExchange* pDX); - virtual void OnOK(); - -}; - -// *************************************************************************** - -#endif // TOOLSLOGIC_H +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TOOLSLOGIC_H +#define TOOLSLOGIC_H + +// *************************************************************************** + +#include +#include "resource.h" +#include "color_button.h" +#include "main_frm.h" + +// *************************************************************************** + +class CMainFrame; +class CToolsLogic; + +// *************************************************************************** + +class CToolsLogicTree : public CTreeCtrl +{ + struct SRegionInfo + { + std::string Name; + HTREEITEM RegionItem; + //HTREEITEM PointItem, PathItem, ZoneItem; + std::vector Groups; + }; + + CToolsLogic *_ToolLogic; + CMainFrame *_MainFrame; + std::vector _RegionsInfo; + + // for items drag-and-drop + bool m_boDragging; + HTREEITEM m_hDragItem; + HTREEITEM m_hDragTarget; + CImageList* m_pDragImgList; + +public: + + // Begin selection mark (select with SHIFT) + HTREEITEM SelectMark; + + // Old stuff + + CToolsLogicTree(); + + void init (CMainFrame *pMF); + void reset (); + void uninit (); + void setTool (CToolsLogic *pTools); + + uint32 createNewRegion (const std::string &sRegionName); + uint32 createNewGroup (uint32 nRegion, const std::string &sGroupName); + HTREEITEM addPoint (uint32 nRegion, uint32 nGroup, const std::string &sPointName, bool bHide=false); + HTREEITEM addPath (uint32 nRegion, uint32 nGroup, const std::string &sPathName, bool bHide=false); + HTREEITEM addZone (uint32 nRegion, uint32 nGroup, const std::string &sZoneName, bool bHide=false); + void expandAll (uint32 nRegion); + void SuccessfulDrag( HTREEITEM hDest,HTREEITEM hSrc ); + + HTREEITEM InsertItemAndSubtree( HTREEITEM hDest, HTREEITEM hSrc ); + void CopySubtree( HTREEITEM hDest, HTREEITEM hSrc ); + void CopyItem( HTREEITEM hDest, HTREEITEM hSrc ); + + virtual BOOL PreCreateWindow (CREATESTRUCT& cs); + + afx_msg void OnLButtonDown (UINT nFlags, CPoint point); + afx_msg void OnLButtonDblClk(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown (UINT nFlags, CPoint point); + + afx_msg void OnSelChanged (); + + // Contextual menu handlers + afx_msg void OnMenuRegionCreateGroup (); + afx_msg void OnMenuRegionHideAll (); + afx_msg void OnMenuRegionUnhideAll (); + afx_msg void OnMenuRegionHideType (); + afx_msg void OnMenuRegionUnhideType (); + + afx_msg void OnMenuGroupCreatePoint (); + afx_msg void OnMenuGroupCreatePath (); + afx_msg void OnMenuGroupCreateZone (); + afx_msg void OnMenuGroupDelete (); + afx_msg void OnMenuGroupProperties (); + afx_msg void OnMenuGroupHide (); + afx_msg void OnMenuGroupUnhide (); + afx_msg void OnMenuGroupTransfertAppend (); + afx_msg void OnMenuGroupTransfertReplace (); + + afx_msg void OnMenuPrimDelete (); + afx_msg void OnMenuPrimProperties (); + afx_msg void OnProjectNewPrimitive (); + afx_msg void OnViewShow (); + afx_msg void OnViewHide (); + afx_msg void OnEditSelectChildren (); + afx_msg void OnAddPrimitive (UINT nID); + afx_msg void OnGeneratePrimitive (UINT nID); + afx_msg void OnOpenFile (UINT nID); + afx_msg void OnEditExpand (); + afx_msg void OnEditCollapse (); + afx_msg void OnRenameSelected(); + afx_msg void OnRepairSelected(); + afx_msg void OnTreeHelp(); + + afx_msg void OnBegindrag(NMHDR* pNMHDR, LRESULT* pResult); + afx_msg void OnMouseMove(UINT nFlags, CPoint point); + afx_msg void OnLButtonUp(UINT nFlags, CPoint point); + + DECLARE_MESSAGE_MAP () +}; + +// *************************************************************************** + +class CToolsLogic : public CFormView +{ + DECLARE_DYNCREATE(CToolsLogic) + + CToolsLogicTree *_Tree; + bool _TreeCreated; + + CMainFrame *_MainFrame; + +public: + + // \name Modify tree functions + + // Add a primitive + HTREEITEM addPrimitive (HTREEITEM parentItem, HTREEITEM lastBrother, const CDatabaseLocatorPointer &locator); + + // Update primitive parameters + void updatePrimitive (HTREEITEM item, const CDatabaseLocatorPointer &locator); + + void ensureVisible (class IPrimitiveEditor *primitive); + +private: + + // Data are validated + bool _ValidStruct; + bool _ValidParam; + bool _ValidTitles; + +public: + + CToolsLogic(); + + CToolsLogicTree *GetTreeCtrl(); + + void init (CMainFrame *pMF); + void reset (); + void uninit (); + + uint32 createNewRegion (const std::string &sRegionName); + uint32 createNewGroup (uint32 nRegion, const std::string &sGroupName); + HTREEITEM addPoint (uint32 nRegion, uint32 nGroup, const std::string &name, bool bHide=false); + HTREEITEM addPath (uint32 nRegion, uint32 nGroup, const std::string &name, bool bHide=false); + HTREEITEM addZone (uint32 nRegion, uint32 nGroup, const std::string &name, bool bHide=false); + void expandAll (uint32 nRegion); + + // Event handlers + afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct); + afx_msg void OnSize (UINT nType, int cx, int cy); + afx_msg void OnPaint (); + + afx_msg void OnNewGroup (); + afx_msg void OnNewPatat (); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CToolsLogic) + protected: + virtual BOOL OnNotify( WPARAM wParam, LPARAM lParam, LRESULT* pResult ); + //}}AFX_VIRTUAL + + DECLARE_MESSAGE_MAP() +}; + +// *************************************************************************** + +class CCreateDialog : public CDialog +{ + +public: + + char Name[128], + LayerName[128]; + + std::vector *TypesForInit; + + std::string RegionPost; + CMainFrame *MainFrame; + + std::string PropName; + std::string PropType; + + + CComboBox ComboType; + +public: + + CCreateDialog(CWnd*pParent); + + virtual BOOL OnInitDialog (); + virtual void DoDataExchange (CDataExchange* pDX); + virtual void OnOK(); + + void setRegionName(const std::string &rn); + + afx_msg void OnSelChange(); + + + DECLARE_MESSAGE_MAP() + +}; + +// *************************************************************************** + +class CEditStringDlg : public CDialog +{ + +public: + + CString Name; + +public: + + CEditStringDlg (CWnd*pParent); + + virtual BOOL OnInitDialog (); + virtual void DoDataExchange (CDataExchange* pDX); + virtual void OnOK(); + +}; + +// *************************************************************************** + +#endif // TOOLSLOGIC_H diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_zone.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_zone.cpp index 68e8f1cb1..bca5672d6 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_zone.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_zone.cpp @@ -1,695 +1,695 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" -#include "tools_zone.h" - -#include "main_frm.h" - -#include - -using namespace std; - -// --------------------------------------------------------------------------- - -//#define IDC_LIST 0x10000 - - -// *************************************************************************** -// CToolsZoneList -// *************************************************************************** - -// --------------------------------------------------------------------------- - -BEGIN_MESSAGE_MAP (CToolsZoneList, CListBox) - ON_WM_LBUTTONDOWN () - ON_WM_LBUTTONUP () - ON_WM_MOUSEMOVE () -END_MESSAGE_MAP() - -// --------------------------------------------------------------------------- -CToolsZoneList::CToolsZoneList() -{ - _MouseLDown = false; -} - -// --------------------------------------------------------------------------- -void CToolsZoneList::OnLButtonDown (UINT nFlags, CPoint point) -{ - CListBox::OnLButtonDown (nFlags, point); - _MouseLDown = true; - notifyParent(); -} - -// --------------------------------------------------------------------------- -void CToolsZoneList::OnLButtonUp (UINT nFlags, CPoint point) -{ - CListBox::OnLButtonUp (nFlags, point); - _MouseLDown = false; -} - -// --------------------------------------------------------------------------- -void CToolsZoneList::OnMouseMove (UINT nFlags, CPoint point) -{ - CListBox::OnMouseMove (nFlags, point); - if (_MouseLDown) - notifyParent(); -} - -// --------------------------------------------------------------------------- -void CToolsZoneList::setTool (CToolsZone *pTool) -{ - _Tools = pTool; -} - -// --------------------------------------------------------------------------- -void CToolsZoneList::notifyParent () -{ - int nIndex = GetCurSel(); - _Tools->OnSelChange(); -} - -// --------------------------------------------------------------------------- -void CToolsZoneList::setImages (std::vector &vBitmaps) -{ - _BitmapList = vBitmaps; - for (uint32 i = 0; i < _BitmapList.size(); ++i) - { - BITMAP bitmap; - _BitmapList[i]->GetBitmap (&bitmap); - SetItemHeight (i, bitmap.bmHeight); - } -} - -// --------------------------------------------------------------------------- -void CToolsZoneList::reset() -{ - ResetContent(); - _ItemNames.clear(); -} - -// --------------------------------------------------------------------------- -void CToolsZoneList::addItem (const string &itemName) -{ - _ItemNames.push_back (itemName); - InsertString (-1, itemName.c_str()); -} - -// --------------------------------------------------------------------------- -const string &CToolsZoneList::getItem (uint32 nIndex) -{ - return _ItemNames[nIndex]; -} - -// --------------------------------------------------------------------------- -void CToolsZoneList::DrawItem (LPDRAWITEMSTRUCT lpDrawItemStruct) -{ - ASSERT(lpDrawItemStruct->CtlType == ODT_LISTBOX); - LPCTSTR lpszText = (LPCTSTR) lpDrawItemStruct->itemData; - if (lpszText == NULL) - return; - CDC dc; - - if (lpDrawItemStruct->itemID >= _BitmapList.size()) - return; - - dc.Attach (lpDrawItemStruct->hDC); - - // Draw the image - CBitmap *p = _BitmapList[lpDrawItemStruct->itemID]; - BITMAP bitmap; - p->GetBitmap (&bitmap); - dc.DrawState (CPoint(lpDrawItemStruct->rcItem.left,lpDrawItemStruct->rcItem.top), - CSize(bitmap.bmWidth, bitmap.bmHeight) , p, DSS_NORMAL); - - // Reduce the rectangle to display selection box and item text - CRect rectLeft = lpDrawItemStruct->rcItem; - rectLeft.left += bitmap.bmWidth; - - // Save these value to restore them when done drawing. - COLORREF crOldTextColor = dc.GetTextColor(); - COLORREF crOldBkColor = dc.GetBkColor(); - - // If this item is selected, set the background color - // and the text color to appropriate values. Also, erase - // rect by filling it with the background color. - if ((lpDrawItemStruct->itemAction | ODA_SELECT) && - (lpDrawItemStruct->itemState & ODS_SELECTED)) - { - dc.SetTextColor (::GetSysColor(COLOR_HIGHLIGHTTEXT)); - dc.SetBkColor (::GetSysColor(COLOR_HIGHLIGHT)); - dc.FillSolidRect (&rectLeft, ::GetSysColor(COLOR_HIGHLIGHT)); - } - else - { - dc.FillSolidRect (&rectLeft, crOldBkColor); - } - - // If this item has the focus, draw a red frame around the - // item's rect. - if ((lpDrawItemStruct->itemAction | ODA_FOCUS) && - (lpDrawItemStruct->itemState & ODS_FOCUS)) - { - CBrush br(RGB(255, 0, 0)); - dc.FrameRect (&rectLeft, &br); - } - - // Draw the text. - dc.DrawText (lpszText, strlen(lpszText), &rectLeft, DT_CENTER|DT_SINGLELINE|DT_VCENTER); - - // Reset the background color and the text color back to their original values. - dc.SetTextColor (crOldTextColor); - dc.SetBkColor (crOldBkColor); - - dc.Detach (); -} - -// --------------------------------------------------------------------------- -void CToolsZoneList::MeasureItem (LPMEASUREITEMSTRUCT lpMeasureItemStruct) -{ - if (lpMeasureItemStruct->itemID >= 0) - { - if (lpMeasureItemStruct->itemID < _BitmapList.size()) - { - CBitmap *p = _BitmapList[lpMeasureItemStruct->itemID]; - BITMAP b; - p->GetBitmap (&b); - lpMeasureItemStruct->itemHeight = b.bmHeight; - } - } -} - -// --------------------------------------------------------------------------- -int CToolsZoneList::CompareItem (LPCOMPAREITEMSTRUCT) -{ - return 0; -} - -// *************************************************************************** -// CToolsZone -// *************************************************************************** - -// --------------------------------------------------------------------------- - -IMPLEMENT_DYNCREATE (CToolsZone, CFormView) - -// --------------------------------------------------------------------------- - -BEGIN_MESSAGE_MAP (CToolsZone, CFormView) - ON_WM_CREATE() - ON_WM_SIZE () - ON_WM_PAINT () - ON_CBN_SELCHANGE (IDC_CATTYPE1, OnSelectCatType1) - ON_CBN_SELCHANGE (IDC_CATTYPE2, OnSelectCatType2) - ON_CBN_SELCHANGE (IDC_CATTYPE3, OnSelectCatType3) - ON_CBN_SELCHANGE (IDC_CATTYPE4, OnSelectCatType4) - ON_CBN_SELCHANGE (IDC_CATVALUE1, OnSelectCatValue1) - ON_CBN_SELCHANGE (IDC_CATVALUE2, OnSelectCatValue2) - ON_CBN_SELCHANGE (IDC_CATVALUE3, OnSelectCatValue3) - ON_CBN_SELCHANGE (IDC_CATVALUE4, OnSelectCatValue4) - ON_BN_CLICKED (IDC_AND2, OnSelectAnd2) - ON_BN_CLICKED (IDC_OR2, OnSelectOr2) - ON_BN_CLICKED (IDC_AND3, OnSelectAnd3) - ON_BN_CLICKED (IDC_OR3, OnSelectOr3) - ON_BN_CLICKED (IDC_AND4, OnSelectAnd4) - ON_BN_CLICKED (IDC_OR4, OnSelectOr4) - ON_BN_CLICKED (IDC_RANDOM, OnSelectRandom) - ON_BN_CLICKED (IDC_FULL_CYCLE, OnSelectCycle) - ON_BN_CLICKED (IDC_NOT_PROPAGATE, OnSelectNotPropagate) - ON_BN_CLICKED (IDC_FORCE, OnSelectForce) - - ON_BN_CLICKED (IDC_ROT0, OnSelectRot0) - ON_BN_CLICKED (IDC_ROT90, OnSelectRot90) - ON_BN_CLICKED (IDC_ROT180, OnSelectRot180) - ON_BN_CLICKED (IDC_ROT270, OnSelectRot270) - ON_BN_CLICKED (IDC_ROTRANDOM, OnSelectRotRan) - ON_BN_CLICKED (IDC_ROTCYCLE, OnSelectRotCycle) - ON_BN_CLICKED (IDC_FLIPNO, OnSelectFlipNo) - ON_BN_CLICKED (IDC_FLIPYES, OnSelectFlipYes) - ON_BN_CLICKED (IDC_FLIPRANDOM, OnSelectFlipRan) - ON_BN_CLICKED (IDC_FLIPCYCLE, OnSelectFlipCycle) - -END_MESSAGE_MAP() - -// --------------------------------------------------------------------------- -CToolsZone::CToolsZone() : CFormView(IDD_TOOLS_ZONE) -{ - _ListCreated = false; -} - -// --------------------------------------------------------------------------- -CToolsZoneList *CToolsZone::getListCtrl() -{ - return &_List; -} - -// --------------------------------------------------------------------------- -void CToolsZone::addToAllCatTypeCB (const string &Name) -{ - CComboBox* pCB; - pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE1); - pCB->AddString (Name.c_str()); - pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE2); - pCB->AddString (Name.c_str()); - pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE3); - pCB->AddString (Name.c_str()); - pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE4); - pCB->AddString (Name.c_str()); -} - -// --------------------------------------------------------------------------- -void CToolsZone::init (CMainFrame *pMF) -{ - _MainFrame = pMF; - _MainFrame->_ZoneBuilder->setToolsZone (this); - - addToAllCatTypeCB (STRING_UNUSED); - vector allCategoryTypes; - _MainFrame->_ZoneBuilder->getZoneBank().getCategoriesType (allCategoryTypes); - for(uint32 i = 0; i < allCategoryTypes.size(); ++i) - addToAllCatTypeCB (allCategoryTypes[i]); - - // Select right category types - CComboBox* pCB; - pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE1); - pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterType1.c_str()); - pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE2); - pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterType2.c_str()); - pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE3); - pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterType3.c_str()); - pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE4); - pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterType4.c_str()); - - updateComboPairAndFilter (IDC_CATTYPE1, IDC_CATVALUE1, &_MainFrame->_ZoneBuilder->_FilterType1); - pCB = (CComboBox*)GetDlgItem (IDC_CATVALUE1); - pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterValue1.c_str()); - updateComboPairAndFilter (IDC_CATTYPE2, IDC_CATVALUE2, &_MainFrame->_ZoneBuilder->_FilterType2); - pCB = (CComboBox*)GetDlgItem (IDC_CATVALUE2); - pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterValue2.c_str()); - updateComboPairAndFilter (IDC_CATTYPE3, IDC_CATVALUE3, &_MainFrame->_ZoneBuilder->_FilterType3); - pCB = (CComboBox*)GetDlgItem (IDC_CATVALUE3); - pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterValue3.c_str()); - updateComboPairAndFilter (IDC_CATTYPE4, IDC_CATVALUE4, &_MainFrame->_ZoneBuilder->_FilterType4); - pCB = (CComboBox*)GetDlgItem (IDC_CATVALUE4); - pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterValue4.c_str()); - - // Select right operators - CButton *pButAnd, *pButOr; - pButAnd = (CButton*)GetDlgItem(IDC_AND2); - pButOr =(CButton*)GetDlgItem(IDC_OR2); - if (_MainFrame->_ZoneBuilder->_FilterOperator2 == 0) - pButAnd->SetCheck (1); - else - pButOr->SetCheck (1); - - pButAnd = (CButton*)GetDlgItem(IDC_AND3); - pButOr =(CButton*)GetDlgItem(IDC_OR3); - if (_MainFrame->_ZoneBuilder->_FilterOperator3 == 0) - pButAnd->SetCheck (1); - else - pButOr->SetCheck (1); - - pButAnd = (CButton*)GetDlgItem(IDC_AND4); - pButOr =(CButton*)GetDlgItem(IDC_OR4); - if (_MainFrame->_ZoneBuilder->_FilterOperator4 == 0) - pButAnd->SetCheck (1); - else - pButOr->SetCheck (1); - - CButton *pButRan = (CButton*)GetDlgItem(IDC_RANDOM); - if (_MainFrame->_ZoneBuilder->_RandomSelection) - pButRan->SetCheck (1); - else - pButRan->SetCheck (0); - - CButton *pButton; - if (_MainFrame->_ZoneBuilder->_ApplyRotType == 1) // Random - { - pButton = (CButton*)GetDlgItem(IDC_ROTRANDOM); - pButton->SetCheck (1); - } - else if (_MainFrame->_ZoneBuilder->_ApplyRotType == 0) // Normal - { - switch (_MainFrame->_ZoneBuilder->_ApplyRot) - { - case 0: pButton = (CButton*)GetDlgItem(IDC_ROT0); break; - case 1: pButton = (CButton*)GetDlgItem(IDC_ROT90); break; - case 2: pButton = (CButton*)GetDlgItem(IDC_ROT180); break; - case 3: pButton = (CButton*)GetDlgItem(IDC_ROT270); break; - } - pButton->SetCheck (1); - } - else if (_MainFrame->_ZoneBuilder->_ApplyRotType == 2) // Cycle - { - pButton = (CButton*)GetDlgItem(IDC_ROTCYCLE); - pButton->SetCheck (1); - } - - if (_MainFrame->_ZoneBuilder->_ApplyFlipType == 1) // Random - { - pButton = (CButton*)GetDlgItem(IDC_FLIPRANDOM); - pButton->SetCheck (1); - } - else if (_MainFrame->_ZoneBuilder->_ApplyFlipType == 0) // Normal - { - switch (_MainFrame->_ZoneBuilder->_ApplyFlip) - { - case 0: pButton = (CButton*)GetDlgItem(IDC_FLIPNO); break; - case 1: pButton = (CButton*)GetDlgItem(IDC_FLIPYES); break; - } - pButton->SetCheck (1); - } - else if (_MainFrame->_ZoneBuilder->_ApplyFlipType == 2) // Cycle - { - pButton = (CButton*)GetDlgItem(IDC_FLIPCYCLE); - pButton->SetCheck (1); - } - - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -#define LIST_TOP 170 - -// --------------------------------------------------------------------------- -int CToolsZone::OnCreate (LPCREATESTRUCT lpCreateStruct) -{ - if (CFormView::OnCreate (lpCreateStruct) == -1) - return -1; - CRect iniRect; - GetClientRect(&iniRect); - iniRect.top = LIST_TOP; iniRect.left = 10; - iniRect.right -= 20; iniRect.bottom -= 20; - _List.Create (WS_CHILD|WS_VISIBLE|WS_BORDER|WS_HSCROLL|WS_VSCROLL|LBS_OWNERDRAWVARIABLE|LBS_NOTIFY, - iniRect, this, IDC_LIST); - _List.setTool (this); - _ListCreated = true; - return 0; -} - -// --------------------------------------------------------------------------- -void CToolsZone::uninit() -{ -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSize (UINT nType, int cx, int cy) -{ - CFormView::OnSize (nType, cx, cy); - // Resize list ctrl to fill the whole view. - if (_ListCreated) - { - CRect iniRect; - GetClientRect(&iniRect); - - iniRect.top = LIST_TOP; iniRect.left = 10; - iniRect.right -= 10; iniRect.bottom -= 10; - - getListCtrl()->MoveWindow (&iniRect); - } -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnPaint() -{ - getListCtrl()->ShowScrollBar(SB_VERT); - CFormView::OnPaint(); -} - -// --------------------------------------------------------------------------- -void CToolsZone::updateComboPairAndFilter (int CatTypeId, int CatValueId, string *pFilterType) -{ - uint32 i; - char sTmp[256]; - CComboBox *pCBType, *pCBValue; - pCBType = (CComboBox*)GetDlgItem (CatTypeId); - pCBType->GetLBText (pCBType->GetCurSel(), sTmp); - *pFilterType = sTmp; - pCBValue = (CComboBox*)GetDlgItem (CatValueId); - pCBValue->ResetContent (); - - if (*pFilterType == STRING_UNUSED) - return; - - vector allCategoryValues; - _MainFrame->_ZoneBuilder->getZoneBank().getCategoryValues (*pFilterType, allCategoryValues); - for(i = 0; i < allCategoryValues.size(); ++i) - pCBValue->AddString (allCategoryValues[i].c_str()); - pCBValue->SetCurSel (0); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectCatType1 () -{ - updateComboPairAndFilter (IDC_CATTYPE1, IDC_CATVALUE1, &_MainFrame->_ZoneBuilder->_FilterType1); - OnSelectCatValue1 (); - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectCatType2 () -{ - updateComboPairAndFilter (IDC_CATTYPE2, IDC_CATVALUE2, &_MainFrame->_ZoneBuilder->_FilterType2); - OnSelectCatValue2 (); - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectCatType3 () -{ - updateComboPairAndFilter (IDC_CATTYPE3, IDC_CATVALUE3, &_MainFrame->_ZoneBuilder->_FilterType3); - OnSelectCatValue3 (); - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectCatType4 () -{ - updateComboPairAndFilter (IDC_CATTYPE4, IDC_CATVALUE4, &_MainFrame->_ZoneBuilder->_FilterType4); - OnSelectCatValue4 (); - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectCatValue1() -{ - char sTmp[256]; - CComboBox *pCBValue = (CComboBox*)GetDlgItem (IDC_CATVALUE1); - pCBValue->GetLBText (pCBValue->GetCurSel(), sTmp); - _MainFrame->_ZoneBuilder->_FilterValue1 = sTmp; - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectCatValue2() -{ - char sTmp[256]; - CComboBox *pCBValue = (CComboBox*)GetDlgItem (IDC_CATVALUE2); - pCBValue->GetLBText (pCBValue->GetCurSel(), sTmp); - _MainFrame->_ZoneBuilder->_FilterValue2 = sTmp; - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectCatValue3() -{ - char sTmp[256]; - CComboBox *pCBValue = (CComboBox*)GetDlgItem (IDC_CATVALUE3); - pCBValue->GetLBText (pCBValue->GetCurSel(), sTmp); - _MainFrame->_ZoneBuilder->_FilterValue3 = sTmp; - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectCatValue4() -{ - char sTmp[256]; - CComboBox *pCBValue = (CComboBox*)GetDlgItem (IDC_CATVALUE4); - pCBValue->GetLBText (pCBValue->GetCurSel(), sTmp); - _MainFrame->_ZoneBuilder->_FilterValue4 = sTmp; - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectAnd2 () -{ - if (_MainFrame->_ZoneBuilder->_FilterOperator2 == 0) return; - _MainFrame->_ZoneBuilder->_FilterOperator2 = 0; // And - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectOr2 () -{ - if (_MainFrame->_ZoneBuilder->_FilterOperator2 == 1) return; - _MainFrame->_ZoneBuilder->_FilterOperator2 = 1; // Or - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectAnd3 () -{ - if (_MainFrame->_ZoneBuilder->_FilterOperator3 == 0) return; - _MainFrame->_ZoneBuilder->_FilterOperator3 = 0; // And - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectOr3 () -{ - if (_MainFrame->_ZoneBuilder->_FilterOperator3 == 1) return; - _MainFrame->_ZoneBuilder->_FilterOperator3 = 1; // Or - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectAnd4 () -{ - if (_MainFrame->_ZoneBuilder->_FilterOperator3 == 0) return; - _MainFrame->_ZoneBuilder->_FilterOperator4 = 0; // And - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectOr4 () -{ - if (_MainFrame->_ZoneBuilder->_FilterOperator4 == 1) return; - _MainFrame->_ZoneBuilder->_FilterOperator4 = 1; // Or - _MainFrame->_ZoneBuilder->updateToolsZone (); -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectRandom() -{ - _MainFrame->_ZoneBuilder->_RandomSelection = !_MainFrame->_ZoneBuilder->_RandomSelection; - if (_MainFrame->_ZoneBuilder->_RandomSelection) - { - CButton *pBut = (CButton*)GetDlgItem (IDC_FULL_CYCLE); - pBut->SetCheck (0); - _MainFrame->_ZoneBuilder->_CycleSelection = false; - } -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectCycle () -{ - _MainFrame->_ZoneBuilder->_CycleSelection = !_MainFrame->_ZoneBuilder->_CycleSelection; - if (_MainFrame->_ZoneBuilder->_CycleSelection) - { - CButton *pBut = (CButton*)GetDlgItem (IDC_RANDOM); - pBut->SetCheck (0); - _MainFrame->_ZoneBuilder->_RandomSelection = false; - } -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectNotPropagate () -{ - _MainFrame->_ZoneBuilder->_NotPropagate = !_MainFrame->_ZoneBuilder->_NotPropagate; -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectForce () -{ - _MainFrame->_ZoneBuilder->_Force = !_MainFrame->_ZoneBuilder->_Force; - if (_MainFrame->_ZoneBuilder->_Force) - { - CButton *pBut = (CButton*)GetDlgItem (IDC_NOT_PROPAGATE); - pBut->SetCheck (1); - _MainFrame->_ZoneBuilder->_NotPropagate = true; - } -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelChange () -{ - // Select the next item of the currently selected one. - int nIndex = _List.GetCurSel(); - if (nIndex != LB_ERR) - { - // Here for some reason we cant use the GetText(nIndex, str) function... - _MainFrame->_ZoneBuilder->_CurSelectedZone = nIndex;//_List.getItem (nIndex); - } - else - { - _MainFrame->_ZoneBuilder->_CurSelectedZone = -1;//STRING_UNUSED; - } -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectRot0 () -{ - _MainFrame->_ZoneBuilder->_ApplyRot = 0; - _MainFrame->_ZoneBuilder->_ApplyRotType = 0; -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectRot90 () -{ - _MainFrame->_ZoneBuilder->_ApplyRot = 1; - _MainFrame->_ZoneBuilder->_ApplyRotType = 0; -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectRot180 () -{ - _MainFrame->_ZoneBuilder->_ApplyRot = 2; - _MainFrame->_ZoneBuilder->_ApplyRotType = 0; -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectRot270 () -{ - _MainFrame->_ZoneBuilder->_ApplyRot = 3; - _MainFrame->_ZoneBuilder->_ApplyRotType = 0; -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectRotRan () -{ - _MainFrame->_ZoneBuilder->_ApplyRotType = 1; -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectRotCycle () -{ - _MainFrame->_ZoneBuilder->_ApplyRotType = 2; -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectFlipNo () -{ - _MainFrame->_ZoneBuilder->_ApplyFlip = 0; - _MainFrame->_ZoneBuilder->_ApplyFlipType = 0; -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectFlipYes () -{ - _MainFrame->_ZoneBuilder->_ApplyFlip = 1; - _MainFrame->_ZoneBuilder->_ApplyFlipType = 0; -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectFlipRan () -{ - _MainFrame->_ZoneBuilder->_ApplyFlipType = 1; -} - -// --------------------------------------------------------------------------- -void CToolsZone::OnSelectFlipCycle () -{ - _MainFrame->_ZoneBuilder->_ApplyFlipType = 2; +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" +#include "tools_zone.h" + +#include "main_frm.h" + +#include + +using namespace std; + +// --------------------------------------------------------------------------- + +//#define IDC_LIST 0x10000 + + +// *************************************************************************** +// CToolsZoneList +// *************************************************************************** + +// --------------------------------------------------------------------------- + +BEGIN_MESSAGE_MAP (CToolsZoneList, CListBox) + ON_WM_LBUTTONDOWN () + ON_WM_LBUTTONUP () + ON_WM_MOUSEMOVE () +END_MESSAGE_MAP() + +// --------------------------------------------------------------------------- +CToolsZoneList::CToolsZoneList() +{ + _MouseLDown = false; +} + +// --------------------------------------------------------------------------- +void CToolsZoneList::OnLButtonDown (UINT nFlags, CPoint point) +{ + CListBox::OnLButtonDown (nFlags, point); + _MouseLDown = true; + notifyParent(); +} + +// --------------------------------------------------------------------------- +void CToolsZoneList::OnLButtonUp (UINT nFlags, CPoint point) +{ + CListBox::OnLButtonUp (nFlags, point); + _MouseLDown = false; +} + +// --------------------------------------------------------------------------- +void CToolsZoneList::OnMouseMove (UINT nFlags, CPoint point) +{ + CListBox::OnMouseMove (nFlags, point); + if (_MouseLDown) + notifyParent(); +} + +// --------------------------------------------------------------------------- +void CToolsZoneList::setTool (CToolsZone *pTool) +{ + _Tools = pTool; +} + +// --------------------------------------------------------------------------- +void CToolsZoneList::notifyParent () +{ + int nIndex = GetCurSel(); + _Tools->OnSelChange(); +} + +// --------------------------------------------------------------------------- +void CToolsZoneList::setImages (std::vector &vBitmaps) +{ + _BitmapList = vBitmaps; + for (uint32 i = 0; i < _BitmapList.size(); ++i) + { + BITMAP bitmap; + _BitmapList[i]->GetBitmap (&bitmap); + SetItemHeight (i, bitmap.bmHeight); + } +} + +// --------------------------------------------------------------------------- +void CToolsZoneList::reset() +{ + ResetContent(); + _ItemNames.clear(); +} + +// --------------------------------------------------------------------------- +void CToolsZoneList::addItem (const string &itemName) +{ + _ItemNames.push_back (itemName); + InsertString (-1, itemName.c_str()); +} + +// --------------------------------------------------------------------------- +const string &CToolsZoneList::getItem (uint32 nIndex) +{ + return _ItemNames[nIndex]; +} + +// --------------------------------------------------------------------------- +void CToolsZoneList::DrawItem (LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + ASSERT(lpDrawItemStruct->CtlType == ODT_LISTBOX); + LPCTSTR lpszText = (LPCTSTR) lpDrawItemStruct->itemData; + if (lpszText == NULL) + return; + CDC dc; + + if (lpDrawItemStruct->itemID >= _BitmapList.size()) + return; + + dc.Attach (lpDrawItemStruct->hDC); + + // Draw the image + CBitmap *p = _BitmapList[lpDrawItemStruct->itemID]; + BITMAP bitmap; + p->GetBitmap (&bitmap); + dc.DrawState (CPoint(lpDrawItemStruct->rcItem.left,lpDrawItemStruct->rcItem.top), + CSize(bitmap.bmWidth, bitmap.bmHeight) , p, DSS_NORMAL); + + // Reduce the rectangle to display selection box and item text + CRect rectLeft = lpDrawItemStruct->rcItem; + rectLeft.left += bitmap.bmWidth; + + // Save these value to restore them when done drawing. + COLORREF crOldTextColor = dc.GetTextColor(); + COLORREF crOldBkColor = dc.GetBkColor(); + + // If this item is selected, set the background color + // and the text color to appropriate values. Also, erase + // rect by filling it with the background color. + if ((lpDrawItemStruct->itemAction | ODA_SELECT) && + (lpDrawItemStruct->itemState & ODS_SELECTED)) + { + dc.SetTextColor (::GetSysColor(COLOR_HIGHLIGHTTEXT)); + dc.SetBkColor (::GetSysColor(COLOR_HIGHLIGHT)); + dc.FillSolidRect (&rectLeft, ::GetSysColor(COLOR_HIGHLIGHT)); + } + else + { + dc.FillSolidRect (&rectLeft, crOldBkColor); + } + + // If this item has the focus, draw a red frame around the + // item's rect. + if ((lpDrawItemStruct->itemAction | ODA_FOCUS) && + (lpDrawItemStruct->itemState & ODS_FOCUS)) + { + CBrush br(RGB(255, 0, 0)); + dc.FrameRect (&rectLeft, &br); + } + + // Draw the text. + dc.DrawText (lpszText, strlen(lpszText), &rectLeft, DT_CENTER|DT_SINGLELINE|DT_VCENTER); + + // Reset the background color and the text color back to their original values. + dc.SetTextColor (crOldTextColor); + dc.SetBkColor (crOldBkColor); + + dc.Detach (); +} + +// --------------------------------------------------------------------------- +void CToolsZoneList::MeasureItem (LPMEASUREITEMSTRUCT lpMeasureItemStruct) +{ + if (lpMeasureItemStruct->itemID >= 0) + { + if (lpMeasureItemStruct->itemID < _BitmapList.size()) + { + CBitmap *p = _BitmapList[lpMeasureItemStruct->itemID]; + BITMAP b; + p->GetBitmap (&b); + lpMeasureItemStruct->itemHeight = b.bmHeight; + } + } +} + +// --------------------------------------------------------------------------- +int CToolsZoneList::CompareItem (LPCOMPAREITEMSTRUCT) +{ + return 0; +} + +// *************************************************************************** +// CToolsZone +// *************************************************************************** + +// --------------------------------------------------------------------------- + +IMPLEMENT_DYNCREATE (CToolsZone, CFormView) + +// --------------------------------------------------------------------------- + +BEGIN_MESSAGE_MAP (CToolsZone, CFormView) + ON_WM_CREATE() + ON_WM_SIZE () + ON_WM_PAINT () + ON_CBN_SELCHANGE (IDC_CATTYPE1, OnSelectCatType1) + ON_CBN_SELCHANGE (IDC_CATTYPE2, OnSelectCatType2) + ON_CBN_SELCHANGE (IDC_CATTYPE3, OnSelectCatType3) + ON_CBN_SELCHANGE (IDC_CATTYPE4, OnSelectCatType4) + ON_CBN_SELCHANGE (IDC_CATVALUE1, OnSelectCatValue1) + ON_CBN_SELCHANGE (IDC_CATVALUE2, OnSelectCatValue2) + ON_CBN_SELCHANGE (IDC_CATVALUE3, OnSelectCatValue3) + ON_CBN_SELCHANGE (IDC_CATVALUE4, OnSelectCatValue4) + ON_BN_CLICKED (IDC_AND2, OnSelectAnd2) + ON_BN_CLICKED (IDC_OR2, OnSelectOr2) + ON_BN_CLICKED (IDC_AND3, OnSelectAnd3) + ON_BN_CLICKED (IDC_OR3, OnSelectOr3) + ON_BN_CLICKED (IDC_AND4, OnSelectAnd4) + ON_BN_CLICKED (IDC_OR4, OnSelectOr4) + ON_BN_CLICKED (IDC_RANDOM, OnSelectRandom) + ON_BN_CLICKED (IDC_FULL_CYCLE, OnSelectCycle) + ON_BN_CLICKED (IDC_NOT_PROPAGATE, OnSelectNotPropagate) + ON_BN_CLICKED (IDC_FORCE, OnSelectForce) + + ON_BN_CLICKED (IDC_ROT0, OnSelectRot0) + ON_BN_CLICKED (IDC_ROT90, OnSelectRot90) + ON_BN_CLICKED (IDC_ROT180, OnSelectRot180) + ON_BN_CLICKED (IDC_ROT270, OnSelectRot270) + ON_BN_CLICKED (IDC_ROTRANDOM, OnSelectRotRan) + ON_BN_CLICKED (IDC_ROTCYCLE, OnSelectRotCycle) + ON_BN_CLICKED (IDC_FLIPNO, OnSelectFlipNo) + ON_BN_CLICKED (IDC_FLIPYES, OnSelectFlipYes) + ON_BN_CLICKED (IDC_FLIPRANDOM, OnSelectFlipRan) + ON_BN_CLICKED (IDC_FLIPCYCLE, OnSelectFlipCycle) + +END_MESSAGE_MAP() + +// --------------------------------------------------------------------------- +CToolsZone::CToolsZone() : CFormView(IDD_TOOLS_ZONE) +{ + _ListCreated = false; +} + +// --------------------------------------------------------------------------- +CToolsZoneList *CToolsZone::getListCtrl() +{ + return &_List; +} + +// --------------------------------------------------------------------------- +void CToolsZone::addToAllCatTypeCB (const string &Name) +{ + CComboBox* pCB; + pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE1); + pCB->AddString (Name.c_str()); + pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE2); + pCB->AddString (Name.c_str()); + pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE3); + pCB->AddString (Name.c_str()); + pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE4); + pCB->AddString (Name.c_str()); +} + +// --------------------------------------------------------------------------- +void CToolsZone::init (CMainFrame *pMF) +{ + _MainFrame = pMF; + _MainFrame->_ZoneBuilder->setToolsZone (this); + + addToAllCatTypeCB (STRING_UNUSED); + vector allCategoryTypes; + _MainFrame->_ZoneBuilder->getZoneBank().getCategoriesType (allCategoryTypes); + for(uint32 i = 0; i < allCategoryTypes.size(); ++i) + addToAllCatTypeCB (allCategoryTypes[i]); + + // Select right category types + CComboBox* pCB; + pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE1); + pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterType1.c_str()); + pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE2); + pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterType2.c_str()); + pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE3); + pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterType3.c_str()); + pCB = (CComboBox*)GetDlgItem (IDC_CATTYPE4); + pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterType4.c_str()); + + updateComboPairAndFilter (IDC_CATTYPE1, IDC_CATVALUE1, &_MainFrame->_ZoneBuilder->_FilterType1); + pCB = (CComboBox*)GetDlgItem (IDC_CATVALUE1); + pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterValue1.c_str()); + updateComboPairAndFilter (IDC_CATTYPE2, IDC_CATVALUE2, &_MainFrame->_ZoneBuilder->_FilterType2); + pCB = (CComboBox*)GetDlgItem (IDC_CATVALUE2); + pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterValue2.c_str()); + updateComboPairAndFilter (IDC_CATTYPE3, IDC_CATVALUE3, &_MainFrame->_ZoneBuilder->_FilterType3); + pCB = (CComboBox*)GetDlgItem (IDC_CATVALUE3); + pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterValue3.c_str()); + updateComboPairAndFilter (IDC_CATTYPE4, IDC_CATVALUE4, &_MainFrame->_ZoneBuilder->_FilterType4); + pCB = (CComboBox*)GetDlgItem (IDC_CATVALUE4); + pCB->SelectString (-1, _MainFrame->_ZoneBuilder->_FilterValue4.c_str()); + + // Select right operators + CButton *pButAnd, *pButOr; + pButAnd = (CButton*)GetDlgItem(IDC_AND2); + pButOr =(CButton*)GetDlgItem(IDC_OR2); + if (_MainFrame->_ZoneBuilder->_FilterOperator2 == 0) + pButAnd->SetCheck (1); + else + pButOr->SetCheck (1); + + pButAnd = (CButton*)GetDlgItem(IDC_AND3); + pButOr =(CButton*)GetDlgItem(IDC_OR3); + if (_MainFrame->_ZoneBuilder->_FilterOperator3 == 0) + pButAnd->SetCheck (1); + else + pButOr->SetCheck (1); + + pButAnd = (CButton*)GetDlgItem(IDC_AND4); + pButOr =(CButton*)GetDlgItem(IDC_OR4); + if (_MainFrame->_ZoneBuilder->_FilterOperator4 == 0) + pButAnd->SetCheck (1); + else + pButOr->SetCheck (1); + + CButton *pButRan = (CButton*)GetDlgItem(IDC_RANDOM); + if (_MainFrame->_ZoneBuilder->_RandomSelection) + pButRan->SetCheck (1); + else + pButRan->SetCheck (0); + + CButton *pButton; + if (_MainFrame->_ZoneBuilder->_ApplyRotType == 1) // Random + { + pButton = (CButton*)GetDlgItem(IDC_ROTRANDOM); + pButton->SetCheck (1); + } + else if (_MainFrame->_ZoneBuilder->_ApplyRotType == 0) // Normal + { + switch (_MainFrame->_ZoneBuilder->_ApplyRot) + { + case 0: pButton = (CButton*)GetDlgItem(IDC_ROT0); break; + case 1: pButton = (CButton*)GetDlgItem(IDC_ROT90); break; + case 2: pButton = (CButton*)GetDlgItem(IDC_ROT180); break; + case 3: pButton = (CButton*)GetDlgItem(IDC_ROT270); break; + } + pButton->SetCheck (1); + } + else if (_MainFrame->_ZoneBuilder->_ApplyRotType == 2) // Cycle + { + pButton = (CButton*)GetDlgItem(IDC_ROTCYCLE); + pButton->SetCheck (1); + } + + if (_MainFrame->_ZoneBuilder->_ApplyFlipType == 1) // Random + { + pButton = (CButton*)GetDlgItem(IDC_FLIPRANDOM); + pButton->SetCheck (1); + } + else if (_MainFrame->_ZoneBuilder->_ApplyFlipType == 0) // Normal + { + switch (_MainFrame->_ZoneBuilder->_ApplyFlip) + { + case 0: pButton = (CButton*)GetDlgItem(IDC_FLIPNO); break; + case 1: pButton = (CButton*)GetDlgItem(IDC_FLIPYES); break; + } + pButton->SetCheck (1); + } + else if (_MainFrame->_ZoneBuilder->_ApplyFlipType == 2) // Cycle + { + pButton = (CButton*)GetDlgItem(IDC_FLIPCYCLE); + pButton->SetCheck (1); + } + + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +#define LIST_TOP 170 + +// --------------------------------------------------------------------------- +int CToolsZone::OnCreate (LPCREATESTRUCT lpCreateStruct) +{ + if (CFormView::OnCreate (lpCreateStruct) == -1) + return -1; + CRect iniRect; + GetClientRect(&iniRect); + iniRect.top = LIST_TOP; iniRect.left = 10; + iniRect.right -= 20; iniRect.bottom -= 20; + _List.Create (WS_CHILD|WS_VISIBLE|WS_BORDER|WS_HSCROLL|WS_VSCROLL|LBS_OWNERDRAWVARIABLE|LBS_NOTIFY, + iniRect, this, IDC_LIST); + _List.setTool (this); + _ListCreated = true; + return 0; +} + +// --------------------------------------------------------------------------- +void CToolsZone::uninit() +{ +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSize (UINT nType, int cx, int cy) +{ + CFormView::OnSize (nType, cx, cy); + // Resize list ctrl to fill the whole view. + if (_ListCreated) + { + CRect iniRect; + GetClientRect(&iniRect); + + iniRect.top = LIST_TOP; iniRect.left = 10; + iniRect.right -= 10; iniRect.bottom -= 10; + + getListCtrl()->MoveWindow (&iniRect); + } +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnPaint() +{ + getListCtrl()->ShowScrollBar(SB_VERT); + CFormView::OnPaint(); +} + +// --------------------------------------------------------------------------- +void CToolsZone::updateComboPairAndFilter (int CatTypeId, int CatValueId, string *pFilterType) +{ + uint32 i; + char sTmp[256]; + CComboBox *pCBType, *pCBValue; + pCBType = (CComboBox*)GetDlgItem (CatTypeId); + pCBType->GetLBText (pCBType->GetCurSel(), sTmp); + *pFilterType = sTmp; + pCBValue = (CComboBox*)GetDlgItem (CatValueId); + pCBValue->ResetContent (); + + if (*pFilterType == STRING_UNUSED) + return; + + vector allCategoryValues; + _MainFrame->_ZoneBuilder->getZoneBank().getCategoryValues (*pFilterType, allCategoryValues); + for(i = 0; i < allCategoryValues.size(); ++i) + pCBValue->AddString (allCategoryValues[i].c_str()); + pCBValue->SetCurSel (0); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectCatType1 () +{ + updateComboPairAndFilter (IDC_CATTYPE1, IDC_CATVALUE1, &_MainFrame->_ZoneBuilder->_FilterType1); + OnSelectCatValue1 (); + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectCatType2 () +{ + updateComboPairAndFilter (IDC_CATTYPE2, IDC_CATVALUE2, &_MainFrame->_ZoneBuilder->_FilterType2); + OnSelectCatValue2 (); + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectCatType3 () +{ + updateComboPairAndFilter (IDC_CATTYPE3, IDC_CATVALUE3, &_MainFrame->_ZoneBuilder->_FilterType3); + OnSelectCatValue3 (); + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectCatType4 () +{ + updateComboPairAndFilter (IDC_CATTYPE4, IDC_CATVALUE4, &_MainFrame->_ZoneBuilder->_FilterType4); + OnSelectCatValue4 (); + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectCatValue1() +{ + char sTmp[256]; + CComboBox *pCBValue = (CComboBox*)GetDlgItem (IDC_CATVALUE1); + pCBValue->GetLBText (pCBValue->GetCurSel(), sTmp); + _MainFrame->_ZoneBuilder->_FilterValue1 = sTmp; + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectCatValue2() +{ + char sTmp[256]; + CComboBox *pCBValue = (CComboBox*)GetDlgItem (IDC_CATVALUE2); + pCBValue->GetLBText (pCBValue->GetCurSel(), sTmp); + _MainFrame->_ZoneBuilder->_FilterValue2 = sTmp; + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectCatValue3() +{ + char sTmp[256]; + CComboBox *pCBValue = (CComboBox*)GetDlgItem (IDC_CATVALUE3); + pCBValue->GetLBText (pCBValue->GetCurSel(), sTmp); + _MainFrame->_ZoneBuilder->_FilterValue3 = sTmp; + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectCatValue4() +{ + char sTmp[256]; + CComboBox *pCBValue = (CComboBox*)GetDlgItem (IDC_CATVALUE4); + pCBValue->GetLBText (pCBValue->GetCurSel(), sTmp); + _MainFrame->_ZoneBuilder->_FilterValue4 = sTmp; + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectAnd2 () +{ + if (_MainFrame->_ZoneBuilder->_FilterOperator2 == 0) return; + _MainFrame->_ZoneBuilder->_FilterOperator2 = 0; // And + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectOr2 () +{ + if (_MainFrame->_ZoneBuilder->_FilterOperator2 == 1) return; + _MainFrame->_ZoneBuilder->_FilterOperator2 = 1; // Or + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectAnd3 () +{ + if (_MainFrame->_ZoneBuilder->_FilterOperator3 == 0) return; + _MainFrame->_ZoneBuilder->_FilterOperator3 = 0; // And + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectOr3 () +{ + if (_MainFrame->_ZoneBuilder->_FilterOperator3 == 1) return; + _MainFrame->_ZoneBuilder->_FilterOperator3 = 1; // Or + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectAnd4 () +{ + if (_MainFrame->_ZoneBuilder->_FilterOperator3 == 0) return; + _MainFrame->_ZoneBuilder->_FilterOperator4 = 0; // And + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectOr4 () +{ + if (_MainFrame->_ZoneBuilder->_FilterOperator4 == 1) return; + _MainFrame->_ZoneBuilder->_FilterOperator4 = 1; // Or + _MainFrame->_ZoneBuilder->updateToolsZone (); +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectRandom() +{ + _MainFrame->_ZoneBuilder->_RandomSelection = !_MainFrame->_ZoneBuilder->_RandomSelection; + if (_MainFrame->_ZoneBuilder->_RandomSelection) + { + CButton *pBut = (CButton*)GetDlgItem (IDC_FULL_CYCLE); + pBut->SetCheck (0); + _MainFrame->_ZoneBuilder->_CycleSelection = false; + } +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectCycle () +{ + _MainFrame->_ZoneBuilder->_CycleSelection = !_MainFrame->_ZoneBuilder->_CycleSelection; + if (_MainFrame->_ZoneBuilder->_CycleSelection) + { + CButton *pBut = (CButton*)GetDlgItem (IDC_RANDOM); + pBut->SetCheck (0); + _MainFrame->_ZoneBuilder->_RandomSelection = false; + } +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectNotPropagate () +{ + _MainFrame->_ZoneBuilder->_NotPropagate = !_MainFrame->_ZoneBuilder->_NotPropagate; +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectForce () +{ + _MainFrame->_ZoneBuilder->_Force = !_MainFrame->_ZoneBuilder->_Force; + if (_MainFrame->_ZoneBuilder->_Force) + { + CButton *pBut = (CButton*)GetDlgItem (IDC_NOT_PROPAGATE); + pBut->SetCheck (1); + _MainFrame->_ZoneBuilder->_NotPropagate = true; + } +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelChange () +{ + // Select the next item of the currently selected one. + int nIndex = _List.GetCurSel(); + if (nIndex != LB_ERR) + { + // Here for some reason we cant use the GetText(nIndex, str) function... + _MainFrame->_ZoneBuilder->_CurSelectedZone = nIndex;//_List.getItem (nIndex); + } + else + { + _MainFrame->_ZoneBuilder->_CurSelectedZone = -1;//STRING_UNUSED; + } +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectRot0 () +{ + _MainFrame->_ZoneBuilder->_ApplyRot = 0; + _MainFrame->_ZoneBuilder->_ApplyRotType = 0; +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectRot90 () +{ + _MainFrame->_ZoneBuilder->_ApplyRot = 1; + _MainFrame->_ZoneBuilder->_ApplyRotType = 0; +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectRot180 () +{ + _MainFrame->_ZoneBuilder->_ApplyRot = 2; + _MainFrame->_ZoneBuilder->_ApplyRotType = 0; +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectRot270 () +{ + _MainFrame->_ZoneBuilder->_ApplyRot = 3; + _MainFrame->_ZoneBuilder->_ApplyRotType = 0; +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectRotRan () +{ + _MainFrame->_ZoneBuilder->_ApplyRotType = 1; +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectRotCycle () +{ + _MainFrame->_ZoneBuilder->_ApplyRotType = 2; +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectFlipNo () +{ + _MainFrame->_ZoneBuilder->_ApplyFlip = 0; + _MainFrame->_ZoneBuilder->_ApplyFlipType = 0; +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectFlipYes () +{ + _MainFrame->_ZoneBuilder->_ApplyFlip = 1; + _MainFrame->_ZoneBuilder->_ApplyFlipType = 0; +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectFlipRan () +{ + _MainFrame->_ZoneBuilder->_ApplyFlipType = 1; +} + +// --------------------------------------------------------------------------- +void CToolsZone::OnSelectFlipCycle () +{ + _MainFrame->_ZoneBuilder->_ApplyFlipType = 2; } \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_zone.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_zone.h index 9acb2959d..67cdfdf81 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_zone.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/tools_zone.h @@ -1,137 +1,137 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef TOOLSZONE_H -#define TOOLSZONE_H - -// *************************************************************************** - -#include -#include "resource.h" - -#include -#include - -// *************************************************************************** - -class CMainFrame; -class CToolsZone; - -// *************************************************************************** - -class CToolsZoneList : public CListBox -{ - bool _MouseLDown; - CToolsZone *_Tools; - std::vector _ItemNames; - std::vector _BitmapList; - -public: - - CToolsZoneList (); - - void setTool (CToolsZone *pTool); - void setImages (std::vector &vBitmaps); - void addItem (const std::string &itemName); - const std::string &getItem (uint32 nIndex); - void reset (); - - void DrawItem (LPDRAWITEMSTRUCT); - void MeasureItem (LPMEASUREITEMSTRUCT); - int CompareItem (LPCOMPAREITEMSTRUCT); - - // For some obscur reason on subclassing windows system we cant use the message map - // mechanism so we have to notify the parent by hand - - void notifyParent(); - - afx_msg void OnLButtonDown (UINT nFlags, CPoint point); - afx_msg void OnLButtonUp (UINT nFlags, CPoint point); - afx_msg void OnMouseMove (UINT nFlags, CPoint point); - - - DECLARE_MESSAGE_MAP() - -}; - -// *************************************************************************** - -class CToolsZone : public CFormView -{ - DECLARE_DYNCREATE(CToolsZone) - - CToolsZoneList _List; - bool _ListCreated; - - CMainFrame *_MainFrame; - -private: - - void addToAllCatTypeCB (const std::string &Name); - void updateComboPairAndFilter (int CatTypeId, int CatValueId, std::string *pFilterType); - -public: - - CToolsZone(); - - CToolsZoneList *getListCtrl(); - - void init (CMainFrame *pMF); - void uninit (); - - // Event handlers - afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct); - afx_msg void OnSize (UINT nType, int cx, int cy); - afx_msg void OnPaint (); - - afx_msg void OnSelectCatType1 (); - afx_msg void OnSelectCatType2 (); - afx_msg void OnSelectCatType3 (); - afx_msg void OnSelectCatType4 (); - afx_msg void OnSelectCatValue1 (); - afx_msg void OnSelectCatValue2 (); - afx_msg void OnSelectCatValue3 (); - afx_msg void OnSelectCatValue4 (); - afx_msg void OnSelectAnd2 (); - afx_msg void OnSelectOr2 (); - afx_msg void OnSelectAnd3 (); - afx_msg void OnSelectOr3 (); - afx_msg void OnSelectAnd4 (); - afx_msg void OnSelectOr4 (); - afx_msg void OnSelectRandom (); - afx_msg void OnSelectCycle (); - afx_msg void OnSelectNotPropagate (); - afx_msg void OnSelectForce (); - - afx_msg void OnSelectRot0 (); - afx_msg void OnSelectRot90 (); - afx_msg void OnSelectRot180 (); - afx_msg void OnSelectRot270 (); - afx_msg void OnSelectRotRan (); - afx_msg void OnSelectRotCycle (); - afx_msg void OnSelectFlipNo (); - afx_msg void OnSelectFlipYes (); - afx_msg void OnSelectFlipRan (); - afx_msg void OnSelectFlipCycle (); - - void OnSelChange (); // Notified by hand - - DECLARE_MESSAGE_MAP() -}; - -// *************************************************************************** - -#endif // TOOLSZONE_H +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef TOOLSZONE_H +#define TOOLSZONE_H + +// *************************************************************************** + +#include +#include "resource.h" + +#include +#include + +// *************************************************************************** + +class CMainFrame; +class CToolsZone; + +// *************************************************************************** + +class CToolsZoneList : public CListBox +{ + bool _MouseLDown; + CToolsZone *_Tools; + std::vector _ItemNames; + std::vector _BitmapList; + +public: + + CToolsZoneList (); + + void setTool (CToolsZone *pTool); + void setImages (std::vector &vBitmaps); + void addItem (const std::string &itemName); + const std::string &getItem (uint32 nIndex); + void reset (); + + void DrawItem (LPDRAWITEMSTRUCT); + void MeasureItem (LPMEASUREITEMSTRUCT); + int CompareItem (LPCOMPAREITEMSTRUCT); + + // For some obscur reason on subclassing windows system we cant use the message map + // mechanism so we have to notify the parent by hand + + void notifyParent(); + + afx_msg void OnLButtonDown (UINT nFlags, CPoint point); + afx_msg void OnLButtonUp (UINT nFlags, CPoint point); + afx_msg void OnMouseMove (UINT nFlags, CPoint point); + + + DECLARE_MESSAGE_MAP() + +}; + +// *************************************************************************** + +class CToolsZone : public CFormView +{ + DECLARE_DYNCREATE(CToolsZone) + + CToolsZoneList _List; + bool _ListCreated; + + CMainFrame *_MainFrame; + +private: + + void addToAllCatTypeCB (const std::string &Name); + void updateComboPairAndFilter (int CatTypeId, int CatValueId, std::string *pFilterType); + +public: + + CToolsZone(); + + CToolsZoneList *getListCtrl(); + + void init (CMainFrame *pMF); + void uninit (); + + // Event handlers + afx_msg int OnCreate (LPCREATESTRUCT lpCreateStruct); + afx_msg void OnSize (UINT nType, int cx, int cy); + afx_msg void OnPaint (); + + afx_msg void OnSelectCatType1 (); + afx_msg void OnSelectCatType2 (); + afx_msg void OnSelectCatType3 (); + afx_msg void OnSelectCatType4 (); + afx_msg void OnSelectCatValue1 (); + afx_msg void OnSelectCatValue2 (); + afx_msg void OnSelectCatValue3 (); + afx_msg void OnSelectCatValue4 (); + afx_msg void OnSelectAnd2 (); + afx_msg void OnSelectOr2 (); + afx_msg void OnSelectAnd3 (); + afx_msg void OnSelectOr3 (); + afx_msg void OnSelectAnd4 (); + afx_msg void OnSelectOr4 (); + afx_msg void OnSelectRandom (); + afx_msg void OnSelectCycle (); + afx_msg void OnSelectNotPropagate (); + afx_msg void OnSelectForce (); + + afx_msg void OnSelectRot0 (); + afx_msg void OnSelectRot90 (); + afx_msg void OnSelectRot180 (); + afx_msg void OnSelectRot270 (); + afx_msg void OnSelectRotRan (); + afx_msg void OnSelectRotCycle (); + afx_msg void OnSelectFlipNo (); + afx_msg void OnSelectFlipYes (); + afx_msg void OnSelectFlipRan (); + afx_msg void OnSelectFlipCycle (); + + void OnSelChange (); // Notified by hand + + DECLARE_MESSAGE_MAP() +}; + +// *************************************************************************** + +#endif // TOOLSZONE_H diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/type_dlg.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/type_dlg.cpp index 5b18f95e8..a0e27e271 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/type_dlg.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/type_dlg.cpp @@ -1,87 +1,87 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// TypeDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "type_dlg.h" - -///////////////////////////////////////////////////////////////////////////// -// CTypeDlg dialog - - -CTypeDlg::CTypeDlg(CWnd* pParent /*=NULL*/) - : CDialog(CTypeDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CTypeDlg) - EditName = _T(""); - ButtonColor.setColor(CRGBA(255,255,255,255)); - //}}AFX_DATA_INIT -} - - -void CTypeDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CTypeDlg) - DDX_Control(pDX, IDC_BUTTONCOLOR, ButtonColor); - DDX_Text(pDX, IDC_EDITNAME, EditName); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CTypeDlg, CDialog) - //{{AFX_MSG_MAP(CTypeDlg) - ON_BN_CLICKED(IDC_BUTTONCOLOR, OnButtoncolor) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CTypeDlg message handlers - -void CTypeDlg::OnButtoncolor() -{ - // TODO: Add your control notification handler code here - CColorDialog coldlg; - if (coldlg.DoModal() == IDOK) - { - int r = GetRValue(coldlg.GetColor()); - int g = GetGValue(coldlg.GetColor()); - int b = GetBValue(coldlg.GetColor()); - ButtonColor.setColor(CRGBA(r,g,b,255)); - Invalidate(); - } -} - -BOOL CTypeDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - ButtonColor.setColor (ButtonColorValue); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -void CTypeDlg::OnOK() -{ - // TODO: Add extra validation here - ButtonColorValue = ButtonColor.getColor(); - CDialog::OnOK(); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// TypeDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "type_dlg.h" + +///////////////////////////////////////////////////////////////////////////// +// CTypeDlg dialog + + +CTypeDlg::CTypeDlg(CWnd* pParent /*=NULL*/) + : CDialog(CTypeDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTypeDlg) + EditName = _T(""); + ButtonColor.setColor(CRGBA(255,255,255,255)); + //}}AFX_DATA_INIT +} + + +void CTypeDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTypeDlg) + DDX_Control(pDX, IDC_BUTTONCOLOR, ButtonColor); + DDX_Text(pDX, IDC_EDITNAME, EditName); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTypeDlg, CDialog) + //{{AFX_MSG_MAP(CTypeDlg) + ON_BN_CLICKED(IDC_BUTTONCOLOR, OnButtoncolor) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CTypeDlg message handlers + +void CTypeDlg::OnButtoncolor() +{ + // TODO: Add your control notification handler code here + CColorDialog coldlg; + if (coldlg.DoModal() == IDOK) + { + int r = GetRValue(coldlg.GetColor()); + int g = GetGValue(coldlg.GetColor()); + int b = GetBValue(coldlg.GetColor()); + ButtonColor.setColor(CRGBA(r,g,b,255)); + Invalidate(); + } +} + +BOOL CTypeDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + ButtonColor.setColor (ButtonColorValue); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +void CTypeDlg::OnOK() +{ + // TODO: Add extra validation here + ButtonColorValue = ButtonColor.getColor(); + CDialog::OnOK(); +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/type_dlg.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/type_dlg.h index 562a3ce0e..ad9f5f3ea 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/type_dlg.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/type_dlg.h @@ -1,69 +1,69 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_TYPEDLG_H__755F39BC_15C5_44AD_BFB0_B52D335F3173__INCLUDED_) -#define AFX_TYPEDLG_H__755F39BC_15C5_44AD_BFB0_B52D335F3173__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// TypeDlg.h : header file -// -#include "resource.h" -#include "color_button.h" - -///////////////////////////////////////////////////////////////////////////// -// CTypeDlg dialog - -class CTypeDlg : public CDialog -{ -// Construction -public: - CTypeDlg(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CTypeDlg) - enum { IDD = IDD_TYPE }; - CColorButton ButtonColor; - - CRGBA ButtonColorValue; - CString EditName; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CTypeDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CTypeDlg) - afx_msg void OnButtoncolor(); - virtual BOOL OnInitDialog(); - virtual void OnOK(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_TYPEDLG_H__755F39BC_15C5_44AD_BFB0_B52D335F3173__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_TYPEDLG_H__755F39BC_15C5_44AD_BFB0_B52D335F3173__INCLUDED_) +#define AFX_TYPEDLG_H__755F39BC_15C5_44AD_BFB0_B52D335F3173__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TypeDlg.h : header file +// +#include "resource.h" +#include "color_button.h" + +///////////////////////////////////////////////////////////////////////////// +// CTypeDlg dialog + +class CTypeDlg : public CDialog +{ +// Construction +public: + CTypeDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CTypeDlg) + enum { IDD = IDD_TYPE }; + CColorButton ButtonColor; + + CRGBA ButtonColorValue; + CString EditName; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CTypeDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CTypeDlg) + afx_msg void OnButtoncolor(); + virtual BOOL OnInitDialog(); + virtual void OnOK(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_TYPEDLG_H__755F39BC_15C5_44AD_BFB0_B52D335F3173__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/type_manager_dlg.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/type_manager_dlg.cpp index ef84eb62f..6a48d20a5 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/type_manager_dlg.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/type_manager_dlg.cpp @@ -1,146 +1,146 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// TypeManagerDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "type_manager_dlg.h" - -#include "type_dlg.h" - -using namespace std; - -///////////////////////////////////////////////////////////////////////////// -// CTypeManagerDlg dialog - -// --------------------------------------------------------------------------- -CTypeManagerDlg::CTypeManagerDlg(CWnd* pParent /*=NULL*/) - : CDialog(CTypeManagerDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CTypeManagerDlg) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - -// --------------------------------------------------------------------------- -void CTypeManagerDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CTypeManagerDlg) - DDX_Control(pDX, IDC_LISTTYPE, ListType); - //}}AFX_DATA_MAP -} - -// --------------------------------------------------------------------------- -void CTypeManagerDlg::set (const vector &types) -{ - LocalTypes = types; -} - -// --------------------------------------------------------------------------- -const vector CTypeManagerDlg::get () -{ - return LocalTypes; -} - -// --------------------------------------------------------------------------- -BEGIN_MESSAGE_MAP(CTypeManagerDlg, CDialog) - //{{AFX_MSG_MAP(CTypeManagerDlg) - ON_BN_CLICKED(IDC_ADDTYPE, OnAddtype) - ON_BN_CLICKED(IDC_EDITTYPE, OnEdittype) - ON_BN_CLICKED(IDC_REMOVETYPE, OnRemovetype) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CTypeManagerDlg message handlers - -void CTypeManagerDlg::OnAddtype() -{ - // TODO: Add your control notification handler code here - CTypeDlg typeDlg(this); - if (typeDlg.DoModal() == IDOK) - { - SType typeTmp; - typeTmp.Name = (LPCSTR)typeDlg.EditName; - typeTmp.Color = typeDlg.ButtonColorValue; - // Check if the name of the new type is the same as an existing one - bool bFound = false; - for (uint32 i = 0; i < LocalTypes.size(); ++i) - if (LocalTypes[i].Name == typeTmp.Name) - { - bFound = true; - break; - } - // If not Add it to the 2 lists (win and internal) - if (!bFound) - { - LocalTypes.push_back (typeTmp); - ListType.InsertString(-1, typeTmp.Name.c_str()); - } - } -} - -void CTypeManagerDlg::OnEdittype() -{ - // TODO: Add your control notification handler code here - CTypeDlg typeDlg(this); - - int cursel = ListType.GetCurSel(); - if (cursel == -1) - return; - - typeDlg.EditName = LocalTypes[cursel].Name.c_str(); - typeDlg.ButtonColorValue = LocalTypes[cursel].Color; - - if (typeDlg.DoModal() == IDOK) - { - SType typeTmp; - typeTmp.Name = (LPCSTR)typeDlg.EditName; - typeTmp.Color = typeDlg.ButtonColorValue; - LocalTypes[cursel] = typeTmp; - ListType.DeleteString (ListType.GetCurSel()); - ListType.InsertString (cursel, typeTmp.Name.c_str()); - } -} - -void CTypeManagerDlg::OnRemovetype() -{ - // TODO: Add your control notification handler code here - int cursel = ListType.GetCurSel(); - if (cursel == -1) - return; - for (uint32 i = cursel; i < (LocalTypes.size()-1); ++i) - LocalTypes[i] = LocalTypes[i+1]; - LocalTypes.resize(LocalTypes.size()-1); - ListType.DeleteString (ListType.GetCurSel()); -} - -BOOL CTypeManagerDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - for (uint32 i = 0; i < LocalTypes.size(); ++i) - { - ListType.InsertString(-1, LocalTypes[i].Name.c_str()); - } - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// TypeManagerDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "type_manager_dlg.h" + +#include "type_dlg.h" + +using namespace std; + +///////////////////////////////////////////////////////////////////////////// +// CTypeManagerDlg dialog + +// --------------------------------------------------------------------------- +CTypeManagerDlg::CTypeManagerDlg(CWnd* pParent /*=NULL*/) + : CDialog(CTypeManagerDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTypeManagerDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + +// --------------------------------------------------------------------------- +void CTypeManagerDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTypeManagerDlg) + DDX_Control(pDX, IDC_LISTTYPE, ListType); + //}}AFX_DATA_MAP +} + +// --------------------------------------------------------------------------- +void CTypeManagerDlg::set (const vector &types) +{ + LocalTypes = types; +} + +// --------------------------------------------------------------------------- +const vector CTypeManagerDlg::get () +{ + return LocalTypes; +} + +// --------------------------------------------------------------------------- +BEGIN_MESSAGE_MAP(CTypeManagerDlg, CDialog) + //{{AFX_MSG_MAP(CTypeManagerDlg) + ON_BN_CLICKED(IDC_ADDTYPE, OnAddtype) + ON_BN_CLICKED(IDC_EDITTYPE, OnEdittype) + ON_BN_CLICKED(IDC_REMOVETYPE, OnRemovetype) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CTypeManagerDlg message handlers + +void CTypeManagerDlg::OnAddtype() +{ + // TODO: Add your control notification handler code here + CTypeDlg typeDlg(this); + if (typeDlg.DoModal() == IDOK) + { + SType typeTmp; + typeTmp.Name = (LPCSTR)typeDlg.EditName; + typeTmp.Color = typeDlg.ButtonColorValue; + // Check if the name of the new type is the same as an existing one + bool bFound = false; + for (uint32 i = 0; i < LocalTypes.size(); ++i) + if (LocalTypes[i].Name == typeTmp.Name) + { + bFound = true; + break; + } + // If not Add it to the 2 lists (win and internal) + if (!bFound) + { + LocalTypes.push_back (typeTmp); + ListType.InsertString(-1, typeTmp.Name.c_str()); + } + } +} + +void CTypeManagerDlg::OnEdittype() +{ + // TODO: Add your control notification handler code here + CTypeDlg typeDlg(this); + + int cursel = ListType.GetCurSel(); + if (cursel == -1) + return; + + typeDlg.EditName = LocalTypes[cursel].Name.c_str(); + typeDlg.ButtonColorValue = LocalTypes[cursel].Color; + + if (typeDlg.DoModal() == IDOK) + { + SType typeTmp; + typeTmp.Name = (LPCSTR)typeDlg.EditName; + typeTmp.Color = typeDlg.ButtonColorValue; + LocalTypes[cursel] = typeTmp; + ListType.DeleteString (ListType.GetCurSel()); + ListType.InsertString (cursel, typeTmp.Name.c_str()); + } +} + +void CTypeManagerDlg::OnRemovetype() +{ + // TODO: Add your control notification handler code here + int cursel = ListType.GetCurSel(); + if (cursel == -1) + return; + for (uint32 i = cursel; i < (LocalTypes.size()-1); ++i) + LocalTypes[i] = LocalTypes[i+1]; + LocalTypes.resize(LocalTypes.size()-1); + ListType.DeleteString (ListType.GetCurSel()); +} + +BOOL CTypeManagerDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + for (uint32 i = 0; i < LocalTypes.size(); ++i) + { + ListType.InsertString(-1, LocalTypes[i].Name.c_str()); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/type_manager_dlg.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/type_manager_dlg.h index 34ad24c75..8e4dd28ee 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/type_manager_dlg.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/type_manager_dlg.h @@ -1,71 +1,71 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_TypeManagerDlg_H__BCA5979B_8741_4D1A_BCA7_ECFAFB8A14E1__INCLUDED_) -#define AFX_TypeManagerDlg_H__BCA5979B_8741_4D1A_BCA7_ECFAFB8A14E1__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// TypeManagerDlg.h : header file -// -#include "main_frm.h" -#include "resource.h" -///////////////////////////////////////////////////////////////////////////// -// CTypeManagerDlg dialog - -class CTypeManagerDlg : public CDialog -{ - - std::vector LocalTypes; - -// Construction -public: - CTypeManagerDlg(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CTypeManagerDlg) - enum { IDD = IDD_TYPEMANAGER }; - CListBox ListType; - //}}AFX_DATA - - void set (const std::vector &types); - const std::vector get (); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CTypeManagerDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CTypeManagerDlg) - afx_msg void OnAddtype(); - afx_msg void OnEdittype(); - afx_msg void OnRemovetype(); - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_TypeManagerDlg_H__BCA5979B_8741_4D1A_BCA7_ECFAFB8A14E1__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_TypeManagerDlg_H__BCA5979B_8741_4D1A_BCA7_ECFAFB8A14E1__INCLUDED_) +#define AFX_TypeManagerDlg_H__BCA5979B_8741_4D1A_BCA7_ECFAFB8A14E1__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TypeManagerDlg.h : header file +// +#include "main_frm.h" +#include "resource.h" +///////////////////////////////////////////////////////////////////////////// +// CTypeManagerDlg dialog + +class CTypeManagerDlg : public CDialog +{ + + std::vector LocalTypes; + +// Construction +public: + CTypeManagerDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CTypeManagerDlg) + enum { IDD = IDD_TYPEMANAGER }; + CListBox ListType; + //}}AFX_DATA + + void set (const std::vector &types); + const std::vector get (); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CTypeManagerDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CTypeManagerDlg) + afx_msg void OnAddtype(); + afx_msg void OnEdittype(); + afx_msg void OnRemovetype(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_TypeManagerDlg_H__BCA5979B_8741_4D1A_BCA7_ECFAFB8A14E1__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/type_sel_dlg.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/type_sel_dlg.cpp index 419b28df4..67940b654 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/type_sel_dlg.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/type_sel_dlg.cpp @@ -1,80 +1,80 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// TypeSelDlg.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor.h" -#include "type_sel_dlg.h" - -///////////////////////////////////////////////////////////////////////////// -// CTypeSelDlg dialog - - -CTypeSelDlg::CTypeSelDlg(CWnd* pParent /*=NULL*/) - : CDialog(CTypeSelDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CTypeSelDlg) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT -} - - -void CTypeSelDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CTypeSelDlg) - DDX_Control(pDX, IDC_LIST, TypeList); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CTypeSelDlg, CDialog) - //{{AFX_MSG_MAP(CTypeSelDlg) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CTypeSelDlg message handlers - -void CTypeSelDlg::OnOK() -{ - // TODO: Add extra validation here - - if (TypeList.GetCurSel() == -1) - return; - - CString sTmp; - TypeList.GetText(TypeList.GetCurSel(), sTmp); - _TypeSelected = (LPCSTR)sTmp; - - CDialog::OnOK(); -} - -BOOL CTypeSelDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // TODO: Add extra initialization here - for (uint32 i = 0; i < _TypesInit->size(); ++i) - { - TypeList.InsertString(-1, _TypesInit->operator[](i).Name.c_str()); - } - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// TypeSelDlg.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor.h" +#include "type_sel_dlg.h" + +///////////////////////////////////////////////////////////////////////////// +// CTypeSelDlg dialog + + +CTypeSelDlg::CTypeSelDlg(CWnd* pParent /*=NULL*/) + : CDialog(CTypeSelDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CTypeSelDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT +} + + +void CTypeSelDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CTypeSelDlg) + DDX_Control(pDX, IDC_LIST, TypeList); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CTypeSelDlg, CDialog) + //{{AFX_MSG_MAP(CTypeSelDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CTypeSelDlg message handlers + +void CTypeSelDlg::OnOK() +{ + // TODO: Add extra validation here + + if (TypeList.GetCurSel() == -1) + return; + + CString sTmp; + TypeList.GetText(TypeList.GetCurSel(), sTmp); + _TypeSelected = (LPCSTR)sTmp; + + CDialog::OnOK(); +} + +BOOL CTypeSelDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // TODO: Add extra initialization here + for (uint32 i = 0; i < _TypesInit->size(); ++i) + { + TypeList.InsertString(-1, _TypesInit->operator[](i).Name.c_str()); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/type_sel_dlg.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/type_sel_dlg.h index 3ee4d13a8..7febc8e2a 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/type_sel_dlg.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/type_sel_dlg.h @@ -1,71 +1,71 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_TYPESELDLG_H__C138FEAF_AB39_41BB_B71F_D903CE4DF909__INCLUDED_) -#define AFX_TYPESELDLG_H__C138FEAF_AB39_41BB_B71F_D903CE4DF909__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// TypeSelDlg.h : header file -// - -#include "main_frm.h" -#include "resource.h" - -///////////////////////////////////////////////////////////////////////////// -// CTypeSelDlg dialog - -class CTypeSelDlg : public CDialog -{ -// Construction -public: - - CTypeSelDlg(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - - std::vector *_TypesInit; - std::string _TypeSelected; - - //{{AFX_DATA(CTypeSelDlg) - enum { IDD = IDD_TYPESEL }; - CListBox TypeList; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CTypeSelDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CTypeSelDlg) - virtual void OnOK(); - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_TYPESELDLG_H__C138FEAF_AB39_41BB_B71F_D903CE4DF909__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_TYPESELDLG_H__C138FEAF_AB39_41BB_B71F_D903CE4DF909__INCLUDED_) +#define AFX_TYPESELDLG_H__C138FEAF_AB39_41BB_B71F_D903CE4DF909__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// TypeSelDlg.h : header file +// + +#include "main_frm.h" +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// CTypeSelDlg dialog + +class CTypeSelDlg : public CDialog +{ +// Construction +public: + + CTypeSelDlg(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + + std::vector *_TypesInit; + std::string _TypeSelected; + + //{{AFX_DATA(CTypeSelDlg) + enum { IDD = IDD_TYPESEL }; + CListBox TypeList; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CTypeSelDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CTypeSelDlg) + virtual void OnOK(); + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_TYPESELDLG_H__C138FEAF_AB39_41BB_B71F_D903CE4DF909__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor.cpp index b2fcee810..3b6a2fe1f 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor.cpp @@ -1,1051 +1,1051 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// world_editor.cpp : Defines the class behaviors for the application. -// - -#include "stdafx.h" -#include "world_editor.h" -#include -#include - -#include "main_frm.h" -#include "world_editor_doc.h" -#include "world_editor_view.h" -#include "editor_primitive.h" -#include "dialog_properties.h" -#include "primitive_configuration_dlg.h" -#include "splash_screen.h" -#include "file_dialog_ex.h" - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; -using namespace NL3D; - -bool DontUse3D = false; - -//CSplashScreen* splashScreen=new CSplashScreen; - -// *************************************************************************** -// CWorldEditorApp - -BEGIN_MESSAGE_MAP(CWorldEditorApp, CWinApp) - //{{AFX_MSG_MAP(CWorldEditorApp) - ON_COMMAND(ID_APP_ABOUT, OnAppAbout) - ON_COMMAND(ID_FILE_OPEN, OnFileOpen) - ON_COMMAND(ID_FILE_SAVE, OnFileSave) - ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs) - //}}AFX_MSG_MAP - // Standard file based document commands - ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) - ON_COMMAND(ID_FILE_OPEN, OnFileOpen) - ON_COMMAND(ID_FILE_SAVE, OnFileSave) - ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs) - // Standard print setup command - ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) -END_MESSAGE_MAP() - -// *************************************************************************** -// CWorldEditorApp construction - -CWorldEditorApp::CWorldEditorApp() -{ - // TODO: add construction code here, - // Place all significant initialization in InitInstance -} - -CWorldEditorApp::~CWorldEditorApp() -{ -} - -void CWorldEditorApp::deletePlugins() -{ - for(std::vector::iterator it = Plugins.begin(); it != Plugins.end(); ++it) - { - delete *it; - } -} - - - -// *************************************************************************** -// The one and only CWorldEditorApp object - -CWorldEditorApp theApp; - -// *************************************************************************** -// CWorldEditorApp initialization - -BOOL CWorldEditorApp::InitInstance() -{ - // init context - new CApplicationContext; - // Register class - - // Filter the log - NLMISC::createDebug(); - NLMISC::WarningLog->addNegativeFilter ("in not a string"); - CSplashScreen splashScreen; - splashScreen.Create(IDD_SPLASHSCREEN, theApp.GetMainWnd()); - splashScreen.ShowWindow(TRUE); - splashScreen.addLine(string("Register my classes for ligo")); - - // Register my classes for ligo - NLMISC::CClassRegistry::registerClass("CPrimPoint", CPrimPointEditor::creator, typeid(CPrimPointEditor).name()); - NLMISC::CClassRegistry::registerClass("CPrimNode", CPrimNodeEditor::creator, typeid(CPrimNodeEditor).name()); - NLMISC::CClassRegistry::registerClass("CPrimPath", CPrimPathEditor::creator, typeid(CPrimPathEditor).name()); - NLMISC::CClassRegistry::registerClass("CPrimZone", CPrimZoneEditor::creator, typeid(CPrimZoneEditor).name()); - NLMISC::CClassRegistry::registerClass("CPrimAlias", CPrimAliasEditor::creator, typeid(CPrimAliasEditor).name()); - - splashScreen.addLine(string("Init the quad tree")); - - // Init the quad tree - InitQuadGrid (); - - NLMISC_REGISTER_CLASS(CPrimBitmap); - - splashScreen.addLine(string("Init primitive class manager")); - - - // Init primitive class manager - if (!initPath ("world_editor_script.xml", splashScreen)) - return FALSE; - - splashScreen.addLine(string("Exe path")); - - // Exe path - ExePath = GetCommandLine (); - if (ExePath.size()>0) - { - if (ExePath[0] == '\"') - { - uint end=ExePath.find ('\"', 1); - if (end != string::npos) - { - ExePath = ExePath.substr (1, end-1); - } - else - { - nlassert (0); // no! - } - } - else - { - uint end=ExePath.find (' ', 1); - ExePath = ExePath.substr (0, end); - } - } - ExePath = CPath::standardizePath (NLMISC::CFile::getPath (ExePath)); - - splashScreen.addLine(string("Load the Ligoscape.cfg")); - - // Load the Ligoscape.cfg - try - { - string sConfigFileName = ExePath; - sConfigFileName += "ligoscape.cfg"; - - splashScreen.addLine(string("Load the config file")); - - // Load the config file - if (!Config.readConfigFile (sConfigFileName.c_str(), true)) - return FALSE; - - // set the primitive context - CPrimitiveContext::instance().CurrentLigoConfig = &Config; - } - catch (Exception& e) - { - ::MessageBox (NULL, e.what(), "Warning", MB_OK|MB_ICONEXCLAMATION); - - // Can't found the module put some default values - Config.CellSize = 160.0f; - Config.Snap = 1.0f; - } - - AfxEnableControlContainer(); - - splashScreen.addLine(string("Standard initialization")); - - - // Standard initialization - // If you are not using these features and wish to reduce the size - // of your final executable, you should remove from the following - // the specific initialization routines you do not need. - -#ifdef _AFXDLL - Enable3dControls(); // Call this when using MFC in a shared DLL -#else - Enable3dControlsStatic(); // Call this when linking to MFC statically -#endif - - splashScreen.addLine(string("Change the registry key")); - - // Change the registry key under which our settings are stored. - // TODO: You should modify this string to be something appropriate - // such as the name of your company or organization. - SetRegistryKey(_T("Nevrax")); - - LoadStdProfileSettings(15); // Load standard INI file options (including MRU) - - // Register the application's document templates. Document templates - // serve as the connection between documents, frame windows and views. - - CSingleDocTemplate* pDocTemplate; - pDocTemplate = new CSingleDocTemplate( - IDR_MAINFRAME, - RUNTIME_CLASS(CWorldEditorDoc), - RUNTIME_CLASS(CMainFrame), // main SDI frame window - RUNTIME_CLASS(CWorldEditorView)); - AddDocTemplate(pDocTemplate); - - splashScreen.addLine(string("Enable DDE Execute open")); - - - // Enable DDE Execute open - EnableShellOpen(); - RegDeleteKey (HKEY_CLASSES_ROOT, "Worldeditor.Document\\DefaultIcon"); - RegisterShellFileTypes(TRUE); - - // Parse command line for standard shell commands, DDE, file open - CCommandLineInfo cmdInfo; - ParseCommandLine(cmdInfo); - - // Dispatch commands specified on the command line - if (!ProcessShellCommand(cmdInfo)) - return FALSE; - - // The one and only window has been initialized, so show and update it. - m_pMainWnd->ShowWindow(SW_SHOW); - m_pMainWnd->UpdateWindow(); - - // Enable drag/drop open - m_pMainWnd->DragAcceptFiles(); - - splashScreen.addLine(string("Fill image list")); - - // Fill image list - ImageList.create (16, 16); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_POINT_HIDDEN); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_POINT_CLOSED); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_POINT_OPENED); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_LINE_HIDDEN); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_LINE_CLOSED); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_LINE_OPENED); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_ZONE_HIDDEN); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_ZONE_CLOSED); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_ZONE_OPENED); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_FOLDER_HIDDEN); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_FOLDER_OPENED); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_FOLDER_CLOSED); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_PROPERTY_HIDDEN); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_PROPERTY_CLOSED); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_PROPERTY_OPENED); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_ROOT_HIDDEN); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_ROOT_CLOSED); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_ROOT_OPENED); - ImageList.addResourceIcon (theApp.m_hInstance, IDI_ERROR_STRUCTURE); - - // Get icones - vector result; - CPath::getPathContent ("ui", true, false, true, result); - for (uint i=0; iGetMenu(); - - CMenu* menu = new CMenu(); - menu->CreatePopupMenu(); - dynamic_menu->InsertMenu(6, MF_BYPOSITION | MF_POPUP, (UINT)menu->GetSafeHmenu(), "Plugins"); - - for(uint k=0;kgetName(); - menu->InsertMenu( k, MF_BYPOSITION | MF_POPUP, ID_WINDOWS_PLUGINS+1 + k, retest.c_str() ); - menu->CheckMenuItem(ID_WINDOWS_PLUGINS+1 +k, MF_CHECKED); - } - - getMainFrame()->DrawMenuBar(); - getMainFrame()->onMenuModeLogic(); - - // Reset the primitive configurations - reloadPrimitiveConfiguration (); - splashScreen.ShowWindow(false); - splashScreen.DestroyWindow(); - - return TRUE; -} - -void CWorldEditorApp::loadPlugins() -{ - // 1st load the plugin configuration file -// char curDir[MAX_PATH]; -// GetCurrentDirectory (MAX_PATH, curDir); - - PluginConfig.load((ExePath+"/world_editor_plugin.cfg").c_str()); - - // enumerate the plugin variable. - CConfigFile::CVar *plugins = PluginConfig.getVarPtr("PluginsLibrary"); - - if (plugins != 0) - { - for (uint i=0; isize(); ++i) - { - string libname = plugins->asString(i)+nlLibSuffix+".dll"; - - //vl HMODULE h = AfxLoadLibrary(libname.c_str()); - NL_LIB_HANDLE h = nlLoadLibrary(libname.c_str()); - if (h == NULL) - continue; - - //FCreateSoundPlugin *pf = (FCreateSoundPlugin*) GetProcAddress(h, "createSoundPlugin"); - //JC: switch to the generic call as soon as possible - //vl FCreatePlugin *pf = (FCreatePlugin*) GetProcAddress(h, "createPlugin"); - FCreatePlugin *pf = (FCreatePlugin*) nlGetSymbolAddress(h, "createPlugin"); - - if (pf == NULL) - continue; - - // ok, the plugin is loaded. - IPluginCallback *pcb = (IPluginCallback*) pf(); - - if (pcb == 0) - continue; - - nlinfo("Plugins '%s' loaded", libname.c_str()); - Plugins.push_back(pcb); - - // init the plugin. - pcb->init(getMainFrame()); - } - } -} - -// *************************************************************************** - -bool CWorldEditorApp::reloadPrimitiveConfiguration () -{ - // Reset - Config.resetPrimitiveConfiguration (); - - // Load - if (!Config.readPrimitiveClass ("world_editor_primitive_configuration.xml", true)) - return false; - - // Init configurations - Configurations.clear (); - Configurations.resize (theApp.Config.getPrimitiveConfiguration().size()); - - // Create the PrimitiveConfigurationDlg - PrimitiveConfigurationDlg.destroy (); - PrimitiveConfigurationDlg.Create (IDD_PRIMITIVE_CONFIGURATION, m_pMainWnd); - return true; -} - -// *************************************************************************** -// CAboutDlg dialog used for App About - -class CAboutDlg : public CDialog -{ -public: - CAboutDlg(); - -// Dialog Data - //{{AFX_DATA(CAboutDlg) - enum { IDD = IDD_ABOUTBOX }; - CString m_videoMem; - //}}AFX_DATA - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CAboutDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - //{{AFX_MSG(CAboutDlg) - virtual BOOL OnInitDialog(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) -{ - //{{AFX_DATA_INIT(CAboutDlg) - m_videoMem = _T(""); - //}}AFX_DATA_INIT -} - -void CAboutDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CAboutDlg) - DDX_Text(pDX, IDC_STATIC_VIDEO_MEM, m_videoMem); - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) - //{{AFX_MSG_MAP(CAboutDlg) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// App command to run the dialog -void CWorldEditorApp::OnAppAbout() -{ - CAboutDlg aboutDlg; - aboutDlg.DoModal(); -} - -bool CWorldEditorApp::yesNoMessage (const char *format, ... ) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - return MessageBox (m_pMainWnd?m_pMainWnd->m_hWnd:NULL, buffer, "NeL World Editor", MB_YESNO|MB_ICONQUESTION) == IDYES; -} - -void CWorldEditorApp::errorMessage (const char *format, ... ) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - MessageBox (m_pMainWnd?m_pMainWnd->m_hWnd:NULL, buffer, "NeL World Editor", MB_OK|MB_ICONEXCLAMATION); -} - -void CWorldEditorApp::infoMessage (const char *format, ... ) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - MessageBox (m_pMainWnd?m_pMainWnd->m_hWnd:NULL, buffer, "NeL World Editor", MB_OK|MB_ICONINFORMATION); -} - -void CWorldEditorApp::syntaxError (const char *filename, xmlNodePtr xmlNode, const char *format, ...) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - errorMessage ("(%s), node (%s), line (%d) :\n%s", filename, xmlNode->name, (int)xmlNode->content, buffer); -} - -bool CWorldEditorApp::getPropertyString (std::string &result, const char *filename, xmlNodePtr xmlNode, const char *propName) -{ - // Call the CIXml version - if (!CIXml::getPropertyString (result, xmlNode, propName)) - { - // Output a formated error - syntaxError (filename, xmlNode, "Missing XML node property (%s)", propName); - return false; - } - return true; -} - -bool CWorldEditorApp::initPath (const char *filename, CSplashScreen &splashScreen) -{ - // The context strings - set contextStrings; - - // Read the document - CIFile file; - if (file.open (filename)) - { - try - { - // XML stream - CIXml xml; - xml.init (file); - - // Get the root node - xmlNodePtr root = xml.getRootNode (); - nlassert (root); - - // Check the header - if (strcmp ((const char*)root->name, "NEL_WORLD_EDITOR_CONFIG") == 0) - { - // Get the first search_path description - xmlNodePtr search_path = CIXml::getFirstChildNode (root, "SEARCH_PATH"); - if (search_path) - { - do - { - // Get the search_path name - std::string path; - if (getPropertyString (path, filename, search_path, "PATH")) - { - bool recurse = true; - string noRecurse; - if (CIXml::getPropertyString (noRecurse, search_path, "NO_RECURSE")) - { - if (toLower(noRecurse) == "true") - recurse = false; - } - - // Add the search path - CPath::addSearchPath (path, recurse, true, &splashScreen); - } - else - goto failed; - } - while (search_path = CIXml::getNextChildNode (search_path, "SEARCH_PATH")); - } - - // Get the documentation path - xmlNodePtr doc_path = CIXml::getFirstChildNode (root, "DOC_PATH"); - if (doc_path) - { - std::string path; - if (getPropertyString (path, filename, doc_path, "PATH")) - { - string fullPath = CPath::getFullPath(path); - // Store the doc path - DocPath = fullPath; - } - else - goto failed; - } - - // Ok - return true; - } - else - { - syntaxError (filename, root, "Wrong root node, should be NEL_WORLD_EDITOR_CONFIG"); - } - } - catch (Exception &e) - { - errorMessage ("File read error (%s):%s", filename, e.what ()); - } - } - else - { - errorMessage ("Can't open the file %s for reading.", filename); - } - -failed: - return false; -} - -// *************************************************************************** - -sint CWorldEditorApp::getActiveConfiguration (const NLLIGO::IPrimitive &primitive, uint searchBegin) const -{ - const std::vector &configurations = theApp.Config.getPrimitiveConfiguration(); - - uint i; - for (i=searchBegin; iprofileAllocatedTextureMemory(); - - m_videoMem = NLMISC::toString("%u Mo", mem/(1024*1024)).c_str(); - - UpdateData(FALSE); - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - -// *************************************************************************** - -void invalidateLeftView () -{ - CMainFrame *mf = getMainFrame (); - if (mf) - { - mf->m_wndSplitter.GetPane(0,0)->Invalidate (); - } -} - -// *************************************************************************** - -std::string numberize (const char *oldString, uint value) -{ - int i=strlen (oldString)-1; - while ((i>=0) && (((oldString[i]<='9') && (oldString[i]>='0')) || (oldString[i]==' '))) - { - // again - i--; - } - - // String new value - string newValue = oldString; - - // Found ? - if (i<0) - { - newValue.clear (); - } - else - { - newValue = newValue.substr (0, i+1); - // Append a space if there is no space nor underscore - if (newValue[i]!='_' && newValue[i]!=' ') - { - newValue += " "; - } - } - - // Put the value - newValue += toString (value); - return newValue; -} - -// *************************************************************************** - -bool getZoneNameFromXY (sint32 x, sint32 y, std::string &zoneName) -{ - if ((y>0) || (y<-255) || (x<0) || (x>255)) - return false; - zoneName = toString(-y) + "_"; - zoneName += ('A' + (x/26)); - zoneName += ('A' + (x%26)); - return true; -} - -// *************************************************************************** - -bool openFile (const char *filename) -{ - char key[MAX_PATH + MAX_PATH]; - - // Extension - string extension = NLMISC::CFile::getExtension (filename); - - // First try ShellExecute() - HINSTANCE result = ShellExecute(NULL, "open", filename, NULL,NULL, SW_SHOW); - - // If it failed, get the .htm regkey and lookup the program - if ((UINT)result <= HINSTANCE_ERROR) - { - - if (getRegKey(HKEY_CLASSES_ROOT, ("."+extension).c_str (), key) == ERROR_SUCCESS) - { - lstrcat(key, "\\shell\\open\\command"); - - if (getRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS) - { - char *pos; - pos = strstr(key, "\"%1\""); - if (pos == NULL) - { // No quotes found - pos = strstr(key, "%1"); // Check for %1, without quotes - if (pos == NULL) // No parameter at all... - pos = key+lstrlen(key)-1; - else - *pos = '\0'; // Remove the parameter - } - else - *pos = '\0'; // Remove the parameter - - lstrcat(pos, " "); - lstrcat(pos, filename); - result = (HINSTANCE) WinExec(key, SW_SHOW); - return ((UINT)result) >= 31; - } - } - } - else - return true; - return false; -} - -// *************************************************************************** - -uint getRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata) -{ - HKEY hkey; - LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey); - - if (retval == ERROR_SUCCESS) - { - long datasize = MAX_PATH; - char data[MAX_PATH]; - RegQueryValue(hkey, NULL, data, &datasize); - lstrcpy(retdata,data); - RegCloseKey(hkey); - } - - return retval; -} - -// *************************************************************************** - -CNoInteraction::CNoInteraction () -{ - // Get the main frame - CMainFrame *mainFrame = getMainFrame (); - if (mainFrame) - mainFrame->interaction (false); -} - -// *************************************************************************** - -CNoInteraction::~CNoInteraction () -{ - // Get the main frame - CMainFrame *mainFrame = getMainFrame (); - if (mainFrame) - mainFrame->interaction (true); -} - -// *************************************************************************** - -void CMyLigoConfig::errorMessage (const char *format, ... ) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - theApp.errorMessage (buffer); -} - -// *************************************************************************** - -void setEditTextMultiLine (CEdit &edit, const char *text) -{ - string temp; - uint size = strlen (text); - temp.reserve (2*size); - bool previousR=false; - for (uint c=0; c &vect) -{ - string temp; - uint i; - for (i=0; i &vect) -{ - string temp; - uint i; - for (i=0; i &vect) -{ - listBox.ResetContent(); - uint i; - for (i=0; iVisible) && !getPrimitiveEditor (primitive)->getHidden()) - return true; - return false; -} - -// *************************************************************************** - -void CWorldEditorApp::OnFileOpen() -{ - static char BASED_CODE szFilter[] = "NeL World Editor Files (*.worldedit)|*.worldedit|All Files (*.*)|*.*||"; - CFileDialogEx dialog (BASE_REGISTRY_KEY, "worldedit", TRUE, "worldedit", NULL, 0, szFilter); - if (dialog.DoModal() == IDOK) - { - CDocument &doc = *getDocument (); - if (doc.OnOpenDocument (dialog.GetPathName())) - doc.SetPathName (dialog.GetPathName()); - } -} - -// *************************************************************************** - -void CWorldEditorApp::OnFileSave() -{ - CDocument &doc = *getDocument (); - if (doc.IsModified ()) - { - CString pathName = doc.GetPathName( ); - if (pathName == "") - OnFileSaveAs (); - else - doc.OnSaveDocument (pathName); - } -} - -// *************************************************************************** - -void CWorldEditorApp::OnFileSaveAs() -{ - static char BASED_CODE szFilter[] = "NeL World Editor Files (*.worldedit)|*.worldedit|All Files (*.*)|*.*||"; - CFileDialogEx dialog (BASE_REGISTRY_KEY, "worldedit", FALSE, "worldedit", NULL, 0, szFilter); - if (dialog.DoModal() == IDOK) - { - CWorldEditorDoc &doc = *getDocument (); - doc.modifyProject (); - if (doc.OnSaveDocument (dialog.GetPathName())) - doc.SetPathName (dialog.GetPathName()); - } -} - -// *************************************************************************** - -std::string getTextureFile(const std::string &filename) -{ - if(NLMISC::CFile::fileExists(filename+".tga")) - return filename+".tga"; - if(NLMISC::CFile::fileExists(filename+".png")) - return filename+".png"; - else - { - nlwarning("%s doesn't exist in tga or in png", filename.c_str()); - return filename; - } -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// world_editor.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "world_editor.h" +#include +#include + +#include "main_frm.h" +#include "world_editor_doc.h" +#include "world_editor_view.h" +#include "editor_primitive.h" +#include "dialog_properties.h" +#include "primitive_configuration_dlg.h" +#include "splash_screen.h" +#include "file_dialog_ex.h" + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; +using namespace NL3D; + +bool DontUse3D = false; + +//CSplashScreen* splashScreen=new CSplashScreen; + +// *************************************************************************** +// CWorldEditorApp + +BEGIN_MESSAGE_MAP(CWorldEditorApp, CWinApp) + //{{AFX_MSG_MAP(CWorldEditorApp) + ON_COMMAND(ID_APP_ABOUT, OnAppAbout) + ON_COMMAND(ID_FILE_OPEN, OnFileOpen) + ON_COMMAND(ID_FILE_SAVE, OnFileSave) + ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs) + //}}AFX_MSG_MAP + // Standard file based document commands + ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew) + ON_COMMAND(ID_FILE_OPEN, OnFileOpen) + ON_COMMAND(ID_FILE_SAVE, OnFileSave) + ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs) + // Standard print setup command + ON_COMMAND(ID_FILE_PRINT_SETUP, CWinApp::OnFilePrintSetup) +END_MESSAGE_MAP() + +// *************************************************************************** +// CWorldEditorApp construction + +CWorldEditorApp::CWorldEditorApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +CWorldEditorApp::~CWorldEditorApp() +{ +} + +void CWorldEditorApp::deletePlugins() +{ + for(std::vector::iterator it = Plugins.begin(); it != Plugins.end(); ++it) + { + delete *it; + } +} + + + +// *************************************************************************** +// The one and only CWorldEditorApp object + +CWorldEditorApp theApp; + +// *************************************************************************** +// CWorldEditorApp initialization + +BOOL CWorldEditorApp::InitInstance() +{ + // init context + new CApplicationContext; + // Register class + + // Filter the log + NLMISC::createDebug(); + NLMISC::WarningLog->addNegativeFilter ("in not a string"); + CSplashScreen splashScreen; + splashScreen.Create(IDD_SPLASHSCREEN, theApp.GetMainWnd()); + splashScreen.ShowWindow(TRUE); + splashScreen.addLine(string("Register my classes for ligo")); + + // Register my classes for ligo + NLMISC::CClassRegistry::registerClass("CPrimPoint", CPrimPointEditor::creator, typeid(CPrimPointEditor).name()); + NLMISC::CClassRegistry::registerClass("CPrimNode", CPrimNodeEditor::creator, typeid(CPrimNodeEditor).name()); + NLMISC::CClassRegistry::registerClass("CPrimPath", CPrimPathEditor::creator, typeid(CPrimPathEditor).name()); + NLMISC::CClassRegistry::registerClass("CPrimZone", CPrimZoneEditor::creator, typeid(CPrimZoneEditor).name()); + NLMISC::CClassRegistry::registerClass("CPrimAlias", CPrimAliasEditor::creator, typeid(CPrimAliasEditor).name()); + + splashScreen.addLine(string("Init the quad tree")); + + // Init the quad tree + InitQuadGrid (); + + NLMISC_REGISTER_CLASS(CPrimBitmap); + + splashScreen.addLine(string("Init primitive class manager")); + + + // Init primitive class manager + if (!initPath ("world_editor_script.xml", splashScreen)) + return FALSE; + + splashScreen.addLine(string("Exe path")); + + // Exe path + ExePath = GetCommandLine (); + if (ExePath.size()>0) + { + if (ExePath[0] == '\"') + { + uint end=ExePath.find ('\"', 1); + if (end != string::npos) + { + ExePath = ExePath.substr (1, end-1); + } + else + { + nlassert (0); // no! + } + } + else + { + uint end=ExePath.find (' ', 1); + ExePath = ExePath.substr (0, end); + } + } + ExePath = CPath::standardizePath (NLMISC::CFile::getPath (ExePath)); + + splashScreen.addLine(string("Load the Ligoscape.cfg")); + + // Load the Ligoscape.cfg + try + { + string sConfigFileName = ExePath; + sConfigFileName += "ligoscape.cfg"; + + splashScreen.addLine(string("Load the config file")); + + // Load the config file + if (!Config.readConfigFile (sConfigFileName.c_str(), true)) + return FALSE; + + // set the primitive context + CPrimitiveContext::instance().CurrentLigoConfig = &Config; + } + catch (Exception& e) + { + ::MessageBox (NULL, e.what(), "Warning", MB_OK|MB_ICONEXCLAMATION); + + // Can't found the module put some default values + Config.CellSize = 160.0f; + Config.Snap = 1.0f; + } + + AfxEnableControlContainer(); + + splashScreen.addLine(string("Standard initialization")); + + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + splashScreen.addLine(string("Change the registry key")); + + // Change the registry key under which our settings are stored. + // TODO: You should modify this string to be something appropriate + // such as the name of your company or organization. + SetRegistryKey(_T("Nevrax")); + + LoadStdProfileSettings(15); // Load standard INI file options (including MRU) + + // Register the application's document templates. Document templates + // serve as the connection between documents, frame windows and views. + + CSingleDocTemplate* pDocTemplate; + pDocTemplate = new CSingleDocTemplate( + IDR_MAINFRAME, + RUNTIME_CLASS(CWorldEditorDoc), + RUNTIME_CLASS(CMainFrame), // main SDI frame window + RUNTIME_CLASS(CWorldEditorView)); + AddDocTemplate(pDocTemplate); + + splashScreen.addLine(string("Enable DDE Execute open")); + + + // Enable DDE Execute open + EnableShellOpen(); + RegDeleteKey (HKEY_CLASSES_ROOT, "Worldeditor.Document\\DefaultIcon"); + RegisterShellFileTypes(TRUE); + + // Parse command line for standard shell commands, DDE, file open + CCommandLineInfo cmdInfo; + ParseCommandLine(cmdInfo); + + // Dispatch commands specified on the command line + if (!ProcessShellCommand(cmdInfo)) + return FALSE; + + // The one and only window has been initialized, so show and update it. + m_pMainWnd->ShowWindow(SW_SHOW); + m_pMainWnd->UpdateWindow(); + + // Enable drag/drop open + m_pMainWnd->DragAcceptFiles(); + + splashScreen.addLine(string("Fill image list")); + + // Fill image list + ImageList.create (16, 16); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_POINT_HIDDEN); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_POINT_CLOSED); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_POINT_OPENED); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_LINE_HIDDEN); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_LINE_CLOSED); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_LINE_OPENED); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_ZONE_HIDDEN); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_ZONE_CLOSED); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_ZONE_OPENED); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_FOLDER_HIDDEN); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_FOLDER_OPENED); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_FOLDER_CLOSED); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_PROPERTY_HIDDEN); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_PROPERTY_CLOSED); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_PROPERTY_OPENED); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_ROOT_HIDDEN); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_ROOT_CLOSED); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_ROOT_OPENED); + ImageList.addResourceIcon (theApp.m_hInstance, IDI_ERROR_STRUCTURE); + + // Get icones + vector result; + CPath::getPathContent ("ui", true, false, true, result); + for (uint i=0; iGetMenu(); + + CMenu* menu = new CMenu(); + menu->CreatePopupMenu(); + dynamic_menu->InsertMenu(6, MF_BYPOSITION | MF_POPUP, (UINT)menu->GetSafeHmenu(), "Plugins"); + + for(uint k=0;kgetName(); + menu->InsertMenu( k, MF_BYPOSITION | MF_POPUP, ID_WINDOWS_PLUGINS+1 + k, retest.c_str() ); + menu->CheckMenuItem(ID_WINDOWS_PLUGINS+1 +k, MF_CHECKED); + } + + getMainFrame()->DrawMenuBar(); + getMainFrame()->onMenuModeLogic(); + + // Reset the primitive configurations + reloadPrimitiveConfiguration (); + splashScreen.ShowWindow(false); + splashScreen.DestroyWindow(); + + return TRUE; +} + +void CWorldEditorApp::loadPlugins() +{ + // 1st load the plugin configuration file +// char curDir[MAX_PATH]; +// GetCurrentDirectory (MAX_PATH, curDir); + + PluginConfig.load((ExePath+"/world_editor_plugin.cfg").c_str()); + + // enumerate the plugin variable. + CConfigFile::CVar *plugins = PluginConfig.getVarPtr("PluginsLibrary"); + + if (plugins != 0) + { + for (uint i=0; isize(); ++i) + { + string libname = plugins->asString(i)+nlLibSuffix+".dll"; + + //vl HMODULE h = AfxLoadLibrary(libname.c_str()); + NL_LIB_HANDLE h = nlLoadLibrary(libname.c_str()); + if (h == NULL) + continue; + + //FCreateSoundPlugin *pf = (FCreateSoundPlugin*) GetProcAddress(h, "createSoundPlugin"); + //JC: switch to the generic call as soon as possible + //vl FCreatePlugin *pf = (FCreatePlugin*) GetProcAddress(h, "createPlugin"); + FCreatePlugin *pf = (FCreatePlugin*) nlGetSymbolAddress(h, "createPlugin"); + + if (pf == NULL) + continue; + + // ok, the plugin is loaded. + IPluginCallback *pcb = (IPluginCallback*) pf(); + + if (pcb == 0) + continue; + + nlinfo("Plugins '%s' loaded", libname.c_str()); + Plugins.push_back(pcb); + + // init the plugin. + pcb->init(getMainFrame()); + } + } +} + +// *************************************************************************** + +bool CWorldEditorApp::reloadPrimitiveConfiguration () +{ + // Reset + Config.resetPrimitiveConfiguration (); + + // Load + if (!Config.readPrimitiveClass ("world_editor_primitive_configuration.xml", true)) + return false; + + // Init configurations + Configurations.clear (); + Configurations.resize (theApp.Config.getPrimitiveConfiguration().size()); + + // Create the PrimitiveConfigurationDlg + PrimitiveConfigurationDlg.destroy (); + PrimitiveConfigurationDlg.Create (IDD_PRIMITIVE_CONFIGURATION, m_pMainWnd); + return true; +} + +// *************************************************************************** +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + CString m_videoMem; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + virtual BOOL OnInitDialog(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + m_videoMem = _T(""); + //}}AFX_DATA_INIT +} + +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + DDX_Text(pDX, IDC_STATIC_VIDEO_MEM, m_videoMem); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// App command to run the dialog +void CWorldEditorApp::OnAppAbout() +{ + CAboutDlg aboutDlg; + aboutDlg.DoModal(); +} + +bool CWorldEditorApp::yesNoMessage (const char *format, ... ) +{ + char buffer[1024]; + + if (format) + { + va_list args; + va_start( args, format ); + sint ret = vsnprintf( buffer, 1024, format, args ); + va_end( args ); + } + else + { + strcpy(buffer, "Unknown error"); + } + + return MessageBox (m_pMainWnd?m_pMainWnd->m_hWnd:NULL, buffer, "NeL World Editor", MB_YESNO|MB_ICONQUESTION) == IDYES; +} + +void CWorldEditorApp::errorMessage (const char *format, ... ) +{ + char buffer[1024]; + + if (format) + { + va_list args; + va_start( args, format ); + sint ret = vsnprintf( buffer, 1024, format, args ); + va_end( args ); + } + else + { + strcpy(buffer, "Unknown error"); + } + + MessageBox (m_pMainWnd?m_pMainWnd->m_hWnd:NULL, buffer, "NeL World Editor", MB_OK|MB_ICONEXCLAMATION); +} + +void CWorldEditorApp::infoMessage (const char *format, ... ) +{ + char buffer[1024]; + + if (format) + { + va_list args; + va_start( args, format ); + sint ret = vsnprintf( buffer, 1024, format, args ); + va_end( args ); + } + else + { + strcpy(buffer, "Unknown error"); + } + + MessageBox (m_pMainWnd?m_pMainWnd->m_hWnd:NULL, buffer, "NeL World Editor", MB_OK|MB_ICONINFORMATION); +} + +void CWorldEditorApp::syntaxError (const char *filename, xmlNodePtr xmlNode, const char *format, ...) +{ + char buffer[1024]; + + if (format) + { + va_list args; + va_start( args, format ); + sint ret = vsnprintf( buffer, 1024, format, args ); + va_end( args ); + } + else + { + strcpy(buffer, "Unknown error"); + } + + errorMessage ("(%s), node (%s), line (%d) :\n%s", filename, xmlNode->name, (int)xmlNode->content, buffer); +} + +bool CWorldEditorApp::getPropertyString (std::string &result, const char *filename, xmlNodePtr xmlNode, const char *propName) +{ + // Call the CIXml version + if (!CIXml::getPropertyString (result, xmlNode, propName)) + { + // Output a formated error + syntaxError (filename, xmlNode, "Missing XML node property (%s)", propName); + return false; + } + return true; +} + +bool CWorldEditorApp::initPath (const char *filename, CSplashScreen &splashScreen) +{ + // The context strings + set contextStrings; + + // Read the document + CIFile file; + if (file.open (filename)) + { + try + { + // XML stream + CIXml xml; + xml.init (file); + + // Get the root node + xmlNodePtr root = xml.getRootNode (); + nlassert (root); + + // Check the header + if (strcmp ((const char*)root->name, "NEL_WORLD_EDITOR_CONFIG") == 0) + { + // Get the first search_path description + xmlNodePtr search_path = CIXml::getFirstChildNode (root, "SEARCH_PATH"); + if (search_path) + { + do + { + // Get the search_path name + std::string path; + if (getPropertyString (path, filename, search_path, "PATH")) + { + bool recurse = true; + string noRecurse; + if (CIXml::getPropertyString (noRecurse, search_path, "NO_RECURSE")) + { + if (toLower(noRecurse) == "true") + recurse = false; + } + + // Add the search path + CPath::addSearchPath (path, recurse, true, &splashScreen); + } + else + goto failed; + } + while (search_path = CIXml::getNextChildNode (search_path, "SEARCH_PATH")); + } + + // Get the documentation path + xmlNodePtr doc_path = CIXml::getFirstChildNode (root, "DOC_PATH"); + if (doc_path) + { + std::string path; + if (getPropertyString (path, filename, doc_path, "PATH")) + { + string fullPath = CPath::getFullPath(path); + // Store the doc path + DocPath = fullPath; + } + else + goto failed; + } + + // Ok + return true; + } + else + { + syntaxError (filename, root, "Wrong root node, should be NEL_WORLD_EDITOR_CONFIG"); + } + } + catch (Exception &e) + { + errorMessage ("File read error (%s):%s", filename, e.what ()); + } + } + else + { + errorMessage ("Can't open the file %s for reading.", filename); + } + +failed: + return false; +} + +// *************************************************************************** + +sint CWorldEditorApp::getActiveConfiguration (const NLLIGO::IPrimitive &primitive, uint searchBegin) const +{ + const std::vector &configurations = theApp.Config.getPrimitiveConfiguration(); + + uint i; + for (i=searchBegin; iprofileAllocatedTextureMemory(); + + m_videoMem = NLMISC::toString("%u Mo", mem/(1024*1024)).c_str(); + + UpdateData(FALSE); + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + +// *************************************************************************** + +void invalidateLeftView () +{ + CMainFrame *mf = getMainFrame (); + if (mf) + { + mf->m_wndSplitter.GetPane(0,0)->Invalidate (); + } +} + +// *************************************************************************** + +std::string numberize (const char *oldString, uint value) +{ + int i=strlen (oldString)-1; + while ((i>=0) && (((oldString[i]<='9') && (oldString[i]>='0')) || (oldString[i]==' '))) + { + // again + i--; + } + + // String new value + string newValue = oldString; + + // Found ? + if (i<0) + { + newValue.clear (); + } + else + { + newValue = newValue.substr (0, i+1); + // Append a space if there is no space nor underscore + if (newValue[i]!='_' && newValue[i]!=' ') + { + newValue += " "; + } + } + + // Put the value + newValue += toString (value); + return newValue; +} + +// *************************************************************************** + +bool getZoneNameFromXY (sint32 x, sint32 y, std::string &zoneName) +{ + if ((y>0) || (y<-255) || (x<0) || (x>255)) + return false; + zoneName = toString(-y) + "_"; + zoneName += ('A' + (x/26)); + zoneName += ('A' + (x%26)); + return true; +} + +// *************************************************************************** + +bool openFile (const char *filename) +{ + char key[MAX_PATH + MAX_PATH]; + + // Extension + string extension = NLMISC::CFile::getExtension (filename); + + // First try ShellExecute() + HINSTANCE result = ShellExecute(NULL, "open", filename, NULL,NULL, SW_SHOW); + + // If it failed, get the .htm regkey and lookup the program + if ((UINT)result <= HINSTANCE_ERROR) + { + + if (getRegKey(HKEY_CLASSES_ROOT, ("."+extension).c_str (), key) == ERROR_SUCCESS) + { + lstrcat(key, "\\shell\\open\\command"); + + if (getRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS) + { + char *pos; + pos = strstr(key, "\"%1\""); + if (pos == NULL) + { // No quotes found + pos = strstr(key, "%1"); // Check for %1, without quotes + if (pos == NULL) // No parameter at all... + pos = key+lstrlen(key)-1; + else + *pos = '\0'; // Remove the parameter + } + else + *pos = '\0'; // Remove the parameter + + lstrcat(pos, " "); + lstrcat(pos, filename); + result = (HINSTANCE) WinExec(key, SW_SHOW); + return ((UINT)result) >= 31; + } + } + } + else + return true; + return false; +} + +// *************************************************************************** + +uint getRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata) +{ + HKEY hkey; + LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey); + + if (retval == ERROR_SUCCESS) + { + long datasize = MAX_PATH; + char data[MAX_PATH]; + RegQueryValue(hkey, NULL, data, &datasize); + lstrcpy(retdata,data); + RegCloseKey(hkey); + } + + return retval; +} + +// *************************************************************************** + +CNoInteraction::CNoInteraction () +{ + // Get the main frame + CMainFrame *mainFrame = getMainFrame (); + if (mainFrame) + mainFrame->interaction (false); +} + +// *************************************************************************** + +CNoInteraction::~CNoInteraction () +{ + // Get the main frame + CMainFrame *mainFrame = getMainFrame (); + if (mainFrame) + mainFrame->interaction (true); +} + +// *************************************************************************** + +void CMyLigoConfig::errorMessage (const char *format, ... ) +{ + char buffer[1024]; + + if (format) + { + va_list args; + va_start( args, format ); + sint ret = vsnprintf( buffer, 1024, format, args ); + va_end( args ); + } + else + { + strcpy(buffer, "Unknown error"); + } + + theApp.errorMessage (buffer); +} + +// *************************************************************************** + +void setEditTextMultiLine (CEdit &edit, const char *text) +{ + string temp; + uint size = strlen (text); + temp.reserve (2*size); + bool previousR=false; + for (uint c=0; c &vect) +{ + string temp; + uint i; + for (i=0; i &vect) +{ + string temp; + uint i; + for (i=0; i &vect) +{ + listBox.ResetContent(); + uint i; + for (i=0; iVisible) && !getPrimitiveEditor (primitive)->getHidden()) + return true; + return false; +} + +// *************************************************************************** + +void CWorldEditorApp::OnFileOpen() +{ + static char BASED_CODE szFilter[] = "NeL World Editor Files (*.worldedit)|*.worldedit|All Files (*.*)|*.*||"; + CFileDialogEx dialog (BASE_REGISTRY_KEY, "worldedit", TRUE, "worldedit", NULL, 0, szFilter); + if (dialog.DoModal() == IDOK) + { + CDocument &doc = *getDocument (); + if (doc.OnOpenDocument (dialog.GetPathName())) + doc.SetPathName (dialog.GetPathName()); + } +} + +// *************************************************************************** + +void CWorldEditorApp::OnFileSave() +{ + CDocument &doc = *getDocument (); + if (doc.IsModified ()) + { + CString pathName = doc.GetPathName( ); + if (pathName == "") + OnFileSaveAs (); + else + doc.OnSaveDocument (pathName); + } +} + +// *************************************************************************** + +void CWorldEditorApp::OnFileSaveAs() +{ + static char BASED_CODE szFilter[] = "NeL World Editor Files (*.worldedit)|*.worldedit|All Files (*.*)|*.*||"; + CFileDialogEx dialog (BASE_REGISTRY_KEY, "worldedit", FALSE, "worldedit", NULL, 0, szFilter); + if (dialog.DoModal() == IDOK) + { + CWorldEditorDoc &doc = *getDocument (); + doc.modifyProject (); + if (doc.OnSaveDocument (dialog.GetPathName())) + doc.SetPathName (dialog.GetPathName()); + } +} + +// *************************************************************************** + +std::string getTextureFile(const std::string &filename) +{ + if(NLMISC::CFile::fileExists(filename+".tga")) + return filename+".tga"; + if(NLMISC::CFile::fileExists(filename+".png")) + return filename+".png"; + else + { + nlwarning("%s doesn't exist in tga or in png", filename.c_str()); + return filename; + } +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor.h index d7bcfed09..38a17b6bb 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor.h @@ -1,185 +1,185 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// world_editor.h : main header file for the WORLD_EDITOR application -// - -#if !defined(AFX_WORLD_EDITOR_H__534BE790_9E70_4D87_B709_1445991D5824__INCLUDED_) -#define AFX_WORLD_EDITOR_H__534BE790_9E70_4D87_B709_1445991D5824__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including this file for PCH -#endif - -#include "resource.h" // main symbols -#include -#include "imagelist_ex.h" -#include "plugin_interface.h" -//#include "color_edit_wnd.h" -#include "nel/ligo/ligo_config.h" - -// Base registry key -#define BASE_REGISTRY_KEY "Software\\Nevrax\\NeL World Editor" - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorApp: -// See world_editor.cpp for the implementation of this class -// - -class CMyLigoConfig : public NLLIGO::CLigoConfig -{ - virtual void errorMessage (const char *format, ... ); -}; - -class CWorldEditorApp : public CWinApp -{ - friend class CProjectSettings; -public: - CWorldEditorApp(); - ~CWorldEditorApp(); - - // Helpers - bool yesNoMessage (const char *format, ... ); - void errorMessage (const char *format, ... ); - void infoMessage (const char *format, ... ); - void syntaxError (const char *filename, xmlNodePtr, const char *format, ...); - bool getPropertyString (std::string &result, const char *filename, xmlNodePtr xmlNode, const char *propName); - - // The image list - CImageListEx ImageList; - - // Exe path - std::string ExePath; - - // Doc path (for node class html help file) - std::string DocPath; - - // Load any extension plugin - virtual void loadPlugins(); - - /// Configuration file for plugins - NLMISC::CConfigFile PluginConfig; - - /// Vector of loaded plugins. - std::vector Plugins; - - /// list of primitives associated to plugin displayer - std::map PrimitiveDisplayers; - - /// The ligo config - CMyLigoConfig Config; - - /// Get the first active configuration of a primitive. Return -1 else. - sint getActiveConfiguration (const NLLIGO::IPrimitive &primitive, uint searchBegin = 0) const; - - /// Reload the configuration file - bool reloadPrimitiveConfiguration (); - - /// Configuration - class CConfiguration - { - public: - CConfiguration() - { - Activated = false; - } - - bool Activated; - }; - std::vector Configurations; - - - -private: - - // Read the path config file - bool initPath (const char *filename, class CSplashScreen &splashScreen); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CWorldEditorApp) - public: - virtual BOOL InitInstance(); - //}}AFX_VIRTUAL - -// Implementation - //{{AFX_MSG(CWorldEditorApp) - afx_msg void OnAppAbout(); - afx_msg void OnFileOpen(); - afx_msg void OnFileSave(); - afx_msg void OnFileSaveAs(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -public: - // for main frame window only - void deletePlugins(); -}; - -extern CWorldEditorApp theApp; - class CMainFrame *getMainFrame (); -void invalidateLeftView (); -std::string standardizePath (const char *str); -std::string formatString (const char *str); -inline void transformVector (NLMISC::CVector &toTransform, float angle, const NLMISC::CVector &pivot) -{ - float cosa = (float)cos (angle); - float sina = (float)sin (angle); - toTransform -= pivot; - float temp = cosa * toTransform.x - sina * toTransform.y; - toTransform.y = sina * toTransform.x + cosa * toTransform.y; - toTransform.x = temp; - toTransform += pivot; -} -std::string numberize (const char *oldString, uint value); -bool getZoneNameFromXY (sint32 x, sint32 y, std::string &zoneName); -bool openFile (const char *url); -uint getRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata); -void setEditTextMultiLine (CEdit &edit, const char *text); -void setEditTextMultiLine (CEdit &edit, const std::vector &vect); -//void setEditTextMultiLine (ColorEditWnd &edit, const char *text); -//void setEditTextMultiLine (ColorEditWnd &edit, const std::vector &vect); -//void setEditTextMultiLine (CListBox &listBox, const char *text); -void setEditTextMultiLine (CListBox &listBox, const std::vector &vect); -bool setWindowTextUTF8 (HWND hwnd, const char *textUtf8); -bool getWindowTextUTF8 (HWND hwnd, CString &textUtf8); -HTREEITEM insertItemUTF8 (HWND hwnd, const char *textUtf8, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST); -HTREEITEM insertItemUTF8 (HWND hwnd, const char *textUtf8, int nImage, int nSelectedImage, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST); -bool setItemTextUTF8 ( HWND hwnd, HTREEITEM hItem, LPCTSTR lpszItem ); -bool isPrimitiveVisible (const NLLIGO::IPrimitive *primitive); - -std::string getTextureFile(const std::string &filename); - -// *************************************************************************** - -// Class to enable / disable interaction -class CNoInteraction -{ -public: - CNoInteraction (); - ~CNoInteraction (); -}; - - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_WORLD_EDITOR_H__534BE790_9E70_4D87_B709_1445991D5824__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// world_editor.h : main header file for the WORLD_EDITOR application +// + +#if !defined(AFX_WORLD_EDITOR_H__534BE790_9E70_4D87_B709_1445991D5824__INCLUDED_) +#define AFX_WORLD_EDITOR_H__534BE790_9E70_4D87_B709_1445991D5824__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols +#include +#include "imagelist_ex.h" +#include "plugin_interface.h" +//#include "color_edit_wnd.h" +#include "nel/ligo/ligo_config.h" + +// Base registry key +#define BASE_REGISTRY_KEY "Software\\Nevrax\\NeL World Editor" + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorApp: +// See world_editor.cpp for the implementation of this class +// + +class CMyLigoConfig : public NLLIGO::CLigoConfig +{ + virtual void errorMessage (const char *format, ... ); +}; + +class CWorldEditorApp : public CWinApp +{ + friend class CProjectSettings; +public: + CWorldEditorApp(); + ~CWorldEditorApp(); + + // Helpers + bool yesNoMessage (const char *format, ... ); + void errorMessage (const char *format, ... ); + void infoMessage (const char *format, ... ); + void syntaxError (const char *filename, xmlNodePtr, const char *format, ...); + bool getPropertyString (std::string &result, const char *filename, xmlNodePtr xmlNode, const char *propName); + + // The image list + CImageListEx ImageList; + + // Exe path + std::string ExePath; + + // Doc path (for node class html help file) + std::string DocPath; + + // Load any extension plugin + virtual void loadPlugins(); + + /// Configuration file for plugins + NLMISC::CConfigFile PluginConfig; + + /// Vector of loaded plugins. + std::vector Plugins; + + /// list of primitives associated to plugin displayer + std::map PrimitiveDisplayers; + + /// The ligo config + CMyLigoConfig Config; + + /// Get the first active configuration of a primitive. Return -1 else. + sint getActiveConfiguration (const NLLIGO::IPrimitive &primitive, uint searchBegin = 0) const; + + /// Reload the configuration file + bool reloadPrimitiveConfiguration (); + + /// Configuration + class CConfiguration + { + public: + CConfiguration() + { + Activated = false; + } + + bool Activated; + }; + std::vector Configurations; + + + +private: + + // Read the path config file + bool initPath (const char *filename, class CSplashScreen &splashScreen); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CWorldEditorApp) + public: + virtual BOOL InitInstance(); + //}}AFX_VIRTUAL + +// Implementation + //{{AFX_MSG(CWorldEditorApp) + afx_msg void OnAppAbout(); + afx_msg void OnFileOpen(); + afx_msg void OnFileSave(); + afx_msg void OnFileSaveAs(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +public: + // for main frame window only + void deletePlugins(); +}; + +extern CWorldEditorApp theApp; + class CMainFrame *getMainFrame (); +void invalidateLeftView (); +std::string standardizePath (const char *str); +std::string formatString (const char *str); +inline void transformVector (NLMISC::CVector &toTransform, float angle, const NLMISC::CVector &pivot) +{ + float cosa = (float)cos (angle); + float sina = (float)sin (angle); + toTransform -= pivot; + float temp = cosa * toTransform.x - sina * toTransform.y; + toTransform.y = sina * toTransform.x + cosa * toTransform.y; + toTransform.x = temp; + toTransform += pivot; +} +std::string numberize (const char *oldString, uint value); +bool getZoneNameFromXY (sint32 x, sint32 y, std::string &zoneName); +bool openFile (const char *url); +uint getRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata); +void setEditTextMultiLine (CEdit &edit, const char *text); +void setEditTextMultiLine (CEdit &edit, const std::vector &vect); +//void setEditTextMultiLine (ColorEditWnd &edit, const char *text); +//void setEditTextMultiLine (ColorEditWnd &edit, const std::vector &vect); +//void setEditTextMultiLine (CListBox &listBox, const char *text); +void setEditTextMultiLine (CListBox &listBox, const std::vector &vect); +bool setWindowTextUTF8 (HWND hwnd, const char *textUtf8); +bool getWindowTextUTF8 (HWND hwnd, CString &textUtf8); +HTREEITEM insertItemUTF8 (HWND hwnd, const char *textUtf8, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST); +HTREEITEM insertItemUTF8 (HWND hwnd, const char *textUtf8, int nImage, int nSelectedImage, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST); +bool setItemTextUTF8 ( HWND hwnd, HTREEITEM hItem, LPCTSTR lpszItem ); +bool isPrimitiveVisible (const NLLIGO::IPrimitive *primitive); + +std::string getTextureFile(const std::string &filename); + +// *************************************************************************** + +// Class to enable / disable interaction +class CNoInteraction +{ +public: + CNoInteraction (); + ~CNoInteraction (); +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_WORLD_EDITOR_H__534BE790_9E70_4D87_B709_1445991D5824__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_doc.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_doc.cpp index 354e516fd..6e9cd9d39 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_doc.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_doc.cpp @@ -1,2626 +1,2626 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// world_editor_doc.cpp : implementation of the CWorldEditorDoc class -// - -#include "stdafx.h" - -#include "action.h" -#include "world_editor.h" -#include "main_frm.h" -#include "world_editor_doc.h" -#include "display.h" -#include "dialog_properties.h" -#include "editor_primitive.h" -#include "file_dialog_ex.h" - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; -using namespace NL3D; - -#define WORLD_EDITOR_FILE_VERSION 2 -#define WORLD_EDITOR_DATABASE_SIZE 100 - -// *************************************************************************** -// CWorldEditorDoc - -IMPLEMENT_DYNCREATE(CWorldEditorDoc, CDocument) - -BEGIN_MESSAGE_MAP(CWorldEditorDoc, CDocument) - //{{AFX_MSG_MAP(CWorldEditorDoc) - ON_COMMAND(ID_FILE_OPEN, OnFileOpen) - ON_COMMAND(ID_FILE_SAVE, OnFileSave) - ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// *************************************************************************** -// CWorldEditorDoc construction/destruction - -CWorldEditorDoc::CWorldEditorDoc() -{ - _ModificationMode = false; - clearModifications (); -} - -CWorldEditorDoc::~CWorldEditorDoc() -{ - clearModifications (); -} - -// *************************************************************************** - -BOOL CWorldEditorDoc::OnNewDocument() -{ - if (!CDocument::OnNewDocument()) - return FALSE; - - // Main frame ? - CMainFrame *mainFrame = getMainFrame (); - if (mainFrame) - mainFrame->updateData (); - - return newDocument () ? TRUE : FALSE; -} - -// *************************************************************************** - -bool CWorldEditorDoc::newDocument () -{ - /*if (IsWindow(PropertyDialog)) - PropertyDialog.ShowWindow (SW_HIDE);*/ - - std::list::iterator it = PropertiesDialogs.begin(); - - while ( it != PropertiesDialogs.end() ) - { - (*it)->ShowWindow( SW_HIDE ); - delete (*it); - it++; - } - - PropertiesDialogs.clear(); - - _DataDir = ""; - _Context = ""; - - // Erase all editable root primitive - CDatabaseList::iterator ite = _DataHierarchy.begin(); - while (ite != _DataHierarchy.end()) - { - CDatabaseList::iterator next = ite; - next++; - if (ite->Editable) - _DataHierarchy.erase (ite); - ite = next; - } - - _DataHierarchy.recomputePointerArray (); - - // Init the landscape - CMainFrame *mainFrame = getMainFrame (); - if (mainFrame) - mainFrame->initLandscapeData (); - - clearModifications (); - - // Invalidate all - if (getMainFrame ()) - { - getMainFrame ()->invalidateTools (); - } - invalidateLeftView (); - - // Invalidate pointers - InvalidateAllPrimitives (); - if (getMainFrame()) - { - // we verify the structures of the primitives, and mark the incorrect nodes - VerifyPrimitivesStructures(); - } - - return true; -} - -// *************************************************************************** -// CWorldEditorDoc diagnostics - -#ifdef _DEBUG -void CWorldEditorDoc::AssertValid() const -{ - CDocument::AssertValid(); -} - -void CWorldEditorDoc::Dump(CDumpContext& dc) const -{ - CDocument::Dump(dc); -} -#endif //_DEBUG - -// *************************************************************************** -// CWorldEditorDoc commands - -CWorldEditorDoc *getDocument () -{ - if (getMainFrame ()) - return (CWorldEditorDoc *)(getMainFrame ()->GetActiveDocument ()); - else - return NULL; -} - -// *************************************************************************** - -BOOL CWorldEditorDoc::OnOpenDocument(LPCTSTR lpszPathName) -{ - // Timer enabled ? - getMainFrame ()->TimerEnabled = false; - - // Result - newDocument (); - bool res = loadDocument (lpszPathName) ? TRUE : FALSE; - - // Timer enabled ? - getMainFrame ()->TimerEnabled = true; - - return res; -} - -// *************************************************************************** - -bool CWorldEditorDoc::loadDocument (const char *filename) -{ - bool result = true; - - // Get path name - string path = NLMISC::CFile::getPath (filename); - - // Backup current path - string backupPath = CPath::getCurrentPath (); - - // Set current path - CPath::setCurrentPath (path.c_str ()); - - // Load the document - CIFile file; - if (file.open (filename)) - { - try - { - // Load the document in XML - CIXml xml; - xml.init (file); - - // Get root node - bool success = false; - xmlNodePtr rootNode = xml.getRootNode (); - if (rootNode) - { - // Good header ? - if (strcmp ((const char *)(rootNode->name), "NEL_WORLD_EDITOR_PROJECT") ==0) - { - // Read the version - int version = -1; - - // Read the parameters - xmlNodePtr node = CIXml::getFirstChildNode (rootNode, "VERSION"); - if (node) - { - string versionString; - if (CIXml::getContentString (versionString, node)) - version = atoi (versionString.c_str ()); - } - - if (version == -1) - { - // Error - theApp.syntaxError (filename, rootNode, "No version node"); - } - else - { - // Old format, serial it - if (version <= 1) - { - file.close (); - CIFile file2; - nlverify (file2.open (filename)); - CIXml xml2; - xml2.init (file2); - serial (xml2); - - // Done - success = true; - } - else - { - // Read it - if (version > WORLD_EDITOR_FILE_VERSION) - { - theApp.syntaxError (filename, node, "Unknown file version"); - } - else - { - // Read data directory - node = CIXml::getFirstChildNode (rootNode, "DATA_DIRECTORY"); - if (node) - { - CIXml::getPropertyString (_DataDir, node, "VALUE"); - } - - // Read data directory - node = CIXml::getFirstChildNode (rootNode, "CONTEXT"); - if (node) - { - CIXml::getPropertyString (_Context, node, "VALUE"); - } - - // Read the database element - node = CIXml::getFirstChildNode (rootNode, "DATABASE_ELEMENT"); - if (node) - { - do - { - // Get the type - string type; - if (theApp.getPropertyString (type, filename, node, "TYPE")) - { - // Read the filename - string filenameChild; - if (theApp.getPropertyString (filenameChild, filename, node, "FILENAME")) - { - // Is it a landscape ? - if (type == "landscape") - { - _DataHierarchy.push_back (CDatabaseElement (CDatabaseElement::Landscape)); - _DataHierarchy.recomputePointerArray (); - - // Get the primitives - xmlNodePtr primitives = CIXml::getFirstChildNode (node, "PRIMITIVES"); - if (primitives) - { - // Read it - _DataHierarchy.back ().Primitives.read (primitives, filename, theApp.Config); - - // Set the filename - _DataHierarchy.back ().Filename = filenameChild; - } - } - else - { - _DataHierarchy.push_back (CDatabaseElement (CDatabaseElement::Primitive)); - _DataHierarchy.recomputePointerArray (); - - // Set the filename - _DataHierarchy.back ().Filename = filenameChild; - } - - } - } - } - while (node = CIXml::getNextChildNode (node, "DATABASE_ELEMENT")); - } - - // Done - success = true; - } - } - } - } - else - { - // Error - theApp.syntaxError (filename, rootNode, "Unknown file header : %s", rootNode->name); - } - } - - if (!success) - { - result = false; - newDocument (); - } - else - { - // Last time - _LastModifedTime = NLMISC::CFile::getFileModificationDate (filename); - - // Load the files - uint i; - for (i=0; i<_DataHierarchy.size (); i++) - { - if (_DataHierarchy[i].Editable) - { - // Not modified - _DataHierarchy[i].Modified = false; - - getMainFrame()->launchLoadingDialog(toString("loading %s", _DataHierarchy[i].Filename.c_str()).c_str()); - getMainFrame()->progressLoadingDialog(float(i+0.0001f)/_DataHierarchy.size()); - // Landscape ? - if (_DataHierarchy[i].Type == CDatabaseElement::Landscape) - { - // Load the landscape - try - { - CIFile fileIn; - if (fileIn.open (_DataHierarchy[i].Filename)) - { - CIXml xml(true); - xml.init (fileIn); - _DataHierarchy[i].ZoneRegion.serial (xml); - - // Last time - _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); - } - else - { - if (!theApp.yesNoMessage ("Can't open file %s for reading. Continue reading ?", _DataHierarchy[i].Filename.c_str ())) - { - result = false; - } - } - } - catch (Exception& e) - { - theApp.errorMessage ("Error reading file %s : %s", _DataHierarchy[i].Filename.c_str (), e.what ()); - } - } - else - { - // Checks - nlassert (_DataHierarchy[i].Type == CDatabaseElement::Primitive); - - // Load the primitive - try - { - CIFile fileIn; - if (fileIn.open (_DataHierarchy[i].Filename)) - { - // Xml stream - CIXml xmlIn; - xmlIn.init (fileIn); - - // set the primitive context - CPrimitiveContext::instance().CurrentPrimitive = &_DataHierarchy[i].Primitives; - - // Read it - if (!_DataHierarchy[i].Primitives.read (xmlIn.getRootNode (), _DataHierarchy[i].Filename.c_str(), theApp.Config)) - { - theApp.errorMessage ("Error reading file %s", _DataHierarchy[i].Filename.c_str ()); - } - - // cleanup the primitive context - CPrimitiveContext::instance().CurrentPrimitive = NULL; - - // Last time - _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); - } - else - { - if (!theApp.yesNoMessage ("Can't open file %s for reading. Continue reading ?", _DataHierarchy[i].Filename.c_str ())) - { - result = false; - } - } - } - catch (Exception& e) - { - theApp.errorMessage ("Error reading file %s : %s", _DataHierarchy[i].Filename.c_str (), e.what ()); - } - } - - getMainFrame()->terminateLoadingDialog(); - /* // Not modified - _DataHierarchy[i].Modified = false;*/ - } - } - - // Init the landscape - CMainFrame *mainFrame = getMainFrame (); - if (mainFrame) - mainFrame->initLandscapeData (); - - // Reset document changes - clearModifications (); - } - } - catch (Exception &e) - { - theApp.errorMessage ("Error reading file %s : %s", filename, e.what ()); - - result = false; - } - } - else - { - theApp.errorMessage ("Can't open the file %s for reading.", filename); - - result = false; - } - - // Invalidate some stuff - invalidateLeftView (); - getMainFrame ()->invalidateTools (); - - // Invalidate pointers - InvalidateAllPrimitives (); - VerifyPrimitivesStructures(); - - // Restaure current path - CPath::setCurrentPath (backupPath.c_str ()); - - // Initialize default values - for (uint j=0; j<_DataHierarchy.size(); ++j) - { - if (_DataHierarchy[j].Type == CDatabaseElement::Primitive) - { - updateDefaultValues (j); - } - } - - // Check property types - for (uint j=0; j<_DataHierarchy.size(); ++j) - { - if (_DataHierarchy[j].Type == CDatabaseElement::Primitive) - { - updateDefaultValues (j); - } - } - - // Warn the plugins - uint i; - for (i=0; iprimitiveChanged(_DataHierarchy[j].Primitives.RootNode); - } - } - } - - - return result; -} - -// *************************************************************************** - -BOOL CWorldEditorDoc::OnSaveDocument(LPCTSTR lpszPathName) -{ - BOOL result = TRUE; - - // Get path name - string path = NLMISC::CFile::getPath (lpszPathName); - - // Backup current path - string backupPath = CPath::getCurrentPath (); - - // Set current path - CPath::setCurrentPath (path.c_str ()); - - // Timer enabled ? - getMainFrame ()->TimerEnabled = false; - - // Save land files - for (uint i=0; i<_DataHierarchy.size (); i++) - { - if (_DataHierarchy[i].Editable) - { - // Make path relative - string relativeFileName = _DataHierarchy[i].Filename; - CPath::makePathRelative (NLMISC::CFile::getPath (lpszPathName).c_str (), relativeFileName); - if (relativeFileName != _DataHierarchy[i].Filename) - { - _DataHierarchy[i].Filename = relativeFileName; - modifyProject (); - } - - // Modified - if (_DataHierarchy[i].Modified) - { - // Landscape ? - if (_DataHierarchy[i].Type == CDatabaseElement::Landscape) - { - // Save the landscape - try - { - // Got a filename ? - if (_DataHierarchy[i].Filename.empty ()) - { - CFileDialogEx dialog (BASE_REGISTRY_KEY, "land", FALSE, "land", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "NeL Ligo Landscape Files (*.land)|*.land|All Files (*.*)|*.*||", getMainFrame ()); - if (dialog.DoModal() == IDOK) - { - _DataHierarchy[i].Filename = dialog.GetPathName(); - } - else - { - continue; - } - } - - // Open the primitive file for writing - COFile fileOut; - if (fileOut.open (_DataHierarchy[i].Filename, false, false, true)) - { - // Be careful with the flushing of the COXml object - { - COXml xmlOut; - xmlOut.init (&fileOut); - _DataHierarchy[i].ZoneRegion.serial (xmlOut); - - // Done - _DataHierarchy[i].Modified = false; - } - - fileOut.close(); - } - else - { - if (!theApp.yesNoMessage ("Can't open file %s for writing. Continue saving ?", _DataHierarchy[i].Filename.c_str ())) - { - result = FALSE; - } - } - - _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); - } - catch (Exception& e) - { - theApp.errorMessage ("Error writing file %s : %s", _DataHierarchy[i].Filename.c_str (), e.what ()); - } - } - else - { - // Checks - nlassert (_DataHierarchy[i].Type == CDatabaseElement::Primitive); - - // Save the primitive - try - { - // Got a filename ? - if (_DataHierarchy[i].Filename.empty ()) - { - CFileDialogEx dialog (BASE_REGISTRY_KEY, "primitive", FALSE, "primitive", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "NeL Ligo Primitive Files (*.primitive)|*.primitive|All Files (*.*)|*.*||", getMainFrame ()); - if (dialog.DoModal() == IDOK) - { - string pathFromDialog = dialog.GetPathName(); - - // Remove uppercase in filename - string::size_type pos = pathFromDialog.rfind ("\\", 0); - for (uint j=pos+1 ; jinvalidateTools (); - } - else - { - continue; - } - } - - // Open the primitive file for writing - COFile fileOut; - if (fileOut.open (_DataHierarchy[i].Filename, false, false, true)) - { - COXml xmlOut; - xmlOut.init (&fileOut); - - // Write the document - _DataHierarchy[i].Primitives.write (xmlOut.getDocument (), _DataHierarchy[i].Filename.c_str ()); - - // Flush it - xmlOut.flush (); - - // Done - _DataHierarchy[i].Modified = false; - - // Invalidate tools - getMainFrame ()->invalidateToolsParam (); - - // Last time - fileOut.close (); - } - else - { - if (!theApp.yesNoMessage ("Can't open file %s for writing. Continue saving ?", _DataHierarchy[i].Filename.c_str ())) - { - result = FALSE; - } - } - - _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); - } - catch (Exception& e) - { - theApp.errorMessage ("Error writing file %s : %s", _DataHierarchy[i].Filename.c_str (), e.what ()); - } - } - - // Invalidate title - CDatabaseLocatorPointer locator; - locator.getRoot (i); - InvalidatePrimitive (locator, LogicTreeParam); - } - } - } - - // Document modified ? - if (_Modified) - { - // Save the document - COFile file; - if (file.open (lpszPathName, false, false, true)) - { - try - { - { - // Save the document in XML - COXml xml; - xml.init (&file); - - // Create the document - xmlNodePtr rootNode = xmlNewDocNode (xml.getDocument (), NULL, (const xmlChar*)"NEL_WORLD_EDITOR_PROJECT", NULL); - xmlDocSetRootElement (xml.getDocument (), rootNode); - - // Version - xmlNodePtr node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"VERSION", NULL); - xmlNodePtr text = xmlNewText ((const xmlChar *)toString (WORLD_EDITOR_FILE_VERSION).c_str ()); - xmlAddChild (node, text); - - // DATA_DIRECTORY - node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"DATA_DIRECTORY", NULL); - xmlSetProp (node, (const xmlChar*)"VALUE", (const xmlChar*)_DataDir.c_str ()); - - // DATA_DIRECTORY - node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"CONTEXT", NULL); - xmlSetProp (node, (const xmlChar*)"VALUE", (const xmlChar*)_Context.c_str ()); - - // Database - for (uint i=0; i<_DataHierarchy.size (); i++) - { - if (_DataHierarchy[i].Editable) - { - // New element - node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"DATABASE_ELEMENT", NULL); - xmlSetProp (node, (const xmlChar*)"FILENAME", (const xmlChar*)_DataHierarchy[i].Filename.c_str ()); - - // Type - bool landscape = isLandscape (i); - xmlSetProp (node, (const xmlChar*)"TYPE", (const xmlChar*)(landscape?"landscape":"primitive")); - - // Write properties ? - if (landscape) - { - node = xmlNewChild ( node, NULL, (const xmlChar*)"PRIMITIVES", NULL); - _DataHierarchy[i].Primitives.write (node, lpszPathName); - } - } - } - - // Not modified - _Modified = false; - } - - // Last time - file.close (); - } - catch (Exception &e) - { - theApp.errorMessage ("Error writing file %s : %s", lpszPathName, e.what ()); - - result = FALSE; - } - } - else - { - result = FALSE; - } - - _LastModifedTime = NLMISC::CFile::getFileModificationDate (lpszPathName); - } - - // No modification is for this level of undo - _LastSaveUndo = _Undo; - _NoModificationUndo = false; - - updateModifiedState (); - - // Timer enabled - getMainFrame ()->TimerEnabled = true; - - // Restaure current path - CPath::setCurrentPath (backupPath.c_str ()); - - return result; -} - -// *************************************************************************** - -void CWorldEditorDoc::serial (NLMISC::IStream &s) -{ - s.xmlPush ("NEL_WORLD_EDITOR_PROJECT"); - - // Serial - int version = s.serialVersion (2); - - s.xmlSerial (_DataDir, "DATA_DIRECTORY"); - - if (version>0) - { - s.xmlSerial (_Context, "CONTEXT"); - } - - // Old structures - vector landscapes; - vector primitives; - - s.xmlPush ("LANDSCAPE"); - s.serialCont (landscapes); - s.xmlPop (); - - s.xmlPush ("PRIMITIVES"); - s.serialCont (primitives); - s.xmlPop (); - - // * Convert in new structures - - // Resvere - // _DataHierarchy.reserve (landscapes.size () + primitives.size ()); - - // Copy landscapes - uint i; - for (i=0; i=2) && (title[title.size()-1] == '*') && (title[title.size()-2] == ' ') ) - { - title.resize (title.size () - 2); - SetTitle (title.c_str()); - } - } -} - -// *************************************************************************** - -void CWorldEditorDoc::noUndoModification () -{ - _NoModificationUndo = true; - - updateModifiedState (); -} - -// *************************************************************************** - -void CWorldEditorDoc::undo () -{ - // Should not be in modification mode - nlassertex (_ModificationMode == false, ("In modification mode !")); - - if (_Undo > 0) - { - _Undo--; - - // Undo actions - for (uint i=0; i<_Actions[_Undo].size (); i++) - _Actions[_Undo][_Actions[_Undo].size ()-i-1]->undo (); - - updateModifiedState (); - } -} - -// *************************************************************************** - -void CWorldEditorDoc::redo () -{ - // Should not be in modification mode - nlassertex (_ModificationMode == false, ("In modification mode !")); - - if (_Undo < _Actions.size ()) - { - // Undo actions - for (uint i=0; i<_Actions[_Undo].size (); i++) - _Actions[_Undo][i]->redo (); - - _Undo++; - - updateModifiedState (); - } -} - -// *************************************************************************** - -void CWorldEditorDoc::clearModifications () -{ - for (uint i=0; i<_Actions.size (); i++) - for (uint j=0; j<_Actions[i].size (); j++) - { - delete _Actions[i][j]; - } - - _Actions.clear (); - _NoModificationUndo = false; - _Undo = 0; - _LastSaveUndo = 0; - _Modified = false; -} - -// *************************************************************************** - -const string &CWorldEditorDoc::getDataDir () const -{ - return _DataDir; -} - -// *************************************************************************** - - -void CWorldEditorDoc::getFilePath(uint primIndex,string & relativeFileName) -{ - relativeFileName=_DataHierarchy[primIndex].Filename; - CPath::makePathRelative ((NLMISC::CFile::getPath ((LPCTSTR)CWorldEditorDoc::GetPathName())).c_str(), relativeFileName); -} - -// *************************************************************************** - -void CWorldEditorDoc::setDataDir (const char *dir) -{ - _DataDir = dir; - - modifyProject (); - - noUndoModification (); -} - -// *************************************************************************** - -const string& CWorldEditorDoc::getPathOfSelectedPrimitive() const -{ - return _PathOfSelectedPrimitive; -} - -// *************************************************************************** - -void CWorldEditorDoc::setPathOfSelectedPrimitive(const std::string& s) -{ - _PathOfSelectedPrimitive = s; -} - -// *************************************************************************** - -bool CWorldEditorDoc::getZoneAmongRegions (CDatabaseLocator &locator, class CBuilderZoneRegion*& pBZRfrom, sint32 x, sint32 y) -{ - uint32 nNbRegion = _DataHierarchy.size (); - int regionId = -1; - for (uint32 i = 0; i < nNbRegion; ++i) - { - // Landscape ? - if (_DataHierarchy[i].Type == CDatabaseElement::Landscape) - { - regionId++; - const NLLIGO::CZoneRegion ®ion = getZoneRegionAbsolute (i); - if ((x < region.getMinX ())||(x > region.getMaxX ())||(y < region.getMinY ())||(y > region.getMaxY ())) - continue; - if (region.getName (x, y) != STRING_UNUSED) - { - pBZRfrom = getMainFrame ()->_ZoneBuilder->_ZoneRegions[regionId]; - locator = CDatabaseLocator (regionId, x, y); - return true; - } - } - } - - // The zone is not present in other region so it is an empty or oob zone of the current region - const NLLIGO::CZoneRegion ®ion = getZoneRegion(pBZRfrom->RegionId); - if ((x < region.getMinX ())||(x > region.getMaxX ())||(y < region.getMinY ())||(y > region.getMaxY ())) - return false; // Out Of Bound - - locator = CDatabaseLocator (pBZRfrom->RegionId, x, y); - - return true; -} - -// *************************************************************************** - -const NLLIGO::CZoneRegion &CWorldEditorDoc::getZoneRegion (uint landscape) const -{ - uint index = regionIDToDatabaseElementID (landscape); - return _DataHierarchy[index].ZoneRegion; -} - -// *************************************************************************** - -uint CWorldEditorDoc::regionIDToDatabaseElementID (uint landscape) const -{ - uint32 nNbRegion = _DataHierarchy.size (); - uint32 i; - for (i = 0; i < nNbRegion; ++i) - { - // Landscape ? - if (_DataHierarchy[i].Type == CDatabaseElement::Landscape) - { - if (landscape == 0) - return i; - landscape --; - } - } - // Should be found - nlstop; - return i; -} - -// *************************************************************************** - -const NLLIGO::CZoneRegion &CWorldEditorDoc::getZoneRegionAbsolute (uint landscape) const -{ - nlassert (isLandscape (landscape)); - return _DataHierarchy[landscape].ZoneRegion; -} - -// *************************************************************************** - -bool CWorldEditorDoc::addModification (class IAction *action) -{ - // Should be in modification mode - nlassertex (_ModificationMode == true, ("Not in modification mode !")); - - // Push first the action - uint actionId = _CurrentAction.size (); - _CurrentAction.push_back (action); - - // Do the action - if (!action->redo ()) - { - // Delete all new actions - nlassert (_CurrentAction.size ()>0); - for (uint a=_CurrentAction.size ()-1; a>actionId; a--) - { - // Undo - _CurrentAction[a]->undo (); - delete _CurrentAction[a]; - } - delete action; - _CurrentAction.pop_back (); - - return false; - } - - - return true; -} - -// *************************************************************************** - -void CWorldEditorDoc::getLigoData (CLigoData &data, const CDatabaseLocator &locator) -{ - NLLIGO::CZoneRegion ®ion = _DataHierarchy[locator.getDatabaseIndex ()].ZoneRegion; - nlassert ((locator.XSubPrim >= region.getMinX ()) && (locator.XSubPrim <= region.getMaxX ()) && (locator.Y >= region.getMinY ()) && (locator.Y <= region.getMaxY ())); - - data.PosX = region.getPosX (locator.XSubPrim, locator.Y); - data.PosY = region.getPosY (locator.XSubPrim, locator.Y); - data.ZoneName = region.getName (locator.XSubPrim, locator.Y); - data.Rot = region.getRot (locator.XSubPrim, locator.Y); - data.Flip = region.getFlip (locator.XSubPrim, locator.Y); - data.SharingMatNames[0] = region.getSharingMatNames (locator.XSubPrim, locator.Y, 0); - data.SharingMatNames[1] = region.getSharingMatNames (locator.XSubPrim, locator.Y, 1); - data.SharingMatNames[2] = region.getSharingMatNames (locator.XSubPrim, locator.Y, 2); - data.SharingMatNames[3] = region.getSharingMatNames (locator.XSubPrim, locator.Y, 3); - data.SharingCutEdges[0] = region.getSharingCutEdges (locator.XSubPrim, locator.Y, 0); - data.SharingCutEdges[1] = region.getSharingCutEdges (locator.XSubPrim, locator.Y, 1); - data.SharingCutEdges[2] = region.getSharingCutEdges (locator.XSubPrim, locator.Y, 2); - data.SharingCutEdges[3] = region.getSharingCutEdges (locator.XSubPrim, locator.Y, 3); -} - -// *************************************************************************** - -void CWorldEditorDoc::CLandscapeDeprecated::serial (NLMISC::IStream &s) -{ - s.serialVersion (0); - s.serial (Filename); -} - -// *************************************************************************** - -void CWorldEditorDoc::CPrimitiveDeprecated::serial (NLMISC::IStream &s) -{ - s.serialVersion (0); - s.serial (Filename); -} - -// *************************************************************************** - -CWorldEditorDoc::CDatabaseElement::CDatabaseElement () -{ - Type = Undefined; - Editable = true; - Modified = false; -} - -// *************************************************************************** - -CWorldEditorDoc::CDatabaseElement::CDatabaseElement (TType type) -{ - Type = type; - if (Type == Landscape) - Primitives.RootNode->addPropertyByName ("class", new CPropertyString ("landscape")); - Editable = true; - Modified = false; -} - -// *************************************************************************** - -void CWorldEditorDoc::beginModification () -{ - nlassertex (_ModificationMode == false, ("Already in modification mode !")); - _ModificationMode = true; - - // Erase current action - _CurrentAction.clear (); -} - -// *************************************************************************** - -void CWorldEditorDoc::endModification () -{ - nlassertex (_ModificationMode == true, ("Not in modification mode !")); - _ModificationMode = false; - - // Add a undo entry if some actions have been performed - if (!_CurrentAction.empty ()) - { - // Remove next actions - for (uint i=_Undo; i<_Actions.size (); i++) - for (uint j=0; j<_Actions[i].size (); j++) - { - delete _Actions[i][j]; - } - - // Place the current action - _Actions.resize (_Undo+1); - _Actions[_Undo] = _CurrentAction; - - // Invalidate save position - if (_Undo < _LastSaveUndo) - _LastSaveUndo = -1; - - _Undo++; - - updateModifiedState (); - - // check if we need to send an update to the plugins - bool needUpdate = false; - std::vector::iterator first(_CurrentAction.begin()), last(_CurrentAction.end()); - for (; first != last; ++first) - { - needUpdate |= (*first)->isAffectingContent(); - } - if (needUpdate) - { - for (uint i=0; iprimitiveChanged(_DataHierarchy[j].Primitives.RootNode); - } - } - } - } -} - -// *************************************************************************** - -uint CWorldEditorDoc::getNumDatabaseElement () const -{ - return _DataHierarchy.size (); -} - -// *************************************************************************** - -const std::string &CWorldEditorDoc::getDatabaseElement (uint primitive) const -{ - return _DataHierarchy[primitive].Filename; -} - -// *************************************************************************** - -const NLLIGO::CPrimitives &CWorldEditorDoc::getDatabaseElements (uint primitive) const -{ - return _DataHierarchy[primitive].Primitives; -} - -// *************************************************************************** - -void CWorldEditorDoc::getLocator (CDatabaseLocatorPointer &locator, const IPrimitive *primitive) const -{ - static std::vector cache; - cache.clear (); - - // Get the first - const IPrimitive *current = primitive; - const IPrimitive *parent = current->getParent (); - while (parent) - { - // Get the child id - uint childId; - nlverify (parent->getChildId (childId, current)); - cache.push_back (childId); - current = parent; - parent = current->getParent (); - } - - // Root node - uint i; - CWorldEditorDoc *doc = getDocument (); - uint count = doc->getNumDatabaseElement (); - for (i=0; igetDatabaseElements (i).RootNode == current) - { - break; - } - } - - nlassert (i0); - - // Copy the stack - locatorDest._LocateStack = locator._LocateStack; - - // Get the first primitive - locatorDest.Primitive = _DataHierarchy[locator._LocateStack[0]].Primitives.RootNode; - - // Get into the stack - uint stackSize = locator._LocateStack.size (); - for (uint i=1; igetChild (locatorDest.Primitive, locator._LocateStack[i])); - } -} - -// *************************************************************************** - -void CWorldEditorDoc::getFirstLocator (CDatabaseLocatorPointer &locator) const -{ - // Set as end - locator._LocateStack[0] = 0xffffffff; - locator.Primitive = NULL; - - // Is a first primitive ? - if (_DataHierarchy.size ()) - { - locator._LocateStack[0] = 0; - } -} - -// *************************************************************************** - -void CWorldEditorDoc::deletePrimitive (const CDatabaseLocator &locator) -{ - // Locate it - CDatabaseLocatorPointer locatorDest; - getLocator (locatorDest, locator); - - // Get the parent - IPrimitive *parent = const_cast(locatorDest.Primitive)->getParent (); - nlassert (parent); - - // Get the child id - uint childId; - nlverify (parent->getChildId (childId, locatorDest.Primitive)); - - // Delete the child - nlverify (parent->removeChild (childId)); -} - -// *************************************************************************** - -void CWorldEditorDoc::insertPrimitive (const CDatabaseLocator &locator, IPrimitive *primitive) -{ - nlassert (locator._LocateStack.size ()>0); - - // Get the first primitive - IPrimitive *prim = _DataHierarchy[locator._LocateStack[0]].Primitives.RootNode; - - // Get into the stack - uint stackSize = locator._LocateStack.size (); - uint i; - for (i=1; igetChild (prim, locator._LocateStack[i])); - } - - // Set the context - CPrimitiveContext::instance().CurrentPrimitive = &_DataHierarchy[locator._LocateStack[0]].Primitives; - - // Insert the primitive in the parent - nlverify (prim->insertChild (primitive, locator._LocateStack[i])); - - // unset the context - CPrimitiveContext::instance().CurrentPrimitive = NULL; -} - -// *************************************************************************** - -uint32 getUniqueId () -{ - // Wait 1 ms - sint64 time = NLMISC::CTime::getLocalTime (); - sint64 time2; - while ((time2 = NLMISC::CTime::getLocalTime ()) == time) - { - } - - return (uint32)time2; -} - -// *************************************************************************** - -void CWorldEditorDoc::initPrimitiveParameters (const CPrimitiveClass &primClass, IPrimitive &primitive, - const std::vector &initParameters) -{ - // Other parameters - for (uint p=0; p 1) - theApp.errorMessage ("Warning: parameter (%s) in class name (%s) has more than 1 default value (%d).", - parameter.Name.c_str (), primClass.Name.c_str (), parameter.DefaultValue.size ()); - - if ( - (cpStringArray.resize (parameter.DefaultValue.size ()); - for (i=0; iStringArray[i] = toString (getUniqueId ()); - } - else - { - str->StringArray[i] = ""; - } - } - primitive.addPropertyByName (parameter.Name.c_str (), str); - } - break; - } - } - } - } - else - { - // Some feedback - theApp.errorMessage ("Warning: parameter (%s) doesn't exist in class (%s).", - initParameters[p].Name.c_str (), primClass.Name.c_str ()); - } - } -} - -// *************************************************************************** - -const NLLIGO::IPrimitive *CWorldEditorDoc::createPrimitive (const CDatabaseLocator &locator, const char *className, const char *primName, - const CVector &initPos, float deltaPos, - const std::vector &initParameters) -{ - // Get the prim class - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (className); - if (primClass) - { - // Create the base primitive - IPrimitive *primitive = NULL; - switch (primClass->Type) - { - case CPrimitiveClass::Node: - primitive = new CPrimNodeEditor; - break; - case CPrimitiveClass::Point: - { - CPrimPointEditor *point = new CPrimPointEditor; - primitive = point; - point->Point.CVector::operator= (initPos); - } - break; - case CPrimitiveClass::Path: - primitive = new CPrimPathEditor; - break; - case CPrimitiveClass::Zone: - primitive = new CPrimZoneEditor; - break; - case CPrimitiveClass::Alias: - primitive = new CPrimAliasEditor; - break; - case CPrimitiveClass::Bitmap: - primitive = new CPrimBitmap; - break; - } - nlassert (primitive); - - // Add properties - primitive->addPropertyByName ("class", new CPropertyString (className)); - primitive->addPropertyByName ("name", new CPropertyString (primName, primName[0] == 0)); - - // Init with default parameters - std::vector tempParam; - tempParam.reserve (primClass->Parameters.size ()); - for (uint i=0; iParameters.size (); i++) - tempParam.push_back (primClass->Parameters[i]); - initPrimitiveParameters (*primClass, *primitive, tempParam); - - // Init with option parameters - initPrimitiveParameters (*primClass, *primitive, initParameters); - - // Insert the primitive - insertPrimitive (locator, primitive); - - // The new pos - CVector newPos = initPos; - newPos.x += deltaPos; - - // Create static children - uint c; - for (c=0; cStaticChildren.size (); c++) - { - // The child ref - const CPrimitiveClass::CChild &child = primClass->StaticChildren[c]; - - // The new locator - CDatabaseLocator childLocator = locator; - childLocator._LocateStack.push_back (0); - - // Create the child - const NLLIGO::IPrimitive *childPrim = createPrimitive (childLocator, child.ClassName.c_str (), - child.Name.c_str (), newPos, deltaPos, primClass->StaticChildren[c].Parameters); - - // The new pos - newPos.y += deltaPos; - } - - // Canceled ? - if (cStaticChildren.size ()) - { - deletePrimitive (locator); - return NULL; - } - - // Prim file ? - if (primClass->Type == CPrimitiveClass::Bitmap) - { - // Create a dialog file - CFileDialogEx dialog (BASE_REGISTRY_KEY, "image", TRUE, primClass->FileExtension.c_str (), NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, - (primClass->FileType+" (*."+primClass->FileExtension+")|*."+primClass->FileExtension+"|All Files (*.*)|*.*||").c_str (), getMainFrame ()); - if (dialog.DoModal() == IDOK) - { - // Save filename - static_cast(primitive)->init (dialog.GetPathName ()); - } - } - - // Continue ? - if (primitive) - { - // Auto init ? - if (!primClass->AutoInit) - { - // Make a vector of locator - CDatabaseLocatorPointer locatorPtr; - getLocator (locatorPtr, locator); - std::list locators; - locators.push_back (const_cast (locatorPtr.Primitive)); - - // Yes, go - CDialogProperties dialogProperty (locators, getMainFrame ()); - dialogProperty.DoModal (); - } - - // Eval the default name property - string name; - if (!primitive->getPropertyByName ("name", name) || name.empty()) - { - const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*primitive); - if (primClass) - { - uint i; - for (i=0; iParameters.size(); i++) - { - if (primClass->Parameters[i].Name == "name") - { - std::string result; - primClass->Parameters[i].getDefaultValue (result, *primitive, *primClass, NULL); - if (!result.empty()) - { - primitive->removePropertyByName ("name"); - primitive->addPropertyByName ("name", new CPropertyString (result.c_str(), true)); - } - } - } - } - } - - // Init primitive default values - primitive->initDefaultValues (theApp.Config); - } - - // Done - return primitive; - } - else - { - theApp.errorMessage ("Unknown primitive class name : %s", className); - } - return NULL; -} - -// *************************************************************************** - -void CWorldEditorDoc::getPrimitiveDisplayName (std::string &result, uint primitive) const -{ - // Return a formated string - result = formatString (NLMISC::CFile::getFilename (getDatabaseElement (primitive)).c_str ()); - if (result.empty ()) - result = "Untitled"; - if (_DataHierarchy[primitive].Modified && _DataHierarchy[primitive].Editable) - result += " *"; -} - - -// *************************************************************************** - -void CWorldEditorDoc::modifyDatabase (uint dbIndex) -{ - if (_DataHierarchy[dbIndex].Editable) - { - _DataHierarchy[dbIndex].Modified = true; - if (isLandscape (dbIndex)) - modifyProject (); - } - - // Invalidate title - CDatabaseLocatorPointer locator; - locator.getRoot (dbIndex); - InvalidatePrimitive (locator, LogicTreeParam); - - // plugin callback -// for (uint i=0; iprimitiveChanged(locator.Primitive); -} - -// *************************************************************************** - -void CWorldEditorDoc::modifyProject () -{ - _Modified = true; -} - -// *************************************************************************** - -void CWorldEditorDoc::updateFiles () -{ - // Landscape - uint i; - for (i=0; i<_DataHierarchy.size (); i++) - { - // Check date - if (!checkFileDate (_DataHierarchy[i].Filename.c_str (), _DataHierarchy[i].LastModifedTime)) - { - // Ask for reloading - if (theApp.yesNoMessage ("The file \"%s\" has been modified.\nReload it ?", _DataHierarchy[i].Filename.c_str ())) - { - // Clear modification - clearModifications (); - - // Landscape ? - if (_DataHierarchy[i].Type == CDatabaseElement::Landscape) - { - try - { - CIFile fileIn; - if (fileIn.open (_DataHierarchy[i].Filename)) - { - CIXml xml(true); - xml.init (fileIn); - _DataHierarchy[i].ZoneRegion.serial (xml); - } - else - { - theApp.errorMessage ("Can't open file %s for reading.", _DataHierarchy[i].Filename.c_str ()); - } - - // Last time - _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); - } - catch (Exception& e) - { - theApp.errorMessage ("Error reading file %s : %s", _DataHierarchy[i].Filename.c_str (), e.what ()); - } - } - else - { - try - { - CIFile fileIn; - if (fileIn.open (_DataHierarchy[i].Filename)) - { - // Xml stream - CIXml xmlIn; - xmlIn.init (fileIn); - - // Read it - CPrimitiveContext::instance().CurrentPrimitive = &(_DataHierarchy[i].Primitives); - if (!_DataHierarchy[i].Primitives.read (xmlIn.getRootNode (), _DataHierarchy[i].Filename.c_str(), theApp.Config)) - { - theApp.errorMessage ("Error reading file %s", _DataHierarchy[i].Filename.c_str ()); - CPrimitiveContext::instance().CurrentPrimitive = NULL; - } - CPrimitiveContext::instance().CurrentPrimitive = NULL; - - // Last time - _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); - - InvalidateAllPrimitives(); - - } - else - { - theApp.errorMessage ("Can't open file %s for reading.", _DataHierarchy[i].Filename.c_str ()); - } - } - catch (Exception& e) - { - theApp.errorMessage ("Error reading file %s : %s", _DataHierarchy[i].Filename.c_str (), e.what ()); - } - } - - // Invalidate views - invalidateLeftView (); - } - else - { - // Get the new date - _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); - } - } - } - - // Check date - if (!checkFileDate (GetPathName (), _LastModifedTime)) - { - // Ask for reloading - if (theApp.yesNoMessage ("The file \"%s\" has been modified.\nReload it ?", (const char*)GetPathName ())) - { - newDocument (); - loadDocument (GetPathName ()); - } - else - { - // Get the new date - _LastModifedTime = NLMISC::CFile::getFileModificationDate ((const char*)GetPathName ()); - } - } -} - -// *************************************************************************** - -bool CWorldEditorDoc::checkFileDate (const char *filename, uint32 date) -{ - // File exist ? - if (!NLMISC::CFile::fileExists (filename)) - return true; - - // Check each file in the project - return NLMISC::CFile::getFileModificationDate (filename) == date; -} - -// *************************************************************************** - -bool CWorldEditorDoc::undoAvailable () const -{ - return _Undo > 0; -} - -// *************************************************************************** - -bool CWorldEditorDoc::redoAvailable () const -{ - return _Undo < _Actions.size (); -} - -// *************************************************************************** - -bool CWorldEditorDoc::isPrimitiveLoaded(const std::string &primPath) -{ - uint i = 0, count = getNumDatabaseElement(); - string curPath; - - while (i < count) - { - getFilePath(i, curPath); - if (primPath == curPath) - break; - else - i++; - } - - if (i < count) - return true; - else - return false; -} - -// *************************************************************************** - -bool CWorldEditorDoc::isLandscape (uint dbIndex) const -{ - return _DataHierarchy[dbIndex].Type == CDatabaseElement::Landscape; -} - -// *************************************************************************** - -bool CWorldEditorDoc::isPrimitive (uint dbIndex) const -{ - return _DataHierarchy[dbIndex].Type == CDatabaseElement::Primitive; -} - -// *************************************************************************** - -bool CWorldEditorDoc::isEditable (uint dbIndex) const -{ - return _DataHierarchy[dbIndex].Editable; -} - -// *************************************************************************** - -void CWorldEditorDoc::resetUniqueID (const NLLIGO::IPrimitive &primitive, bool onlyZero) -{ - // Got a primitive class ? - const CPrimitiveClass *_class = theApp.Config.getPrimitiveClass (primitive); - if (_class) - { - // For each parameters - uint i; - for (i=0; i<_class->Parameters.size (); i++) - { - // String or string array ? - if (_class->Parameters[i].Type == CPrimitiveClass::CParameter::String) - { - // Default value available ? - if (!_class->Parameters[i].DefaultValue.empty ()) - { - // Unique Id ? - if (_class->Parameters[i].DefaultValue[0].GenID) - { - string propVal; - primitive.getPropertyByName(_class->Parameters[i].Name.c_str(), propVal); - if (!onlyZero || propVal.empty() || propVal == "0") - { - // Remove it - CDatabaseLocatorPointer locator; - getLocator (locator, &primitive); - - addModification (new CActionSetPrimitivePropertyString (locator, _class->Parameters[i].Name.c_str (), toString (getUniqueId ()).c_str (), false)); - } - } - } - } - else if (_class->Parameters[i].Type == CPrimitiveClass::CParameter::StringArray) - { - uint j; - for (j=0; j<_class->Parameters[i].DefaultValue.size (); j++) - { - // Unique Id ? - if (_class->Parameters[i].DefaultValue[j].GenID) - { - string propVal; - primitive.getPropertyByName(_class->Parameters[j].Name.c_str(), propVal); - if (!onlyZero || propVal.empty() || propVal == "0") - { - // The doesn't exist ? - std::vector result; - std::vector *resultPtr = NULL; - primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), resultPtr); - - // Copy - if (resultPtr) - result = *resultPtr; - - // Resize - if (result.size ()<=j) - result.resize (j+1); - - // Set the value - result[j] = toString (getUniqueId ()); - - CDatabaseLocatorPointer locator; - getLocator (locator, &primitive); - addModification (new CActionSetPrimitivePropertyStringArray (locator, _class->Parameters[i].Name.c_str (), result, false)); - } - } - } - } - } - } - - // Recurcive call - uint i; - const uint count = primitive.getNumChildren (); - for (i=0; i &ids, std::vector &nonUnique) -{ - // Got a primitive class ? - const CPrimitiveClass *_class = theApp.Config.getPrimitiveClass (primitive); - if (_class) - { - // For each parameters - uint i; - for (i=0; i<_class->Parameters.size (); i++) - { - // String or string array ? - if (_class->Parameters[i].Type == CPrimitiveClass::CParameter::String) - { - // Default value available ? - if (!_class->Parameters[i].DefaultValue.empty ()) - { - // Unique Id ? - if (_class->Parameters[i].DefaultValue[0].GenID) - { - string propVal; - primitive.getPropertyByName(_class->Parameters[i].Name.c_str(), propVal); - if (ids.find(propVal) != ids.end()) - { - // store it in the list of non unique id - TPropertyNonUnique nu; - nu.Primitive = &primitive; - nu.PropertyName = _class->Parameters[i].Name; - - nonUnique.push_back(nu); -// // regenerate it -// CDatabaseLocatorPointer locator; -// getLocator (locator, &primitive); -// -// addModification (new CActionSetPrimitivePropertyString (locator, _class->Parameters[i].Name.c_str (), toString (getUniqueId ()).c_str (), false)); -// -// regenCount++; - } - primitive.getPropertyByName(_class->Parameters[i].Name.c_str(), propVal); - ids.insert(propVal); - } - } - } - else if (_class->Parameters[i].Type == CPrimitiveClass::CParameter::StringArray) - { - uint j; - for (j=0; j<_class->Parameters[i].DefaultValue.size (); j++) - { - // Unique Id ? - if (_class->Parameters[i].DefaultValue[j].GenID) - { - string propVal; - primitive.getPropertyByName(_class->Parameters[j].Name.c_str(), propVal); - if (ids.find(propVal) != ids.end()) - { - // store it in the list of non unique id - TPropertyNonUnique nu; - nu.Primitive = &primitive; - nu.PropertyName = _class->Parameters[j].Name; - - nonUnique.push_back(nu); -// // The doesn't exist ? -// std::vector result; -// std::vector *resultPtr = NULL; -// primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), resultPtr); -// -// // Copy -// if (resultPtr) -// result = *resultPtr; -// -// // Resize -// if (result.size ()<=j) -// result.resize (j+1); -// -// // Set the value -// result[j] = toString (getUniqueId ()); -// -// CDatabaseLocatorPointer locator; -// getLocator (locator, &primitive); -// addModification (new CActionSetPrimitivePropertyStringArray (locator, _class->Parameters[i].Name.c_str (), result, false)); -// -// regenCount++; - } - primitive.getPropertyByName(_class->Parameters[j].Name.c_str(), propVal); - ids.insert(propVal); - } - } - } - } - } - - // Recursive call - uint i; - const uint count = primitive.getNumChildren (); - for (i=0; iParameters.size (); i++) - { - // First check the primitive property has to good type - IProperty *prop; - if (primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), prop)) - { - // String to array ? - CPropertyString *propString = dynamic_cast (prop);; - const bool classStringArray = _class->Parameters[i].Type == CPrimitiveClass::CParameter::StringArray || - _class->Parameters[i].Type == CPrimitiveClass::CParameter::ConstStringArray; - if (propString && classStringArray) - { - // Build an array string - vector array; - if (!propString->String.empty()) - array.push_back (propString->String); - prop = new CPropertyStringArray (array); - primitive.removePropertyByName (_class->Parameters[i].Name.c_str ()); - primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), prop); - modified = true; - } - - // Array to string ? - CPropertyStringArray *propStringArray = dynamic_cast (prop); - if (propStringArray && !classStringArray) - { - // Build an array string - string str; - if (!propStringArray->StringArray.empty()) - str = propStringArray->StringArray[0]; - prop = new CPropertyString (str); - primitive.removePropertyByName (_class->Parameters[i].Name.c_str ()); - primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), prop); - modified = true; - } - } - - // String or string array ? - if (_class->Parameters[i].Type == CPrimitiveClass::CParameter::String) - { - // Default value available ? - if (!_class->Parameters[i].DefaultValue.empty ()) - { - // Unique Id ? - if (_class->Parameters[i].DefaultValue[0].GenID) - { - // The doesn't exist ? - string result; - if (!primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), result)) - { - // Add it ! - primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), new CPropertyString (toString (getUniqueId ()).c_str ())); - modified = true; - } - } - // Hidden ? - else if (!_class->Parameters[i].Visible) - { - // The doesn't exist ? - string result; - if (!primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), result)) - { - // Add it ! - primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), new CPropertyString ("")); - modified = true; - } - } - } - } - else if ( (_class->Parameters[i].Type == CPrimitiveClass::CParameter::StringArray) || - (_class->Parameters[i].Type == CPrimitiveClass::CParameter::ConstStringArray) ) - { - uint j; - for (j=0; j<_class->Parameters[i].DefaultValue.size (); j++) - { - // Unique Id ? - if (_class->Parameters[i].DefaultValue[j].GenID) - { - // The doesn't exist ? - std::vector result; - std::vector *resultPtr = NULL; - if (!primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), resultPtr) || (resultPtr->size ()<=j)) - { - // Copy - if (resultPtr) - result = *resultPtr; - - // Resize - if (result.size ()<=j) - result.resize (j+1); - - // Resize to it - primitive.removePropertyByName (_class->Parameters[i].Name.c_str ()); - - // Set the value - result[j] = toString (getUniqueId ()); - - // Add the new property array - primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), new CPropertyStringArray (result)); - modified = true; - } - } - // Hidden ? - else if (!_class->Parameters[i].Visible) - { - // The doesn't exist ? - std::vector result; - std::vector *resultPtr = NULL; - if (!primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), resultPtr) || (resultPtr->size ()<=j)) - { - // Copy - if (resultPtr) - result = *resultPtr; - - // Resize - if (result.size ()<=j) - result.resize (j+1); - - // Resize to it - primitive.removePropertyByName (_class->Parameters[i].Name.c_str ()); - - // Set the value - result[j] = ""; - - // Add the new property array - primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), new CPropertyStringArray (result)); - modified = true; - } - } - } - } - else - { - // Default value available ? - if (!_class->Parameters[i].DefaultValue.empty ()) - { - // Hidden ? - if (!_class->Parameters[i].Visible) - { - // The doesn't exist ? - string result; - if (!primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), result)) - { - // Add it ! - primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), new CPropertyString ("")); - modified = true; - } - } - } - } - } - } - - // Recurcive call - uint i; - const uint count = primitive.getNumChildren (); - for (i=0; iisActive()) - theApp.Plugins.at(i-ID_WINDOWS_PLUGINS-1)->closePlugin(); - else - theApp.Plugins.at(i-ID_WINDOWS_PLUGINS-1)->activatePlugin(); - - } - else if (nCode == CN_UPDATE_COMMAND_UI) - { - // Update UI element state - - if(theApp.Plugins.at(i-ID_WINDOWS_PLUGINS-1)->isActive()) - pCmdUI->SetCheck(); - else - pCmdUI->SetCheck(0); - pCmdUI->Enable(); - - } - return TRUE; - } - } - } - - // If we didn't process the command, call the base class - // version of OnCmdMsg so the message-map can handle the message - return CDocument::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); -} - -// *************************************************************************** - - - - - -// *************************************************************************** -// CDatabaseLocator -// *************************************************************************** - -uint CDatabaseLocator::getDatabaseIndex () const -{ - return _LocateStack[0]; -} - -// *************************************************************************** - -void CDatabaseLocator::getParent () -{ - _LocateStack.resize (_LocateStack.size ()-1); -} - -// *************************************************************************** -// CDatabaseLocatorPointer -// *************************************************************************** - -void CDatabaseLocatorPointer::getParent () -{ - nlassert (Primitive); - CDatabaseLocator::getParent (); - - // Get the parent pointer - Primitive = Primitive->getParent (); -} - -// *************************************************************************** - -bool CDatabaseLocatorPointer::operator== (const CDatabaseLocatorPointer &other) const -{ - return CDatabaseLocator::operator== (other); -} - -// *************************************************************************** - -void CDatabaseLocatorPointer::appendChild (CDatabaseLocator &dest) const -{ - nlassert (Primitive); - dest._LocateStack = _LocateStack; - dest._LocateStack.push_back (Primitive->getNumChildren ()); - dest.XSubPrim = 0xffffffff; -} - -// *************************************************************************** - -bool CDatabaseLocatorPointer::next () -{ - // Should not be end - if (_LocateStack[0] == 0xffffffff) - return false; - - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // We are in a primitive ? - if (Primitive) - { - // Some children to visite ? - if (Primitive->getNumChildren () > 0) - { - // Get the first child - nlverify (Primitive->getChild (Primitive, 0)); - - // Push - _LocateStack.push_back (0); - - // Done - return true; - } - - // Try to visit a brother - const IPrimitive *parent = Primitive->getParent (); - - // Have a parent ? - while (parent) - { - // The child Id - uint childId; - - nlverify (parent->getChildId (childId, Primitive)); - childId++; - if (childId < parent->getNumChildren ()) - { - nlassert (_LocateStack.back () == childId-1); - _LocateStack.back () = childId; - nlverify (parent->getChild (Primitive, childId)); - return true; - } - else - { - // Get next parent - Primitive = parent; - parent = parent->getParent (); - - // Unstack - _LocateStack.pop_back (); - } - } - - // Next primitive Id - _LocateStack[0]++; - nlassert (_LocateStack.size () == 1); - Primitive = NULL; - if (_LocateStack[0] < doc->_DataHierarchy.size ()) - { - return true; - } - - // End - _LocateStack[0] = 0xffffffff; - return false; - } - else - { - Primitive = doc->_DataHierarchy[_LocateStack[0]].Primitives.RootNode; - return true; - } -} - -// *************************************************************************** - -void CDatabaseLocatorPointer::getRoot (uint i) -{ - XSubPrim = 0xffffffff; - _LocateStack.clear (); - _LocateStack.push_back (i); - - // Get the document - CWorldEditorDoc *doc = getDocument (); - - Primitive = doc->_DataHierarchy[i].Primitives.RootNode; -} - -// *************************************************************************** - -void CDatabaseLocatorPointer::getRoot (const string& rootFileName) -{ - XSubPrim = 0xffffffff; - _LocateStack.clear (); - - - // Get the document - CWorldEditorDoc *doc = getDocument (); - uint count = doc->getNumDatabaseElement (); - uint i=0; - for(i=0;i_DataHierarchy[i].Filename)==0) - break; - if(i_DataHierarchy[i].Primitives.RootNode; - _LocateStack.push_back (i); - } - else - { - exception e("Bad primitive File Name. Please refresh."); - throw(e); - } -} - -// *************************************************************************** - -string& CDatabaseLocatorPointer::getRootFileName (IPrimitive* rootPrim) -{ - // Get the document - CWorldEditorDoc *doc = getDocument (); - uint count = doc->getNumDatabaseElement (); - uint i=0; - for(i=0;i_DataHierarchy[i].Primitives.RootNode ==rootPrim) - break; - - if(i==count) - { - exception e("Bad primitive File Name. Please refresh."); - throw(e); - } - - return doc->_DataHierarchy[i].Filename; - -} - -// *************************************************************************** - -bool CDatabaseLocatorPointer::firstChild () -{ - XSubPrim = 0xffffffff; - // Should not be end - if (_LocateStack[0] == 0xffffffff) - return false; - - // Get the document - CWorldEditorDoc *doc = getDocument (); - - // Some children to visite ? - if (Primitive->getNumChildren () > 0) - { - // Get the first child - nlverify (Primitive->getChild (Primitive, 0)); - - // Push - _LocateStack.push_back (0); - - // Done - return true; - } - else - { - // Primitive doesn't exist - Primitive = NULL; - - // Push - _LocateStack.push_back (0); - - // Done - return false; - } -} - -// *************************************************************************** - -bool CDatabaseLocatorPointer::nextChild () -{ - // Try to visit a brother - const IPrimitive *parent = Primitive->getParent (); - - // Have a parent ? - nlassert (parent); - - // The child Id - uint childId; - - nlverify (parent->getChildId (childId, Primitive)); - childId++; - if (childId < parent->getNumChildren ()) - { - nlassert (_LocateStack.back () == childId-1); - _LocateStack.back () = childId; - nlverify (parent->getChild (Primitive, childId)); - return true; - } - else - { - // Get next parent - Primitive = parent; - parent = parent->getParent (); - - // Unstack - _LocateStack.pop_back (); - return false; - } -} - -// *************************************************************************** - -bool CDatabaseLocatorPointer::previousChild () -{ - // Try to visit a brother - const IPrimitive *parent = Primitive->getParent (); - - // Have a parent ? - nlassert (parent); - - // The child Id - uint childId; - - nlverify (parent->getChildId (childId, Primitive)); - if (childId > 0) - { - childId--; - nlassert (_LocateStack.back () == childId+1); - _LocateStack.back () = childId; - nlverify (parent->getChild (Primitive, childId)); - return true; - } - else - { - // Get next parent - Primitive = parent; - parent = parent->getParent (); - - // Unstack - _LocateStack.pop_back (); - return false; - } -} - -// *************************************************************************** - -bool CDatabaseLocator::operator== (const CDatabaseLocator &other) const -{ - return _LocateStack == other._LocateStack; -} - -// *************************************************************************** - -std::string CDatabaseLocator::getPathName () const -{ - // Get the doc - CWorldEditorDoc *doc = getDocument (); - - // First string - string path; - doc->getPrimitiveDisplayName (path, _LocateStack[0]); - - // Next - const IPrimitive *prim = doc->_DataHierarchy[_LocateStack[0]].Primitives.RootNode; - for (uint i=1; i<_LocateStack.size (); i++) - { - // Add the child - prim->getChild (prim, _LocateStack[i]); - - // Get its name - path += "."; - string name; - if (prim->getPropertyByName ("name", name)) - path += name; - } - - return path; -} - -// *************************************************************************** - -CDatabaseLocator::CDatabaseLocator (uint region, sint32 x, sint32 y) -{ - _LocateStack.push_back (getDocument ()->regionIDToDatabaseElementID(region)); - XSubPrim = x; - Y = y; -} - -// *************************************************************************** - -void CWorldEditorDoc::OnFileOpen() -{ - theApp.OnFileOpen (); -} - -// *************************************************************************** - -void CWorldEditorDoc::OnFileSave() -{ - theApp.OnFileSave (); -} - -// *************************************************************************** - -void CWorldEditorDoc::OnFileSaveAs() -{ - theApp.OnFileSaveAs (); -} - -// *************************************************************************** - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// world_editor_doc.cpp : implementation of the CWorldEditorDoc class +// + +#include "stdafx.h" + +#include "action.h" +#include "world_editor.h" +#include "main_frm.h" +#include "world_editor_doc.h" +#include "display.h" +#include "dialog_properties.h" +#include "editor_primitive.h" +#include "file_dialog_ex.h" + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; +using namespace NL3D; + +#define WORLD_EDITOR_FILE_VERSION 2 +#define WORLD_EDITOR_DATABASE_SIZE 100 + +// *************************************************************************** +// CWorldEditorDoc + +IMPLEMENT_DYNCREATE(CWorldEditorDoc, CDocument) + +BEGIN_MESSAGE_MAP(CWorldEditorDoc, CDocument) + //{{AFX_MSG_MAP(CWorldEditorDoc) + ON_COMMAND(ID_FILE_OPEN, OnFileOpen) + ON_COMMAND(ID_FILE_SAVE, OnFileSave) + ON_COMMAND(ID_FILE_SAVE_AS, OnFileSaveAs) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// *************************************************************************** +// CWorldEditorDoc construction/destruction + +CWorldEditorDoc::CWorldEditorDoc() +{ + _ModificationMode = false; + clearModifications (); +} + +CWorldEditorDoc::~CWorldEditorDoc() +{ + clearModifications (); +} + +// *************************************************************************** + +BOOL CWorldEditorDoc::OnNewDocument() +{ + if (!CDocument::OnNewDocument()) + return FALSE; + + // Main frame ? + CMainFrame *mainFrame = getMainFrame (); + if (mainFrame) + mainFrame->updateData (); + + return newDocument () ? TRUE : FALSE; +} + +// *************************************************************************** + +bool CWorldEditorDoc::newDocument () +{ + /*if (IsWindow(PropertyDialog)) + PropertyDialog.ShowWindow (SW_HIDE);*/ + + std::list::iterator it = PropertiesDialogs.begin(); + + while ( it != PropertiesDialogs.end() ) + { + (*it)->ShowWindow( SW_HIDE ); + delete (*it); + it++; + } + + PropertiesDialogs.clear(); + + _DataDir = ""; + _Context = ""; + + // Erase all editable root primitive + CDatabaseList::iterator ite = _DataHierarchy.begin(); + while (ite != _DataHierarchy.end()) + { + CDatabaseList::iterator next = ite; + next++; + if (ite->Editable) + _DataHierarchy.erase (ite); + ite = next; + } + + _DataHierarchy.recomputePointerArray (); + + // Init the landscape + CMainFrame *mainFrame = getMainFrame (); + if (mainFrame) + mainFrame->initLandscapeData (); + + clearModifications (); + + // Invalidate all + if (getMainFrame ()) + { + getMainFrame ()->invalidateTools (); + } + invalidateLeftView (); + + // Invalidate pointers + InvalidateAllPrimitives (); + if (getMainFrame()) + { + // we verify the structures of the primitives, and mark the incorrect nodes + VerifyPrimitivesStructures(); + } + + return true; +} + +// *************************************************************************** +// CWorldEditorDoc diagnostics + +#ifdef _DEBUG +void CWorldEditorDoc::AssertValid() const +{ + CDocument::AssertValid(); +} + +void CWorldEditorDoc::Dump(CDumpContext& dc) const +{ + CDocument::Dump(dc); +} +#endif //_DEBUG + +// *************************************************************************** +// CWorldEditorDoc commands + +CWorldEditorDoc *getDocument () +{ + if (getMainFrame ()) + return (CWorldEditorDoc *)(getMainFrame ()->GetActiveDocument ()); + else + return NULL; +} + +// *************************************************************************** + +BOOL CWorldEditorDoc::OnOpenDocument(LPCTSTR lpszPathName) +{ + // Timer enabled ? + getMainFrame ()->TimerEnabled = false; + + // Result + newDocument (); + bool res = loadDocument (lpszPathName) ? TRUE : FALSE; + + // Timer enabled ? + getMainFrame ()->TimerEnabled = true; + + return res; +} + +// *************************************************************************** + +bool CWorldEditorDoc::loadDocument (const char *filename) +{ + bool result = true; + + // Get path name + string path = NLMISC::CFile::getPath (filename); + + // Backup current path + string backupPath = CPath::getCurrentPath (); + + // Set current path + CPath::setCurrentPath (path.c_str ()); + + // Load the document + CIFile file; + if (file.open (filename)) + { + try + { + // Load the document in XML + CIXml xml; + xml.init (file); + + // Get root node + bool success = false; + xmlNodePtr rootNode = xml.getRootNode (); + if (rootNode) + { + // Good header ? + if (strcmp ((const char *)(rootNode->name), "NEL_WORLD_EDITOR_PROJECT") ==0) + { + // Read the version + int version = -1; + + // Read the parameters + xmlNodePtr node = CIXml::getFirstChildNode (rootNode, "VERSION"); + if (node) + { + string versionString; + if (CIXml::getContentString (versionString, node)) + version = atoi (versionString.c_str ()); + } + + if (version == -1) + { + // Error + theApp.syntaxError (filename, rootNode, "No version node"); + } + else + { + // Old format, serial it + if (version <= 1) + { + file.close (); + CIFile file2; + nlverify (file2.open (filename)); + CIXml xml2; + xml2.init (file2); + serial (xml2); + + // Done + success = true; + } + else + { + // Read it + if (version > WORLD_EDITOR_FILE_VERSION) + { + theApp.syntaxError (filename, node, "Unknown file version"); + } + else + { + // Read data directory + node = CIXml::getFirstChildNode (rootNode, "DATA_DIRECTORY"); + if (node) + { + CIXml::getPropertyString (_DataDir, node, "VALUE"); + } + + // Read data directory + node = CIXml::getFirstChildNode (rootNode, "CONTEXT"); + if (node) + { + CIXml::getPropertyString (_Context, node, "VALUE"); + } + + // Read the database element + node = CIXml::getFirstChildNode (rootNode, "DATABASE_ELEMENT"); + if (node) + { + do + { + // Get the type + string type; + if (theApp.getPropertyString (type, filename, node, "TYPE")) + { + // Read the filename + string filenameChild; + if (theApp.getPropertyString (filenameChild, filename, node, "FILENAME")) + { + // Is it a landscape ? + if (type == "landscape") + { + _DataHierarchy.push_back (CDatabaseElement (CDatabaseElement::Landscape)); + _DataHierarchy.recomputePointerArray (); + + // Get the primitives + xmlNodePtr primitives = CIXml::getFirstChildNode (node, "PRIMITIVES"); + if (primitives) + { + // Read it + _DataHierarchy.back ().Primitives.read (primitives, filename, theApp.Config); + + // Set the filename + _DataHierarchy.back ().Filename = filenameChild; + } + } + else + { + _DataHierarchy.push_back (CDatabaseElement (CDatabaseElement::Primitive)); + _DataHierarchy.recomputePointerArray (); + + // Set the filename + _DataHierarchy.back ().Filename = filenameChild; + } + + } + } + } + while (node = CIXml::getNextChildNode (node, "DATABASE_ELEMENT")); + } + + // Done + success = true; + } + } + } + } + else + { + // Error + theApp.syntaxError (filename, rootNode, "Unknown file header : %s", rootNode->name); + } + } + + if (!success) + { + result = false; + newDocument (); + } + else + { + // Last time + _LastModifedTime = NLMISC::CFile::getFileModificationDate (filename); + + // Load the files + uint i; + for (i=0; i<_DataHierarchy.size (); i++) + { + if (_DataHierarchy[i].Editable) + { + // Not modified + _DataHierarchy[i].Modified = false; + + getMainFrame()->launchLoadingDialog(toString("loading %s", _DataHierarchy[i].Filename.c_str()).c_str()); + getMainFrame()->progressLoadingDialog(float(i+0.0001f)/_DataHierarchy.size()); + // Landscape ? + if (_DataHierarchy[i].Type == CDatabaseElement::Landscape) + { + // Load the landscape + try + { + CIFile fileIn; + if (fileIn.open (_DataHierarchy[i].Filename)) + { + CIXml xml(true); + xml.init (fileIn); + _DataHierarchy[i].ZoneRegion.serial (xml); + + // Last time + _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); + } + else + { + if (!theApp.yesNoMessage ("Can't open file %s for reading. Continue reading ?", _DataHierarchy[i].Filename.c_str ())) + { + result = false; + } + } + } + catch (Exception& e) + { + theApp.errorMessage ("Error reading file %s : %s", _DataHierarchy[i].Filename.c_str (), e.what ()); + } + } + else + { + // Checks + nlassert (_DataHierarchy[i].Type == CDatabaseElement::Primitive); + + // Load the primitive + try + { + CIFile fileIn; + if (fileIn.open (_DataHierarchy[i].Filename)) + { + // Xml stream + CIXml xmlIn; + xmlIn.init (fileIn); + + // set the primitive context + CPrimitiveContext::instance().CurrentPrimitive = &_DataHierarchy[i].Primitives; + + // Read it + if (!_DataHierarchy[i].Primitives.read (xmlIn.getRootNode (), _DataHierarchy[i].Filename.c_str(), theApp.Config)) + { + theApp.errorMessage ("Error reading file %s", _DataHierarchy[i].Filename.c_str ()); + } + + // cleanup the primitive context + CPrimitiveContext::instance().CurrentPrimitive = NULL; + + // Last time + _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); + } + else + { + if (!theApp.yesNoMessage ("Can't open file %s for reading. Continue reading ?", _DataHierarchy[i].Filename.c_str ())) + { + result = false; + } + } + } + catch (Exception& e) + { + theApp.errorMessage ("Error reading file %s : %s", _DataHierarchy[i].Filename.c_str (), e.what ()); + } + } + + getMainFrame()->terminateLoadingDialog(); + /* // Not modified + _DataHierarchy[i].Modified = false;*/ + } + } + + // Init the landscape + CMainFrame *mainFrame = getMainFrame (); + if (mainFrame) + mainFrame->initLandscapeData (); + + // Reset document changes + clearModifications (); + } + } + catch (Exception &e) + { + theApp.errorMessage ("Error reading file %s : %s", filename, e.what ()); + + result = false; + } + } + else + { + theApp.errorMessage ("Can't open the file %s for reading.", filename); + + result = false; + } + + // Invalidate some stuff + invalidateLeftView (); + getMainFrame ()->invalidateTools (); + + // Invalidate pointers + InvalidateAllPrimitives (); + VerifyPrimitivesStructures(); + + // Restaure current path + CPath::setCurrentPath (backupPath.c_str ()); + + // Initialize default values + for (uint j=0; j<_DataHierarchy.size(); ++j) + { + if (_DataHierarchy[j].Type == CDatabaseElement::Primitive) + { + updateDefaultValues (j); + } + } + + // Check property types + for (uint j=0; j<_DataHierarchy.size(); ++j) + { + if (_DataHierarchy[j].Type == CDatabaseElement::Primitive) + { + updateDefaultValues (j); + } + } + + // Warn the plugins + uint i; + for (i=0; iprimitiveChanged(_DataHierarchy[j].Primitives.RootNode); + } + } + } + + + return result; +} + +// *************************************************************************** + +BOOL CWorldEditorDoc::OnSaveDocument(LPCTSTR lpszPathName) +{ + BOOL result = TRUE; + + // Get path name + string path = NLMISC::CFile::getPath (lpszPathName); + + // Backup current path + string backupPath = CPath::getCurrentPath (); + + // Set current path + CPath::setCurrentPath (path.c_str ()); + + // Timer enabled ? + getMainFrame ()->TimerEnabled = false; + + // Save land files + for (uint i=0; i<_DataHierarchy.size (); i++) + { + if (_DataHierarchy[i].Editable) + { + // Make path relative + string relativeFileName = _DataHierarchy[i].Filename; + CPath::makePathRelative (NLMISC::CFile::getPath (lpszPathName).c_str (), relativeFileName); + if (relativeFileName != _DataHierarchy[i].Filename) + { + _DataHierarchy[i].Filename = relativeFileName; + modifyProject (); + } + + // Modified + if (_DataHierarchy[i].Modified) + { + // Landscape ? + if (_DataHierarchy[i].Type == CDatabaseElement::Landscape) + { + // Save the landscape + try + { + // Got a filename ? + if (_DataHierarchy[i].Filename.empty ()) + { + CFileDialogEx dialog (BASE_REGISTRY_KEY, "land", FALSE, "land", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "NeL Ligo Landscape Files (*.land)|*.land|All Files (*.*)|*.*||", getMainFrame ()); + if (dialog.DoModal() == IDOK) + { + _DataHierarchy[i].Filename = dialog.GetPathName(); + } + else + { + continue; + } + } + + // Open the primitive file for writing + COFile fileOut; + if (fileOut.open (_DataHierarchy[i].Filename, false, false, true)) + { + // Be careful with the flushing of the COXml object + { + COXml xmlOut; + xmlOut.init (&fileOut); + _DataHierarchy[i].ZoneRegion.serial (xmlOut); + + // Done + _DataHierarchy[i].Modified = false; + } + + fileOut.close(); + } + else + { + if (!theApp.yesNoMessage ("Can't open file %s for writing. Continue saving ?", _DataHierarchy[i].Filename.c_str ())) + { + result = FALSE; + } + } + + _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); + } + catch (Exception& e) + { + theApp.errorMessage ("Error writing file %s : %s", _DataHierarchy[i].Filename.c_str (), e.what ()); + } + } + else + { + // Checks + nlassert (_DataHierarchy[i].Type == CDatabaseElement::Primitive); + + // Save the primitive + try + { + // Got a filename ? + if (_DataHierarchy[i].Filename.empty ()) + { + CFileDialogEx dialog (BASE_REGISTRY_KEY, "primitive", FALSE, "primitive", NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, "NeL Ligo Primitive Files (*.primitive)|*.primitive|All Files (*.*)|*.*||", getMainFrame ()); + if (dialog.DoModal() == IDOK) + { + string pathFromDialog = dialog.GetPathName(); + + // Remove uppercase in filename + string::size_type pos = pathFromDialog.rfind ("\\", 0); + for (uint j=pos+1 ; jinvalidateTools (); + } + else + { + continue; + } + } + + // Open the primitive file for writing + COFile fileOut; + if (fileOut.open (_DataHierarchy[i].Filename, false, false, true)) + { + COXml xmlOut; + xmlOut.init (&fileOut); + + // Write the document + _DataHierarchy[i].Primitives.write (xmlOut.getDocument (), _DataHierarchy[i].Filename.c_str ()); + + // Flush it + xmlOut.flush (); + + // Done + _DataHierarchy[i].Modified = false; + + // Invalidate tools + getMainFrame ()->invalidateToolsParam (); + + // Last time + fileOut.close (); + } + else + { + if (!theApp.yesNoMessage ("Can't open file %s for writing. Continue saving ?", _DataHierarchy[i].Filename.c_str ())) + { + result = FALSE; + } + } + + _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); + } + catch (Exception& e) + { + theApp.errorMessage ("Error writing file %s : %s", _DataHierarchy[i].Filename.c_str (), e.what ()); + } + } + + // Invalidate title + CDatabaseLocatorPointer locator; + locator.getRoot (i); + InvalidatePrimitive (locator, LogicTreeParam); + } + } + } + + // Document modified ? + if (_Modified) + { + // Save the document + COFile file; + if (file.open (lpszPathName, false, false, true)) + { + try + { + { + // Save the document in XML + COXml xml; + xml.init (&file); + + // Create the document + xmlNodePtr rootNode = xmlNewDocNode (xml.getDocument (), NULL, (const xmlChar*)"NEL_WORLD_EDITOR_PROJECT", NULL); + xmlDocSetRootElement (xml.getDocument (), rootNode); + + // Version + xmlNodePtr node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"VERSION", NULL); + xmlNodePtr text = xmlNewText ((const xmlChar *)toString (WORLD_EDITOR_FILE_VERSION).c_str ()); + xmlAddChild (node, text); + + // DATA_DIRECTORY + node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"DATA_DIRECTORY", NULL); + xmlSetProp (node, (const xmlChar*)"VALUE", (const xmlChar*)_DataDir.c_str ()); + + // DATA_DIRECTORY + node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"CONTEXT", NULL); + xmlSetProp (node, (const xmlChar*)"VALUE", (const xmlChar*)_Context.c_str ()); + + // Database + for (uint i=0; i<_DataHierarchy.size (); i++) + { + if (_DataHierarchy[i].Editable) + { + // New element + node = xmlNewChild ( rootNode, NULL, (const xmlChar*)"DATABASE_ELEMENT", NULL); + xmlSetProp (node, (const xmlChar*)"FILENAME", (const xmlChar*)_DataHierarchy[i].Filename.c_str ()); + + // Type + bool landscape = isLandscape (i); + xmlSetProp (node, (const xmlChar*)"TYPE", (const xmlChar*)(landscape?"landscape":"primitive")); + + // Write properties ? + if (landscape) + { + node = xmlNewChild ( node, NULL, (const xmlChar*)"PRIMITIVES", NULL); + _DataHierarchy[i].Primitives.write (node, lpszPathName); + } + } + } + + // Not modified + _Modified = false; + } + + // Last time + file.close (); + } + catch (Exception &e) + { + theApp.errorMessage ("Error writing file %s : %s", lpszPathName, e.what ()); + + result = FALSE; + } + } + else + { + result = FALSE; + } + + _LastModifedTime = NLMISC::CFile::getFileModificationDate (lpszPathName); + } + + // No modification is for this level of undo + _LastSaveUndo = _Undo; + _NoModificationUndo = false; + + updateModifiedState (); + + // Timer enabled + getMainFrame ()->TimerEnabled = true; + + // Restaure current path + CPath::setCurrentPath (backupPath.c_str ()); + + return result; +} + +// *************************************************************************** + +void CWorldEditorDoc::serial (NLMISC::IStream &s) +{ + s.xmlPush ("NEL_WORLD_EDITOR_PROJECT"); + + // Serial + int version = s.serialVersion (2); + + s.xmlSerial (_DataDir, "DATA_DIRECTORY"); + + if (version>0) + { + s.xmlSerial (_Context, "CONTEXT"); + } + + // Old structures + vector landscapes; + vector primitives; + + s.xmlPush ("LANDSCAPE"); + s.serialCont (landscapes); + s.xmlPop (); + + s.xmlPush ("PRIMITIVES"); + s.serialCont (primitives); + s.xmlPop (); + + // * Convert in new structures + + // Resvere + // _DataHierarchy.reserve (landscapes.size () + primitives.size ()); + + // Copy landscapes + uint i; + for (i=0; i=2) && (title[title.size()-1] == '*') && (title[title.size()-2] == ' ') ) + { + title.resize (title.size () - 2); + SetTitle (title.c_str()); + } + } +} + +// *************************************************************************** + +void CWorldEditorDoc::noUndoModification () +{ + _NoModificationUndo = true; + + updateModifiedState (); +} + +// *************************************************************************** + +void CWorldEditorDoc::undo () +{ + // Should not be in modification mode + nlassertex (_ModificationMode == false, ("In modification mode !")); + + if (_Undo > 0) + { + _Undo--; + + // Undo actions + for (uint i=0; i<_Actions[_Undo].size (); i++) + _Actions[_Undo][_Actions[_Undo].size ()-i-1]->undo (); + + updateModifiedState (); + } +} + +// *************************************************************************** + +void CWorldEditorDoc::redo () +{ + // Should not be in modification mode + nlassertex (_ModificationMode == false, ("In modification mode !")); + + if (_Undo < _Actions.size ()) + { + // Undo actions + for (uint i=0; i<_Actions[_Undo].size (); i++) + _Actions[_Undo][i]->redo (); + + _Undo++; + + updateModifiedState (); + } +} + +// *************************************************************************** + +void CWorldEditorDoc::clearModifications () +{ + for (uint i=0; i<_Actions.size (); i++) + for (uint j=0; j<_Actions[i].size (); j++) + { + delete _Actions[i][j]; + } + + _Actions.clear (); + _NoModificationUndo = false; + _Undo = 0; + _LastSaveUndo = 0; + _Modified = false; +} + +// *************************************************************************** + +const string &CWorldEditorDoc::getDataDir () const +{ + return _DataDir; +} + +// *************************************************************************** + + +void CWorldEditorDoc::getFilePath(uint primIndex,string & relativeFileName) +{ + relativeFileName=_DataHierarchy[primIndex].Filename; + CPath::makePathRelative ((NLMISC::CFile::getPath ((LPCTSTR)CWorldEditorDoc::GetPathName())).c_str(), relativeFileName); +} + +// *************************************************************************** + +void CWorldEditorDoc::setDataDir (const char *dir) +{ + _DataDir = dir; + + modifyProject (); + + noUndoModification (); +} + +// *************************************************************************** + +const string& CWorldEditorDoc::getPathOfSelectedPrimitive() const +{ + return _PathOfSelectedPrimitive; +} + +// *************************************************************************** + +void CWorldEditorDoc::setPathOfSelectedPrimitive(const std::string& s) +{ + _PathOfSelectedPrimitive = s; +} + +// *************************************************************************** + +bool CWorldEditorDoc::getZoneAmongRegions (CDatabaseLocator &locator, class CBuilderZoneRegion*& pBZRfrom, sint32 x, sint32 y) +{ + uint32 nNbRegion = _DataHierarchy.size (); + int regionId = -1; + for (uint32 i = 0; i < nNbRegion; ++i) + { + // Landscape ? + if (_DataHierarchy[i].Type == CDatabaseElement::Landscape) + { + regionId++; + const NLLIGO::CZoneRegion ®ion = getZoneRegionAbsolute (i); + if ((x < region.getMinX ())||(x > region.getMaxX ())||(y < region.getMinY ())||(y > region.getMaxY ())) + continue; + if (region.getName (x, y) != STRING_UNUSED) + { + pBZRfrom = getMainFrame ()->_ZoneBuilder->_ZoneRegions[regionId]; + locator = CDatabaseLocator (regionId, x, y); + return true; + } + } + } + + // The zone is not present in other region so it is an empty or oob zone of the current region + const NLLIGO::CZoneRegion ®ion = getZoneRegion(pBZRfrom->RegionId); + if ((x < region.getMinX ())||(x > region.getMaxX ())||(y < region.getMinY ())||(y > region.getMaxY ())) + return false; // Out Of Bound + + locator = CDatabaseLocator (pBZRfrom->RegionId, x, y); + + return true; +} + +// *************************************************************************** + +const NLLIGO::CZoneRegion &CWorldEditorDoc::getZoneRegion (uint landscape) const +{ + uint index = regionIDToDatabaseElementID (landscape); + return _DataHierarchy[index].ZoneRegion; +} + +// *************************************************************************** + +uint CWorldEditorDoc::regionIDToDatabaseElementID (uint landscape) const +{ + uint32 nNbRegion = _DataHierarchy.size (); + uint32 i; + for (i = 0; i < nNbRegion; ++i) + { + // Landscape ? + if (_DataHierarchy[i].Type == CDatabaseElement::Landscape) + { + if (landscape == 0) + return i; + landscape --; + } + } + // Should be found + nlstop; + return i; +} + +// *************************************************************************** + +const NLLIGO::CZoneRegion &CWorldEditorDoc::getZoneRegionAbsolute (uint landscape) const +{ + nlassert (isLandscape (landscape)); + return _DataHierarchy[landscape].ZoneRegion; +} + +// *************************************************************************** + +bool CWorldEditorDoc::addModification (class IAction *action) +{ + // Should be in modification mode + nlassertex (_ModificationMode == true, ("Not in modification mode !")); + + // Push first the action + uint actionId = _CurrentAction.size (); + _CurrentAction.push_back (action); + + // Do the action + if (!action->redo ()) + { + // Delete all new actions + nlassert (_CurrentAction.size ()>0); + for (uint a=_CurrentAction.size ()-1; a>actionId; a--) + { + // Undo + _CurrentAction[a]->undo (); + delete _CurrentAction[a]; + } + delete action; + _CurrentAction.pop_back (); + + return false; + } + + + return true; +} + +// *************************************************************************** + +void CWorldEditorDoc::getLigoData (CLigoData &data, const CDatabaseLocator &locator) +{ + NLLIGO::CZoneRegion ®ion = _DataHierarchy[locator.getDatabaseIndex ()].ZoneRegion; + nlassert ((locator.XSubPrim >= region.getMinX ()) && (locator.XSubPrim <= region.getMaxX ()) && (locator.Y >= region.getMinY ()) && (locator.Y <= region.getMaxY ())); + + data.PosX = region.getPosX (locator.XSubPrim, locator.Y); + data.PosY = region.getPosY (locator.XSubPrim, locator.Y); + data.ZoneName = region.getName (locator.XSubPrim, locator.Y); + data.Rot = region.getRot (locator.XSubPrim, locator.Y); + data.Flip = region.getFlip (locator.XSubPrim, locator.Y); + data.SharingMatNames[0] = region.getSharingMatNames (locator.XSubPrim, locator.Y, 0); + data.SharingMatNames[1] = region.getSharingMatNames (locator.XSubPrim, locator.Y, 1); + data.SharingMatNames[2] = region.getSharingMatNames (locator.XSubPrim, locator.Y, 2); + data.SharingMatNames[3] = region.getSharingMatNames (locator.XSubPrim, locator.Y, 3); + data.SharingCutEdges[0] = region.getSharingCutEdges (locator.XSubPrim, locator.Y, 0); + data.SharingCutEdges[1] = region.getSharingCutEdges (locator.XSubPrim, locator.Y, 1); + data.SharingCutEdges[2] = region.getSharingCutEdges (locator.XSubPrim, locator.Y, 2); + data.SharingCutEdges[3] = region.getSharingCutEdges (locator.XSubPrim, locator.Y, 3); +} + +// *************************************************************************** + +void CWorldEditorDoc::CLandscapeDeprecated::serial (NLMISC::IStream &s) +{ + s.serialVersion (0); + s.serial (Filename); +} + +// *************************************************************************** + +void CWorldEditorDoc::CPrimitiveDeprecated::serial (NLMISC::IStream &s) +{ + s.serialVersion (0); + s.serial (Filename); +} + +// *************************************************************************** + +CWorldEditorDoc::CDatabaseElement::CDatabaseElement () +{ + Type = Undefined; + Editable = true; + Modified = false; +} + +// *************************************************************************** + +CWorldEditorDoc::CDatabaseElement::CDatabaseElement (TType type) +{ + Type = type; + if (Type == Landscape) + Primitives.RootNode->addPropertyByName ("class", new CPropertyString ("landscape")); + Editable = true; + Modified = false; +} + +// *************************************************************************** + +void CWorldEditorDoc::beginModification () +{ + nlassertex (_ModificationMode == false, ("Already in modification mode !")); + _ModificationMode = true; + + // Erase current action + _CurrentAction.clear (); +} + +// *************************************************************************** + +void CWorldEditorDoc::endModification () +{ + nlassertex (_ModificationMode == true, ("Not in modification mode !")); + _ModificationMode = false; + + // Add a undo entry if some actions have been performed + if (!_CurrentAction.empty ()) + { + // Remove next actions + for (uint i=_Undo; i<_Actions.size (); i++) + for (uint j=0; j<_Actions[i].size (); j++) + { + delete _Actions[i][j]; + } + + // Place the current action + _Actions.resize (_Undo+1); + _Actions[_Undo] = _CurrentAction; + + // Invalidate save position + if (_Undo < _LastSaveUndo) + _LastSaveUndo = -1; + + _Undo++; + + updateModifiedState (); + + // check if we need to send an update to the plugins + bool needUpdate = false; + std::vector::iterator first(_CurrentAction.begin()), last(_CurrentAction.end()); + for (; first != last; ++first) + { + needUpdate |= (*first)->isAffectingContent(); + } + if (needUpdate) + { + for (uint i=0; iprimitiveChanged(_DataHierarchy[j].Primitives.RootNode); + } + } + } + } +} + +// *************************************************************************** + +uint CWorldEditorDoc::getNumDatabaseElement () const +{ + return _DataHierarchy.size (); +} + +// *************************************************************************** + +const std::string &CWorldEditorDoc::getDatabaseElement (uint primitive) const +{ + return _DataHierarchy[primitive].Filename; +} + +// *************************************************************************** + +const NLLIGO::CPrimitives &CWorldEditorDoc::getDatabaseElements (uint primitive) const +{ + return _DataHierarchy[primitive].Primitives; +} + +// *************************************************************************** + +void CWorldEditorDoc::getLocator (CDatabaseLocatorPointer &locator, const IPrimitive *primitive) const +{ + static std::vector cache; + cache.clear (); + + // Get the first + const IPrimitive *current = primitive; + const IPrimitive *parent = current->getParent (); + while (parent) + { + // Get the child id + uint childId; + nlverify (parent->getChildId (childId, current)); + cache.push_back (childId); + current = parent; + parent = current->getParent (); + } + + // Root node + uint i; + CWorldEditorDoc *doc = getDocument (); + uint count = doc->getNumDatabaseElement (); + for (i=0; igetDatabaseElements (i).RootNode == current) + { + break; + } + } + + nlassert (i0); + + // Copy the stack + locatorDest._LocateStack = locator._LocateStack; + + // Get the first primitive + locatorDest.Primitive = _DataHierarchy[locator._LocateStack[0]].Primitives.RootNode; + + // Get into the stack + uint stackSize = locator._LocateStack.size (); + for (uint i=1; igetChild (locatorDest.Primitive, locator._LocateStack[i])); + } +} + +// *************************************************************************** + +void CWorldEditorDoc::getFirstLocator (CDatabaseLocatorPointer &locator) const +{ + // Set as end + locator._LocateStack[0] = 0xffffffff; + locator.Primitive = NULL; + + // Is a first primitive ? + if (_DataHierarchy.size ()) + { + locator._LocateStack[0] = 0; + } +} + +// *************************************************************************** + +void CWorldEditorDoc::deletePrimitive (const CDatabaseLocator &locator) +{ + // Locate it + CDatabaseLocatorPointer locatorDest; + getLocator (locatorDest, locator); + + // Get the parent + IPrimitive *parent = const_cast(locatorDest.Primitive)->getParent (); + nlassert (parent); + + // Get the child id + uint childId; + nlverify (parent->getChildId (childId, locatorDest.Primitive)); + + // Delete the child + nlverify (parent->removeChild (childId)); +} + +// *************************************************************************** + +void CWorldEditorDoc::insertPrimitive (const CDatabaseLocator &locator, IPrimitive *primitive) +{ + nlassert (locator._LocateStack.size ()>0); + + // Get the first primitive + IPrimitive *prim = _DataHierarchy[locator._LocateStack[0]].Primitives.RootNode; + + // Get into the stack + uint stackSize = locator._LocateStack.size (); + uint i; + for (i=1; igetChild (prim, locator._LocateStack[i])); + } + + // Set the context + CPrimitiveContext::instance().CurrentPrimitive = &_DataHierarchy[locator._LocateStack[0]].Primitives; + + // Insert the primitive in the parent + nlverify (prim->insertChild (primitive, locator._LocateStack[i])); + + // unset the context + CPrimitiveContext::instance().CurrentPrimitive = NULL; +} + +// *************************************************************************** + +uint32 getUniqueId () +{ + // Wait 1 ms + sint64 time = NLMISC::CTime::getLocalTime (); + sint64 time2; + while ((time2 = NLMISC::CTime::getLocalTime ()) == time) + { + } + + return (uint32)time2; +} + +// *************************************************************************** + +void CWorldEditorDoc::initPrimitiveParameters (const CPrimitiveClass &primClass, IPrimitive &primitive, + const std::vector &initParameters) +{ + // Other parameters + for (uint p=0; p 1) + theApp.errorMessage ("Warning: parameter (%s) in class name (%s) has more than 1 default value (%d).", + parameter.Name.c_str (), primClass.Name.c_str (), parameter.DefaultValue.size ()); + + if ( + (cpStringArray.resize (parameter.DefaultValue.size ()); + for (i=0; iStringArray[i] = toString (getUniqueId ()); + } + else + { + str->StringArray[i] = ""; + } + } + primitive.addPropertyByName (parameter.Name.c_str (), str); + } + break; + } + } + } + } + else + { + // Some feedback + theApp.errorMessage ("Warning: parameter (%s) doesn't exist in class (%s).", + initParameters[p].Name.c_str (), primClass.Name.c_str ()); + } + } +} + +// *************************************************************************** + +const NLLIGO::IPrimitive *CWorldEditorDoc::createPrimitive (const CDatabaseLocator &locator, const char *className, const char *primName, + const CVector &initPos, float deltaPos, + const std::vector &initParameters) +{ + // Get the prim class + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (className); + if (primClass) + { + // Create the base primitive + IPrimitive *primitive = NULL; + switch (primClass->Type) + { + case CPrimitiveClass::Node: + primitive = new CPrimNodeEditor; + break; + case CPrimitiveClass::Point: + { + CPrimPointEditor *point = new CPrimPointEditor; + primitive = point; + point->Point.CVector::operator= (initPos); + } + break; + case CPrimitiveClass::Path: + primitive = new CPrimPathEditor; + break; + case CPrimitiveClass::Zone: + primitive = new CPrimZoneEditor; + break; + case CPrimitiveClass::Alias: + primitive = new CPrimAliasEditor; + break; + case CPrimitiveClass::Bitmap: + primitive = new CPrimBitmap; + break; + } + nlassert (primitive); + + // Add properties + primitive->addPropertyByName ("class", new CPropertyString (className)); + primitive->addPropertyByName ("name", new CPropertyString (primName, primName[0] == 0)); + + // Init with default parameters + std::vector tempParam; + tempParam.reserve (primClass->Parameters.size ()); + for (uint i=0; iParameters.size (); i++) + tempParam.push_back (primClass->Parameters[i]); + initPrimitiveParameters (*primClass, *primitive, tempParam); + + // Init with option parameters + initPrimitiveParameters (*primClass, *primitive, initParameters); + + // Insert the primitive + insertPrimitive (locator, primitive); + + // The new pos + CVector newPos = initPos; + newPos.x += deltaPos; + + // Create static children + uint c; + for (c=0; cStaticChildren.size (); c++) + { + // The child ref + const CPrimitiveClass::CChild &child = primClass->StaticChildren[c]; + + // The new locator + CDatabaseLocator childLocator = locator; + childLocator._LocateStack.push_back (0); + + // Create the child + const NLLIGO::IPrimitive *childPrim = createPrimitive (childLocator, child.ClassName.c_str (), + child.Name.c_str (), newPos, deltaPos, primClass->StaticChildren[c].Parameters); + + // The new pos + newPos.y += deltaPos; + } + + // Canceled ? + if (cStaticChildren.size ()) + { + deletePrimitive (locator); + return NULL; + } + + // Prim file ? + if (primClass->Type == CPrimitiveClass::Bitmap) + { + // Create a dialog file + CFileDialogEx dialog (BASE_REGISTRY_KEY, "image", TRUE, primClass->FileExtension.c_str (), NULL, OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, + (primClass->FileType+" (*."+primClass->FileExtension+")|*."+primClass->FileExtension+"|All Files (*.*)|*.*||").c_str (), getMainFrame ()); + if (dialog.DoModal() == IDOK) + { + // Save filename + static_cast(primitive)->init (dialog.GetPathName ()); + } + } + + // Continue ? + if (primitive) + { + // Auto init ? + if (!primClass->AutoInit) + { + // Make a vector of locator + CDatabaseLocatorPointer locatorPtr; + getLocator (locatorPtr, locator); + std::list locators; + locators.push_back (const_cast (locatorPtr.Primitive)); + + // Yes, go + CDialogProperties dialogProperty (locators, getMainFrame ()); + dialogProperty.DoModal (); + } + + // Eval the default name property + string name; + if (!primitive->getPropertyByName ("name", name) || name.empty()) + { + const CPrimitiveClass *primClass = theApp.Config.getPrimitiveClass (*primitive); + if (primClass) + { + uint i; + for (i=0; iParameters.size(); i++) + { + if (primClass->Parameters[i].Name == "name") + { + std::string result; + primClass->Parameters[i].getDefaultValue (result, *primitive, *primClass, NULL); + if (!result.empty()) + { + primitive->removePropertyByName ("name"); + primitive->addPropertyByName ("name", new CPropertyString (result.c_str(), true)); + } + } + } + } + } + + // Init primitive default values + primitive->initDefaultValues (theApp.Config); + } + + // Done + return primitive; + } + else + { + theApp.errorMessage ("Unknown primitive class name : %s", className); + } + return NULL; +} + +// *************************************************************************** + +void CWorldEditorDoc::getPrimitiveDisplayName (std::string &result, uint primitive) const +{ + // Return a formated string + result = formatString (NLMISC::CFile::getFilename (getDatabaseElement (primitive)).c_str ()); + if (result.empty ()) + result = "Untitled"; + if (_DataHierarchy[primitive].Modified && _DataHierarchy[primitive].Editable) + result += " *"; +} + + +// *************************************************************************** + +void CWorldEditorDoc::modifyDatabase (uint dbIndex) +{ + if (_DataHierarchy[dbIndex].Editable) + { + _DataHierarchy[dbIndex].Modified = true; + if (isLandscape (dbIndex)) + modifyProject (); + } + + // Invalidate title + CDatabaseLocatorPointer locator; + locator.getRoot (dbIndex); + InvalidatePrimitive (locator, LogicTreeParam); + + // plugin callback +// for (uint i=0; iprimitiveChanged(locator.Primitive); +} + +// *************************************************************************** + +void CWorldEditorDoc::modifyProject () +{ + _Modified = true; +} + +// *************************************************************************** + +void CWorldEditorDoc::updateFiles () +{ + // Landscape + uint i; + for (i=0; i<_DataHierarchy.size (); i++) + { + // Check date + if (!checkFileDate (_DataHierarchy[i].Filename.c_str (), _DataHierarchy[i].LastModifedTime)) + { + // Ask for reloading + if (theApp.yesNoMessage ("The file \"%s\" has been modified.\nReload it ?", _DataHierarchy[i].Filename.c_str ())) + { + // Clear modification + clearModifications (); + + // Landscape ? + if (_DataHierarchy[i].Type == CDatabaseElement::Landscape) + { + try + { + CIFile fileIn; + if (fileIn.open (_DataHierarchy[i].Filename)) + { + CIXml xml(true); + xml.init (fileIn); + _DataHierarchy[i].ZoneRegion.serial (xml); + } + else + { + theApp.errorMessage ("Can't open file %s for reading.", _DataHierarchy[i].Filename.c_str ()); + } + + // Last time + _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); + } + catch (Exception& e) + { + theApp.errorMessage ("Error reading file %s : %s", _DataHierarchy[i].Filename.c_str (), e.what ()); + } + } + else + { + try + { + CIFile fileIn; + if (fileIn.open (_DataHierarchy[i].Filename)) + { + // Xml stream + CIXml xmlIn; + xmlIn.init (fileIn); + + // Read it + CPrimitiveContext::instance().CurrentPrimitive = &(_DataHierarchy[i].Primitives); + if (!_DataHierarchy[i].Primitives.read (xmlIn.getRootNode (), _DataHierarchy[i].Filename.c_str(), theApp.Config)) + { + theApp.errorMessage ("Error reading file %s", _DataHierarchy[i].Filename.c_str ()); + CPrimitiveContext::instance().CurrentPrimitive = NULL; + } + CPrimitiveContext::instance().CurrentPrimitive = NULL; + + // Last time + _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); + + InvalidateAllPrimitives(); + + } + else + { + theApp.errorMessage ("Can't open file %s for reading.", _DataHierarchy[i].Filename.c_str ()); + } + } + catch (Exception& e) + { + theApp.errorMessage ("Error reading file %s : %s", _DataHierarchy[i].Filename.c_str (), e.what ()); + } + } + + // Invalidate views + invalidateLeftView (); + } + else + { + // Get the new date + _DataHierarchy[i].LastModifedTime = NLMISC::CFile::getFileModificationDate (_DataHierarchy[i].Filename); + } + } + } + + // Check date + if (!checkFileDate (GetPathName (), _LastModifedTime)) + { + // Ask for reloading + if (theApp.yesNoMessage ("The file \"%s\" has been modified.\nReload it ?", (const char*)GetPathName ())) + { + newDocument (); + loadDocument (GetPathName ()); + } + else + { + // Get the new date + _LastModifedTime = NLMISC::CFile::getFileModificationDate ((const char*)GetPathName ()); + } + } +} + +// *************************************************************************** + +bool CWorldEditorDoc::checkFileDate (const char *filename, uint32 date) +{ + // File exist ? + if (!NLMISC::CFile::fileExists (filename)) + return true; + + // Check each file in the project + return NLMISC::CFile::getFileModificationDate (filename) == date; +} + +// *************************************************************************** + +bool CWorldEditorDoc::undoAvailable () const +{ + return _Undo > 0; +} + +// *************************************************************************** + +bool CWorldEditorDoc::redoAvailable () const +{ + return _Undo < _Actions.size (); +} + +// *************************************************************************** + +bool CWorldEditorDoc::isPrimitiveLoaded(const std::string &primPath) +{ + uint i = 0, count = getNumDatabaseElement(); + string curPath; + + while (i < count) + { + getFilePath(i, curPath); + if (primPath == curPath) + break; + else + i++; + } + + if (i < count) + return true; + else + return false; +} + +// *************************************************************************** + +bool CWorldEditorDoc::isLandscape (uint dbIndex) const +{ + return _DataHierarchy[dbIndex].Type == CDatabaseElement::Landscape; +} + +// *************************************************************************** + +bool CWorldEditorDoc::isPrimitive (uint dbIndex) const +{ + return _DataHierarchy[dbIndex].Type == CDatabaseElement::Primitive; +} + +// *************************************************************************** + +bool CWorldEditorDoc::isEditable (uint dbIndex) const +{ + return _DataHierarchy[dbIndex].Editable; +} + +// *************************************************************************** + +void CWorldEditorDoc::resetUniqueID (const NLLIGO::IPrimitive &primitive, bool onlyZero) +{ + // Got a primitive class ? + const CPrimitiveClass *_class = theApp.Config.getPrimitiveClass (primitive); + if (_class) + { + // For each parameters + uint i; + for (i=0; i<_class->Parameters.size (); i++) + { + // String or string array ? + if (_class->Parameters[i].Type == CPrimitiveClass::CParameter::String) + { + // Default value available ? + if (!_class->Parameters[i].DefaultValue.empty ()) + { + // Unique Id ? + if (_class->Parameters[i].DefaultValue[0].GenID) + { + string propVal; + primitive.getPropertyByName(_class->Parameters[i].Name.c_str(), propVal); + if (!onlyZero || propVal.empty() || propVal == "0") + { + // Remove it + CDatabaseLocatorPointer locator; + getLocator (locator, &primitive); + + addModification (new CActionSetPrimitivePropertyString (locator, _class->Parameters[i].Name.c_str (), toString (getUniqueId ()).c_str (), false)); + } + } + } + } + else if (_class->Parameters[i].Type == CPrimitiveClass::CParameter::StringArray) + { + uint j; + for (j=0; j<_class->Parameters[i].DefaultValue.size (); j++) + { + // Unique Id ? + if (_class->Parameters[i].DefaultValue[j].GenID) + { + string propVal; + primitive.getPropertyByName(_class->Parameters[j].Name.c_str(), propVal); + if (!onlyZero || propVal.empty() || propVal == "0") + { + // The doesn't exist ? + std::vector result; + std::vector *resultPtr = NULL; + primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), resultPtr); + + // Copy + if (resultPtr) + result = *resultPtr; + + // Resize + if (result.size ()<=j) + result.resize (j+1); + + // Set the value + result[j] = toString (getUniqueId ()); + + CDatabaseLocatorPointer locator; + getLocator (locator, &primitive); + addModification (new CActionSetPrimitivePropertyStringArray (locator, _class->Parameters[i].Name.c_str (), result, false)); + } + } + } + } + } + } + + // Recurcive call + uint i; + const uint count = primitive.getNumChildren (); + for (i=0; i &ids, std::vector &nonUnique) +{ + // Got a primitive class ? + const CPrimitiveClass *_class = theApp.Config.getPrimitiveClass (primitive); + if (_class) + { + // For each parameters + uint i; + for (i=0; i<_class->Parameters.size (); i++) + { + // String or string array ? + if (_class->Parameters[i].Type == CPrimitiveClass::CParameter::String) + { + // Default value available ? + if (!_class->Parameters[i].DefaultValue.empty ()) + { + // Unique Id ? + if (_class->Parameters[i].DefaultValue[0].GenID) + { + string propVal; + primitive.getPropertyByName(_class->Parameters[i].Name.c_str(), propVal); + if (ids.find(propVal) != ids.end()) + { + // store it in the list of non unique id + TPropertyNonUnique nu; + nu.Primitive = &primitive; + nu.PropertyName = _class->Parameters[i].Name; + + nonUnique.push_back(nu); +// // regenerate it +// CDatabaseLocatorPointer locator; +// getLocator (locator, &primitive); +// +// addModification (new CActionSetPrimitivePropertyString (locator, _class->Parameters[i].Name.c_str (), toString (getUniqueId ()).c_str (), false)); +// +// regenCount++; + } + primitive.getPropertyByName(_class->Parameters[i].Name.c_str(), propVal); + ids.insert(propVal); + } + } + } + else if (_class->Parameters[i].Type == CPrimitiveClass::CParameter::StringArray) + { + uint j; + for (j=0; j<_class->Parameters[i].DefaultValue.size (); j++) + { + // Unique Id ? + if (_class->Parameters[i].DefaultValue[j].GenID) + { + string propVal; + primitive.getPropertyByName(_class->Parameters[j].Name.c_str(), propVal); + if (ids.find(propVal) != ids.end()) + { + // store it in the list of non unique id + TPropertyNonUnique nu; + nu.Primitive = &primitive; + nu.PropertyName = _class->Parameters[j].Name; + + nonUnique.push_back(nu); +// // The doesn't exist ? +// std::vector result; +// std::vector *resultPtr = NULL; +// primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), resultPtr); +// +// // Copy +// if (resultPtr) +// result = *resultPtr; +// +// // Resize +// if (result.size ()<=j) +// result.resize (j+1); +// +// // Set the value +// result[j] = toString (getUniqueId ()); +// +// CDatabaseLocatorPointer locator; +// getLocator (locator, &primitive); +// addModification (new CActionSetPrimitivePropertyStringArray (locator, _class->Parameters[i].Name.c_str (), result, false)); +// +// regenCount++; + } + primitive.getPropertyByName(_class->Parameters[j].Name.c_str(), propVal); + ids.insert(propVal); + } + } + } + } + } + + // Recursive call + uint i; + const uint count = primitive.getNumChildren (); + for (i=0; iParameters.size (); i++) + { + // First check the primitive property has to good type + IProperty *prop; + if (primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), prop)) + { + // String to array ? + CPropertyString *propString = dynamic_cast (prop);; + const bool classStringArray = _class->Parameters[i].Type == CPrimitiveClass::CParameter::StringArray || + _class->Parameters[i].Type == CPrimitiveClass::CParameter::ConstStringArray; + if (propString && classStringArray) + { + // Build an array string + vector array; + if (!propString->String.empty()) + array.push_back (propString->String); + prop = new CPropertyStringArray (array); + primitive.removePropertyByName (_class->Parameters[i].Name.c_str ()); + primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), prop); + modified = true; + } + + // Array to string ? + CPropertyStringArray *propStringArray = dynamic_cast (prop); + if (propStringArray && !classStringArray) + { + // Build an array string + string str; + if (!propStringArray->StringArray.empty()) + str = propStringArray->StringArray[0]; + prop = new CPropertyString (str); + primitive.removePropertyByName (_class->Parameters[i].Name.c_str ()); + primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), prop); + modified = true; + } + } + + // String or string array ? + if (_class->Parameters[i].Type == CPrimitiveClass::CParameter::String) + { + // Default value available ? + if (!_class->Parameters[i].DefaultValue.empty ()) + { + // Unique Id ? + if (_class->Parameters[i].DefaultValue[0].GenID) + { + // The doesn't exist ? + string result; + if (!primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), result)) + { + // Add it ! + primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), new CPropertyString (toString (getUniqueId ()).c_str ())); + modified = true; + } + } + // Hidden ? + else if (!_class->Parameters[i].Visible) + { + // The doesn't exist ? + string result; + if (!primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), result)) + { + // Add it ! + primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), new CPropertyString ("")); + modified = true; + } + } + } + } + else if ( (_class->Parameters[i].Type == CPrimitiveClass::CParameter::StringArray) || + (_class->Parameters[i].Type == CPrimitiveClass::CParameter::ConstStringArray) ) + { + uint j; + for (j=0; j<_class->Parameters[i].DefaultValue.size (); j++) + { + // Unique Id ? + if (_class->Parameters[i].DefaultValue[j].GenID) + { + // The doesn't exist ? + std::vector result; + std::vector *resultPtr = NULL; + if (!primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), resultPtr) || (resultPtr->size ()<=j)) + { + // Copy + if (resultPtr) + result = *resultPtr; + + // Resize + if (result.size ()<=j) + result.resize (j+1); + + // Resize to it + primitive.removePropertyByName (_class->Parameters[i].Name.c_str ()); + + // Set the value + result[j] = toString (getUniqueId ()); + + // Add the new property array + primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), new CPropertyStringArray (result)); + modified = true; + } + } + // Hidden ? + else if (!_class->Parameters[i].Visible) + { + // The doesn't exist ? + std::vector result; + std::vector *resultPtr = NULL; + if (!primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), resultPtr) || (resultPtr->size ()<=j)) + { + // Copy + if (resultPtr) + result = *resultPtr; + + // Resize + if (result.size ()<=j) + result.resize (j+1); + + // Resize to it + primitive.removePropertyByName (_class->Parameters[i].Name.c_str ()); + + // Set the value + result[j] = ""; + + // Add the new property array + primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), new CPropertyStringArray (result)); + modified = true; + } + } + } + } + else + { + // Default value available ? + if (!_class->Parameters[i].DefaultValue.empty ()) + { + // Hidden ? + if (!_class->Parameters[i].Visible) + { + // The doesn't exist ? + string result; + if (!primitive.getPropertyByName (_class->Parameters[i].Name.c_str (), result)) + { + // Add it ! + primitive.addPropertyByName (_class->Parameters[i].Name.c_str (), new CPropertyString ("")); + modified = true; + } + } + } + } + } + } + + // Recurcive call + uint i; + const uint count = primitive.getNumChildren (); + for (i=0; iisActive()) + theApp.Plugins.at(i-ID_WINDOWS_PLUGINS-1)->closePlugin(); + else + theApp.Plugins.at(i-ID_WINDOWS_PLUGINS-1)->activatePlugin(); + + } + else if (nCode == CN_UPDATE_COMMAND_UI) + { + // Update UI element state + + if(theApp.Plugins.at(i-ID_WINDOWS_PLUGINS-1)->isActive()) + pCmdUI->SetCheck(); + else + pCmdUI->SetCheck(0); + pCmdUI->Enable(); + + } + return TRUE; + } + } + } + + // If we didn't process the command, call the base class + // version of OnCmdMsg so the message-map can handle the message + return CDocument::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); +} + +// *************************************************************************** + + + + + +// *************************************************************************** +// CDatabaseLocator +// *************************************************************************** + +uint CDatabaseLocator::getDatabaseIndex () const +{ + return _LocateStack[0]; +} + +// *************************************************************************** + +void CDatabaseLocator::getParent () +{ + _LocateStack.resize (_LocateStack.size ()-1); +} + +// *************************************************************************** +// CDatabaseLocatorPointer +// *************************************************************************** + +void CDatabaseLocatorPointer::getParent () +{ + nlassert (Primitive); + CDatabaseLocator::getParent (); + + // Get the parent pointer + Primitive = Primitive->getParent (); +} + +// *************************************************************************** + +bool CDatabaseLocatorPointer::operator== (const CDatabaseLocatorPointer &other) const +{ + return CDatabaseLocator::operator== (other); +} + +// *************************************************************************** + +void CDatabaseLocatorPointer::appendChild (CDatabaseLocator &dest) const +{ + nlassert (Primitive); + dest._LocateStack = _LocateStack; + dest._LocateStack.push_back (Primitive->getNumChildren ()); + dest.XSubPrim = 0xffffffff; +} + +// *************************************************************************** + +bool CDatabaseLocatorPointer::next () +{ + // Should not be end + if (_LocateStack[0] == 0xffffffff) + return false; + + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // We are in a primitive ? + if (Primitive) + { + // Some children to visite ? + if (Primitive->getNumChildren () > 0) + { + // Get the first child + nlverify (Primitive->getChild (Primitive, 0)); + + // Push + _LocateStack.push_back (0); + + // Done + return true; + } + + // Try to visit a brother + const IPrimitive *parent = Primitive->getParent (); + + // Have a parent ? + while (parent) + { + // The child Id + uint childId; + + nlverify (parent->getChildId (childId, Primitive)); + childId++; + if (childId < parent->getNumChildren ()) + { + nlassert (_LocateStack.back () == childId-1); + _LocateStack.back () = childId; + nlverify (parent->getChild (Primitive, childId)); + return true; + } + else + { + // Get next parent + Primitive = parent; + parent = parent->getParent (); + + // Unstack + _LocateStack.pop_back (); + } + } + + // Next primitive Id + _LocateStack[0]++; + nlassert (_LocateStack.size () == 1); + Primitive = NULL; + if (_LocateStack[0] < doc->_DataHierarchy.size ()) + { + return true; + } + + // End + _LocateStack[0] = 0xffffffff; + return false; + } + else + { + Primitive = doc->_DataHierarchy[_LocateStack[0]].Primitives.RootNode; + return true; + } +} + +// *************************************************************************** + +void CDatabaseLocatorPointer::getRoot (uint i) +{ + XSubPrim = 0xffffffff; + _LocateStack.clear (); + _LocateStack.push_back (i); + + // Get the document + CWorldEditorDoc *doc = getDocument (); + + Primitive = doc->_DataHierarchy[i].Primitives.RootNode; +} + +// *************************************************************************** + +void CDatabaseLocatorPointer::getRoot (const string& rootFileName) +{ + XSubPrim = 0xffffffff; + _LocateStack.clear (); + + + // Get the document + CWorldEditorDoc *doc = getDocument (); + uint count = doc->getNumDatabaseElement (); + uint i=0; + for(i=0;i_DataHierarchy[i].Filename)==0) + break; + if(i_DataHierarchy[i].Primitives.RootNode; + _LocateStack.push_back (i); + } + else + { + exception e("Bad primitive File Name. Please refresh."); + throw(e); + } +} + +// *************************************************************************** + +string& CDatabaseLocatorPointer::getRootFileName (IPrimitive* rootPrim) +{ + // Get the document + CWorldEditorDoc *doc = getDocument (); + uint count = doc->getNumDatabaseElement (); + uint i=0; + for(i=0;i_DataHierarchy[i].Primitives.RootNode ==rootPrim) + break; + + if(i==count) + { + exception e("Bad primitive File Name. Please refresh."); + throw(e); + } + + return doc->_DataHierarchy[i].Filename; + +} + +// *************************************************************************** + +bool CDatabaseLocatorPointer::firstChild () +{ + XSubPrim = 0xffffffff; + // Should not be end + if (_LocateStack[0] == 0xffffffff) + return false; + + // Get the document + CWorldEditorDoc *doc = getDocument (); + + // Some children to visite ? + if (Primitive->getNumChildren () > 0) + { + // Get the first child + nlverify (Primitive->getChild (Primitive, 0)); + + // Push + _LocateStack.push_back (0); + + // Done + return true; + } + else + { + // Primitive doesn't exist + Primitive = NULL; + + // Push + _LocateStack.push_back (0); + + // Done + return false; + } +} + +// *************************************************************************** + +bool CDatabaseLocatorPointer::nextChild () +{ + // Try to visit a brother + const IPrimitive *parent = Primitive->getParent (); + + // Have a parent ? + nlassert (parent); + + // The child Id + uint childId; + + nlverify (parent->getChildId (childId, Primitive)); + childId++; + if (childId < parent->getNumChildren ()) + { + nlassert (_LocateStack.back () == childId-1); + _LocateStack.back () = childId; + nlverify (parent->getChild (Primitive, childId)); + return true; + } + else + { + // Get next parent + Primitive = parent; + parent = parent->getParent (); + + // Unstack + _LocateStack.pop_back (); + return false; + } +} + +// *************************************************************************** + +bool CDatabaseLocatorPointer::previousChild () +{ + // Try to visit a brother + const IPrimitive *parent = Primitive->getParent (); + + // Have a parent ? + nlassert (parent); + + // The child Id + uint childId; + + nlverify (parent->getChildId (childId, Primitive)); + if (childId > 0) + { + childId--; + nlassert (_LocateStack.back () == childId+1); + _LocateStack.back () = childId; + nlverify (parent->getChild (Primitive, childId)); + return true; + } + else + { + // Get next parent + Primitive = parent; + parent = parent->getParent (); + + // Unstack + _LocateStack.pop_back (); + return false; + } +} + +// *************************************************************************** + +bool CDatabaseLocator::operator== (const CDatabaseLocator &other) const +{ + return _LocateStack == other._LocateStack; +} + +// *************************************************************************** + +std::string CDatabaseLocator::getPathName () const +{ + // Get the doc + CWorldEditorDoc *doc = getDocument (); + + // First string + string path; + doc->getPrimitiveDisplayName (path, _LocateStack[0]); + + // Next + const IPrimitive *prim = doc->_DataHierarchy[_LocateStack[0]].Primitives.RootNode; + for (uint i=1; i<_LocateStack.size (); i++) + { + // Add the child + prim->getChild (prim, _LocateStack[i]); + + // Get its name + path += "."; + string name; + if (prim->getPropertyByName ("name", name)) + path += name; + } + + return path; +} + +// *************************************************************************** + +CDatabaseLocator::CDatabaseLocator (uint region, sint32 x, sint32 y) +{ + _LocateStack.push_back (getDocument ()->regionIDToDatabaseElementID(region)); + XSubPrim = x; + Y = y; +} + +// *************************************************************************** + +void CWorldEditorDoc::OnFileOpen() +{ + theApp.OnFileOpen (); +} + +// *************************************************************************** + +void CWorldEditorDoc::OnFileSave() +{ + theApp.OnFileSave (); +} + +// *************************************************************************** + +void CWorldEditorDoc::OnFileSaveAs() +{ + theApp.OnFileSaveAs (); +} + +// *************************************************************************** + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_doc.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_doc.h index 5c9343175..f3f5d4b47 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_doc.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_doc.h @@ -1,474 +1,474 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// world_editor_doc.h : interface of the CWorldEditorDoc class -// -///////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_WORLD_EDITOR_DOC_H__79C92BF7_274F_4B2C_A546_91B7E5218C49__INCLUDED_) -#define AFX_WORLD_EDITOR_DOC_H__79C92BF7_274F_4B2C_A546_91B7E5218C49__INCLUDED_ - -#include -#include -#include - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -// Data -struct CLigoData -{ - uint8 PosX; - uint8 PosY; - uint8 Rot; - uint8 Flip; - std::string ZoneName; - std::string SharingMatNames[4]; - uint8 SharingCutEdges[4]; - bool operator!= (const CLigoData& other) const - { - return (PosX != other.PosX) || - (PosY != other.PosY) || - (Rot != other.Rot) || - (Flip != other.Flip) || - (ZoneName != other.ZoneName) || - (SharingMatNames[0] != other.SharingMatNames[0]) || - (SharingMatNames[1] != other.SharingMatNames[1]) || - (SharingMatNames[2] != other.SharingMatNames[2]) || - (SharingMatNames[3] != other.SharingMatNames[3]) || - (SharingCutEdges[0] != other.SharingCutEdges[0]) || - (SharingCutEdges[1] != other.SharingCutEdges[1]) || - (SharingCutEdges[2] != other.SharingCutEdges[2]) || - (SharingCutEdges[3] != other.SharingCutEdges[3]); - } -}; - -// Primitive locator -class CDatabaseLocator -{ - friend class CWorldEditorDoc; - friend class CDatabaseLocatorPointer; -public: - // Default cstor, reserve some room - CDatabaseLocator () - { - _LocateStack.reserve (10); - _LocateStack.resize (1); - XSubPrim = 0xffffffff; - Y = 0xffffffff; - } - CDatabaseLocator (uint region, sint32 x, sint32 y); - - bool operator== (const CDatabaseLocator &other) const; - bool operator< (const CDatabaseLocator &other) const - { - const uint size = (uint)_LocateStack.size (); - const uint otherSize = (uint)other._LocateStack.size (); - const uint minSize = std::min (size, otherSize); - uint i; - for (i=0; i other._LocateStack[i]) - return false; - } - return (size < otherSize); - } - - uint getDatabaseIndex () const; - virtual void getParent (); - - std::string getPathName () const; - -public: - // Region X, Y - sint32 XSubPrim, Y; - -protected: - // The locate stack - std::vector _LocateStack; -}; - -// Primitive pointer -class CDatabaseLocatorPointer : public CDatabaseLocator -{ -public: - - bool next (); - void getRoot (uint i); - void getRoot (const std::string& rootFileName); - std::string& getRootFileName(NLLIGO::IPrimitive* rootNode); - bool firstChild (); - bool nextChild (); - bool previousChild (); - virtual void getParent (); - void appendChild (CDatabaseLocator &dest) const; - bool operator== (const CDatabaseLocatorPointer &other) const; - - const NLLIGO::IPrimitive *Primitive; -}; - -class CWorldEditorDoc : public CDocument -{ - friend class CDatabaseLocator; - friend class CDatabaseLocatorPointer; - friend class CActionLigoTile; - friend class CActionLigoMove; - friend class CActionLigoResize; - friend class CActionImportPrimitive; - friend class CActionLoadPrimitive; - friend class CActionNewPrimitive; - friend class CActionClearPrimitives; - friend class CActionDelete; - friend class CActionAddPrimitiveByClass; - friend class CActionAddLandscape; - friend class CActionDeleteDatabaseElement; - friend class CActionAddPrimitive; - friend class CToolsLogicTree; - friend class CMainFrame; - friend class CActionNewLandscape; - friend class CActionXChgDatabaseElement; -protected: // create from serialization only - CWorldEditorDoc(); - DECLARE_DYNCREATE(CWorldEditorDoc) - -// Attributes -public: - -// Methods - - // Get the data directory - const std::string &getDataDir () const; - - // Get the default save path - void getFilePath(uint primIndex,std::string&); - - // Set the data directory - void setDataDir (const char *dir); - - // Get the path of selected primitive - const std::string &getPathOfSelectedPrimitive() const; - - // Set the path of selected primitive - void setPathOfSelectedPrimitive(const std::string&); - - // Serial - void serial (NLMISC::IStream &s); - - // Modify the document - void beginModification (); - - // Add a modification at the document in a undo/redo session. Return false if the redo method has failed and the action is deleted. - bool addModification (class IAction *action); - - void endModification (); - - bool inModificationMode() const {return _ModificationMode;} - - // Notify the document it as been modified without possible undo - void noUndoModification (); - - // Notify an undo / redo on in ligo mode - void redo (); - void undo (); - - // Is undo / redo available ? - bool undoAvailable () const; - bool redoAvailable () const; - - // Notify modification - - void modifyDatabase (uint dbIndex); - void modifyProject (); - - // *** Acces Zone region - - uint regionIDToDatabaseElementID (uint landscape) const; - const NLLIGO::CZoneRegion &getZoneRegion (uint landscape) const; - const NLLIGO::CZoneRegion &getZoneRegionAbsolute (uint landscape) const; - - // Get ligo data at a specific locator - void getLigoData (CLigoData &data, const CDatabaseLocator &locator); - - // Get a specific zone among all zones - bool getZoneAmongRegions (CDatabaseLocator &locator, class CBuilderZoneRegion*& pBZRfrom, sint32 x, sint32 y); - - // *** Acces Prim region - -public: - - // Get primitives count - uint getNumDatabaseElement () const; - - // Get a primitive filename - const std::string &getDatabaseElement (uint primitive) const; - - // Get a primitive - const NLLIGO::CPrimitives &getDatabaseElements (uint primitive) const; - - // Get a primitive formated name - void getPrimitiveDisplayName (std::string &result, uint primitive) const; - - // Is a primitive already loaded in the document ? - bool isPrimitiveLoaded(const std::string &primPath); - - // Is a landscape ? - bool isLandscape (uint dbIndex) const; - - // Is a primitive ? - bool isPrimitive (uint dbIndex) const; - - // Is an editable primtive ? - bool isEditable (uint dbIndex) const; - - // Update default values - void updateDefaultValues (uint dnIndex); - - // Reset default values. onlyZero flag reset id only iof id is 0 - void resetUniqueID (const NLLIGO::IPrimitive &primitive, bool onlyZero = false); - - struct TPropertyNonUnique - { - const NLLIGO::IPrimitive *Primitive; - std::string PropertyName; - }; - - // Regenerate any ID that is not unique (i.e. any id that is found in the received hash_set). - // All the valid or regenerated ID are then inserted in the hash_set - void forceIDUniqueness(const NLLIGO::IPrimitive &primitive, CHashSet &ids, std::vector &nonUnique); - -private: - bool updateDefaultValuesInternal (NLLIGO::IPrimitive &primitive); - -private: - - // Delete a primitive, for actions only - void deletePrimitive (const CDatabaseLocator &locator); - - // Insert a primitive, for actions only - void insertPrimitive (const CDatabaseLocator &locator, NLLIGO::IPrimitive *primitive); - - // Create a primitive, for actions only - const NLLIGO::IPrimitive *createPrimitive (const CDatabaseLocator &locator, const char *className, const char *primName, - const NLMISC::CVector &initPos, float deltaPos, const std::vector &initParameters); - - // Init a primitive parameters - void initPrimitiveParameters (const NLLIGO::CPrimitiveClass &primClass, NLLIGO::IPrimitive &primitive, - const std::vector &initParameters); - - - // Get a locator with a primitive -public: - void getLocator (CDatabaseLocatorPointer &locator, const NLLIGO::IPrimitive *primitive) const; - void getLocator (CDatabaseLocatorPointer &locatorDest, const CDatabaseLocator &locator) const; - void getFirstLocator (CDatabaseLocatorPointer &locator) const; - - // *** File modification - void updateFiles (); - static bool checkFileDate (const char *filename, uint32 date); - -/* // Get ligo data at a specific locator - void getLigoData (CLigoData &data, const CDatabaseLocator &locator); - - // Get a specific zone among all zones - bool getZoneAmongRegions (CDatabaseLocator &locator, class CBuilderZoneRegion*& pBZRfrom, sint32 x, sint32 y);*/ - - // Get document context - const std::string &getContext () const - { - return _Context; - } - - // Get document context - void setContext (const char *context) - { - _Context = context; - } - - - void modifyPropertyDlg(); - -private: - - // Data directory - std::string _DataDir; - - // Document context - std::string _Context; - - // Path of selected primitive - std::string _PathOfSelectedPrimitive; - - // Set the modified mode for the document - void updateModifiedState (); - - // Clear changes - void clearModifications (); - - // List of landscape, deprecated, for compatibility - struct CLandscapeDeprecated - { - CLandscapeDeprecated () - { - Modified = false; - } - std::string Filename; - NLLIGO::CZoneRegion ZoneRegion; - void serial (NLMISC::IStream &s); - bool Modified; - uint32 LastModifedTime; - }; - - // List of primitive, deprecated, for compatibility - struct CPrimitiveDeprecated - { - CPrimitiveDeprecated () - { - Modified = false; - } - std::string Filename; - NLLIGO::CPrimitives Primitives; - void serial (NLMISC::IStream &s); - bool Modified; - uint32 LastModifedTime; - }; - - // Database - class CDatabaseElement - { - public: - // Landscape or primitive ? - enum TType - { - Landscape, - Primitive, - Undefined - }; - - // Constructor - CDatabaseElement (); - CDatabaseElement (TType type); - - // Landscape or primitive ? - TType Type; - - // Global - std::string Filename; - void serial (NLMISC::IStream &s); - bool Modified; - bool Editable; - uint32 LastModifedTime; - - // Landscape - NLLIGO::CZoneRegion ZoneRegion; - - // Primitives - NLLIGO::CPrimitives Primitives; - - // set of used alias in the primitives - std::set UsedAliases; - }; - - // The database - class CDatabaseList : public std::list - { - public: - const CDatabaseElement& operator[] (uint index) const - { - return *(_PointerArray[index]); - } - CDatabaseElement& operator[] (uint index) - { - return *(_PointerArray[index]); - } - - // Recompute pointer array - void recomputePointerArray () - { - _PointerArray.clear (); - std::list::iterator ite = begin (); - while (ite != end ()) - { - _PointerArray.push_back (&(*ite)); - ite++; - } - } - - private: - // The pointer array - std::vector _PointerArray; - }; - - CDatabaseList _DataHierarchy; - - // Undo / redo / modification flags - std::vector< std::vector > _Actions; - std::vector _CurrentAction; - bool _NoModificationUndo; - uint _Undo; - uint _LastSaveUndo; - bool _ModificationMode; - bool _Modified; - uint32 _LastModifedTime; - - -// Operations -public: - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CWorldEditorDoc) - public: - virtual BOOL OnNewDocument(); - virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); - virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); - virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); - //}}AFX_VIRTUAL - -private: - bool newDocument (); - bool loadDocument (const char *filename); - -// Implementation -public: - virtual ~CWorldEditorDoc(); -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - -protected: - -// Generated message map functions -protected: - //{{AFX_MSG(CWorldEditorDoc) - afx_msg void OnFileOpen(); - afx_msg void OnFileSave(); - afx_msg void OnFileSaveAs(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -class CWorldEditorDoc *getDocument (); - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_WORLD_EDITOR_DOC_H__79C92BF7_274F_4B2C_A546_91B7E5218C49__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// world_editor_doc.h : interface of the CWorldEditorDoc class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_WORLD_EDITOR_DOC_H__79C92BF7_274F_4B2C_A546_91B7E5218C49__INCLUDED_) +#define AFX_WORLD_EDITOR_DOC_H__79C92BF7_274F_4B2C_A546_91B7E5218C49__INCLUDED_ + +#include +#include +#include + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +// Data +struct CLigoData +{ + uint8 PosX; + uint8 PosY; + uint8 Rot; + uint8 Flip; + std::string ZoneName; + std::string SharingMatNames[4]; + uint8 SharingCutEdges[4]; + bool operator!= (const CLigoData& other) const + { + return (PosX != other.PosX) || + (PosY != other.PosY) || + (Rot != other.Rot) || + (Flip != other.Flip) || + (ZoneName != other.ZoneName) || + (SharingMatNames[0] != other.SharingMatNames[0]) || + (SharingMatNames[1] != other.SharingMatNames[1]) || + (SharingMatNames[2] != other.SharingMatNames[2]) || + (SharingMatNames[3] != other.SharingMatNames[3]) || + (SharingCutEdges[0] != other.SharingCutEdges[0]) || + (SharingCutEdges[1] != other.SharingCutEdges[1]) || + (SharingCutEdges[2] != other.SharingCutEdges[2]) || + (SharingCutEdges[3] != other.SharingCutEdges[3]); + } +}; + +// Primitive locator +class CDatabaseLocator +{ + friend class CWorldEditorDoc; + friend class CDatabaseLocatorPointer; +public: + // Default cstor, reserve some room + CDatabaseLocator () + { + _LocateStack.reserve (10); + _LocateStack.resize (1); + XSubPrim = 0xffffffff; + Y = 0xffffffff; + } + CDatabaseLocator (uint region, sint32 x, sint32 y); + + bool operator== (const CDatabaseLocator &other) const; + bool operator< (const CDatabaseLocator &other) const + { + const uint size = (uint)_LocateStack.size (); + const uint otherSize = (uint)other._LocateStack.size (); + const uint minSize = std::min (size, otherSize); + uint i; + for (i=0; i other._LocateStack[i]) + return false; + } + return (size < otherSize); + } + + uint getDatabaseIndex () const; + virtual void getParent (); + + std::string getPathName () const; + +public: + // Region X, Y + sint32 XSubPrim, Y; + +protected: + // The locate stack + std::vector _LocateStack; +}; + +// Primitive pointer +class CDatabaseLocatorPointer : public CDatabaseLocator +{ +public: + + bool next (); + void getRoot (uint i); + void getRoot (const std::string& rootFileName); + std::string& getRootFileName(NLLIGO::IPrimitive* rootNode); + bool firstChild (); + bool nextChild (); + bool previousChild (); + virtual void getParent (); + void appendChild (CDatabaseLocator &dest) const; + bool operator== (const CDatabaseLocatorPointer &other) const; + + const NLLIGO::IPrimitive *Primitive; +}; + +class CWorldEditorDoc : public CDocument +{ + friend class CDatabaseLocator; + friend class CDatabaseLocatorPointer; + friend class CActionLigoTile; + friend class CActionLigoMove; + friend class CActionLigoResize; + friend class CActionImportPrimitive; + friend class CActionLoadPrimitive; + friend class CActionNewPrimitive; + friend class CActionClearPrimitives; + friend class CActionDelete; + friend class CActionAddPrimitiveByClass; + friend class CActionAddLandscape; + friend class CActionDeleteDatabaseElement; + friend class CActionAddPrimitive; + friend class CToolsLogicTree; + friend class CMainFrame; + friend class CActionNewLandscape; + friend class CActionXChgDatabaseElement; +protected: // create from serialization only + CWorldEditorDoc(); + DECLARE_DYNCREATE(CWorldEditorDoc) + +// Attributes +public: + +// Methods + + // Get the data directory + const std::string &getDataDir () const; + + // Get the default save path + void getFilePath(uint primIndex,std::string&); + + // Set the data directory + void setDataDir (const char *dir); + + // Get the path of selected primitive + const std::string &getPathOfSelectedPrimitive() const; + + // Set the path of selected primitive + void setPathOfSelectedPrimitive(const std::string&); + + // Serial + void serial (NLMISC::IStream &s); + + // Modify the document + void beginModification (); + + // Add a modification at the document in a undo/redo session. Return false if the redo method has failed and the action is deleted. + bool addModification (class IAction *action); + + void endModification (); + + bool inModificationMode() const {return _ModificationMode;} + + // Notify the document it as been modified without possible undo + void noUndoModification (); + + // Notify an undo / redo on in ligo mode + void redo (); + void undo (); + + // Is undo / redo available ? + bool undoAvailable () const; + bool redoAvailable () const; + + // Notify modification + + void modifyDatabase (uint dbIndex); + void modifyProject (); + + // *** Acces Zone region + + uint regionIDToDatabaseElementID (uint landscape) const; + const NLLIGO::CZoneRegion &getZoneRegion (uint landscape) const; + const NLLIGO::CZoneRegion &getZoneRegionAbsolute (uint landscape) const; + + // Get ligo data at a specific locator + void getLigoData (CLigoData &data, const CDatabaseLocator &locator); + + // Get a specific zone among all zones + bool getZoneAmongRegions (CDatabaseLocator &locator, class CBuilderZoneRegion*& pBZRfrom, sint32 x, sint32 y); + + // *** Acces Prim region + +public: + + // Get primitives count + uint getNumDatabaseElement () const; + + // Get a primitive filename + const std::string &getDatabaseElement (uint primitive) const; + + // Get a primitive + const NLLIGO::CPrimitives &getDatabaseElements (uint primitive) const; + + // Get a primitive formated name + void getPrimitiveDisplayName (std::string &result, uint primitive) const; + + // Is a primitive already loaded in the document ? + bool isPrimitiveLoaded(const std::string &primPath); + + // Is a landscape ? + bool isLandscape (uint dbIndex) const; + + // Is a primitive ? + bool isPrimitive (uint dbIndex) const; + + // Is an editable primtive ? + bool isEditable (uint dbIndex) const; + + // Update default values + void updateDefaultValues (uint dnIndex); + + // Reset default values. onlyZero flag reset id only iof id is 0 + void resetUniqueID (const NLLIGO::IPrimitive &primitive, bool onlyZero = false); + + struct TPropertyNonUnique + { + const NLLIGO::IPrimitive *Primitive; + std::string PropertyName; + }; + + // Regenerate any ID that is not unique (i.e. any id that is found in the received hash_set). + // All the valid or regenerated ID are then inserted in the hash_set + void forceIDUniqueness(const NLLIGO::IPrimitive &primitive, CHashSet &ids, std::vector &nonUnique); + +private: + bool updateDefaultValuesInternal (NLLIGO::IPrimitive &primitive); + +private: + + // Delete a primitive, for actions only + void deletePrimitive (const CDatabaseLocator &locator); + + // Insert a primitive, for actions only + void insertPrimitive (const CDatabaseLocator &locator, NLLIGO::IPrimitive *primitive); + + // Create a primitive, for actions only + const NLLIGO::IPrimitive *createPrimitive (const CDatabaseLocator &locator, const char *className, const char *primName, + const NLMISC::CVector &initPos, float deltaPos, const std::vector &initParameters); + + // Init a primitive parameters + void initPrimitiveParameters (const NLLIGO::CPrimitiveClass &primClass, NLLIGO::IPrimitive &primitive, + const std::vector &initParameters); + + + // Get a locator with a primitive +public: + void getLocator (CDatabaseLocatorPointer &locator, const NLLIGO::IPrimitive *primitive) const; + void getLocator (CDatabaseLocatorPointer &locatorDest, const CDatabaseLocator &locator) const; + void getFirstLocator (CDatabaseLocatorPointer &locator) const; + + // *** File modification + void updateFiles (); + static bool checkFileDate (const char *filename, uint32 date); + +/* // Get ligo data at a specific locator + void getLigoData (CLigoData &data, const CDatabaseLocator &locator); + + // Get a specific zone among all zones + bool getZoneAmongRegions (CDatabaseLocator &locator, class CBuilderZoneRegion*& pBZRfrom, sint32 x, sint32 y);*/ + + // Get document context + const std::string &getContext () const + { + return _Context; + } + + // Get document context + void setContext (const char *context) + { + _Context = context; + } + + + void modifyPropertyDlg(); + +private: + + // Data directory + std::string _DataDir; + + // Document context + std::string _Context; + + // Path of selected primitive + std::string _PathOfSelectedPrimitive; + + // Set the modified mode for the document + void updateModifiedState (); + + // Clear changes + void clearModifications (); + + // List of landscape, deprecated, for compatibility + struct CLandscapeDeprecated + { + CLandscapeDeprecated () + { + Modified = false; + } + std::string Filename; + NLLIGO::CZoneRegion ZoneRegion; + void serial (NLMISC::IStream &s); + bool Modified; + uint32 LastModifedTime; + }; + + // List of primitive, deprecated, for compatibility + struct CPrimitiveDeprecated + { + CPrimitiveDeprecated () + { + Modified = false; + } + std::string Filename; + NLLIGO::CPrimitives Primitives; + void serial (NLMISC::IStream &s); + bool Modified; + uint32 LastModifedTime; + }; + + // Database + class CDatabaseElement + { + public: + // Landscape or primitive ? + enum TType + { + Landscape, + Primitive, + Undefined + }; + + // Constructor + CDatabaseElement (); + CDatabaseElement (TType type); + + // Landscape or primitive ? + TType Type; + + // Global + std::string Filename; + void serial (NLMISC::IStream &s); + bool Modified; + bool Editable; + uint32 LastModifedTime; + + // Landscape + NLLIGO::CZoneRegion ZoneRegion; + + // Primitives + NLLIGO::CPrimitives Primitives; + + // set of used alias in the primitives + std::set UsedAliases; + }; + + // The database + class CDatabaseList : public std::list + { + public: + const CDatabaseElement& operator[] (uint index) const + { + return *(_PointerArray[index]); + } + CDatabaseElement& operator[] (uint index) + { + return *(_PointerArray[index]); + } + + // Recompute pointer array + void recomputePointerArray () + { + _PointerArray.clear (); + std::list::iterator ite = begin (); + while (ite != end ()) + { + _PointerArray.push_back (&(*ite)); + ite++; + } + } + + private: + // The pointer array + std::vector _PointerArray; + }; + + CDatabaseList _DataHierarchy; + + // Undo / redo / modification flags + std::vector< std::vector > _Actions; + std::vector _CurrentAction; + bool _NoModificationUndo; + uint _Undo; + uint _LastSaveUndo; + bool _ModificationMode; + bool _Modified; + uint32 _LastModifedTime; + + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CWorldEditorDoc) + public: + virtual BOOL OnNewDocument(); + virtual BOOL OnOpenDocument(LPCTSTR lpszPathName); + virtual BOOL OnSaveDocument(LPCTSTR lpszPathName); + virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); + //}}AFX_VIRTUAL + +private: + bool newDocument (); + bool loadDocument (const char *filename); + +// Implementation +public: + virtual ~CWorldEditorDoc(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CWorldEditorDoc) + afx_msg void OnFileOpen(); + afx_msg void OnFileSave(); + afx_msg void OnFileSaveAs(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +class CWorldEditorDoc *getDocument (); + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_WORLD_EDITOR_DOC_H__79C92BF7_274F_4B2C_A546_91B7E5218C49__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_view.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_view.cpp index 565b6a86b..843fcc4f1 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_view.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_view.cpp @@ -1,114 +1,114 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// world_editor_view.cpp : implementation of the CWorldEditorView class -// - -#include "stdafx.h" -#include "world_editor.h" - -#include "world_editor_doc.h" -#include "world_editor_view.h" - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorView - -IMPLEMENT_DYNCREATE(CWorldEditorView, CView) - -BEGIN_MESSAGE_MAP(CWorldEditorView, CView) - //{{AFX_MSG_MAP(CWorldEditorView) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code! - //}}AFX_MSG_MAP - // Standard printing commands - ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) - ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) - ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorView construction/destruction - -CWorldEditorView::CWorldEditorView() -{ - // TODO: add construction code here - -} - -CWorldEditorView::~CWorldEditorView() -{ -} - -BOOL CWorldEditorView::PreCreateWindow(CREATESTRUCT& cs) -{ - // TODO: Modify the Window class or styles here by modifying - // the CREATESTRUCT cs - - return CView::PreCreateWindow(cs); -} - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorView drawing - -void CWorldEditorView::OnDraw(CDC* pDC) -{ - CWorldEditorDoc* pDoc = GetDocument(); - ASSERT_VALID(pDoc); - // TODO: add draw code for native data here -} - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorView printing - -BOOL CWorldEditorView::OnPreparePrinting(CPrintInfo* pInfo) -{ - // default preparation - return DoPreparePrinting(pInfo); -} - -void CWorldEditorView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) -{ - // TODO: add extra initialization before printing -} - -void CWorldEditorView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) -{ - // TODO: add cleanup after printing -} - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorView diagnostics - -#ifdef _DEBUG -void CWorldEditorView::AssertValid() const -{ - CView::AssertValid(); -} - -void CWorldEditorView::Dump(CDumpContext& dc) const -{ - CView::Dump(dc); -} - -CWorldEditorDoc* CWorldEditorView::GetDocument() // non-debug version is inline -{ - ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CWorldEditorDoc))); - return (CWorldEditorDoc*)m_pDocument; -} -#endif //_DEBUG - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorView message handlers +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// world_editor_view.cpp : implementation of the CWorldEditorView class +// + +#include "stdafx.h" +#include "world_editor.h" + +#include "world_editor_doc.h" +#include "world_editor_view.h" + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorView + +IMPLEMENT_DYNCREATE(CWorldEditorView, CView) + +BEGIN_MESSAGE_MAP(CWorldEditorView, CView) + //{{AFX_MSG_MAP(CWorldEditorView) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP + // Standard printing commands + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorView construction/destruction + +CWorldEditorView::CWorldEditorView() +{ + // TODO: add construction code here + +} + +CWorldEditorView::~CWorldEditorView() +{ +} + +BOOL CWorldEditorView::PreCreateWindow(CREATESTRUCT& cs) +{ + // TODO: Modify the Window class or styles here by modifying + // the CREATESTRUCT cs + + return CView::PreCreateWindow(cs); +} + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorView drawing + +void CWorldEditorView::OnDraw(CDC* pDC) +{ + CWorldEditorDoc* pDoc = GetDocument(); + ASSERT_VALID(pDoc); + // TODO: add draw code for native data here +} + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorView printing + +BOOL CWorldEditorView::OnPreparePrinting(CPrintInfo* pInfo) +{ + // default preparation + return DoPreparePrinting(pInfo); +} + +void CWorldEditorView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add extra initialization before printing +} + +void CWorldEditorView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) +{ + // TODO: add cleanup after printing +} + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorView diagnostics + +#ifdef _DEBUG +void CWorldEditorView::AssertValid() const +{ + CView::AssertValid(); +} + +void CWorldEditorView::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} + +CWorldEditorDoc* CWorldEditorView::GetDocument() // non-debug version is inline +{ + ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CWorldEditorDoc))); + return (CWorldEditorDoc*)m_pDocument; +} +#endif //_DEBUG + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorView message handlers diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_view.h b/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_view.h index b6953266e..8bcdb42be 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_view.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor/world_editor_view.h @@ -1,83 +1,83 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// world_editor_view.h : interface of the CWorldEditorView class -// -///////////////////////////////////////////////////////////////////////////// - -#if !defined(AFX_WORLD_EDITOR_VIEW_H__4B3B2FD3_B06F_434B_B6BC_F6514AAB05EA__INCLUDED_) -#define AFX_WORLD_EDITOR_VIEW_H__4B3B2FD3_B06F_434B_B6BC_F6514AAB05EA__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - - -class CWorldEditorView : public CView -{ -protected: // create from serialization only - CWorldEditorView(); - DECLARE_DYNCREATE(CWorldEditorView) - -// Attributes -public: - CWorldEditorDoc* GetDocument(); - -// Operations -public: - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CWorldEditorView) - public: - virtual void OnDraw(CDC* pDC); // overridden to draw this view - virtual BOOL PreCreateWindow(CREATESTRUCT& cs); - protected: - virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); - virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); - virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); - //}}AFX_VIRTUAL - -// Implementation -public: - virtual ~CWorldEditorView(); -#ifdef _DEBUG - virtual void AssertValid() const; - virtual void Dump(CDumpContext& dc) const; -#endif - -protected: - -// Generated message map functions -protected: - //{{AFX_MSG(CWorldEditorView) - // NOTE - the ClassWizard will add and remove member functions here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -#ifndef _DEBUG // debug version in world_editor_view.cpp -inline CWorldEditorDoc* CWorldEditorView::GetDocument() - { return (CWorldEditorDoc*)m_pDocument; } -#endif - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_WORLD_EDITOR_VIEW_H__4B3B2FD3_B06F_434B_B6BC_F6514AAB05EA__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// world_editor_view.h : interface of the CWorldEditorView class +// +///////////////////////////////////////////////////////////////////////////// + +#if !defined(AFX_WORLD_EDITOR_VIEW_H__4B3B2FD3_B06F_434B_B6BC_F6514AAB05EA__INCLUDED_) +#define AFX_WORLD_EDITOR_VIEW_H__4B3B2FD3_B06F_434B_B6BC_F6514AAB05EA__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +class CWorldEditorView : public CView +{ +protected: // create from serialization only + CWorldEditorView(); + DECLARE_DYNCREATE(CWorldEditorView) + +// Attributes +public: + CWorldEditorDoc* GetDocument(); + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CWorldEditorView) + public: + virtual void OnDraw(CDC* pDC); // overridden to draw this view + virtual BOOL PreCreateWindow(CREATESTRUCT& cs); + protected: + virtual BOOL OnPreparePrinting(CPrintInfo* pInfo); + virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo); + virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CWorldEditorView(); +#ifdef _DEBUG + virtual void AssertValid() const; + virtual void Dump(CDumpContext& dc) const; +#endif + +protected: + +// Generated message map functions +protected: + //{{AFX_MSG(CWorldEditorView) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +#ifndef _DEBUG // debug version in world_editor_view.cpp +inline CWorldEditorDoc* CWorldEditorView::GetDocument() + { return (CWorldEditorDoc*)m_pDocument; } +#endif + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_WORLD_EDITOR_VIEW_H__4B3B2FD3_B06F_434B_B6BC_F6514AAB05EA__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/DialogFlags.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/DialogFlags.cpp index 415a16e82..80d31a728 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/DialogFlags.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/DialogFlags.cpp @@ -1,122 +1,122 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// DialogFlags.cpp : implementation file -// - -#include "stdafx.h" -#include "world_editor_fauna_graph_plugin.h" -#include "DialogFlags.h" -#include "plugin.h" - - -///////////////////////////////////////////////////////////////////////////// -// CDialogFlags dialog - - -CDialogFlags::CDialogFlags(CPlugin *plugin) - : DisplayCondition(DisplayAll), _Plugin(plugin) -{ - //AFX_MANAGE_STATE(AfxGetStaticModuleState()); - //{{AFX_DATA_INIT(CDialogFlags) - m_DisplayFlags = TRUE; - m_DisplayIndices = TRUE; - m_DisplayTargetIndices = FALSE; - //}}AFX_DATA_INIT -} - - -void CDialogFlags::DoDataExchange(CDataExchange* pDX) -{ - //AFX_MANAGE_STATE(AfxGetStaticModuleState()); - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CDialogFlags) - DDX_Check(pDX, IDC_DISPLAY_FLAGS, m_DisplayFlags); - DDX_Check(pDX, IDC_DISPLAY_INDICES, m_DisplayIndices); - DDX_Check(pDX, IDC_DISPLAY_TARGET_INDICES, m_DisplayTargetIndices); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CDialogFlags, CDialog) - //{{AFX_MSG_MAP(CDialogFlags) - ON_CBN_SELCHANGE(IDC_DISPLAY_CONDITION, OnSelchangeDisplayCondition) - ON_BN_CLICKED(IDC_DISPLAY_FLAGS, OnDisplayFlags) - ON_BN_CLICKED(IDC_DISPLAY_INDICES, OnDisplayIndices) - ON_BN_CLICKED(IDC_DISPLAY_TARGET_INDICES, OnDisplayTargetIndices) - ON_WM_CLOSE() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CDialogFlags message handlers - -void CDialogFlags::OnSelchangeDisplayCondition() -{ - //AFX_MANAGE_STATE(AfxGetStaticModuleState()); - UpdateData(TRUE); - CComboBox *lb = (CComboBox *) GetDlgItem(IDC_DISPLAY_CONDITION); - DisplayCondition = (TDisplayCondition) lb->GetCurSel(); - BOOL enabled = DisplayCondition == DisplayOff ? FALSE : TRUE; - GetDlgItem(IDC_DISPLAY_FLAGS)->EnableWindow(enabled); - GetDlgItem(IDC_DISPLAY_INDICES)->EnableWindow(enabled); - GetDlgItem(IDC_DISPLAY_INDICES)->EnableWindow(enabled); - GetDlgItem(IDC_DISPLAY_TARGET_INDICES)->EnableWindow(enabled); - _Plugin->getPluginAccess()->invalidateLeftView(); -} - -void CDialogFlags::OnDisplayFlags() -{ - //AFX_MANAGE_STATE(AfxGetStaticModuleState()); - UpdateData(TRUE); - _Plugin->getPluginAccess()->invalidateLeftView(); -} - -void CDialogFlags::OnDisplayIndices() -{ - //AFX_MANAGE_STATE(AfxGetStaticModuleState()); - UpdateData(TRUE); - _Plugin->getPluginAccess()->invalidateLeftView(); -} - - -void CDialogFlags::OnDisplayTargetIndices() -{ - //AFX_MANAGE_STATE(AfxGetStaticModuleState()); - UpdateData(TRUE); - _Plugin->getPluginAccess()->invalidateLeftView(); -} - -BOOL CDialogFlags::OnInitDialog() -{ - //AFX_MANAGE_STATE(AfxGetStaticModuleState()); - CDialog::OnInitDialog(); - // - CComboBox *lb = (CComboBox *) GetDlgItem(IDC_DISPLAY_CONDITION); - CString str; - lb->SetCurSel(0); - // - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - - -void CDialogFlags::OnClose() -{ - //AFX_MANAGE_STATE(AfxGetStaticModuleState()); - _Plugin->closePlugin(); - CDialog::OnClose(); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// DialogFlags.cpp : implementation file +// + +#include "stdafx.h" +#include "world_editor_fauna_graph_plugin.h" +#include "DialogFlags.h" +#include "plugin.h" + + +///////////////////////////////////////////////////////////////////////////// +// CDialogFlags dialog + + +CDialogFlags::CDialogFlags(CPlugin *plugin) + : DisplayCondition(DisplayAll), _Plugin(plugin) +{ + //AFX_MANAGE_STATE(AfxGetStaticModuleState()); + //{{AFX_DATA_INIT(CDialogFlags) + m_DisplayFlags = TRUE; + m_DisplayIndices = TRUE; + m_DisplayTargetIndices = FALSE; + //}}AFX_DATA_INIT +} + + +void CDialogFlags::DoDataExchange(CDataExchange* pDX) +{ + //AFX_MANAGE_STATE(AfxGetStaticModuleState()); + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDialogFlags) + DDX_Check(pDX, IDC_DISPLAY_FLAGS, m_DisplayFlags); + DDX_Check(pDX, IDC_DISPLAY_INDICES, m_DisplayIndices); + DDX_Check(pDX, IDC_DISPLAY_TARGET_INDICES, m_DisplayTargetIndices); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDialogFlags, CDialog) + //{{AFX_MSG_MAP(CDialogFlags) + ON_CBN_SELCHANGE(IDC_DISPLAY_CONDITION, OnSelchangeDisplayCondition) + ON_BN_CLICKED(IDC_DISPLAY_FLAGS, OnDisplayFlags) + ON_BN_CLICKED(IDC_DISPLAY_INDICES, OnDisplayIndices) + ON_BN_CLICKED(IDC_DISPLAY_TARGET_INDICES, OnDisplayTargetIndices) + ON_WM_CLOSE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDialogFlags message handlers + +void CDialogFlags::OnSelchangeDisplayCondition() +{ + //AFX_MANAGE_STATE(AfxGetStaticModuleState()); + UpdateData(TRUE); + CComboBox *lb = (CComboBox *) GetDlgItem(IDC_DISPLAY_CONDITION); + DisplayCondition = (TDisplayCondition) lb->GetCurSel(); + BOOL enabled = DisplayCondition == DisplayOff ? FALSE : TRUE; + GetDlgItem(IDC_DISPLAY_FLAGS)->EnableWindow(enabled); + GetDlgItem(IDC_DISPLAY_INDICES)->EnableWindow(enabled); + GetDlgItem(IDC_DISPLAY_INDICES)->EnableWindow(enabled); + GetDlgItem(IDC_DISPLAY_TARGET_INDICES)->EnableWindow(enabled); + _Plugin->getPluginAccess()->invalidateLeftView(); +} + +void CDialogFlags::OnDisplayFlags() +{ + //AFX_MANAGE_STATE(AfxGetStaticModuleState()); + UpdateData(TRUE); + _Plugin->getPluginAccess()->invalidateLeftView(); +} + +void CDialogFlags::OnDisplayIndices() +{ + //AFX_MANAGE_STATE(AfxGetStaticModuleState()); + UpdateData(TRUE); + _Plugin->getPluginAccess()->invalidateLeftView(); +} + + +void CDialogFlags::OnDisplayTargetIndices() +{ + //AFX_MANAGE_STATE(AfxGetStaticModuleState()); + UpdateData(TRUE); + _Plugin->getPluginAccess()->invalidateLeftView(); +} + +BOOL CDialogFlags::OnInitDialog() +{ + //AFX_MANAGE_STATE(AfxGetStaticModuleState()); + CDialog::OnInitDialog(); + // + CComboBox *lb = (CComboBox *) GetDlgItem(IDC_DISPLAY_CONDITION); + CString str; + lb->SetCurSel(0); + // + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +void CDialogFlags::OnClose() +{ + //AFX_MANAGE_STATE(AfxGetStaticModuleState()); + _Plugin->closePlugin(); + CDialog::OnClose(); +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/DialogFlags.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/DialogFlags.h index a41b37b69..e06237785 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/DialogFlags.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/DialogFlags.h @@ -1,82 +1,82 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_DIALOGFLAGS_H__96559C1A_5580_443D_9FB0_94555B12EC28__INCLUDED_) -#define AFX_DIALOGFLAGS_H__96559C1A_5580_443D_9FB0_94555B12EC28__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// DialogFlags.h : header file -// - - -class CPlugin; -///////////////////////////////////////////////////////////////////////////// -// CDialogFlags dialog - -class CDialogFlags : public CDialog -{ -// Construction -public: - CDialogFlags(CPlugin *plugin); // standard constructor - - enum TDisplayCondition - { - DisplayAll = 0, - DisplayWhenSelected, - DisplayOff - }; - - TDisplayCondition DisplayCondition; - -// Dialog Data - //{{AFX_DATA(CDialogFlags) - enum { IDD = IDD_DIALOG_FLAGS }; - BOOL m_DisplayFlags; - BOOL m_DisplayIndices; - BOOL m_DisplayTargetIndices; - // NOTE: the ClassWizard will add data members here - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CDialogFlags) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - CPlugin *_Plugin; - - // Generated message map functions - //{{AFX_MSG(CDialogFlags) - afx_msg void OnSelchangeDisplayCondition(); - afx_msg void OnDisplayFlags(); - afx_msg void OnDisplayIndices(); - afx_msg void OnDisplayTargetIndices(); - virtual BOOL OnInitDialog(); - afx_msg void OnClose(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_DIALOGFLAGS_H__96559C1A_5580_443D_9FB0_94555B12EC28__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_DIALOGFLAGS_H__96559C1A_5580_443D_9FB0_94555B12EC28__INCLUDED_) +#define AFX_DIALOGFLAGS_H__96559C1A_5580_443D_9FB0_94555B12EC28__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DialogFlags.h : header file +// + + +class CPlugin; +///////////////////////////////////////////////////////////////////////////// +// CDialogFlags dialog + +class CDialogFlags : public CDialog +{ +// Construction +public: + CDialogFlags(CPlugin *plugin); // standard constructor + + enum TDisplayCondition + { + DisplayAll = 0, + DisplayWhenSelected, + DisplayOff + }; + + TDisplayCondition DisplayCondition; + +// Dialog Data + //{{AFX_DATA(CDialogFlags) + enum { IDD = IDD_DIALOG_FLAGS }; + BOOL m_DisplayFlags; + BOOL m_DisplayIndices; + BOOL m_DisplayTargetIndices; + // NOTE: the ClassWizard will add data members here + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDialogFlags) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + CPlugin *_Plugin; + + // Generated message map functions + //{{AFX_MSG(CDialogFlags) + afx_msg void OnSelchangeDisplayCondition(); + afx_msg void OnDisplayFlags(); + afx_msg void OnDisplayIndices(); + afx_msg void OnDisplayTargetIndices(); + virtual BOOL OnInitDialog(); + afx_msg void OnClose(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DIALOGFLAGS_H__96559C1A_5580_443D_9FB0_94555B12EC28__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/ReadMe.txt b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/ReadMe.txt index 73fcd438b..39ace2014 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/ReadMe.txt +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/ReadMe.txt @@ -1,66 +1,66 @@ -======================================================================== - MICROSOFT FOUNDATION CLASS LIBRARY : world_editor_fauna_graph_plugin -======================================================================== - - -AppWizard has created this world_editor_fauna_graph_plugin DLL for you. This DLL not only -demonstrates the basics of using the Microsoft Foundation classes but -is also a starting point for writing your DLL. - -This file contains a summary of what you will find in each of the files that -make up your world_editor_fauna_graph_plugin DLL. - -world_editor_fauna_graph_plugin.dsp - This file (the project file) contains information at the project level and - is used to build a single project or subproject. Other users can share the - project (.dsp) file, but they should export the makefiles locally. - -world_editor_fauna_graph_plugin.h - This is the main header file for the DLL. It declares the - CWorld_editor_fauna_graph_pluginApp class. - -world_editor_fauna_graph_plugin.cpp - This is the main DLL source file. It contains the class CWorld_editor_fauna_graph_pluginApp. - - -world_editor_fauna_graph_plugin.rc - This is a listing of all of the Microsoft Windows resources that the - program uses. It includes the icons, bitmaps, and cursors that are stored - in the RES subdirectory. This file can be directly edited in Microsoft - Visual C++. - -world_editor_fauna_graph_plugin.clw - This file contains information used by ClassWizard to edit existing - classes or add new classes. ClassWizard also uses this file to store - information needed to create and edit message maps and dialog data - maps and to create prototype member functions. - -res\world_editor_fauna_graph_plugin.rc2 - This file contains resources that are not edited by Microsoft - Visual C++. You should place all resources not editable by - the resource editor in this file. - -world_editor_fauna_graph_plugin.def - This file contains information about the DLL that must be - provided to run with Microsoft Windows. It defines parameters - such as the name and description of the DLL. It also exports - functions from the DLL. - -///////////////////////////////////////////////////////////////////////////// -Other standard files: - -StdAfx.h, StdAfx.cpp - These files are used to build a precompiled header (PCH) file - named world_editor_fauna_graph_plugin.pch and a precompiled types file named StdAfx.obj. - -Resource.h - This is the standard header file, which defines new resource IDs. - Microsoft Visual C++ reads and updates this file. - -///////////////////////////////////////////////////////////////////////////// -Other notes: - -AppWizard uses "TODO:" to indicate parts of the source code you -should add to or customize. - -///////////////////////////////////////////////////////////////////////////// +======================================================================== + MICROSOFT FOUNDATION CLASS LIBRARY : world_editor_fauna_graph_plugin +======================================================================== + + +AppWizard has created this world_editor_fauna_graph_plugin DLL for you. This DLL not only +demonstrates the basics of using the Microsoft Foundation classes but +is also a starting point for writing your DLL. + +This file contains a summary of what you will find in each of the files that +make up your world_editor_fauna_graph_plugin DLL. + +world_editor_fauna_graph_plugin.dsp + This file (the project file) contains information at the project level and + is used to build a single project or subproject. Other users can share the + project (.dsp) file, but they should export the makefiles locally. + +world_editor_fauna_graph_plugin.h + This is the main header file for the DLL. It declares the + CWorld_editor_fauna_graph_pluginApp class. + +world_editor_fauna_graph_plugin.cpp + This is the main DLL source file. It contains the class CWorld_editor_fauna_graph_pluginApp. + + +world_editor_fauna_graph_plugin.rc + This is a listing of all of the Microsoft Windows resources that the + program uses. It includes the icons, bitmaps, and cursors that are stored + in the RES subdirectory. This file can be directly edited in Microsoft + Visual C++. + +world_editor_fauna_graph_plugin.clw + This file contains information used by ClassWizard to edit existing + classes or add new classes. ClassWizard also uses this file to store + information needed to create and edit message maps and dialog data + maps and to create prototype member functions. + +res\world_editor_fauna_graph_plugin.rc2 + This file contains resources that are not edited by Microsoft + Visual C++. You should place all resources not editable by + the resource editor in this file. + +world_editor_fauna_graph_plugin.def + This file contains information about the DLL that must be + provided to run with Microsoft Windows. It defines parameters + such as the name and description of the DLL. It also exports + functions from the DLL. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named world_editor_fauna_graph_plugin.pch and a precompiled types file named StdAfx.obj. + +Resource.h + This is the standard header file, which defines new resource IDs. + Microsoft Visual C++ reads and updates this file. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + +///////////////////////////////////////////////////////////////////////////// diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/Resource.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/Resource.h index 53aeb6cc5..7130a2cf1 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/Resource.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/Resource.h @@ -1,37 +1,37 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by world_editor_fauna_graph_plugin.rc -// -#define IDR_FLAG_ICONS_TGA 2000 -#define IDC_DISPLAY_FLAGS 2000 -#define IDD_DIALOG_FLAGS 2001 -#define IDC_DISPLAY_INDICES 2001 -#define IDC_DISPLAY_TARGET_INDICES 2002 -#define IDC_DISPLAY_CONDITION 2003 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 2003 -#define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 2005 -#define _APS_NEXT_SYMED_VALUE 2000 -#endif -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by world_editor_fauna_graph_plugin.rc +// +#define IDR_FLAG_ICONS_TGA 2000 +#define IDC_DISPLAY_FLAGS 2000 +#define IDD_DIALOG_FLAGS 2001 +#define IDC_DISPLAY_INDICES 2001 +#define IDC_DISPLAY_TARGET_INDICES 2002 +#define IDC_DISPLAY_CONDITION 2003 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 2003 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 2005 +#define _APS_NEXT_SYMED_VALUE 2000 +#endif +#endif diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/StdAfx.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/StdAfx.cpp index 1afa35897..6ef68a0bc 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/StdAfx.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/StdAfx.cpp @@ -1,24 +1,24 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.cpp : source file that includes just the standard includes -// world_editor_fauna_graph_plugin.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.cpp : source file that includes just the standard includes +// world_editor_fauna_graph_plugin.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/StdAfx.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/StdAfx.h index 9693049a7..ce6eca86c 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/StdAfx.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/StdAfx.h @@ -1,62 +1,62 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__320B1AF7_B3A8_40AC_8147_12DCC86B3436__INCLUDED_) -#define AFX_STDAFX_H__320B1AF7_B3A8_40AC_8147_12DCC86B3436__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#define NOMINMAX -#define _WIN32_WINNT 0x0500 - -#include - -#include // MFC core and standard components -#include // MFC extensions - -#ifndef _AFX_NO_OLE_SUPPORT -#include // MFC OLE classes -#include // MFC OLE dialog classes -#include // MFC Automation classes -#endif // _AFX_NO_OLE_SUPPORT - - -#ifndef _AFX_NO_DB_SUPPORT -#include // MFC ODBC database classes -#endif // _AFX_NO_DB_SUPPORT - -#ifndef _AFX_NO_DAO_SUPPORT -#include // MFC DAO database classes -#endif // _AFX_NO_DAO_SUPPORT - -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__320B1AF7_B3A8_40AC_8147_12DCC86B3436__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__320B1AF7_B3A8_40AC_8147_12DCC86B3436__INCLUDED_) +#define AFX_STDAFX_H__320B1AF7_B3A8_40AC_8147_12DCC86B3436__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#define NOMINMAX +#define _WIN32_WINNT 0x0500 + +#include + +#include // MFC core and standard components +#include // MFC extensions + +#ifndef _AFX_NO_OLE_SUPPORT +#include // MFC OLE classes +#include // MFC OLE dialog classes +#include // MFC Automation classes +#endif // _AFX_NO_OLE_SUPPORT + + +#ifndef _AFX_NO_DB_SUPPORT +#include // MFC ODBC database classes +#endif // _AFX_NO_DB_SUPPORT + +#ifndef _AFX_NO_DAO_SUPPORT +#include // MFC DAO database classes +#endif // _AFX_NO_DAO_SUPPORT + +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__320B1AF7_B3A8_40AC_8147_12DCC86B3436__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/plugin.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/plugin.cpp index 577817016..9d59e797e 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/plugin.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/plugin.cpp @@ -1,392 +1,392 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" -#include "plugin.h" -#include "resource.h" -#include "DialogFlags.h" - - -using namespace NLMISC; - - -const std::string FAUNA_PLACE = "fauna_generic_place"; -const float ARROW_POS = 0.7f; -const float ARROW_WIDTH = 8.f; -const float ARROW_LENGTH = 20.f; -const float MIN_ARROW_LENGTH_BEFORE_SCALE = 4 * ARROW_LENGTH; -const NLMISC::CRGBA ARROW_COLOR(192, 168, 128, 255); -const sint FLAG_ICON_SIZE = 16; - -//**************************************************************** -CPlugin::CPlugin() : _PluginActive(true), _PluginAccess(NULL), _FaunaFlagIcons(NULL) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - _DialogFlags = new CDialogFlags(this); -} - -// *************************************************************************** -CPlugin::~CPlugin() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - if (_DialogFlags) - { - _DialogFlags->DestroyWindow(); - } - delete _DialogFlags; - if (_PluginAccess && _FaunaFlagIcons) - { - _PluginAccess->deleteTexture(_FaunaFlagIcons); - } -} - -// *************************************************************************** -bool CPlugin::isActive() -{ - return _PluginActive; -} - -// *************************************************************************** -std::string &CPlugin::getName() -{ - static std::string ret="Fauna graph"; - return ret; -} - -// *************************************************************************** -bool CPlugin::activatePlugin() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - if(!_PluginActive) - { - //_DialogFlag->ShowWindow(TRUE); - _PluginActive=true; - _DialogFlags->ShowWindow(SW_SHOW); - return true; - } - - return false; -} - -// *************************************************************************** -bool CPlugin::closePlugin() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - if(_PluginActive) - { - //_DialogFlag->ShowWindow(FALSE); - - _PluginActive=false; - _DialogFlags->ShowWindow(SW_HIDE); - return true; - } - return false; -} - -//**************************************************************** -void CPlugin::init(IPluginAccess *pluginAccess) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - std::vector classNames; - classNames.push_back(FAUNA_PLACE); - _PluginAccess = pluginAccess; - _PluginAccess->registerPrimitiveDisplayer(this, classNames); - // - _DialogFlags->Create(IDD_DIALOG_FLAGS, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); - _DialogFlags->ShowWindow(TRUE); -} - -//**************************************************************** -void CPlugin::drawPrimitive(const NLLIGO::IPrimitive *primitive, const TRenderContext &renderContext) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - nlassert(primitive); - // - _FaunaGroups.insert(primitive->getParent()); - // default drawing - // NB: default drawing isn't done by caller, because it is assumed - // that we, as a IPrimitveDisplayer, should do it. - renderContext.Display->primitiveRenderProxy(*primitive); -} - - -class CVertex -{ -public: - NLMISC::CVector Pos; - std::set Arcs; - bool ReachNext; -public: - void swap(CVertex &other) - { - std::swap(other.Pos, Pos); - std::swap(other.ReachNext, ReachNext); - Arcs.swap(other.Arcs); - } -}; - - -//**************************************************************** -void CPlugin::drawArrow(CDisplay &display, const NLMISC::CVector &start, const NLMISC::CVector &end) -{ - if (start == end) return; - NLMISC::CVector pixelArrow = ARROW_POS * end + (1.f - ARROW_POS) * start; - NLMISC::CVector I = (end- start).normed(); - NLMISC::CVector J(I.y, - I.x, 0.f); - display.pixelVectorToWorld(I); - display.pixelVectorToWorld(J); - display.lineRenderProxy(ARROW_COLOR, start, end, 0); - NLMISC::CVector pixelStart = start; - NLMISC::CVector pixelEnd = end; - display.worldToFloatPixel(pixelStart); - display.worldToFloatPixel(pixelEnd); - float arrowSizeFactor = 1.f; - float arrowLength = (pixelStart - pixelEnd).norm(); - if (arrowLength < MIN_ARROW_LENGTH_BEFORE_SCALE) - { - arrowSizeFactor = arrowLength / MIN_ARROW_LENGTH_BEFORE_SCALE; - } - display.triRenderProxy(ARROW_COLOR, pixelArrow + arrowSizeFactor * ARROW_WIDTH * J, pixelArrow + arrowSizeFactor * ARROW_LENGTH * I, pixelArrow - arrowSizeFactor * ARROW_WIDTH * J, 0); -} - - -//**************************************************************** -void CPlugin::pushIcon(CDisplay &display, sint stepX, sint stepY, NLMISC::CVector &currPos, uint srcX, uint srcY, const CPrimTexture &pt) -{ - CVector center = currPos; - display.worldToPixel(center); - CVector tl(center.x - FLAG_ICON_SIZE / 2, center.y + FLAG_ICON_SIZE / 2, 0.f); - CVector br(center.x + FLAG_ICON_SIZE / 2, center.y - FLAG_ICON_SIZE / 2, 0.f); - display.pixelToWorld(tl); - display.pixelToWorld(br); - NLMISC::CQuadColorUV quvc; - quvc.V0.set(tl.x, tl.y, 0.f); - quvc.V1.set(br.x, tl.y, 0.f); - quvc.V2.set(br.x, br.y, 0.f); - quvc.V3.set(tl.x, br.y, 0.f); - quvc.Color0 = quvc.Color1 = quvc.Color2 = quvc.Color3 = CRGBA::White; - if (pt.getWidth() == 0 || pt.getHeight() == 0) - { - // if texture width is 0, then texture hasn't been found, so display the whole 'not found' texture - quvc.Uv0.set(0.f, 0.f); - quvc.Uv1.set(1.f, 0.f); - quvc.Uv2.set(1.f, 1.f); - quvc.Uv3.set(0.f, 1.f); - } - else - { - float invWidth = 1.f / pt.getWidth(); - float invHeight = 1.f / pt.getHeight(); - srcX *= FLAG_ICON_SIZE; - srcY *= FLAG_ICON_SIZE; - quvc.Uv0.set(srcX * invWidth, srcY * invHeight); - quvc.Uv1.set((srcX + FLAG_ICON_SIZE) * invWidth, srcY * invHeight); - quvc.Uv2.set((srcX + FLAG_ICON_SIZE) * invWidth, (srcY + FLAG_ICON_SIZE) * invHeight); - quvc.Uv3.set(srcX * invWidth, (srcY + FLAG_ICON_SIZE) * invHeight); - } - display.texQuadRenderProxy(quvc, 0); - center.x += (float) stepX; - center.y += (float) stepY; - currPos = center; - display.pixelToWorld(currPos); -} - -typedef std::multimap TVertMap; - - -//**************************************************************** -void CPlugin::drawFaunaGraph(CDisplay &display, const NLLIGO::IPrimitive &grp) -{ - if (_DialogFlags->DisplayCondition == CDialogFlags::DisplayWhenSelected) - { - if (!_PluginAccess->isSelected(grp)) - { - // if group is not selected, then see if at least one child is selected - bool found = false; - for(uint k = 0; k < grp.getNumChildren(); ++k) - { - const NLLIGO::IPrimitive *child; - if (!grp.getChild(child, k)) continue; - std::string className; - if (!child->getPropertyByName("class", className)) continue; - if (NLMISC::toLower(className) != FAUNA_PLACE) continue; - if (_PluginAccess->isSelected(*child)) - { - found = true; - break; - } - } - if (!found) return; - } - } - TVertMap vertices; - for(uint k = 0; k < grp.getNumChildren(); ++k) - { - const NLLIGO::IPrimitive *child; - if (!grp.getChild(child, k)) continue; - std::string className; - if (!child->getPropertyByName("class", className)) continue; - if (NLMISC::toLower(className) != FAUNA_PLACE) continue; - std::string indexStr; - int index; - if (!child->getPropertyByName("index", indexStr)) continue; - if (sscanf(indexStr.c_str(), "%d", &index) != 1) continue; - CVector pos = child->getPrimVector()[0]; - CVertex vertex; - vertex.Pos = pos; - vertex.ReachNext = false; - std::string reachableIndicesUniqueStr; - if (!child->getPropertyByName("index_next", reachableIndicesUniqueStr)) continue; - std::vector reachableIndicesStr; - NLMISC::explode(reachableIndicesUniqueStr, std::string(","), reachableIndicesStr); - for(uint k = 0; k < reachableIndicesStr.size(); ++k) - { - if (NLMISC::nlstricmp(reachableIndicesStr[k], "next") == 0) - { - vertex.ReachNext = true; - } - int currentIndex; - if (sscanf(reachableIndicesStr[k].c_str(), "%d", ¤tIndex) != 1) continue; - vertex.Arcs.insert((uint) currentIndex); - } - TVertMap::iterator it = vertices.insert(TVertMap::value_type(index, CVertex())); - it->second.swap(vertex); - // write index for current vertex - CVector textPos = pos; - display.worldToPixel(textPos); - if (_DialogFlags->m_DisplayIndices) - { - display.print(toString(index), textPos.x + 4, textPos.y, 12, CRGBA::White, CDisplay::MiddleLeft); - } - if (_DialogFlags->m_DisplayTargetIndices) - { - std::string nextIndices; - display.print('(' + reachableIndicesUniqueStr + ')', textPos.x, textPos.y - 8, 12, CRGBA::White, CDisplay::MiddleTop); - } - // display icons depending on flags - if (_FaunaFlagIcons && _DialogFlags->m_DisplayFlags) - { - CVector delta(- FLAG_ICON_SIZE / 2.f - 2, 0.f, 0.f); - display.pixelVectorToWorld(delta); - pos += delta; - std::string flag; - child->getPropertyByName("flag_spawn", flag); - if (flag == "true") pushIcon(display, - FLAG_ICON_SIZE, 0, pos, 0, 0, *_FaunaFlagIcons); - child->getPropertyByName("flag_food", flag); - if (flag == "true") pushIcon(display, - FLAG_ICON_SIZE, 0, pos, 1, 0, *_FaunaFlagIcons); - child->getPropertyByName("flag_rest", flag); - if (flag == "true") pushIcon(display, - FLAG_ICON_SIZE, 0, pos, 2, 0, *_FaunaFlagIcons); - } - } - for(TVertMap::const_iterator it = vertices.begin(); it != vertices.end(); ++it) - { - const CVertex &vertex = it->second; - if (vertex.ReachNext) - { - // find next vertex with highest index, else loop to first index - TVertMap::const_iterator nextIt = it; - do - { - ++ nextIt; - if (nextIt == vertices.end()) - { - nextIt = vertices.begin(); - if (nextIt != it && nextIt->first != it->first) - { - uint firstIndex = nextIt->first; - do - { - drawArrow(display, vertex.Pos, nextIt->second.Pos); - ++nextIt ; - } - while (nextIt->first == firstIndex); - break; - } - } - if (nextIt->first > it->first) - { - uint wantedIndex = nextIt->first; - do - { - drawArrow(display, vertex.Pos, nextIt->second.Pos); - ++ nextIt; - } - while (nextIt != vertices.end() && nextIt->first == wantedIndex); - break; - } - } - while (nextIt != it); - } - for(std::set::const_iterator it = vertex.Arcs.begin(); it != vertex.Arcs.end(); ++it) - { - TVertMap::const_iterator first = vertices.lower_bound(*it); - TVertMap::const_iterator last = vertices.upper_bound(*it); - for (TVertMap::const_iterator targetIt = first; targetIt != last; ++targetIt) - { - drawArrow(display, vertex.Pos, targetIt->second.Pos); - } - } - } -} - -//**************************************************************** -void CPlugin::postRender(CDisplay &display) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - if (_DialogFlags->DisplayCondition == CDialogFlags::DisplayOff) return; - // Init icon texture if not already done - if (!_FaunaFlagIcons) - { - // TODO nico This code is duplicated with world_editor_shard_monitor - static bool createFailed = false; - if (createFailed) return; - HRSRC rsc = FindResource(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_FLAG_ICONS_TGA), "TGA"); - if (rsc == NULL) - { - DWORD lastError = GetLastError(); - createFailed = true; - return; - } - NLMISC::CBitmap bm; - if (!_PluginAccess->buildNLBitmapFromTGARsc(rsc, AfxGetInstanceHandle(), bm)) - { - createFailed = true; - return; - } - _FaunaFlagIcons = _PluginAccess->createTexture(); - nlassert(_FaunaFlagIcons); - _FaunaFlagIcons->buildFromNLBitmap(bm); - } - display.flush(); // must flush before we assign a next texture - display.setLayerTexture(0, _FaunaFlagIcons); - // for each fauna group parent, draw graph of its sons - for(std::set::iterator it = _FaunaGroups.begin(); it != _FaunaGroups.end(); ++it) - { - nlassert(*it); - drawFaunaGraph(display, **it); - } - _FaunaGroups.clear(); -} - - - -extern "C" -{ - void *createPlugin() - { - return new CPlugin(); - } -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" +#include "plugin.h" +#include "resource.h" +#include "DialogFlags.h" + + +using namespace NLMISC; + + +const std::string FAUNA_PLACE = "fauna_generic_place"; +const float ARROW_POS = 0.7f; +const float ARROW_WIDTH = 8.f; +const float ARROW_LENGTH = 20.f; +const float MIN_ARROW_LENGTH_BEFORE_SCALE = 4 * ARROW_LENGTH; +const NLMISC::CRGBA ARROW_COLOR(192, 168, 128, 255); +const sint FLAG_ICON_SIZE = 16; + +//**************************************************************** +CPlugin::CPlugin() : _PluginActive(true), _PluginAccess(NULL), _FaunaFlagIcons(NULL) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + _DialogFlags = new CDialogFlags(this); +} + +// *************************************************************************** +CPlugin::~CPlugin() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + if (_DialogFlags) + { + _DialogFlags->DestroyWindow(); + } + delete _DialogFlags; + if (_PluginAccess && _FaunaFlagIcons) + { + _PluginAccess->deleteTexture(_FaunaFlagIcons); + } +} + +// *************************************************************************** +bool CPlugin::isActive() +{ + return _PluginActive; +} + +// *************************************************************************** +std::string &CPlugin::getName() +{ + static std::string ret="Fauna graph"; + return ret; +} + +// *************************************************************************** +bool CPlugin::activatePlugin() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + if(!_PluginActive) + { + //_DialogFlag->ShowWindow(TRUE); + _PluginActive=true; + _DialogFlags->ShowWindow(SW_SHOW); + return true; + } + + return false; +} + +// *************************************************************************** +bool CPlugin::closePlugin() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + if(_PluginActive) + { + //_DialogFlag->ShowWindow(FALSE); + + _PluginActive=false; + _DialogFlags->ShowWindow(SW_HIDE); + return true; + } + return false; +} + +//**************************************************************** +void CPlugin::init(IPluginAccess *pluginAccess) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + std::vector classNames; + classNames.push_back(FAUNA_PLACE); + _PluginAccess = pluginAccess; + _PluginAccess->registerPrimitiveDisplayer(this, classNames); + // + _DialogFlags->Create(IDD_DIALOG_FLAGS, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); + _DialogFlags->ShowWindow(TRUE); +} + +//**************************************************************** +void CPlugin::drawPrimitive(const NLLIGO::IPrimitive *primitive, const TRenderContext &renderContext) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + nlassert(primitive); + // + _FaunaGroups.insert(primitive->getParent()); + // default drawing + // NB: default drawing isn't done by caller, because it is assumed + // that we, as a IPrimitveDisplayer, should do it. + renderContext.Display->primitiveRenderProxy(*primitive); +} + + +class CVertex +{ +public: + NLMISC::CVector Pos; + std::set Arcs; + bool ReachNext; +public: + void swap(CVertex &other) + { + std::swap(other.Pos, Pos); + std::swap(other.ReachNext, ReachNext); + Arcs.swap(other.Arcs); + } +}; + + +//**************************************************************** +void CPlugin::drawArrow(CDisplay &display, const NLMISC::CVector &start, const NLMISC::CVector &end) +{ + if (start == end) return; + NLMISC::CVector pixelArrow = ARROW_POS * end + (1.f - ARROW_POS) * start; + NLMISC::CVector I = (end- start).normed(); + NLMISC::CVector J(I.y, - I.x, 0.f); + display.pixelVectorToWorld(I); + display.pixelVectorToWorld(J); + display.lineRenderProxy(ARROW_COLOR, start, end, 0); + NLMISC::CVector pixelStart = start; + NLMISC::CVector pixelEnd = end; + display.worldToFloatPixel(pixelStart); + display.worldToFloatPixel(pixelEnd); + float arrowSizeFactor = 1.f; + float arrowLength = (pixelStart - pixelEnd).norm(); + if (arrowLength < MIN_ARROW_LENGTH_BEFORE_SCALE) + { + arrowSizeFactor = arrowLength / MIN_ARROW_LENGTH_BEFORE_SCALE; + } + display.triRenderProxy(ARROW_COLOR, pixelArrow + arrowSizeFactor * ARROW_WIDTH * J, pixelArrow + arrowSizeFactor * ARROW_LENGTH * I, pixelArrow - arrowSizeFactor * ARROW_WIDTH * J, 0); +} + + +//**************************************************************** +void CPlugin::pushIcon(CDisplay &display, sint stepX, sint stepY, NLMISC::CVector &currPos, uint srcX, uint srcY, const CPrimTexture &pt) +{ + CVector center = currPos; + display.worldToPixel(center); + CVector tl(center.x - FLAG_ICON_SIZE / 2, center.y + FLAG_ICON_SIZE / 2, 0.f); + CVector br(center.x + FLAG_ICON_SIZE / 2, center.y - FLAG_ICON_SIZE / 2, 0.f); + display.pixelToWorld(tl); + display.pixelToWorld(br); + NLMISC::CQuadColorUV quvc; + quvc.V0.set(tl.x, tl.y, 0.f); + quvc.V1.set(br.x, tl.y, 0.f); + quvc.V2.set(br.x, br.y, 0.f); + quvc.V3.set(tl.x, br.y, 0.f); + quvc.Color0 = quvc.Color1 = quvc.Color2 = quvc.Color3 = CRGBA::White; + if (pt.getWidth() == 0 || pt.getHeight() == 0) + { + // if texture width is 0, then texture hasn't been found, so display the whole 'not found' texture + quvc.Uv0.set(0.f, 0.f); + quvc.Uv1.set(1.f, 0.f); + quvc.Uv2.set(1.f, 1.f); + quvc.Uv3.set(0.f, 1.f); + } + else + { + float invWidth = 1.f / pt.getWidth(); + float invHeight = 1.f / pt.getHeight(); + srcX *= FLAG_ICON_SIZE; + srcY *= FLAG_ICON_SIZE; + quvc.Uv0.set(srcX * invWidth, srcY * invHeight); + quvc.Uv1.set((srcX + FLAG_ICON_SIZE) * invWidth, srcY * invHeight); + quvc.Uv2.set((srcX + FLAG_ICON_SIZE) * invWidth, (srcY + FLAG_ICON_SIZE) * invHeight); + quvc.Uv3.set(srcX * invWidth, (srcY + FLAG_ICON_SIZE) * invHeight); + } + display.texQuadRenderProxy(quvc, 0); + center.x += (float) stepX; + center.y += (float) stepY; + currPos = center; + display.pixelToWorld(currPos); +} + +typedef std::multimap TVertMap; + + +//**************************************************************** +void CPlugin::drawFaunaGraph(CDisplay &display, const NLLIGO::IPrimitive &grp) +{ + if (_DialogFlags->DisplayCondition == CDialogFlags::DisplayWhenSelected) + { + if (!_PluginAccess->isSelected(grp)) + { + // if group is not selected, then see if at least one child is selected + bool found = false; + for(uint k = 0; k < grp.getNumChildren(); ++k) + { + const NLLIGO::IPrimitive *child; + if (!grp.getChild(child, k)) continue; + std::string className; + if (!child->getPropertyByName("class", className)) continue; + if (NLMISC::toLower(className) != FAUNA_PLACE) continue; + if (_PluginAccess->isSelected(*child)) + { + found = true; + break; + } + } + if (!found) return; + } + } + TVertMap vertices; + for(uint k = 0; k < grp.getNumChildren(); ++k) + { + const NLLIGO::IPrimitive *child; + if (!grp.getChild(child, k)) continue; + std::string className; + if (!child->getPropertyByName("class", className)) continue; + if (NLMISC::toLower(className) != FAUNA_PLACE) continue; + std::string indexStr; + int index; + if (!child->getPropertyByName("index", indexStr)) continue; + if (sscanf(indexStr.c_str(), "%d", &index) != 1) continue; + CVector pos = child->getPrimVector()[0]; + CVertex vertex; + vertex.Pos = pos; + vertex.ReachNext = false; + std::string reachableIndicesUniqueStr; + if (!child->getPropertyByName("index_next", reachableIndicesUniqueStr)) continue; + std::vector reachableIndicesStr; + NLMISC::explode(reachableIndicesUniqueStr, std::string(","), reachableIndicesStr); + for(uint k = 0; k < reachableIndicesStr.size(); ++k) + { + if (NLMISC::nlstricmp(reachableIndicesStr[k], "next") == 0) + { + vertex.ReachNext = true; + } + int currentIndex; + if (sscanf(reachableIndicesStr[k].c_str(), "%d", ¤tIndex) != 1) continue; + vertex.Arcs.insert((uint) currentIndex); + } + TVertMap::iterator it = vertices.insert(TVertMap::value_type(index, CVertex())); + it->second.swap(vertex); + // write index for current vertex + CVector textPos = pos; + display.worldToPixel(textPos); + if (_DialogFlags->m_DisplayIndices) + { + display.print(toString(index), textPos.x + 4, textPos.y, 12, CRGBA::White, CDisplay::MiddleLeft); + } + if (_DialogFlags->m_DisplayTargetIndices) + { + std::string nextIndices; + display.print('(' + reachableIndicesUniqueStr + ')', textPos.x, textPos.y - 8, 12, CRGBA::White, CDisplay::MiddleTop); + } + // display icons depending on flags + if (_FaunaFlagIcons && _DialogFlags->m_DisplayFlags) + { + CVector delta(- FLAG_ICON_SIZE / 2.f - 2, 0.f, 0.f); + display.pixelVectorToWorld(delta); + pos += delta; + std::string flag; + child->getPropertyByName("flag_spawn", flag); + if (flag == "true") pushIcon(display, - FLAG_ICON_SIZE, 0, pos, 0, 0, *_FaunaFlagIcons); + child->getPropertyByName("flag_food", flag); + if (flag == "true") pushIcon(display, - FLAG_ICON_SIZE, 0, pos, 1, 0, *_FaunaFlagIcons); + child->getPropertyByName("flag_rest", flag); + if (flag == "true") pushIcon(display, - FLAG_ICON_SIZE, 0, pos, 2, 0, *_FaunaFlagIcons); + } + } + for(TVertMap::const_iterator it = vertices.begin(); it != vertices.end(); ++it) + { + const CVertex &vertex = it->second; + if (vertex.ReachNext) + { + // find next vertex with highest index, else loop to first index + TVertMap::const_iterator nextIt = it; + do + { + ++ nextIt; + if (nextIt == vertices.end()) + { + nextIt = vertices.begin(); + if (nextIt != it && nextIt->first != it->first) + { + uint firstIndex = nextIt->first; + do + { + drawArrow(display, vertex.Pos, nextIt->second.Pos); + ++nextIt ; + } + while (nextIt->first == firstIndex); + break; + } + } + if (nextIt->first > it->first) + { + uint wantedIndex = nextIt->first; + do + { + drawArrow(display, vertex.Pos, nextIt->second.Pos); + ++ nextIt; + } + while (nextIt != vertices.end() && nextIt->first == wantedIndex); + break; + } + } + while (nextIt != it); + } + for(std::set::const_iterator it = vertex.Arcs.begin(); it != vertex.Arcs.end(); ++it) + { + TVertMap::const_iterator first = vertices.lower_bound(*it); + TVertMap::const_iterator last = vertices.upper_bound(*it); + for (TVertMap::const_iterator targetIt = first; targetIt != last; ++targetIt) + { + drawArrow(display, vertex.Pos, targetIt->second.Pos); + } + } + } +} + +//**************************************************************** +void CPlugin::postRender(CDisplay &display) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + if (_DialogFlags->DisplayCondition == CDialogFlags::DisplayOff) return; + // Init icon texture if not already done + if (!_FaunaFlagIcons) + { + // TODO nico This code is duplicated with world_editor_shard_monitor + static bool createFailed = false; + if (createFailed) return; + HRSRC rsc = FindResource(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_FLAG_ICONS_TGA), "TGA"); + if (rsc == NULL) + { + DWORD lastError = GetLastError(); + createFailed = true; + return; + } + NLMISC::CBitmap bm; + if (!_PluginAccess->buildNLBitmapFromTGARsc(rsc, AfxGetInstanceHandle(), bm)) + { + createFailed = true; + return; + } + _FaunaFlagIcons = _PluginAccess->createTexture(); + nlassert(_FaunaFlagIcons); + _FaunaFlagIcons->buildFromNLBitmap(bm); + } + display.flush(); // must flush before we assign a next texture + display.setLayerTexture(0, _FaunaFlagIcons); + // for each fauna group parent, draw graph of its sons + for(std::set::iterator it = _FaunaGroups.begin(); it != _FaunaGroups.end(); ++it) + { + nlassert(*it); + drawFaunaGraph(display, **it); + } + _FaunaGroups.clear(); +} + + + +extern "C" +{ + void *createPlugin() + { + return new CPlugin(); + } +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/plugin.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/plugin.h index 66234d3a8..6802649db 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/plugin.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/plugin.h @@ -1,87 +1,87 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef PLUGIN_H -#define PLUGIN_H - -#include "../world_editor/plugin_interface.h" -#include - - - -class CDialogFlags; - -class CPlugin : public IPluginCallback, - public IPrimitiveDisplayer -{ -public: - CPlugin(); - ~CPlugin(); - // from IPluginCallback - virtual void init(IPluginAccess *pluginAccess); - virtual void primitiveChanged(const NLLIGO::IPrimitive *root) {} - virtual void positionMoved(const NLMISC::CVector &position) {} - virtual void lostPositionControl() {} - virtual void onIdle() {} - virtual void postRender(CDisplay &display); - virtual std::string& getName(); - virtual bool isActive(); - virtual bool activatePlugin(); - virtual bool closePlugin(); - // from IPrimitiveDisplayer - virtual void drawPrimitive(const NLLIGO::IPrimitive *primitive, const TRenderContext &renderContext); - IPluginAccess *getPluginAccess() const { return _PluginAccess; } - // -private: - std::set _FaunaGroups; - bool _PluginActive; - private: - IPluginAccess *_PluginAccess; - NL3D::CTextContext _TextContext; - CPrimTexture *_FaunaFlagIcons; - CDialogFlags *_DialogFlags; -private: - void drawArrow(CDisplay &display, const NLMISC::CVector &start, const NLMISC::CVector &end); - void drawFaunaGraph(CDisplay &display, const NLLIGO::IPrimitive &grp); - void pushIcon(CDisplay &display, sint stepX, sint stepY, NLMISC::CVector &currPos, uint srcX, uint srcY, const CPrimTexture &pt); -}; - - - - -extern "C" -{ - /// Export the C factory method for dynamic linking.. - __declspec( dllexport ) void *createPlugin(); -} - - - - - - - - - - - - - - - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef PLUGIN_H +#define PLUGIN_H + +#include "../world_editor/plugin_interface.h" +#include + + + +class CDialogFlags; + +class CPlugin : public IPluginCallback, + public IPrimitiveDisplayer +{ +public: + CPlugin(); + ~CPlugin(); + // from IPluginCallback + virtual void init(IPluginAccess *pluginAccess); + virtual void primitiveChanged(const NLLIGO::IPrimitive *root) {} + virtual void positionMoved(const NLMISC::CVector &position) {} + virtual void lostPositionControl() {} + virtual void onIdle() {} + virtual void postRender(CDisplay &display); + virtual std::string& getName(); + virtual bool isActive(); + virtual bool activatePlugin(); + virtual bool closePlugin(); + // from IPrimitiveDisplayer + virtual void drawPrimitive(const NLLIGO::IPrimitive *primitive, const TRenderContext &renderContext); + IPluginAccess *getPluginAccess() const { return _PluginAccess; } + // +private: + std::set _FaunaGroups; + bool _PluginActive; + private: + IPluginAccess *_PluginAccess; + NL3D::CTextContext _TextContext; + CPrimTexture *_FaunaFlagIcons; + CDialogFlags *_DialogFlags; +private: + void drawArrow(CDisplay &display, const NLMISC::CVector &start, const NLMISC::CVector &end); + void drawFaunaGraph(CDisplay &display, const NLLIGO::IPrimitive &grp); + void pushIcon(CDisplay &display, sint stepX, sint stepY, NLMISC::CVector &currPos, uint srcX, uint srcY, const CPrimTexture &pt); +}; + + + + +extern "C" +{ + /// Export the C factory method for dynamic linking.. + __declspec( dllexport ) void *createPlugin(); +} + + + + + + + + + + + + + + + + + #endif \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/world_editor_fauna_graph_plugin.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/world_editor_fauna_graph_plugin.cpp index cb1958225..bdaca4abd 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/world_editor_fauna_graph_plugin.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/world_editor_fauna_graph_plugin.cpp @@ -1,72 +1,72 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// world_editor_fauna_graph_plugin.cpp : Defines the initialization routines for the DLL. -// - -#include "stdafx.h" -#include "world_editor_fauna_graph_plugin.h" - -// -// Note! -// -// If this DLL is dynamically linked against the MFC -// DLLs, any functions exported from this DLL which -// call into MFC must have the AFX_MANAGE_STATE macro -// added at the very beginning of the function. -// -// For example: -// -// extern "C" BOOL PASCAL EXPORT ExportedFunction() -// { -// AFX_MANAGE_STATE(AfxGetStaticModuleState()); -// // normal function body here -// } -// -// It is very important that this macro appear in each -// function, prior to any calls into MFC. This means that -// it must appear as the first statement within the -// function, even before any object variable declarations -// as their constructors may generate calls into the MFC -// DLL. -// -// Please see MFC Technical Notes 33 and 58 for additional -// details. -// - -///////////////////////////////////////////////////////////////////////////// -// CWorld_editor_fauna_graph_pluginApp - -BEGIN_MESSAGE_MAP(CWorld_editor_fauna_graph_pluginApp, CWinApp) - //{{AFX_MSG_MAP(CWorld_editor_fauna_graph_pluginApp) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code! - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CWorld_editor_fauna_graph_pluginApp construction - -CWorld_editor_fauna_graph_pluginApp::CWorld_editor_fauna_graph_pluginApp() -{ - // TODO: add construction code here, - // Place all significant initialization in InitInstance -} - -///////////////////////////////////////////////////////////////////////////// -// The one and only CWorld_editor_fauna_graph_pluginApp object - -CWorld_editor_fauna_graph_pluginApp theApp; +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// world_editor_fauna_graph_plugin.cpp : Defines the initialization routines for the DLL. +// + +#include "stdafx.h" +#include "world_editor_fauna_graph_plugin.h" + +// +// Note! +// +// If this DLL is dynamically linked against the MFC +// DLLs, any functions exported from this DLL which +// call into MFC must have the AFX_MANAGE_STATE macro +// added at the very beginning of the function. +// +// For example: +// +// extern "C" BOOL PASCAL EXPORT ExportedFunction() +// { +// AFX_MANAGE_STATE(AfxGetStaticModuleState()); +// // normal function body here +// } +// +// It is very important that this macro appear in each +// function, prior to any calls into MFC. This means that +// it must appear as the first statement within the +// function, even before any object variable declarations +// as their constructors may generate calls into the MFC +// DLL. +// +// Please see MFC Technical Notes 33 and 58 for additional +// details. +// + +///////////////////////////////////////////////////////////////////////////// +// CWorld_editor_fauna_graph_pluginApp + +BEGIN_MESSAGE_MAP(CWorld_editor_fauna_graph_pluginApp, CWinApp) + //{{AFX_MSG_MAP(CWorld_editor_fauna_graph_pluginApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CWorld_editor_fauna_graph_pluginApp construction + +CWorld_editor_fauna_graph_pluginApp::CWorld_editor_fauna_graph_pluginApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CWorld_editor_fauna_graph_pluginApp object + +CWorld_editor_fauna_graph_pluginApp theApp; diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/world_editor_fauna_graph_plugin.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/world_editor_fauna_graph_plugin.h index 6b382fcb4..a494fb21f 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/world_editor_fauna_graph_plugin.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_fauna_graph_plugin/world_editor_fauna_graph_plugin.h @@ -1,61 +1,61 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// world_editor_fauna_graph_plugin.h : main header file for the WORLD_EDITOR_FAUNA_GRAPH_PLUGIN DLL -// - -#if !defined(AFX_WORLD_EDITOR_FAUNA_GRAPH_PLUGIN_H__4130FBAA_31C2_4AF1_BF3C_175AFE9995DB__INCLUDED_) -#define AFX_WORLD_EDITOR_FAUNA_GRAPH_PLUGIN_H__4130FBAA_31C2_4AF1_BF3C_175AFE9995DB__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including this file for PCH -#endif - -#include "resource.h" // main symbols - -///////////////////////////////////////////////////////////////////////////// -// CWorld_editor_fauna_graph_pluginApp -// See world_editor_fauna_graph_plugin.cpp for the implementation of this class -// - -class CWorld_editor_fauna_graph_pluginApp : public CWinApp -{ -public: - CWorld_editor_fauna_graph_pluginApp(); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CWorld_editor_fauna_graph_pluginApp) - //}}AFX_VIRTUAL - - //{{AFX_MSG(CWorld_editor_fauna_graph_pluginApp) - // NOTE - the ClassWizard will add and remove member functions here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_WORLD_EDITOR_FAUNA_GRAPH_PLUGIN_H__4130FBAA_31C2_4AF1_BF3C_175AFE9995DB__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// world_editor_fauna_graph_plugin.h : main header file for the WORLD_EDITOR_FAUNA_GRAPH_PLUGIN DLL +// + +#if !defined(AFX_WORLD_EDITOR_FAUNA_GRAPH_PLUGIN_H__4130FBAA_31C2_4AF1_BF3C_175AFE9995DB__INCLUDED_) +#define AFX_WORLD_EDITOR_FAUNA_GRAPH_PLUGIN_H__4130FBAA_31C2_4AF1_BF3C_175AFE9995DB__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CWorld_editor_fauna_graph_pluginApp +// See world_editor_fauna_graph_plugin.cpp for the implementation of this class +// + +class CWorld_editor_fauna_graph_pluginApp : public CWinApp +{ +public: + CWorld_editor_fauna_graph_pluginApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CWorld_editor_fauna_graph_pluginApp) + //}}AFX_VIRTUAL + + //{{AFX_MSG(CWorld_editor_fauna_graph_pluginApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_WORLD_EDITOR_FAUNA_GRAPH_PLUGIN_H__4130FBAA_31C2_4AF1_BF3C_175AFE9995DB__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/StdAfx.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/StdAfx.cpp index 0313de3fa..bddc75270 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/StdAfx.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/StdAfx.cpp @@ -1,24 +1,24 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.cpp : source file that includes just the standard includes -// world_editor_graph_plugin.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.cpp : source file that includes just the standard includes +// world_editor_graph_plugin.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/StdAfx.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/StdAfx.h index 3b63009a8..1d240ae08 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/StdAfx.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/StdAfx.h @@ -1,50 +1,50 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__4CC93548_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_) -#define AFX_STDAFX_H__4CC93548_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#define NOMINMAX -#define _WIN32_WINNT 0x0500 - -#include - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC Automation classes -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls - -#include - -#endif // _AFX_NO_AFXCMN_SUPPORT - - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__4CC93548_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__4CC93548_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_) +#define AFX_STDAFX_H__4CC93548_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#define NOMINMAX +#define _WIN32_WINNT 0x0500 + +#include + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls + +#include + +#endif // _AFX_NO_AFXCMN_SUPPORT + + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__4CC93548_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/graph_plugin.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/graph_plugin.cpp index 92f145510..048678b14 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/graph_plugin.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/graph_plugin.cpp @@ -1,946 +1,946 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// graph_plugin.cpp: implementation of the CGraphPlugin class. -// -////////////////////////////////////////////////////////////////////// - -#include "stdafx.h" - -#include "nel/misc/types_nl.h" -#include "nel/misc/bitmap.h" -#include "graph_plugin.h" -#include -#include -#include "nel/ligo/primitive_utils.h" -#include "../../../leveldesign/mission_compiler_lib/mission_compiler.h" -#include "nel/misc/i18n.h" -#include -#include - -using namespace NLMISC; -using namespace NLLIGO; -using namespace NLNET; -using namespace std; - -class CDatabaseLocator; - -CFileDisplayer *GraphPluginLogDisplayer= NULL; - -// vl: important to add the next line or AfxGetApp() will returns 0 after AFX_MANAGE_STATE(AfxGetStaticModuleState()); -CWinApp theApp; - -////////////////////////////////////////////////////////////////////// -// Construction/Destruction -////////////////////////////////////////////////////////////////////// - -extern "C" -{ - void *createPlugin() - { - return new CGraphPlugin(); - } -} - -CGraphPlugin::CGraphPlugin() -{ - NLMISC::createDebug(); - - GraphPluginLogDisplayer= new CFileDisplayer("world_editor_graph_plugin.log", true, "WORLD_EDITOR_GRAPH_PLUGIN.LOG"); - DebugLog->addDisplayer (GraphPluginLogDisplayer); - InfoLog->addDisplayer (GraphPluginLogDisplayer); - WarningLog->addDisplayer (GraphPluginLogDisplayer); - ErrorLog->addDisplayer (GraphPluginLogDisplayer); - AssertLog->addDisplayer (GraphPluginLogDisplayer); - - nlinfo("Starting graph plugin..."); - GraphDlg=new CWorldEditorGraphPluginDlg(); -} - -CGraphPlugin::~CGraphPlugin() -{ - delete [] GraphDlg; -} - -void CGraphPlugin::init(IPluginAccess *pluginAccess) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - AfxEnableControlContainer(); - - _PluginAccess = pluginAccess; - - _Name="mission_graph"; - - GraphDlg->Create(IDD_WORLDEDITORGRAPHPLUGIN_DIALOG, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); - GraphDlg->ShowWindow(TRUE); - GraphDlg->init(this); - _PluginActive=true; - - // Retreive the dot exe path - CConfigFile::CVar *dotPath = pluginAccess->getConfigFile().getVarPtr("DotPath"); - nlinfo("%s", dotPath->asString().c_str()); - if (dotPath) - { - _DotPath = CPath::getFullPath(dotPath->asString(), false); - nlinfo("%s", _DotPath.c_str()); - } - else - { - // use default configuration - nlwarning("graph_plugin : Can't find configuration variable 'DotPath', using 'dot/dot.exe' instead"); - _DotPath = CPath::getFullPath("dot/dot.exe", false); - } -} - - -/// The current region has changed. -//void CSoundPlugin::primRegionChanged(const std::vector ®ions) -void CGraphPlugin::primitiveChanged(const NLLIGO::IPrimitive *root) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); -} - - -void CGraphPlugin::positionMoved(const NLMISC::CVector &position) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); -} - -void CGraphPlugin::lostPositionControl() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); -} - - -void CGraphPlugin::onIdle() -{ -} - -void CGraphPlugin::refreshPrimitives() -{ - // get the current selection - const list &selection = _PluginAccess->getCurrentSelection(); - - if (selection.empty()) - return; - - TPrimitiveClassPredicate pred("mission_tree"); - // for each selected node, look for an interesting class - list::const_iterator first(selection.begin()), last(selection.end()),curIte; - IPrimitive* missionTreeRoot=(*first); - CPrimitiveSet offsprings; - TPrimitiveSet resltOffspring; - offsprings.buildSet(missionTreeRoot,pred,resltOffspring); - - vector vectSel;//vector of faulty mission element (sent by the mission compiler) - - if ((pred(missionTreeRoot))|| - ((missionTreeRoot=getPrimitiveParent((*first),pred))!=NULL)|| - ((!resltOffspring.empty())&&(missionTreeRoot=*resltOffspring.begin()))) - { - // ok, we find a good node - try - { - - - IPrimitive *rootNode = missionTreeRoot; - while (rootNode->getParent()) - rootNode = rootNode->getParent(); - string fileName = _PluginAccess->getRootFileName(rootNode); - - CMissionCompiler mc; - mc.compileMission(missionTreeRoot, NLMISC::CFile::getFilename(fileName)); - TMissionDataPtr md = mc.getMission(0); - string dot = md->generateDotScript(); - - string tmpPath = string(::getenv("TEMP")); - FILE *fp = fopen ((tmpPath+"/lang.dot").c_str(), "wt"); - if (!fp) - { - string msg("Can't write script file '"); - msg += tmpPath+"/lang.dot'"; - AfxMessageBox(msg.c_str()); - } - else - { - fwrite(dot.data(), dot.size(), 1, fp); - fclose(fp); -// NLMISC::CI18N::writeTextFile(tmpPath+"/lang.dot", dot, true); - NLMISC::CFile::deleteFile(tmpPath+"/output.png"); - NLMISC::CFile::deleteFile(tmpPath+"/output.imap"); - system((_DotPath+" "+tmpPath+"/lang.dot -Tpng -o "+tmpPath+"/output.png").c_str()); - system((_DotPath+" "+tmpPath+"/lang.dot -Timap -o "+tmpPath+"/output.imap").c_str()); - - //currently using output.png as the input file... - if(!createBitmap(tmpPath)) - AfxMessageBox("BEWARE: the image couldn't be loaded."); - } - - while (missionTreeRoot->getParent()!=NULL) - { - missionTreeRoot=missionTreeRoot->getParent(); - } - _rootFileName=_PluginAccess->getRootFileName(missionTreeRoot); - } - catch(EParseException &e) - { - string err = e.Why; - if (e.Primitive != NULL) - { - string primName; - - vectSel.push_back(e.Primitive); - e.Primitive->getPropertyByName("name", primName); - - err = toString("%s : %s", primName.c_str(), e.Why.c_str()); - } - AfxMessageBox(err.c_str()); - } - catch (exception e) //catch a possible exception from getRootFileName - { - AfxMessageBox(e.what()); - } - } - else - { - refreshMachine(); - } - - if(vectSel.size()>0) - _PluginAccess->setCurrentSelection(vectSel); - GraphDlg->Invalidate(); -} - -void CGraphPlugin::refreshMachine() -{ - // get the current selection - const list &selection = _PluginAccess->getCurrentSelection(); - - if (selection.empty()) - return; - - TPrimitiveClassPredicate predFolder("npc_folder"); - TPrimitiveClassPredicate predManager("npc_manager"); - // for each selected node, look for an interesting class - list::const_iterator first(selection.begin()), last(selection.end()),curIte; - IPrimitive* missionTreeRoot=(*first); - CPrimitiveSet offsprings; - TPrimitiveSet resltOffspring; - offsprings.buildSet(missionTreeRoot,predFolder,resltOffspring); - - if ((predFolder(missionTreeRoot))|| - ((missionTreeRoot=getPrimitiveParent((*first),predFolder))!=NULL)) - { - - - string dot = generateDotScript(missionTreeRoot); - - string tmpPath = string(::getenv("TEMP")); - FILE *fp = fopen ((tmpPath+"/lang.dot").c_str(), "wt"); - if (!fp) - { - string msg("Can't write script file '"); - msg += tmpPath+"/lang.dot'"; - AfxMessageBox(msg.c_str()); - } - else - { - fwrite(dot.data(), dot.size(), 1, fp); - fclose(fp); - // NLMISC::CI18N::writeTextFile(tmpPath+"/lang.dot", dot, true); - NLMISC::CFile::deleteFile(tmpPath+"/output.png"); - NLMISC::CFile::deleteFile(tmpPath+"/output.imap"); - system((_DotPath+" "+tmpPath+"/lang.dot -Tpng -o "+tmpPath+"/output.png").c_str()); - system((_DotPath+" "+tmpPath+"/lang.dot -Timap -o "+tmpPath+"/output.imap").c_str()); - - //currently using output.png as the input file... - if(!createBitmap(tmpPath)) - AfxMessageBox("BEWARE: the image couldn't be loaded."); - } - - while (missionTreeRoot->getParent()!=NULL) - { - missionTreeRoot=missionTreeRoot->getParent(); - } - _rootFileName=_PluginAccess->getRootFileName(missionTreeRoot); - - - - } - else - { - list::const_iterator first(selection.begin()), last(selection.end()),curIte; - IPrimitive* missionTreeRoot=(*first); - offsprings.buildSet(missionTreeRoot,predManager,resltOffspring); - if ((predManager(missionTreeRoot))|| - ((missionTreeRoot=getPrimitiveParent((*first),predManager))!=NULL)) - { - - - string dot = generateDotScript(missionTreeRoot); - - string tmpPath = string(::getenv("TEMP")); - FILE *fp = fopen ((tmpPath+"/lang.dot").c_str(), "wt"); - if (!fp) - { - string msg("Can't write script file '"); - msg += tmpPath+"/lang.dot'"; - AfxMessageBox(msg.c_str()); - } - else - { - fwrite(dot.data(), dot.size(), 1, fp); - fclose(fp); -// NLMISC::CI18N::writeTextFile(tmpPath+"/lang.dot", dot, true); - NLMISC::CFile::deleteFile(tmpPath+"/output.png"); - NLMISC::CFile::deleteFile(tmpPath+"/output.imap"); - system((_DotPath+" "+tmpPath+"/lang.dot -Tpng -o "+tmpPath+"/output.png").c_str()); - system((_DotPath+" "+tmpPath+"/lang.dot -Timap -o "+tmpPath+"/output.imap").c_str()); - - //currently using output.png as the input file... - if(!createBitmap(tmpPath)) - AfxMessageBox("BEWARE: the image couldn't be loaded."); - } - - while (missionTreeRoot->getParent()!=NULL) - { - missionTreeRoot=missionTreeRoot->getParent(); - } - _rootFileName=_PluginAccess->getRootFileName(missionTreeRoot); - } - else - { - AfxMessageBox("The selected node could not be processed."); - } - - } - - - - -} - -////////////////////////////////////////////////////////////////////////// - -string CGraphPlugin::spaceTo_(string strInput) -{ - string ret; - vector strTmp; - explode(strInput,string(" "),strTmp); - if (strTmp.size()>1) - { - - for(uint i=0;i strTmpTmp; - explode(strTmp[i],string(":"),strTmpTmp); - for(uint j=0;j offsprings; - offsprings.buildSet(managerNode,predicate,resSet); - - for (uint i=0; igetPropertyByName("name",strName); - ret += "subgraph "; - ret += "cluster_"; - char* res=new char[100]; - _itoa(i+numClusters,res,10) ; - ret += res; - delete []res; - ret +="{"; - ret +=NL; - ret += "label = " ; - ret +='"'; - ret += spaceTo_(strName) ; - ret +='"'; - ret +=";"; - ret += NL ; - ret += spaceTo_(strName) ; - ret += " [URL=\""+buildPrimPath(resSet[i])+"\"]"; - ret += "[shape="; - ret += strShape.c_str(); - ret += "];" ; - ret += NL ; - ret += "}" ; - ret += NL; - - } - - - numClusters+=resSet.size(); - return ret; -} - -////////////////////////////////////////////////////////////////////////// - -string CGraphPlugin::createParsedNode(IPrimitive* managerNode,string strPredicate,uint& numClusters,string strShape) -{ - string ret; - TPrimitiveClassPredicate predicate(strPredicate.c_str()); - TPrimitiveSet resSet; - CPrimitiveSet offsprings; - offsprings.buildSet(managerNode,predicate,resSet); - - for (uint i=0; igetPropertyByName("name",strName); - ret += "subgraph "; - ret += "cluster_"; - char* res=new char[100]; - _itoa(i+numClusters,res,10) ; - ret += res; - delete []res; - ret +="{"; - ret +=NL; - ret += "label = " ; - ret +='"'; - ret += spaceTo_(strName) ; - ret +='"'; - ret +=";"; - ret += NL ; - ret += parseStateMachine(resSet[i],spaceTo_(strName),string(""),string("_")+spaceTo_(strName)); - ret += "}" ; - ret += NL; - - } - for (uint i=0; igetPropertyByName("name",strName); - - TPrimitiveClassPredicate predJump("npc_event_handler_action"); - TPrimitiveSet resJump; - offsprings.buildSet(resSet[i],predJump,resJump); - //if there is a change state action - for(uint j=0;jgetPropertyByName("name", labelTail); - if (labelTail.size()==0) - { - TPrimitiveClassPredicate predTail("npc_group_event_handler"); - primTail=getPrimitiveParent(resJump[j],predTail); - if(primTail) - primTail->getPropertyByName("name", labelTail); - } - - vector *jumpDest; - resJump[j]->getPropertyByName("action",strAction); - if (strAction.compare(string("begin_state"))==0) - { - ret += spaceTo_(strName) ; - resJump[j]->getPropertyByName("parameters",jumpDest); - ret += "->"; - ret +=spaceTo_(jumpDest->at(0)); - ret +="[label="; - ret +=spaceTo_(labelTail); - ret +="]"; - ret += ";" ; - ret += NL; - } - /*if (strAction.compare(string("random_select_state"))==0) - { - vector* jumpDest; - string strTmpTmpName; - - resJump[j]->getPropertyByName("parameters",jumpDest); - resJump[j]->getPropertyByName("name",strTmpTmpName); - - ret += spaceTo_(strName) ; - ret +="->"; - ret +=strTmpTmpName; - ret +="_"; - ret += spaceTo_(strName) ; - ret += "[color=pink];"; - ret += NL; - for(uint k=0;ksize();k++) - { - ret +=strTmpTmpName; - ret +="_"; - ret += spaceTo_(strName) ; - ret +="->"; - - vector resJump; - explode(jumpDest->at(k)," ",resJump); - ret +=resJump[1]; - ret+= ";"; - ret+=NL; - - } - }*/ - if (strAction.compare(string("punctual_state"))==0) - { - ret += spaceTo_(strName) ; - resJump[j]->getPropertyByName("parameters",jumpDest); - ret += "->"; - ret +=spaceTo_(jumpDest->at(0)); - ret +="[label="; - ret +=spaceTo_(labelTail); - ret +="]"; - ret += ";" ; - ret += NL; - ret +=spaceTo_(jumpDest->at(0)); - ret += "->"; - ret += strName ; - ret +="[label="; - ret +=spaceTo_(labelTail); - ret +="]"; - ret += ";" ; - ret += NL; - } - } - - } - numClusters+=resSet.size(); - return ret; -} - -////////////////////////////////////////////////////////////////////////// - - -string CGraphPlugin::generateDotScript(IPrimitive* managerNode) -{ - string resName; - managerNode->getPropertyByName("name",resName); - string ret = "digraph " + spaceTo_(resName) + NL; - ret += "{" + NL; - - uint numNode=0; - - ret+=createNode(managerNode,string("npc_zone"),numNode,string("Mrecord")); - - ret+=createNode(managerNode,string("npc_route"),numNode,string("Mrecord")); - - ret+=createNode(managerNode,string("npc_punctual_state"),numNode,string("Mrecord")); - - numNode=0; - - ret+=createParsedNode(managerNode,string("npc_zone"),numNode,string("Mrecord")); - - ret+=createParsedNode(managerNode,string("npc_route"),numNode,string("Mrecord")); - - ret+=createParsedNode(managerNode,string("npc_punctual_state"),numNode,string("Mrecord")); - - ret += "}" + NL; - - return ret; -} - -string CGraphPlugin::parseStateMachine(NLLIGO::IPrimitive* currentNode,string emiterNode,string tailLabel,string tag) -{ - string ret,strName,strClassName,strAction,strCurName,strCurClassName,strCurAction,strTail; - currentNode->getPropertyByName("class",strCurClassName); - currentNode->getPropertyByName("name",strCurName); - currentNode->getPropertyByName("action",strCurAction); - - uint numChild=currentNode->getNumChildren(); - for(uint i=0;igetChild(child,i); - child->getPropertyByName("class",strClassName); - child->getPropertyByName("name",strName); - child->getPropertyByName("action",strAction); - - if (strClassName.compare(string("npc_group"))==0) - { - child->getPropertyByName("name",strName); - - ret+=spaceTo_(strName); - ret+=tag; - ret += " [URL=\""+buildPrimPath(child)+"\"];"+NL; - ret+=spaceTo_(strName); - ret+=tag; - ret+="->"; - ret+=emiterNode; - ret+="[arrowhead=none]"; - if(!tailLabel.empty()) - { - ret+="[label="; - ret+=tailLabel; - ret+="]"; - } - ret+=";"; - ret+=NL; - ret+=parseStateMachine(child,spaceTo_(strName+tag),spaceTo_(tailLabel),tag); - } - else if (strClassName.compare(string("npc_state_event_handler"))==0) - { - child->getPropertyByName("name",strTail); - ret+=parseStateMachine(child,emiterNode,spaceTo_(strTail+"][color=cyan"),tag); - } - else if (strClassName.compare(string("npc_group_event_handler"))==0) - { - child->getPropertyByName("name",strTail); - ret+=parseStateMachine(child,emiterNode,spaceTo_(strTail+"][color=cyan"),tag); - } - else if ((strAction.compare(string("multi_actions"))==0) - || (strAction.compare(string("random_select"))==0)) - { - child->getPropertyByName("name",strName); - ret+=spaceTo_(strName); - ret+=tag; - ret += " [URL=\""+buildPrimPath(child)+"\"];"+NL; - if(strAction.compare(string("random_select"))==0) - { - ret+=spaceTo_(strName); - ret+=tag; - ret+="_"; - ret+="random_select"; - ret += " [URL=\""+buildPrimPath(child)+"\"];"+NL; - ret+=spaceTo_(strName); - ret+=tag; - ret+="->"; - ret+=spaceTo_(strName); - ret+=tag; - ret+="_random_select;"+NL; - ret+=spaceTo_(strName); - ret+=tag; - ret+="_"; - ret+="random_select"; - } - else - { - ret+=spaceTo_(strName); - ret+=tag; - } - ret+="[shape=record]"; - if(child->getNumChildren()>0) - { - bool first=false; - ret+="[label="; - ret+='"'; - ret+="{"; - for (uint l=0;lgetNumChildren();l++ ) - { - string tmpStr; - IPrimitive* tmpChild; - child->getChild(tmpChild,l); - tmpChild->getPropertyByName("name",tmpStr); - tmpChild->getPropertyByName("class",strClassName); - tmpChild->getPropertyByName("action",strAction); - if ((!tmpStr.empty()) - && (strClassName.compare("npc_event_handler_action")==0) - && (!strAction.compare("begin_state")==0) - && (!strAction.compare("random_select")==0)) - { - if (first) - { - ret+="|"; - } - ret+=strAction; - ret+=tag; - first=true; - } - - } - ret+="}"; - ret+='"'; - ret+="]"; - } - ret+=";"; - ret+=NL; - ret+=emiterNode; - ret+="->"; - ret+=spaceTo_(strName); - ret+=tag; - if(!tailLabel.empty()) - { - ret+="[label="; - ret+=tailLabel; - ret+="]"; - } - ret+=";"; - ret+=NL; - if(child->getNumChildren()>0) - { - for (uint l=0;lgetNumChildren();l++ ) - { - string tmpStr; - IPrimitive* tmpChild; - child->getChild(tmpChild,l); - tmpChild->getPropertyByName("name",tmpStr); - tmpChild->getPropertyByName("class",strClassName); - tmpChild->getPropertyByName("action",strAction); - if ((!tmpStr.empty()) - && (strClassName.compare("random_select_state")==0)) - { - vector* jumpDest; - child->getPropertyByName("parameters",jumpDest); - for(uint k=0;ksize();k++) - { - ret+=spaceTo_(strName); - ret+=tag; - ret+="->"; - ret +=spaceTo_(jumpDest->at(k)); - ret+= ";"; - ret+=NL; - } - } - - } - ret+=NL; - } - /* ret+=spaceTo_(strName); - ret+=tag; - ret+="->"; - ret+=spaceTo_(strName); - ret+=tag; - ret+="_"; - ret+="random_select"; - ret+="[arrowhead=none];"; - ret+=NL;*/ - for (uint l=0;lgetNumChildren();l++ ) - { - IPrimitive* tmpChild; - child->getChild(tmpChild,l); - for (uint m=0;mgetNumChildren();m++ ) - { - IPrimitive* tmpTmpChild; - child->getChild(tmpTmpChild,m); - ret+=parseStateMachine(tmpTmpChild,spaceTo_(strName+tag),string(""),tag); - } - } - } - else if (strAction.compare(string("random_select_state"))==0) - { - vector* jumpDest; - bool first=true; - child->getPropertyByName("parameters",jumpDest); - - ret += spaceTo_(strName) ; - ret +="_"; - ret += emiterNode; - ret += " [URL=\""+buildPrimPath(child)+"\"];"+NL; - ret += spaceTo_(strName) ; - ret +="_"; - ret += emiterNode; - ret +="->"; - for(uint k=0;ksize();k++) - { - if (!first) - { - ret += spaceTo_(strName) ; - ret +="_"; - ret += emiterNode; - ret +="->"; - } - first=false; - vector resJump; - explode(jumpDest->at(k),string(" "),resJump); - ret +=resJump[1]; - ret+= ";"; - ret+=NL; - - } - ret+=emiterNode; - ret += "->"; - ret += spaceTo_(strName) ; - ret +="_"; - ret += emiterNode; - ret +=";"; - ret +=NL; - } - else - { - ret+=parseStateMachine(child,emiterNode,tailLabel,tag); - - } - - - } - currentNode->getPropertyByName("class",strClassName); - currentNode->getPropertyByName("name",strName); - currentNode->getPropertyByName("action",strAction); - if ( (numChild==0) - && (!strName.empty()) - && (!strAction.compare("begin_state")==0) - && (!strAction.compare("random_select_state")==0) - && (!strAction.compare("random_select")==0) - && (strClassName.compare("npc_event_handler_action")==0)) - { - ret+=spaceTo_(strAction); - ret+=tag; - ret+="[color=green]"; - ret += " [URL=\""+buildPrimPath(currentNode)+"\"];"; - ret+=NL; - ret+=emiterNode; - ret+="->"; - ret+=spaceTo_(strAction); - ret+=tag; - if(!tailLabel.empty()) - { - ret+="[label="; - ret+=tailLabel; - ret+="]"; - } - ret+=";"; - ret+=NL; - } - return ret; - -} - -bool CGraphPlugin::createBitmap (const string &tmpPath) -{ - string fileName(tmpPath+"/output.png"); - NLMISC::CBitmap bitmap; - NLMISC::CIFile pngLocation; - if(!pngLocation.open(fileName)) - { - nlwarning("Can't open file '%s'", fileName.c_str()); - return false; - } - - WORD retour; - - if(retour=bitmap.load(pngLocation)) - { - - HBITMAP &_Hbmp=GraphDlg->_Hbmp; - - HBITMAP &_Hdib=GraphDlg->_Hdib; - - BITMAPINFO &_DibBitmapInfo=GraphDlg->_DibBitmapInfo;; - - uint8* &_DibBits=GraphDlg->_DibBits; - - _DibBitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFO); - _DibBitmapInfo.bmiHeader.biWidth = bitmap.getWidth(); - _DibBitmapInfo.bmiHeader.biHeight = bitmap.getHeight(); - _DibBitmapInfo.bmiHeader.biPlanes = 1; - _DibBitmapInfo.bmiHeader.biBitCount = retour; - _DibBitmapInfo.bmiHeader.biCompression = BI_RGB; - _DibBitmapInfo.bmiHeader.biSizeImage = bitmap.getSize(); - _DibBitmapInfo.bmiHeader.biXPelsPerMeter = 0; - _DibBitmapInfo.bmiHeader.biYPelsPerMeter = 0; - _DibBitmapInfo.bmiHeader.biClrUsed = 0; - _DibBitmapInfo.bmiHeader.biClrImportant = 0; - - // Create the bitmap - HWND desktop = ::GetDesktopWindow(); - HDC dc = ::GetDC (desktop); - - nlverify(_Hdib = CreateDIBSection(dc, &_DibBitmapInfo, DIB_RGB_COLORS, - (void**)&_DibBits, NULL, 0)); - - bitmap.getDibData(_DibBits); - - nlverify (_Hbmp = CreateDIBitmap(dc, &(_DibBitmapInfo.bmiHeader), CBM_INIT, - (void*)_DibBits, &_DibBitmapInfo, DIB_RGB_COLORS)); - ::ReleaseDC (desktop, dc); - pngLocation.close(); - pngLocation.flush(); - return true; - } - else - { - nlwarning("Can't load file '%s'", fileName.c_str()); - } - pngLocation.close(); - pngLocation.flush(); - return false; -} - - -bool CGraphPlugin::activatePlugin() -{ - if(!_PluginActive) - { - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - AfxEnableControlContainer(); - GraphDlg->ShowWindow(TRUE); - _PluginActive=true; - return true; - } - return false; -} - -bool CGraphPlugin::closePlugin() -{ - if (_PluginActive) - { - GraphDlg->ShowWindow(FALSE); - _PluginActive=false; - return true; - } - return false; -} - -std::string& CGraphPlugin::getName() -{ - return _Name; -} - -bool CGraphPlugin::isActive() -{ - return _PluginActive; -} - -void CGraphPlugin::unsetDlgGraph() -{ - _PluginActive=false; -} - - -void CGraphPlugin::doSelection(const string& primPath) -{ - IPrimitive *rootNode; - - TPrimitiveClassPredicate pred("root"); - TPrimitiveSet resSet; - - if(_PluginAccess->getCurrentSelection().size()>0) - { - - try - { - rootNode=(IPrimitive*)_PluginAccess->getRootNode(_rootFileName); - - selectPrimByPath(rootNode,primPath,resSet); - - _PluginAccess->setCurrentSelection(resSet); - - }catch(exception e){ - GraphDlg->MessageBox(e.what()); - } - } +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// graph_plugin.cpp: implementation of the CGraphPlugin class. +// +////////////////////////////////////////////////////////////////////// + +#include "stdafx.h" + +#include "nel/misc/types_nl.h" +#include "nel/misc/bitmap.h" +#include "graph_plugin.h" +#include +#include +#include "nel/ligo/primitive_utils.h" +#include "../../../leveldesign/mission_compiler_lib/mission_compiler.h" +#include "nel/misc/i18n.h" +#include +#include + +using namespace NLMISC; +using namespace NLLIGO; +using namespace NLNET; +using namespace std; + +class CDatabaseLocator; + +CFileDisplayer *GraphPluginLogDisplayer= NULL; + +// vl: important to add the next line or AfxGetApp() will returns 0 after AFX_MANAGE_STATE(AfxGetStaticModuleState()); +CWinApp theApp; + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +extern "C" +{ + void *createPlugin() + { + return new CGraphPlugin(); + } +} + +CGraphPlugin::CGraphPlugin() +{ + NLMISC::createDebug(); + + GraphPluginLogDisplayer= new CFileDisplayer("world_editor_graph_plugin.log", true, "WORLD_EDITOR_GRAPH_PLUGIN.LOG"); + DebugLog->addDisplayer (GraphPluginLogDisplayer); + InfoLog->addDisplayer (GraphPluginLogDisplayer); + WarningLog->addDisplayer (GraphPluginLogDisplayer); + ErrorLog->addDisplayer (GraphPluginLogDisplayer); + AssertLog->addDisplayer (GraphPluginLogDisplayer); + + nlinfo("Starting graph plugin..."); + GraphDlg=new CWorldEditorGraphPluginDlg(); +} + +CGraphPlugin::~CGraphPlugin() +{ + delete [] GraphDlg; +} + +void CGraphPlugin::init(IPluginAccess *pluginAccess) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + AfxEnableControlContainer(); + + _PluginAccess = pluginAccess; + + _Name="mission_graph"; + + GraphDlg->Create(IDD_WORLDEDITORGRAPHPLUGIN_DIALOG, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); + GraphDlg->ShowWindow(TRUE); + GraphDlg->init(this); + _PluginActive=true; + + // Retreive the dot exe path + CConfigFile::CVar *dotPath = pluginAccess->getConfigFile().getVarPtr("DotPath"); + nlinfo("%s", dotPath->asString().c_str()); + if (dotPath) + { + _DotPath = CPath::getFullPath(dotPath->asString(), false); + nlinfo("%s", _DotPath.c_str()); + } + else + { + // use default configuration + nlwarning("graph_plugin : Can't find configuration variable 'DotPath', using 'dot/dot.exe' instead"); + _DotPath = CPath::getFullPath("dot/dot.exe", false); + } +} + + +/// The current region has changed. +//void CSoundPlugin::primRegionChanged(const std::vector ®ions) +void CGraphPlugin::primitiveChanged(const NLLIGO::IPrimitive *root) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); +} + + +void CGraphPlugin::positionMoved(const NLMISC::CVector &position) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); +} + +void CGraphPlugin::lostPositionControl() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); +} + + +void CGraphPlugin::onIdle() +{ +} + +void CGraphPlugin::refreshPrimitives() +{ + // get the current selection + const list &selection = _PluginAccess->getCurrentSelection(); + + if (selection.empty()) + return; + + TPrimitiveClassPredicate pred("mission_tree"); + // for each selected node, look for an interesting class + list::const_iterator first(selection.begin()), last(selection.end()),curIte; + IPrimitive* missionTreeRoot=(*first); + CPrimitiveSet offsprings; + TPrimitiveSet resltOffspring; + offsprings.buildSet(missionTreeRoot,pred,resltOffspring); + + vector vectSel;//vector of faulty mission element (sent by the mission compiler) + + if ((pred(missionTreeRoot))|| + ((missionTreeRoot=getPrimitiveParent((*first),pred))!=NULL)|| + ((!resltOffspring.empty())&&(missionTreeRoot=*resltOffspring.begin()))) + { + // ok, we find a good node + try + { + + + IPrimitive *rootNode = missionTreeRoot; + while (rootNode->getParent()) + rootNode = rootNode->getParent(); + string fileName = _PluginAccess->getRootFileName(rootNode); + + CMissionCompiler mc; + mc.compileMission(missionTreeRoot, NLMISC::CFile::getFilename(fileName)); + TMissionDataPtr md = mc.getMission(0); + string dot = md->generateDotScript(); + + string tmpPath = string(::getenv("TEMP")); + FILE *fp = fopen ((tmpPath+"/lang.dot").c_str(), "wt"); + if (!fp) + { + string msg("Can't write script file '"); + msg += tmpPath+"/lang.dot'"; + AfxMessageBox(msg.c_str()); + } + else + { + fwrite(dot.data(), dot.size(), 1, fp); + fclose(fp); +// NLMISC::CI18N::writeTextFile(tmpPath+"/lang.dot", dot, true); + NLMISC::CFile::deleteFile(tmpPath+"/output.png"); + NLMISC::CFile::deleteFile(tmpPath+"/output.imap"); + system((_DotPath+" "+tmpPath+"/lang.dot -Tpng -o "+tmpPath+"/output.png").c_str()); + system((_DotPath+" "+tmpPath+"/lang.dot -Timap -o "+tmpPath+"/output.imap").c_str()); + + //currently using output.png as the input file... + if(!createBitmap(tmpPath)) + AfxMessageBox("BEWARE: the image couldn't be loaded."); + } + + while (missionTreeRoot->getParent()!=NULL) + { + missionTreeRoot=missionTreeRoot->getParent(); + } + _rootFileName=_PluginAccess->getRootFileName(missionTreeRoot); + } + catch(EParseException &e) + { + string err = e.Why; + if (e.Primitive != NULL) + { + string primName; + + vectSel.push_back(e.Primitive); + e.Primitive->getPropertyByName("name", primName); + + err = toString("%s : %s", primName.c_str(), e.Why.c_str()); + } + AfxMessageBox(err.c_str()); + } + catch (exception e) //catch a possible exception from getRootFileName + { + AfxMessageBox(e.what()); + } + } + else + { + refreshMachine(); + } + + if(vectSel.size()>0) + _PluginAccess->setCurrentSelection(vectSel); + GraphDlg->Invalidate(); +} + +void CGraphPlugin::refreshMachine() +{ + // get the current selection + const list &selection = _PluginAccess->getCurrentSelection(); + + if (selection.empty()) + return; + + TPrimitiveClassPredicate predFolder("npc_folder"); + TPrimitiveClassPredicate predManager("npc_manager"); + // for each selected node, look for an interesting class + list::const_iterator first(selection.begin()), last(selection.end()),curIte; + IPrimitive* missionTreeRoot=(*first); + CPrimitiveSet offsprings; + TPrimitiveSet resltOffspring; + offsprings.buildSet(missionTreeRoot,predFolder,resltOffspring); + + if ((predFolder(missionTreeRoot))|| + ((missionTreeRoot=getPrimitiveParent((*first),predFolder))!=NULL)) + { + + + string dot = generateDotScript(missionTreeRoot); + + string tmpPath = string(::getenv("TEMP")); + FILE *fp = fopen ((tmpPath+"/lang.dot").c_str(), "wt"); + if (!fp) + { + string msg("Can't write script file '"); + msg += tmpPath+"/lang.dot'"; + AfxMessageBox(msg.c_str()); + } + else + { + fwrite(dot.data(), dot.size(), 1, fp); + fclose(fp); + // NLMISC::CI18N::writeTextFile(tmpPath+"/lang.dot", dot, true); + NLMISC::CFile::deleteFile(tmpPath+"/output.png"); + NLMISC::CFile::deleteFile(tmpPath+"/output.imap"); + system((_DotPath+" "+tmpPath+"/lang.dot -Tpng -o "+tmpPath+"/output.png").c_str()); + system((_DotPath+" "+tmpPath+"/lang.dot -Timap -o "+tmpPath+"/output.imap").c_str()); + + //currently using output.png as the input file... + if(!createBitmap(tmpPath)) + AfxMessageBox("BEWARE: the image couldn't be loaded."); + } + + while (missionTreeRoot->getParent()!=NULL) + { + missionTreeRoot=missionTreeRoot->getParent(); + } + _rootFileName=_PluginAccess->getRootFileName(missionTreeRoot); + + + + } + else + { + list::const_iterator first(selection.begin()), last(selection.end()),curIte; + IPrimitive* missionTreeRoot=(*first); + offsprings.buildSet(missionTreeRoot,predManager,resltOffspring); + if ((predManager(missionTreeRoot))|| + ((missionTreeRoot=getPrimitiveParent((*first),predManager))!=NULL)) + { + + + string dot = generateDotScript(missionTreeRoot); + + string tmpPath = string(::getenv("TEMP")); + FILE *fp = fopen ((tmpPath+"/lang.dot").c_str(), "wt"); + if (!fp) + { + string msg("Can't write script file '"); + msg += tmpPath+"/lang.dot'"; + AfxMessageBox(msg.c_str()); + } + else + { + fwrite(dot.data(), dot.size(), 1, fp); + fclose(fp); +// NLMISC::CI18N::writeTextFile(tmpPath+"/lang.dot", dot, true); + NLMISC::CFile::deleteFile(tmpPath+"/output.png"); + NLMISC::CFile::deleteFile(tmpPath+"/output.imap"); + system((_DotPath+" "+tmpPath+"/lang.dot -Tpng -o "+tmpPath+"/output.png").c_str()); + system((_DotPath+" "+tmpPath+"/lang.dot -Timap -o "+tmpPath+"/output.imap").c_str()); + + //currently using output.png as the input file... + if(!createBitmap(tmpPath)) + AfxMessageBox("BEWARE: the image couldn't be loaded."); + } + + while (missionTreeRoot->getParent()!=NULL) + { + missionTreeRoot=missionTreeRoot->getParent(); + } + _rootFileName=_PluginAccess->getRootFileName(missionTreeRoot); + } + else + { + AfxMessageBox("The selected node could not be processed."); + } + + } + + + + +} + +////////////////////////////////////////////////////////////////////////// + +string CGraphPlugin::spaceTo_(string strInput) +{ + string ret; + vector strTmp; + explode(strInput,string(" "),strTmp); + if (strTmp.size()>1) + { + + for(uint i=0;i strTmpTmp; + explode(strTmp[i],string(":"),strTmpTmp); + for(uint j=0;j offsprings; + offsprings.buildSet(managerNode,predicate,resSet); + + for (uint i=0; igetPropertyByName("name",strName); + ret += "subgraph "; + ret += "cluster_"; + char* res=new char[100]; + _itoa(i+numClusters,res,10) ; + ret += res; + delete []res; + ret +="{"; + ret +=NL; + ret += "label = " ; + ret +='"'; + ret += spaceTo_(strName) ; + ret +='"'; + ret +=";"; + ret += NL ; + ret += spaceTo_(strName) ; + ret += " [URL=\""+buildPrimPath(resSet[i])+"\"]"; + ret += "[shape="; + ret += strShape.c_str(); + ret += "];" ; + ret += NL ; + ret += "}" ; + ret += NL; + + } + + + numClusters+=resSet.size(); + return ret; +} + +////////////////////////////////////////////////////////////////////////// + +string CGraphPlugin::createParsedNode(IPrimitive* managerNode,string strPredicate,uint& numClusters,string strShape) +{ + string ret; + TPrimitiveClassPredicate predicate(strPredicate.c_str()); + TPrimitiveSet resSet; + CPrimitiveSet offsprings; + offsprings.buildSet(managerNode,predicate,resSet); + + for (uint i=0; igetPropertyByName("name",strName); + ret += "subgraph "; + ret += "cluster_"; + char* res=new char[100]; + _itoa(i+numClusters,res,10) ; + ret += res; + delete []res; + ret +="{"; + ret +=NL; + ret += "label = " ; + ret +='"'; + ret += spaceTo_(strName) ; + ret +='"'; + ret +=";"; + ret += NL ; + ret += parseStateMachine(resSet[i],spaceTo_(strName),string(""),string("_")+spaceTo_(strName)); + ret += "}" ; + ret += NL; + + } + for (uint i=0; igetPropertyByName("name",strName); + + TPrimitiveClassPredicate predJump("npc_event_handler_action"); + TPrimitiveSet resJump; + offsprings.buildSet(resSet[i],predJump,resJump); + //if there is a change state action + for(uint j=0;jgetPropertyByName("name", labelTail); + if (labelTail.size()==0) + { + TPrimitiveClassPredicate predTail("npc_group_event_handler"); + primTail=getPrimitiveParent(resJump[j],predTail); + if(primTail) + primTail->getPropertyByName("name", labelTail); + } + + vector *jumpDest; + resJump[j]->getPropertyByName("action",strAction); + if (strAction.compare(string("begin_state"))==0) + { + ret += spaceTo_(strName) ; + resJump[j]->getPropertyByName("parameters",jumpDest); + ret += "->"; + ret +=spaceTo_(jumpDest->at(0)); + ret +="[label="; + ret +=spaceTo_(labelTail); + ret +="]"; + ret += ";" ; + ret += NL; + } + /*if (strAction.compare(string("random_select_state"))==0) + { + vector* jumpDest; + string strTmpTmpName; + + resJump[j]->getPropertyByName("parameters",jumpDest); + resJump[j]->getPropertyByName("name",strTmpTmpName); + + ret += spaceTo_(strName) ; + ret +="->"; + ret +=strTmpTmpName; + ret +="_"; + ret += spaceTo_(strName) ; + ret += "[color=pink];"; + ret += NL; + for(uint k=0;ksize();k++) + { + ret +=strTmpTmpName; + ret +="_"; + ret += spaceTo_(strName) ; + ret +="->"; + + vector resJump; + explode(jumpDest->at(k)," ",resJump); + ret +=resJump[1]; + ret+= ";"; + ret+=NL; + + } + }*/ + if (strAction.compare(string("punctual_state"))==0) + { + ret += spaceTo_(strName) ; + resJump[j]->getPropertyByName("parameters",jumpDest); + ret += "->"; + ret +=spaceTo_(jumpDest->at(0)); + ret +="[label="; + ret +=spaceTo_(labelTail); + ret +="]"; + ret += ";" ; + ret += NL; + ret +=spaceTo_(jumpDest->at(0)); + ret += "->"; + ret += strName ; + ret +="[label="; + ret +=spaceTo_(labelTail); + ret +="]"; + ret += ";" ; + ret += NL; + } + } + + } + numClusters+=resSet.size(); + return ret; +} + +////////////////////////////////////////////////////////////////////////// + + +string CGraphPlugin::generateDotScript(IPrimitive* managerNode) +{ + string resName; + managerNode->getPropertyByName("name",resName); + string ret = "digraph " + spaceTo_(resName) + NL; + ret += "{" + NL; + + uint numNode=0; + + ret+=createNode(managerNode,string("npc_zone"),numNode,string("Mrecord")); + + ret+=createNode(managerNode,string("npc_route"),numNode,string("Mrecord")); + + ret+=createNode(managerNode,string("npc_punctual_state"),numNode,string("Mrecord")); + + numNode=0; + + ret+=createParsedNode(managerNode,string("npc_zone"),numNode,string("Mrecord")); + + ret+=createParsedNode(managerNode,string("npc_route"),numNode,string("Mrecord")); + + ret+=createParsedNode(managerNode,string("npc_punctual_state"),numNode,string("Mrecord")); + + ret += "}" + NL; + + return ret; +} + +string CGraphPlugin::parseStateMachine(NLLIGO::IPrimitive* currentNode,string emiterNode,string tailLabel,string tag) +{ + string ret,strName,strClassName,strAction,strCurName,strCurClassName,strCurAction,strTail; + currentNode->getPropertyByName("class",strCurClassName); + currentNode->getPropertyByName("name",strCurName); + currentNode->getPropertyByName("action",strCurAction); + + uint numChild=currentNode->getNumChildren(); + for(uint i=0;igetChild(child,i); + child->getPropertyByName("class",strClassName); + child->getPropertyByName("name",strName); + child->getPropertyByName("action",strAction); + + if (strClassName.compare(string("npc_group"))==0) + { + child->getPropertyByName("name",strName); + + ret+=spaceTo_(strName); + ret+=tag; + ret += " [URL=\""+buildPrimPath(child)+"\"];"+NL; + ret+=spaceTo_(strName); + ret+=tag; + ret+="->"; + ret+=emiterNode; + ret+="[arrowhead=none]"; + if(!tailLabel.empty()) + { + ret+="[label="; + ret+=tailLabel; + ret+="]"; + } + ret+=";"; + ret+=NL; + ret+=parseStateMachine(child,spaceTo_(strName+tag),spaceTo_(tailLabel),tag); + } + else if (strClassName.compare(string("npc_state_event_handler"))==0) + { + child->getPropertyByName("name",strTail); + ret+=parseStateMachine(child,emiterNode,spaceTo_(strTail+"][color=cyan"),tag); + } + else if (strClassName.compare(string("npc_group_event_handler"))==0) + { + child->getPropertyByName("name",strTail); + ret+=parseStateMachine(child,emiterNode,spaceTo_(strTail+"][color=cyan"),tag); + } + else if ((strAction.compare(string("multi_actions"))==0) + || (strAction.compare(string("random_select"))==0)) + { + child->getPropertyByName("name",strName); + ret+=spaceTo_(strName); + ret+=tag; + ret += " [URL=\""+buildPrimPath(child)+"\"];"+NL; + if(strAction.compare(string("random_select"))==0) + { + ret+=spaceTo_(strName); + ret+=tag; + ret+="_"; + ret+="random_select"; + ret += " [URL=\""+buildPrimPath(child)+"\"];"+NL; + ret+=spaceTo_(strName); + ret+=tag; + ret+="->"; + ret+=spaceTo_(strName); + ret+=tag; + ret+="_random_select;"+NL; + ret+=spaceTo_(strName); + ret+=tag; + ret+="_"; + ret+="random_select"; + } + else + { + ret+=spaceTo_(strName); + ret+=tag; + } + ret+="[shape=record]"; + if(child->getNumChildren()>0) + { + bool first=false; + ret+="[label="; + ret+='"'; + ret+="{"; + for (uint l=0;lgetNumChildren();l++ ) + { + string tmpStr; + IPrimitive* tmpChild; + child->getChild(tmpChild,l); + tmpChild->getPropertyByName("name",tmpStr); + tmpChild->getPropertyByName("class",strClassName); + tmpChild->getPropertyByName("action",strAction); + if ((!tmpStr.empty()) + && (strClassName.compare("npc_event_handler_action")==0) + && (!strAction.compare("begin_state")==0) + && (!strAction.compare("random_select")==0)) + { + if (first) + { + ret+="|"; + } + ret+=strAction; + ret+=tag; + first=true; + } + + } + ret+="}"; + ret+='"'; + ret+="]"; + } + ret+=";"; + ret+=NL; + ret+=emiterNode; + ret+="->"; + ret+=spaceTo_(strName); + ret+=tag; + if(!tailLabel.empty()) + { + ret+="[label="; + ret+=tailLabel; + ret+="]"; + } + ret+=";"; + ret+=NL; + if(child->getNumChildren()>0) + { + for (uint l=0;lgetNumChildren();l++ ) + { + string tmpStr; + IPrimitive* tmpChild; + child->getChild(tmpChild,l); + tmpChild->getPropertyByName("name",tmpStr); + tmpChild->getPropertyByName("class",strClassName); + tmpChild->getPropertyByName("action",strAction); + if ((!tmpStr.empty()) + && (strClassName.compare("random_select_state")==0)) + { + vector* jumpDest; + child->getPropertyByName("parameters",jumpDest); + for(uint k=0;ksize();k++) + { + ret+=spaceTo_(strName); + ret+=tag; + ret+="->"; + ret +=spaceTo_(jumpDest->at(k)); + ret+= ";"; + ret+=NL; + } + } + + } + ret+=NL; + } + /* ret+=spaceTo_(strName); + ret+=tag; + ret+="->"; + ret+=spaceTo_(strName); + ret+=tag; + ret+="_"; + ret+="random_select"; + ret+="[arrowhead=none];"; + ret+=NL;*/ + for (uint l=0;lgetNumChildren();l++ ) + { + IPrimitive* tmpChild; + child->getChild(tmpChild,l); + for (uint m=0;mgetNumChildren();m++ ) + { + IPrimitive* tmpTmpChild; + child->getChild(tmpTmpChild,m); + ret+=parseStateMachine(tmpTmpChild,spaceTo_(strName+tag),string(""),tag); + } + } + } + else if (strAction.compare(string("random_select_state"))==0) + { + vector* jumpDest; + bool first=true; + child->getPropertyByName("parameters",jumpDest); + + ret += spaceTo_(strName) ; + ret +="_"; + ret += emiterNode; + ret += " [URL=\""+buildPrimPath(child)+"\"];"+NL; + ret += spaceTo_(strName) ; + ret +="_"; + ret += emiterNode; + ret +="->"; + for(uint k=0;ksize();k++) + { + if (!first) + { + ret += spaceTo_(strName) ; + ret +="_"; + ret += emiterNode; + ret +="->"; + } + first=false; + vector resJump; + explode(jumpDest->at(k),string(" "),resJump); + ret +=resJump[1]; + ret+= ";"; + ret+=NL; + + } + ret+=emiterNode; + ret += "->"; + ret += spaceTo_(strName) ; + ret +="_"; + ret += emiterNode; + ret +=";"; + ret +=NL; + } + else + { + ret+=parseStateMachine(child,emiterNode,tailLabel,tag); + + } + + + } + currentNode->getPropertyByName("class",strClassName); + currentNode->getPropertyByName("name",strName); + currentNode->getPropertyByName("action",strAction); + if ( (numChild==0) + && (!strName.empty()) + && (!strAction.compare("begin_state")==0) + && (!strAction.compare("random_select_state")==0) + && (!strAction.compare("random_select")==0) + && (strClassName.compare("npc_event_handler_action")==0)) + { + ret+=spaceTo_(strAction); + ret+=tag; + ret+="[color=green]"; + ret += " [URL=\""+buildPrimPath(currentNode)+"\"];"; + ret+=NL; + ret+=emiterNode; + ret+="->"; + ret+=spaceTo_(strAction); + ret+=tag; + if(!tailLabel.empty()) + { + ret+="[label="; + ret+=tailLabel; + ret+="]"; + } + ret+=";"; + ret+=NL; + } + return ret; + +} + +bool CGraphPlugin::createBitmap (const string &tmpPath) +{ + string fileName(tmpPath+"/output.png"); + NLMISC::CBitmap bitmap; + NLMISC::CIFile pngLocation; + if(!pngLocation.open(fileName)) + { + nlwarning("Can't open file '%s'", fileName.c_str()); + return false; + } + + WORD retour; + + if(retour=bitmap.load(pngLocation)) + { + + HBITMAP &_Hbmp=GraphDlg->_Hbmp; + + HBITMAP &_Hdib=GraphDlg->_Hdib; + + BITMAPINFO &_DibBitmapInfo=GraphDlg->_DibBitmapInfo;; + + uint8* &_DibBits=GraphDlg->_DibBits; + + _DibBitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFO); + _DibBitmapInfo.bmiHeader.biWidth = bitmap.getWidth(); + _DibBitmapInfo.bmiHeader.biHeight = bitmap.getHeight(); + _DibBitmapInfo.bmiHeader.biPlanes = 1; + _DibBitmapInfo.bmiHeader.biBitCount = retour; + _DibBitmapInfo.bmiHeader.biCompression = BI_RGB; + _DibBitmapInfo.bmiHeader.biSizeImage = bitmap.getSize(); + _DibBitmapInfo.bmiHeader.biXPelsPerMeter = 0; + _DibBitmapInfo.bmiHeader.biYPelsPerMeter = 0; + _DibBitmapInfo.bmiHeader.biClrUsed = 0; + _DibBitmapInfo.bmiHeader.biClrImportant = 0; + + // Create the bitmap + HWND desktop = ::GetDesktopWindow(); + HDC dc = ::GetDC (desktop); + + nlverify(_Hdib = CreateDIBSection(dc, &_DibBitmapInfo, DIB_RGB_COLORS, + (void**)&_DibBits, NULL, 0)); + + bitmap.getDibData(_DibBits); + + nlverify (_Hbmp = CreateDIBitmap(dc, &(_DibBitmapInfo.bmiHeader), CBM_INIT, + (void*)_DibBits, &_DibBitmapInfo, DIB_RGB_COLORS)); + ::ReleaseDC (desktop, dc); + pngLocation.close(); + pngLocation.flush(); + return true; + } + else + { + nlwarning("Can't load file '%s'", fileName.c_str()); + } + pngLocation.close(); + pngLocation.flush(); + return false; +} + + +bool CGraphPlugin::activatePlugin() +{ + if(!_PluginActive) + { + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + AfxEnableControlContainer(); + GraphDlg->ShowWindow(TRUE); + _PluginActive=true; + return true; + } + return false; +} + +bool CGraphPlugin::closePlugin() +{ + if (_PluginActive) + { + GraphDlg->ShowWindow(FALSE); + _PluginActive=false; + return true; + } + return false; +} + +std::string& CGraphPlugin::getName() +{ + return _Name; +} + +bool CGraphPlugin::isActive() +{ + return _PluginActive; +} + +void CGraphPlugin::unsetDlgGraph() +{ + _PluginActive=false; +} + + +void CGraphPlugin::doSelection(const string& primPath) +{ + IPrimitive *rootNode; + + TPrimitiveClassPredicate pred("root"); + TPrimitiveSet resSet; + + if(_PluginAccess->getCurrentSelection().size()>0) + { + + try + { + rootNode=(IPrimitive*)_PluginAccess->getRootNode(_rootFileName); + + selectPrimByPath(rootNode,primPath,resSet); + + _PluginAccess->setCurrentSelection(resSet); + + }catch(exception e){ + GraphDlg->MessageBox(e.what()); + } + } } \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/graph_plugin.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/graph_plugin.h index 213aecc62..a2ffd159d 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/graph_plugin.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/graph_plugin.h @@ -1,102 +1,102 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//graph_plugin.h - - -#ifndef GRAPH_PLUGIN -#define GRAPH_PLUGIN - -#include "..\world_editor\plugin_interface.h" -#include "world_editor_graph_plugin_dlg.h" - - - -class CGraphPlugin : public IPluginCallback -{ - -public: - CGraphPlugin(); - virtual ~CGraphPlugin(); - // @{ - // \name Overload for IPluginCallback - virtual void init(IPluginAccess *pluginAccess); - - /// The current region has changed. -// virtual void primRegionChanged(const std::vector ®ions); - virtual void primitiveChanged(const NLLIGO::IPrimitive *root); - - /// The region has been modifed. -// virtual void primRegionModifed(); - /// The listener has been moved on the map. - virtual void positionMoved(const NLMISC::CVector &position); - /// The plugin lost the control of the position - virtual void lostPositionControl(); - - virtual void onIdle(); - - virtual std::string& getName(); - - virtual bool isActive(); - - virtual bool activatePlugin(); - - virtual bool closePlugin(); - - void doSelection(const std::string&); - void refreshPrimitives(); - void refreshMachine(); - void unsetDlgGraph(); - std::string generateDotScript(NLLIGO::IPrimitive* managerNode); - std::string parseStateMachine(NLLIGO::IPrimitive* currentNode,std::string emiterNode,std::string tailLabel,std::string tag); - std::string spaceTo_(std::string strInput); - std::string createNode(NLLIGO::IPrimitive* managerNode,std::string strPredicate,uint& numClusters,std::string strShape); - std::string createParsedNode(NLLIGO::IPrimitive* managerNode,std::string strPredicate,uint& numClusters,std::string strShape); -private: - - bool createBitmap (const std::string& tmpPath); - - std::string _DotPath; - - // Graph DLG - CWorldEditorGraphPluginDlg *GraphDlg; - - /// The world editor interface. - IPluginAccess *_PluginAccess; - - //Plugin's name - std::string _Name; - - //set to true if the plugin is currently shown - bool _PluginActive; - - //Root's FileName, frome _dataHierarchy - std::string _rootFileName; - - -}; - -extern "C" -{ - /// Export the C factory method for dynamic linking.. - //__declspec( dllexport ) void *createSoundPlugin(); - __declspec( dllexport ) void *createPlugin(); - - - -}; - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//graph_plugin.h + + +#ifndef GRAPH_PLUGIN +#define GRAPH_PLUGIN + +#include "..\world_editor\plugin_interface.h" +#include "world_editor_graph_plugin_dlg.h" + + + +class CGraphPlugin : public IPluginCallback +{ + +public: + CGraphPlugin(); + virtual ~CGraphPlugin(); + // @{ + // \name Overload for IPluginCallback + virtual void init(IPluginAccess *pluginAccess); + + /// The current region has changed. +// virtual void primRegionChanged(const std::vector ®ions); + virtual void primitiveChanged(const NLLIGO::IPrimitive *root); + + /// The region has been modifed. +// virtual void primRegionModifed(); + /// The listener has been moved on the map. + virtual void positionMoved(const NLMISC::CVector &position); + /// The plugin lost the control of the position + virtual void lostPositionControl(); + + virtual void onIdle(); + + virtual std::string& getName(); + + virtual bool isActive(); + + virtual bool activatePlugin(); + + virtual bool closePlugin(); + + void doSelection(const std::string&); + void refreshPrimitives(); + void refreshMachine(); + void unsetDlgGraph(); + std::string generateDotScript(NLLIGO::IPrimitive* managerNode); + std::string parseStateMachine(NLLIGO::IPrimitive* currentNode,std::string emiterNode,std::string tailLabel,std::string tag); + std::string spaceTo_(std::string strInput); + std::string createNode(NLLIGO::IPrimitive* managerNode,std::string strPredicate,uint& numClusters,std::string strShape); + std::string createParsedNode(NLLIGO::IPrimitive* managerNode,std::string strPredicate,uint& numClusters,std::string strShape); +private: + + bool createBitmap (const std::string& tmpPath); + + std::string _DotPath; + + // Graph DLG + CWorldEditorGraphPluginDlg *GraphDlg; + + /// The world editor interface. + IPluginAccess *_PluginAccess; + + //Plugin's name + std::string _Name; + + //set to true if the plugin is currently shown + bool _PluginActive; + + //Root's FileName, frome _dataHierarchy + std::string _rootFileName; + + +}; + +extern "C" +{ + /// Export the C factory method for dynamic linking.. + //__declspec( dllexport ) void *createSoundPlugin(); + __declspec( dllexport ) void *createPlugin(); + + + +}; + #endif \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/resource.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/resource.h index 80f998853..d75c4cb35 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/resource.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/resource.h @@ -1,46 +1,46 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by world_editor_graph_plugin.rc -// -#define IDM_ABOUTBOX 0x0010 -#define IDD_ABOUTBOX 100 -#define IDS_ABOUTBOX 101 -#define IDD_WORLDEDITORGRAPHPLUGIN_DIALOG 102 -#define IDR_MAINFRAME 128 -#define IDR_IMG1 129 -#define IDC_BORDER 1000 -#define IDC_SCROLLBAR_HORZ 1001 -#define IDC_SCROLLBAR_VERT 1002 -#define IDC_Z_50 1003 -#define IDC_Z_100 1004 -#define IDC_Z_200 1005 -#define IDC_Z_150 1006 -#define IDREFRESH 1008 -#define IDC_IMAGE_FRAME 1010 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 130 -#define _APS_NEXT_COMMAND_VALUE 32771 -#define _APS_NEXT_CONTROL_VALUE 1012 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by world_editor_graph_plugin.rc +// +#define IDM_ABOUTBOX 0x0010 +#define IDD_ABOUTBOX 100 +#define IDS_ABOUTBOX 101 +#define IDD_WORLDEDITORGRAPHPLUGIN_DIALOG 102 +#define IDR_MAINFRAME 128 +#define IDR_IMG1 129 +#define IDC_BORDER 1000 +#define IDC_SCROLLBAR_HORZ 1001 +#define IDC_SCROLLBAR_VERT 1002 +#define IDC_Z_50 1003 +#define IDC_Z_100 1004 +#define IDC_Z_200 1005 +#define IDC_Z_150 1006 +#define IDREFRESH 1008 +#define IDC_IMAGE_FRAME 1010 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 130 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1012 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin.cpp index 516b60fe6..e391ce7bd 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin.cpp @@ -1,92 +1,92 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// world_editor_graph_plugin.cpp : Defines the class behaviors for the application. -// - -#include "stdafx.h" -#include "world_editor_graph_plugin.h" -#include "world_editor_graph_plugin_dlg.h" - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorGraphPluginApp - -BEGIN_MESSAGE_MAP(CWorldEditorGraphPluginApp, CWinApp) - //{{AFX_MSG_MAP(CWorldEditorGraphPluginApp) - // NOTE - the ClassWizard will add and remove mapping macros here. - // DO NOT EDIT what you see in these blocks of generated code! - //}}AFX_MSG - ON_COMMAND(ID_HELP, CWinApp::OnHelp) -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorGraphPluginApp construction - -CWorldEditorGraphPluginApp::CWorldEditorGraphPluginApp() -{ - // TODO: add construction code here, - // Place all significant initialization in InitInstance -} - -///////////////////////////////////////////////////////////////////////////// -// The one and only CWorldEditorGraphPluginApp object - -// if we put that, it failed to load the dll : -// "A dynamic link library (DLL) initialization routine failed." -//CWorldEditorGraphPluginApp theApp; - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorGraphPluginApp initialization - -BOOL CWorldEditorGraphPluginApp::InitInstance() -{ - AfxEnableControlContainer(); - - // Standard initialization - // If you are not using these features and wish to reduce the size - // of your final executable, you should remove from the following - // the specific initialization routines you do not need. - -#ifdef _AFXDLL - Enable3dControls(); // Call this when using MFC in a shared DLL -#else - Enable3dControlsStatic(); // Call this when linking to MFC statically -#endif - - - CWorldEditorGraphPluginDlg dlg; - m_pMainWnd = &dlg; - int nResponse = dlg.DoModal(); - if (nResponse == IDOK) - { - // TODO: Place code here to handle when the dialog is - // dismissed with OK - } - else if (nResponse == IDCANCEL) - { - // TODO: Place code here to handle when the dialog is - // dismissed with Cancel - } - - // Since the dialog has been closed, return FALSE so that we exit the - // application, rather than start the application's message pump. - return FALSE; -} - -int CWorldEditorGraphPluginApp::ExitInstance() -{ - return CWinApp::ExitInstance(); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// world_editor_graph_plugin.cpp : Defines the class behaviors for the application. +// + +#include "stdafx.h" +#include "world_editor_graph_plugin.h" +#include "world_editor_graph_plugin_dlg.h" + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorGraphPluginApp + +BEGIN_MESSAGE_MAP(CWorldEditorGraphPluginApp, CWinApp) + //{{AFX_MSG_MAP(CWorldEditorGraphPluginApp) + // NOTE - the ClassWizard will add and remove mapping macros here. + // DO NOT EDIT what you see in these blocks of generated code! + //}}AFX_MSG + ON_COMMAND(ID_HELP, CWinApp::OnHelp) +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorGraphPluginApp construction + +CWorldEditorGraphPluginApp::CWorldEditorGraphPluginApp() +{ + // TODO: add construction code here, + // Place all significant initialization in InitInstance +} + +///////////////////////////////////////////////////////////////////////////// +// The one and only CWorldEditorGraphPluginApp object + +// if we put that, it failed to load the dll : +// "A dynamic link library (DLL) initialization routine failed." +//CWorldEditorGraphPluginApp theApp; + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorGraphPluginApp initialization + +BOOL CWorldEditorGraphPluginApp::InitInstance() +{ + AfxEnableControlContainer(); + + // Standard initialization + // If you are not using these features and wish to reduce the size + // of your final executable, you should remove from the following + // the specific initialization routines you do not need. + +#ifdef _AFXDLL + Enable3dControls(); // Call this when using MFC in a shared DLL +#else + Enable3dControlsStatic(); // Call this when linking to MFC statically +#endif + + + CWorldEditorGraphPluginDlg dlg; + m_pMainWnd = &dlg; + int nResponse = dlg.DoModal(); + if (nResponse == IDOK) + { + // TODO: Place code here to handle when the dialog is + // dismissed with OK + } + else if (nResponse == IDCANCEL) + { + // TODO: Place code here to handle when the dialog is + // dismissed with Cancel + } + + // Since the dialog has been closed, return FALSE so that we exit the + // application, rather than start the application's message pump. + return FALSE; +} + +int CWorldEditorGraphPluginApp::ExitInstance() +{ + return CWinApp::ExitInstance(); +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin.h index bb23de3f1..5ab74a9ce 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin.h @@ -1,67 +1,67 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// world_editor_graph_plugin.h : main header file for the world_editor_graph_plugin application -// - -#if !defined(AFX_WORLDEDITORGRAPHPLUGIN_H__4CC93544_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_) -#define AFX_WORLDEDITORGRAPHPLUGIN_H__4CC93544_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#ifndef __AFXWIN_H__ - #error include 'stdafx.h' before including this file for PCH -#endif - -#include "resource.h" // main symbols - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorGraphPluginApp: -// See world_editor_graph_plugin.cpp for the implementation of this class -// - -class CWorldEditorGraphPluginApp : public CWinApp -{ -public: - CWorldEditorGraphPluginApp(); - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CWorldEditorGraphPluginApp) - public: - virtual BOOL InitInstance(); - virtual int ExitInstance(); - //}}AFX_VIRTUAL - -// Implementation - - //{{AFX_MSG(CWorldEditorGraphPluginApp) - // NOTE - the ClassWizard will add and remove member functions here. - // DO NOT EDIT what you see in these blocks of generated code ! - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - -}; - - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_WORLDEDITORGRAPHPLUGIN_H__4CC93544_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// world_editor_graph_plugin.h : main header file for the world_editor_graph_plugin application +// + +#if !defined(AFX_WORLDEDITORGRAPHPLUGIN_H__4CC93544_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_) +#define AFX_WORLDEDITORGRAPHPLUGIN_H__4CC93544_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#ifndef __AFXWIN_H__ + #error include 'stdafx.h' before including this file for PCH +#endif + +#include "resource.h" // main symbols + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorGraphPluginApp: +// See world_editor_graph_plugin.cpp for the implementation of this class +// + +class CWorldEditorGraphPluginApp : public CWinApp +{ +public: + CWorldEditorGraphPluginApp(); + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CWorldEditorGraphPluginApp) + public: + virtual BOOL InitInstance(); + virtual int ExitInstance(); + //}}AFX_VIRTUAL + +// Implementation + + //{{AFX_MSG(CWorldEditorGraphPluginApp) + // NOTE - the ClassWizard will add and remove member functions here. + // DO NOT EDIT what you see in these blocks of generated code ! + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + +}; + + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_WORLDEDITORGRAPHPLUGIN_H__4CC93544_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin_dlg.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin_dlg.cpp index ac3596475..f21ead4f5 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin_dlg.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin_dlg.cpp @@ -1,767 +1,767 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// world_editor_graph_plugin_dlg.cpp : implementation file -// - -#include "stdafx.h" -#include "nel/misc/types_nl.h" -#include -#include -#include -#include -#include -#include "nel/misc/common.h" -#include "graph_plugin.h" -#include "world_editor_graph_plugin_dlg.h" - -using namespace NLMISC; -using namespace NLLIGO; -using namespace std; - -///////////////////////////////////////////////////////////////////////////// -// CAboutDlg dialog used for App About - -class CAboutDlg : public CDialog -{ -public: - CAboutDlg(); - -// Dialog Data - //{{AFX_DATA(CAboutDlg) - enum { IDD = IDD_ABOUTBOX }; - //}}AFX_DATA - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CAboutDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual void OnPaint(); - //}}AFX_VIRTUAL - -// Implementation -protected: - //{{AFX_MSG(CAboutDlg) - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) -{ - //{{AFX_DATA_INIT(CAboutDlg) - //}}AFX_DATA_INIT -} -void CAboutDlg::OnPaint()/*:CDialog::OnPaint()*/ -{ - CDialog::OnPaint(); -} -void CAboutDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CAboutDlg) - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) - //{{AFX_MSG_MAP(CAboutDlg) - // No message handlers - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorGraphPluginDlg dialog - -CWorldEditorGraphPluginDlg::CWorldEditorGraphPluginDlg(CWnd* pParent /*=NULL*/) - : CDialog(CWorldEditorGraphPluginDlg::IDD, pParent) -{ - //{{AFX_DATA_INIT(CWorldEditorGraphPluginDlg) - // NOTE: the ClassWizard will add member initialization here - //}}AFX_DATA_INIT - // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 - m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); -} - -void CWorldEditorGraphPluginDlg::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CWorldEditorGraphPluginDlg) - DDX_Control(pDX, IDC_BORDER, m_border); - DDX_Control(pDX, IDC_IMAGE_FRAME, m_mainFrame); - DDX_Control(pDX, IDC_SCROLLBAR_VERT, m_scroll_vert); - DDX_Control(pDX, IDC_SCROLLBAR_HORZ, m_scroll_horz); - //}}AFX_DATA_MAP -} - -BEGIN_MESSAGE_MAP(CWorldEditorGraphPluginDlg, CDialog) - //{{AFX_MSG_MAP(CWorldEditorGraphPluginDlg) - ON_WM_SYSCOMMAND() - ON_WM_PAINT() - ON_WM_QUERYDRAGICON() - ON_WM_VSCROLL() - ON_WM_HSCROLL() - ON_BN_CLICKED(IDC_Z_50, OnZ50) - ON_BN_CLICKED(IDC_Z_100, OnZ100) - ON_BN_CLICKED(IDC_Z_150, OnZ150) - ON_BN_CLICKED(IDC_Z_200, OnZ200) - ON_WM_LBUTTONDOWN() - ON_WM_RBUTTONDOWN() - ON_BN_CLICKED(IDREFRESH, OnRefresh) - ON_WM_CLOSE() - ON_WM_SIZE() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorGraphPluginDlg message handlers - -BOOL CWorldEditorGraphPluginDlg::OnInitDialog() -{ - CDialog::OnInitDialog(); - - // Add "About..." menu item to system menu. - - // IDM_ABOUTBOX must be in the system command range. - ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); - ASSERT(IDM_ABOUTBOX < 0xF000); - - RECT rect; - m_mainFrame.GetClientRect(&rect); - m_mainFrame.ClientToScreen(&rect); - ScreenToClient(&rect); - aff_size.left = rect.left; - aff_size.top = rect.top; - aff_size.right = rect.right; - aff_size.bottom = rect.bottom; - - magnifier=1; - #undef new - _DibBits=NULL; - - CMenu* pSysMenu = GetSystemMenu(FALSE); - if (pSysMenu != NULL) - { - CString strAboutMenu; - strAboutMenu.LoadString(IDS_ABOUTBOX); - if (!strAboutMenu.IsEmpty()) - { - pSysMenu->AppendMenu(MF_SEPARATOR); - pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); - } - } - - // Set the icon for this dialog. The framework does this automatically - // when the application's main window is not a dialog - SetIcon(m_hIcon, TRUE); // Set big icon - SetIcon(m_hIcon, FALSE); // Set small icon - - // TODO: Add extra initialization here - - return TRUE; // return TRUE unless you set the focus to a control -} - -void CWorldEditorGraphPluginDlg::OnSysCommand(UINT nID, LPARAM lParam) -{ - if ((nID & 0xFFF0) == IDM_ABOUTBOX) - { - CAboutDlg dlgAbout; - dlgAbout.DoModal(); - } - else - { - CDialog::OnSysCommand(nID, lParam); - } -} - -// If you add a minimize button to your dialog, you will need the code below -// to draw the icon. For MFC applications using the document/view model, -// this is automatically done for you by the framework. - -void CWorldEditorGraphPluginDlg::OnPaint() -{ - CDialog::OnPaint(); - - HDC hdc(m_mainFrame.GetDC()->GetSafeHdc()); - RECT rect; - RECT test; - GetClientRect(&test); - - int maxX,minX; - m_scroll_horz.GetScrollRange(&minX,&maxX); -////////////////////////////////////// - m_mainFrame.GetClientRect(&rect); - ClientToScreen(&rect); - ScreenToClient(&rect); - - aff_size.left = rect.left; - aff_size.top = rect.top; - aff_size.right = (LONG)(rect.left+_DibBitmapInfo.bmiHeader.biWidth*(float)magnifier); - aff_size.bottom = (LONG)(rect.top+_DibBitmapInfo.bmiHeader.biHeight*(float)magnifier); - - ::CRect img_src_size; - - img_src_size.left = 0; - img_src_size.top = 0; - img_src_size.right = _DibBitmapInfo.bmiHeader.biWidth; - img_src_size.bottom = _DibBitmapInfo.bmiHeader.biHeight; - - int decX=m_scroll_horz.GetScrollPos(),decY=m_scroll_vert.GetScrollPos(); - - uint32 imgWidLd=uint32(_DibBitmapInfo.bmiHeader.biWidth*(float)magnifier),imgHgtLd=uint32(_DibBitmapInfo.bmiHeader.biHeight*(float)magnifier); - - if(rect.right-rect.left<_DibBitmapInfo.bmiHeader.biWidth*(float)magnifier) - { - imgWidLd=rect.right-rect.left; - img_src_size.left=LONG(decX/(float)magnifier); - img_src_size.right=LONG(img_src_size.left+imgWidLd/(float)magnifier); - aff_size.right = rect.right; - } - - if(rect.bottom-rect.top<_DibBitmapInfo.bmiHeader.biHeight*(float)magnifier) - { - imgHgtLd=rect.bottom-rect.top; - img_src_size.top=LONG(_DibBitmapInfo.bmiHeader.biHeight-imgHgtLd/(float)magnifier-decY/(float)magnifier); - img_src_size.bottom=LONG(_DibBitmapInfo.bmiHeader.biHeight-decY/(float)magnifier); - aff_size.bottom=rect.bottom; - } - - - StretchDIBits( - hdc, // handle to DC - aff_size.left, // x-coord of destination upper-left corner - aff_size.top, // y-coord of destination upper-left corner - aff_size.Width(), // width of destination rectangle - aff_size.Height(), // height of destination rectangle - img_src_size.left, // x-coord of source upper-left corner - img_src_size.top, // y-coord of source upper-left corner - img_src_size.Width(), // width of source rectangle - img_src_size.Height(), // height of source rectangle - _DibBits, // bitmap bits - &_DibBitmapInfo, // bitmap data - DIB_RGB_COLORS, // usage options - SRCCOPY // raster operation code - ); - - -} - -// The system calls this to obtain the cursor to display while the user drags -// the minimized window. -HCURSOR CWorldEditorGraphPluginDlg::OnQueryDragIcon() -{ - return (HCURSOR) m_hIcon; -} - -void CWorldEditorGraphPluginDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) -{ - // TODO: Add your message handler code here and/or call default - int CurPos = pScrollBar->GetScrollPos(); - int maxpos=0,minpos=0; -// INT imax, imin; - m_scroll_horz.GetScrollRange(&minpos, &maxpos); - - // Determine the new position of scroll box. - switch (nSBCode) - { - case SB_LEFT: // Scroll to far left. - CurPos = 0; - break; - - case SB_RIGHT: // Scroll to far right. - CurPos = maxpos; - break; - - case SB_ENDSCROLL: // End scroll. - break; - - case SB_LINELEFT: // Scroll left. - if (CurPos > 0) - CurPos--; - break; - - case SB_LINERIGHT: // Scroll right. - if (CurPos < maxpos) - CurPos++; - break; - - case SB_PAGELEFT: // Scroll one page left. - { - // Get the page size. - SCROLLINFO info; - pScrollBar->GetScrollInfo(&info, SIF_ALL); - - if (CurPos > 0) - CurPos = std::max(0, CurPos - (int) info.nPage); - } - break; - - case SB_PAGERIGHT: // Scroll one page right - { - // Get the page size. - SCROLLINFO info; - pScrollBar->GetScrollInfo(&info, SIF_ALL); - - if (CurPos < maxpos) - CurPos = std::min(maxpos, CurPos + (int) info.nPage); - } - break; - - case SB_THUMBPOSITION: // Scroll to absolute position. nPos is the position - CurPos = nPos; // of the scroll box at the end of the drag operation. - break; - - case SB_THUMBTRACK: // Drag scroll box to specified position. nPos is the - CurPos = nPos; // position that the scroll box has been dragged to. - break; - } - - // Set the new position of the thumb (scroll box). - pScrollBar->SetScrollPos(CurPos); - - CDialog::OnVScroll(nSBCode, nPos, pScrollBar); - RECT dlgRect; - m_mainFrame.GetClientRect(&dlgRect); - m_mainFrame.ClientToScreen(&dlgRect); - ScreenToClient(&dlgRect); - InvalidateRect(&dlgRect); -} - - -void CWorldEditorGraphPluginDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) -{ - // TODO: Add your message handler code here and/or call default - int CurPos = pScrollBar->GetScrollPos(); - int maxpos=0,minpos=0; -// LPINT lpmax=NULL,lpmin=NULL; - m_scroll_horz.GetScrollRange(&minpos, &maxpos); - - // Determine the new position of scroll box. - switch (nSBCode) - { - case SB_TOP: // Scroll to far left. - CurPos = 0; - break; - - case SB_BOTTOM: // Scroll to far right. - CurPos = maxpos; - break; - - case SB_ENDSCROLL: // End scroll. - break; - - case SB_LINEUP: // Scroll left. - if (CurPos > 0) - CurPos--; - break; - - case SB_LINEDOWN: // Scroll right. - if (CurPos GetScrollInfo(&info, SIF_ALL); - - if (CurPos > 0) - CurPos = std::max(0, CurPos - (int) info.nPage); - } - break; - - case SB_PAGEDOWN: // Scroll one page right - { - // Get the page size. - SCROLLINFO info; - pScrollBar->GetScrollInfo(&info, SIF_ALL); - - if (CurPos < maxpos) - CurPos = std::min(maxpos, CurPos + (int) info.nPage); - } - break; - - case SB_THUMBPOSITION: // Scroll to absolute position. nPos is the position - CurPos = nPos; // of the scroll box at the end of the drag operation. - break; - - case SB_THUMBTRACK: // Drag scroll box to specified position. nPos is the - CurPos = nPos; // position that the scroll box has been dragged to. - break; - } - - // Set the new position of the thumb (scroll box). - pScrollBar->SetScrollPos(CurPos); - - CDialog::OnHScroll(nSBCode, nPos, pScrollBar); - - RECT dlgRect; - m_mainFrame.GetClientRect(&dlgRect); - m_mainFrame.ClientToScreen(&dlgRect); - ScreenToClient(&dlgRect); - InvalidateRect(&dlgRect); -// Invalidate(); -} - - - -void CWorldEditorGraphPluginDlg::OnZ50() -{ - magnifier=0.5; - - rescaleScroll(); - RECT dlgRect; - m_mainFrame.GetClientRect(&dlgRect); - m_mainFrame.ClientToScreen(&dlgRect); - ScreenToClient(&dlgRect); - InvalidateRect(&dlgRect); -// Invalidate(); -} - -void CWorldEditorGraphPluginDlg::OnZ100() -{ - // TODO: Add your control notification handler code here - magnifier=1; - - rescaleScroll(); - RECT dlgRect; - m_mainFrame.GetClientRect(&dlgRect); - m_mainFrame.ClientToScreen(&dlgRect); - ScreenToClient(&dlgRect); - InvalidateRect(&dlgRect); -// Invalidate(); -} - -void CWorldEditorGraphPluginDlg::OnZ150() -{ - // TODO: Add your control notification handler code here - magnifier=1.5; - - rescaleScroll(); - RECT dlgRect; - m_mainFrame.GetClientRect(&dlgRect); - m_mainFrame.ClientToScreen(&dlgRect); - ScreenToClient(&dlgRect); - InvalidateRect(&dlgRect); -// Invalidate(); -} - -void CWorldEditorGraphPluginDlg::OnZ200() -{ - // TODO: Add your control notification handler code here - magnifier=2; - - rescaleScroll(); - RECT dlgRect; - m_mainFrame.GetClientRect(&dlgRect); - m_mainFrame.ClientToScreen(&dlgRect); - ScreenToClient(&dlgRect); - InvalidateRect(&dlgRect); -// Invalidate(); -} - -void CWorldEditorGraphPluginDlg::OnRButtonDown(UINT nFlags, CPoint point) -{ - - if(_DibBits!=NULL) - { - //get the correct coordinates - ClientToScreen(&point); - m_mainFrame.ScreenToClient(&point); - ::CRect rect; - m_mainFrame.GetClientRect(&rect); - - CPaintDC dc(this); - - sint32 tmpAff; - if (isWithin(rect,point)) - { - if (((point.x-getXCenter(rect) +m_scroll_horz.GetScrollPos())0)) - { - tmpAff=point.x-getXCenter(rect) +m_scroll_horz.GetScrollPos(); - m_scroll_horz.SetScrollPos(tmpAff); - } - else - { - if ((point.x-getXCenter(rect) +m_scroll_horz.GetScrollPos())<0) - { - tmpAff=0; - m_scroll_horz.SetScrollPos(tmpAff); - } - else - { - tmpAff = sint32(magnifier*_DibBitmapInfo.bmiHeader.biWidth-getXCenter(rect)); - m_scroll_horz.SetScrollPos(tmpAff); - } - } - - - if (((point.y-getYCenter(rect) +m_scroll_vert.GetScrollPos())>0)&&((point.y-getYCenter(rect) +m_scroll_vert.GetScrollPos())<_DibBitmapInfo.bmiHeader.biHeight*magnifier)) - { - tmpAff=point.y-getYCenter(rect) +m_scroll_vert.GetScrollPos(); - m_scroll_vert.SetScrollPos(tmpAff); - } - else - { - if ((point.y-getYCenter(rect) +m_scroll_vert.GetScrollPos())<0) - { - tmpAff=0; - m_scroll_vert.SetScrollPos(tmpAff); - } - else - { - tmpAff=sint32(magnifier*_DibBitmapInfo.bmiHeader.biHeight-getYCenter(rect)); - m_scroll_vert.SetScrollPos(tmpAff); - } - } - } - CDialog::OnRButtonDown(nFlags, point); - RECT dlgRect; - m_mainFrame.GetClientRect(&dlgRect); - m_mainFrame.ClientToScreen(&dlgRect); - ScreenToClient(&dlgRect); - InvalidateRect(&dlgRect); - } -} - -void CWorldEditorGraphPluginDlg::OnLButtonDown(UINT nFlags, CPoint point) -{ - - if(_DibBits!=NULL) - { - // TODO: Add your message handler code here and/or call default - string tmpPath = string(::getenv("TEMP")); - ifstream cmap((tmpPath+"/output.imap").c_str()); - - if(cmap.is_open()) - { - - //get the correct coordinates - ClientToScreen(&point); - m_mainFrame.ScreenToClient(&point); - - char *bufferCH=new char[256]; - cmap.getline(bufferCH,256); - std::string strBuff(bufferCH); - cmap.getline(bufferCH,256); - strBuff=bufferCH; - CPoint iRes2,iRes3; - char *ret=new char[256]; - std::vector strRes,strRes2,strRes3; - strcpy(ret,"Nothing to point to"); - double cmpx = 1/magnifier, cmpy = 1/magnifier; - - ::CRect rect; - m_mainFrame.GetClientRect(&rect); - ::CRect tok; - int x,y; - - while(strcmp(bufferCH,"")!=0) - { - - x=point.x; - y=point.y; - - try{ - explode(strBuff,string(" "),strRes,true); - explode(strRes.at(2),string(","),strRes2,true); - explode(strRes.at(3),string(","),strRes3,true); - tok.left=atoi(strRes2.at(0).c_str()); - tok.top=atoi(strRes2.at(1).c_str()); - tok.right=atoi(strRes3.at(0).c_str()); - tok.bottom=atoi(strRes3.at(1).c_str()); - }catch (exception e) {return;} - - - - x = int(x*cmpx); - y = int(y*cmpy); - x = int(x+(m_scroll_horz.GetScrollPos())*cmpx); - y = int(y+(m_scroll_vert.GetScrollPos())*cmpy); - - - - if(isWithin(tok,CPoint(x,y))) - { - //strcpy(ret,.c_str()); - - - graph_plug->doSelection(strRes.at(1)); - - - break; - } - - cmap.getline(bufferCH,256); - strBuff=bufferCH; - - } - - cmap.close(); - delete []ret; - delete []bufferCH; - } - } - - CDialog::OnLButtonDown(nFlags, point); - -} - - - -void CWorldEditorGraphPluginDlg::OnRefresh() -{ - // TODO: Add your control notification handler code here - - graph_plug->refreshPrimitives(); - OnZ100(); - rescaleScroll(); - RECT dlgRect; - m_mainFrame.GetClientRect(&dlgRect); - m_mainFrame.ClientToScreen(&dlgRect); - ScreenToClient(&dlgRect); - InvalidateRect(&dlgRect); -} - -void CWorldEditorGraphPluginDlg::init(CGraphPlugin* plugin) -{ - graph_plug=plugin; -} - -void CWorldEditorGraphPluginDlg::OnClose() -{ - // TODO: Add your message handler code here and/or call default - graph_plug->unsetDlgGraph(); - CDialog::OnClose(); -} - -CWorldEditorGraphPluginDlg::~CWorldEditorGraphPluginDlg() -{ -} - -void CWorldEditorGraphPluginDlg::OnSize(UINT nType, int cx, int cy) -{ - CDialog::OnSize(nType, cx, cy); - - // 1st place the 'border' relative to new dialg size - RECT dlgRect; - GetClientRect(&dlgRect); - ClientToScreen(&dlgRect); - RECT rect; - m_border.GetWindowRect(&rect); - rect.left = dlgRect.left; - rect.right = dlgRect.right; - rect.bottom = dlgRect.bottom; - ScreenToClient(&rect); - m_border.MoveWindow(&rect, true); - - // 2nd, place other component relative to border client surface - m_border.GetClientRect(&dlgRect); - m_border.ClientToScreen(&dlgRect); - - m_scroll_vert.GetWindowRect(&rect); - rect.top = dlgRect.top; - rect.left = dlgRect.right-16; - rect.right = dlgRect.right; - rect.bottom = dlgRect.bottom-16; - ScreenToClient(&rect); - m_scroll_vert.MoveWindow(&rect, true); - - m_scroll_horz.GetWindowRect(&rect); - rect.left = dlgRect.left; - rect.right = dlgRect.right-16; - rect.top = dlgRect.bottom-16; - rect.bottom = dlgRect.bottom; - ScreenToClient(&rect); - m_scroll_horz.MoveWindow(&rect, true); - - m_mainFrame.GetWindowRect(&rect); - rect.top = dlgRect.top; - rect.left = dlgRect.left; - rect.right = dlgRect.right-16; - rect.bottom = dlgRect.bottom-16; - ScreenToClient(&rect); - m_mainFrame.MoveWindow(&rect, true); - - rescaleScroll(); - Invalidate(); - - -} - -void CWorldEditorGraphPluginDlg::rescaleScroll() -{ - if (_DibBits) - { - RECT rect; - m_mainFrame.GetClientRect(&rect); - - // recompute slider size - m_scroll_vert.EnableWindow(TRUE); - m_scroll_horz.EnableWindow(TRUE); - SCROLLINFO si; - si.cbSize = sizeof(SCROLLINFO); - si.fMask = SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL; - si.nMin = 0; - si.nMax = int(_DibBitmapInfo.bmiHeader.biHeight*magnifier); - si.nPage = rect.bottom; - - m_scroll_vert.SetScrollInfo(&si, true); - si.nMax = int(_DibBitmapInfo.bmiHeader.biWidth*magnifier); - si.nPage = rect.right; - m_scroll_horz.SetScrollInfo(&si, true); - } - else - { - m_scroll_vert.EnableWindow(FALSE); - m_scroll_horz.EnableWindow(FALSE); - } -} - - -bool CWorldEditorGraphPluginDlg::isWithin(::CRect &rect,CPoint &point) -{ - if (rect.leftpoint.x) - { - if (rect.bottom>point.y) - { - if (rect.topunsetDlgGraph(); - CDialog::OnCancel(); -} - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// world_editor_graph_plugin_dlg.cpp : implementation file +// + +#include "stdafx.h" +#include "nel/misc/types_nl.h" +#include +#include +#include +#include +#include +#include "nel/misc/common.h" +#include "graph_plugin.h" +#include "world_editor_graph_plugin_dlg.h" + +using namespace NLMISC; +using namespace NLLIGO; +using namespace std; + +///////////////////////////////////////////////////////////////////////////// +// CAboutDlg dialog used for App About + +class CAboutDlg : public CDialog +{ +public: + CAboutDlg(); + +// Dialog Data + //{{AFX_DATA(CAboutDlg) + enum { IDD = IDD_ABOUTBOX }; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CAboutDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual void OnPaint(); + //}}AFX_VIRTUAL + +// Implementation +protected: + //{{AFX_MSG(CAboutDlg) + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD) +{ + //{{AFX_DATA_INIT(CAboutDlg) + //}}AFX_DATA_INIT +} +void CAboutDlg::OnPaint()/*:CDialog::OnPaint()*/ +{ + CDialog::OnPaint(); +} +void CAboutDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CAboutDlg) + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) + //{{AFX_MSG_MAP(CAboutDlg) + // No message handlers + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorGraphPluginDlg dialog + +CWorldEditorGraphPluginDlg::CWorldEditorGraphPluginDlg(CWnd* pParent /*=NULL*/) + : CDialog(CWorldEditorGraphPluginDlg::IDD, pParent) +{ + //{{AFX_DATA_INIT(CWorldEditorGraphPluginDlg) + // NOTE: the ClassWizard will add member initialization here + //}}AFX_DATA_INIT + // Note that LoadIcon does not require a subsequent DestroyIcon in Win32 + m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); +} + +void CWorldEditorGraphPluginDlg::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CWorldEditorGraphPluginDlg) + DDX_Control(pDX, IDC_BORDER, m_border); + DDX_Control(pDX, IDC_IMAGE_FRAME, m_mainFrame); + DDX_Control(pDX, IDC_SCROLLBAR_VERT, m_scroll_vert); + DDX_Control(pDX, IDC_SCROLLBAR_HORZ, m_scroll_horz); + //}}AFX_DATA_MAP +} + +BEGIN_MESSAGE_MAP(CWorldEditorGraphPluginDlg, CDialog) + //{{AFX_MSG_MAP(CWorldEditorGraphPluginDlg) + ON_WM_SYSCOMMAND() + ON_WM_PAINT() + ON_WM_QUERYDRAGICON() + ON_WM_VSCROLL() + ON_WM_HSCROLL() + ON_BN_CLICKED(IDC_Z_50, OnZ50) + ON_BN_CLICKED(IDC_Z_100, OnZ100) + ON_BN_CLICKED(IDC_Z_150, OnZ150) + ON_BN_CLICKED(IDC_Z_200, OnZ200) + ON_WM_LBUTTONDOWN() + ON_WM_RBUTTONDOWN() + ON_BN_CLICKED(IDREFRESH, OnRefresh) + ON_WM_CLOSE() + ON_WM_SIZE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorGraphPluginDlg message handlers + +BOOL CWorldEditorGraphPluginDlg::OnInitDialog() +{ + CDialog::OnInitDialog(); + + // Add "About..." menu item to system menu. + + // IDM_ABOUTBOX must be in the system command range. + ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); + ASSERT(IDM_ABOUTBOX < 0xF000); + + RECT rect; + m_mainFrame.GetClientRect(&rect); + m_mainFrame.ClientToScreen(&rect); + ScreenToClient(&rect); + aff_size.left = rect.left; + aff_size.top = rect.top; + aff_size.right = rect.right; + aff_size.bottom = rect.bottom; + + magnifier=1; + #undef new + _DibBits=NULL; + + CMenu* pSysMenu = GetSystemMenu(FALSE); + if (pSysMenu != NULL) + { + CString strAboutMenu; + strAboutMenu.LoadString(IDS_ABOUTBOX); + if (!strAboutMenu.IsEmpty()) + { + pSysMenu->AppendMenu(MF_SEPARATOR); + pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); + } + } + + // Set the icon for this dialog. The framework does this automatically + // when the application's main window is not a dialog + SetIcon(m_hIcon, TRUE); // Set big icon + SetIcon(m_hIcon, FALSE); // Set small icon + + // TODO: Add extra initialization here + + return TRUE; // return TRUE unless you set the focus to a control +} + +void CWorldEditorGraphPluginDlg::OnSysCommand(UINT nID, LPARAM lParam) +{ + if ((nID & 0xFFF0) == IDM_ABOUTBOX) + { + CAboutDlg dlgAbout; + dlgAbout.DoModal(); + } + else + { + CDialog::OnSysCommand(nID, lParam); + } +} + +// If you add a minimize button to your dialog, you will need the code below +// to draw the icon. For MFC applications using the document/view model, +// this is automatically done for you by the framework. + +void CWorldEditorGraphPluginDlg::OnPaint() +{ + CDialog::OnPaint(); + + HDC hdc(m_mainFrame.GetDC()->GetSafeHdc()); + RECT rect; + RECT test; + GetClientRect(&test); + + int maxX,minX; + m_scroll_horz.GetScrollRange(&minX,&maxX); +////////////////////////////////////// + m_mainFrame.GetClientRect(&rect); + ClientToScreen(&rect); + ScreenToClient(&rect); + + aff_size.left = rect.left; + aff_size.top = rect.top; + aff_size.right = (LONG)(rect.left+_DibBitmapInfo.bmiHeader.biWidth*(float)magnifier); + aff_size.bottom = (LONG)(rect.top+_DibBitmapInfo.bmiHeader.biHeight*(float)magnifier); + + ::CRect img_src_size; + + img_src_size.left = 0; + img_src_size.top = 0; + img_src_size.right = _DibBitmapInfo.bmiHeader.biWidth; + img_src_size.bottom = _DibBitmapInfo.bmiHeader.biHeight; + + int decX=m_scroll_horz.GetScrollPos(),decY=m_scroll_vert.GetScrollPos(); + + uint32 imgWidLd=uint32(_DibBitmapInfo.bmiHeader.biWidth*(float)magnifier),imgHgtLd=uint32(_DibBitmapInfo.bmiHeader.biHeight*(float)magnifier); + + if(rect.right-rect.left<_DibBitmapInfo.bmiHeader.biWidth*(float)magnifier) + { + imgWidLd=rect.right-rect.left; + img_src_size.left=LONG(decX/(float)magnifier); + img_src_size.right=LONG(img_src_size.left+imgWidLd/(float)magnifier); + aff_size.right = rect.right; + } + + if(rect.bottom-rect.top<_DibBitmapInfo.bmiHeader.biHeight*(float)magnifier) + { + imgHgtLd=rect.bottom-rect.top; + img_src_size.top=LONG(_DibBitmapInfo.bmiHeader.biHeight-imgHgtLd/(float)magnifier-decY/(float)magnifier); + img_src_size.bottom=LONG(_DibBitmapInfo.bmiHeader.biHeight-decY/(float)magnifier); + aff_size.bottom=rect.bottom; + } + + + StretchDIBits( + hdc, // handle to DC + aff_size.left, // x-coord of destination upper-left corner + aff_size.top, // y-coord of destination upper-left corner + aff_size.Width(), // width of destination rectangle + aff_size.Height(), // height of destination rectangle + img_src_size.left, // x-coord of source upper-left corner + img_src_size.top, // y-coord of source upper-left corner + img_src_size.Width(), // width of source rectangle + img_src_size.Height(), // height of source rectangle + _DibBits, // bitmap bits + &_DibBitmapInfo, // bitmap data + DIB_RGB_COLORS, // usage options + SRCCOPY // raster operation code + ); + + +} + +// The system calls this to obtain the cursor to display while the user drags +// the minimized window. +HCURSOR CWorldEditorGraphPluginDlg::OnQueryDragIcon() +{ + return (HCURSOR) m_hIcon; +} + +void CWorldEditorGraphPluginDlg::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + // TODO: Add your message handler code here and/or call default + int CurPos = pScrollBar->GetScrollPos(); + int maxpos=0,minpos=0; +// INT imax, imin; + m_scroll_horz.GetScrollRange(&minpos, &maxpos); + + // Determine the new position of scroll box. + switch (nSBCode) + { + case SB_LEFT: // Scroll to far left. + CurPos = 0; + break; + + case SB_RIGHT: // Scroll to far right. + CurPos = maxpos; + break; + + case SB_ENDSCROLL: // End scroll. + break; + + case SB_LINELEFT: // Scroll left. + if (CurPos > 0) + CurPos--; + break; + + case SB_LINERIGHT: // Scroll right. + if (CurPos < maxpos) + CurPos++; + break; + + case SB_PAGELEFT: // Scroll one page left. + { + // Get the page size. + SCROLLINFO info; + pScrollBar->GetScrollInfo(&info, SIF_ALL); + + if (CurPos > 0) + CurPos = std::max(0, CurPos - (int) info.nPage); + } + break; + + case SB_PAGERIGHT: // Scroll one page right + { + // Get the page size. + SCROLLINFO info; + pScrollBar->GetScrollInfo(&info, SIF_ALL); + + if (CurPos < maxpos) + CurPos = std::min(maxpos, CurPos + (int) info.nPage); + } + break; + + case SB_THUMBPOSITION: // Scroll to absolute position. nPos is the position + CurPos = nPos; // of the scroll box at the end of the drag operation. + break; + + case SB_THUMBTRACK: // Drag scroll box to specified position. nPos is the + CurPos = nPos; // position that the scroll box has been dragged to. + break; + } + + // Set the new position of the thumb (scroll box). + pScrollBar->SetScrollPos(CurPos); + + CDialog::OnVScroll(nSBCode, nPos, pScrollBar); + RECT dlgRect; + m_mainFrame.GetClientRect(&dlgRect); + m_mainFrame.ClientToScreen(&dlgRect); + ScreenToClient(&dlgRect); + InvalidateRect(&dlgRect); +} + + +void CWorldEditorGraphPluginDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) +{ + // TODO: Add your message handler code here and/or call default + int CurPos = pScrollBar->GetScrollPos(); + int maxpos=0,minpos=0; +// LPINT lpmax=NULL,lpmin=NULL; + m_scroll_horz.GetScrollRange(&minpos, &maxpos); + + // Determine the new position of scroll box. + switch (nSBCode) + { + case SB_TOP: // Scroll to far left. + CurPos = 0; + break; + + case SB_BOTTOM: // Scroll to far right. + CurPos = maxpos; + break; + + case SB_ENDSCROLL: // End scroll. + break; + + case SB_LINEUP: // Scroll left. + if (CurPos > 0) + CurPos--; + break; + + case SB_LINEDOWN: // Scroll right. + if (CurPos GetScrollInfo(&info, SIF_ALL); + + if (CurPos > 0) + CurPos = std::max(0, CurPos - (int) info.nPage); + } + break; + + case SB_PAGEDOWN: // Scroll one page right + { + // Get the page size. + SCROLLINFO info; + pScrollBar->GetScrollInfo(&info, SIF_ALL); + + if (CurPos < maxpos) + CurPos = std::min(maxpos, CurPos + (int) info.nPage); + } + break; + + case SB_THUMBPOSITION: // Scroll to absolute position. nPos is the position + CurPos = nPos; // of the scroll box at the end of the drag operation. + break; + + case SB_THUMBTRACK: // Drag scroll box to specified position. nPos is the + CurPos = nPos; // position that the scroll box has been dragged to. + break; + } + + // Set the new position of the thumb (scroll box). + pScrollBar->SetScrollPos(CurPos); + + CDialog::OnHScroll(nSBCode, nPos, pScrollBar); + + RECT dlgRect; + m_mainFrame.GetClientRect(&dlgRect); + m_mainFrame.ClientToScreen(&dlgRect); + ScreenToClient(&dlgRect); + InvalidateRect(&dlgRect); +// Invalidate(); +} + + + +void CWorldEditorGraphPluginDlg::OnZ50() +{ + magnifier=0.5; + + rescaleScroll(); + RECT dlgRect; + m_mainFrame.GetClientRect(&dlgRect); + m_mainFrame.ClientToScreen(&dlgRect); + ScreenToClient(&dlgRect); + InvalidateRect(&dlgRect); +// Invalidate(); +} + +void CWorldEditorGraphPluginDlg::OnZ100() +{ + // TODO: Add your control notification handler code here + magnifier=1; + + rescaleScroll(); + RECT dlgRect; + m_mainFrame.GetClientRect(&dlgRect); + m_mainFrame.ClientToScreen(&dlgRect); + ScreenToClient(&dlgRect); + InvalidateRect(&dlgRect); +// Invalidate(); +} + +void CWorldEditorGraphPluginDlg::OnZ150() +{ + // TODO: Add your control notification handler code here + magnifier=1.5; + + rescaleScroll(); + RECT dlgRect; + m_mainFrame.GetClientRect(&dlgRect); + m_mainFrame.ClientToScreen(&dlgRect); + ScreenToClient(&dlgRect); + InvalidateRect(&dlgRect); +// Invalidate(); +} + +void CWorldEditorGraphPluginDlg::OnZ200() +{ + // TODO: Add your control notification handler code here + magnifier=2; + + rescaleScroll(); + RECT dlgRect; + m_mainFrame.GetClientRect(&dlgRect); + m_mainFrame.ClientToScreen(&dlgRect); + ScreenToClient(&dlgRect); + InvalidateRect(&dlgRect); +// Invalidate(); +} + +void CWorldEditorGraphPluginDlg::OnRButtonDown(UINT nFlags, CPoint point) +{ + + if(_DibBits!=NULL) + { + //get the correct coordinates + ClientToScreen(&point); + m_mainFrame.ScreenToClient(&point); + ::CRect rect; + m_mainFrame.GetClientRect(&rect); + + CPaintDC dc(this); + + sint32 tmpAff; + if (isWithin(rect,point)) + { + if (((point.x-getXCenter(rect) +m_scroll_horz.GetScrollPos())0)) + { + tmpAff=point.x-getXCenter(rect) +m_scroll_horz.GetScrollPos(); + m_scroll_horz.SetScrollPos(tmpAff); + } + else + { + if ((point.x-getXCenter(rect) +m_scroll_horz.GetScrollPos())<0) + { + tmpAff=0; + m_scroll_horz.SetScrollPos(tmpAff); + } + else + { + tmpAff = sint32(magnifier*_DibBitmapInfo.bmiHeader.biWidth-getXCenter(rect)); + m_scroll_horz.SetScrollPos(tmpAff); + } + } + + + if (((point.y-getYCenter(rect) +m_scroll_vert.GetScrollPos())>0)&&((point.y-getYCenter(rect) +m_scroll_vert.GetScrollPos())<_DibBitmapInfo.bmiHeader.biHeight*magnifier)) + { + tmpAff=point.y-getYCenter(rect) +m_scroll_vert.GetScrollPos(); + m_scroll_vert.SetScrollPos(tmpAff); + } + else + { + if ((point.y-getYCenter(rect) +m_scroll_vert.GetScrollPos())<0) + { + tmpAff=0; + m_scroll_vert.SetScrollPos(tmpAff); + } + else + { + tmpAff=sint32(magnifier*_DibBitmapInfo.bmiHeader.biHeight-getYCenter(rect)); + m_scroll_vert.SetScrollPos(tmpAff); + } + } + } + CDialog::OnRButtonDown(nFlags, point); + RECT dlgRect; + m_mainFrame.GetClientRect(&dlgRect); + m_mainFrame.ClientToScreen(&dlgRect); + ScreenToClient(&dlgRect); + InvalidateRect(&dlgRect); + } +} + +void CWorldEditorGraphPluginDlg::OnLButtonDown(UINT nFlags, CPoint point) +{ + + if(_DibBits!=NULL) + { + // TODO: Add your message handler code here and/or call default + string tmpPath = string(::getenv("TEMP")); + ifstream cmap((tmpPath+"/output.imap").c_str()); + + if(cmap.is_open()) + { + + //get the correct coordinates + ClientToScreen(&point); + m_mainFrame.ScreenToClient(&point); + + char *bufferCH=new char[256]; + cmap.getline(bufferCH,256); + std::string strBuff(bufferCH); + cmap.getline(bufferCH,256); + strBuff=bufferCH; + CPoint iRes2,iRes3; + char *ret=new char[256]; + std::vector strRes,strRes2,strRes3; + strcpy(ret,"Nothing to point to"); + double cmpx = 1/magnifier, cmpy = 1/magnifier; + + ::CRect rect; + m_mainFrame.GetClientRect(&rect); + ::CRect tok; + int x,y; + + while(strcmp(bufferCH,"")!=0) + { + + x=point.x; + y=point.y; + + try{ + explode(strBuff,string(" "),strRes,true); + explode(strRes.at(2),string(","),strRes2,true); + explode(strRes.at(3),string(","),strRes3,true); + tok.left=atoi(strRes2.at(0).c_str()); + tok.top=atoi(strRes2.at(1).c_str()); + tok.right=atoi(strRes3.at(0).c_str()); + tok.bottom=atoi(strRes3.at(1).c_str()); + }catch (exception e) {return;} + + + + x = int(x*cmpx); + y = int(y*cmpy); + x = int(x+(m_scroll_horz.GetScrollPos())*cmpx); + y = int(y+(m_scroll_vert.GetScrollPos())*cmpy); + + + + if(isWithin(tok,CPoint(x,y))) + { + //strcpy(ret,.c_str()); + + + graph_plug->doSelection(strRes.at(1)); + + + break; + } + + cmap.getline(bufferCH,256); + strBuff=bufferCH; + + } + + cmap.close(); + delete []ret; + delete []bufferCH; + } + } + + CDialog::OnLButtonDown(nFlags, point); + +} + + + +void CWorldEditorGraphPluginDlg::OnRefresh() +{ + // TODO: Add your control notification handler code here + + graph_plug->refreshPrimitives(); + OnZ100(); + rescaleScroll(); + RECT dlgRect; + m_mainFrame.GetClientRect(&dlgRect); + m_mainFrame.ClientToScreen(&dlgRect); + ScreenToClient(&dlgRect); + InvalidateRect(&dlgRect); +} + +void CWorldEditorGraphPluginDlg::init(CGraphPlugin* plugin) +{ + graph_plug=plugin; +} + +void CWorldEditorGraphPluginDlg::OnClose() +{ + // TODO: Add your message handler code here and/or call default + graph_plug->unsetDlgGraph(); + CDialog::OnClose(); +} + +CWorldEditorGraphPluginDlg::~CWorldEditorGraphPluginDlg() +{ +} + +void CWorldEditorGraphPluginDlg::OnSize(UINT nType, int cx, int cy) +{ + CDialog::OnSize(nType, cx, cy); + + // 1st place the 'border' relative to new dialg size + RECT dlgRect; + GetClientRect(&dlgRect); + ClientToScreen(&dlgRect); + RECT rect; + m_border.GetWindowRect(&rect); + rect.left = dlgRect.left; + rect.right = dlgRect.right; + rect.bottom = dlgRect.bottom; + ScreenToClient(&rect); + m_border.MoveWindow(&rect, true); + + // 2nd, place other component relative to border client surface + m_border.GetClientRect(&dlgRect); + m_border.ClientToScreen(&dlgRect); + + m_scroll_vert.GetWindowRect(&rect); + rect.top = dlgRect.top; + rect.left = dlgRect.right-16; + rect.right = dlgRect.right; + rect.bottom = dlgRect.bottom-16; + ScreenToClient(&rect); + m_scroll_vert.MoveWindow(&rect, true); + + m_scroll_horz.GetWindowRect(&rect); + rect.left = dlgRect.left; + rect.right = dlgRect.right-16; + rect.top = dlgRect.bottom-16; + rect.bottom = dlgRect.bottom; + ScreenToClient(&rect); + m_scroll_horz.MoveWindow(&rect, true); + + m_mainFrame.GetWindowRect(&rect); + rect.top = dlgRect.top; + rect.left = dlgRect.left; + rect.right = dlgRect.right-16; + rect.bottom = dlgRect.bottom-16; + ScreenToClient(&rect); + m_mainFrame.MoveWindow(&rect, true); + + rescaleScroll(); + Invalidate(); + + +} + +void CWorldEditorGraphPluginDlg::rescaleScroll() +{ + if (_DibBits) + { + RECT rect; + m_mainFrame.GetClientRect(&rect); + + // recompute slider size + m_scroll_vert.EnableWindow(TRUE); + m_scroll_horz.EnableWindow(TRUE); + SCROLLINFO si; + si.cbSize = sizeof(SCROLLINFO); + si.fMask = SIF_RANGE | SIF_PAGE | SIF_DISABLENOSCROLL; + si.nMin = 0; + si.nMax = int(_DibBitmapInfo.bmiHeader.biHeight*magnifier); + si.nPage = rect.bottom; + + m_scroll_vert.SetScrollInfo(&si, true); + si.nMax = int(_DibBitmapInfo.bmiHeader.biWidth*magnifier); + si.nPage = rect.right; + m_scroll_horz.SetScrollInfo(&si, true); + } + else + { + m_scroll_vert.EnableWindow(FALSE); + m_scroll_horz.EnableWindow(FALSE); + } +} + + +bool CWorldEditorGraphPluginDlg::isWithin(::CRect &rect,CPoint &point) +{ + if (rect.leftpoint.x) + { + if (rect.bottom>point.y) + { + if (rect.topunsetDlgGraph(); + CDialog::OnCancel(); +} + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin_dlg.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin_dlg.h index 78b49761a..92304617c 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin_dlg.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_graph_plugin/world_editor_graph_plugin_dlg.h @@ -1,110 +1,110 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// world_editor_graph_plugin_dlg.h : header file -// - -#if !defined(AFX_WORLDEDITORGRAPHPLUGINDLG_H__4CC93546_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_) -#define AFX_WORLDEDITORGRAPHPLUGINDLG_H__4CC93546_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_ - - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -class CGraphPlugin; - -#include "resource.h" -#include "nel/misc/types_nl.h" -///////////////////////////////////////////////////////////////////////////// -// CWorldEditorGraphPluginDlg dialog - -#include "stdafx.h" - -class CWorldEditorGraphPluginDlg : public CDialog -{ -// Construction -public: - CWorldEditorGraphPluginDlg(CWnd* pParent = NULL); // standard constructor - ~CWorldEditorGraphPluginDlg(); - void init(CGraphPlugin*); - void refresh(); - void rescaleScroll(); - bool isWithin(CRect &rect,CPoint &point); - int getXCenter(CRect &rect); - int getYCenter(CRect &rect); -// Dialog Data - //{{AFX_DATA(CWorldEditorGraphPluginDlg) - enum { IDD = IDD_WORLDEDITORGRAPHPLUGIN_DIALOG }; - CStatic m_border; - CStatic m_mainFrame; - CScrollBar m_scroll_vert; - CScrollBar m_scroll_horz; - //}}AFX_DATA - - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CWorldEditorGraphPluginDlg) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnInitDialog(); - - //}}AFX_VIRTUAL - -// Implementation -public: - - HBITMAP _Hbmp; - - HBITMAP _Hdib; - - BITMAPINFO _DibBitmapInfo; - - uint8* _DibBits; - -protected: - HICON m_hIcon; - CRect aff_size; - CGraphPlugin *graph_plug; - double magnifier; - //UINT m_magnifier; - // Generated message map functions - //{{AFX_MSG(CWorldEditorGraphPluginDlg) - afx_msg void OnSysCommand(UINT nID, LPARAM lParam); - afx_msg void OnPaint(); - afx_msg HCURSOR OnQueryDragIcon(); - afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); - afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); - afx_msg void OnZ50(); - afx_msg void OnZ100(); - afx_msg void OnZ150(); - afx_msg void OnZ200(); - afx_msg void OnLButtonDown(UINT nFlags, CPoint point); - afx_msg void OnRButtonDown(UINT nFlags, CPoint point); - afx_msg void OnRefresh(); - afx_msg void OnClose(); - afx_msg void OnSize(UINT nType, int cx, int cy); - virtual void OnCancel(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() - - - -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_WORLDEDITORGRAPHPLUGINDLG_H__4CC93546_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// world_editor_graph_plugin_dlg.h : header file +// + +#if !defined(AFX_WORLDEDITORGRAPHPLUGINDLG_H__4CC93546_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_) +#define AFX_WORLDEDITORGRAPHPLUGINDLG_H__4CC93546_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_ + + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +class CGraphPlugin; + +#include "resource.h" +#include "nel/misc/types_nl.h" +///////////////////////////////////////////////////////////////////////////// +// CWorldEditorGraphPluginDlg dialog + +#include "stdafx.h" + +class CWorldEditorGraphPluginDlg : public CDialog +{ +// Construction +public: + CWorldEditorGraphPluginDlg(CWnd* pParent = NULL); // standard constructor + ~CWorldEditorGraphPluginDlg(); + void init(CGraphPlugin*); + void refresh(); + void rescaleScroll(); + bool isWithin(CRect &rect,CPoint &point); + int getXCenter(CRect &rect); + int getYCenter(CRect &rect); +// Dialog Data + //{{AFX_DATA(CWorldEditorGraphPluginDlg) + enum { IDD = IDD_WORLDEDITORGRAPHPLUGIN_DIALOG }; + CStatic m_border; + CStatic m_mainFrame; + CScrollBar m_scroll_vert; + CScrollBar m_scroll_horz; + //}}AFX_DATA + + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CWorldEditorGraphPluginDlg) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnInitDialog(); + + //}}AFX_VIRTUAL + +// Implementation +public: + + HBITMAP _Hbmp; + + HBITMAP _Hdib; + + BITMAPINFO _DibBitmapInfo; + + uint8* _DibBits; + +protected: + HICON m_hIcon; + CRect aff_size; + CGraphPlugin *graph_plug; + double magnifier; + //UINT m_magnifier; + // Generated message map functions + //{{AFX_MSG(CWorldEditorGraphPluginDlg) + afx_msg void OnSysCommand(UINT nID, LPARAM lParam); + afx_msg void OnPaint(); + afx_msg HCURSOR OnQueryDragIcon(); + afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar); + afx_msg void OnZ50(); + afx_msg void OnZ100(); + afx_msg void OnZ150(); + afx_msg void OnZ200(); + afx_msg void OnLButtonDown(UINT nFlags, CPoint point); + afx_msg void OnRButtonDown(UINT nFlags, CPoint point); + afx_msg void OnRefresh(); + afx_msg void OnClose(); + afx_msg void OnSize(UINT nType, int cx, int cy); + virtual void OnCancel(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() + + + +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_WORLDEDITORGRAPHPLUGINDLG_H__4CC93546_46D9_11D5_AE4A_0080ADB4DF70__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/CMakeLists.txt b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/CMakeLists.txt index 1a91cd575..f12eab168 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/CMakeLists.txt +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/CMakeLists.txt @@ -1,26 +1,26 @@ -FILE(GLOB SRC *.cpp *.h) - -ADD_LIBRARY(world_editor_plugin SHARED ${SRC} world_editor_plugin.rc) - -INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) - -TARGET_LINK_LIBRARIES(world_editor_plugin - nelmisc - nel3d - nelsound - nelsnd_lowlevel - Version.lib) - -NL_DEFAULT_PROPS(world_editor_plugin "Ryzom, Tools, World: World Editor Plugin DLL") -NL_ADD_RUNTIME_FLAGS(world_editor_plugin) -NL_ADD_LIB_SUFFIX(world_editor_plugin) - -ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} ${MFC_DEFINITIONS} -DOBJECT_VIEWER_LIB_EXPORTS) - -IF(WITH_PCH) - ADD_NATIVE_PRECOMPILED_HEADER(world_editor_plugin ${CMAKE_CURRENT_SOURCE_DIR}/StdAfx.h ${CMAKE_CURRENT_SOURCE_DIR}/StdAfx.cpp) -ENDIF(WITH_PCH) - -INSTALL(TARGETS world_editor_plugin LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) -INSTALL(FILES WorldEditorPlugin.cfg DESTINATION bin COMPONENT tools3d) - +FILE(GLOB SRC *.cpp *.h) + +ADD_LIBRARY(world_editor_plugin SHARED ${SRC} world_editor_plugin.rc) + +INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) + +TARGET_LINK_LIBRARIES(world_editor_plugin + nelmisc + nel3d + nelsound + nelsnd_lowlevel + Version.lib) + +NL_DEFAULT_PROPS(world_editor_plugin "Ryzom, Tools, World: World Editor Plugin DLL") +NL_ADD_RUNTIME_FLAGS(world_editor_plugin) +NL_ADD_LIB_SUFFIX(world_editor_plugin) + +ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} ${MFC_DEFINITIONS} -DOBJECT_VIEWER_LIB_EXPORTS) + +IF(WITH_PCH) + ADD_NATIVE_PRECOMPILED_HEADER(world_editor_plugin ${CMAKE_CURRENT_SOURCE_DIR}/StdAfx.h ${CMAKE_CURRENT_SOURCE_DIR}/StdAfx.cpp) +ENDIF(WITH_PCH) + +INSTALL(TARGETS world_editor_plugin LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) +INSTALL(FILES WorldEditorPlugin.cfg DESTINATION bin COMPONENT tools3d) + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/DialogFlags.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/DialogFlags.cpp index eeed7ca0f..812215d0e 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/DialogFlags.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/DialogFlags.cpp @@ -1,77 +1,77 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// DailogFlags.cpp : implementation file -// - -#include "stdafx.h" -#include "DialogFlags.h" -#include -#include "plugin.h" - -using namespace std; -using namespace NLMISC; -using namespace NLSOUND; - -///////////////////////////////////////////////////////////////////////////// -// CDialogFlags dialog - - -CDialogFlags::CDialogFlags(CWnd* pParent /*=NULL*/) - : CDialog(CDialogFlags::IDD, pParent) -{ -} - -void CDialogFlags::init(CPlugin *plugin) -{ - _Plugin = plugin; -} - -void CDialogFlags::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CDialogFlags) - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CDialogFlags, CDialog) - //{{AFX_MSG_MAP(CDialogFlags) - ON_WM_CREATE() - ON_WM_DESTROY() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - - -int CDialogFlags::OnCreate(LPCREATESTRUCT lpCreateStruct) -{ - if (CDialog::OnCreate(lpCreateStruct) == -1) - return -1; - // TODO: Add your specialized creation code here - return 0; -} - -void CDialogFlags::OnDestroy() -{ - CDialog::OnDestroy(); - // TODO: Add your message handler code here -} - -BOOL CDialogFlags::OnCommand(WPARAM wParam, LPARAM lParam) -{ - // TODO: Add your specialized code here and/or call the base class - return CDialog::OnCommand(wParam, lParam); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// DailogFlags.cpp : implementation file +// + +#include "stdafx.h" +#include "DialogFlags.h" +#include +#include "plugin.h" + +using namespace std; +using namespace NLMISC; +using namespace NLSOUND; + +///////////////////////////////////////////////////////////////////////////// +// CDialogFlags dialog + + +CDialogFlags::CDialogFlags(CWnd* pParent /*=NULL*/) + : CDialog(CDialogFlags::IDD, pParent) +{ +} + +void CDialogFlags::init(CPlugin *plugin) +{ + _Plugin = plugin; +} + +void CDialogFlags::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDialogFlags) + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDialogFlags, CDialog) + //{{AFX_MSG_MAP(CDialogFlags) + ON_WM_CREATE() + ON_WM_DESTROY() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +int CDialogFlags::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CDialog::OnCreate(lpCreateStruct) == -1) + return -1; + // TODO: Add your specialized creation code here + return 0; +} + +void CDialogFlags::OnDestroy() +{ + CDialog::OnDestroy(); + // TODO: Add your message handler code here +} + +BOOL CDialogFlags::OnCommand(WPARAM wParam, LPARAM lParam) +{ + // TODO: Add your specialized code here and/or call the base class + return CDialog::OnCommand(wParam, lParam); +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/DialogFlags.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/DialogFlags.h index a935ae1f3..0794d1e5f 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/DialogFlags.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/DialogFlags.h @@ -1,75 +1,75 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_) -#define AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// DailogFlags.h : header file -// - -#include "stdafx.h" -#include "resource.h" -#include "nel/sound/u_audio_mixer.h" - - -class CPlugin; - -///////////////////////////////////////////////////////////////////////////// -// CDialogFlags dialog - -class CDialogFlags : public CDialog -{ -// Construction -public: - CDialogFlags(/*NLSOUND::UAudioMixer *mixer,*/ CWnd* pParent = NULL); // standard constructor - - void init(CPlugin *plugin); -// Dialog Data - //{{AFX_DATA(CDialogFlags) - enum { IDD = IDD_DIALOG_FLAGS }; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CDialogFlags) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - //}}AFX_VIRTUAL - - -// Implementation - -protected: - - - CPlugin *_Plugin; - // Generated message map functions - //{{AFX_MSG(CDialogFlags) - afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); - afx_msg void OnDestroy(); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_) +#define AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DailogFlags.h : header file +// + +#include "stdafx.h" +#include "resource.h" +#include "nel/sound/u_audio_mixer.h" + + +class CPlugin; + +///////////////////////////////////////////////////////////////////////////// +// CDialogFlags dialog + +class CDialogFlags : public CDialog +{ +// Construction +public: + CDialogFlags(/*NLSOUND::UAudioMixer *mixer,*/ CWnd* pParent = NULL); // standard constructor + + void init(CPlugin *plugin); +// Dialog Data + //{{AFX_DATA(CDialogFlags) + enum { IDD = IDD_DIALOG_FLAGS }; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDialogFlags) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + + +// Implementation + +protected: + + + CPlugin *_Plugin; + // Generated message map functions + //{{AFX_MSG(CDialogFlags) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnDestroy(); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/LoadDialog.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/LoadDialog.cpp index 90a033733..0da73baca 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/LoadDialog.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/LoadDialog.cpp @@ -1,53 +1,53 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// LoadDialog.cpp : implementation file -// - -#include "stdafx.h" -#include "resource.h" -#include "LoadDialog.h" - -///////////////////////////////////////////////////////////////////////////// -// CLoadDialog dialog - - -CLoadDialog::CLoadDialog(CWnd* pParent /*=NULL*/) - : CDialog(CLoadDialog::IDD, pParent) -{ - //{{AFX_DATA_INIT(CLoadDialog) - Message = _T(""); - //}}AFX_DATA_INIT -} - - -void CLoadDialog::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CLoadDialog) - DDX_Text(pDX, IDC_STATIC_MESSAGE, Message); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CLoadDialog, CDialog) - //{{AFX_MSG_MAP(CLoadDialog) - // NOTE: the ClassWizard will add message map macros here - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CLoadDialog message handlers +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// LoadDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "resource.h" +#include "LoadDialog.h" + +///////////////////////////////////////////////////////////////////////////// +// CLoadDialog dialog + + +CLoadDialog::CLoadDialog(CWnd* pParent /*=NULL*/) + : CDialog(CLoadDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CLoadDialog) + Message = _T(""); + //}}AFX_DATA_INIT +} + + +void CLoadDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLoadDialog) + DDX_Text(pDX, IDC_STATIC_MESSAGE, Message); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLoadDialog, CDialog) + //{{AFX_MSG_MAP(CLoadDialog) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLoadDialog message handlers diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/LoadDialog.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/LoadDialog.h index 0eee7b149..2f90fd23e 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/LoadDialog.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/LoadDialog.h @@ -1,62 +1,62 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_LOADDIALOG_H__3F11071D_1F55_433E_964D_E953168443AC__INCLUDED_) -#define AFX_LOADDIALOG_H__3F11071D_1F55_433E_964D_E953168443AC__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// LoadDialog.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CLoadDialog dialog - -class CLoadDialog : public CDialog -{ -// Construction -public: - CLoadDialog(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CLoadDialog) - enum { IDD = IDD_DIALOG_LOAD }; - CString Message; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CLoadDialog) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CLoadDialog) - // NOTE: the ClassWizard will add member functions here - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_LOADDIALOG_H__3F11071D_1F55_433E_964D_E953168443AC__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_LOADDIALOG_H__3F11071D_1F55_433E_964D_E953168443AC__INCLUDED_) +#define AFX_LOADDIALOG_H__3F11071D_1F55_433E_964D_E953168443AC__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LoadDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLoadDialog dialog + +class CLoadDialog : public CDialog +{ +// Construction +public: + CLoadDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CLoadDialog) + enum { IDD = IDD_DIALOG_LOAD }; + CString Message; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLoadDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLoadDialog) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LOADDIALOG_H__3F11071D_1F55_433E_964D_E953168443AC__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/StdAfx.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/StdAfx.cpp index b61ba02cd..b67d952bd 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/StdAfx.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/StdAfx.cpp @@ -1,24 +1,24 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.cpp : source file that includes just the standard includes -// World_Editor.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.cpp : source file that includes just the standard includes +// World_Editor.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/StdAfx.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/StdAfx.h index 1a4822a4b..01d4fe59a 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/StdAfx.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/StdAfx.h @@ -1,50 +1,50 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_) -#define AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_ - -#pragma warning(disable : 4786) - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC Automation classes -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -#undef min -#undef max - -#include -#include "nel/misc/common.h" - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_) +#define AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_ + +#pragma warning(disable : 4786) + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#undef min +#undef max + +#include +#include "nel/misc/common.h" + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/plugin.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/plugin.cpp index dcfd244d9..ff837c912 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/plugin.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/plugin.cpp @@ -1,345 +1,345 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -/* - Petite documentation sur le fonctionnement du plugin - -1) Le WorldEditor se connecte au plugin (config dans WorldEditorPlugin.cfg) - -2) Le plugin se connecte au World_Editor_Service - -3) Le World_Editor_Service (config dans WorldEditorService.cfg) envoie des paquets contenant au maximum 100 joueurs. -Ces joueurs sont soit nouveaux, soit leurs coordonnées ont changé. - -4) Les informations des joueurs sont envoyées (voir onIdle) sous forme de primitives "player": - -Voici la définition de la primitive "player", dans WORLD_EDITOR_SCRIPT.XML - - - - - - - - - - - -5) World_Editor_Service utilise un cache pour stocker les déplacements des joueurs, afin de n'envoyer que ce qui bouge - -6) World_Editor_Plugin utilise aussi un cache avec un pointeur sur les Primitives, afin de ne modifier dans WE que ce qui bouge - -*/ -#include "stdafx.h" -#include "plugin.h" -#include "resource.h" -#include "nel/misc/path.h" -#include "LoadDialog.h" -#include "nel/sound/u_listener.h" - -using namespace NLMISC; -using namespace NLLIGO; -using namespace NLSOUND; -using namespace NLNET; -using namespace std; - - -class Player -{ -public: - string _name; - float _x, _y; - const IPrimitive *primitive; - // Constructor - Player::Player() - { - primitive = NULL; - } - - Player::Player(string name, float x, float y) - { - primitive = NULL; - _name = name; - _x = x; - _y = y; - } - /// Destructor - Player::~Player() - { - } -}; - -vector StackPlayers; - -map StoredPlayers; - - -extern "C" -{ - void *createPlugin() - { - return new CPlugin(); - } -} - -CPlugin::CPlugin() - : _PluginAccess(0) -{ - m_Initialized = false; - _Client = NULL; - StackPlayers.clear(); -} - -CPlugin::~CPlugin() -{ - delete _Client; - - if (m_Initialized) - { - _PluginAccess->deleteRootPluginPrimitive(); - m_Initialized = false; - } -} - -void CPlugin::progress (float progressValue) -{ - /*char tmp[1024]; - sprintf(tmp, "Initializing mixer : %i%%", int(progressValue * 100)); - LoadDlg->Message = tmp; - LoadDlg->UpdateData(FALSE); - LoadDlg->RedrawWindow();*/ -} - -// *************************************************************************** -void serverSentPos (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - // Called when the server sent a POS message - uint32 count; - - msgin.serial(count); - for (uint i = 0;i < count;++i) - { - string name; - msgin.serial(name); - - float x, y; - msgin.serial(x); - msgin.serial(y); - // we received name, x, y, we save it in the stack - StackPlayers.push_back (Player(name, x, y)); - } -} - -// *************************************************************************** -void serverSentInfo (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - // Called when the server sent a INFO message - string text; - msgin.serial(text); - printf("%s\n", text.c_str()); -} - -// *************************************************************************** -// All messages handled by this server -#define NB_CB 2 -TCallbackItem CallbackArray[NB_CB] = -{ - { "POS", serverSentPos }, - { "INFO", serverSentInfo }, -}; - -void CPlugin::init(IPluginAccess *pluginAccess) -{ - CLoadDialog *LoadDlg; - - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - AfxEnableControlContainer(); - _PluginAccess = pluginAccess; - _PluginName="Player Plugin"; -//#undef new - LoadDlg = new CLoadDialog; -//#define new NL_NEW - LoadDlg->Create(IDD_DIALOG_LOAD); - LoadDlg->Message = "Connecting..."; - LoadDlg->UpdateData(FALSE); - //LoadDlg->Invalidate(); - LoadDlg->ShowWindow(SW_SHOW); - //LoadDlg->RedrawWindow(); - - // connect to the server here... - - // Read the host where to connect in the client.cfg file - CConfigFile ConfigFile; - ConfigFile.load ("client.cfg"); - string LSHost(ConfigFile.getVar("LSHost").asString()); - - // Init and Connect the client to the server located on port 3333 - _Client = new CCallbackClient(); - _Client->addCallbackArray (CallbackArray, NB_CB); - - //printf("Please wait connecting...\n"); - try - { - CInetAddress addr(LSHost+":48888"); - _Client->connect(addr); - } - catch(ESocket &e) - { - MessageBox (NULL, e.what(), "Error", MB_ICONERROR|MB_OK); - delete LoadDlg; - LoadDlg = 0; - return; - } - delete LoadDlg; - LoadDlg = 0; - - if (!_Client->connected()) - { - MessageBox (NULL, "The connection failed", "Error", MB_ICONERROR|MB_OK); - return; - } - -//#undef new - _DialogFlag = new CDialogFlags(/*_Mixer*/); -//#define new NL_NEW - // open the dialog flag window - _DialogFlag->Create(IDD_DIALOG_FLAGS, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); - _DialogFlag->init(this); - _DialogFlag->ShowWindow(TRUE); - - // - { - CMessage msg; - msg.setType("WINDOW"); - float xmin = 0; - float xmax = 10000; - float ymin = 0; - float ymax = 10000; - msg.serial (xmin); - msg.serial (ymin); - msg.serial (xmax); - msg.serial (ymax); - _Client->send(msg); - } -} - -/// The current region has changed. -void CPlugin::primitiveChanged(const NLLIGO::IPrimitive *root) -{ -} - -/// The listener has been moved on the map. -void CPlugin::positionMoved(const NLMISC::CVector &position) -{ -} - -void CPlugin::lostPositionControl() -{ -} - -void CPlugin::onIdle() -{ - if (_Client && _Client->connected()) - { - // during the first call, we create a Root primitive to store all players - if (!m_Initialized) - { - m_Initialized = true; - _PluginAccess->createRootPluginPrimitive(); - } - else - { - // first, we receive the stack of messages, which is composed of players informations - _Client->update(); - // now, we insert the players into the GUI - for (uint i = 0; i < StackPlayers.size(); ++i) - { - map::const_iterator ite; - ite = StoredPlayers.find(StackPlayers[i]._name); - if (ite == StoredPlayers.end()) - { - // if the player doesn't exist in the static list, we add it - //StoredPlayers.insert(map::value_type(StackPlayers[i]._name, StackPlayers[i])); - StoredPlayers[StackPlayers[i]._name] = StackPlayers[i]; - std::vector Parameters; - - Parameters.push_back (CPrimitiveClass::CInitParameters ()); - CPrimitiveClass::CInitParameters ¶m1 = Parameters.back (); - param1.DefaultValue.resize (1); - param1.Name = "x"; - param1.DefaultValue[0].GenID = false; - param1.DefaultValue[0].Name = toString(StackPlayers[i]._x); - - Parameters.push_back (CPrimitiveClass::CInitParameters ()); - CPrimitiveClass::CInitParameters ¶m2 = Parameters.back (); - param2.DefaultValue.resize (1); - param2 = Parameters.back (); - param2.Name = "y"; - param2.DefaultValue[0].GenID = false; - param2.DefaultValue[0].Name = toString(StackPlayers[i]._y); - - // create a player in WorldEditor - StoredPlayers[StackPlayers[i]._name].primitive = _PluginAccess->createPluginPrimitive("player",StackPlayers[i]._name.c_str(),NLMISC::CVector(StackPlayers[i]._x,StackPlayers[i]._y,0),0,Parameters); - } - else - { - // the player has moved, we need to change its coordinates - _PluginAccess->movePluginPrimitive(StoredPlayers[StackPlayers[i]._name].primitive, CVector(StackPlayers[i]._x, StackPlayers[i]._y, 0)); - } - } - // we clear the stack - StackPlayers.clear(); - } - } -} - -std::string& CPlugin::getName() -{ - return _PluginName; -} - -bool CPlugin::isActive() -{ - return _PluginActive; -} - -bool CPlugin::activatePlugin() -{ - if(!_PluginActive) - { - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - AfxEnableControlContainer(); - - //_DialogFlag->Create(IDD_DIALOG_FLAGS, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); - _DialogFlag->ShowWindow(TRUE); - //_DialogFlag->init(this); - _PluginActive=true; - return true; - } - return false; -} - -bool CPlugin::closePlugin() -{ - if (_PluginActive) - { - //_DialogFlag->CloseWindow(); - _DialogFlag->ShowWindow(FALSE); - _PluginActive=false; - return true; - } - return false; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +/* + Petite documentation sur le fonctionnement du plugin + +1) Le WorldEditor se connecte au plugin (config dans WorldEditorPlugin.cfg) + +2) Le plugin se connecte au World_Editor_Service + +3) Le World_Editor_Service (config dans WorldEditorService.cfg) envoie des paquets contenant au maximum 100 joueurs. +Ces joueurs sont soit nouveaux, soit leurs coordonnées ont changé. + +4) Les informations des joueurs sont envoyées (voir onIdle) sous forme de primitives "player": + +Voici la définition de la primitive "player", dans WORLD_EDITOR_SCRIPT.XML + + + + + + + + + + + +5) World_Editor_Service utilise un cache pour stocker les déplacements des joueurs, afin de n'envoyer que ce qui bouge + +6) World_Editor_Plugin utilise aussi un cache avec un pointeur sur les Primitives, afin de ne modifier dans WE que ce qui bouge + +*/ +#include "stdafx.h" +#include "plugin.h" +#include "resource.h" +#include "nel/misc/path.h" +#include "LoadDialog.h" +#include "nel/sound/u_listener.h" + +using namespace NLMISC; +using namespace NLLIGO; +using namespace NLSOUND; +using namespace NLNET; +using namespace std; + + +class Player +{ +public: + string _name; + float _x, _y; + const IPrimitive *primitive; + // Constructor + Player::Player() + { + primitive = NULL; + } + + Player::Player(string name, float x, float y) + { + primitive = NULL; + _name = name; + _x = x; + _y = y; + } + /// Destructor + Player::~Player() + { + } +}; + +vector StackPlayers; + +map StoredPlayers; + + +extern "C" +{ + void *createPlugin() + { + return new CPlugin(); + } +} + +CPlugin::CPlugin() + : _PluginAccess(0) +{ + m_Initialized = false; + _Client = NULL; + StackPlayers.clear(); +} + +CPlugin::~CPlugin() +{ + delete _Client; + + if (m_Initialized) + { + _PluginAccess->deleteRootPluginPrimitive(); + m_Initialized = false; + } +} + +void CPlugin::progress (float progressValue) +{ + /*char tmp[1024]; + sprintf(tmp, "Initializing mixer : %i%%", int(progressValue * 100)); + LoadDlg->Message = tmp; + LoadDlg->UpdateData(FALSE); + LoadDlg->RedrawWindow();*/ +} + +// *************************************************************************** +void serverSentPos (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + // Called when the server sent a POS message + uint32 count; + + msgin.serial(count); + for (uint i = 0;i < count;++i) + { + string name; + msgin.serial(name); + + float x, y; + msgin.serial(x); + msgin.serial(y); + // we received name, x, y, we save it in the stack + StackPlayers.push_back (Player(name, x, y)); + } +} + +// *************************************************************************** +void serverSentInfo (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + // Called when the server sent a INFO message + string text; + msgin.serial(text); + printf("%s\n", text.c_str()); +} + +// *************************************************************************** +// All messages handled by this server +#define NB_CB 2 +TCallbackItem CallbackArray[NB_CB] = +{ + { "POS", serverSentPos }, + { "INFO", serverSentInfo }, +}; + +void CPlugin::init(IPluginAccess *pluginAccess) +{ + CLoadDialog *LoadDlg; + + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + AfxEnableControlContainer(); + _PluginAccess = pluginAccess; + _PluginName="Player Plugin"; +//#undef new + LoadDlg = new CLoadDialog; +//#define new NL_NEW + LoadDlg->Create(IDD_DIALOG_LOAD); + LoadDlg->Message = "Connecting..."; + LoadDlg->UpdateData(FALSE); + //LoadDlg->Invalidate(); + LoadDlg->ShowWindow(SW_SHOW); + //LoadDlg->RedrawWindow(); + + // connect to the server here... + + // Read the host where to connect in the client.cfg file + CConfigFile ConfigFile; + ConfigFile.load ("client.cfg"); + string LSHost(ConfigFile.getVar("LSHost").asString()); + + // Init and Connect the client to the server located on port 3333 + _Client = new CCallbackClient(); + _Client->addCallbackArray (CallbackArray, NB_CB); + + //printf("Please wait connecting...\n"); + try + { + CInetAddress addr(LSHost+":48888"); + _Client->connect(addr); + } + catch(ESocket &e) + { + MessageBox (NULL, e.what(), "Error", MB_ICONERROR|MB_OK); + delete LoadDlg; + LoadDlg = 0; + return; + } + delete LoadDlg; + LoadDlg = 0; + + if (!_Client->connected()) + { + MessageBox (NULL, "The connection failed", "Error", MB_ICONERROR|MB_OK); + return; + } + +//#undef new + _DialogFlag = new CDialogFlags(/*_Mixer*/); +//#define new NL_NEW + // open the dialog flag window + _DialogFlag->Create(IDD_DIALOG_FLAGS, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); + _DialogFlag->init(this); + _DialogFlag->ShowWindow(TRUE); + + // + { + CMessage msg; + msg.setType("WINDOW"); + float xmin = 0; + float xmax = 10000; + float ymin = 0; + float ymax = 10000; + msg.serial (xmin); + msg.serial (ymin); + msg.serial (xmax); + msg.serial (ymax); + _Client->send(msg); + } +} + +/// The current region has changed. +void CPlugin::primitiveChanged(const NLLIGO::IPrimitive *root) +{ +} + +/// The listener has been moved on the map. +void CPlugin::positionMoved(const NLMISC::CVector &position) +{ +} + +void CPlugin::lostPositionControl() +{ +} + +void CPlugin::onIdle() +{ + if (_Client && _Client->connected()) + { + // during the first call, we create a Root primitive to store all players + if (!m_Initialized) + { + m_Initialized = true; + _PluginAccess->createRootPluginPrimitive(); + } + else + { + // first, we receive the stack of messages, which is composed of players informations + _Client->update(); + // now, we insert the players into the GUI + for (uint i = 0; i < StackPlayers.size(); ++i) + { + map::const_iterator ite; + ite = StoredPlayers.find(StackPlayers[i]._name); + if (ite == StoredPlayers.end()) + { + // if the player doesn't exist in the static list, we add it + //StoredPlayers.insert(map::value_type(StackPlayers[i]._name, StackPlayers[i])); + StoredPlayers[StackPlayers[i]._name] = StackPlayers[i]; + std::vector Parameters; + + Parameters.push_back (CPrimitiveClass::CInitParameters ()); + CPrimitiveClass::CInitParameters ¶m1 = Parameters.back (); + param1.DefaultValue.resize (1); + param1.Name = "x"; + param1.DefaultValue[0].GenID = false; + param1.DefaultValue[0].Name = toString(StackPlayers[i]._x); + + Parameters.push_back (CPrimitiveClass::CInitParameters ()); + CPrimitiveClass::CInitParameters ¶m2 = Parameters.back (); + param2.DefaultValue.resize (1); + param2 = Parameters.back (); + param2.Name = "y"; + param2.DefaultValue[0].GenID = false; + param2.DefaultValue[0].Name = toString(StackPlayers[i]._y); + + // create a player in WorldEditor + StoredPlayers[StackPlayers[i]._name].primitive = _PluginAccess->createPluginPrimitive("player",StackPlayers[i]._name.c_str(),NLMISC::CVector(StackPlayers[i]._x,StackPlayers[i]._y,0),0,Parameters); + } + else + { + // the player has moved, we need to change its coordinates + _PluginAccess->movePluginPrimitive(StoredPlayers[StackPlayers[i]._name].primitive, CVector(StackPlayers[i]._x, StackPlayers[i]._y, 0)); + } + } + // we clear the stack + StackPlayers.clear(); + } + } +} + +std::string& CPlugin::getName() +{ + return _PluginName; +} + +bool CPlugin::isActive() +{ + return _PluginActive; +} + +bool CPlugin::activatePlugin() +{ + if(!_PluginActive) + { + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + AfxEnableControlContainer(); + + //_DialogFlag->Create(IDD_DIALOG_FLAGS, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); + _DialogFlag->ShowWindow(TRUE); + //_DialogFlag->init(this); + _PluginActive=true; + return true; + } + return false; +} + +bool CPlugin::closePlugin() +{ + if (_PluginActive) + { + //_DialogFlag->CloseWindow(); + _DialogFlag->ShowWindow(FALSE); + _PluginActive=false; + return true; + } + return false; +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/plugin.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/plugin.h index 7e57dd2e7..ed3a037d9 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/plugin.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/plugin.h @@ -1,86 +1,86 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/sound/u_audio_mixer.h" -#include "nel/ligo/primitive.h" -#include "nel/misc/progress_callback.h" -#include "../world_editor/plugin_interface.h" -#include "DialogFlags.h" -#include "nel/sound/u_audio_mixer.h" -#include "LoadDialog.h" - -class CPlugin : public IPluginCallback -{ -public: - /// Constructor - CPlugin(); - /// Destructor - ~CPlugin(); -private: - // @{ - // \name Overload for IPluginCallback - virtual void init(IPluginAccess *pluginAccess); - - /// The current region has changed. - virtual void primitiveChanged(const NLLIGO::IPrimitive *root); - - /// The region has been modifed. - /// The listener has been moved on the map. - virtual void positionMoved(const NLMISC::CVector &position); - /// The plugin lost the control of the position - virtual void lostPositionControl(); - // @} - - // callback for mixer init progression - void progress (float progressValue); - // Dialog for mixer init progression display - //CLoadDialog *LoadDlg; - - /// The world editor interface. - IPluginAccess *_PluginAccess; - - /// Sound plugin dialog. - CDialogFlags *_DialogFlag; - - std::string _PluginName; - - bool _PluginActive; - - //NLSOUND::UAudioMixer *_Mixer; - - /// the position of the listener. - //NLMISC::CVector _ListenerPos; - virtual void onIdle(); - - //getting the name of the plugin - virtual std::string& getName(); - - //testing whether the plugin is active or not (currently in use or not) - virtual bool isActive(); - - - virtual bool activatePlugin(); - - virtual bool closePlugin(); - - bool m_Initialized; -}; - -extern "C" -{ - /// Export the C factory method for dynamic linking.. - __declspec( dllexport ) void *createPlugin(); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/sound/u_audio_mixer.h" +#include "nel/ligo/primitive.h" +#include "nel/misc/progress_callback.h" +#include "../world_editor/plugin_interface.h" +#include "DialogFlags.h" +#include "nel/sound/u_audio_mixer.h" +#include "LoadDialog.h" + +class CPlugin : public IPluginCallback +{ +public: + /// Constructor + CPlugin(); + /// Destructor + ~CPlugin(); +private: + // @{ + // \name Overload for IPluginCallback + virtual void init(IPluginAccess *pluginAccess); + + /// The current region has changed. + virtual void primitiveChanged(const NLLIGO::IPrimitive *root); + + /// The region has been modifed. + /// The listener has been moved on the map. + virtual void positionMoved(const NLMISC::CVector &position); + /// The plugin lost the control of the position + virtual void lostPositionControl(); + // @} + + // callback for mixer init progression + void progress (float progressValue); + // Dialog for mixer init progression display + //CLoadDialog *LoadDlg; + + /// The world editor interface. + IPluginAccess *_PluginAccess; + + /// Sound plugin dialog. + CDialogFlags *_DialogFlag; + + std::string _PluginName; + + bool _PluginActive; + + //NLSOUND::UAudioMixer *_Mixer; + + /// the position of the listener. + //NLMISC::CVector _ListenerPos; + virtual void onIdle(); + + //getting the name of the plugin + virtual std::string& getName(); + + //testing whether the plugin is active or not (currently in use or not) + virtual bool isActive(); + + + virtual bool activatePlugin(); + + virtual bool closePlugin(); + + bool m_Initialized; +}; + +extern "C" +{ + /// Export the C factory method for dynamic linking.. + __declspec( dllexport ) void *createPlugin(); +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/resource.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/resource.h index 76a7aab78..1101291e0 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/resource.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/resource.h @@ -1,80 +1,80 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by world_editor_plugin.rc -// -#define IDR_TOOLBAR1 101 -#define IDR_TOOLBAR_SOUND 101 -#define IDB_BITMAP_STOP 103 -#define IDD_DIALOG_FLAGS 104 -#define IDB_BITMAP_PLAY 105 -#define IDB_BITMAP_EAR 106 -#define IDB_BITMAP_MOVE_EAR 107 -#define IDD_DIALOG_LOAD 108 -#define IDC_CHECK_FLAG_00 1000 -#define IDC_CHECK_FLAG_01 1001 -#define IDC_CHECK_FLAG_02 1002 -#define IDC_CHECK_FLAG_03 1003 -#define IDC_CHECK_FLAG_04 1004 -#define IDC_CHECK_FLAG_05 1005 -#define IDC_CHECK_FLAG_06 1006 -#define IDC_CHECK_FLAG_07 1007 -#define IDC_CHECK_FLAG_08 1008 -#define IDC_CHECK_FLAG_09 1009 -#define IDC_CHECK_FLAG_10 1010 -#define IDC_CHECK_FLAG_11 1011 -#define IDC_CHECK_FLAG_12 1012 -#define IDC_CHECK_FLAG_13 1013 -#define IDC_CHECK_FLAG_14 1014 -#define IDC_CHECK_FLAG_15 1015 -#define IDC_BUTTON_PLAY_STOP 1016 -#define IDC_CHECK_MOVE_EAR 1018 -#define IDC_STATIC_MESSAGE 1019 -#define IDC_CHECK_FLAG_16 1019 -#define IDC_STATIC_SAMPLE_SIZE 1020 -#define IDC_CHECK_FLAG_17 1021 -#define IDC_CHECK_FLAG_18 1022 -#define IDC_CHECK_FLAG_19 1023 -#define IDC_CHECK_FLAG_20 1024 -#define IDC_CHECK_FLAG_21 1025 -#define IDC_CHECK_FLAG_22 1026 -#define IDC_CHECK_FLAG_23 1027 -#define IDC_CHECK_FLAG_24 1028 -#define IDC_CHECK_FLAG_25 1029 -#define IDC_CHECK_FLAG_26 1030 -#define IDC_CHECK_FLAG_27 1031 -#define IDC_CHECK_FLAG_28 1032 -#define IDC_CHECK_FLAG_29 1033 -#define IDC_CHECK_FLAG_30 1034 -#define IDC_CHECK_FLAG_31 1035 -#define IDC_SCROLLBAR_SB 1037 -#define IDC_SB_LIST 1059 -#define ID_BUTTON40001 40001 -#define ID_BUTTON40002 40002 -#define ID_BUTTON40003 40003 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 109 -#define _APS_NEXT_COMMAND_VALUE 40004 -#define _APS_NEXT_CONTROL_VALUE 1060 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by world_editor_plugin.rc +// +#define IDR_TOOLBAR1 101 +#define IDR_TOOLBAR_SOUND 101 +#define IDB_BITMAP_STOP 103 +#define IDD_DIALOG_FLAGS 104 +#define IDB_BITMAP_PLAY 105 +#define IDB_BITMAP_EAR 106 +#define IDB_BITMAP_MOVE_EAR 107 +#define IDD_DIALOG_LOAD 108 +#define IDC_CHECK_FLAG_00 1000 +#define IDC_CHECK_FLAG_01 1001 +#define IDC_CHECK_FLAG_02 1002 +#define IDC_CHECK_FLAG_03 1003 +#define IDC_CHECK_FLAG_04 1004 +#define IDC_CHECK_FLAG_05 1005 +#define IDC_CHECK_FLAG_06 1006 +#define IDC_CHECK_FLAG_07 1007 +#define IDC_CHECK_FLAG_08 1008 +#define IDC_CHECK_FLAG_09 1009 +#define IDC_CHECK_FLAG_10 1010 +#define IDC_CHECK_FLAG_11 1011 +#define IDC_CHECK_FLAG_12 1012 +#define IDC_CHECK_FLAG_13 1013 +#define IDC_CHECK_FLAG_14 1014 +#define IDC_CHECK_FLAG_15 1015 +#define IDC_BUTTON_PLAY_STOP 1016 +#define IDC_CHECK_MOVE_EAR 1018 +#define IDC_STATIC_MESSAGE 1019 +#define IDC_CHECK_FLAG_16 1019 +#define IDC_STATIC_SAMPLE_SIZE 1020 +#define IDC_CHECK_FLAG_17 1021 +#define IDC_CHECK_FLAG_18 1022 +#define IDC_CHECK_FLAG_19 1023 +#define IDC_CHECK_FLAG_20 1024 +#define IDC_CHECK_FLAG_21 1025 +#define IDC_CHECK_FLAG_22 1026 +#define IDC_CHECK_FLAG_23 1027 +#define IDC_CHECK_FLAG_24 1028 +#define IDC_CHECK_FLAG_25 1029 +#define IDC_CHECK_FLAG_26 1030 +#define IDC_CHECK_FLAG_27 1031 +#define IDC_CHECK_FLAG_28 1032 +#define IDC_CHECK_FLAG_29 1033 +#define IDC_CHECK_FLAG_30 1034 +#define IDC_CHECK_FLAG_31 1035 +#define IDC_SCROLLBAR_SB 1037 +#define IDC_SB_LIST 1059 +#define ID_BUTTON40001 40001 +#define ID_BUTTON40002 40002 +#define ID_BUTTON40003 40003 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 109 +#define _APS_NEXT_COMMAND_VALUE 40004 +#define _APS_NEXT_CONTROL_VALUE 1060 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/world_editor_scriptPLAYER.xml b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/world_editor_scriptPLAYER.xml index 135f5c4a6..188431e03 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/world_editor_scriptPLAYER.xml +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_plugin/world_editor_scriptPLAYER.xml @@ -1,10 +1,10 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_primitive_plugin/CMakeLists.txt b/code/ryzom/tools/leveldesign/world_editor/world_editor_primitive_plugin/CMakeLists.txt index 13fe663ed..4175cb8f9 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_primitive_plugin/CMakeLists.txt +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_primitive_plugin/CMakeLists.txt @@ -1,21 +1,21 @@ -FILE(GLOB SRC *.cpp *.h) - -ADD_LIBRARY(world_editor_primitive_plugin SHARED ${SRC}) - -INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) - -TARGET_LINK_LIBRARIES(world_editor_primitive_plugin - nelmisc - nel3d - nelsound - nelsnd_lowlevel) - -NL_DEFAULT_PROPS(world_editor_primitive_plugin "Ryzom, Tools, World: World Editor Primitive Plugin") -NL_ADD_RUNTIME_FLAGS(world_editor_primitive_plugin) -NL_ADD_LIB_SUFFIX(world_editor_primitive_plugin) - -ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} ${MFC_DEFINITIONS} -DWIN32_DLL_EXPORTS) - - -INSTALL(TARGETS world_editor_primitive_plugin LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) - +FILE(GLOB SRC *.cpp *.h) + +ADD_LIBRARY(world_editor_primitive_plugin SHARED ${SRC}) + +INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) + +TARGET_LINK_LIBRARIES(world_editor_primitive_plugin + nelmisc + nel3d + nelsound + nelsnd_lowlevel) + +NL_DEFAULT_PROPS(world_editor_primitive_plugin "Ryzom, Tools, World: World Editor Primitive Plugin") +NL_ADD_RUNTIME_FLAGS(world_editor_primitive_plugin) +NL_ADD_LIB_SUFFIX(world_editor_primitive_plugin) + +ADD_DEFINITIONS(${LIBXML2_DEFINITIONS} ${MFC_DEFINITIONS} -DWIN32_DLL_EXPORTS) + + +INSTALL(TARGETS world_editor_primitive_plugin LIBRARY DESTINATION lib RUNTIME DESTINATION bin ARCHIVE DESTINATION lib COMPONENT tools3d) + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_primitive_plugin/primitive_plugin.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_primitive_plugin/primitive_plugin.cpp index 3cc18a60f..f7b01a05f 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_primitive_plugin/primitive_plugin.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_primitive_plugin/primitive_plugin.cpp @@ -1,357 +1,357 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "primitive_plugin.h" - -#include "../world_editor/world_editor.h" -#include "../world_editor/display.h" -#include -#include -#include -#include - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; - -CFileDisplayer *PrimitivePluginLogDisplayer= NULL; - -extern "C" -{ - void *createPlugin() - { - return new CPrimitivePlugin(); - } -} - -CPrimitivePlugin::CPrimitivePlugin() -{ - NLMISC::createDebug(); - PrimitivePluginLogDisplayer= new CFileDisplayer("world_editor_primitive_plugin.log", true, "WORLD_EDITOR_PRIMITIVE_PLUGIN.LOG"); - DebugLog->addDisplayer (PrimitivePluginLogDisplayer); - InfoLog->addDisplayer (PrimitivePluginLogDisplayer); - WarningLog->addDisplayer (PrimitivePluginLogDisplayer); - ErrorLog->addDisplayer (PrimitivePluginLogDisplayer); - AssertLog->addDisplayer (PrimitivePluginLogDisplayer); - - nlinfo("Starting primitive plugin..."); - - _PluginActive = false; - _PluginAccess = NULL; -} - - -bool CPrimitivePlugin::isActive() -{ - return _PluginActive; -} - -bool CPrimitivePlugin::activatePlugin() -{ - _PluginActive = true; - - // TODO : open the 'rebuild npc data' dialog box - - return true; -} - -bool CPrimitivePlugin::closePlugin() -{ - _PluginActive = false; - return true; -} - -std::string& CPrimitivePlugin::getName() -{ - static string name("Primitive displayer"); - return name; -} - - -void CPrimitivePlugin::TCreatureInfo::readGeorges (const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId) -{ - const NLGEORGES::UFormElm &item=form->getRootNode(); - - // the form was found so read the true values from Georges - item.getValueByName(Radius, "Collision.CollisionRadius"); - HaveRadius = Radius != 0.0f; - item.getValueByName(Length, "Collision.Length"); - item.getValueByName(Width, "Collision.Width"); - HaveBox = (Length != 0 && Width != 0); -} - -void CPrimitivePlugin::TCreatureInfo::serial (NLMISC::IStream &s) -{ - s.serial(HaveRadius); - s.serial(Radius); - s.serial(HaveBox); - s.serial(Width); - s.serial(Length); -} - -uint CPrimitivePlugin::TCreatureInfo::getVersion () -{ - return 1; -} - - - -// @{ -// \name Overload for IPluginCallback -void CPrimitivePlugin::init(IPluginAccess *pluginAccess) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - AfxEnableControlContainer(); - _PluginAccess = pluginAccess; - - string packedFileName("primitive_plugin.packed_sheets"); - - vector paths; - string sheetIdPath; - - // add the search path - CConfigFile &cf = pluginAccess->getConfigFile(); - CConfigFile::CVar *pv = cf.getVarPtr("PrimitivePluginPath"); - if (pv) - { - for (uint i=0; isize(); ++i) - paths.push_back(pv->asString(i)); - } - // add the sheetId file - pv = cf.getVarPtr("PrimitivePluginSheetId"); - sheetIdPath = pv->asString(); - - // Init the sheet id - CPath::addSearchFile(sheetIdPath); - CSheetId::init(false); - - // Read the sheets - if (NLMISC::CFile::fileExists(packedFileName)) - loadForm("creature", packedFileName, _CreatureInfos, false, false); - else - { - for (uint i=0; i classNames; - classNames.push_back("npc_bot"); - _PluginAccess->registerPrimitiveDisplayer(this, classNames); -} - -/// The current region has changed. -void CPrimitivePlugin::primitiveChanged(const NLLIGO::IPrimitive *root) -{ -} - -void CPrimitivePlugin::drawPrimitive(const NLLIGO::IPrimitive *primitive, const TRenderContext &ctx) -{ -// AFX_MANAGE_STATE(AfxGetStaticModuleState()); - static const float POINT_ARROW_LINE_SIZE = 20.f; - static const float POINT_ARROW_HEAD_SIZE = 8.f; - static const float POINT_DOT_SIZE = 3.f; - - static const uint CIRCLE_SEGMENT_SIZE = 20; - static const uint CIRCLE_MIN_SEGMENT_COUNT = 8; - - std::string *sheetName; - primitive->getPropertyByName("sheet_client", sheetName); - - TCreatureInfo *info = NULL; - if (!sheetName->empty()) - { - // two step init of id to remove a flooding NeL warning - CSheetId id; - id.buildSheetId(*sheetName+".creature"); - std::map::iterator it(_CreatureInfos.find(id)); - if (it != _CreatureInfos.end()) - { - info = &(it->second); - } - } - - - const CPrimPoint *point = dynamic_cast(primitive); - if (point) - { - // Clip ? - if (!ctx.Display->isClipped (&point->Point, 1)) - { - // Position in world - CVector center = point->Point; - ctx.Display->worldToPixel (center); - - // Dot - CVector dot0, dot1, dot2, dot3; - dot0 = center; - dot0.x += POINT_DOT_SIZE; - dot0.y += POINT_DOT_SIZE; - dot1 = center; - dot1.x -= POINT_DOT_SIZE; - dot1.y += POINT_DOT_SIZE; - dot2 = center; - dot2.x -= POINT_DOT_SIZE; - dot2.y -= POINT_DOT_SIZE; - dot3 = center; - dot3.x += POINT_DOT_SIZE; - dot3.y -= POINT_DOT_SIZE; - - // Transform primitive - transformVector (dot0, point->Angle, center); - transformVector (dot1, point->Angle, center); - transformVector (dot2, point->Angle, center); - transformVector (dot3, point->Angle, center); - - // In world space - ctx.Display->pixelToWorld (center); - ctx.Display->pixelToWorld (dot0); - ctx.Display->pixelToWorld (dot1); - ctx.Display->pixelToWorld (dot2); - ctx.Display->pixelToWorld (dot3); - - // Draw it - ctx.Display->triRenderProxy (ctx.MainColor, dot0, dot1, dot2, ctx.Selected?2:0); - ctx.Display->triRenderProxy (ctx.MainColor, dot2, dot3, dot0, ctx.Selected?2:0); - - // Need detail? - if (ctx.ShowDetail) - { - // Prim class available ? - const CPrimitiveClass *primClass = ctx.PrimitiveClass; - if (primClass != NULL) - { - // Draw an arraow ? - if (primClass->ShowArrow) - { - // Position in world - center = point->Point; - ctx.Display->worldToPixel (center); - CVector arrow = center; - CVector arrow0 = center; - arrow.x += POINT_ARROW_LINE_SIZE; - CVector arrow1 = arrow; - CVector arrow2 = arrow; - arrow0.x += POINT_ARROW_LINE_SIZE + POINT_ARROW_HEAD_SIZE; - arrow1.y += POINT_ARROW_HEAD_SIZE; - arrow2.y -= POINT_ARROW_HEAD_SIZE; - - // Transform primitive - transformVector (arrow, point->Angle, center); - transformVector (arrow0, point->Angle, center); - transformVector (arrow1, point->Angle, center); - transformVector (arrow2, point->Angle, center); - - // In world space - ctx.Display->pixelToWorld (center); - ctx.Display->pixelToWorld (arrow); - ctx.Display->pixelToWorld (arrow0); - ctx.Display->pixelToWorld (arrow1); - ctx.Display->pixelToWorld (arrow2); - - // Draw it - ctx.Display->lineRenderProxy (ctx.MainColor, center, arrow, ctx.Selected?2:0); - ctx.Display->triRenderProxy (ctx.ArrowColor, arrow0, arrow1, arrow2, ctx.Selected?2:0); - } - } - - // Have bounding info ? - if (info != NULL) - { - if (info->HaveRadius) - { - // Get it - float fRadius = info->Radius; - - // Get the perimeter - float perimeter = 2.f*(float)Pi*fRadius; - - // Get the perimeter on the screen - perimeter *= (float)ctx.Display->getWidth() / (ctx.Display->_CurViewMax.x - ctx.Display->_CurViewMin.x); - - // Get the segement count - perimeter /= (float)CIRCLE_SEGMENT_SIZE; - - // Clamp - if (perimeter < CIRCLE_MIN_SEGMENT_COUNT) - perimeter = CIRCLE_MIN_SEGMENT_COUNT; - - // Segment count - uint segmentCount = (uint)perimeter; - - // Draw a circle - CVector posInit = center; - posInit.x += fRadius; - CVector posPrevious = posInit; - for (uint i=1; ilineRenderProxy (ctx.MainColor, pos, posPrevious, ctx.Selected?2:0); - posPrevious = pos; - } - } - if (info->HaveBox) - { - CVector center = point->Point; -// ctx.Display->worldToPixel (center); - - // Dot - CVector dot0, dot1, dot2, dot3; - dot0 = center; - dot0.x += info->Length/2; - dot0.y += info->Width/2; - dot1 = center; - dot1.x -= info->Length/2; - dot1.y += info->Width/2; - dot2 = center; - dot2.x -= info->Length/2; - dot2.y -= info->Width/2; - dot3 = center; - dot3.x += info->Length/2; - dot3.y -= info->Width/2; - - // Transform primitive - transformVector (dot0, point->Angle, center); - transformVector (dot1, point->Angle, center); - transformVector (dot2, point->Angle, center); - transformVector (dot3, point->Angle, center); - - // In world space -/* ctx.Display->pixelToWorld (center); - ctx.Display->pixelToWorld (dot0); - ctx.Display->pixelToWorld (dot1); - ctx.Display->pixelToWorld (dot2); - ctx.Display->pixelToWorld (dot3); -*/ - // Draw it - ctx.Display->lineRenderProxy (ctx.MainColor, dot0, dot1, ctx.Selected?2:0); - ctx.Display->lineRenderProxy (ctx.MainColor, dot1, dot2, ctx.Selected?2:0); - ctx.Display->lineRenderProxy (ctx.MainColor, dot2, dot3, ctx.Selected?2:0); - ctx.Display->lineRenderProxy (ctx.MainColor, dot3, dot0, ctx.Selected?2:0); - } - } - } - } - } - -} - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "primitive_plugin.h" + +#include "../world_editor/world_editor.h" +#include "../world_editor/display.h" +#include +#include +#include +#include + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; + +CFileDisplayer *PrimitivePluginLogDisplayer= NULL; + +extern "C" +{ + void *createPlugin() + { + return new CPrimitivePlugin(); + } +} + +CPrimitivePlugin::CPrimitivePlugin() +{ + NLMISC::createDebug(); + PrimitivePluginLogDisplayer= new CFileDisplayer("world_editor_primitive_plugin.log", true, "WORLD_EDITOR_PRIMITIVE_PLUGIN.LOG"); + DebugLog->addDisplayer (PrimitivePluginLogDisplayer); + InfoLog->addDisplayer (PrimitivePluginLogDisplayer); + WarningLog->addDisplayer (PrimitivePluginLogDisplayer); + ErrorLog->addDisplayer (PrimitivePluginLogDisplayer); + AssertLog->addDisplayer (PrimitivePluginLogDisplayer); + + nlinfo("Starting primitive plugin..."); + + _PluginActive = false; + _PluginAccess = NULL; +} + + +bool CPrimitivePlugin::isActive() +{ + return _PluginActive; +} + +bool CPrimitivePlugin::activatePlugin() +{ + _PluginActive = true; + + // TODO : open the 'rebuild npc data' dialog box + + return true; +} + +bool CPrimitivePlugin::closePlugin() +{ + _PluginActive = false; + return true; +} + +std::string& CPrimitivePlugin::getName() +{ + static string name("Primitive displayer"); + return name; +} + + +void CPrimitivePlugin::TCreatureInfo::readGeorges (const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId) +{ + const NLGEORGES::UFormElm &item=form->getRootNode(); + + // the form was found so read the true values from Georges + item.getValueByName(Radius, "Collision.CollisionRadius"); + HaveRadius = Radius != 0.0f; + item.getValueByName(Length, "Collision.Length"); + item.getValueByName(Width, "Collision.Width"); + HaveBox = (Length != 0 && Width != 0); +} + +void CPrimitivePlugin::TCreatureInfo::serial (NLMISC::IStream &s) +{ + s.serial(HaveRadius); + s.serial(Radius); + s.serial(HaveBox); + s.serial(Width); + s.serial(Length); +} + +uint CPrimitivePlugin::TCreatureInfo::getVersion () +{ + return 1; +} + + + +// @{ +// \name Overload for IPluginCallback +void CPrimitivePlugin::init(IPluginAccess *pluginAccess) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + AfxEnableControlContainer(); + _PluginAccess = pluginAccess; + + string packedFileName("primitive_plugin.packed_sheets"); + + vector paths; + string sheetIdPath; + + // add the search path + CConfigFile &cf = pluginAccess->getConfigFile(); + CConfigFile::CVar *pv = cf.getVarPtr("PrimitivePluginPath"); + if (pv) + { + for (uint i=0; isize(); ++i) + paths.push_back(pv->asString(i)); + } + // add the sheetId file + pv = cf.getVarPtr("PrimitivePluginSheetId"); + sheetIdPath = pv->asString(); + + // Init the sheet id + CPath::addSearchFile(sheetIdPath); + CSheetId::init(false); + + // Read the sheets + if (NLMISC::CFile::fileExists(packedFileName)) + loadForm("creature", packedFileName, _CreatureInfos, false, false); + else + { + for (uint i=0; i classNames; + classNames.push_back("npc_bot"); + _PluginAccess->registerPrimitiveDisplayer(this, classNames); +} + +/// The current region has changed. +void CPrimitivePlugin::primitiveChanged(const NLLIGO::IPrimitive *root) +{ +} + +void CPrimitivePlugin::drawPrimitive(const NLLIGO::IPrimitive *primitive, const TRenderContext &ctx) +{ +// AFX_MANAGE_STATE(AfxGetStaticModuleState()); + static const float POINT_ARROW_LINE_SIZE = 20.f; + static const float POINT_ARROW_HEAD_SIZE = 8.f; + static const float POINT_DOT_SIZE = 3.f; + + static const uint CIRCLE_SEGMENT_SIZE = 20; + static const uint CIRCLE_MIN_SEGMENT_COUNT = 8; + + std::string *sheetName; + primitive->getPropertyByName("sheet_client", sheetName); + + TCreatureInfo *info = NULL; + if (!sheetName->empty()) + { + // two step init of id to remove a flooding NeL warning + CSheetId id; + id.buildSheetId(*sheetName+".creature"); + std::map::iterator it(_CreatureInfos.find(id)); + if (it != _CreatureInfos.end()) + { + info = &(it->second); + } + } + + + const CPrimPoint *point = dynamic_cast(primitive); + if (point) + { + // Clip ? + if (!ctx.Display->isClipped (&point->Point, 1)) + { + // Position in world + CVector center = point->Point; + ctx.Display->worldToPixel (center); + + // Dot + CVector dot0, dot1, dot2, dot3; + dot0 = center; + dot0.x += POINT_DOT_SIZE; + dot0.y += POINT_DOT_SIZE; + dot1 = center; + dot1.x -= POINT_DOT_SIZE; + dot1.y += POINT_DOT_SIZE; + dot2 = center; + dot2.x -= POINT_DOT_SIZE; + dot2.y -= POINT_DOT_SIZE; + dot3 = center; + dot3.x += POINT_DOT_SIZE; + dot3.y -= POINT_DOT_SIZE; + + // Transform primitive + transformVector (dot0, point->Angle, center); + transformVector (dot1, point->Angle, center); + transformVector (dot2, point->Angle, center); + transformVector (dot3, point->Angle, center); + + // In world space + ctx.Display->pixelToWorld (center); + ctx.Display->pixelToWorld (dot0); + ctx.Display->pixelToWorld (dot1); + ctx.Display->pixelToWorld (dot2); + ctx.Display->pixelToWorld (dot3); + + // Draw it + ctx.Display->triRenderProxy (ctx.MainColor, dot0, dot1, dot2, ctx.Selected?2:0); + ctx.Display->triRenderProxy (ctx.MainColor, dot2, dot3, dot0, ctx.Selected?2:0); + + // Need detail? + if (ctx.ShowDetail) + { + // Prim class available ? + const CPrimitiveClass *primClass = ctx.PrimitiveClass; + if (primClass != NULL) + { + // Draw an arraow ? + if (primClass->ShowArrow) + { + // Position in world + center = point->Point; + ctx.Display->worldToPixel (center); + CVector arrow = center; + CVector arrow0 = center; + arrow.x += POINT_ARROW_LINE_SIZE; + CVector arrow1 = arrow; + CVector arrow2 = arrow; + arrow0.x += POINT_ARROW_LINE_SIZE + POINT_ARROW_HEAD_SIZE; + arrow1.y += POINT_ARROW_HEAD_SIZE; + arrow2.y -= POINT_ARROW_HEAD_SIZE; + + // Transform primitive + transformVector (arrow, point->Angle, center); + transformVector (arrow0, point->Angle, center); + transformVector (arrow1, point->Angle, center); + transformVector (arrow2, point->Angle, center); + + // In world space + ctx.Display->pixelToWorld (center); + ctx.Display->pixelToWorld (arrow); + ctx.Display->pixelToWorld (arrow0); + ctx.Display->pixelToWorld (arrow1); + ctx.Display->pixelToWorld (arrow2); + + // Draw it + ctx.Display->lineRenderProxy (ctx.MainColor, center, arrow, ctx.Selected?2:0); + ctx.Display->triRenderProxy (ctx.ArrowColor, arrow0, arrow1, arrow2, ctx.Selected?2:0); + } + } + + // Have bounding info ? + if (info != NULL) + { + if (info->HaveRadius) + { + // Get it + float fRadius = info->Radius; + + // Get the perimeter + float perimeter = 2.f*(float)Pi*fRadius; + + // Get the perimeter on the screen + perimeter *= (float)ctx.Display->getWidth() / (ctx.Display->_CurViewMax.x - ctx.Display->_CurViewMin.x); + + // Get the segement count + perimeter /= (float)CIRCLE_SEGMENT_SIZE; + + // Clamp + if (perimeter < CIRCLE_MIN_SEGMENT_COUNT) + perimeter = CIRCLE_MIN_SEGMENT_COUNT; + + // Segment count + uint segmentCount = (uint)perimeter; + + // Draw a circle + CVector posInit = center; + posInit.x += fRadius; + CVector posPrevious = posInit; + for (uint i=1; ilineRenderProxy (ctx.MainColor, pos, posPrevious, ctx.Selected?2:0); + posPrevious = pos; + } + } + if (info->HaveBox) + { + CVector center = point->Point; +// ctx.Display->worldToPixel (center); + + // Dot + CVector dot0, dot1, dot2, dot3; + dot0 = center; + dot0.x += info->Length/2; + dot0.y += info->Width/2; + dot1 = center; + dot1.x -= info->Length/2; + dot1.y += info->Width/2; + dot2 = center; + dot2.x -= info->Length/2; + dot2.y -= info->Width/2; + dot3 = center; + dot3.x += info->Length/2; + dot3.y -= info->Width/2; + + // Transform primitive + transformVector (dot0, point->Angle, center); + transformVector (dot1, point->Angle, center); + transformVector (dot2, point->Angle, center); + transformVector (dot3, point->Angle, center); + + // In world space +/* ctx.Display->pixelToWorld (center); + ctx.Display->pixelToWorld (dot0); + ctx.Display->pixelToWorld (dot1); + ctx.Display->pixelToWorld (dot2); + ctx.Display->pixelToWorld (dot3); +*/ + // Draw it + ctx.Display->lineRenderProxy (ctx.MainColor, dot0, dot1, ctx.Selected?2:0); + ctx.Display->lineRenderProxy (ctx.MainColor, dot1, dot2, ctx.Selected?2:0); + ctx.Display->lineRenderProxy (ctx.MainColor, dot2, dot3, ctx.Selected?2:0); + ctx.Display->lineRenderProxy (ctx.MainColor, dot3, dot0, ctx.Selected?2:0); + } + } + } + } + } + +} + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_primitive_plugin/primitive_plugin.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_primitive_plugin/primitive_plugin.h index 7fcb78fc1..416f05204 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_primitive_plugin/primitive_plugin.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_primitive_plugin/primitive_plugin.h @@ -1,106 +1,106 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef PRIMITIVE_PLUGIN_H -#define PRIMITIVE_PLUGIN_H - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC Automation classes -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -#include - -#undef min -#undef max - -#include -#include - -#include "../world_editor/plugin_interface.h" - -class CPrimitivePlugin : public IPluginCallback, public IPrimitiveDisplayer -{ -public: - - virtual bool isActive(); - - virtual bool activatePlugin(); - - virtual bool closePlugin(); - - virtual std::string& getName(); - - CPrimitivePlugin(); - - virtual void positionMoved(const NLMISC::CVector &position) {} - virtual void lostPositionControl() {} - virtual void onIdle() {} - - virtual void drawPrimitive(const NLLIGO::IPrimitive *primitive, const TRenderContext &renderContext); - - -private: - - struct TCreatureInfo - { - bool HaveRadius; - float Radius; - bool HaveBox; - float Width; - float Length; - - void readGeorges (const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId); - - void serial (NLMISC::IStream &s); - - static uint getVersion () - - void removed() {} - }; - - std::map _CreatureInfos; - - // @{ - // \name Overload for IPluginCallback - virtual void init(IPluginAccess *pluginAccess); - - /// The current region has changed. - virtual void primitiveChanged(const NLLIGO::IPrimitive *root); - // @} - - bool _PluginActive; - - bool m_Initialized; - - // The plugin access - IPluginAccess *_PluginAccess; - -}; - -extern "C" -{ - /// Export the C factory method for dynamic linking.. - __declspec( dllexport ) void *createPlugin(); -} - - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef PRIMITIVE_PLUGIN_H +#define PRIMITIVE_PLUGIN_H + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include + +#undef min +#undef max + +#include +#include + +#include "../world_editor/plugin_interface.h" + +class CPrimitivePlugin : public IPluginCallback, public IPrimitiveDisplayer +{ +public: + + virtual bool isActive(); + + virtual bool activatePlugin(); + + virtual bool closePlugin(); + + virtual std::string& getName(); + + CPrimitivePlugin(); + + virtual void positionMoved(const NLMISC::CVector &position) {} + virtual void lostPositionControl() {} + virtual void onIdle() {} + + virtual void drawPrimitive(const NLLIGO::IPrimitive *primitive, const TRenderContext &renderContext); + + +private: + + struct TCreatureInfo + { + bool HaveRadius; + float Radius; + bool HaveBox; + float Width; + float Length; + + void readGeorges (const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId); + + void serial (NLMISC::IStream &s); + + static uint getVersion () + + void removed() {} + }; + + std::map _CreatureInfos; + + // @{ + // \name Overload for IPluginCallback + virtual void init(IPluginAccess *pluginAccess); + + /// The current region has changed. + virtual void primitiveChanged(const NLLIGO::IPrimitive *root); + // @} + + bool _PluginActive; + + bool m_Initialized; + + // The plugin access + IPluginAccess *_PluginAccess; + +}; + +extern "C" +{ + /// Export the C factory method for dynamic linking.. + __declspec( dllexport ) void *createPlugin(); +} + + +#endif diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogFlags.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogFlags.cpp index a980f6403..7fc7ddf65 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogFlags.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogFlags.cpp @@ -1,498 +1,498 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// DailogFlags.cpp : implementation file -// - -#include "stdafx.h" -#include "DialogFlags.h" -#include "plugin.h" -#include "list_box_color.h" -#include "entity_display_info.h" -#include "../../../../common/src/game_share/mode_and_behaviour.h" - -using namespace std; -using namespace NLMISC; -using namespace NLSOUND; - - - - -// registry tag to save info about entity display -const std::string ENTITY_DISPLAY_MODE_REG_ID[EntityDisplayModeCount] = -{ - "entity_type", - "entity_alive", - "entity_hit_points", - "entity_mode" -}; - -const bool ENTITY_DISPLAY_VISIBLE_CHECK_BOX_FLAG[EntityDisplayModeCount] = -{ - true, // entity type - false, // alive - false, // hit points - true // mode -}; - -const bool ENTITY_DISPLAY_ICONS[EntityDisplayModeCount] = -{ - true, // entity type - false, // alive - false, // hit points - true // mode -}; - - -static void initDisplayInfo(const CEntityDisplayInfo *data, uint count, TEntityDisplayInfoVect &dest) -{ - dest.resize(count); - std::copy(data, data + count, dest.begin()); -} - -///////////////////////////////////////////////////////////////////////////// -// CDialogFlags dialog - -CDialogFlags::CDialogFlags(CWnd* pParent /*=NULL*/) - : CDialog(CDialogFlags::IDD, pParent) -{ - // init default display infos - { - CEntityDisplayInfo di[] = - { - CEntityDisplayInfo(RYZOMID::building, "Building", NLMISC::CRGBA(192, 0, 0)), - CEntityDisplayInfo(RYZOMID::creature, "Creature", NLMISC::CRGBA(255, 127, 0), 2, 0), - CEntityDisplayInfo(RYZOMID::deposit, "Deposit", NLMISC::CRGBA(0, 255, 0)), - CEntityDisplayInfo(RYZOMID::flora, "Flora", NLMISC::CRGBA(255, 127, 0)), - CEntityDisplayInfo(RYZOMID::forageSource, "Forage Source", NLMISC::CRGBA(0, 255, 0)), - CEntityDisplayInfo(RYZOMID::mount, "Mount", NLMISC::CRGBA(127, 63, 0), 3, 0), - CEntityDisplayInfo(RYZOMID::npc, "NPC", NLMISC::CRGBA(255, 0, 0), 1, 0), - CEntityDisplayInfo(RYZOMID::object, "Object", NLMISC::CRGBA(192, 255, 255)), - CEntityDisplayInfo(RYZOMID::pack_animal, "Pack Animal", NLMISC::CRGBA(127, 63, 0), 3, 0), - CEntityDisplayInfo(RYZOMID::player, "Player", NLMISC::CRGBA(127, 127, 255), 0, 0), - CEntityDisplayInfo(RYZOMID::fx_entity, "FX Entity", NLMISC::CRGBA(0, 255, 0)), - CEntityDisplayInfo(RYZOMID::unknown, "Unknown", NLMISC::CRGBA(127, 127, 127)), - }; - initDisplayInfo(di, sizeofarray(di), _EntityDisplayInfo[EntityType]); - } - // - { - CEntityDisplayInfo di[] = - { - CEntityDisplayInfo(0, "Dead", NLMISC::CRGBA(255, 0, 0)), - CEntityDisplayInfo(1, "Weak", NLMISC::CRGBA(255, 255, 0)), - CEntityDisplayInfo(2, "Full shape", NLMISC::CRGBA(0, 255, 0)), - CEntityDisplayInfo(3, "No Hit Points", NLMISC::CRGBA(127, 127, 127)), - }; - initDisplayInfo(di, sizeofarray(di), _EntityDisplayInfo[EntityHitPoints]); - } - // - { - CEntityDisplayInfo di[] = - { - CEntityDisplayInfo(0, "Dead", NLMISC::CRGBA(255, 0, 0)), - CEntityDisplayInfo(1, "Alive", NLMISC::CRGBA(0, 0, 255)), - CEntityDisplayInfo(2, "No Hit Points", NLMISC::CRGBA(127, 127, 127)), - }; - initDisplayInfo(di, sizeofarray(di), _EntityDisplayInfo[EntityAlive]); - } - // - { - CEntityDisplayInfo di[] = - { - CEntityDisplayInfo(MBEHAV::UNKNOWN_MODE, "Unknown", NLMISC::CRGBA(127, 127, 127)), - CEntityDisplayInfo(MBEHAV::NORMAL, "Normal", NLMISC::CRGBA(255, 255, 255)), - CEntityDisplayInfo(MBEHAV::COMBAT_FLOAT, "Combat float", NLMISC::CRGBA(255, 0, 0), 0, 1), - CEntityDisplayInfo(MBEHAV::COMBAT, "Combat", NLMISC::CRGBA(255, 0, 0), 0, 1), - CEntityDisplayInfo(MBEHAV::SWIM, "Swim", NLMISC::CRGBA(0, 0, 255)), - CEntityDisplayInfo(MBEHAV::SIT, "Sit", NLMISC::CRGBA(0, 255, 255)), - CEntityDisplayInfo(MBEHAV::MOUNT_NORMAL, "Mount Normal", NLMISC::CRGBA(192, 128, 0)), - CEntityDisplayInfo(MBEHAV::MOUNT_SWIM, "Mount Swim", NLMISC::CRGBA(0, 0, 255)), - CEntityDisplayInfo(MBEHAV::EAT, "Eat", NLMISC::CRGBA(0, 255, 0)), - CEntityDisplayInfo(MBEHAV::ALERT, "Alert", NLMISC::CRGBA(255, 127, 0)), - CEntityDisplayInfo(MBEHAV::HUNGRY, "Hungry", NLMISC::CRGBA(255, 255, 0)), - CEntityDisplayInfo(MBEHAV::DEATH, "Death", NLMISC::CRGBA(0, 0, 0)), - CEntityDisplayInfo(MBEHAV::SWIM_DEATH, "SwimDeath", NLMISC::CRGBA(0, 0, 0)) - }; - initDisplayInfo(di, sizeofarray(di), _EntityDisplayInfo[EntityMode]); - } -} - -//****************************************************************************************************** -void CDialogFlags::init(CPlugin *plugin) -{ - _Plugin = plugin; -} - -//****************************************************************************************************** -void CDialogFlags::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CDialogFlags) - DDX_Control(pDX, IDC_DETAILS_DISTANCE, DetailsDistanceCtrl); - DDX_Control(pDX, IDC_COLOR_LIST, m_EntityColorList); - DDX_Control(pDX, IDC_DOWNLOAD, DownloadCtrl); - DDX_Control(pDX, IDC_CONNECT, ConnectCtrl); - DDX_Text(pDX, IDC_ENTITES, Entites); - DDX_Text(pDX, IDC_RECEIVED, Received); - DDX_Text(pDX, IDC_SENT, Sent); - DDX_Text(pDX, IDC_STATE, State); - DDX_Slider(pDX, IDC_DOWNLOAD, Download); - DDX_Text(pDX, IDC_DLDVALUE, DownloadValue); - DDX_Slider(pDX, IDC_DETAILS_DISTANCE, DetailsDistance); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CDialogFlags, CDialog) - //{{AFX_MSG_MAP(CDialogFlags) - ON_WM_CREATE() - ON_WM_DESTROY() - ON_BN_CLICKED(IDC_CONNECT, OnConnect) - ON_WM_CLOSE() - ON_CBN_SELCHANGE(IDC_DISPLAY_MODE_COMBO, OnSelchangeDisplayModeCombo) - ON_LBN_SELCHANGE(IDC_COLOR_LIST, OnSelChangeColorList) - ON_BN_CLICKED(IDC_BROWSE_COLOR, OnBrowseColor) - ON_CLBN_CHKCHANGE(IDC_COLOR_LIST, OnCheckVisible) - ON_BN_CLICKED(IDC_SELECT_ALL, OnSelectAll) - ON_BN_CLICKED(IDC_UNSELECT_ALL, OnUnselectAll) - ON_BN_CLICKED(IDC_HP_DOWN, OnHpDown) - ON_BN_CLICKED(IDC_CLOSE_UP_SHOW_TYPE, OnCloseUpShowType) - ON_BN_CLICKED(IDC_CLOSE_UP_SHOW_MODE, OnCloseUpShowMode) - ON_BN_CLICKED(IDC_CLOSE_UP_SHOW_HP, OnCloseUpShowHp) - ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_DETAILS_DISTANCE, OnReleasedcaptureDetailsDistance) - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - - -//****************************************************************************************************** -int CDialogFlags::OnCreate(LPCREATESTRUCT lpCreateStruct) -{ - if (CDialog::OnCreate(lpCreateStruct) == -1) - return -1; - // TODO: Add your specialized creation code here - return 0; -} - -//****************************************************************************************************** -void CDialogFlags::OnDestroy() -{ - CDialog::OnDestroy(); - // TODO: Add your message handler code here -} - -//****************************************************************************************************** -BOOL CDialogFlags::OnCommand(WPARAM wParam, LPARAM lParam) -{ - // TODO: Add your specialized code here and/or call the base class - return CDialog::OnCommand(wParam, lParam); -} - -//****************************************************************************************************** -void CDialogFlags::OnConnect() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - _Plugin->connectDisconnect(); -} - -//****************************************************************************************************** -BOOL CDialogFlags::OnInitDialog() -{ - CDialog::OnInitDialog(); - - HRSRC rsc = FindResource(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ENTITY_ICONS_TGA), "TGA"); - if (rsc != NULL) - { - NLMISC::CBitmap bm; - if (_Plugin->getPluginAccess()->buildNLBitmapFromTGARsc(rsc, AfxGetInstanceHandle(), bm)) - { - m_EntityColorList.setIconBitmap(bm, ENTITY_ICON_SIZE); - } - } - - - DownloadCtrl.SetRange(512, 32768); - DetailsDistanceCtrl.SetRange(0, 100); - - for(uint k = 0; k < EntityDisplayModeCount; ++k) - { - loadEntityDisplayInfoToRegistry(_EntityDisplayInfo[k], ENTITY_DISPLAY_MODE_REG_ID[k]); - } - - setCurrentEntityDisplayMode(EntityType); - - updateCtrlGrayedState(); - - ((CComboBox *) GetDlgItem(IDC_DISPLAY_MODE_COMBO))->SetCurSel(0); - - ((CButton *) GetDlgItem(IDC_HP_DOWN))->SetCheck(1); - ((CButton *) GetDlgItem(IDC_CLOSE_UP_SHOW_TYPE))->SetCheck(1); - ((CButton *) GetDlgItem(IDC_CLOSE_UP_SHOW_MODE))->SetCheck(1); - - ((CButton *) GetDlgItem(IDC_CLOSE_UP_SHOW_HP))->SetCheck(1); - - ::CRect shardListRect; - GetDlgItem(IDC_SHARD_LIST_PLACEMENT)->GetWindowRect(shardListRect); - ScreenToClient(&shardListRect); - ShardCtrl.create(WS_CHILD|WS_TABSTOP, shardListRect, this, 0, REGKEY_BASE_PATH "\\shard_list", 10); - ShardCtrl.ShowWindow (SW_SHOW); - CFont* font = GetFont (); - ShardCtrl.SetFont(font); - ShardCtrl.refreshStrings(); - //ShardCtrl.setFocus(); - if (ShardCtrl.getCount() != 0) - { - ShardCtrl.setCurSel(0); - } - - CConfigFile ConfigFile; - ConfigFile.load ("world_editor_plugin.cfg"); - CConfigFile::CVar *var = ConfigFile.getVarPtr("MOSHost"); - if (var) - { - ShardCtrl.pushString(var->asString().c_str()); - ShardCtrl.setCurSel(var->asString()); - } - - return TRUE; // return TRUE unless you set the focus to a control - // EXCEPTION: OCX Property Pages should return FALSE -} - - -//****************************************************************************************************** -void CDialogFlags::setCurrentEntityDisplayMode(TEntityDisplayMode edm) -{ - nlassert(edm < EntityDisplayModeCount); - const TEntityDisplayInfoVect &currList = _EntityDisplayInfo[edm]; - const std::string ®Id = ENTITY_DISPLAY_MODE_REG_ID[edm]; - m_EntityColorList.ResetContent(); - m_EntityColorList.enableCheckBoxes(ENTITY_DISPLAY_VISIBLE_CHECK_BOX_FLAG[edm]); - m_EntityColorList.enableIcons(ENTITY_DISPLAY_VISIBLE_CHECK_BOX_FLAG[edm]); - for(uint k = 0; k < currList.size(); ++k) - { - m_EntityColorList.AddString(currList[k].Name); - CRGBA col = currList[k].Color; - m_EntityColorList.setColor(k, RGB(col.R, col.G, col.B)); - m_EntityColorList.setIcon(k, currList[k].Icon.X, currList[k].Icon.Y); - m_EntityColorList.SetCheck(k, currList[k].Visible); - } - _CurrentEntityDisplayMode = edm; - updateCtrlGrayedState(); -} - - - -#define REGKEY_ENTITY_DISPLAY_INFO REGKEY_BASE_PATH "\\entity_display_info\\" - -//****************************************************************************************************** -void CDialogFlags::loadEntityDisplayInfoToRegistry(TEntityDisplayInfoVect &infos, const std::string ®Id) -{ - HKEY hKey; - if (RegOpenKeyEx(HKEY_CURRENT_USER, (REGKEY_ENTITY_DISPLAY_INFO + regId).c_str(), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) - { - DWORD index = 0; - for(;;) - { - char valueStr[256] = { 0 }; - BYTE dataStr[256] = { 0 }; - DWORD valueSize = sizeofarray(valueStr); - DWORD dataSize = sizeofarray(dataStr); - LONG result = RegEnumValue(hKey, index, valueStr, &valueSize, NULL, NULL, dataStr, &dataSize); - if (result != ERROR_SUCCESS) break; - uint value = (uint) atoi(valueStr); - for(uint k = 0; k < infos.size(); ++k) - { - if (infos[k].Value == value) - { - int r, g, b, visible; - if (sscanf((const char *) dataStr, "%d, %d, %d, visible = %d", &r, &g, &b, &visible) == 4) - { - infos[k].Color = CRGBA(r, g, b); - infos[k].Visible = visible != 0; - } - else - { - nlwarning("Can't retrieve color in registry for type %s", infos[k].Name); - } - } - } - ++ index; - } - } -} - -//****************************************************************************************************** -void CDialogFlags::saveEntityDisplayInfoToRegistry(const TEntityDisplayInfoVect &infos, const std::string ®Id) -{ - HKEY hKey; - if (RegCreateKeyEx(HKEY_CURRENT_USER, (REGKEY_ENTITY_DISPLAY_INFO + regId).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) - { - for(uint k = 0; k < infos.size(); ++k) - { - char colorStr[128]; - CRGBA color = infos[k].Color; - sprintf(colorStr, "%d, %d, %d, visible = %d", (int) color.R, (int) color.G, (int) color.B, (int) (infos[k].Visible ? 1 : 0)); - LONG result = RegSetValueEx(hKey, toString((int) infos[k].Value).c_str(), 0, REG_SZ, (const BYTE *) colorStr, strlen(colorStr)); - if (result != ERROR_SUCCESS) - { - nlwarning("Couldn't write registry key for entity % color", infos[k].Name); - } - } - } -} - -//****************************************************************************************************** -void CDialogFlags::OnClose() -{ - _Plugin->closePlugin(); -// CDialog::OnClose(); -} - -//****************************************************************************************************** -void CDialogFlags::OnSelchangeDisplayModeCombo() -{ - CComboBox *cb = (CComboBox *) GetDlgItem(IDC_DISPLAY_MODE_COMBO); - TEntityDisplayMode displayMode = (TEntityDisplayMode) cb->GetCurSel(); - if (displayMode == LB_ERR) return; - nlassert(displayMode < EntityDisplayModeCount); - setCurrentEntityDisplayMode(displayMode); - updateCtrlGrayedState(); - _Plugin->setEntityDisplayMode((TEntityDisplayMode) displayMode); -} - - - -//****************************************************************************************************** -void CDialogFlags::OnSelChangeColorList() -{ - updateCtrlGrayedState(); -} - -//****************************************************************************************************** -void CDialogFlags::updateCtrlGrayedState() -{ - GetDlgItem(IDC_BROWSE_COLOR)->EnableWindow(m_EntityColorList.GetCurSel() != LB_ERR ? TRUE : FALSE); - BOOL hasCheckBoxes = ENTITY_DISPLAY_VISIBLE_CHECK_BOX_FLAG[_CurrentEntityDisplayMode]; - GetDlgItem(IDC_SELECT_ALL)->EnableWindow(hasCheckBoxes); - GetDlgItem(IDC_UNSELECT_ALL)->EnableWindow(hasCheckBoxes); -} - -//****************************************************************************************************** -void CDialogFlags::saveCurrentEntityDisplayInfo() -{ - saveEntityDisplayInfoToRegistry(_EntityDisplayInfo[_CurrentEntityDisplayMode], ENTITY_DISPLAY_MODE_REG_ID[_CurrentEntityDisplayMode]); -} - - -//****************************************************************************************************** -void CDialogFlags::OnBrowseColor() -{ - int currSel = m_EntityColorList.GetCurSel(); - if (currSel == LB_ERR) return; - CColorDialog cd; - if (cd.DoModal() == IDOK) - { - COLORREF col = cd.GetColor(); - m_EntityColorList.setColor(currSel, col); - m_EntityColorList.Invalidate(); - nlassert(currSel < (int) _EntityDisplayInfo[_CurrentEntityDisplayMode].size()); - CRGBA nelCol(GetRValue(col), GetGValue(col), GetBValue(col)); - _EntityDisplayInfo[_CurrentEntityDisplayMode][currSel].Color = nelCol; - saveCurrentEntityDisplayInfo(); - _Plugin->updateDisplay(); - } -} - -// *************************************************************************** -const TEntityDisplayInfoVect &CDialogFlags::getEntityDisplayInfos(TEntityDisplayMode mode) const -{ - nlassert(mode < EntityDisplayModeCount); - return _EntityDisplayInfo[mode]; -} - -// *************************************************************************** -void CDialogFlags::OnCheckVisible() -{ - int currSel = m_EntityColorList.GetCurSel(); - if (currSel == LB_ERR) return; - nlassert(currSel < (int) _EntityDisplayInfo[_CurrentEntityDisplayMode].size()); - _EntityDisplayInfo[_CurrentEntityDisplayMode][currSel].Visible = m_EntityColorList.GetCheck(currSel) != 0; - saveCurrentEntityDisplayInfo(); - _Plugin->updateDisplay(); -} - -// *************************************************************************** -void CDialogFlags::OnSelectAll() -{ - setAllChecks(true); -} - -// *************************************************************************** -void CDialogFlags::OnUnselectAll() -{ - setAllChecks(false); -} - -// *************************************************************************** -void CDialogFlags::setAllChecks(bool checked) -{ - TEntityDisplayInfoVect &di = _EntityDisplayInfo[_CurrentEntityDisplayMode]; - for(uint k = 0; k < di.size(); ++k) - { - di[k].Visible = checked; - m_EntityColorList.SetCheck(k, checked); - } - saveCurrentEntityDisplayInfo(); - _Plugin->updateDisplay(); -} - -// *************************************************************************** -void CDialogFlags::OnHpDown() -{ - bool on = ((CButton *) GetDlgItem(IDC_HP_DOWN))->GetCheck() != 0; - _Plugin->setDisplayHitsFlag(on); -} - -// *************************************************************************** -void CDialogFlags::OnCloseUpShowType() -{ - bool on = ((CButton *) GetDlgItem(IDC_CLOSE_UP_SHOW_TYPE))->GetCheck() != 0; - _Plugin->setCloseUpFlag(CPlugin::CloseUpEntityType, on); -} - -// *************************************************************************** -void CDialogFlags::OnCloseUpShowMode() -{ - bool on = ((CButton *) GetDlgItem(IDC_CLOSE_UP_SHOW_MODE))->GetCheck() != 0; - _Plugin->setCloseUpFlag(CPlugin::CloseUpEntityMode, on); -} - -// *************************************************************************** -void CDialogFlags::OnCloseUpShowHp() -{ - bool on = ((CButton *) GetDlgItem(IDC_CLOSE_UP_SHOW_HP))->GetCheck() != 0; - _Plugin->setCloseUpFlag(CPlugin::CloseUpEntityHP, on); -} - - -// *************************************************************************** -void CDialogFlags::OnReleasedcaptureDetailsDistance(NMHDR* pNMHDR, LRESULT* pResult) -{ - UpdateData(); - float lambda = DetailsDistance / 100.f; - _Plugin->setCloseUpDisplayDistance((1.f - lambda) * 10.f + lambda * (1.f / 160.f)); - *pResult = 0; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// DailogFlags.cpp : implementation file +// + +#include "stdafx.h" +#include "DialogFlags.h" +#include "plugin.h" +#include "list_box_color.h" +#include "entity_display_info.h" +#include "../../../../common/src/game_share/mode_and_behaviour.h" + +using namespace std; +using namespace NLMISC; +using namespace NLSOUND; + + + + +// registry tag to save info about entity display +const std::string ENTITY_DISPLAY_MODE_REG_ID[EntityDisplayModeCount] = +{ + "entity_type", + "entity_alive", + "entity_hit_points", + "entity_mode" +}; + +const bool ENTITY_DISPLAY_VISIBLE_CHECK_BOX_FLAG[EntityDisplayModeCount] = +{ + true, // entity type + false, // alive + false, // hit points + true // mode +}; + +const bool ENTITY_DISPLAY_ICONS[EntityDisplayModeCount] = +{ + true, // entity type + false, // alive + false, // hit points + true // mode +}; + + +static void initDisplayInfo(const CEntityDisplayInfo *data, uint count, TEntityDisplayInfoVect &dest) +{ + dest.resize(count); + std::copy(data, data + count, dest.begin()); +} + +///////////////////////////////////////////////////////////////////////////// +// CDialogFlags dialog + +CDialogFlags::CDialogFlags(CWnd* pParent /*=NULL*/) + : CDialog(CDialogFlags::IDD, pParent) +{ + // init default display infos + { + CEntityDisplayInfo di[] = + { + CEntityDisplayInfo(RYZOMID::building, "Building", NLMISC::CRGBA(192, 0, 0)), + CEntityDisplayInfo(RYZOMID::creature, "Creature", NLMISC::CRGBA(255, 127, 0), 2, 0), + CEntityDisplayInfo(RYZOMID::deposit, "Deposit", NLMISC::CRGBA(0, 255, 0)), + CEntityDisplayInfo(RYZOMID::flora, "Flora", NLMISC::CRGBA(255, 127, 0)), + CEntityDisplayInfo(RYZOMID::forageSource, "Forage Source", NLMISC::CRGBA(0, 255, 0)), + CEntityDisplayInfo(RYZOMID::mount, "Mount", NLMISC::CRGBA(127, 63, 0), 3, 0), + CEntityDisplayInfo(RYZOMID::npc, "NPC", NLMISC::CRGBA(255, 0, 0), 1, 0), + CEntityDisplayInfo(RYZOMID::object, "Object", NLMISC::CRGBA(192, 255, 255)), + CEntityDisplayInfo(RYZOMID::pack_animal, "Pack Animal", NLMISC::CRGBA(127, 63, 0), 3, 0), + CEntityDisplayInfo(RYZOMID::player, "Player", NLMISC::CRGBA(127, 127, 255), 0, 0), + CEntityDisplayInfo(RYZOMID::fx_entity, "FX Entity", NLMISC::CRGBA(0, 255, 0)), + CEntityDisplayInfo(RYZOMID::unknown, "Unknown", NLMISC::CRGBA(127, 127, 127)), + }; + initDisplayInfo(di, sizeofarray(di), _EntityDisplayInfo[EntityType]); + } + // + { + CEntityDisplayInfo di[] = + { + CEntityDisplayInfo(0, "Dead", NLMISC::CRGBA(255, 0, 0)), + CEntityDisplayInfo(1, "Weak", NLMISC::CRGBA(255, 255, 0)), + CEntityDisplayInfo(2, "Full shape", NLMISC::CRGBA(0, 255, 0)), + CEntityDisplayInfo(3, "No Hit Points", NLMISC::CRGBA(127, 127, 127)), + }; + initDisplayInfo(di, sizeofarray(di), _EntityDisplayInfo[EntityHitPoints]); + } + // + { + CEntityDisplayInfo di[] = + { + CEntityDisplayInfo(0, "Dead", NLMISC::CRGBA(255, 0, 0)), + CEntityDisplayInfo(1, "Alive", NLMISC::CRGBA(0, 0, 255)), + CEntityDisplayInfo(2, "No Hit Points", NLMISC::CRGBA(127, 127, 127)), + }; + initDisplayInfo(di, sizeofarray(di), _EntityDisplayInfo[EntityAlive]); + } + // + { + CEntityDisplayInfo di[] = + { + CEntityDisplayInfo(MBEHAV::UNKNOWN_MODE, "Unknown", NLMISC::CRGBA(127, 127, 127)), + CEntityDisplayInfo(MBEHAV::NORMAL, "Normal", NLMISC::CRGBA(255, 255, 255)), + CEntityDisplayInfo(MBEHAV::COMBAT_FLOAT, "Combat float", NLMISC::CRGBA(255, 0, 0), 0, 1), + CEntityDisplayInfo(MBEHAV::COMBAT, "Combat", NLMISC::CRGBA(255, 0, 0), 0, 1), + CEntityDisplayInfo(MBEHAV::SWIM, "Swim", NLMISC::CRGBA(0, 0, 255)), + CEntityDisplayInfo(MBEHAV::SIT, "Sit", NLMISC::CRGBA(0, 255, 255)), + CEntityDisplayInfo(MBEHAV::MOUNT_NORMAL, "Mount Normal", NLMISC::CRGBA(192, 128, 0)), + CEntityDisplayInfo(MBEHAV::MOUNT_SWIM, "Mount Swim", NLMISC::CRGBA(0, 0, 255)), + CEntityDisplayInfo(MBEHAV::EAT, "Eat", NLMISC::CRGBA(0, 255, 0)), + CEntityDisplayInfo(MBEHAV::ALERT, "Alert", NLMISC::CRGBA(255, 127, 0)), + CEntityDisplayInfo(MBEHAV::HUNGRY, "Hungry", NLMISC::CRGBA(255, 255, 0)), + CEntityDisplayInfo(MBEHAV::DEATH, "Death", NLMISC::CRGBA(0, 0, 0)), + CEntityDisplayInfo(MBEHAV::SWIM_DEATH, "SwimDeath", NLMISC::CRGBA(0, 0, 0)) + }; + initDisplayInfo(di, sizeofarray(di), _EntityDisplayInfo[EntityMode]); + } +} + +//****************************************************************************************************** +void CDialogFlags::init(CPlugin *plugin) +{ + _Plugin = plugin; +} + +//****************************************************************************************************** +void CDialogFlags::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDialogFlags) + DDX_Control(pDX, IDC_DETAILS_DISTANCE, DetailsDistanceCtrl); + DDX_Control(pDX, IDC_COLOR_LIST, m_EntityColorList); + DDX_Control(pDX, IDC_DOWNLOAD, DownloadCtrl); + DDX_Control(pDX, IDC_CONNECT, ConnectCtrl); + DDX_Text(pDX, IDC_ENTITES, Entites); + DDX_Text(pDX, IDC_RECEIVED, Received); + DDX_Text(pDX, IDC_SENT, Sent); + DDX_Text(pDX, IDC_STATE, State); + DDX_Slider(pDX, IDC_DOWNLOAD, Download); + DDX_Text(pDX, IDC_DLDVALUE, DownloadValue); + DDX_Slider(pDX, IDC_DETAILS_DISTANCE, DetailsDistance); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDialogFlags, CDialog) + //{{AFX_MSG_MAP(CDialogFlags) + ON_WM_CREATE() + ON_WM_DESTROY() + ON_BN_CLICKED(IDC_CONNECT, OnConnect) + ON_WM_CLOSE() + ON_CBN_SELCHANGE(IDC_DISPLAY_MODE_COMBO, OnSelchangeDisplayModeCombo) + ON_LBN_SELCHANGE(IDC_COLOR_LIST, OnSelChangeColorList) + ON_BN_CLICKED(IDC_BROWSE_COLOR, OnBrowseColor) + ON_CLBN_CHKCHANGE(IDC_COLOR_LIST, OnCheckVisible) + ON_BN_CLICKED(IDC_SELECT_ALL, OnSelectAll) + ON_BN_CLICKED(IDC_UNSELECT_ALL, OnUnselectAll) + ON_BN_CLICKED(IDC_HP_DOWN, OnHpDown) + ON_BN_CLICKED(IDC_CLOSE_UP_SHOW_TYPE, OnCloseUpShowType) + ON_BN_CLICKED(IDC_CLOSE_UP_SHOW_MODE, OnCloseUpShowMode) + ON_BN_CLICKED(IDC_CLOSE_UP_SHOW_HP, OnCloseUpShowHp) + ON_NOTIFY(NM_RELEASEDCAPTURE, IDC_DETAILS_DISTANCE, OnReleasedcaptureDetailsDistance) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +//****************************************************************************************************** +int CDialogFlags::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CDialog::OnCreate(lpCreateStruct) == -1) + return -1; + // TODO: Add your specialized creation code here + return 0; +} + +//****************************************************************************************************** +void CDialogFlags::OnDestroy() +{ + CDialog::OnDestroy(); + // TODO: Add your message handler code here +} + +//****************************************************************************************************** +BOOL CDialogFlags::OnCommand(WPARAM wParam, LPARAM lParam) +{ + // TODO: Add your specialized code here and/or call the base class + return CDialog::OnCommand(wParam, lParam); +} + +//****************************************************************************************************** +void CDialogFlags::OnConnect() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + _Plugin->connectDisconnect(); +} + +//****************************************************************************************************** +BOOL CDialogFlags::OnInitDialog() +{ + CDialog::OnInitDialog(); + + HRSRC rsc = FindResource(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ENTITY_ICONS_TGA), "TGA"); + if (rsc != NULL) + { + NLMISC::CBitmap bm; + if (_Plugin->getPluginAccess()->buildNLBitmapFromTGARsc(rsc, AfxGetInstanceHandle(), bm)) + { + m_EntityColorList.setIconBitmap(bm, ENTITY_ICON_SIZE); + } + } + + + DownloadCtrl.SetRange(512, 32768); + DetailsDistanceCtrl.SetRange(0, 100); + + for(uint k = 0; k < EntityDisplayModeCount; ++k) + { + loadEntityDisplayInfoToRegistry(_EntityDisplayInfo[k], ENTITY_DISPLAY_MODE_REG_ID[k]); + } + + setCurrentEntityDisplayMode(EntityType); + + updateCtrlGrayedState(); + + ((CComboBox *) GetDlgItem(IDC_DISPLAY_MODE_COMBO))->SetCurSel(0); + + ((CButton *) GetDlgItem(IDC_HP_DOWN))->SetCheck(1); + ((CButton *) GetDlgItem(IDC_CLOSE_UP_SHOW_TYPE))->SetCheck(1); + ((CButton *) GetDlgItem(IDC_CLOSE_UP_SHOW_MODE))->SetCheck(1); + + ((CButton *) GetDlgItem(IDC_CLOSE_UP_SHOW_HP))->SetCheck(1); + + ::CRect shardListRect; + GetDlgItem(IDC_SHARD_LIST_PLACEMENT)->GetWindowRect(shardListRect); + ScreenToClient(&shardListRect); + ShardCtrl.create(WS_CHILD|WS_TABSTOP, shardListRect, this, 0, REGKEY_BASE_PATH "\\shard_list", 10); + ShardCtrl.ShowWindow (SW_SHOW); + CFont* font = GetFont (); + ShardCtrl.SetFont(font); + ShardCtrl.refreshStrings(); + //ShardCtrl.setFocus(); + if (ShardCtrl.getCount() != 0) + { + ShardCtrl.setCurSel(0); + } + + CConfigFile ConfigFile; + ConfigFile.load ("world_editor_plugin.cfg"); + CConfigFile::CVar *var = ConfigFile.getVarPtr("MOSHost"); + if (var) + { + ShardCtrl.pushString(var->asString().c_str()); + ShardCtrl.setCurSel(var->asString()); + } + + return TRUE; // return TRUE unless you set the focus to a control + // EXCEPTION: OCX Property Pages should return FALSE +} + + +//****************************************************************************************************** +void CDialogFlags::setCurrentEntityDisplayMode(TEntityDisplayMode edm) +{ + nlassert(edm < EntityDisplayModeCount); + const TEntityDisplayInfoVect &currList = _EntityDisplayInfo[edm]; + const std::string ®Id = ENTITY_DISPLAY_MODE_REG_ID[edm]; + m_EntityColorList.ResetContent(); + m_EntityColorList.enableCheckBoxes(ENTITY_DISPLAY_VISIBLE_CHECK_BOX_FLAG[edm]); + m_EntityColorList.enableIcons(ENTITY_DISPLAY_VISIBLE_CHECK_BOX_FLAG[edm]); + for(uint k = 0; k < currList.size(); ++k) + { + m_EntityColorList.AddString(currList[k].Name); + CRGBA col = currList[k].Color; + m_EntityColorList.setColor(k, RGB(col.R, col.G, col.B)); + m_EntityColorList.setIcon(k, currList[k].Icon.X, currList[k].Icon.Y); + m_EntityColorList.SetCheck(k, currList[k].Visible); + } + _CurrentEntityDisplayMode = edm; + updateCtrlGrayedState(); +} + + + +#define REGKEY_ENTITY_DISPLAY_INFO REGKEY_BASE_PATH "\\entity_display_info\\" + +//****************************************************************************************************** +void CDialogFlags::loadEntityDisplayInfoToRegistry(TEntityDisplayInfoVect &infos, const std::string ®Id) +{ + HKEY hKey; + if (RegOpenKeyEx(HKEY_CURRENT_USER, (REGKEY_ENTITY_DISPLAY_INFO + regId).c_str(), 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS) + { + DWORD index = 0; + for(;;) + { + char valueStr[256] = { 0 }; + BYTE dataStr[256] = { 0 }; + DWORD valueSize = sizeofarray(valueStr); + DWORD dataSize = sizeofarray(dataStr); + LONG result = RegEnumValue(hKey, index, valueStr, &valueSize, NULL, NULL, dataStr, &dataSize); + if (result != ERROR_SUCCESS) break; + uint value = (uint) atoi(valueStr); + for(uint k = 0; k < infos.size(); ++k) + { + if (infos[k].Value == value) + { + int r, g, b, visible; + if (sscanf((const char *) dataStr, "%d, %d, %d, visible = %d", &r, &g, &b, &visible) == 4) + { + infos[k].Color = CRGBA(r, g, b); + infos[k].Visible = visible != 0; + } + else + { + nlwarning("Can't retrieve color in registry for type %s", infos[k].Name); + } + } + } + ++ index; + } + } +} + +//****************************************************************************************************** +void CDialogFlags::saveEntityDisplayInfoToRegistry(const TEntityDisplayInfoVect &infos, const std::string ®Id) +{ + HKEY hKey; + if (RegCreateKeyEx(HKEY_CURRENT_USER, (REGKEY_ENTITY_DISPLAY_INFO + regId).c_str(), 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL) == ERROR_SUCCESS) + { + for(uint k = 0; k < infos.size(); ++k) + { + char colorStr[128]; + CRGBA color = infos[k].Color; + sprintf(colorStr, "%d, %d, %d, visible = %d", (int) color.R, (int) color.G, (int) color.B, (int) (infos[k].Visible ? 1 : 0)); + LONG result = RegSetValueEx(hKey, toString((int) infos[k].Value).c_str(), 0, REG_SZ, (const BYTE *) colorStr, strlen(colorStr)); + if (result != ERROR_SUCCESS) + { + nlwarning("Couldn't write registry key for entity % color", infos[k].Name); + } + } + } +} + +//****************************************************************************************************** +void CDialogFlags::OnClose() +{ + _Plugin->closePlugin(); +// CDialog::OnClose(); +} + +//****************************************************************************************************** +void CDialogFlags::OnSelchangeDisplayModeCombo() +{ + CComboBox *cb = (CComboBox *) GetDlgItem(IDC_DISPLAY_MODE_COMBO); + TEntityDisplayMode displayMode = (TEntityDisplayMode) cb->GetCurSel(); + if (displayMode == LB_ERR) return; + nlassert(displayMode < EntityDisplayModeCount); + setCurrentEntityDisplayMode(displayMode); + updateCtrlGrayedState(); + _Plugin->setEntityDisplayMode((TEntityDisplayMode) displayMode); +} + + + +//****************************************************************************************************** +void CDialogFlags::OnSelChangeColorList() +{ + updateCtrlGrayedState(); +} + +//****************************************************************************************************** +void CDialogFlags::updateCtrlGrayedState() +{ + GetDlgItem(IDC_BROWSE_COLOR)->EnableWindow(m_EntityColorList.GetCurSel() != LB_ERR ? TRUE : FALSE); + BOOL hasCheckBoxes = ENTITY_DISPLAY_VISIBLE_CHECK_BOX_FLAG[_CurrentEntityDisplayMode]; + GetDlgItem(IDC_SELECT_ALL)->EnableWindow(hasCheckBoxes); + GetDlgItem(IDC_UNSELECT_ALL)->EnableWindow(hasCheckBoxes); +} + +//****************************************************************************************************** +void CDialogFlags::saveCurrentEntityDisplayInfo() +{ + saveEntityDisplayInfoToRegistry(_EntityDisplayInfo[_CurrentEntityDisplayMode], ENTITY_DISPLAY_MODE_REG_ID[_CurrentEntityDisplayMode]); +} + + +//****************************************************************************************************** +void CDialogFlags::OnBrowseColor() +{ + int currSel = m_EntityColorList.GetCurSel(); + if (currSel == LB_ERR) return; + CColorDialog cd; + if (cd.DoModal() == IDOK) + { + COLORREF col = cd.GetColor(); + m_EntityColorList.setColor(currSel, col); + m_EntityColorList.Invalidate(); + nlassert(currSel < (int) _EntityDisplayInfo[_CurrentEntityDisplayMode].size()); + CRGBA nelCol(GetRValue(col), GetGValue(col), GetBValue(col)); + _EntityDisplayInfo[_CurrentEntityDisplayMode][currSel].Color = nelCol; + saveCurrentEntityDisplayInfo(); + _Plugin->updateDisplay(); + } +} + +// *************************************************************************** +const TEntityDisplayInfoVect &CDialogFlags::getEntityDisplayInfos(TEntityDisplayMode mode) const +{ + nlassert(mode < EntityDisplayModeCount); + return _EntityDisplayInfo[mode]; +} + +// *************************************************************************** +void CDialogFlags::OnCheckVisible() +{ + int currSel = m_EntityColorList.GetCurSel(); + if (currSel == LB_ERR) return; + nlassert(currSel < (int) _EntityDisplayInfo[_CurrentEntityDisplayMode].size()); + _EntityDisplayInfo[_CurrentEntityDisplayMode][currSel].Visible = m_EntityColorList.GetCheck(currSel) != 0; + saveCurrentEntityDisplayInfo(); + _Plugin->updateDisplay(); +} + +// *************************************************************************** +void CDialogFlags::OnSelectAll() +{ + setAllChecks(true); +} + +// *************************************************************************** +void CDialogFlags::OnUnselectAll() +{ + setAllChecks(false); +} + +// *************************************************************************** +void CDialogFlags::setAllChecks(bool checked) +{ + TEntityDisplayInfoVect &di = _EntityDisplayInfo[_CurrentEntityDisplayMode]; + for(uint k = 0; k < di.size(); ++k) + { + di[k].Visible = checked; + m_EntityColorList.SetCheck(k, checked); + } + saveCurrentEntityDisplayInfo(); + _Plugin->updateDisplay(); +} + +// *************************************************************************** +void CDialogFlags::OnHpDown() +{ + bool on = ((CButton *) GetDlgItem(IDC_HP_DOWN))->GetCheck() != 0; + _Plugin->setDisplayHitsFlag(on); +} + +// *************************************************************************** +void CDialogFlags::OnCloseUpShowType() +{ + bool on = ((CButton *) GetDlgItem(IDC_CLOSE_UP_SHOW_TYPE))->GetCheck() != 0; + _Plugin->setCloseUpFlag(CPlugin::CloseUpEntityType, on); +} + +// *************************************************************************** +void CDialogFlags::OnCloseUpShowMode() +{ + bool on = ((CButton *) GetDlgItem(IDC_CLOSE_UP_SHOW_MODE))->GetCheck() != 0; + _Plugin->setCloseUpFlag(CPlugin::CloseUpEntityMode, on); +} + +// *************************************************************************** +void CDialogFlags::OnCloseUpShowHp() +{ + bool on = ((CButton *) GetDlgItem(IDC_CLOSE_UP_SHOW_HP))->GetCheck() != 0; + _Plugin->setCloseUpFlag(CPlugin::CloseUpEntityHP, on); +} + + +// *************************************************************************** +void CDialogFlags::OnReleasedcaptureDetailsDistance(NMHDR* pNMHDR, LRESULT* pResult) +{ + UpdateData(); + float lambda = DetailsDistance / 100.f; + _Plugin->setCloseUpDisplayDistance((1.f - lambda) * 10.f + lambda * (1.f / 160.f)); + *pResult = 0; +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogFlags.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogFlags.h index 6df49f8d1..b505aec31 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogFlags.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogFlags.h @@ -1,125 +1,125 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_) -#define AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// DailogFlags.h : header file -// - -#include "stdafx.h" -#include "resource.h" -#include "list_box_color.h" -#include "entity_display_info.h" -#include "memory_combo_box.h" - - -class CPlugin; - -///////////////////////////////////////////////////////////////////////////// -// CDialogFlags dialog - -class CDialogFlags : public CDialog -{ -// Construction -public: - CDialogFlags(/*NLSOUND::UAudioMixer *mixer,*/ CWnd* pParent); // standard constructor - - void init(CPlugin *plugin); - - const TEntityDisplayInfoVect &getEntityDisplayInfos(TEntityDisplayMode mode) const; - -// Dialog Data - //{{AFX_DATA(CDialogFlags) - enum { IDD = IDD_DIALOG_FLAGS }; - CMemoryComboBox ShardCtrl; - CSliderCtrl DetailsDistanceCtrl; - CListBoxColor m_EntityColorList; - CSliderCtrl DownloadCtrl; - CButton ConnectCtrl; - CString Entites; - CString Received; - CString Sent; - CString State; - int Download; - CString DownloadValue; - int DetailsDistance; - CString Combo1; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CDialogFlags) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - //}}AFX_VIRTUAL - - -// Implementation - - -protected: - - CString Shard; - - CPlugin *_Plugin; - - TEntityDisplayInfoVect _EntityDisplayInfo[EntityDisplayModeCount]; - - - void loadEntityDisplayInfoToRegistry(TEntityDisplayInfoVect &infos, const std::string ®Id); - void saveEntityDisplayInfoToRegistry(const TEntityDisplayInfoVect &infos, const std::string ®Id); - void setCurrentEntityDisplayMode(TEntityDisplayMode edm); - void saveCurrentEntityDisplayInfo(); - // - void updateCtrlGrayedState(); - void setAllChecks(bool checked); - - TEntityDisplayMode _CurrentEntityDisplayMode; - - - - // Generated message map functions - //{{AFX_MSG(CDialogFlags) - afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); - afx_msg void OnDestroy(); - afx_msg void OnConnect(); - afx_msg void OnClose(); - virtual BOOL OnInitDialog(); - afx_msg void OnSelchangeDisplayModeCombo(); - afx_msg void OnSelChangeColorList(); - afx_msg void OnBrowseColor(); - afx_msg void OnCheckVisible(); - afx_msg void OnSelectAll(); - afx_msg void OnUnselectAll(); - afx_msg void OnHpDown(); - afx_msg void OnCloseUpShowType(); - afx_msg void OnCloseUpShowMode(); - afx_msg void OnCloseUpShowHp(); - afx_msg void OnReleasedcaptureDetailsDistance(NMHDR* pNMHDR, LRESULT* pResult); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_) +#define AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DailogFlags.h : header file +// + +#include "stdafx.h" +#include "resource.h" +#include "list_box_color.h" +#include "entity_display_info.h" +#include "memory_combo_box.h" + + +class CPlugin; + +///////////////////////////////////////////////////////////////////////////// +// CDialogFlags dialog + +class CDialogFlags : public CDialog +{ +// Construction +public: + CDialogFlags(/*NLSOUND::UAudioMixer *mixer,*/ CWnd* pParent); // standard constructor + + void init(CPlugin *plugin); + + const TEntityDisplayInfoVect &getEntityDisplayInfos(TEntityDisplayMode mode) const; + +// Dialog Data + //{{AFX_DATA(CDialogFlags) + enum { IDD = IDD_DIALOG_FLAGS }; + CMemoryComboBox ShardCtrl; + CSliderCtrl DetailsDistanceCtrl; + CListBoxColor m_EntityColorList; + CSliderCtrl DownloadCtrl; + CButton ConnectCtrl; + CString Entites; + CString Received; + CString Sent; + CString State; + int Download; + CString DownloadValue; + int DetailsDistance; + CString Combo1; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDialogFlags) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + + +// Implementation + + +protected: + + CString Shard; + + CPlugin *_Plugin; + + TEntityDisplayInfoVect _EntityDisplayInfo[EntityDisplayModeCount]; + + + void loadEntityDisplayInfoToRegistry(TEntityDisplayInfoVect &infos, const std::string ®Id); + void saveEntityDisplayInfoToRegistry(const TEntityDisplayInfoVect &infos, const std::string ®Id); + void setCurrentEntityDisplayMode(TEntityDisplayMode edm); + void saveCurrentEntityDisplayInfo(); + // + void updateCtrlGrayedState(); + void setAllChecks(bool checked); + + TEntityDisplayMode _CurrentEntityDisplayMode; + + + + // Generated message map functions + //{{AFX_MSG(CDialogFlags) + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnDestroy(); + afx_msg void OnConnect(); + afx_msg void OnClose(); + virtual BOOL OnInitDialog(); + afx_msg void OnSelchangeDisplayModeCombo(); + afx_msg void OnSelChangeColorList(); + afx_msg void OnBrowseColor(); + afx_msg void OnCheckVisible(); + afx_msg void OnSelectAll(); + afx_msg void OnUnselectAll(); + afx_msg void OnHpDown(); + afx_msg void OnCloseUpShowType(); + afx_msg void OnCloseUpShowMode(); + afx_msg void OnCloseUpShowHp(); + afx_msg void OnReleasedcaptureDetailsDistance(NMHDR* pNMHDR, LRESULT* pResult); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogLogin.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogLogin.cpp index bada50586..b385e76fd 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogLogin.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogLogin.cpp @@ -1,55 +1,55 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// DialogLogin.cpp : implementation file -// - -#include "stdafx.h" -#include "DialogLogin.h" - - -///////////////////////////////////////////////////////////////////////////// -// CDialogLogin dialog - - -CDialogLogin::CDialogLogin(CWnd* pParent /*=NULL*/) - : CDialog(CDialogLogin::IDD, pParent) -{ - //{{AFX_DATA_INIT(CDialogLogin) - m_Login = _T(""); - m_Password = _T(""); - //}}AFX_DATA_INIT -} - - -void CDialogLogin::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CDialogLogin) - DDX_Text(pDX, IDC_LOGIN, m_Login); - DDX_Text(pDX, IDC_PASSWORD, m_Password); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CDialogLogin, CDialog) - //{{AFX_MSG_MAP(CDialogLogin) - // NOTE: the ClassWizard will add message map macros here - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CDialogLogin message handlers +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// DialogLogin.cpp : implementation file +// + +#include "stdafx.h" +#include "DialogLogin.h" + + +///////////////////////////////////////////////////////////////////////////// +// CDialogLogin dialog + + +CDialogLogin::CDialogLogin(CWnd* pParent /*=NULL*/) + : CDialog(CDialogLogin::IDD, pParent) +{ + //{{AFX_DATA_INIT(CDialogLogin) + m_Login = _T(""); + m_Password = _T(""); + //}}AFX_DATA_INIT +} + + +void CDialogLogin::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDialogLogin) + DDX_Text(pDX, IDC_LOGIN, m_Login); + DDX_Text(pDX, IDC_PASSWORD, m_Password); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDialogLogin, CDialog) + //{{AFX_MSG_MAP(CDialogLogin) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CDialogLogin message handlers diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogLogin.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogLogin.h index f8807136c..08d711dc5 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogLogin.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/DialogLogin.h @@ -1,65 +1,65 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_DIALOGLOGIN_H__9F945B65_4E9D_4951_A0DB_EDF44D43693D__INCLUDED_) -#define AFX_DIALOGLOGIN_H__9F945B65_4E9D_4951_A0DB_EDF44D43693D__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// DialogLogin.h : header file -// - -#include "resource.h" - -///////////////////////////////////////////////////////////////////////////// -// CDialogLogin dialog - -class CDialogLogin : public CDialog -{ -// Construction -public: - CDialogLogin(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CDialogLogin) - enum { IDD = IDD_DIALOG_LOGIN }; - CString m_Login; - CString m_Password; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CDialogLogin) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CDialogLogin) - // NOTE: the ClassWizard will add member functions here - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_DIALOGLOGIN_H__9F945B65_4E9D_4951_A0DB_EDF44D43693D__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_DIALOGLOGIN_H__9F945B65_4E9D_4951_A0DB_EDF44D43693D__INCLUDED_) +#define AFX_DIALOGLOGIN_H__9F945B65_4E9D_4951_A0DB_EDF44D43693D__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DialogLogin.h : header file +// + +#include "resource.h" + +///////////////////////////////////////////////////////////////////////////// +// CDialogLogin dialog + +class CDialogLogin : public CDialog +{ +// Construction +public: + CDialogLogin(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CDialogLogin) + enum { IDD = IDD_DIALOG_LOGIN }; + CString m_Login; + CString m_Password; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDialogLogin) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CDialogLogin) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DIALOGLOGIN_H__9F945B65_4E9D_4951_A0DB_EDF44D43693D__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/StdAfx.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/StdAfx.cpp index b61ba02cd..b67d952bd 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/StdAfx.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/StdAfx.cpp @@ -1,24 +1,24 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.cpp : source file that includes just the standard includes -// World_Editor.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.cpp : source file that includes just the standard includes +// World_Editor.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/StdAfx.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/StdAfx.h index e465d1cc2..9b8256d5e 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/StdAfx.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/StdAfx.h @@ -1,57 +1,57 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_) -#define AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_ - -#pragma warning(disable : 4786) - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#define NOMINMAX -#define _WIN32_WINNT 0x0500 - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC Automation classes -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -#include -#include - -#include -#include -#include -#include -#include "../world_editor/plugin_interface.h" -#include -#include - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_) +#define AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_ + +#pragma warning(disable : 4786) + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#define NOMINMAX +#define _WIN32_WINNT 0x0500 + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include +#include + +#include +#include +#include +#include +#include "../world_editor/plugin_interface.h" +#include +#include + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/entity_display_info.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/entity_display_info.h index b83859715..8c3afda74 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/entity_display_info.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/entity_display_info.h @@ -1,65 +1,65 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef RY_ENTITY_DISPLAY_INFO_H -#define RY_ENTITY_DISPLAY_INFO_H - - -#include "../../../../common/src/game_share/ryzom_entity_id.h" -#include "nel/misc/rgba.h" - - -// Icon for an entity, may be NULL icon is X is -1 or Y is -1 -class CEntityIcon -{ -public: - CEntityIcon(sint x = -1, sint y = -1) : X(x), Y(y) {} - sint X; // unit is ENTITY_ICON_SIZE pixels - sint Y; -}; - -// various display mode for entities -enum TEntityDisplayMode -{ - EntityType = 0, - EntityAlive, - EntityHitPoints, - EntityMode, - EntityDisplayModeCount -}; - - -class CEntityDisplayInfo -{ -public: - uint Value; - const char *Name; - CEntityIcon Icon; - NLMISC::CRGBA Color; - bool Visible; - CEntityDisplayInfo() {} - CEntityDisplayInfo(uint value, const char *name, NLMISC::CRGBA color, sint iconX = -1, sint iconY = -1) - : Value(value), Name(name), Color(color), Visible(true), Icon(iconX, iconY) {} -}; - -typedef std::vector TEntityDisplayInfoVect; - - -const std::string ENTITY_ICONS_BITMAP = "entity_icons.tga"; -const uint ENTITY_ICON_SIZE = 24; - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef RY_ENTITY_DISPLAY_INFO_H +#define RY_ENTITY_DISPLAY_INFO_H + + +#include "../../../../common/src/game_share/ryzom_entity_id.h" +#include "nel/misc/rgba.h" + + +// Icon for an entity, may be NULL icon is X is -1 or Y is -1 +class CEntityIcon +{ +public: + CEntityIcon(sint x = -1, sint y = -1) : X(x), Y(y) {} + sint X; // unit is ENTITY_ICON_SIZE pixels + sint Y; +}; + +// various display mode for entities +enum TEntityDisplayMode +{ + EntityType = 0, + EntityAlive, + EntityHitPoints, + EntityMode, + EntityDisplayModeCount +}; + + +class CEntityDisplayInfo +{ +public: + uint Value; + const char *Name; + CEntityIcon Icon; + NLMISC::CRGBA Color; + bool Visible; + CEntityDisplayInfo() {} + CEntityDisplayInfo(uint value, const char *name, NLMISC::CRGBA color, sint iconX = -1, sint iconY = -1) + : Value(value), Name(name), Color(color), Visible(true), Icon(iconX, iconY) {} +}; + +typedef std::vector TEntityDisplayInfoVect; + + +const std::string ENTITY_ICONS_BITMAP = "entity_icons.tga"; +const uint ENTITY_ICON_SIZE = 24; + + #endif \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/list_box_color.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/list_box_color.cpp index e2f4a3c50..1940d1243 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/list_box_color.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/list_box_color.cpp @@ -1,341 +1,341 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// list_box_color.cpp : implementation file -// - -#include "stdafx.h" -#include "list_box_color.h" -#include "nel/misc/bitmap.h" -#include "nel/misc/file.h" - - -const uint COLOR_BOX_SIZE = 16; -const uint COLOR_BOX_SIZE_GAP = 4; - -///////////////////////////////////////////////////////////////////////////// -// CListBoxColor - -//********************************************************************************************************************** -CListBoxColor::CListBoxColor() -{ - _CheckBoxEnabled = true; - _IconsEnabled = true; - _IconSize = 0; - _IconsBitmapLoaded = false; -} - -//********************************************************************************************************************** -CListBoxColor::~CListBoxColor() -{ -} - - -BEGIN_MESSAGE_MAP(CListBoxColor, CCheckListBox) - //{{AFX_MSG_MAP(CListBoxColor) - ON_WM_DRAWITEM_REFLECT() - ON_WM_MEASUREITEM_REFLECT() - ON_WM_CREATE() - ON_WM_DESTROY() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -//********************************************************************************************************************** -CRect CListBoxColor::OnGetCheckPosition( CRect rectItem, CRect rectCheckBox ) -{ - CRect result; - result.left = rectCheckBox.left; - result.right = rectCheckBox.right; - result.top = (rectCheckBox.top + rectCheckBox.bottom - rectCheckBox.Height()) / 2; - result.bottom = result.top + rectCheckBox.Height(); - return result; -} - -//********************************************************************************************************************** -BOOL CListBoxColor::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) -{ - if (message == WM_DRAWITEM) - { - if (_CheckBoxEnabled) - { - CCheckListBox::PreDrawItem((LPDRAWITEMSTRUCT)lParam); - return CCheckListBox::OnChildNotify(message, wParam, lParam, pResult); - } - else - { - DrawItem((LPDRAWITEMSTRUCT)lParam); - return TRUE; - } - } - return CCheckListBox::OnChildNotify(message, wParam, lParam, pResult); -} - -//********************************************************************************************************************** -void CListBoxColor::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) -{ - CDC dc; - dc.Attach(lpDrawItemStruct->hDC); - - - - ASSERT(lpDrawItemStruct->CtlType == ODT_LISTBOX); - CString text; - GetText(lpDrawItemStruct->itemID, text); - - // Save these values to restore them when done drawing. - COLORREF crOldTextColor = dc.GetTextColor(); - COLORREF crOldBkColor = dc.GetBkColor(); - - // If this item is selected, set the background color - // and the text color to appropriate values. Also, erase - // rect by filling it with the background color. - if ((lpDrawItemStruct->itemAction | ODA_SELECT) && - (lpDrawItemStruct->itemState & ODS_SELECTED)) - { - dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT)); - dc.SetBkColor(::GetSysColor(COLOR_HIGHLIGHT)); - dc.FillSolidRect(&lpDrawItemStruct->rcItem, - ::GetSysColor(COLOR_HIGHLIGHT)); - } - else - { - dc.FillSolidRect(&lpDrawItemStruct->rcItem, crOldBkColor); - } - - - DWORD gap = 4; - lpDrawItemStruct->rcItem.left += gap; - lpDrawItemStruct->rcItem.right += gap; - - RECT r; - - r = lpDrawItemStruct->rcItem; - r.left += COLOR_BOX_SIZE + COLOR_BOX_SIZE_GAP; - r.right += COLOR_BOX_SIZE + COLOR_BOX_SIZE_GAP; - - // if icons are enabled, draw them - if (_IconsEnabled) - { - if (_IconsBitmapLoaded) - { - sint x, y; - getIcon(lpDrawItemStruct->itemID, x, y); - if (x != -1 && y !=-1) - { - CDC srcDC; - srcDC.CreateCompatibleDC(&dc); - srcDC.SelectObject(_PackedIcons); - BLENDFUNCTION bf; - bf.BlendOp = AC_SRC_OVER; - bf.BlendFlags = 0; - //bf.SourceConstantAlpha = GetCheck(lpDrawItemStruct->itemID) ? 255 : 127; - bf.SourceConstantAlpha = 255; - bf.AlphaFormat = 0x01; // AC_SRC_ALPHA - BOOL res = AlphaBlend(dc.m_hDC, r.left, r.top, _IconSize, _IconSize, srcDC.m_hDC, (int) x * _IconSize, (int) y * _IconSize, _IconSize, _IconSize, bf); - nlassert(res != ERROR_INVALID_PARAMETER); - } - } - r.left += _IconSize + COLOR_BOX_SIZE_GAP; - r.right += _IconSize + COLOR_BOX_SIZE_GAP; - } - - // Draw the text. - dc.DrawText( - (LPCTSTR) text, - text.GetLength(), - &r, - DT_LEFT|DT_SINGLELINE|DT_VCENTER); - - // Reset the background color and the text color back to their - // original values. - dc.SetTextColor(crOldTextColor); - dc.SetBkColor(crOldBkColor); - - r.left = lpDrawItemStruct->rcItem.left; - r.right = r.left + COLOR_BOX_SIZE; - r.top = (lpDrawItemStruct->rcItem.top + lpDrawItemStruct->rcItem.bottom - COLOR_BOX_SIZE) / 2; - r.bottom = (lpDrawItemStruct->rcItem.top + lpDrawItemStruct->rcItem.bottom + COLOR_BOX_SIZE) / 2; - - // color stored in item data - { - CBrush b(getColor(lpDrawItemStruct->itemID)); - dc.FillRect(&r, &b); - } - - { - CBrush b(RGB(0, 0, 0)); - dc.FrameRect(&r, &b); - } - dc.Detach(); -} - -//********************************************************************************************************************** -void CListBoxColor::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) -{ - lpMeasureItemStruct->itemHeight = COLOR_BOX_SIZE + COLOR_BOX_SIZE_GAP; - if (_IconsEnabled) - { - lpMeasureItemStruct->itemHeight = std::max((UINT) _IconSize, lpMeasureItemStruct->itemHeight); - } -} - -//********************************************************************************************************************** -void CListBoxColor::setColor(uint index, COLORREF col) -{ - nlassert(index < (uint) GetCount()); - _Colors.resize(GetCount()); - _Colors[index] = col; -} - -//********************************************************************************************************************** -void CListBoxColor::setIcon(uint index, sint srcX, sint srcY) -{ - nlassert(index < (uint) GetCount()); - _Icons.resize(GetCount()); - _Icons[index].SrcX = srcX; - _Icons[index].SrcY = srcY; -} - -//********************************************************************************************************************** -void CListBoxColor::getIcon(uint index, sint &x, sint &y) -{ - nlassert(index < (uint) GetCount()); - if (index < _Icons.size()) - { - x = _Icons[index].SrcX; - y = _Icons[index].SrcY; - return; - } - x = -1; - y = -1; -} - -//********************************************************************************************************************** -COLORREF CListBoxColor::getColor(uint index) const -{ - nlassert(index < (uint) GetCount()); - if (index < _Colors.size()) return _Colors[index]; - return 0; -} - -//********************************************************************************************************************** -void CListBoxColor::setIconBitmap(const NLMISC::CBitmap &bm, uint iconSize) -{ - NLMISC::CBitmap tmpBM = bm; - tmpBM.convertToType(NLMISC::CBitmap::RGBA); - uint8 *firstPix = (uint8 *) &(tmpBM.getPixels()[0]); - const uint8 *lastPix = firstPix + bm.getWidth() * bm.getHeight() * 4; - // convert from rgba to bgra, & premultiply by alpha (required by windows alpha blend) - uint8 *currPix = firstPix; - while (currPix != lastPix) - { - std::swap(currPix[0], currPix[2]); // swap B & R - currPix[0] = (uint8) (((uint16) currPix[3] * (uint16) currPix[0]) >> 8); - currPix[1] = (uint8) (((uint16) currPix[3] * (uint16) currPix[1]) >> 8); - currPix[2] = (uint8) (((uint16) currPix[3] * (uint16) currPix[2]) >> 8); - currPix += 4; - } - // - _PackedIcons.CreateBitmap(tmpBM.getWidth(), tmpBM.getHeight(), 1, 32, firstPix); - _IconsBitmapLoaded = true; - _IconSize = iconSize; -} - - - -/* -struct CListBoxIdent -{ - HWND Wnd; - WPARAM CtrlID; -}; -inline static bool operator < (const CListBoxIdent &lhs, const CListBoxIdent &rhs) -{ - if (lhs.Wnd != rhs.Wnd) return lhs.Wnd < rhs.Wnd; - return lhs.CtrlID < rhs.CtrlID; -} - -struct CListBoxInfo -{ - WNDPROC OldProc; - CListBoxColor *ListBox; -}; - - -static std::map ListBoxMap; - -// When a check box is checked the whole list box item has to be updated. Can't do it in SetCheck because it is not virtual... -static LRESULT CALLBACK catchCheckBoxsProc( - HWND hwnd, // handle to window - UINT uMsg, // message identifier - WPARAM wParam, // first message parameter - LPARAM lParam // second message parameter -) -{ - CListBoxIdent ident; - ident.Wnd = hwnd; - ident.WAPRAM = wParam; - nlassert(ListBoxMap.count(ident)); - CListBoxInfo &lbInfo = ListBoxMap[ident].second; - lbInfo.ListBox->Invalidate(); - if (uMsg == CLBN_CHKCHANGE) - { - - } - return ::CallWindowProc(catchCheckBoxsProc, OldParenProcMap[hwnd], hwnd, uMsg, wParam, lParam); -} - -*/ - -int CListBoxColor::OnCreate(LPCREATESTRUCT lpCreateStruct) -{ - if (CCheckListBox::OnCreate(lpCreateStruct) == -1) - return -1; -/* - if (GetParent()) - { - WNDPROC oldParentWndProc = GetWindowLong(GetParent()->m_hWnd, GWL_WNDPROC); - CListBoxIdent ident; - ident.Wnd = GetParent()->m_hWnd; - ident.CtrlId = GetCtrlID(); - CListBoxInfo lbInfo; - lbInfo.OldProc = oldParentWndProc; - ListBoxColorMap[ident] = lbinfo; - // Intercept msg from parent - SubclassWindow(GetParent()->m_hWnd, catchCheckBoxsProc); - } - */ - return 0; -} - - - - -void CListBoxColor::OnDestroy() -{ - /* - std::map::iterator it = ListBoxColorMap.find(GetParent()->m_hWnd); - if (it != ListBoxColorMap.end()) - { - SubclassWindow((GetParent()->m_hWnd, (*it)->_OldParentWndProc); - ListBoxColorMap.erase(*it); - } - */ - CCheckListBox::OnDestroy(); -} - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// list_box_color.cpp : implementation file +// + +#include "stdafx.h" +#include "list_box_color.h" +#include "nel/misc/bitmap.h" +#include "nel/misc/file.h" + + +const uint COLOR_BOX_SIZE = 16; +const uint COLOR_BOX_SIZE_GAP = 4; + +///////////////////////////////////////////////////////////////////////////// +// CListBoxColor + +//********************************************************************************************************************** +CListBoxColor::CListBoxColor() +{ + _CheckBoxEnabled = true; + _IconsEnabled = true; + _IconSize = 0; + _IconsBitmapLoaded = false; +} + +//********************************************************************************************************************** +CListBoxColor::~CListBoxColor() +{ +} + + +BEGIN_MESSAGE_MAP(CListBoxColor, CCheckListBox) + //{{AFX_MSG_MAP(CListBoxColor) + ON_WM_DRAWITEM_REFLECT() + ON_WM_MEASUREITEM_REFLECT() + ON_WM_CREATE() + ON_WM_DESTROY() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +//********************************************************************************************************************** +CRect CListBoxColor::OnGetCheckPosition( CRect rectItem, CRect rectCheckBox ) +{ + CRect result; + result.left = rectCheckBox.left; + result.right = rectCheckBox.right; + result.top = (rectCheckBox.top + rectCheckBox.bottom - rectCheckBox.Height()) / 2; + result.bottom = result.top + rectCheckBox.Height(); + return result; +} + +//********************************************************************************************************************** +BOOL CListBoxColor::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) +{ + if (message == WM_DRAWITEM) + { + if (_CheckBoxEnabled) + { + CCheckListBox::PreDrawItem((LPDRAWITEMSTRUCT)lParam); + return CCheckListBox::OnChildNotify(message, wParam, lParam, pResult); + } + else + { + DrawItem((LPDRAWITEMSTRUCT)lParam); + return TRUE; + } + } + return CCheckListBox::OnChildNotify(message, wParam, lParam, pResult); +} + +//********************************************************************************************************************** +void CListBoxColor::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct) +{ + CDC dc; + dc.Attach(lpDrawItemStruct->hDC); + + + + ASSERT(lpDrawItemStruct->CtlType == ODT_LISTBOX); + CString text; + GetText(lpDrawItemStruct->itemID, text); + + // Save these values to restore them when done drawing. + COLORREF crOldTextColor = dc.GetTextColor(); + COLORREF crOldBkColor = dc.GetBkColor(); + + // If this item is selected, set the background color + // and the text color to appropriate values. Also, erase + // rect by filling it with the background color. + if ((lpDrawItemStruct->itemAction | ODA_SELECT) && + (lpDrawItemStruct->itemState & ODS_SELECTED)) + { + dc.SetTextColor(::GetSysColor(COLOR_HIGHLIGHTTEXT)); + dc.SetBkColor(::GetSysColor(COLOR_HIGHLIGHT)); + dc.FillSolidRect(&lpDrawItemStruct->rcItem, + ::GetSysColor(COLOR_HIGHLIGHT)); + } + else + { + dc.FillSolidRect(&lpDrawItemStruct->rcItem, crOldBkColor); + } + + + DWORD gap = 4; + lpDrawItemStruct->rcItem.left += gap; + lpDrawItemStruct->rcItem.right += gap; + + RECT r; + + r = lpDrawItemStruct->rcItem; + r.left += COLOR_BOX_SIZE + COLOR_BOX_SIZE_GAP; + r.right += COLOR_BOX_SIZE + COLOR_BOX_SIZE_GAP; + + // if icons are enabled, draw them + if (_IconsEnabled) + { + if (_IconsBitmapLoaded) + { + sint x, y; + getIcon(lpDrawItemStruct->itemID, x, y); + if (x != -1 && y !=-1) + { + CDC srcDC; + srcDC.CreateCompatibleDC(&dc); + srcDC.SelectObject(_PackedIcons); + BLENDFUNCTION bf; + bf.BlendOp = AC_SRC_OVER; + bf.BlendFlags = 0; + //bf.SourceConstantAlpha = GetCheck(lpDrawItemStruct->itemID) ? 255 : 127; + bf.SourceConstantAlpha = 255; + bf.AlphaFormat = 0x01; // AC_SRC_ALPHA + BOOL res = AlphaBlend(dc.m_hDC, r.left, r.top, _IconSize, _IconSize, srcDC.m_hDC, (int) x * _IconSize, (int) y * _IconSize, _IconSize, _IconSize, bf); + nlassert(res != ERROR_INVALID_PARAMETER); + } + } + r.left += _IconSize + COLOR_BOX_SIZE_GAP; + r.right += _IconSize + COLOR_BOX_SIZE_GAP; + } + + // Draw the text. + dc.DrawText( + (LPCTSTR) text, + text.GetLength(), + &r, + DT_LEFT|DT_SINGLELINE|DT_VCENTER); + + // Reset the background color and the text color back to their + // original values. + dc.SetTextColor(crOldTextColor); + dc.SetBkColor(crOldBkColor); + + r.left = lpDrawItemStruct->rcItem.left; + r.right = r.left + COLOR_BOX_SIZE; + r.top = (lpDrawItemStruct->rcItem.top + lpDrawItemStruct->rcItem.bottom - COLOR_BOX_SIZE) / 2; + r.bottom = (lpDrawItemStruct->rcItem.top + lpDrawItemStruct->rcItem.bottom + COLOR_BOX_SIZE) / 2; + + // color stored in item data + { + CBrush b(getColor(lpDrawItemStruct->itemID)); + dc.FillRect(&r, &b); + } + + { + CBrush b(RGB(0, 0, 0)); + dc.FrameRect(&r, &b); + } + dc.Detach(); +} + +//********************************************************************************************************************** +void CListBoxColor::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct) +{ + lpMeasureItemStruct->itemHeight = COLOR_BOX_SIZE + COLOR_BOX_SIZE_GAP; + if (_IconsEnabled) + { + lpMeasureItemStruct->itemHeight = std::max((UINT) _IconSize, lpMeasureItemStruct->itemHeight); + } +} + +//********************************************************************************************************************** +void CListBoxColor::setColor(uint index, COLORREF col) +{ + nlassert(index < (uint) GetCount()); + _Colors.resize(GetCount()); + _Colors[index] = col; +} + +//********************************************************************************************************************** +void CListBoxColor::setIcon(uint index, sint srcX, sint srcY) +{ + nlassert(index < (uint) GetCount()); + _Icons.resize(GetCount()); + _Icons[index].SrcX = srcX; + _Icons[index].SrcY = srcY; +} + +//********************************************************************************************************************** +void CListBoxColor::getIcon(uint index, sint &x, sint &y) +{ + nlassert(index < (uint) GetCount()); + if (index < _Icons.size()) + { + x = _Icons[index].SrcX; + y = _Icons[index].SrcY; + return; + } + x = -1; + y = -1; +} + +//********************************************************************************************************************** +COLORREF CListBoxColor::getColor(uint index) const +{ + nlassert(index < (uint) GetCount()); + if (index < _Colors.size()) return _Colors[index]; + return 0; +} + +//********************************************************************************************************************** +void CListBoxColor::setIconBitmap(const NLMISC::CBitmap &bm, uint iconSize) +{ + NLMISC::CBitmap tmpBM = bm; + tmpBM.convertToType(NLMISC::CBitmap::RGBA); + uint8 *firstPix = (uint8 *) &(tmpBM.getPixels()[0]); + const uint8 *lastPix = firstPix + bm.getWidth() * bm.getHeight() * 4; + // convert from rgba to bgra, & premultiply by alpha (required by windows alpha blend) + uint8 *currPix = firstPix; + while (currPix != lastPix) + { + std::swap(currPix[0], currPix[2]); // swap B & R + currPix[0] = (uint8) (((uint16) currPix[3] * (uint16) currPix[0]) >> 8); + currPix[1] = (uint8) (((uint16) currPix[3] * (uint16) currPix[1]) >> 8); + currPix[2] = (uint8) (((uint16) currPix[3] * (uint16) currPix[2]) >> 8); + currPix += 4; + } + // + _PackedIcons.CreateBitmap(tmpBM.getWidth(), tmpBM.getHeight(), 1, 32, firstPix); + _IconsBitmapLoaded = true; + _IconSize = iconSize; +} + + + +/* +struct CListBoxIdent +{ + HWND Wnd; + WPARAM CtrlID; +}; +inline static bool operator < (const CListBoxIdent &lhs, const CListBoxIdent &rhs) +{ + if (lhs.Wnd != rhs.Wnd) return lhs.Wnd < rhs.Wnd; + return lhs.CtrlID < rhs.CtrlID; +} + +struct CListBoxInfo +{ + WNDPROC OldProc; + CListBoxColor *ListBox; +}; + + +static std::map ListBoxMap; + +// When a check box is checked the whole list box item has to be updated. Can't do it in SetCheck because it is not virtual... +static LRESULT CALLBACK catchCheckBoxsProc( + HWND hwnd, // handle to window + UINT uMsg, // message identifier + WPARAM wParam, // first message parameter + LPARAM lParam // second message parameter +) +{ + CListBoxIdent ident; + ident.Wnd = hwnd; + ident.WAPRAM = wParam; + nlassert(ListBoxMap.count(ident)); + CListBoxInfo &lbInfo = ListBoxMap[ident].second; + lbInfo.ListBox->Invalidate(); + if (uMsg == CLBN_CHKCHANGE) + { + + } + return ::CallWindowProc(catchCheckBoxsProc, OldParenProcMap[hwnd], hwnd, uMsg, wParam, lParam); +} + +*/ + +int CListBoxColor::OnCreate(LPCREATESTRUCT lpCreateStruct) +{ + if (CCheckListBox::OnCreate(lpCreateStruct) == -1) + return -1; +/* + if (GetParent()) + { + WNDPROC oldParentWndProc = GetWindowLong(GetParent()->m_hWnd, GWL_WNDPROC); + CListBoxIdent ident; + ident.Wnd = GetParent()->m_hWnd; + ident.CtrlId = GetCtrlID(); + CListBoxInfo lbInfo; + lbInfo.OldProc = oldParentWndProc; + ListBoxColorMap[ident] = lbinfo; + // Intercept msg from parent + SubclassWindow(GetParent()->m_hWnd, catchCheckBoxsProc); + } + */ + return 0; +} + + + + +void CListBoxColor::OnDestroy() +{ + /* + std::map::iterator it = ListBoxColorMap.find(GetParent()->m_hWnd); + if (it != ListBoxColorMap.end()) + { + SubclassWindow((GetParent()->m_hWnd, (*it)->_OldParentWndProc); + ListBoxColorMap.erase(*it); + } + */ + CCheckListBox::OnDestroy(); +} + + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/list_box_color.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/list_box_color.h index 4c89cda38..558e47fc3 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/list_box_color.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/list_box_color.h @@ -1,117 +1,117 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_LIST_BOX_COLOR_H__C4882C3B_0E50_4BC6_A51A_EAA1B4C2E479__INCLUDED_) -#define AFX_LIST_BOX_COLOR_H__C4882C3B_0E50_4BC6_A51A_EAA1B4C2E479__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// list_box_color.h : header file -// - - -namespace NLMISC -{ - class CBitmap; -} - - -///////////////////////////////////////////////////////////////////////////// -// CListBoxColor window - -// A list box with color buttons. -// Additionnaly, check box can be added -// TODO nico : rename this CListBoxEntity or something like that -class CListBoxColor : public CCheckListBox -{ -// Construction -public: - CListBoxColor(); - - - void setColor(uint index, COLORREF col); - COLORREF getColor(uint index) const; - void enableCheckBoxes(bool enabled) { _CheckBoxEnabled = enabled; Invalidate(); } - // enable icons - void enableIcons(bool enabled) { _IconsEnabled = enabled; Invalidate(); } - - /** Preload a bitmap where packed icons are taken from - * NB : bitmap must be in TGA format - */ - void setIconBitmap(const NLMISC::CBitmap &bm, uint iconSize); - - /** Set an icon from the big bitmap for the given index - * Set -1 for x or y to disable icons for that item - */ - void setIcon(uint index, sint srcX, sint srcY); - void getIcon(uint index, sint &x, sint &y); - - -// Attributes -public: - -// Operations -public: - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CListBoxColor) - //}}AFX_VIRTUAL - -// Implementation -public: - virtual ~CListBoxColor(); - - // Generated message map functions -protected: - bool _CheckBoxEnabled; - bool _IconsEnabled; - std::vector _Colors; - uint _IconSize; - ::CBitmap _PackedIcons; - class CIcon // an icon taken from the big bitmap - { - public: - sint SrcX; - sint SrcY; - CIcon() : SrcX(-1), SrcY(-1) {} - }; - std::vector _Icons; - bool _IconsBitmapLoaded; - - - - - //{{AFX_MSG(CListBoxColor) - afx_msg void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); - afx_msg void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); - afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); - afx_msg void OnDestroy(); - //}}AFX_MSG - - virtual CRect OnGetCheckPosition( CRect rectItem, CRect rectCheckBox ); - BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult); - - DECLARE_MESSAGE_MAP() -}; - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_LIST_BOX_COLOR_H__C4882C3B_0E50_4BC6_A51A_EAA1B4C2E479__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_LIST_BOX_COLOR_H__C4882C3B_0E50_4BC6_A51A_EAA1B4C2E479__INCLUDED_) +#define AFX_LIST_BOX_COLOR_H__C4882C3B_0E50_4BC6_A51A_EAA1B4C2E479__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// list_box_color.h : header file +// + + +namespace NLMISC +{ + class CBitmap; +} + + +///////////////////////////////////////////////////////////////////////////// +// CListBoxColor window + +// A list box with color buttons. +// Additionnaly, check box can be added +// TODO nico : rename this CListBoxEntity or something like that +class CListBoxColor : public CCheckListBox +{ +// Construction +public: + CListBoxColor(); + + + void setColor(uint index, COLORREF col); + COLORREF getColor(uint index) const; + void enableCheckBoxes(bool enabled) { _CheckBoxEnabled = enabled; Invalidate(); } + // enable icons + void enableIcons(bool enabled) { _IconsEnabled = enabled; Invalidate(); } + + /** Preload a bitmap where packed icons are taken from + * NB : bitmap must be in TGA format + */ + void setIconBitmap(const NLMISC::CBitmap &bm, uint iconSize); + + /** Set an icon from the big bitmap for the given index + * Set -1 for x or y to disable icons for that item + */ + void setIcon(uint index, sint srcX, sint srcY); + void getIcon(uint index, sint &x, sint &y); + + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CListBoxColor) + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CListBoxColor(); + + // Generated message map functions +protected: + bool _CheckBoxEnabled; + bool _IconsEnabled; + std::vector _Colors; + uint _IconSize; + ::CBitmap _PackedIcons; + class CIcon // an icon taken from the big bitmap + { + public: + sint SrcX; + sint SrcY; + CIcon() : SrcX(-1), SrcY(-1) {} + }; + std::vector _Icons; + bool _IconsBitmapLoaded; + + + + + //{{AFX_MSG(CListBoxColor) + afx_msg void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct); + afx_msg void MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnDestroy(); + //}}AFX_MSG + + virtual CRect OnGetCheckPosition( CRect rectItem, CRect rectCheckBox ); + BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult); + + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LIST_BOX_COLOR_H__C4882C3B_0E50_4BC6_A51A_EAA1B4C2E479__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/memory_combo_box.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/memory_combo_box.cpp index 64b5aa2a2..a6d4a909d 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/memory_combo_box.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/memory_combo_box.cpp @@ -1,776 +1,776 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// memory_combo_box.cpp : implementation file -// - -#include "stdafx.h" -#include "memory_combo_box.h" - -using namespace std; -using namespace NLMISC; - -// *************************************************************************** -// CMemoryComboBox -// *************************************************************************** - -CMemoryComboBox::CMemoryComboBox() -{ - _EditChanged = false; - _ComboOpen = false; - _ComboCurSel = -1; - _AutoCompleteExtension = false; -} - -// *************************************************************************** - -CMemoryComboBox::~CMemoryComboBox() -{ -} - -// *************************************************************************** - -void CMemoryComboBox::create (DWORD style, const RECT &rect, CWnd *parent, UINT nId, const char *registerAdress, int memoryCount) -{ - // Register a window - Id = nId; - RegisterAdress = registerAdress; - MemoryCount = memoryCount; - LPCTSTR clas = AfxRegisterWndClass (0); - if (clas) - { - if (Create (clas, "MemoryComboBox", style, rect, parent, nId)) - { - // Create the combo box - RECT comboRect; - comboRect.left = 0; - comboRect.top = 0; - comboRect.right = rect.right-rect.left; - comboRect.bottom = 200; //rect.bottom-rect.top; - _ComboBox.Create (WS_CHILD|WS_VSCROLL|WS_VISIBLE|CBS_DROPDOWN|CBS_HASSTRINGS|CBS_AUTOHSCROLL, comboRect, this, 0); - } - } -} - -// *************************************************************************** - -BEGIN_MESSAGE_MAP(CMemoryComboBox, CWnd) - //{{AFX_MSG_MAP(CMemoryComboBox) - ON_WM_SIZE() - ON_WM_SETFOCUS() - ON_WM_ENABLE() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -// *************************************************************************** - -void CMemoryComboBox::OnSize(UINT nType, int cx, int cy) -{ - CWnd::OnSize(nType, cx, cy); - - if (IsWindow (_ComboBox)) - { - uint pos = _ComboBox.GetEditSel (); - _ComboBox.SetWindowPos (NULL, 0, 0, cx, 200, SWP_NOZORDER); - _ComboBox.SetEditSel (pos&0xffff, pos>>16); - } -} - -// *************************************************************************** - -bool CMemoryComboBox::getMemory (int slot, std::string &ret) -{ - // Open the key - HKEY hKey; - if (RegOpenKey (HKEY_CURRENT_USER, RegisterAdress.c_str (), &hKey) == ERROR_SUCCESS) - { - // Get the value - char strSrc[512]; - smprintf (strSrc, 512, "%d", slot); - char str[512]; - long size = 512; - if (RegQueryValue (hKey, strSrc, str, &size) == ERROR_SUCCESS) - { - ret = str; - - // Close - RegCloseKey (hKey); - - return true; - } - - // Close - RegCloseKey (hKey); - } - return false; -} - -// *************************************************************************** - -void CMemoryComboBox::scrollDown (int start, int end) -{ - // Open the key - HKEY hKey; - if (RegCreateKey (HKEY_CURRENT_USER, RegisterAdress.c_str (), &hKey) == ERROR_SUCCESS) - { - // Scroll down the list - for (int i=end-1; i>start; i--) - { - // Get the old value - char strSrc[512]; - smprintf (strSrc, 512, "%d", i-1); - char str[512]; - long size = 512; - if (RegQueryValue (hKey, strSrc, str, &size) == ERROR_SUCCESS) - { - // Set the value - char strDst[512]; - smprintf (strDst, 512, "%d", i); - RegSetValue (hKey, strDst, REG_SZ, str, size); - } - } - - // Close - RegCloseKey (hKey); - } -} - -// *************************************************************************** - -void CMemoryComboBox::writeStringInRegistry (const std::string &str) -{ - // Open the key - HKEY hKey; - if (RegCreateKey (HKEY_CURRENT_USER, RegisterAdress.c_str (), &hKey) == ERROR_SUCCESS) - { - // Set the value - RegSetValue (hKey, "0", REG_SZ, str.c_str (), str.size ()); - - // Close - RegCloseKey (hKey); - } -} - -// *************************************************************************** - -BOOL CMemoryComboBox::OnCommand(WPARAM wParam, LPARAM lParam) -{ - // Branch the message - switch (HIWORD(wParam)) - { - case CBN_CLOSEUP: - { - // Closed - _ComboOpen = false; - if (_ComboCurSel != _ComboBox.GetCurSel ()) - { - notifyParent (); - } - - CString str; - _ComboBox.GetWindowText (str); - // nlinfo ("CBN_CLOSEUP: %s", str); - - if ((uint)_ComboBox.GetCurSel () < Commands.size()) - { - GetParent ()->SendMessage (MC_COMMAND, Commands[_ComboBox.GetCurSel ()].Id, Id); - } - } - break; - case CBN_SELCHANGE: - { - CString str; - _ComboBox.GetWindowText (str); - // nlinfo ("CBN_SELCHANGE: %s", str); - - // Edit not changed since select a string - _EditChanged = false; - - // Open ? - if (!_ComboOpen) - { - // Notify parent for string change - notifyParent (); - } - } - break; - case CBN_DBLCLK: - { - CString str; - _ComboBox.GetWindowText (str); - // nlinfo ("CBN_DBLCLK: %s", str); - - if ((uint)_ComboBox.GetCurSel () < Commands.size()) - { - break; - } - } - break; - case CBN_EDITCHANGE: - { - _EditChanged = true; - CString str; - _ComboBox.GetWindowText (str); - // nlinfo ("CBN_EDITCHANGE: %s", str); - - if ((uint)_ComboBox.GetCurSel () < Commands.size()) - { - break; - } - }; - break; - case CBN_EDITUPDATE: - { - CString str; - _ComboBox.GetWindowText (str); - // nlinfo ("CBN_EDITUPDATE: %s", str); - - if ((uint)_ComboBox.GetCurSel () < Commands.size()) - { - break; - } - }; - break; - case CBN_DROPDOWN: - { - // Edit change ? - if (_EditChanged) - { - notifyParent (); - } - - // Closed - _ComboOpen = true; - - // Get current text - CString strText; - _ComboBox.GetWindowText (strText); - - // Look for the string in the combo - uint i; - uint count = _ComboBox.GetCount (); - _ComboCurSel = -1; - for (i=0; iSendMessage (WM_NOTIFY, Id, (LPARAM)&strNotify); - } - break; - case CBN_SELENDCANCEL: - { - CString str; - _ComboBox.GetWindowText (str); - // nlinfo ("CBN_SELENDCANCEL: %s", str); - - if ((uint)_ComboBox.GetCurSel () < Commands.size()) - { - } - } - break; - case CBN_SELENDOK: - { - CString str; - _ComboBox.GetWindowText (str); - // nlinfo ("CBN_SELENDOK: %s", str); - - if ((uint)_ComboBox.GetCurSel () < Commands.size()) - { - break; - } - } - break; - case CBN_SETFOCUS: - { - _EditChanged = false; - CString str; - _ComboBox.GetWindowText (str); - refreshStrings (); - _ComboBox.SetWindowText (str); - // nlinfo ("CBN_SETFOCUS: %s", str); - - if ((uint)_ComboBox.GetCurSel () < Commands.size()) - { - break; - } - - // Send the notify message to the parent - NMHDR strNotify; - strNotify.hwndFrom = *this; - strNotify.idFrom = Id; - strNotify.code = NM_SETFOCUS; - GetParent ()->SendMessage (WM_NOTIFY, Id, (LPARAM)&strNotify); - } - break; - } - - return CWnd::OnCommand(wParam, lParam); -} - -// *************************************************************************** - -void CMemoryComboBox::pushString () -{ - CString str; - GetWindowText (str); - pushString((LPCTSTR) str); -} - - -// *************************************************************************** - -void CMemoryComboBox::pushString (const std::string &str) -{ - if (str != "") - { - // Look for an existing static - uint i; - for (i=0; i0) - { - _ComboBox.GetLBText( i, value); - if (value == str.c_str()) - break; - } - } - - // Something change ? - if (i == (int)(itemCount+Commands.size()+ StaticStrings.size())) - { - // Insert the sting - _ComboBox.InsertString (Commands.size()+ StaticStrings.size(), str.c_str()); - } - } - } -} - -// *************************************************************************** - -void CMemoryComboBox::refreshStrings () -{ - _ComboBox.ResetContent (); - - uint i; - for (i=0; iSendMessage (WM_COMMAND, wParam, 0); -} - -// *************************************************************************** - -void CMemoryComboBox::onCancel () -{ - _ComboBox.SetEditSel (0, -1); - - // Send the message to the parent - DWORD wParam = (CBN_SELENDCANCEL<<16) + Id; - GetParent ()->SendMessage (WM_COMMAND, wParam, 0); -} - -// *************************************************************************** - -void CMemoryComboBox::clearStaticStrings () -{ - StaticStrings.clear (); -} - -// *************************************************************************** - -void CMemoryComboBox::addStaticStrings (const char* strings) -{ - StaticStrings.push_back (strings); -} - -// *************************************************************************** - -LRESULT CMemoryComboBox::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) -{ - // Get window text - switch (message) - { - case WM_GETTEXTLENGTH: - { - int curSel = _ComboBox.GetCurSel (); - if ((curSel == -1) || ((uint)curSelGetParent () : NULL; - return focus && - ( (focus->m_hWnd == this->m_hWnd) || (focus->m_hWnd == _ComboBox.m_hWnd ) || - ( parent && (parent->m_hWnd == this->m_hWnd) || (parent->m_hWnd == _ComboBox.m_hWnd ) ) ); -} - -// *************************************************************************** - -bool CMemoryComboBox::isWnd (const CWnd *wnd) const -{ - if (wnd) - { - return (this == wnd) || (&_ComboBox == wnd) || (&_ComboBox == (const CWnd*)wnd->GetParent ()); - } - return false; -} - -// *************************************************************************** - -void CMemoryComboBox::notifyParent () -{ - // nlinfo ("notify parent"); - - // Push the string - pushString (); - - // Edit not changed - _EditChanged = false; - - // Notify parent - CWnd *parent = GetParent (); - if (parent) - { - parent->SendMessage (MC_STRINGCHANGE, Id, 0); - } -} - -// *************************************************************************** - -BOOL CMemoryComboBox::PreTranslateMessage(MSG* pMsg) -{ - switch (pMsg->message) - { - case WM_KEYDOWN: - { - if (pMsg->wParam==VK_ESCAPE) - { - CWnd *parent = GetParent (); - if (parent) - { - parent->SendMessage (MC_ESCAPE, Id, 0); - } - } - if (pMsg->wParam==VK_RETURN) - { - if (!_ComboBox.GetDroppedState ()) - { - // Auto compelete ? - if (_AutoCompleteExtension) - { - CString str; - _ComboBox.GetWindowText (str); - string str2 = str; - if ((!str2.empty ()) && (str2.find ('.') == string::npos)) - { - str2 += "." + _Extension; - _ComboBox.SetWindowText (str2.c_str ()); - } - } - - // Select the text - _ComboBox.SetEditSel (0, -1); - - // Notify parent change - notifyParent (); - return TRUE; - } - } - } - break; - } - - return CWnd::PreTranslateMessage(pMsg); -} - -// *************************************************************************** - -void CMemoryComboBox::OnEnable(BOOL bEnable) -{ - CWnd::OnEnable(bEnable); - - _ComboBox.EnableWindow (bEnable); -} - -// *************************************************************************** - -void CMemoryComboBox::enableAutoCompleteExtension (bool enable, const char * ext) -{ - _AutoCompleteExtension = enable; - const char *point = ext; - while ((*point == '.') || (*point == '*')) - point++; - _Extension = point; -} - -// *************************************************************************** - -CString CMemoryComboBox::getCurrString() const -{ - CString str; - _ComboBox.GetWindowText(str); - return str; -} - -// *************************************************************************** -void CMemoryComboBox::setCurSel(const std::string &value) -{ - int index = _ComboBox.FindStringExact(0, value.c_str()); - if (index != CB_ERR) - { - _ComboBox.SetCurSel(index); - } -} - -// *************************************************************************** -void CMemoryComboBox::setCurSel(int index) -{ - _ComboBox.SetCurSel(index); -} - -// *************************************************************************** -int CMemoryComboBox::getCount() const -{ - return _ComboBox.GetCount(); -} - -// *************************************************************************** -BOOL CMemoryComboBox::setEditSel(int startChar, int endChar) -{ - return _ComboBox.SetEditSel(startChar, endChar); -} - -// *************************************************************************** -void CMemoryComboBox::setFocus() -{ - _ComboBox.SetFocus(); -} - - -// *************************************************************************** - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// memory_combo_box.cpp : implementation file +// + +#include "stdafx.h" +#include "memory_combo_box.h" + +using namespace std; +using namespace NLMISC; + +// *************************************************************************** +// CMemoryComboBox +// *************************************************************************** + +CMemoryComboBox::CMemoryComboBox() +{ + _EditChanged = false; + _ComboOpen = false; + _ComboCurSel = -1; + _AutoCompleteExtension = false; +} + +// *************************************************************************** + +CMemoryComboBox::~CMemoryComboBox() +{ +} + +// *************************************************************************** + +void CMemoryComboBox::create (DWORD style, const RECT &rect, CWnd *parent, UINT nId, const char *registerAdress, int memoryCount) +{ + // Register a window + Id = nId; + RegisterAdress = registerAdress; + MemoryCount = memoryCount; + LPCTSTR clas = AfxRegisterWndClass (0); + if (clas) + { + if (Create (clas, "MemoryComboBox", style, rect, parent, nId)) + { + // Create the combo box + RECT comboRect; + comboRect.left = 0; + comboRect.top = 0; + comboRect.right = rect.right-rect.left; + comboRect.bottom = 200; //rect.bottom-rect.top; + _ComboBox.Create (WS_CHILD|WS_VSCROLL|WS_VISIBLE|CBS_DROPDOWN|CBS_HASSTRINGS|CBS_AUTOHSCROLL, comboRect, this, 0); + } + } +} + +// *************************************************************************** + +BEGIN_MESSAGE_MAP(CMemoryComboBox, CWnd) + //{{AFX_MSG_MAP(CMemoryComboBox) + ON_WM_SIZE() + ON_WM_SETFOCUS() + ON_WM_ENABLE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +// *************************************************************************** + +void CMemoryComboBox::OnSize(UINT nType, int cx, int cy) +{ + CWnd::OnSize(nType, cx, cy); + + if (IsWindow (_ComboBox)) + { + uint pos = _ComboBox.GetEditSel (); + _ComboBox.SetWindowPos (NULL, 0, 0, cx, 200, SWP_NOZORDER); + _ComboBox.SetEditSel (pos&0xffff, pos>>16); + } +} + +// *************************************************************************** + +bool CMemoryComboBox::getMemory (int slot, std::string &ret) +{ + // Open the key + HKEY hKey; + if (RegOpenKey (HKEY_CURRENT_USER, RegisterAdress.c_str (), &hKey) == ERROR_SUCCESS) + { + // Get the value + char strSrc[512]; + smprintf (strSrc, 512, "%d", slot); + char str[512]; + long size = 512; + if (RegQueryValue (hKey, strSrc, str, &size) == ERROR_SUCCESS) + { + ret = str; + + // Close + RegCloseKey (hKey); + + return true; + } + + // Close + RegCloseKey (hKey); + } + return false; +} + +// *************************************************************************** + +void CMemoryComboBox::scrollDown (int start, int end) +{ + // Open the key + HKEY hKey; + if (RegCreateKey (HKEY_CURRENT_USER, RegisterAdress.c_str (), &hKey) == ERROR_SUCCESS) + { + // Scroll down the list + for (int i=end-1; i>start; i--) + { + // Get the old value + char strSrc[512]; + smprintf (strSrc, 512, "%d", i-1); + char str[512]; + long size = 512; + if (RegQueryValue (hKey, strSrc, str, &size) == ERROR_SUCCESS) + { + // Set the value + char strDst[512]; + smprintf (strDst, 512, "%d", i); + RegSetValue (hKey, strDst, REG_SZ, str, size); + } + } + + // Close + RegCloseKey (hKey); + } +} + +// *************************************************************************** + +void CMemoryComboBox::writeStringInRegistry (const std::string &str) +{ + // Open the key + HKEY hKey; + if (RegCreateKey (HKEY_CURRENT_USER, RegisterAdress.c_str (), &hKey) == ERROR_SUCCESS) + { + // Set the value + RegSetValue (hKey, "0", REG_SZ, str.c_str (), str.size ()); + + // Close + RegCloseKey (hKey); + } +} + +// *************************************************************************** + +BOOL CMemoryComboBox::OnCommand(WPARAM wParam, LPARAM lParam) +{ + // Branch the message + switch (HIWORD(wParam)) + { + case CBN_CLOSEUP: + { + // Closed + _ComboOpen = false; + if (_ComboCurSel != _ComboBox.GetCurSel ()) + { + notifyParent (); + } + + CString str; + _ComboBox.GetWindowText (str); + // nlinfo ("CBN_CLOSEUP: %s", str); + + if ((uint)_ComboBox.GetCurSel () < Commands.size()) + { + GetParent ()->SendMessage (MC_COMMAND, Commands[_ComboBox.GetCurSel ()].Id, Id); + } + } + break; + case CBN_SELCHANGE: + { + CString str; + _ComboBox.GetWindowText (str); + // nlinfo ("CBN_SELCHANGE: %s", str); + + // Edit not changed since select a string + _EditChanged = false; + + // Open ? + if (!_ComboOpen) + { + // Notify parent for string change + notifyParent (); + } + } + break; + case CBN_DBLCLK: + { + CString str; + _ComboBox.GetWindowText (str); + // nlinfo ("CBN_DBLCLK: %s", str); + + if ((uint)_ComboBox.GetCurSel () < Commands.size()) + { + break; + } + } + break; + case CBN_EDITCHANGE: + { + _EditChanged = true; + CString str; + _ComboBox.GetWindowText (str); + // nlinfo ("CBN_EDITCHANGE: %s", str); + + if ((uint)_ComboBox.GetCurSel () < Commands.size()) + { + break; + } + }; + break; + case CBN_EDITUPDATE: + { + CString str; + _ComboBox.GetWindowText (str); + // nlinfo ("CBN_EDITUPDATE: %s", str); + + if ((uint)_ComboBox.GetCurSel () < Commands.size()) + { + break; + } + }; + break; + case CBN_DROPDOWN: + { + // Edit change ? + if (_EditChanged) + { + notifyParent (); + } + + // Closed + _ComboOpen = true; + + // Get current text + CString strText; + _ComboBox.GetWindowText (strText); + + // Look for the string in the combo + uint i; + uint count = _ComboBox.GetCount (); + _ComboCurSel = -1; + for (i=0; iSendMessage (WM_NOTIFY, Id, (LPARAM)&strNotify); + } + break; + case CBN_SELENDCANCEL: + { + CString str; + _ComboBox.GetWindowText (str); + // nlinfo ("CBN_SELENDCANCEL: %s", str); + + if ((uint)_ComboBox.GetCurSel () < Commands.size()) + { + } + } + break; + case CBN_SELENDOK: + { + CString str; + _ComboBox.GetWindowText (str); + // nlinfo ("CBN_SELENDOK: %s", str); + + if ((uint)_ComboBox.GetCurSel () < Commands.size()) + { + break; + } + } + break; + case CBN_SETFOCUS: + { + _EditChanged = false; + CString str; + _ComboBox.GetWindowText (str); + refreshStrings (); + _ComboBox.SetWindowText (str); + // nlinfo ("CBN_SETFOCUS: %s", str); + + if ((uint)_ComboBox.GetCurSel () < Commands.size()) + { + break; + } + + // Send the notify message to the parent + NMHDR strNotify; + strNotify.hwndFrom = *this; + strNotify.idFrom = Id; + strNotify.code = NM_SETFOCUS; + GetParent ()->SendMessage (WM_NOTIFY, Id, (LPARAM)&strNotify); + } + break; + } + + return CWnd::OnCommand(wParam, lParam); +} + +// *************************************************************************** + +void CMemoryComboBox::pushString () +{ + CString str; + GetWindowText (str); + pushString((LPCTSTR) str); +} + + +// *************************************************************************** + +void CMemoryComboBox::pushString (const std::string &str) +{ + if (str != "") + { + // Look for an existing static + uint i; + for (i=0; i0) + { + _ComboBox.GetLBText( i, value); + if (value == str.c_str()) + break; + } + } + + // Something change ? + if (i == (int)(itemCount+Commands.size()+ StaticStrings.size())) + { + // Insert the sting + _ComboBox.InsertString (Commands.size()+ StaticStrings.size(), str.c_str()); + } + } + } +} + +// *************************************************************************** + +void CMemoryComboBox::refreshStrings () +{ + _ComboBox.ResetContent (); + + uint i; + for (i=0; iSendMessage (WM_COMMAND, wParam, 0); +} + +// *************************************************************************** + +void CMemoryComboBox::onCancel () +{ + _ComboBox.SetEditSel (0, -1); + + // Send the message to the parent + DWORD wParam = (CBN_SELENDCANCEL<<16) + Id; + GetParent ()->SendMessage (WM_COMMAND, wParam, 0); +} + +// *************************************************************************** + +void CMemoryComboBox::clearStaticStrings () +{ + StaticStrings.clear (); +} + +// *************************************************************************** + +void CMemoryComboBox::addStaticStrings (const char* strings) +{ + StaticStrings.push_back (strings); +} + +// *************************************************************************** + +LRESULT CMemoryComboBox::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) +{ + // Get window text + switch (message) + { + case WM_GETTEXTLENGTH: + { + int curSel = _ComboBox.GetCurSel (); + if ((curSel == -1) || ((uint)curSelGetParent () : NULL; + return focus && + ( (focus->m_hWnd == this->m_hWnd) || (focus->m_hWnd == _ComboBox.m_hWnd ) || + ( parent && (parent->m_hWnd == this->m_hWnd) || (parent->m_hWnd == _ComboBox.m_hWnd ) ) ); +} + +// *************************************************************************** + +bool CMemoryComboBox::isWnd (const CWnd *wnd) const +{ + if (wnd) + { + return (this == wnd) || (&_ComboBox == wnd) || (&_ComboBox == (const CWnd*)wnd->GetParent ()); + } + return false; +} + +// *************************************************************************** + +void CMemoryComboBox::notifyParent () +{ + // nlinfo ("notify parent"); + + // Push the string + pushString (); + + // Edit not changed + _EditChanged = false; + + // Notify parent + CWnd *parent = GetParent (); + if (parent) + { + parent->SendMessage (MC_STRINGCHANGE, Id, 0); + } +} + +// *************************************************************************** + +BOOL CMemoryComboBox::PreTranslateMessage(MSG* pMsg) +{ + switch (pMsg->message) + { + case WM_KEYDOWN: + { + if (pMsg->wParam==VK_ESCAPE) + { + CWnd *parent = GetParent (); + if (parent) + { + parent->SendMessage (MC_ESCAPE, Id, 0); + } + } + if (pMsg->wParam==VK_RETURN) + { + if (!_ComboBox.GetDroppedState ()) + { + // Auto compelete ? + if (_AutoCompleteExtension) + { + CString str; + _ComboBox.GetWindowText (str); + string str2 = str; + if ((!str2.empty ()) && (str2.find ('.') == string::npos)) + { + str2 += "." + _Extension; + _ComboBox.SetWindowText (str2.c_str ()); + } + } + + // Select the text + _ComboBox.SetEditSel (0, -1); + + // Notify parent change + notifyParent (); + return TRUE; + } + } + } + break; + } + + return CWnd::PreTranslateMessage(pMsg); +} + +// *************************************************************************** + +void CMemoryComboBox::OnEnable(BOOL bEnable) +{ + CWnd::OnEnable(bEnable); + + _ComboBox.EnableWindow (bEnable); +} + +// *************************************************************************** + +void CMemoryComboBox::enableAutoCompleteExtension (bool enable, const char * ext) +{ + _AutoCompleteExtension = enable; + const char *point = ext; + while ((*point == '.') || (*point == '*')) + point++; + _Extension = point; +} + +// *************************************************************************** + +CString CMemoryComboBox::getCurrString() const +{ + CString str; + _ComboBox.GetWindowText(str); + return str; +} + +// *************************************************************************** +void CMemoryComboBox::setCurSel(const std::string &value) +{ + int index = _ComboBox.FindStringExact(0, value.c_str()); + if (index != CB_ERR) + { + _ComboBox.SetCurSel(index); + } +} + +// *************************************************************************** +void CMemoryComboBox::setCurSel(int index) +{ + _ComboBox.SetCurSel(index); +} + +// *************************************************************************** +int CMemoryComboBox::getCount() const +{ + return _ComboBox.GetCount(); +} + +// *************************************************************************** +BOOL CMemoryComboBox::setEditSel(int startChar, int endChar) +{ + return _ComboBox.SetEditSel(startChar, endChar); +} + +// *************************************************************************** +void CMemoryComboBox::setFocus() +{ + _ComboBox.SetFocus(); +} + + +// *************************************************************************** + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/memory_combo_box.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/memory_combo_box.h index 2d706d439..4de972865 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/memory_combo_box.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/memory_combo_box.h @@ -1,153 +1,153 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_MEMORY_COMBO_BOX_H__A0A59637_63E4_40A6_AA7D_B57B4707ABF2__INCLUDED_) -#define AFX_MEMORY_COMBO_BOX_H__A0A59637_63E4_40A6_AA7D_B57B4707ABF2__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// memory_combo_box.h : header file -// - -#define MC_COMMAND (WM_APP+0x29) -#define MC_STRINGCHANGE (WM_APP+0x30) -#define MC_ESCAPE (WM_APP+0x45) - -#include - -///////////////////////////////////////////////////////////////////////////// -// CMemoryComboBox window - -class CMemoryComboBox : public CWnd -{ -// Construction -public: - CMemoryComboBox(); - - enum - { - HeightMin = 100, - }; - - void onOK (); - void onCancel (); - void create (DWORD style, const RECT &rect, CWnd *parent, UINT nId, const char *registerAdress, int memoryCount); - void create (DWORD style, const RECT &rect, CWnd *parent, UINT nId); - void setRegisterAdress (const char *registerAdress); - void clearCommand (); - void addCommand (const char* commandLabel, uint commandId); - void clearStaticStrings (); - void addStaticStrings (const char* strings); - uint getCommandCount () const; - void showDropDown (); - bool haveFocus (); - bool isWnd (const CWnd *wnd) const; - void enableAutoCompleteExtension (bool enable, const char * ext); - void setCurSel(const std::string &value); - void setCurSel(int index); - int getCount() const; - BOOL setEditSel(int startChar, int endChar); - void setFocus(); - - std::string RegisterAdress; - int MemoryCount; - UINT Id; - - class CCommand - { - public: - std::string Label; - uint Id; - }; - - std::vector StaticStrings; - std::vector Commands; - - CString getCurrString() const; - - // Add the current string in the registry - void pushString (); - // - void pushString (const std::string &str); - - - // Get strings from the registry - void refreshStrings (); - -private: - - // Auto complete extension - bool _AutoCompleteExtension; - std::string _Extension; - - // Send the string changed to the parent - void notifyParent (); - - - - // The internal combobox - CComboBox _ComboBox; - - // Edit changed - bool _EditChanged; - bool _ComboOpen; - int _ComboCurSel; - - // Use the memory - bool _Memory; - - void scrollDown (int start, int end); - bool getMemory (int slot, std::string &ret); - void addLabelCommands (uint i); - void writeStringInRegistry(const std::string &str); - -// Attributes -public: - -// Operations -public: - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CMemoryComboBox) - public: - virtual BOOL PreTranslateMessage(MSG* pMsg); - protected: - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); - //}}AFX_VIRTUAL - -// Implementation -public: - virtual ~CMemoryComboBox(); - - // Generated message map functions -protected: - //{{AFX_MSG(CMemoryComboBox) - afx_msg void OnSize(UINT nType, int cx, int cy); - afx_msg void OnSetFocus(CWnd* pOldWnd); - afx_msg void OnEnable(BOOL bEnable); - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -///////////////////////////////////////////////////////////////////////////// - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_MEMORY_COMBO_BOX_H__A0A59637_63E4_40A6_AA7D_B57B4707ABF2__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_MEMORY_COMBO_BOX_H__A0A59637_63E4_40A6_AA7D_B57B4707ABF2__INCLUDED_) +#define AFX_MEMORY_COMBO_BOX_H__A0A59637_63E4_40A6_AA7D_B57B4707ABF2__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// memory_combo_box.h : header file +// + +#define MC_COMMAND (WM_APP+0x29) +#define MC_STRINGCHANGE (WM_APP+0x30) +#define MC_ESCAPE (WM_APP+0x45) + +#include + +///////////////////////////////////////////////////////////////////////////// +// CMemoryComboBox window + +class CMemoryComboBox : public CWnd +{ +// Construction +public: + CMemoryComboBox(); + + enum + { + HeightMin = 100, + }; + + void onOK (); + void onCancel (); + void create (DWORD style, const RECT &rect, CWnd *parent, UINT nId, const char *registerAdress, int memoryCount); + void create (DWORD style, const RECT &rect, CWnd *parent, UINT nId); + void setRegisterAdress (const char *registerAdress); + void clearCommand (); + void addCommand (const char* commandLabel, uint commandId); + void clearStaticStrings (); + void addStaticStrings (const char* strings); + uint getCommandCount () const; + void showDropDown (); + bool haveFocus (); + bool isWnd (const CWnd *wnd) const; + void enableAutoCompleteExtension (bool enable, const char * ext); + void setCurSel(const std::string &value); + void setCurSel(int index); + int getCount() const; + BOOL setEditSel(int startChar, int endChar); + void setFocus(); + + std::string RegisterAdress; + int MemoryCount; + UINT Id; + + class CCommand + { + public: + std::string Label; + uint Id; + }; + + std::vector StaticStrings; + std::vector Commands; + + CString getCurrString() const; + + // Add the current string in the registry + void pushString (); + // + void pushString (const std::string &str); + + + // Get strings from the registry + void refreshStrings (); + +private: + + // Auto complete extension + bool _AutoCompleteExtension; + std::string _Extension; + + // Send the string changed to the parent + void notifyParent (); + + + + // The internal combobox + CComboBox _ComboBox; + + // Edit changed + bool _EditChanged; + bool _ComboOpen; + int _ComboCurSel; + + // Use the memory + bool _Memory; + + void scrollDown (int start, int end); + bool getMemory (int slot, std::string &ret); + void addLabelCommands (uint i); + void writeStringInRegistry(const std::string &str); + +// Attributes +public: + +// Operations +public: + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CMemoryComboBox) + public: + virtual BOOL PreTranslateMessage(MSG* pMsg); + protected: + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + +// Implementation +public: + virtual ~CMemoryComboBox(); + + // Generated message map functions +protected: + //{{AFX_MSG(CMemoryComboBox) + afx_msg void OnSize(UINT nType, int cx, int cy); + afx_msg void OnSetFocus(CWnd* pOldWnd); + afx_msg void OnEnable(BOOL bEnable); + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +///////////////////////////////////////////////////////////////////////////// + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_MEMORY_COMBO_BOX_H__A0A59637_63E4_40A6_AA7D_B57B4707ABF2__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/plugin.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/plugin.cpp index c55a6f178..cdcc61c4e 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/plugin.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/plugin.cpp @@ -1,1301 +1,1301 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" -#include "nel/misc/time_nl.h" -#include "plugin.h" -#include "resource.h" -#include "nel/misc/entity_id.h" -#include "nel/misc/geom_ext.h" -#include "nel/misc/time_nl.h" -#include "DialogLogin.h" -#include - -using namespace NLMISC; -using namespace NLLIGO; -using namespace NLSOUND; -using namespace NLNET; -using namespace std; - -CFileDisplayer *ShardMonitorPluginLogDisplayer= NULL; - -// vl: important to add the next line or AfxGetApp() will returns 0 after AFX_MANAGE_STATE(AfxGetStaticModuleState()); -CWinApp theApp; - - -// *************************************************************************** -extern "C" -{ - void *createPlugin() - { - return new CPlugin(); - } -} - -// *************************************************************************** - -CPlugin::CPlugin() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - NLMISC::createDebug(); - ShardMonitorPluginLogDisplayer= new CFileDisplayer("world_editor_shard_monitor_plugin.log", true, "WORLD_EDITOR_SHARD_MONITOR_PLUGIN.LOG"); - DebugLog->addDisplayer (ShardMonitorPluginLogDisplayer); - InfoLog->addDisplayer (ShardMonitorPluginLogDisplayer); - WarningLog->addDisplayer (ShardMonitorPluginLogDisplayer); - ErrorLog->addDisplayer (ShardMonitorPluginLogDisplayer); - AssertLog->addDisplayer (ShardMonitorPluginLogDisplayer); - - nlinfo("Starting shard monitor plugin..."); - - _DialogFlag = new CDialogFlags(NULL); - m_Initialized = false; - _Client = NULL; - _Root = NULL; - _RequestedDownload = 0; - _EntityDisplayMode = EntityType; - _DisplayHits = true; - - _EntityIcons = NULL; - - _CloseUpDisplayDistance = 10.f; - - std::fill(_CloseUpFlags, _CloseUpFlags + sizeofarray(_CloseUpFlags), true); - - _ConnectState = Disconnected; - -} - -// *************************************************************************** - -CPlugin::~CPlugin() -{ - if (m_Initialized) - { - _PluginAccess->deleteRootPluginPrimitive(); - _Root = NULL; - m_Initialized = false; - if (_PluginAccess) - { - _PluginAccess->deleteTexture(_EntityIcons); - } - } -} - -// *************************************************************************** -void CPlugin::progress (float progressValue) -{ -} - -// *************************************************************************** - -void CPlugin::removeEntity (CEntityEntry &entity) -{ - // Changes ? - if (entity.Primitive) - { - std::map::iterator ite = _PrimitiveToString.find (entity.Primitive); - if(ite != _PrimitiveToString.end()) - { - uint32 stringId = (*ite).second; - _PrimitiveToString.erase(entity.Primitive); - - std::multimap::iterator ite2 = _StringToPrimitive.find (stringId); - while ((ite2 != _StringToPrimitive.end()) && (ite2->first == stringId)) - { - std::multimap::iterator ite2delete = ite2; - ite2++; - _StringToPrimitive.erase(ite2delete); - } - } - - _PluginAccess->deletePluginPrimitive (entity.Primitive); - entity.Primitive = NULL; - entity.ColorDirty = true; - } -} - -/** Map a color of an entity to its aspect (color & icon) - * \param di array giving the aspect for several value of the property. - * \param value value for which aspect is queried - * \param defaultValue value of the property that gives the default aspect - */ -static void getEntityColorFromValue(const TEntityDisplayInfoVect &di, uint value, uint defaultValue, CRGBA &destColor) -{ - CRGBA defaultCol(127, 127, 127); - for(uint k = 0; k < di.size(); ++k) - { - if (di[k].Value == defaultValue) - { - defaultCol = di[k].Color; - } - else if (di[k].Value == value) - { - destColor = di[k].Color; - return; - } - } - destColor = defaultCol; -} - - -static void getEntityIconFromValue(const TEntityDisplayInfoVect &di, uint value, uint defaultValue, CEntityIcon &destIcon) -{ - CEntityIcon defaultIcon; - for(uint k = 0; k < di.size(); ++k) - { - if (di[k].Value == defaultValue) - { - defaultIcon = di[k].Icon; - } - else if (di[k].Value == value) - { - destIcon = di[k].Icon; - return; - } - } - destIcon = defaultIcon; -} - -static bool getEntityVisibilityFromValue(const TEntityDisplayInfoVect &di, uint value) -{ - for(uint k = 0; k < di.size(); ++k) - { - if (di[k].Value == value) - { - return di[k].Visible; - } - } - return true; -} - -// *************************************************************************** -void CPlugin::updateEntityAspect(CEntityEntry &entity) -{ - if (!entity.Primitive) return; - NLMISC::CRGBA color; - bool visible = true; - const TEntityDisplayInfoVect &di = _DialogFlag->getEntityDisplayInfos(_EntityDisplayMode); - // update icons - getEntityIconFromValue(_DialogFlag->getEntityDisplayInfos(EntityType), (uint) entity.EntityId.getType(), RYZOMID::unknown, entity.IconForEntityType); - getEntityIconFromValue(_DialogFlag->getEntityDisplayInfos(EntityMode), (uint) entity.Mode, MBEHAV::UNKNOWN_MODE, entity.IconForEntityMode); - // - switch(_EntityDisplayMode) - { - case EntityType: - getEntityColorFromValue(di, (uint) entity.EntityId.getType(), RYZOMID::unknown, color); - visible = getEntityVisibilityFromValue(di, (uint) entity.EntityId.getType()); - break; - case EntityMode: - getEntityColorFromValue(di, (uint) entity.Mode, MBEHAV::UNKNOWN_MODE, color); - visible = getEntityVisibilityFromValue(di, (uint) entity.EntityId.getType()); - break; - case EntityHitPoints: - { - if (entity.MaxHitPoints == 0) - { - color = di[3].Color; - } - else - { - float ratio = (float) entity.HitPoints / (float) entity.MaxHitPoints; - if (ratio > 0.5f) - { - color.blendFromui(di[1].Color, di[2].Color, (uint8) (255.f * 2.f * (ratio - 0.5f))); - } - else - { - color.blendFromui(di[0].Color, di[1].Color, (uint8) (255.f * 2.f * ratio)); - } - } - } - break; - case EntityAlive: - { - if (entity.MaxHitPoints == 0) - { - color = di[2].Color; - } - else - { - if (entity.HitPoints == 0) color = di[0].Color; - else color = di[1].Color; - } - } - break; - default: - nlassert(0); - break; - } - if (color != entity.CurrentColor || entity.ColorDirty) - { - nlassert(entity.Primitive); - entity.Primitive->removePropertyByName ("Color"); - entity.Primitive->addPropertyByName ("Color", new CPropertyColor(color)); - _PluginAccess->invalidatePluginPrimitive (entity.Primitive, QuadTree); - entity.CurrentColor = color; - entity.ColorDirty = false; - } - entity.Hidden = !visible; - _PluginAccess->setPrimitiveHideFlag(*entity.Primitive, !visible); - -} - - -// *************************************************************************** -void serverSentAdd (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - // Get the plugin - CPlugin *plugin = (CPlugin *)(from->appId()); - - // Read the message version - // Version 1 : added sheet id - sint version = msgin.serialVersion(1); - - // Called when the server sent a ADD message - uint32 count; - msgin.serial(count); - - for (uint i = 0;i < count; i++) - { - uint32 id; - uint32 stringId; - CEntityId entityId; - NLMISC::CSheetId sheetID; - msgin.serial(id); - msgin.serial(stringId); - msgin.serial (entityId); - if (version >= 1) - { - msgin.serial(sheetID); - } - - // Resize the player array - if (id >= plugin->_Entites.size()) - plugin->_Entites.resize (id+1); - - std::vector Parameters; - plugin->_Entites[id].Primitive = (CPrimPoint*)(plugin->_PluginAccess->createPluginPrimitive ("player", "", NLMISC::CVector::Null, 0, Parameters, plugin->_Root)); - plugin->_Entites[id].EntityId = entityId; - - if (plugin->_Entites[id].Primitive) - { - if (stringId) - { - plugin->_PrimitiveToString.insert (std::map::value_type (plugin->_Entites[id].Primitive, stringId)); - plugin->_StringToPrimitive.insert (std::multimap::value_type (stringId, plugin->_Entites[id].Primitive)); - - // Set the primitive name - plugin->setPrimitiveName (plugin->_Entites[id].Primitive, stringId); - } - else - { - // Set the new name - plugin->_Entites[id].Primitive->removePropertyByName ("name"); - plugin->_Entites[id].Primitive->addPropertyByName ("name", new CPropertyString (sheetID.toString().c_str())); - - // Invalidate the name - plugin->_PluginAccess->invalidatePluginPrimitive (plugin->_Entites[id].Primitive, LogicTreeParam); - } - - // Set the entity id - plugin->_Entites[id].Primitive->removePropertyByName ("entity id"); - plugin->_Entites[id].Primitive->addPropertyByName ("entity id", new CPropertyString (entityId.toString().c_str())); - - // Set the sheet name - plugin->_Entites[id].Primitive->removePropertyByName ("Sheet"); - plugin->_Entites[id].Primitive->addPropertyByName ("Sheet", new CPropertyString (sheetID.toString().c_str())); - - // set start color - plugin->updateEntityAspect(plugin->_Entites[id]); - } - } -} - -// *************************************************************************** - -void serverSentPos (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - // Get the plugin - CPlugin *plugin = (CPlugin *)(from->appId()); - - // Read the message version - sint version = msgin.serialVersion(0); - - // Called when the server sent a POS message - uint32 count; - msgin.serial(count); - - for (uint i = 0;i < count; i++) - { - uint32 id; - msgin.serial(id); - - // Read position - CPlugin::CEntityEntry &entity = plugin->_Entites[id]; - float x, y, theta; - msgin.serial (x); - msgin.serial (y); - msgin.serial (theta); - - // Changes ? - if (entity.Primitive) - { - if ((entity.Primitive->Point.x != x) || (entity.Primitive->Point.y != y) || (entity.Primitive->Angle != theta)) - { - entity.Primitive->Point.x = x; - entity.Primitive->Point.y = y; - entity.Primitive->Angle = theta; - plugin->_PluginAccess->invalidatePluginPrimitive (entity.Primitive, QuadTree); - } - } - } -} - -// *************************************************************************** - -void serverSentMiscProp (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - // Get the plugin - CPlugin *plugin = (CPlugin *)(from->appId()); - - // Read the message version - sint version = msgin.serialVersion(0); - - // Called when the server sent a HIT_POINTS message - uint32 count; - msgin.serial(count); - - for (uint i = 0;i < count; i++) - { - uint32 id; - msgin.serial(id); - - // Read hitpoints - CPlugin::CEntityEntry &entity = plugin->_Entites[id]; - sint32 hitPoints; - sint32 maxHitPoints; - uint8 mode; - uint8 behaviour; - msgin.serial (hitPoints); - msgin.serial (maxHitPoints); - msgin.serial(mode); - msgin.serial(behaviour); - - - // Changes ? - if (entity.Primitive) - { - if (hitPoints < entity.HitPoints) - { - CPlugin::CHit hit; - hit.EntityId = id; - hit.HitTime = plugin->_CurrentTime; - plugin->_HitList.push_front(hit); - } - entity.HitPoints = hitPoints; - entity.MaxHitPoints = maxHitPoints; - entity.Mode = (MBEHAV::EMode) mode; - - plugin->updateEntityAspect(entity); - plugin->_Entites[id].Primitive->removePropertyByName ("HitPoints"); - plugin->_Entites[id].Primitive->addPropertyByName ("HitPoints", new CPropertyString (toString(hitPoints))); - plugin->_Entites[id].Primitive->removePropertyByName ("MaxHitPoints"); - plugin->_Entites[id].Primitive->addPropertyByName ("MaxHitPoints", new CPropertyString (toString(maxHitPoints))); - plugin->_Entites[id].Primitive->removePropertyByName ("Mode"); - plugin->_Entites[id].Primitive->addPropertyByName ("Mode", new CPropertyString (MBEHAV::modeToString((MBEHAV::EMode) mode))); - plugin->_Entites[id].Primitive->removePropertyByName ("Behaviour"); - plugin->_Entites[id].Primitive->addPropertyByName ("Behaviour", new CPropertyString (MBEHAV::behaviourToString((MBEHAV::EBehaviour) mode))); - plugin->_PluginAccess->invalidatePluginPrimitive (plugin->_Entites[id].Primitive, QuadTree); - - // if the primitive is the only one that is selected, then update the property dialog - const std::list &currSel = plugin->_PluginAccess->getCurrentSelection(); - if (currSel.size() == 1) - { - if (currSel.front() == plugin->_Entites[id].Primitive) - { - // properties for this primitive are currently displayed -> refresh - plugin->_PluginAccess->refreshPropertyDialog(); - } - } - } - } -} - -void serverSentParams(CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - CPlugin *plugin = (CPlugin *)(from->appId()); - CConnectionMsg cm; - cm.MsgType = CConnectionMsg::ServerParamsMsg; - msgin.serial(cm.ServerParams.Version); - msgin.serial(cm.ServerParams.LoginRequired); - plugin->setConnectionMsg(cm); -} - -void serverSentAuthentValid(CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - CPlugin *plugin = (CPlugin *)(from->appId()); - CConnectionMsg cm; - cm.MsgType = CConnectionMsg::AuthentValid; - plugin->setConnectionMsg(cm); -} - -void serverSentAuthentInvalid(CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - CPlugin *plugin = (CPlugin *)(from->appId()); - CConnectionMsg cm; - cm.MsgType = CConnectionMsg::AuthentInvalid; - plugin->setConnectionMsg(cm); -} - - -// *************************************************************************** -void CPlugin::authentValid() -{ - if (_ConnectState == WaitingLoginConfirmation) - { - _ConnectState = Authentificated; - updateConnectionState(); - } -} - -// *************************************************************************** -void CPlugin::authentInvalid() -{ - if (_ConnectState == WaitingLoginConfirmation) - { - if (_Client->connected()) - { - connectDisconnect(); - updateConnectionState(); - } - MessageBox(NULL, getStringRsc(IDS_LOGIN_FAILED), getStringRsc(IDS_ERROR), MB_ICONEXCLAMATION); - } -} - -// *************************************************************************** -void CPlugin::serverParamsReceived(const CServerParams &sp) -{ - nlassert(sp.Version == 0); // version system not used now (since first version ...) - if (_ConnectState != WaitingServerParams) return; - if (sp.LoginRequired) - { - CDialogLogin dl; - if (dl.DoModal() == IDOK) - { - CMessage msg; - msg.setType("AUTHENT"); - std::string login = (LPCTSTR)dl.m_Login; - std::string password = (LPCTSTR)dl.m_Password; - sint ver = msg.serialVersion(0); - msg.serial(login); - msg.serial(password); - _Client->send(msg); - _ConnectState = WaitingLoginConfirmation; - updateConnectionState(); - } - else - { - if (_Client->connected()) - { - connectDisconnect(); - updateConnectionState(); - } - } - } - else - { - // no need for a password, so we are already authentificated - _ConnectState = Authentificated; - updateConnectionState(); - } -} - - -// *************************************************************************** -void CPlugin::setEntityDisplayMode(TEntityDisplayMode edm) -{ - if (edm == _EntityDisplayMode) return; - _EntityDisplayMode = edm; - updateDisplay(); -} - -// *************************************************************************** -void CPlugin::updateDisplay() -{ - for(uint k = 0; k < _Entites.size(); ++k) - { - CPlugin::CEntityEntry &entity = _Entites[k]; - if (entity.Primitive) - { - updateEntityAspect(entity); - _PluginAccess->invalidatePluginPrimitive (entity.Primitive, QuadTree); - } - } -} - -// *************************************************************************** -void serverSentString (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - // Get the plugin - CPlugin *plugin = (CPlugin *)(from->appId()); - - // Read the message version - sint version = msgin.serialVersion(0); - - // Called when the server sent a POS message - uint32 count; - msgin.serial(count); - - for (uint i = 0;i < count; i++) - { - uint32 stringId; - string str; - msgin.serial(stringId); - msgin.serial(str); - - // Set the string - plugin->_StringIdToString.insert (std::map::value_type (stringId, str)); - - // Modify entites - - // Changes ? - std::multimap::iterator ite = plugin->_StringToPrimitive.find (stringId); - while ((ite != plugin->_StringToPrimitive.end()) && (ite->first == stringId)) - { - // Set the name - plugin->setPrimitiveName (ite->second, stringId); - - ite++; - } - } -} - -// *************************************************************************** - -void serverSentRemove (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - // Get the plugin - CPlugin *plugin = (CPlugin *)(from->appId()); - - // Read the message version - sint version = msgin.serialVersion(0); - - // Called when the server sent a POS message - uint32 count; - msgin.serial(count); - - for (uint i = 0;i < count; i++) - { - uint32 id; - msgin.serial(id); - - plugin->removeEntity (plugin->_Entites[id]); - } -} - -// *************************************************************************** -void serverSentInfo (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - // Called when the server sent a INFO message - string text; - msgin.serial(text); - printf("%s\n", text.c_str()); -} - -// *************************************************************************** -// All messages handled by this server -#define NB_CB 9 -TCallbackItem CallbackArray[NB_CB] = -{ - { "ADD", serverSentAdd }, - { "RMV", serverSentRemove }, - { "POS", serverSentPos }, - { "STR", serverSentString }, - { "INFO", serverSentInfo }, - { "MISC_PROP", serverSentMiscProp }, // Misc. properties - { "SERVER_PARAMS", serverSentParams }, - { "AUTHENT_VALID", serverSentAuthentValid }, - { "AUTHENT_INVALID", serverSentAuthentInvalid }, -}; - -// *************************************************************************** - -void CPlugin::init(IPluginAccess *pluginAccess) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - AfxEnableControlContainer(); - try - { - _PluginAccess = pluginAccess; - - // Add the search paths - NLMISC::CConfigFile::CVar *path = _PluginAccess->getConfigFile().getVarPtr("ShardMonitorPath"); - if (path) - { - for(uint k = 0; k < (uint) path->size(); ++k) - { - NLMISC::CPath::addSearchPath(path->asString(k), false, false); - } - } - - // connect to the server here... - - // open the dialog flag window - _DialogFlag->init(this); - _DialogFlag->Create(IDD_DIALOG_FLAGS, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); - _DialogFlag->ShowWindow(TRUE); - - // Read the host where to connect in the client.cfg file - _PluginActive=true; - updateConnectionState(); - - // init the sheets - std::string sheetIDPath = CPath::lookup("sheet_id.bin", false, false); - if (sheetIDPath.empty()) - { - _PluginAccess->errorMessage(NULL, "Couldn't find sheet_id.bin, Please check shard monitor paths in world_editor_plugin.cfg.", "Warning", MB_OK|MB_ICONEXCLAMATION); - } - else - { - NLMISC::CSheetId::init(false); - } - - } - catch (Exception &e) - { - errorMessage (e.what ()); - } -} - -// *************************************************************************** - -void CPlugin::connectDisconnect() -{ - try - { - _DialogFlag->UpdateData(); - _DialogFlag->Download = 0; - _DialogFlag->UpdateData(FALSE); - if (!_Client || !_Client->connected()) - { - // Create the socket - if (_Client) - delete _Client; - _Client = new CCallbackClient; - - // Init and Connect the client to the server located on port 3333 - _Client->addCallbackArray (CallbackArray, NB_CB); - _Client->getSockId ()->setAppId ((uint64)this); - - // connect to the server here... - - // Erase all the primitives - uint i; - for (i=0; i<_Entites.size(); i++) - { - removeEntity (_Entites[i]); - } - - // Erase string cache - _PrimitiveToString.clear (); - _StringToPrimitive.clear (); - _StringIdToString.clear (); - - // Read the host where to connect in the client.cfg file - nlassert (_DialogFlag); - _DialogFlag->UpdateData (TRUE); - - _SHost = (const char*)_DialogFlag->ShardCtrl.getCurrString(); - - _DialogFlag->ShardCtrl.onOK(); - - try - { - CInetAddress addr(_SHost+":48888"); - _Client->connect(addr); - } - catch(ESocket &e) - { - errorMessage (e.what ()); - return; - } - - if (!_Client->connected()) - { - errorMessage ("The connection failed"); - return; - } - - // todo move the looking window - { - /* - CMessage msg; - msg.setType("WINDOW"); - float xmin = 0; - float xmax = 10000; - float ymin = -10000; - float ymax = 0; - msg.serial (xmin); - msg.serial (ymin); - msg.serial (xmax); - msg.serial (ymax); - _Client->send(msg); - */ - _WMin = CVector(+0.0f, -10000.0f, 0.0f); - _WMax = CVector(+10000.0f, +0.0f, 0.0f); - } - - _ConnectState = WaitingServerParams; - } - else - { - // - _Client->disconnect(); - if (_Client->connected()) - { - errorMessage ("The disconnection failed"); - delete _Client; - _Client = NULL; - return; - } - delete _Client; - _Client = NULL; - } - updateConnectionState(); - } - catch (Exception &e) - { - errorMessage (e.what ()); - delete _Client; - _Client = NULL; - } -} - -// *************************************************************************** - -/// The current region has changed. -void CPlugin::primitiveChanged(const NLLIGO::IPrimitive *root) -{ -} - -// *************************************************************************** - -/// The listener has been moved on the map. -void CPlugin::positionMoved(const NLMISC::CVector &position) -{ -} - -// *************************************************************************** - -void CPlugin::lostPositionControl() -{ -} - -// *************************************************************************** - -void CPlugin::onIdle() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - static bool in = false; - if (!in) - { - in = true; - - // during the first call, we create a Root primitive to store all players - if (!m_Initialized) - { - m_Initialized = true; - _Root = _PluginAccess->createRootPluginPrimitive("Shard Monitor"); - - // Set the new name - _Root->removePropertyByName ("name"); - _Root->addPropertyByName ("name", new CPropertyString ("Shard Monitor")); - - // Invalidate the name - _PluginAccess->invalidatePluginPrimitive (_Root, LogicTreeParam); - } - else - { - if (_Client && _Client->connected()) - { - _ConnectionMsg.MsgType = CConnectionMsg::NoMsg; - // first, we receive the stack of messages, which is composed of players informations - _Client->update(); - // See if there's aconnection relarted msg - switch(_ConnectionMsg.MsgType) - { - case CConnectionMsg::ServerParamsMsg: - serverParamsReceived(_ConnectionMsg.ServerParams); - break; - case CConnectionMsg::AuthentValid: - authentValid(); - break; - case CConnectionMsg::AuthentInvalid: - authentInvalid(); - break; - default: - // no-op - break; - } - - - if (_ConnectState == Authentificated) - { - // here check window coordinates - CVector vmin, vmax; - _PluginAccess->getWindowCoordinates(vmin, vmax); - if (vmin != _WMin || vmax != _WMax) - { - CMessage msg; - msg.setType("WINDOW"); - float xmin = vmin.x; - float xmax = vmax.x; - float ymin = vmin.y; - float ymax = vmax.y; - msg.serial (xmin); - msg.serial (ymin); - msg.serial (xmax); - msg.serial (ymax); - _Client->send(msg); - _WMin = vmin; - _WMax = vmax; - } - - if (_CtrlRequestedDownload != _RequestedDownload) - { - _RequestedDownload = _CtrlRequestedDownload; - CMessage msg; - msg.setType("BANDW"); - uint32 bandw = _RequestedDownload; - msg.serial(bandw); - _Client->send(msg); - } - } - } - } - - // Update strings - updateConnectionState(); - - in = false; - - } -} - -const uint HIT_TIME_IN_MS = 1000; - -// *************************************************************************** -void CPlugin::displayHits(CDisplay &display) -{ - std::list::iterator it = _HitList.begin(); - while (it != _HitList.end()) - { - std::list::iterator tmpIt = it; - ++ it; - if (_CurrentTime - tmpIt->HitTime >= HIT_TIME_IN_MS) - { - _HitList.erase(tmpIt); - } - else - { - - CEntityEntry &entity = _Entites[tmpIt->EntityId]; - if (!entity.Hidden && _DisplayHits) - { - const CPrimPoint *point = dynamic_cast(entity.Primitive); - if (point) - { - // Clip ? - if (!display.isClipped (&point->Point, 1)) - { - const float HIT_SIZE = 10.f; - uint dt = (uint) (_CurrentTime - tmpIt->HitTime); - float currHitSize = HIT_SIZE * (float) dt / HIT_TIME_IN_MS; - - // Position in world - CVector center = point->Point; - display.worldToPixel (center); - - // Dot - CVector corners[] = - { - CVector(0.5f, 1.f, 0.f), - CVector(1.0f, 0.5f, 0.f), - CVector(1.0f, -0.5f, 0.f), - CVector(0.5f, -1.f, 0.f), - CVector(-0.5f, -1.f, 0.f), - CVector(-1.f, -0.5f, 0.f), - CVector(-1.f, 0.5f, 0.f), - CVector(-0.5f, 1.f, 0.f), - }; - const uint numCorners = sizeofarray(corners); - for(uint k = 0; k < numCorners; ++k) - { - corners[k] = currHitSize * corners[k] + center; - display.pixelToWorld(corners[k]); - } - const CRGBA HIT_COLOR(255, 0, 0); - for(uint k = 0; k < numCorners; ++k) - { - display.lineRenderProxy(HIT_COLOR, corners[k], corners[(k + 1) % numCorners], 0); - } - } - } - } - } - } -} - - -// *************************************************************************** -void CPlugin::pushIcon(CDisplay &display, sint stepX, sint stepY, NLMISC::CVector &currPos, const CEntityIcon &icon, const CPrimTexture &pt) -{ - // if icon is NULL then no-op - if (icon.X < 0 || icon.Y < 0) return; - CVector center = currPos; - display.worldToPixel(center); - center.x += (float) stepX; - center.y += (float) stepY; - currPos = center; - display.pixelToWorld(currPos); - CVector tl(center.x - ENTITY_ICON_SIZE / 2, center.y + ENTITY_ICON_SIZE / 2, 0.f); - CVector br(center.x + ENTITY_ICON_SIZE / 2, center.y - ENTITY_ICON_SIZE / 2, 0.f); - display.pixelToWorld(tl); - display.pixelToWorld(br); - NLMISC::CQuadColorUV quvc; - quvc.V0.set(tl.x, tl.y, 0.f); - quvc.V1.set(br.x, tl.y, 0.f); - quvc.V2.set(br.x, br.y, 0.f); - quvc.V3.set(tl.x, br.y, 0.f); - quvc.Color0 = quvc.Color1 = quvc.Color2 = quvc.Color3 = CRGBA::White; - if (pt.getWidth() == 0 || pt.getHeight() == 0) - { - // if texture width is 0, then texture hasn't been found, so display the whole 'not found' texture - quvc.Uv0.set(0.f, 0.f); - quvc.Uv1.set(1.f, 0.f); - quvc.Uv2.set(1.f, 1.f); - quvc.Uv3.set(0.f, 1.f); - } - else - { - float invWidth = 1.f / pt.getWidth(); - float invHeight = 1.f / pt.getHeight(); - sint srcX = icon.X * ENTITY_ICON_SIZE; - sint srcY = icon.Y * ENTITY_ICON_SIZE; - quvc.Uv0.set(srcX * invWidth, srcY * invHeight); - quvc.Uv1.set((srcX + ENTITY_ICON_SIZE) * invWidth, srcY * invHeight); - quvc.Uv2.set((srcX + ENTITY_ICON_SIZE) * invWidth, (srcY + ENTITY_ICON_SIZE) * invHeight); - quvc.Uv3.set(srcX * invWidth, (srcY + ENTITY_ICON_SIZE) * invHeight); - } - display.texQuadRenderProxy(quvc, 0); -} - -// *************************************************************************** -void CPlugin::displayCloseUp(CDisplay &display) -{ - // init icon texture if not already done - if (!_EntityIcons) - { - static bool createFailed = false; - if (createFailed) return; - HRSRC rsc = FindResource(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ENTITY_ICONS_TGA), "TGA"); - if (rsc == NULL) - { - createFailed = true; - return; - } - NLMISC::CBitmap bm; - if (!_PluginAccess->buildNLBitmapFromTGARsc(rsc, AfxGetInstanceHandle(), bm)) - { - createFailed = true; - return; - } - _EntityIcons = _PluginAccess->createTexture(); - nlassert(_EntityIcons); - _EntityIcons->buildFromNLBitmap(bm); - } - display.flush(); // must flush before we assign a next texture - display.setLayerTexture(0, _EntityIcons); - for(uint k = 0; k < _Entites.size(); ++k) - { - if (!_Entites[k].Hidden) - { - CEntityEntry &entity = _Entites[k]; - const CPrimPoint *point = dynamic_cast(entity.Primitive); - if (point) - { - // Clip ? - if (!display.isClipped (&point->Point, 1)) - { - CVector currPos = point->Point; - // display type of entity - if (_CloseUpFlags[CloseUpEntityType]) // want to display the type as an icon ? - { - // see if there's an icon associated with current type - pushIcon(display, ENTITY_ICON_SIZE / 2 + 4, 0, currPos, entity.IconForEntityType, *_EntityIcons); - } - if (_CloseUpFlags[CloseUpEntityMode]) // want to display the type as an icon ? - { - // see if there's an icon associated with current type - pushIcon(display, ENTITY_ICON_SIZE + 4, 0, currPos, entity.IconForEntityMode, *_EntityIcons); - } - if (_CloseUpFlags[CloseUpEntityHP]) // want to display the type as an icon ? - { - if (entity.MaxHitPoints != 0) - { - uint iconIndex = 0; - if (entity.HitPoints != 0) - { - iconIndex = 1 + (3 * entity.HitPoints) / entity.MaxHitPoints; - } - // icons position is hardcoded for now... - pushIcon(display, ENTITY_ICON_SIZE + 4, 0, currPos, CEntityIcon(iconIndex, 2), *_EntityIcons); - } - } - } - } - } - } -} - -// *************************************************************************** -void CPlugin::postRender(CDisplay &display) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - _CurrentTime = NLMISC::CTime::getLocalTime(); - const uint HIT_TIME_IN_MS = 1000; - // Display entities that are being hit - displayHits(display); - // Display close up details - CVector oneMeter(1.f, 0.f, 0.f); - display.worldVectorToFloatPixelVector(oneMeter); - if (oneMeter.x >= _CloseUpDisplayDistance) - { - displayCloseUp(display); - } -} - -// *************************************************************************** - -bool CPlugin::yesNoMessage (const char *format, ... ) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - return _PluginAccess->yesNoMessage ("Plugin AI : %s", buffer); -} - -// *************************************************************************** - -void CPlugin::errorMessage (const char *format, ... ) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - _PluginAccess->errorMessage ("Plugin AI : %s", buffer); -} - -// *************************************************************************** - -void CPlugin::infoMessage (const char *format, ... ) -{ - char buffer[1024]; - - if (format) - { - va_list args; - va_start( args, format ); - sint ret = vsnprintf( buffer, 1024, format, args ); - va_end( args ); - } - else - { - strcpy(buffer, "Unknown error"); - } - - _PluginAccess->infoMessage ("Plugin AI : %s", buffer); -} - -// *************************************************************************** - -void CPlugin::updateConnectionState() -{ - _DialogFlag->UpdateData (); - _DialogFlag->Sent = ""; - _DialogFlag->Received = ""; - _DialogFlag->DownloadValue = (toString("%.1f kB/s", _DialogFlag->Download/1024.0)).c_str(); - if (!_Client || !_Client->connected()) - { - _ConnectState = Disconnected; - // Change the text - _DialogFlag->ConnectCtrl.SetWindowText (getStringRsc(IDS_CONNECT)); - _DialogFlag->State = getStringRsc(IDS_NOT_CONNECTED); - } - else - { - switch(_ConnectState) - { - case Authentificated: - { - static deque< pair > dataSize; - dataSize.push_back( make_pair(NLMISC::CTime::getLocalTime(), _Client->getBytesReceived()) ); - if (dataSize.size() > 20) - dataSize.pop_front(); - - double bandwidth = 0.0; - if (dataSize.size() > 1) - { - uint dSize = (uint)(dataSize.back().second - dataSize.front().second); - uint dt = (uint)(dataSize.back().first - dataSize.front().first); - bandwidth = (double)dSize*1000.0 / dt; - } - - // Change the text - _DialogFlag->ConnectCtrl.SetWindowText (getStringRsc(IDS_DISCONNECT)); - _DialogFlag->State = (LPCTSTR) (getStringRsc(IDS_CONNECTED_TO) + _SHost.c_str()); - _DialogFlag->Sent = (toString ((uint32)_Client->getBytesSent ()) + (LPCTSTR) getStringRsc(IDS_BYTE_SENT)).c_str(); - //_DialogFlag->Received = (toString ((uint32)_Client->getBytesReceived ()) + " bytes received").c_str(); - _DialogFlag->Received = (toString("%.1f", bandwidth/1024.0) + " kB/s").c_str(); - _DialogFlag->DownloadValue = (toString("%.1f kB/s", _DialogFlag->Download/1024.0)).c_str(); - _CtrlRequestedDownload = _DialogFlag->Download; - } - break; - case WaitingServerParams: - _DialogFlag->ConnectCtrl.SetWindowText (getStringRsc(IDS_CANCEL_CONNECT)); - _DialogFlag->State = (LPCTSTR) (getStringRsc(IDS_WAITING_SERVER_PARAMS) + _SHost.c_str()); - break; - case WaitingLoginConfirmation: - { - _DialogFlag->ConnectCtrl.SetWindowText (getStringRsc(IDS_CANCEL_CONNECT)); - std::string label = (LPCTSTR) getStringRsc(IDS_WAITING_LOGIN_CONFIRMATION) +_SHost; - switch((NLMISC::CTime::getLocalTime() / 200) % 4) - { - case 0: label+= "-"; break; - case 1: label+= "/"; break; - case 2: label+= "|"; break; - case 3: label+= "\\"; break; - } - _DialogFlag->State = label.c_str(); - } - break; - default: - nlassert(0); - break; - } - } - _DialogFlag->UpdateData (FALSE); -} - -// *************************************************************************** - -void CPlugin::setPrimitiveName (NLLIGO::IPrimitive *primitive, uint32 stringId) -{ - std::map::iterator ite = _StringIdToString.find (stringId); - if (ite != _StringIdToString.end ()) - { - // Set the new name - primitive->removePropertyByName ("name"); - primitive->addPropertyByName ("name", new CPropertyString (ite->second.c_str())); - } - else - { - // Set the new name - primitive->removePropertyByName ("name"); - primitive->addPropertyByName ("name", new CPropertyString ("")); - } - - // Invalidate the name - _PluginAccess->invalidatePluginPrimitive (primitive, LogicTreeParam); -} - -// *************************************************************************** -bool CPlugin::isActive() -{ - return _PluginActive; -} - -// *************************************************************************** -string& CPlugin::getName() -{ - static string ret="Shard Monitor"; - return ret; -} - -// *************************************************************************** -bool CPlugin::activatePlugin() -{ - if(!_PluginActive) - { - _DialogFlag->ShowWindow(TRUE); - _PluginActive=true; - return true; - } - - return false; -} - -// *************************************************************************** -bool CPlugin::closePlugin() -{ - if(_PluginActive) - { - _DialogFlag->ShowWindow(FALSE); - - _PluginActive=false; - - return true; - } - return false; -} - -// *************************************************************************** -void CPlugin::setCloseUpFlag(TCloseUpFlag flag, bool on) -{ - if (on == _CloseUpFlags[flag]) return; - nlassert(flag < CloseUpFlagCount); - _CloseUpFlags[flag] = on; - updateDisplay(); -} - -CString getStringRsc(UINT strID) -{ - CString s; - s.LoadString(strID); - return s; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" +#include "nel/misc/time_nl.h" +#include "plugin.h" +#include "resource.h" +#include "nel/misc/entity_id.h" +#include "nel/misc/geom_ext.h" +#include "nel/misc/time_nl.h" +#include "DialogLogin.h" +#include + +using namespace NLMISC; +using namespace NLLIGO; +using namespace NLSOUND; +using namespace NLNET; +using namespace std; + +CFileDisplayer *ShardMonitorPluginLogDisplayer= NULL; + +// vl: important to add the next line or AfxGetApp() will returns 0 after AFX_MANAGE_STATE(AfxGetStaticModuleState()); +CWinApp theApp; + + +// *************************************************************************** +extern "C" +{ + void *createPlugin() + { + return new CPlugin(); + } +} + +// *************************************************************************** + +CPlugin::CPlugin() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + NLMISC::createDebug(); + ShardMonitorPluginLogDisplayer= new CFileDisplayer("world_editor_shard_monitor_plugin.log", true, "WORLD_EDITOR_SHARD_MONITOR_PLUGIN.LOG"); + DebugLog->addDisplayer (ShardMonitorPluginLogDisplayer); + InfoLog->addDisplayer (ShardMonitorPluginLogDisplayer); + WarningLog->addDisplayer (ShardMonitorPluginLogDisplayer); + ErrorLog->addDisplayer (ShardMonitorPluginLogDisplayer); + AssertLog->addDisplayer (ShardMonitorPluginLogDisplayer); + + nlinfo("Starting shard monitor plugin..."); + + _DialogFlag = new CDialogFlags(NULL); + m_Initialized = false; + _Client = NULL; + _Root = NULL; + _RequestedDownload = 0; + _EntityDisplayMode = EntityType; + _DisplayHits = true; + + _EntityIcons = NULL; + + _CloseUpDisplayDistance = 10.f; + + std::fill(_CloseUpFlags, _CloseUpFlags + sizeofarray(_CloseUpFlags), true); + + _ConnectState = Disconnected; + +} + +// *************************************************************************** + +CPlugin::~CPlugin() +{ + if (m_Initialized) + { + _PluginAccess->deleteRootPluginPrimitive(); + _Root = NULL; + m_Initialized = false; + if (_PluginAccess) + { + _PluginAccess->deleteTexture(_EntityIcons); + } + } +} + +// *************************************************************************** +void CPlugin::progress (float progressValue) +{ +} + +// *************************************************************************** + +void CPlugin::removeEntity (CEntityEntry &entity) +{ + // Changes ? + if (entity.Primitive) + { + std::map::iterator ite = _PrimitiveToString.find (entity.Primitive); + if(ite != _PrimitiveToString.end()) + { + uint32 stringId = (*ite).second; + _PrimitiveToString.erase(entity.Primitive); + + std::multimap::iterator ite2 = _StringToPrimitive.find (stringId); + while ((ite2 != _StringToPrimitive.end()) && (ite2->first == stringId)) + { + std::multimap::iterator ite2delete = ite2; + ite2++; + _StringToPrimitive.erase(ite2delete); + } + } + + _PluginAccess->deletePluginPrimitive (entity.Primitive); + entity.Primitive = NULL; + entity.ColorDirty = true; + } +} + +/** Map a color of an entity to its aspect (color & icon) + * \param di array giving the aspect for several value of the property. + * \param value value for which aspect is queried + * \param defaultValue value of the property that gives the default aspect + */ +static void getEntityColorFromValue(const TEntityDisplayInfoVect &di, uint value, uint defaultValue, CRGBA &destColor) +{ + CRGBA defaultCol(127, 127, 127); + for(uint k = 0; k < di.size(); ++k) + { + if (di[k].Value == defaultValue) + { + defaultCol = di[k].Color; + } + else if (di[k].Value == value) + { + destColor = di[k].Color; + return; + } + } + destColor = defaultCol; +} + + +static void getEntityIconFromValue(const TEntityDisplayInfoVect &di, uint value, uint defaultValue, CEntityIcon &destIcon) +{ + CEntityIcon defaultIcon; + for(uint k = 0; k < di.size(); ++k) + { + if (di[k].Value == defaultValue) + { + defaultIcon = di[k].Icon; + } + else if (di[k].Value == value) + { + destIcon = di[k].Icon; + return; + } + } + destIcon = defaultIcon; +} + +static bool getEntityVisibilityFromValue(const TEntityDisplayInfoVect &di, uint value) +{ + for(uint k = 0; k < di.size(); ++k) + { + if (di[k].Value == value) + { + return di[k].Visible; + } + } + return true; +} + +// *************************************************************************** +void CPlugin::updateEntityAspect(CEntityEntry &entity) +{ + if (!entity.Primitive) return; + NLMISC::CRGBA color; + bool visible = true; + const TEntityDisplayInfoVect &di = _DialogFlag->getEntityDisplayInfos(_EntityDisplayMode); + // update icons + getEntityIconFromValue(_DialogFlag->getEntityDisplayInfos(EntityType), (uint) entity.EntityId.getType(), RYZOMID::unknown, entity.IconForEntityType); + getEntityIconFromValue(_DialogFlag->getEntityDisplayInfos(EntityMode), (uint) entity.Mode, MBEHAV::UNKNOWN_MODE, entity.IconForEntityMode); + // + switch(_EntityDisplayMode) + { + case EntityType: + getEntityColorFromValue(di, (uint) entity.EntityId.getType(), RYZOMID::unknown, color); + visible = getEntityVisibilityFromValue(di, (uint) entity.EntityId.getType()); + break; + case EntityMode: + getEntityColorFromValue(di, (uint) entity.Mode, MBEHAV::UNKNOWN_MODE, color); + visible = getEntityVisibilityFromValue(di, (uint) entity.EntityId.getType()); + break; + case EntityHitPoints: + { + if (entity.MaxHitPoints == 0) + { + color = di[3].Color; + } + else + { + float ratio = (float) entity.HitPoints / (float) entity.MaxHitPoints; + if (ratio > 0.5f) + { + color.blendFromui(di[1].Color, di[2].Color, (uint8) (255.f * 2.f * (ratio - 0.5f))); + } + else + { + color.blendFromui(di[0].Color, di[1].Color, (uint8) (255.f * 2.f * ratio)); + } + } + } + break; + case EntityAlive: + { + if (entity.MaxHitPoints == 0) + { + color = di[2].Color; + } + else + { + if (entity.HitPoints == 0) color = di[0].Color; + else color = di[1].Color; + } + } + break; + default: + nlassert(0); + break; + } + if (color != entity.CurrentColor || entity.ColorDirty) + { + nlassert(entity.Primitive); + entity.Primitive->removePropertyByName ("Color"); + entity.Primitive->addPropertyByName ("Color", new CPropertyColor(color)); + _PluginAccess->invalidatePluginPrimitive (entity.Primitive, QuadTree); + entity.CurrentColor = color; + entity.ColorDirty = false; + } + entity.Hidden = !visible; + _PluginAccess->setPrimitiveHideFlag(*entity.Primitive, !visible); + +} + + +// *************************************************************************** +void serverSentAdd (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + // Get the plugin + CPlugin *plugin = (CPlugin *)(from->appId()); + + // Read the message version + // Version 1 : added sheet id + sint version = msgin.serialVersion(1); + + // Called when the server sent a ADD message + uint32 count; + msgin.serial(count); + + for (uint i = 0;i < count; i++) + { + uint32 id; + uint32 stringId; + CEntityId entityId; + NLMISC::CSheetId sheetID; + msgin.serial(id); + msgin.serial(stringId); + msgin.serial (entityId); + if (version >= 1) + { + msgin.serial(sheetID); + } + + // Resize the player array + if (id >= plugin->_Entites.size()) + plugin->_Entites.resize (id+1); + + std::vector Parameters; + plugin->_Entites[id].Primitive = (CPrimPoint*)(plugin->_PluginAccess->createPluginPrimitive ("player", "", NLMISC::CVector::Null, 0, Parameters, plugin->_Root)); + plugin->_Entites[id].EntityId = entityId; + + if (plugin->_Entites[id].Primitive) + { + if (stringId) + { + plugin->_PrimitiveToString.insert (std::map::value_type (plugin->_Entites[id].Primitive, stringId)); + plugin->_StringToPrimitive.insert (std::multimap::value_type (stringId, plugin->_Entites[id].Primitive)); + + // Set the primitive name + plugin->setPrimitiveName (plugin->_Entites[id].Primitive, stringId); + } + else + { + // Set the new name + plugin->_Entites[id].Primitive->removePropertyByName ("name"); + plugin->_Entites[id].Primitive->addPropertyByName ("name", new CPropertyString (sheetID.toString().c_str())); + + // Invalidate the name + plugin->_PluginAccess->invalidatePluginPrimitive (plugin->_Entites[id].Primitive, LogicTreeParam); + } + + // Set the entity id + plugin->_Entites[id].Primitive->removePropertyByName ("entity id"); + plugin->_Entites[id].Primitive->addPropertyByName ("entity id", new CPropertyString (entityId.toString().c_str())); + + // Set the sheet name + plugin->_Entites[id].Primitive->removePropertyByName ("Sheet"); + plugin->_Entites[id].Primitive->addPropertyByName ("Sheet", new CPropertyString (sheetID.toString().c_str())); + + // set start color + plugin->updateEntityAspect(plugin->_Entites[id]); + } + } +} + +// *************************************************************************** + +void serverSentPos (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + // Get the plugin + CPlugin *plugin = (CPlugin *)(from->appId()); + + // Read the message version + sint version = msgin.serialVersion(0); + + // Called when the server sent a POS message + uint32 count; + msgin.serial(count); + + for (uint i = 0;i < count; i++) + { + uint32 id; + msgin.serial(id); + + // Read position + CPlugin::CEntityEntry &entity = plugin->_Entites[id]; + float x, y, theta; + msgin.serial (x); + msgin.serial (y); + msgin.serial (theta); + + // Changes ? + if (entity.Primitive) + { + if ((entity.Primitive->Point.x != x) || (entity.Primitive->Point.y != y) || (entity.Primitive->Angle != theta)) + { + entity.Primitive->Point.x = x; + entity.Primitive->Point.y = y; + entity.Primitive->Angle = theta; + plugin->_PluginAccess->invalidatePluginPrimitive (entity.Primitive, QuadTree); + } + } + } +} + +// *************************************************************************** + +void serverSentMiscProp (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + // Get the plugin + CPlugin *plugin = (CPlugin *)(from->appId()); + + // Read the message version + sint version = msgin.serialVersion(0); + + // Called when the server sent a HIT_POINTS message + uint32 count; + msgin.serial(count); + + for (uint i = 0;i < count; i++) + { + uint32 id; + msgin.serial(id); + + // Read hitpoints + CPlugin::CEntityEntry &entity = plugin->_Entites[id]; + sint32 hitPoints; + sint32 maxHitPoints; + uint8 mode; + uint8 behaviour; + msgin.serial (hitPoints); + msgin.serial (maxHitPoints); + msgin.serial(mode); + msgin.serial(behaviour); + + + // Changes ? + if (entity.Primitive) + { + if (hitPoints < entity.HitPoints) + { + CPlugin::CHit hit; + hit.EntityId = id; + hit.HitTime = plugin->_CurrentTime; + plugin->_HitList.push_front(hit); + } + entity.HitPoints = hitPoints; + entity.MaxHitPoints = maxHitPoints; + entity.Mode = (MBEHAV::EMode) mode; + + plugin->updateEntityAspect(entity); + plugin->_Entites[id].Primitive->removePropertyByName ("HitPoints"); + plugin->_Entites[id].Primitive->addPropertyByName ("HitPoints", new CPropertyString (toString(hitPoints))); + plugin->_Entites[id].Primitive->removePropertyByName ("MaxHitPoints"); + plugin->_Entites[id].Primitive->addPropertyByName ("MaxHitPoints", new CPropertyString (toString(maxHitPoints))); + plugin->_Entites[id].Primitive->removePropertyByName ("Mode"); + plugin->_Entites[id].Primitive->addPropertyByName ("Mode", new CPropertyString (MBEHAV::modeToString((MBEHAV::EMode) mode))); + plugin->_Entites[id].Primitive->removePropertyByName ("Behaviour"); + plugin->_Entites[id].Primitive->addPropertyByName ("Behaviour", new CPropertyString (MBEHAV::behaviourToString((MBEHAV::EBehaviour) mode))); + plugin->_PluginAccess->invalidatePluginPrimitive (plugin->_Entites[id].Primitive, QuadTree); + + // if the primitive is the only one that is selected, then update the property dialog + const std::list &currSel = plugin->_PluginAccess->getCurrentSelection(); + if (currSel.size() == 1) + { + if (currSel.front() == plugin->_Entites[id].Primitive) + { + // properties for this primitive are currently displayed -> refresh + plugin->_PluginAccess->refreshPropertyDialog(); + } + } + } + } +} + +void serverSentParams(CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + CPlugin *plugin = (CPlugin *)(from->appId()); + CConnectionMsg cm; + cm.MsgType = CConnectionMsg::ServerParamsMsg; + msgin.serial(cm.ServerParams.Version); + msgin.serial(cm.ServerParams.LoginRequired); + plugin->setConnectionMsg(cm); +} + +void serverSentAuthentValid(CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + CPlugin *plugin = (CPlugin *)(from->appId()); + CConnectionMsg cm; + cm.MsgType = CConnectionMsg::AuthentValid; + plugin->setConnectionMsg(cm); +} + +void serverSentAuthentInvalid(CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + CPlugin *plugin = (CPlugin *)(from->appId()); + CConnectionMsg cm; + cm.MsgType = CConnectionMsg::AuthentInvalid; + plugin->setConnectionMsg(cm); +} + + +// *************************************************************************** +void CPlugin::authentValid() +{ + if (_ConnectState == WaitingLoginConfirmation) + { + _ConnectState = Authentificated; + updateConnectionState(); + } +} + +// *************************************************************************** +void CPlugin::authentInvalid() +{ + if (_ConnectState == WaitingLoginConfirmation) + { + if (_Client->connected()) + { + connectDisconnect(); + updateConnectionState(); + } + MessageBox(NULL, getStringRsc(IDS_LOGIN_FAILED), getStringRsc(IDS_ERROR), MB_ICONEXCLAMATION); + } +} + +// *************************************************************************** +void CPlugin::serverParamsReceived(const CServerParams &sp) +{ + nlassert(sp.Version == 0); // version system not used now (since first version ...) + if (_ConnectState != WaitingServerParams) return; + if (sp.LoginRequired) + { + CDialogLogin dl; + if (dl.DoModal() == IDOK) + { + CMessage msg; + msg.setType("AUTHENT"); + std::string login = (LPCTSTR)dl.m_Login; + std::string password = (LPCTSTR)dl.m_Password; + sint ver = msg.serialVersion(0); + msg.serial(login); + msg.serial(password); + _Client->send(msg); + _ConnectState = WaitingLoginConfirmation; + updateConnectionState(); + } + else + { + if (_Client->connected()) + { + connectDisconnect(); + updateConnectionState(); + } + } + } + else + { + // no need for a password, so we are already authentificated + _ConnectState = Authentificated; + updateConnectionState(); + } +} + + +// *************************************************************************** +void CPlugin::setEntityDisplayMode(TEntityDisplayMode edm) +{ + if (edm == _EntityDisplayMode) return; + _EntityDisplayMode = edm; + updateDisplay(); +} + +// *************************************************************************** +void CPlugin::updateDisplay() +{ + for(uint k = 0; k < _Entites.size(); ++k) + { + CPlugin::CEntityEntry &entity = _Entites[k]; + if (entity.Primitive) + { + updateEntityAspect(entity); + _PluginAccess->invalidatePluginPrimitive (entity.Primitive, QuadTree); + } + } +} + +// *************************************************************************** +void serverSentString (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + // Get the plugin + CPlugin *plugin = (CPlugin *)(from->appId()); + + // Read the message version + sint version = msgin.serialVersion(0); + + // Called when the server sent a POS message + uint32 count; + msgin.serial(count); + + for (uint i = 0;i < count; i++) + { + uint32 stringId; + string str; + msgin.serial(stringId); + msgin.serial(str); + + // Set the string + plugin->_StringIdToString.insert (std::map::value_type (stringId, str)); + + // Modify entites + + // Changes ? + std::multimap::iterator ite = plugin->_StringToPrimitive.find (stringId); + while ((ite != plugin->_StringToPrimitive.end()) && (ite->first == stringId)) + { + // Set the name + plugin->setPrimitiveName (ite->second, stringId); + + ite++; + } + } +} + +// *************************************************************************** + +void serverSentRemove (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + // Get the plugin + CPlugin *plugin = (CPlugin *)(from->appId()); + + // Read the message version + sint version = msgin.serialVersion(0); + + // Called when the server sent a POS message + uint32 count; + msgin.serial(count); + + for (uint i = 0;i < count; i++) + { + uint32 id; + msgin.serial(id); + + plugin->removeEntity (plugin->_Entites[id]); + } +} + +// *************************************************************************** +void serverSentInfo (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + // Called when the server sent a INFO message + string text; + msgin.serial(text); + printf("%s\n", text.c_str()); +} + +// *************************************************************************** +// All messages handled by this server +#define NB_CB 9 +TCallbackItem CallbackArray[NB_CB] = +{ + { "ADD", serverSentAdd }, + { "RMV", serverSentRemove }, + { "POS", serverSentPos }, + { "STR", serverSentString }, + { "INFO", serverSentInfo }, + { "MISC_PROP", serverSentMiscProp }, // Misc. properties + { "SERVER_PARAMS", serverSentParams }, + { "AUTHENT_VALID", serverSentAuthentValid }, + { "AUTHENT_INVALID", serverSentAuthentInvalid }, +}; + +// *************************************************************************** + +void CPlugin::init(IPluginAccess *pluginAccess) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + AfxEnableControlContainer(); + try + { + _PluginAccess = pluginAccess; + + // Add the search paths + NLMISC::CConfigFile::CVar *path = _PluginAccess->getConfigFile().getVarPtr("ShardMonitorPath"); + if (path) + { + for(uint k = 0; k < (uint) path->size(); ++k) + { + NLMISC::CPath::addSearchPath(path->asString(k), false, false); + } + } + + // connect to the server here... + + // open the dialog flag window + _DialogFlag->init(this); + _DialogFlag->Create(IDD_DIALOG_FLAGS, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); + _DialogFlag->ShowWindow(TRUE); + + // Read the host where to connect in the client.cfg file + _PluginActive=true; + updateConnectionState(); + + // init the sheets + std::string sheetIDPath = CPath::lookup("sheet_id.bin", false, false); + if (sheetIDPath.empty()) + { + _PluginAccess->errorMessage(NULL, "Couldn't find sheet_id.bin, Please check shard monitor paths in world_editor_plugin.cfg.", "Warning", MB_OK|MB_ICONEXCLAMATION); + } + else + { + NLMISC::CSheetId::init(false); + } + + } + catch (Exception &e) + { + errorMessage (e.what ()); + } +} + +// *************************************************************************** + +void CPlugin::connectDisconnect() +{ + try + { + _DialogFlag->UpdateData(); + _DialogFlag->Download = 0; + _DialogFlag->UpdateData(FALSE); + if (!_Client || !_Client->connected()) + { + // Create the socket + if (_Client) + delete _Client; + _Client = new CCallbackClient; + + // Init and Connect the client to the server located on port 3333 + _Client->addCallbackArray (CallbackArray, NB_CB); + _Client->getSockId ()->setAppId ((uint64)this); + + // connect to the server here... + + // Erase all the primitives + uint i; + for (i=0; i<_Entites.size(); i++) + { + removeEntity (_Entites[i]); + } + + // Erase string cache + _PrimitiveToString.clear (); + _StringToPrimitive.clear (); + _StringIdToString.clear (); + + // Read the host where to connect in the client.cfg file + nlassert (_DialogFlag); + _DialogFlag->UpdateData (TRUE); + + _SHost = (const char*)_DialogFlag->ShardCtrl.getCurrString(); + + _DialogFlag->ShardCtrl.onOK(); + + try + { + CInetAddress addr(_SHost+":48888"); + _Client->connect(addr); + } + catch(ESocket &e) + { + errorMessage (e.what ()); + return; + } + + if (!_Client->connected()) + { + errorMessage ("The connection failed"); + return; + } + + // todo move the looking window + { + /* + CMessage msg; + msg.setType("WINDOW"); + float xmin = 0; + float xmax = 10000; + float ymin = -10000; + float ymax = 0; + msg.serial (xmin); + msg.serial (ymin); + msg.serial (xmax); + msg.serial (ymax); + _Client->send(msg); + */ + _WMin = CVector(+0.0f, -10000.0f, 0.0f); + _WMax = CVector(+10000.0f, +0.0f, 0.0f); + } + + _ConnectState = WaitingServerParams; + } + else + { + // + _Client->disconnect(); + if (_Client->connected()) + { + errorMessage ("The disconnection failed"); + delete _Client; + _Client = NULL; + return; + } + delete _Client; + _Client = NULL; + } + updateConnectionState(); + } + catch (Exception &e) + { + errorMessage (e.what ()); + delete _Client; + _Client = NULL; + } +} + +// *************************************************************************** + +/// The current region has changed. +void CPlugin::primitiveChanged(const NLLIGO::IPrimitive *root) +{ +} + +// *************************************************************************** + +/// The listener has been moved on the map. +void CPlugin::positionMoved(const NLMISC::CVector &position) +{ +} + +// *************************************************************************** + +void CPlugin::lostPositionControl() +{ +} + +// *************************************************************************** + +void CPlugin::onIdle() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + static bool in = false; + if (!in) + { + in = true; + + // during the first call, we create a Root primitive to store all players + if (!m_Initialized) + { + m_Initialized = true; + _Root = _PluginAccess->createRootPluginPrimitive("Shard Monitor"); + + // Set the new name + _Root->removePropertyByName ("name"); + _Root->addPropertyByName ("name", new CPropertyString ("Shard Monitor")); + + // Invalidate the name + _PluginAccess->invalidatePluginPrimitive (_Root, LogicTreeParam); + } + else + { + if (_Client && _Client->connected()) + { + _ConnectionMsg.MsgType = CConnectionMsg::NoMsg; + // first, we receive the stack of messages, which is composed of players informations + _Client->update(); + // See if there's aconnection relarted msg + switch(_ConnectionMsg.MsgType) + { + case CConnectionMsg::ServerParamsMsg: + serverParamsReceived(_ConnectionMsg.ServerParams); + break; + case CConnectionMsg::AuthentValid: + authentValid(); + break; + case CConnectionMsg::AuthentInvalid: + authentInvalid(); + break; + default: + // no-op + break; + } + + + if (_ConnectState == Authentificated) + { + // here check window coordinates + CVector vmin, vmax; + _PluginAccess->getWindowCoordinates(vmin, vmax); + if (vmin != _WMin || vmax != _WMax) + { + CMessage msg; + msg.setType("WINDOW"); + float xmin = vmin.x; + float xmax = vmax.x; + float ymin = vmin.y; + float ymax = vmax.y; + msg.serial (xmin); + msg.serial (ymin); + msg.serial (xmax); + msg.serial (ymax); + _Client->send(msg); + _WMin = vmin; + _WMax = vmax; + } + + if (_CtrlRequestedDownload != _RequestedDownload) + { + _RequestedDownload = _CtrlRequestedDownload; + CMessage msg; + msg.setType("BANDW"); + uint32 bandw = _RequestedDownload; + msg.serial(bandw); + _Client->send(msg); + } + } + } + } + + // Update strings + updateConnectionState(); + + in = false; + + } +} + +const uint HIT_TIME_IN_MS = 1000; + +// *************************************************************************** +void CPlugin::displayHits(CDisplay &display) +{ + std::list::iterator it = _HitList.begin(); + while (it != _HitList.end()) + { + std::list::iterator tmpIt = it; + ++ it; + if (_CurrentTime - tmpIt->HitTime >= HIT_TIME_IN_MS) + { + _HitList.erase(tmpIt); + } + else + { + + CEntityEntry &entity = _Entites[tmpIt->EntityId]; + if (!entity.Hidden && _DisplayHits) + { + const CPrimPoint *point = dynamic_cast(entity.Primitive); + if (point) + { + // Clip ? + if (!display.isClipped (&point->Point, 1)) + { + const float HIT_SIZE = 10.f; + uint dt = (uint) (_CurrentTime - tmpIt->HitTime); + float currHitSize = HIT_SIZE * (float) dt / HIT_TIME_IN_MS; + + // Position in world + CVector center = point->Point; + display.worldToPixel (center); + + // Dot + CVector corners[] = + { + CVector(0.5f, 1.f, 0.f), + CVector(1.0f, 0.5f, 0.f), + CVector(1.0f, -0.5f, 0.f), + CVector(0.5f, -1.f, 0.f), + CVector(-0.5f, -1.f, 0.f), + CVector(-1.f, -0.5f, 0.f), + CVector(-1.f, 0.5f, 0.f), + CVector(-0.5f, 1.f, 0.f), + }; + const uint numCorners = sizeofarray(corners); + for(uint k = 0; k < numCorners; ++k) + { + corners[k] = currHitSize * corners[k] + center; + display.pixelToWorld(corners[k]); + } + const CRGBA HIT_COLOR(255, 0, 0); + for(uint k = 0; k < numCorners; ++k) + { + display.lineRenderProxy(HIT_COLOR, corners[k], corners[(k + 1) % numCorners], 0); + } + } + } + } + } + } +} + + +// *************************************************************************** +void CPlugin::pushIcon(CDisplay &display, sint stepX, sint stepY, NLMISC::CVector &currPos, const CEntityIcon &icon, const CPrimTexture &pt) +{ + // if icon is NULL then no-op + if (icon.X < 0 || icon.Y < 0) return; + CVector center = currPos; + display.worldToPixel(center); + center.x += (float) stepX; + center.y += (float) stepY; + currPos = center; + display.pixelToWorld(currPos); + CVector tl(center.x - ENTITY_ICON_SIZE / 2, center.y + ENTITY_ICON_SIZE / 2, 0.f); + CVector br(center.x + ENTITY_ICON_SIZE / 2, center.y - ENTITY_ICON_SIZE / 2, 0.f); + display.pixelToWorld(tl); + display.pixelToWorld(br); + NLMISC::CQuadColorUV quvc; + quvc.V0.set(tl.x, tl.y, 0.f); + quvc.V1.set(br.x, tl.y, 0.f); + quvc.V2.set(br.x, br.y, 0.f); + quvc.V3.set(tl.x, br.y, 0.f); + quvc.Color0 = quvc.Color1 = quvc.Color2 = quvc.Color3 = CRGBA::White; + if (pt.getWidth() == 0 || pt.getHeight() == 0) + { + // if texture width is 0, then texture hasn't been found, so display the whole 'not found' texture + quvc.Uv0.set(0.f, 0.f); + quvc.Uv1.set(1.f, 0.f); + quvc.Uv2.set(1.f, 1.f); + quvc.Uv3.set(0.f, 1.f); + } + else + { + float invWidth = 1.f / pt.getWidth(); + float invHeight = 1.f / pt.getHeight(); + sint srcX = icon.X * ENTITY_ICON_SIZE; + sint srcY = icon.Y * ENTITY_ICON_SIZE; + quvc.Uv0.set(srcX * invWidth, srcY * invHeight); + quvc.Uv1.set((srcX + ENTITY_ICON_SIZE) * invWidth, srcY * invHeight); + quvc.Uv2.set((srcX + ENTITY_ICON_SIZE) * invWidth, (srcY + ENTITY_ICON_SIZE) * invHeight); + quvc.Uv3.set(srcX * invWidth, (srcY + ENTITY_ICON_SIZE) * invHeight); + } + display.texQuadRenderProxy(quvc, 0); +} + +// *************************************************************************** +void CPlugin::displayCloseUp(CDisplay &display) +{ + // init icon texture if not already done + if (!_EntityIcons) + { + static bool createFailed = false; + if (createFailed) return; + HRSRC rsc = FindResource(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_ENTITY_ICONS_TGA), "TGA"); + if (rsc == NULL) + { + createFailed = true; + return; + } + NLMISC::CBitmap bm; + if (!_PluginAccess->buildNLBitmapFromTGARsc(rsc, AfxGetInstanceHandle(), bm)) + { + createFailed = true; + return; + } + _EntityIcons = _PluginAccess->createTexture(); + nlassert(_EntityIcons); + _EntityIcons->buildFromNLBitmap(bm); + } + display.flush(); // must flush before we assign a next texture + display.setLayerTexture(0, _EntityIcons); + for(uint k = 0; k < _Entites.size(); ++k) + { + if (!_Entites[k].Hidden) + { + CEntityEntry &entity = _Entites[k]; + const CPrimPoint *point = dynamic_cast(entity.Primitive); + if (point) + { + // Clip ? + if (!display.isClipped (&point->Point, 1)) + { + CVector currPos = point->Point; + // display type of entity + if (_CloseUpFlags[CloseUpEntityType]) // want to display the type as an icon ? + { + // see if there's an icon associated with current type + pushIcon(display, ENTITY_ICON_SIZE / 2 + 4, 0, currPos, entity.IconForEntityType, *_EntityIcons); + } + if (_CloseUpFlags[CloseUpEntityMode]) // want to display the type as an icon ? + { + // see if there's an icon associated with current type + pushIcon(display, ENTITY_ICON_SIZE + 4, 0, currPos, entity.IconForEntityMode, *_EntityIcons); + } + if (_CloseUpFlags[CloseUpEntityHP]) // want to display the type as an icon ? + { + if (entity.MaxHitPoints != 0) + { + uint iconIndex = 0; + if (entity.HitPoints != 0) + { + iconIndex = 1 + (3 * entity.HitPoints) / entity.MaxHitPoints; + } + // icons position is hardcoded for now... + pushIcon(display, ENTITY_ICON_SIZE + 4, 0, currPos, CEntityIcon(iconIndex, 2), *_EntityIcons); + } + } + } + } + } + } +} + +// *************************************************************************** +void CPlugin::postRender(CDisplay &display) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + _CurrentTime = NLMISC::CTime::getLocalTime(); + const uint HIT_TIME_IN_MS = 1000; + // Display entities that are being hit + displayHits(display); + // Display close up details + CVector oneMeter(1.f, 0.f, 0.f); + display.worldVectorToFloatPixelVector(oneMeter); + if (oneMeter.x >= _CloseUpDisplayDistance) + { + displayCloseUp(display); + } +} + +// *************************************************************************** + +bool CPlugin::yesNoMessage (const char *format, ... ) +{ + char buffer[1024]; + + if (format) + { + va_list args; + va_start( args, format ); + sint ret = vsnprintf( buffer, 1024, format, args ); + va_end( args ); + } + else + { + strcpy(buffer, "Unknown error"); + } + + return _PluginAccess->yesNoMessage ("Plugin AI : %s", buffer); +} + +// *************************************************************************** + +void CPlugin::errorMessage (const char *format, ... ) +{ + char buffer[1024]; + + if (format) + { + va_list args; + va_start( args, format ); + sint ret = vsnprintf( buffer, 1024, format, args ); + va_end( args ); + } + else + { + strcpy(buffer, "Unknown error"); + } + + _PluginAccess->errorMessage ("Plugin AI : %s", buffer); +} + +// *************************************************************************** + +void CPlugin::infoMessage (const char *format, ... ) +{ + char buffer[1024]; + + if (format) + { + va_list args; + va_start( args, format ); + sint ret = vsnprintf( buffer, 1024, format, args ); + va_end( args ); + } + else + { + strcpy(buffer, "Unknown error"); + } + + _PluginAccess->infoMessage ("Plugin AI : %s", buffer); +} + +// *************************************************************************** + +void CPlugin::updateConnectionState() +{ + _DialogFlag->UpdateData (); + _DialogFlag->Sent = ""; + _DialogFlag->Received = ""; + _DialogFlag->DownloadValue = (toString("%.1f kB/s", _DialogFlag->Download/1024.0)).c_str(); + if (!_Client || !_Client->connected()) + { + _ConnectState = Disconnected; + // Change the text + _DialogFlag->ConnectCtrl.SetWindowText (getStringRsc(IDS_CONNECT)); + _DialogFlag->State = getStringRsc(IDS_NOT_CONNECTED); + } + else + { + switch(_ConnectState) + { + case Authentificated: + { + static deque< pair > dataSize; + dataSize.push_back( make_pair(NLMISC::CTime::getLocalTime(), _Client->getBytesReceived()) ); + if (dataSize.size() > 20) + dataSize.pop_front(); + + double bandwidth = 0.0; + if (dataSize.size() > 1) + { + uint dSize = (uint)(dataSize.back().second - dataSize.front().second); + uint dt = (uint)(dataSize.back().first - dataSize.front().first); + bandwidth = (double)dSize*1000.0 / dt; + } + + // Change the text + _DialogFlag->ConnectCtrl.SetWindowText (getStringRsc(IDS_DISCONNECT)); + _DialogFlag->State = (LPCTSTR) (getStringRsc(IDS_CONNECTED_TO) + _SHost.c_str()); + _DialogFlag->Sent = (toString ((uint32)_Client->getBytesSent ()) + (LPCTSTR) getStringRsc(IDS_BYTE_SENT)).c_str(); + //_DialogFlag->Received = (toString ((uint32)_Client->getBytesReceived ()) + " bytes received").c_str(); + _DialogFlag->Received = (toString("%.1f", bandwidth/1024.0) + " kB/s").c_str(); + _DialogFlag->DownloadValue = (toString("%.1f kB/s", _DialogFlag->Download/1024.0)).c_str(); + _CtrlRequestedDownload = _DialogFlag->Download; + } + break; + case WaitingServerParams: + _DialogFlag->ConnectCtrl.SetWindowText (getStringRsc(IDS_CANCEL_CONNECT)); + _DialogFlag->State = (LPCTSTR) (getStringRsc(IDS_WAITING_SERVER_PARAMS) + _SHost.c_str()); + break; + case WaitingLoginConfirmation: + { + _DialogFlag->ConnectCtrl.SetWindowText (getStringRsc(IDS_CANCEL_CONNECT)); + std::string label = (LPCTSTR) getStringRsc(IDS_WAITING_LOGIN_CONFIRMATION) +_SHost; + switch((NLMISC::CTime::getLocalTime() / 200) % 4) + { + case 0: label+= "-"; break; + case 1: label+= "/"; break; + case 2: label+= "|"; break; + case 3: label+= "\\"; break; + } + _DialogFlag->State = label.c_str(); + } + break; + default: + nlassert(0); + break; + } + } + _DialogFlag->UpdateData (FALSE); +} + +// *************************************************************************** + +void CPlugin::setPrimitiveName (NLLIGO::IPrimitive *primitive, uint32 stringId) +{ + std::map::iterator ite = _StringIdToString.find (stringId); + if (ite != _StringIdToString.end ()) + { + // Set the new name + primitive->removePropertyByName ("name"); + primitive->addPropertyByName ("name", new CPropertyString (ite->second.c_str())); + } + else + { + // Set the new name + primitive->removePropertyByName ("name"); + primitive->addPropertyByName ("name", new CPropertyString ("")); + } + + // Invalidate the name + _PluginAccess->invalidatePluginPrimitive (primitive, LogicTreeParam); +} + +// *************************************************************************** +bool CPlugin::isActive() +{ + return _PluginActive; +} + +// *************************************************************************** +string& CPlugin::getName() +{ + static string ret="Shard Monitor"; + return ret; +} + +// *************************************************************************** +bool CPlugin::activatePlugin() +{ + if(!_PluginActive) + { + _DialogFlag->ShowWindow(TRUE); + _PluginActive=true; + return true; + } + + return false; +} + +// *************************************************************************** +bool CPlugin::closePlugin() +{ + if(_PluginActive) + { + _DialogFlag->ShowWindow(FALSE); + + _PluginActive=false; + + return true; + } + return false; +} + +// *************************************************************************** +void CPlugin::setCloseUpFlag(TCloseUpFlag flag, bool on) +{ + if (on == _CloseUpFlags[flag]) return; + nlassert(flag < CloseUpFlagCount); + _CloseUpFlags[flag] = on; + updateDisplay(); +} + +CString getStringRsc(UINT strID) +{ + CString s; + s.LoadString(strID); + return s; +} diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/plugin.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/plugin.h index 731566ec6..c2eab50df 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/plugin.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/plugin.h @@ -1,263 +1,263 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "DialogFlags.h" -#include "nel/misc/sheet_id.h" -#include "nel/misc/rgba.h" -#include "nel/misc/entity_id.h" -#include "../world_editor/display.h" -#include "../../../../common/src/game_share/mode_and_behaviour.h" - - -#define REGKEY_BASE_PATH "Software\\Nevrax\\nel\\world_editor_shard_monitor_plugin" - -// -struct CServerParams -{ - uint32 Version; - bool LoginRequired; -}; - - -struct CConnectionMsg -{ - enum TMsgType { NoMsg = 0, AuthentValid, AuthentInvalid, ServerParamsMsg }; - TMsgType MsgType; - CServerParams ServerParams; // filled when msgtype is 'ServerParams' -}; - -class CPlugin : public IPluginCallback -{ -public: - - enum TCloseUpFlag - { - CloseUpEntityType = 0, - CloseUpEntityMode, - CloseUpEntityHP, - CloseUpFlagCount - }; - - - friend void serverSentAdd (NLNET::CMessage &msgin, NLNET::TSockId from, NLNET::CCallbackNetBase &netbase); - friend void serverSentPos (NLNET::CMessage &msgin, NLNET::TSockId from, NLNET::CCallbackNetBase &netbase); - friend void serverSentRemove (NLNET::CMessage &msgin, NLNET::TSockId from, NLNET::CCallbackNetBase &netbase); - friend void serverSentString (NLNET::CMessage &msgin, NLNET::TSockId from, NLNET::CCallbackNetBase &netbase); - friend void serverSentMiscProp (NLNET::CMessage &msgin, NLNET::TSockId from, NLNET::CCallbackNetBase &netbase); - - /// Constructor - CPlugin(); - /// Destructor - ~CPlugin(); - - // Connect disconnect - void connectDisconnect(); - - virtual bool isActive(); - - virtual bool activatePlugin(); - - virtual bool closePlugin(); - - virtual std::string& getName(); - - void setEntityDisplayMode(TEntityDisplayMode dm); - - // update colors for all entities - void updateDisplay(); - - // post render part - virtual void postRender(CDisplay &display); - - // display hits on entity - void setDisplayHitsFlag(bool on) { _DisplayHits = on; } - - - void setCloseUpFlag(TCloseUpFlag flag, bool on); - - // Set distance at which close-up details are displayed - void setCloseUpDisplayDistance(float metersPerPixel) { _CloseUpDisplayDistance = metersPerPixel; updateDisplay(); } - - - IPluginAccess *getPluginAccess() const { return _PluginAccess; } - - - void serverParamsReceived(const CServerParams &sp); - - void authentValid(); - void authentInvalid(); - - // set current connection related msg - void setConnectionMsg(const CConnectionMsg &cm) { _ConnectionMsg = cm; } - -private: - - /// An entity entry - class CEntityEntry - { - public: - CEntityEntry () - { - Primitive = NULL; - ColorDirty = true; - HitPoints = 0; - MaxHitPoints = 0; - Hidden = false; - Mode = MBEHAV::UNKNOWN_MODE; - } - NLMISC::CEntityId EntityId; - NLLIGO::CPrimPoint *Primitive; - NLMISC::CRGBA CurrentColor; - bool ColorDirty; - sint32 HitPoints; - sint32 MaxHitPoints; - MBEHAV::EMode Mode; - bool Hidden; // reminder for hidden flag - // cache for the type icon (if any) - CEntityIcon IconForEntityType; - // cache for the mode icon (if any) - CEntityIcon IconForEntityMode; - }; - - // Current host - std::string _SHost; - - // Root primitive index - NLLIGO::IPrimitive *_Root; - - // Error messages - bool yesNoMessage (const char *format, ... ); - void errorMessage (const char *format, ... ); - void infoMessage (const char *format, ... ); - - // Connect disconnect - void updateConnectionState(); - - // @{ - // \name Overload for IPluginCallback - virtual void init(IPluginAccess *pluginAccess); - - /// The current region has changed. - virtual void primitiveChanged(const NLLIGO::IPrimitive *root); - - /// The region has been modified. - /// The listener has been moved on the map. - virtual void positionMoved(const NLMISC::CVector &position); - /// The plug-in lost the control of the position - virtual void lostPositionControl(); - - // update color & visibility of an entity - void updateEntityAspect(CEntityEntry &entity); - - // @} - - // Remove an entity primitive - void removeEntity (CEntityEntry &entity); - - // Set an entity primitive name - void setPrimitiveName (NLLIGO::IPrimitive *primitive, uint32 stringId); - - // callback for mixer init progression - void progress (float progressValue); - - /// The plug-in dialog. - CDialogFlags *_DialogFlag; - - /// The network callback - NLNET::CCallbackClient *_Client; - - CConnectionMsg _ConnectionMsg; - - /// the position of the listener. - virtual void onIdle(); - - bool _PluginActive; - - bool m_Initialized; - - bool _DisplayHits; - - // The entity vector - std::vector _Entites; - - // The plugin acces - IPluginAccess *_PluginAccess; - - // Primitive to string id map - std::map _PrimitiveToString; - - // String id to primitive waiting there string id multimap - std::multimap _StringToPrimitive; - - // String id to string map - std::map _StringIdToString; - - // Current window coordinates - NLMISC::CVector _WMin, _WMax; - - // Request Download - uint _RequestedDownload; - uint _CtrlRequestedDownload; - - TEntityDisplayMode _EntityDisplayMode; - - NLMISC::TTime _CurrentTime; - - // A hit on an entity. All hits are displayed on the map - struct CHit - { - uint EntityId; - NLMISC::TTime HitTime; - }; - - /// list of hits - std::list _HitList; - - CPrimTexture *_EntityIcons; - - bool _CloseUpFlags[CloseUpFlagCount]; - - float _CloseUpDisplayDistance; - - // display hits on entities - void displayHits(CDisplay &display); - // display an icon & update position for next display - void pushIcon(CDisplay &display, sint stepX, sint stepY, NLMISC::CVector &currPos, const CEntityIcon &icon, const CPrimTexture &pt); - // display close-up icons for all entities - void displayCloseUp(CDisplay &display); - - - enum TConnectState - { - Disconnected = 0, - WaitingServerParams, - WaitingLoginConfirmation, - Authentificated - }; - - TConnectState _ConnectState; - -}; - -extern "C" -{ - /// Export the C factory method for dynamic linking.. - __declspec( dllexport ) void *createPlugin(); -} - -// geta string from string table -CString getStringRsc(UINT strID); - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "DialogFlags.h" +#include "nel/misc/sheet_id.h" +#include "nel/misc/rgba.h" +#include "nel/misc/entity_id.h" +#include "../world_editor/display.h" +#include "../../../../common/src/game_share/mode_and_behaviour.h" + + +#define REGKEY_BASE_PATH "Software\\Nevrax\\nel\\world_editor_shard_monitor_plugin" + +// +struct CServerParams +{ + uint32 Version; + bool LoginRequired; +}; + + +struct CConnectionMsg +{ + enum TMsgType { NoMsg = 0, AuthentValid, AuthentInvalid, ServerParamsMsg }; + TMsgType MsgType; + CServerParams ServerParams; // filled when msgtype is 'ServerParams' +}; + +class CPlugin : public IPluginCallback +{ +public: + + enum TCloseUpFlag + { + CloseUpEntityType = 0, + CloseUpEntityMode, + CloseUpEntityHP, + CloseUpFlagCount + }; + + + friend void serverSentAdd (NLNET::CMessage &msgin, NLNET::TSockId from, NLNET::CCallbackNetBase &netbase); + friend void serverSentPos (NLNET::CMessage &msgin, NLNET::TSockId from, NLNET::CCallbackNetBase &netbase); + friend void serverSentRemove (NLNET::CMessage &msgin, NLNET::TSockId from, NLNET::CCallbackNetBase &netbase); + friend void serverSentString (NLNET::CMessage &msgin, NLNET::TSockId from, NLNET::CCallbackNetBase &netbase); + friend void serverSentMiscProp (NLNET::CMessage &msgin, NLNET::TSockId from, NLNET::CCallbackNetBase &netbase); + + /// Constructor + CPlugin(); + /// Destructor + ~CPlugin(); + + // Connect disconnect + void connectDisconnect(); + + virtual bool isActive(); + + virtual bool activatePlugin(); + + virtual bool closePlugin(); + + virtual std::string& getName(); + + void setEntityDisplayMode(TEntityDisplayMode dm); + + // update colors for all entities + void updateDisplay(); + + // post render part + virtual void postRender(CDisplay &display); + + // display hits on entity + void setDisplayHitsFlag(bool on) { _DisplayHits = on; } + + + void setCloseUpFlag(TCloseUpFlag flag, bool on); + + // Set distance at which close-up details are displayed + void setCloseUpDisplayDistance(float metersPerPixel) { _CloseUpDisplayDistance = metersPerPixel; updateDisplay(); } + + + IPluginAccess *getPluginAccess() const { return _PluginAccess; } + + + void serverParamsReceived(const CServerParams &sp); + + void authentValid(); + void authentInvalid(); + + // set current connection related msg + void setConnectionMsg(const CConnectionMsg &cm) { _ConnectionMsg = cm; } + +private: + + /// An entity entry + class CEntityEntry + { + public: + CEntityEntry () + { + Primitive = NULL; + ColorDirty = true; + HitPoints = 0; + MaxHitPoints = 0; + Hidden = false; + Mode = MBEHAV::UNKNOWN_MODE; + } + NLMISC::CEntityId EntityId; + NLLIGO::CPrimPoint *Primitive; + NLMISC::CRGBA CurrentColor; + bool ColorDirty; + sint32 HitPoints; + sint32 MaxHitPoints; + MBEHAV::EMode Mode; + bool Hidden; // reminder for hidden flag + // cache for the type icon (if any) + CEntityIcon IconForEntityType; + // cache for the mode icon (if any) + CEntityIcon IconForEntityMode; + }; + + // Current host + std::string _SHost; + + // Root primitive index + NLLIGO::IPrimitive *_Root; + + // Error messages + bool yesNoMessage (const char *format, ... ); + void errorMessage (const char *format, ... ); + void infoMessage (const char *format, ... ); + + // Connect disconnect + void updateConnectionState(); + + // @{ + // \name Overload for IPluginCallback + virtual void init(IPluginAccess *pluginAccess); + + /// The current region has changed. + virtual void primitiveChanged(const NLLIGO::IPrimitive *root); + + /// The region has been modified. + /// The listener has been moved on the map. + virtual void positionMoved(const NLMISC::CVector &position); + /// The plug-in lost the control of the position + virtual void lostPositionControl(); + + // update color & visibility of an entity + void updateEntityAspect(CEntityEntry &entity); + + // @} + + // Remove an entity primitive + void removeEntity (CEntityEntry &entity); + + // Set an entity primitive name + void setPrimitiveName (NLLIGO::IPrimitive *primitive, uint32 stringId); + + // callback for mixer init progression + void progress (float progressValue); + + /// The plug-in dialog. + CDialogFlags *_DialogFlag; + + /// The network callback + NLNET::CCallbackClient *_Client; + + CConnectionMsg _ConnectionMsg; + + /// the position of the listener. + virtual void onIdle(); + + bool _PluginActive; + + bool m_Initialized; + + bool _DisplayHits; + + // The entity vector + std::vector _Entites; + + // The plugin acces + IPluginAccess *_PluginAccess; + + // Primitive to string id map + std::map _PrimitiveToString; + + // String id to primitive waiting there string id multimap + std::multimap _StringToPrimitive; + + // String id to string map + std::map _StringIdToString; + + // Current window coordinates + NLMISC::CVector _WMin, _WMax; + + // Request Download + uint _RequestedDownload; + uint _CtrlRequestedDownload; + + TEntityDisplayMode _EntityDisplayMode; + + NLMISC::TTime _CurrentTime; + + // A hit on an entity. All hits are displayed on the map + struct CHit + { + uint EntityId; + NLMISC::TTime HitTime; + }; + + /// list of hits + std::list _HitList; + + CPrimTexture *_EntityIcons; + + bool _CloseUpFlags[CloseUpFlagCount]; + + float _CloseUpDisplayDistance; + + // display hits on entities + void displayHits(CDisplay &display); + // display an icon & update position for next display + void pushIcon(CDisplay &display, sint stepX, sint stepY, NLMISC::CVector &currPos, const CEntityIcon &icon, const CPrimTexture &pt); + // display close-up icons for all entities + void displayCloseUp(CDisplay &display); + + + enum TConnectState + { + Disconnected = 0, + WaitingServerParams, + WaitingLoginConfirmation, + Authentificated + }; + + TConnectState _ConnectState; + +}; + +extern "C" +{ + /// Export the C factory method for dynamic linking.. + __declspec( dllexport ) void *createPlugin(); +} + +// geta string from string table +CString getStringRsc(UINT strID); + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/resource.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/resource.h index d36c07631..c75be5f11 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/resource.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/resource.h @@ -1,125 +1,125 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by world_editor_shard_monitor_plugin.rc -// -#define IDS_CONNECT 1 -#define IDS_NOT_CONNECTED 2 -#define IDS_DISCONNECT 3 -#define IDS_CONNECTED_TO 4 -#define IDS_BYTE_SENT 5 -#define IDS_WAITING_SERVER_PARAMS 6 -#define IDS_CANCEL_CONNECT 7 -#define IDS_WAITING_LOGIN_CONFIRMATION_0 8 -#define IDS_WAITING_LOGIN_CONFIRMATION 8 -#define IDS_LOGIN_FAILED 9 -#define IDS_ERROR 10 -#define IDR_TOOLBAR1 101 -#define IDR_TOOLBAR_SOUND 101 -#define IDB_BITMAP_STOP 103 -#define IDD_DIALOG_FLAGS 104 -#define IDB_BITMAP_PLAY 105 -#define IDB_BITMAP_EAR 106 -#define IDB_BITMAP_MOVE_EAR 107 -#define IDD_DIALOG_LOAD 108 -#define IDR_ENTITY_ICONS_TGA 112 -#define IDD_DIALOG_LOGIN 113 -#define IDC_CHECK_FLAG_00 1000 -#define IDC_CHECK_FLAG_01 1001 -#define IDC_CHECK_FLAG_02 1002 -#define IDC_CHECK_FLAG_03 1003 -#define IDC_CHECK_FLAG_04 1004 -#define IDC_CHECK_FLAG_05 1005 -#define IDC_CHECK_FLAG_06 1006 -#define IDC_CHECK_FLAG_07 1007 -#define IDC_CHECK_FLAG_08 1008 -#define IDC_CHECK_FLAG_09 1009 -#define IDC_CHECK_FLAG_10 1010 -#define IDC_CHECK_FLAG_11 1011 -#define IDC_CHECK_FLAG_12 1012 -#define IDC_CHECK_FLAG_13 1013 -#define IDC_CHECK_FLAG_14 1014 -#define IDC_CHECK_FLAG_15 1015 -#define IDC_BUTTON_PLAY_STOP 1016 -#define IDC_CHECK_MOVE_EAR 1018 -#define IDC_STATIC_MESSAGE 1019 -#define IDC_CHECK_FLAG_16 1019 -#define IDC_STATIC_SAMPLE_SIZE 1020 -#define IDC_CHECK_FLAG_17 1021 -#define IDC_CHECK_FLAG_18 1022 -#define IDC_CHECK_FLAG_19 1023 -#define IDC_CHECK_FLAG_20 1024 -#define IDC_CHECK_FLAG_21 1025 -#define IDC_CHECK_FLAG_22 1026 -#define IDC_CHECK_FLAG_23 1027 -#define IDC_CHECK_FLAG_24 1028 -#define IDC_CHECK_FLAG_25 1029 -#define IDC_CHECK_FLAG_26 1030 -#define IDC_CHECK_FLAG_27 1031 -#define IDC_CHECK_FLAG_28 1032 -#define IDC_CHECK_FLAG_29 1033 -#define IDC_CHECK_FLAG_30 1034 -#define IDC_CHECK_FLAG_31 1035 -#define IDC_SCROLLBAR_SB 1037 -#define IDC_SB_LIST 1059 -#define IDC_BUTTON1 1060 -#define IDC_CONNECT 1060 -#define IDC_STATE 1061 -#define IDC_RECEIVED 1062 -#define IDC_SENT 1063 -#define IDC_ENTITES 1064 -#define IDC_SHARD 1065 -#define IDC_DOWNLOAD 1066 -#define IDC_DLDVALUE 1068 -#define IDC_DISPLAY_MODE 1069 -#define IDC_DISPLAY_MODE_COMBO 1070 -#define IDC_ENTITY_COLORS 1071 -#define IDC_COLOR_LIST 1073 -#define IDC_BROWSE_COLOR 1074 -#define IDC_SELECT_ALL 1075 -#define IDC_UNSELECT_ALL 1076 -#define IDC_STATIC_SHARD 1077 -#define IDC_STATIC_DISPLAY 1078 -#define IDC_STATIC_CLOSE_UP_DETAILS 1079 -#define IDC_CLOSE_UP_SHOW_TYPE 1080 -#define IDC_CLOSE_UP_SHOW_MODE 1081 -#define IDC_CLOSE_UP_SHOW_HP 1082 -#define IDC_HP_DOWN 1083 -#define IDC_DETAIL_DISTANCE_STATIC 1084 -#define IDC_DETAILS_DISTANCE 1085 -#define IDC_STATIC_NEAR 1087 -#define IDC_STATIC_FAR 1088 -#define IDC_SHARD_LIST_PLACEMENT 1091 -#define IDC_LOGIN_TEXT 1092 -#define IDC_PASSWORD_TEXT 1093 -#define IDC_LOGIN 1095 -#define IDC_PASSWORD 1096 -#define ID_BUTTON40001 40001 -#define ID_BUTTON40002 40002 -#define ID_BUTTON40003 40003 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 114 -#define _APS_NEXT_COMMAND_VALUE 40004 -#define _APS_NEXT_CONTROL_VALUE 1097 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by world_editor_shard_monitor_plugin.rc +// +#define IDS_CONNECT 1 +#define IDS_NOT_CONNECTED 2 +#define IDS_DISCONNECT 3 +#define IDS_CONNECTED_TO 4 +#define IDS_BYTE_SENT 5 +#define IDS_WAITING_SERVER_PARAMS 6 +#define IDS_CANCEL_CONNECT 7 +#define IDS_WAITING_LOGIN_CONFIRMATION_0 8 +#define IDS_WAITING_LOGIN_CONFIRMATION 8 +#define IDS_LOGIN_FAILED 9 +#define IDS_ERROR 10 +#define IDR_TOOLBAR1 101 +#define IDR_TOOLBAR_SOUND 101 +#define IDB_BITMAP_STOP 103 +#define IDD_DIALOG_FLAGS 104 +#define IDB_BITMAP_PLAY 105 +#define IDB_BITMAP_EAR 106 +#define IDB_BITMAP_MOVE_EAR 107 +#define IDD_DIALOG_LOAD 108 +#define IDR_ENTITY_ICONS_TGA 112 +#define IDD_DIALOG_LOGIN 113 +#define IDC_CHECK_FLAG_00 1000 +#define IDC_CHECK_FLAG_01 1001 +#define IDC_CHECK_FLAG_02 1002 +#define IDC_CHECK_FLAG_03 1003 +#define IDC_CHECK_FLAG_04 1004 +#define IDC_CHECK_FLAG_05 1005 +#define IDC_CHECK_FLAG_06 1006 +#define IDC_CHECK_FLAG_07 1007 +#define IDC_CHECK_FLAG_08 1008 +#define IDC_CHECK_FLAG_09 1009 +#define IDC_CHECK_FLAG_10 1010 +#define IDC_CHECK_FLAG_11 1011 +#define IDC_CHECK_FLAG_12 1012 +#define IDC_CHECK_FLAG_13 1013 +#define IDC_CHECK_FLAG_14 1014 +#define IDC_CHECK_FLAG_15 1015 +#define IDC_BUTTON_PLAY_STOP 1016 +#define IDC_CHECK_MOVE_EAR 1018 +#define IDC_STATIC_MESSAGE 1019 +#define IDC_CHECK_FLAG_16 1019 +#define IDC_STATIC_SAMPLE_SIZE 1020 +#define IDC_CHECK_FLAG_17 1021 +#define IDC_CHECK_FLAG_18 1022 +#define IDC_CHECK_FLAG_19 1023 +#define IDC_CHECK_FLAG_20 1024 +#define IDC_CHECK_FLAG_21 1025 +#define IDC_CHECK_FLAG_22 1026 +#define IDC_CHECK_FLAG_23 1027 +#define IDC_CHECK_FLAG_24 1028 +#define IDC_CHECK_FLAG_25 1029 +#define IDC_CHECK_FLAG_26 1030 +#define IDC_CHECK_FLAG_27 1031 +#define IDC_CHECK_FLAG_28 1032 +#define IDC_CHECK_FLAG_29 1033 +#define IDC_CHECK_FLAG_30 1034 +#define IDC_CHECK_FLAG_31 1035 +#define IDC_SCROLLBAR_SB 1037 +#define IDC_SB_LIST 1059 +#define IDC_BUTTON1 1060 +#define IDC_CONNECT 1060 +#define IDC_STATE 1061 +#define IDC_RECEIVED 1062 +#define IDC_SENT 1063 +#define IDC_ENTITES 1064 +#define IDC_SHARD 1065 +#define IDC_DOWNLOAD 1066 +#define IDC_DLDVALUE 1068 +#define IDC_DISPLAY_MODE 1069 +#define IDC_DISPLAY_MODE_COMBO 1070 +#define IDC_ENTITY_COLORS 1071 +#define IDC_COLOR_LIST 1073 +#define IDC_BROWSE_COLOR 1074 +#define IDC_SELECT_ALL 1075 +#define IDC_UNSELECT_ALL 1076 +#define IDC_STATIC_SHARD 1077 +#define IDC_STATIC_DISPLAY 1078 +#define IDC_STATIC_CLOSE_UP_DETAILS 1079 +#define IDC_CLOSE_UP_SHOW_TYPE 1080 +#define IDC_CLOSE_UP_SHOW_MODE 1081 +#define IDC_CLOSE_UP_SHOW_HP 1082 +#define IDC_HP_DOWN 1083 +#define IDC_DETAIL_DISTANCE_STATIC 1084 +#define IDC_DETAILS_DISTANCE 1085 +#define IDC_STATIC_NEAR 1087 +#define IDC_STATIC_FAR 1088 +#define IDC_SHARD_LIST_PLACEMENT 1091 +#define IDC_LOGIN_TEXT 1092 +#define IDC_PASSWORD_TEXT 1093 +#define IDC_LOGIN 1095 +#define IDC_PASSWORD 1096 +#define ID_BUTTON40001 40001 +#define ID_BUTTON40002 40002 +#define ID_BUTTON40003 40003 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 114 +#define _APS_NEXT_COMMAND_VALUE 40004 +#define _APS_NEXT_CONTROL_VALUE 1097 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/world_editor_shard_monitor_plugin.xml b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/world_editor_shard_monitor_plugin.xml index d07a955e9..7f017a34b 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/world_editor_shard_monitor_plugin.xml +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_shard_monitor_plugin/world_editor_shard_monitor_plugin.xml @@ -1,13 +1,13 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/DialogFlags.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/DialogFlags.cpp index 036e197fe..83c9ab58a 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/DialogFlags.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/DialogFlags.cpp @@ -1,329 +1,329 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// DailogFlags.cpp : implementation file -// - -#include "stdafx.h" -#include "DialogFlags.h" -#include -#include "sound_plugin.h" -#include "nel/sound/u_listener.h" - - -using namespace std; -using namespace NLMISC; -using namespace NLSOUND; - -::CBitmap PlayBitmap; -::CBitmap StopBitmap; -::CBitmap EarBitmap; -::CBitmap EarMoveBitmap; - -uint BG_FLAG_ID[] = -{ - IDC_CHECK_FLAG_00, - IDC_CHECK_FLAG_01, - IDC_CHECK_FLAG_02, - IDC_CHECK_FLAG_03, - IDC_CHECK_FLAG_04, - IDC_CHECK_FLAG_05, - IDC_CHECK_FLAG_06, - IDC_CHECK_FLAG_07, - IDC_CHECK_FLAG_08, - IDC_CHECK_FLAG_09, - IDC_CHECK_FLAG_10, - IDC_CHECK_FLAG_11, - IDC_CHECK_FLAG_12, - IDC_CHECK_FLAG_13, - IDC_CHECK_FLAG_14, - IDC_CHECK_FLAG_15, - IDC_CHECK_FLAG_16, - IDC_CHECK_FLAG_17, - IDC_CHECK_FLAG_18, - IDC_CHECK_FLAG_19, - IDC_CHECK_FLAG_20, - IDC_CHECK_FLAG_21, - IDC_CHECK_FLAG_22, - IDC_CHECK_FLAG_23, - IDC_CHECK_FLAG_24, - IDC_CHECK_FLAG_25, - IDC_CHECK_FLAG_26, - IDC_CHECK_FLAG_27, - IDC_CHECK_FLAG_28, - IDC_CHECK_FLAG_29, - IDC_CHECK_FLAG_30, - IDC_CHECK_FLAG_31 -}; - -map BG_FLAG_ID_IDX; - - -///////////////////////////////////////////////////////////////////////////// -// CDialogFlags dialog - - -CDialogFlags::CDialogFlags(UAudioMixer *mixer, CWnd* pParent /*=NULL*/) - : CDialog(CDialogFlags::IDD, pParent), - _Mixer(mixer) -{ - //{{AFX_DATA_INIT(CDialogFlags) - SampleSize = _T(""); - //}}AFX_DATA_INIT - - // load initial bitmap into control - PlayBitmap.LoadBitmap(IDB_BITMAP_PLAY); - StopBitmap.LoadBitmap(IDB_BITMAP_STOP); - EarBitmap.LoadBitmap(IDB_BITMAP_EAR); - EarMoveBitmap.LoadBitmap(IDB_BITMAP_MOVE_EAR); - - // init the flags. - - ScrollPos = 0; - - _Flags = mixer->getBackgroundFlags(); - for (uint i=0; i<32; ++i) - { -// _Flags.Flags[i] = false; - BG_FLAG_ID_IDX.insert(make_pair(BG_FLAG_ID[i], i)); -// BgControlId[i] = BG_FLAG_ID[i]; - } - -// mixer->setBackgroundFlags(_Flags); - -} - -void CDialogFlags::init(CSoundPlugin *plugin) -{ - _Plugin = plugin; - - BtnPlayStop.SetBitmap(PlayBitmap); - CheckMoveEar.SetBitmap(EarBitmap); - - // preset the state of the flags - const NLSOUND::UAudioMixer::TBackgroundFlags &flags = _Mixer->getBackgroundFlags(); - for (uint i =0; i(GetDlgItem(BG_FLAG_ID[i]))->SetCheck(flags.Flags[i] ? 1 : 0); - GetDlgItem(BG_FLAG_ID[i])->SetWindowText(_Mixer->getBackgroundFlagName(i).c_str()); - } - - - // init the Sound bank list - LVCOLUMN col; - col.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; - col.fmt = LVCFMT_LEFT; - col.cx = 140; - col.pszText = "bank names"; - col.cchTextMax = sizeof("bank names"); - _SbList.InsertColumn(0, &col); - - col.fmt = LVCFMT_RIGHT; - col.cx = 50; - col.pszText = "size"; - col.cchTextMax = sizeof("size"); - _SbList.InsertColumn(1, &col); - -} - - -void CDialogFlags::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CDialogFlags) - DDX_Control(pDX, IDC_SB_LIST, _SbList); - DDX_Control(pDX, IDC_CHECK_MOVE_EAR, CheckMoveEar); - DDX_Control(pDX, IDC_BUTTON_PLAY_STOP, BtnPlayStop); - DDX_Text(pDX, IDC_STATIC_SAMPLE_SIZE, SampleSize); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CDialogFlags, CDialog) - //{{AFX_MSG_MAP(CDialogFlags) - ON_BN_CLICKED(IDC_BUTTON_PLAY_STOP, OnButtonPlayStop) - ON_BN_CLICKED(IDC_CHECK_MOVE_EAR, OnCheckMoveEar) - ON_WM_TIMER() - ON_WM_CREATE() - ON_WM_DESTROY() - ON_BN_CLICKED(IDC_RELOAD, OnReload) - ON_WM_CLOSE() - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - - - -void CDialogFlags::OnButtonPlayStop() -{ - static bool play = true; - - if (play) - { - _Plugin->play(); - play = false; - BtnPlayStop.SetBitmap(StopBitmap); -// SetTimer(1, 20, NULL); - } - else - { -// KillTimer(1); - _Plugin->stop(); - play = true; - BtnPlayStop.SetBitmap(PlayBitmap); - - } - -} - -void CDialogFlags::OnCheckMoveEar() -{ - if (CheckMoveEar.GetCheck() == 1) - { - _Plugin->startMoveEar(); - CheckMoveEar.SetBitmap(EarMoveBitmap); - } - else - { - _Plugin->stopMoveEar(); - CheckMoveEar.SetBitmap(EarBitmap); - } -} - -void CDialogFlags::lostPositionControl() -{ - CheckMoveEar.SetCheck(0); - CheckMoveEar.SetBitmap(EarBitmap); -} - -void CDialogFlags::OnTimer(UINT_PTR nIDEvent) -{ - CDialog::OnTimer(nIDEvent); - - _Plugin->update(); - std::string txt = _Plugin->getStatusString(); -// uint size = _Plugin->getLoadedSampleSize(); - - SampleSize = txt.c_str(); - - // loaded sample banks size info - _Plugin->getLoadedSampleBankInfo(SampleBanks); - - uint c, i; - c = _SbList.GetItemCount(); - for (i=0; i(GetDlgItem(id))->GetState() & (0x0003 != 0); - - _Mixer->setBackgroundFlags(_Flags); - } - - return CDialog::OnCommand(wParam, lParam); -} - -void CDialogFlags::OnReload() -{ - NLMISC::CVector pos(NLMISC::CVector::Null); - if (_Mixer) - { - pos = _Mixer->getListener()->getPos(); - } - - _Plugin->ReInit(); - _Mixer = _Plugin->getMixer(); - - if (_Mixer) - { - _Mixer->setBackgroundFlags(_Flags); - _Mixer->setListenerPos(pos); - } -} - -void CDialogFlags::OnClose() -{ - _Plugin->closePlugin(); - -} - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// DailogFlags.cpp : implementation file +// + +#include "stdafx.h" +#include "DialogFlags.h" +#include +#include "sound_plugin.h" +#include "nel/sound/u_listener.h" + + +using namespace std; +using namespace NLMISC; +using namespace NLSOUND; + +::CBitmap PlayBitmap; +::CBitmap StopBitmap; +::CBitmap EarBitmap; +::CBitmap EarMoveBitmap; + +uint BG_FLAG_ID[] = +{ + IDC_CHECK_FLAG_00, + IDC_CHECK_FLAG_01, + IDC_CHECK_FLAG_02, + IDC_CHECK_FLAG_03, + IDC_CHECK_FLAG_04, + IDC_CHECK_FLAG_05, + IDC_CHECK_FLAG_06, + IDC_CHECK_FLAG_07, + IDC_CHECK_FLAG_08, + IDC_CHECK_FLAG_09, + IDC_CHECK_FLAG_10, + IDC_CHECK_FLAG_11, + IDC_CHECK_FLAG_12, + IDC_CHECK_FLAG_13, + IDC_CHECK_FLAG_14, + IDC_CHECK_FLAG_15, + IDC_CHECK_FLAG_16, + IDC_CHECK_FLAG_17, + IDC_CHECK_FLAG_18, + IDC_CHECK_FLAG_19, + IDC_CHECK_FLAG_20, + IDC_CHECK_FLAG_21, + IDC_CHECK_FLAG_22, + IDC_CHECK_FLAG_23, + IDC_CHECK_FLAG_24, + IDC_CHECK_FLAG_25, + IDC_CHECK_FLAG_26, + IDC_CHECK_FLAG_27, + IDC_CHECK_FLAG_28, + IDC_CHECK_FLAG_29, + IDC_CHECK_FLAG_30, + IDC_CHECK_FLAG_31 +}; + +map BG_FLAG_ID_IDX; + + +///////////////////////////////////////////////////////////////////////////// +// CDialogFlags dialog + + +CDialogFlags::CDialogFlags(UAudioMixer *mixer, CWnd* pParent /*=NULL*/) + : CDialog(CDialogFlags::IDD, pParent), + _Mixer(mixer) +{ + //{{AFX_DATA_INIT(CDialogFlags) + SampleSize = _T(""); + //}}AFX_DATA_INIT + + // load initial bitmap into control + PlayBitmap.LoadBitmap(IDB_BITMAP_PLAY); + StopBitmap.LoadBitmap(IDB_BITMAP_STOP); + EarBitmap.LoadBitmap(IDB_BITMAP_EAR); + EarMoveBitmap.LoadBitmap(IDB_BITMAP_MOVE_EAR); + + // init the flags. + + ScrollPos = 0; + + _Flags = mixer->getBackgroundFlags(); + for (uint i=0; i<32; ++i) + { +// _Flags.Flags[i] = false; + BG_FLAG_ID_IDX.insert(make_pair(BG_FLAG_ID[i], i)); +// BgControlId[i] = BG_FLAG_ID[i]; + } + +// mixer->setBackgroundFlags(_Flags); + +} + +void CDialogFlags::init(CSoundPlugin *plugin) +{ + _Plugin = plugin; + + BtnPlayStop.SetBitmap(PlayBitmap); + CheckMoveEar.SetBitmap(EarBitmap); + + // preset the state of the flags + const NLSOUND::UAudioMixer::TBackgroundFlags &flags = _Mixer->getBackgroundFlags(); + for (uint i =0; i(GetDlgItem(BG_FLAG_ID[i]))->SetCheck(flags.Flags[i] ? 1 : 0); + GetDlgItem(BG_FLAG_ID[i])->SetWindowText(_Mixer->getBackgroundFlagName(i).c_str()); + } + + + // init the Sound bank list + LVCOLUMN col; + col.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT; + col.fmt = LVCFMT_LEFT; + col.cx = 140; + col.pszText = "bank names"; + col.cchTextMax = sizeof("bank names"); + _SbList.InsertColumn(0, &col); + + col.fmt = LVCFMT_RIGHT; + col.cx = 50; + col.pszText = "size"; + col.cchTextMax = sizeof("size"); + _SbList.InsertColumn(1, &col); + +} + + +void CDialogFlags::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CDialogFlags) + DDX_Control(pDX, IDC_SB_LIST, _SbList); + DDX_Control(pDX, IDC_CHECK_MOVE_EAR, CheckMoveEar); + DDX_Control(pDX, IDC_BUTTON_PLAY_STOP, BtnPlayStop); + DDX_Text(pDX, IDC_STATIC_SAMPLE_SIZE, SampleSize); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CDialogFlags, CDialog) + //{{AFX_MSG_MAP(CDialogFlags) + ON_BN_CLICKED(IDC_BUTTON_PLAY_STOP, OnButtonPlayStop) + ON_BN_CLICKED(IDC_CHECK_MOVE_EAR, OnCheckMoveEar) + ON_WM_TIMER() + ON_WM_CREATE() + ON_WM_DESTROY() + ON_BN_CLICKED(IDC_RELOAD, OnReload) + ON_WM_CLOSE() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + + +void CDialogFlags::OnButtonPlayStop() +{ + static bool play = true; + + if (play) + { + _Plugin->play(); + play = false; + BtnPlayStop.SetBitmap(StopBitmap); +// SetTimer(1, 20, NULL); + } + else + { +// KillTimer(1); + _Plugin->stop(); + play = true; + BtnPlayStop.SetBitmap(PlayBitmap); + + } + +} + +void CDialogFlags::OnCheckMoveEar() +{ + if (CheckMoveEar.GetCheck() == 1) + { + _Plugin->startMoveEar(); + CheckMoveEar.SetBitmap(EarMoveBitmap); + } + else + { + _Plugin->stopMoveEar(); + CheckMoveEar.SetBitmap(EarBitmap); + } +} + +void CDialogFlags::lostPositionControl() +{ + CheckMoveEar.SetCheck(0); + CheckMoveEar.SetBitmap(EarBitmap); +} + +void CDialogFlags::OnTimer(UINT_PTR nIDEvent) +{ + CDialog::OnTimer(nIDEvent); + + _Plugin->update(); + std::string txt = _Plugin->getStatusString(); +// uint size = _Plugin->getLoadedSampleSize(); + + SampleSize = txt.c_str(); + + // loaded sample banks size info + _Plugin->getLoadedSampleBankInfo(SampleBanks); + + uint c, i; + c = _SbList.GetItemCount(); + for (i=0; i(GetDlgItem(id))->GetState() & (0x0003 != 0); + + _Mixer->setBackgroundFlags(_Flags); + } + + return CDialog::OnCommand(wParam, lParam); +} + +void CDialogFlags::OnReload() +{ + NLMISC::CVector pos(NLMISC::CVector::Null); + if (_Mixer) + { + pos = _Mixer->getListener()->getPos(); + } + + _Plugin->ReInit(); + _Mixer = _Plugin->getMixer(); + + if (_Mixer) + { + _Mixer->setBackgroundFlags(_Flags); + _Mixer->setListenerPos(pos); + } +} + +void CDialogFlags::OnClose() +{ + _Plugin->closePlugin(); + +} + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/DialogFlags.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/DialogFlags.h index e2105bf64..ebba5891f 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/DialogFlags.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/DialogFlags.h @@ -1,98 +1,98 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_) -#define AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// DailogFlags.h : header file -// - -#include "stdafx.h" -#include "resource.h" -#include "nel/sound/u_audio_mixer.h" - - -class CSoundPlugin; - -///////////////////////////////////////////////////////////////////////////// -// CDialogFlags dialog - -class CDialogFlags : public CDialog -{ -// Construction -public: - CDialogFlags(NLSOUND::UAudioMixer *mixer, CWnd* pParent = NULL); // standard constructor - - void init(CSoundPlugin *plugin); - void lostPositionControl(); - - void setMixer(NLSOUND::UAudioMixer *mixer) { _Mixer = mixer;} - -// uint BgControlId[32]; - - std::vector > SampleBanks; - - uint ScrollPos; - - -// Dialog Data - //{{AFX_DATA(CDialogFlags) - enum { IDD = IDD_DIALOG_FLAGS }; - CListCtrl _SbList; - CButton CheckMoveEar; - CButton BtnPlayStop; - CString SampleSize; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CDialogFlags) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); - //}}AFX_VIRTUAL - - -// Implementation - afx_msg void OnClose(); -protected: - - - CSoundPlugin *_Plugin; - NLSOUND::UAudioMixer *_Mixer; - NLSOUND::UAudioMixer::TBackgroundFlags _Flags; - - // Generated message map functions - //{{AFX_MSG(CDialogFlags) - afx_msg void OnButtonPlayStop(); - afx_msg void OnCheckMoveEar(); - afx_msg void OnTimer(UINT_PTR nIDEvent); - afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); - afx_msg void OnDestroy(); - afx_msg void OnReload(); - - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_) +#define AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// DailogFlags.h : header file +// + +#include "stdafx.h" +#include "resource.h" +#include "nel/sound/u_audio_mixer.h" + + +class CSoundPlugin; + +///////////////////////////////////////////////////////////////////////////// +// CDialogFlags dialog + +class CDialogFlags : public CDialog +{ +// Construction +public: + CDialogFlags(NLSOUND::UAudioMixer *mixer, CWnd* pParent = NULL); // standard constructor + + void init(CSoundPlugin *plugin); + void lostPositionControl(); + + void setMixer(NLSOUND::UAudioMixer *mixer) { _Mixer = mixer;} + +// uint BgControlId[32]; + + std::vector > SampleBanks; + + uint ScrollPos; + + +// Dialog Data + //{{AFX_DATA(CDialogFlags) + enum { IDD = IDD_DIALOG_FLAGS }; + CListCtrl _SbList; + CButton CheckMoveEar; + CButton BtnPlayStop; + CString SampleSize; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CDialogFlags) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + virtual BOOL OnCommand(WPARAM wParam, LPARAM lParam); + //}}AFX_VIRTUAL + + +// Implementation + afx_msg void OnClose(); +protected: + + + CSoundPlugin *_Plugin; + NLSOUND::UAudioMixer *_Mixer; + NLSOUND::UAudioMixer::TBackgroundFlags _Flags; + + // Generated message map functions + //{{AFX_MSG(CDialogFlags) + afx_msg void OnButtonPlayStop(); + afx_msg void OnCheckMoveEar(); + afx_msg void OnTimer(UINT_PTR nIDEvent); + afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); + afx_msg void OnDestroy(); + afx_msg void OnReload(); + + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_DAILOGFLAGS_H__0D9E26EE_5A7F_4CFA_AED0_4470B8F0E3EC__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/LoadDialog.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/LoadDialog.cpp index 90a033733..0da73baca 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/LoadDialog.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/LoadDialog.cpp @@ -1,53 +1,53 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// LoadDialog.cpp : implementation file -// - -#include "stdafx.h" -#include "resource.h" -#include "LoadDialog.h" - -///////////////////////////////////////////////////////////////////////////// -// CLoadDialog dialog - - -CLoadDialog::CLoadDialog(CWnd* pParent /*=NULL*/) - : CDialog(CLoadDialog::IDD, pParent) -{ - //{{AFX_DATA_INIT(CLoadDialog) - Message = _T(""); - //}}AFX_DATA_INIT -} - - -void CLoadDialog::DoDataExchange(CDataExchange* pDX) -{ - CDialog::DoDataExchange(pDX); - //{{AFX_DATA_MAP(CLoadDialog) - DDX_Text(pDX, IDC_STATIC_MESSAGE, Message); - //}}AFX_DATA_MAP -} - - -BEGIN_MESSAGE_MAP(CLoadDialog, CDialog) - //{{AFX_MSG_MAP(CLoadDialog) - // NOTE: the ClassWizard will add message map macros here - //}}AFX_MSG_MAP -END_MESSAGE_MAP() - -///////////////////////////////////////////////////////////////////////////// -// CLoadDialog message handlers +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// LoadDialog.cpp : implementation file +// + +#include "stdafx.h" +#include "resource.h" +#include "LoadDialog.h" + +///////////////////////////////////////////////////////////////////////////// +// CLoadDialog dialog + + +CLoadDialog::CLoadDialog(CWnd* pParent /*=NULL*/) + : CDialog(CLoadDialog::IDD, pParent) +{ + //{{AFX_DATA_INIT(CLoadDialog) + Message = _T(""); + //}}AFX_DATA_INIT +} + + +void CLoadDialog::DoDataExchange(CDataExchange* pDX) +{ + CDialog::DoDataExchange(pDX); + //{{AFX_DATA_MAP(CLoadDialog) + DDX_Text(pDX, IDC_STATIC_MESSAGE, Message); + //}}AFX_DATA_MAP +} + + +BEGIN_MESSAGE_MAP(CLoadDialog, CDialog) + //{{AFX_MSG_MAP(CLoadDialog) + // NOTE: the ClassWizard will add message map macros here + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + +///////////////////////////////////////////////////////////////////////////// +// CLoadDialog message handlers diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/LoadDialog.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/LoadDialog.h index 0eee7b149..2f90fd23e 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/LoadDialog.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/LoadDialog.h @@ -1,62 +1,62 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if !defined(AFX_LOADDIALOG_H__3F11071D_1F55_433E_964D_E953168443AC__INCLUDED_) -#define AFX_LOADDIALOG_H__3F11071D_1F55_433E_964D_E953168443AC__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 -// LoadDialog.h : header file -// - -///////////////////////////////////////////////////////////////////////////// -// CLoadDialog dialog - -class CLoadDialog : public CDialog -{ -// Construction -public: - CLoadDialog(CWnd* pParent = NULL); // standard constructor - -// Dialog Data - //{{AFX_DATA(CLoadDialog) - enum { IDD = IDD_DIALOG_LOAD }; - CString Message; - //}}AFX_DATA - - -// Overrides - // ClassWizard generated virtual function overrides - //{{AFX_VIRTUAL(CLoadDialog) - protected: - virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support - //}}AFX_VIRTUAL - -// Implementation -protected: - - // Generated message map functions - //{{AFX_MSG(CLoadDialog) - // NOTE: the ClassWizard will add member functions here - //}}AFX_MSG - DECLARE_MESSAGE_MAP() -}; - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_LOADDIALOG_H__3F11071D_1F55_433E_964D_E953168443AC__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if !defined(AFX_LOADDIALOG_H__3F11071D_1F55_433E_964D_E953168443AC__INCLUDED_) +#define AFX_LOADDIALOG_H__3F11071D_1F55_433E_964D_E953168443AC__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 +// LoadDialog.h : header file +// + +///////////////////////////////////////////////////////////////////////////// +// CLoadDialog dialog + +class CLoadDialog : public CDialog +{ +// Construction +public: + CLoadDialog(CWnd* pParent = NULL); // standard constructor + +// Dialog Data + //{{AFX_DATA(CLoadDialog) + enum { IDD = IDD_DIALOG_LOAD }; + CString Message; + //}}AFX_DATA + + +// Overrides + // ClassWizard generated virtual function overrides + //{{AFX_VIRTUAL(CLoadDialog) + protected: + virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support + //}}AFX_VIRTUAL + +// Implementation +protected: + + // Generated message map functions + //{{AFX_MSG(CLoadDialog) + // NOTE: the ClassWizard will add member functions here + //}}AFX_MSG + DECLARE_MESSAGE_MAP() +}; + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_LOADDIALOG_H__3F11071D_1F55_433E_964D_E953168443AC__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/StdAfx.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/StdAfx.cpp index 6c7418ceb..e11d5ecc5 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/StdAfx.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/StdAfx.cpp @@ -1,24 +1,24 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.cpp : source file that includes just the standard includes -// WorldEditor.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.cpp : source file that includes just the standard includes +// WorldEditor.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + + + diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/StdAfx.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/StdAfx.h index 9b9b77693..23a0b70ad 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/StdAfx.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/StdAfx.h @@ -1,53 +1,53 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_) -#define AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_ - -#pragma warning(disable : 4786) - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - -#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers -#define NOMINMAX -#define _WIN32_WINNT 0x0500 - -#include // MFC core and standard components -#include // MFC extensions -#include // MFC Automation classes -#include // MFC support for Internet Explorer 4 Common Controls -#ifndef _AFX_NO_AFXCMN_SUPPORT -#include // MFC support for Windows Common Controls -#endif // _AFX_NO_AFXCMN_SUPPORT - -#include - -#include - -#include -#include - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_) +#define AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_ + +#pragma warning(disable : 4786) + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + +#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers +#define NOMINMAX +#define _WIN32_WINNT 0x0500 + +#include // MFC core and standard components +#include // MFC extensions +#include // MFC Automation classes +#include // MFC support for Internet Explorer 4 Common Controls +#ifndef _AFX_NO_AFXCMN_SUPPORT +#include // MFC support for Windows Common Controls +#endif // _AFX_NO_AFXCMN_SUPPORT + +#include + +#include + +#include +#include + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__C8D89813_A2BC_40F5_B924_C2480C2AFBA9__INCLUDED_) diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/resource.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/resource.h index f1f0c9bc6..165a2ce68 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/resource.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/resource.h @@ -1,81 +1,81 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by worldeditor_sound_plugin.rc -// -#define IDR_TOOLBAR1 101 -#define IDR_TOOLBAR_SOUND 101 -#define IDB_BITMAP_STOP 103 -#define IDD_DIALOG_FLAGS 104 -#define IDB_BITMAP_PLAY 105 -#define IDB_BITMAP_EAR 106 -#define IDB_BITMAP_MOVE_EAR 107 -#define IDD_DIALOG_LOAD 108 -#define IDC_CHECK_FLAG_00 1000 -#define IDC_CHECK_FLAG_01 1001 -#define IDC_CHECK_FLAG_02 1002 -#define IDC_CHECK_FLAG_03 1003 -#define IDC_CHECK_FLAG_04 1004 -#define IDC_CHECK_FLAG_05 1005 -#define IDC_CHECK_FLAG_06 1006 -#define IDC_CHECK_FLAG_07 1007 -#define IDC_CHECK_FLAG_08 1008 -#define IDC_CHECK_FLAG_09 1009 -#define IDC_CHECK_FLAG_10 1010 -#define IDC_CHECK_FLAG_11 1011 -#define IDC_CHECK_FLAG_12 1012 -#define IDC_CHECK_FLAG_13 1013 -#define IDC_CHECK_FLAG_14 1014 -#define IDC_CHECK_FLAG_15 1015 -#define IDC_BUTTON_PLAY_STOP 1016 -#define IDC_CHECK_MOVE_EAR 1018 -#define IDC_STATIC_MESSAGE 1019 -#define IDC_CHECK_FLAG_16 1019 -#define IDC_STATIC_SAMPLE_SIZE 1020 -#define IDC_CHECK_FLAG_17 1021 -#define IDC_CHECK_FLAG_18 1022 -#define IDC_CHECK_FLAG_19 1023 -#define IDC_CHECK_FLAG_20 1024 -#define IDC_CHECK_FLAG_21 1025 -#define IDC_CHECK_FLAG_22 1026 -#define IDC_CHECK_FLAG_23 1027 -#define IDC_CHECK_FLAG_24 1028 -#define IDC_CHECK_FLAG_25 1029 -#define IDC_CHECK_FLAG_26 1030 -#define IDC_CHECK_FLAG_27 1031 -#define IDC_CHECK_FLAG_28 1032 -#define IDC_CHECK_FLAG_29 1033 -#define IDC_CHECK_FLAG_30 1034 -#define IDC_CHECK_FLAG_31 1035 -#define IDC_SCROLLBAR_SB 1037 -#define IDC_SB_LIST 1059 -#define IDC_RELOAD 1060 -#define ID_BUTTON40001 40001 -#define ID_BUTTON40002 40002 -#define ID_BUTTON40003 40003 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 109 -#define _APS_NEXT_COMMAND_VALUE 40004 -#define _APS_NEXT_CONTROL_VALUE 1061 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by worldeditor_sound_plugin.rc +// +#define IDR_TOOLBAR1 101 +#define IDR_TOOLBAR_SOUND 101 +#define IDB_BITMAP_STOP 103 +#define IDD_DIALOG_FLAGS 104 +#define IDB_BITMAP_PLAY 105 +#define IDB_BITMAP_EAR 106 +#define IDB_BITMAP_MOVE_EAR 107 +#define IDD_DIALOG_LOAD 108 +#define IDC_CHECK_FLAG_00 1000 +#define IDC_CHECK_FLAG_01 1001 +#define IDC_CHECK_FLAG_02 1002 +#define IDC_CHECK_FLAG_03 1003 +#define IDC_CHECK_FLAG_04 1004 +#define IDC_CHECK_FLAG_05 1005 +#define IDC_CHECK_FLAG_06 1006 +#define IDC_CHECK_FLAG_07 1007 +#define IDC_CHECK_FLAG_08 1008 +#define IDC_CHECK_FLAG_09 1009 +#define IDC_CHECK_FLAG_10 1010 +#define IDC_CHECK_FLAG_11 1011 +#define IDC_CHECK_FLAG_12 1012 +#define IDC_CHECK_FLAG_13 1013 +#define IDC_CHECK_FLAG_14 1014 +#define IDC_CHECK_FLAG_15 1015 +#define IDC_BUTTON_PLAY_STOP 1016 +#define IDC_CHECK_MOVE_EAR 1018 +#define IDC_STATIC_MESSAGE 1019 +#define IDC_CHECK_FLAG_16 1019 +#define IDC_STATIC_SAMPLE_SIZE 1020 +#define IDC_CHECK_FLAG_17 1021 +#define IDC_CHECK_FLAG_18 1022 +#define IDC_CHECK_FLAG_19 1023 +#define IDC_CHECK_FLAG_20 1024 +#define IDC_CHECK_FLAG_21 1025 +#define IDC_CHECK_FLAG_22 1026 +#define IDC_CHECK_FLAG_23 1027 +#define IDC_CHECK_FLAG_24 1028 +#define IDC_CHECK_FLAG_25 1029 +#define IDC_CHECK_FLAG_26 1030 +#define IDC_CHECK_FLAG_27 1031 +#define IDC_CHECK_FLAG_28 1032 +#define IDC_CHECK_FLAG_29 1033 +#define IDC_CHECK_FLAG_30 1034 +#define IDC_CHECK_FLAG_31 1035 +#define IDC_SCROLLBAR_SB 1037 +#define IDC_SB_LIST 1059 +#define IDC_RELOAD 1060 +#define ID_BUTTON40001 40001 +#define ID_BUTTON40002 40002 +#define ID_BUTTON40003 40003 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 109 +#define _APS_NEXT_COMMAND_VALUE 40004 +#define _APS_NEXT_CONTROL_VALUE 1061 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/sound_plugin.cpp b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/sound_plugin.cpp index 8d1dd968e..45e93d731 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/sound_plugin.cpp +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/sound_plugin.cpp @@ -1,406 +1,406 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdafx.h" -#include "sound_plugin.h" -#include "resource.h" -#include "nel/misc/path.h" -#include "LoadDialog.h" -#include "nel/sound/u_listener.h" - -using namespace NLMISC; -using namespace NLLIGO; -using namespace NLSOUND; -using namespace std; - -CFileDisplayer *SoundPluginLogDisplayer= NULL; - -// vl: important to add the next line or AfxGetApp() will returns 0 after AFX_MANAGE_STATE(AfxGetStaticModuleState()); -CWinApp theApp; - -extern "C" -{ - //void *createSoundPlugin() - void *createPlugin() - { - return new CSoundPlugin(); - } -} - -CSoundPlugin::CSoundPlugin() - : _PluginAccess(0), - _ListenerPos(0,0,0), - LoadDlg(0), - _BackgroundSoundPlayed(false), - _Mixer(NULL) - -{ - NLMISC::createDebug(); - SoundPluginLogDisplayer= new CFileDisplayer("world_editor_sound_plugin.log", true, "WORLD_EDITOR_SOUND_PLUGIN.LOG"); - DebugLog->addDisplayer (SoundPluginLogDisplayer); - InfoLog->addDisplayer (SoundPluginLogDisplayer); - WarningLog->addDisplayer (SoundPluginLogDisplayer); - ErrorLog->addDisplayer (SoundPluginLogDisplayer); - AssertLog->addDisplayer (SoundPluginLogDisplayer); - - nlinfo("Starting sound plugin..."); - -} - - -CSoundPlugin::~CSoundPlugin() -{ -} - -void CSoundPlugin::progress (float progressValue) -{ - char tmp[1024]; - sprintf(tmp, "Initializing mixer : %i%%", int(progressValue * 100)); - LoadDlg->Message = tmp; - LoadDlg->UpdateData(FALSE); - LoadDlg->RedrawWindow(); -} - - -void CSoundPlugin::init(IPluginAccess *pluginAccess) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - AfxEnableControlContainer(); - _PluginAccess = pluginAccess; - _PluginName="Sound Plugin"; - - LoadDlg = new CLoadDialog; - LoadDlg->Create(IDD_DIALOG_LOAD); - LoadDlg->Message = "Initializing mixer"; - LoadDlg->UpdateData(FALSE); - LoadDlg->ShowWindow(SW_SHOW); - LoadDlg->RedrawWindow(); - -// std::string path = "r:/code/ryzom/data/sound"; -// NLMISC::CPath::addSearchPath(path, true, false); - - LoadDlg->Message = "Adding search path"; - LoadDlg->UpdateData(FALSE); - LoadDlg->Invalidate(); - - CConfigFile &cf = pluginAccess->getConfigFile(); - // Add the search path - try - { - CConfigFile::CVar *psearchPath = cf.getVarPtr("SearchPath"); - for (uint i=0; isize(); ++i) - { - std::string path = psearchPath->asString(i); - LoadDlg->Message = (std::string("Adding search path \"")+path+"\"").c_str(); - LoadDlg->UpdateData(FALSE); - LoadDlg->RedrawWindow(); - NLMISC::CPath::addSearchPath(path, true, false); - } - } - catch(...) - { - nlwarning("Error while setting search path"); - } - delete LoadDlg; - LoadDlg = 0; - - ReInit(); - - _DialogFlag = new CDialogFlags(_Mixer); - // open the dialog flag window - _DialogFlag->Create(IDD_DIALOG_FLAGS, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); - _DialogFlag->init(this); - - _DialogFlag->ShowWindow(TRUE); - - _Mixer->getListener()->setOrientation(CVector(0,1,0), CVector(0,0,1)); - - _PluginActive=true; -} - -void CSoundPlugin::ReInit() -{ - CConfigFile &cf = _PluginAccess->getConfigFile(); - std::string packedSheetPath; - CConfigFile::CVar *ppackedSheetPath = cf.getVarPtr("PackedSheetPath"); - packedSheetPath = ppackedSheetPath->asString(); - - LoadDlg = new CLoadDialog; - LoadDlg->Create(IDD_DIALOG_LOAD); - LoadDlg->Message = "Initializing Audio Mixer"; - LoadDlg->UpdateData(FALSE); - LoadDlg->ShowWindow(SW_SHOW); - LoadDlg->RedrawWindow(); - - // If it's a true reinit, must reload primitives - bool mustReloadPrimitives= false; - if (_Mixer != NULL) - { - mustReloadPrimitives= true; - delete _Mixer; - _Mixer = NULL; - } - - // get maxtrack - int maxTrack; - try - { - maxTrack = cf.getVar("MaxTrack").asInt(); - } - catch(...) - { - maxTrack = 32; - } - - // get DriverMod - bool fmodDriver = false; - try - { - fmodDriver = toLower(cf.getVar("DriverSound").asString())=="fmod"; - } - catch(...) - { - fmodDriver = false; - } - - // create the audio mixer. - _Mixer = UAudioMixer::createAudioMixer(); - _Mixer->setSamplePath(cf.getVar("SamplePath").asString()); - _Mixer->setPackedSheetOption(packedSheetPath, true); - try - { - if(fmodDriver) - { - // init FMod, software, no eax - _Mixer->init(maxTrack, false, false, this, false, UAudioMixer::DriverFMod, true); - } - else - { - // init DSound, hardware, eax - _Mixer->init(maxTrack, true, false, this, false, UAudioMixer::DriverAuto, false); - } - } - catch(...) - { - MessageBox(NULL, "Error while initializing audio mixer.\n", "ERROR", MB_ICONERROR); - exit(1); - } - - // Force reinit of all the primitives if reload - if(mustReloadPrimitives) - { - std::vector prims; - _PluginAccess->getAllRootPluginPrimitive(prims); - for(uint i=0;iplayBackgroundSound(); - } - - - delete LoadDlg; - LoadDlg = 0; - - // remove flood of config file reparsing - DebugLog->addNegativeFilter("Adding config file"); -} - -/// The current region has changed. -//void CSoundPlugin::primRegionChanged(const std::vector ®ions) -void CSoundPlugin::primitiveChanged(const NLLIGO::IPrimitive *root) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - // load the first region of each kind : audio, effect and sample. - bool audio = false; - bool effects = false; - bool samples = false; - - _Mixer->loadBackgroundAudioFromPrimitives(*root); - -/* std::vector::const_iterator first(regions.begin()), last(regions.end()); - for (; first != last; ++first) - { - if ((*first)->Name.find("_audio") != std::string::npos && !audio) - { - _Mixer->loadBackgroundSoundFromRegion(*(*first)); - audio = true; - } - else if ((*first)->Name.find("_effects") != std::string::npos && !effects) - { - _Mixer->loadBackgroundEffectsFromRegion(*(*first)); - effects = true; - } - else if ((*first)->Name.find("_samples") != std::string::npos && !samples) - { - _Mixer->loadBackgroundSamplesFromRegion(*(*first)); - samples = true; - } - } -*/ -} -/// The region has been modifed. -/*void CSoundPlugin::primRegionModifed() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); -} -*/ -/// The listener has been moved on the map. -void CSoundPlugin::positionMoved(const NLMISC::CVector &position) -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - _ListenerPos = position; - - _Mixer->setListenerPos(_ListenerPos); -} - -void CSoundPlugin::lostPositionControl() -{ - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - - // update the dialog box. - _DialogFlag->lostPositionControl(); - -} - - -void CSoundPlugin::play() -{ - // set the user var present in the config file - CConfigFile &cfg = _PluginAccess->getConfigFile(); - try - { - cfg.reparse(); - CConfigFile::CVar v = cfg.getVar("UserVarSim"); - for (uint i=0; isetUserVar(CStringMapper::map(varName), value); - } - } - catch(...) - { - } - - _Mixer->playBackgroundSound(); - _BackgroundSoundPlayed= true; -} -void CSoundPlugin::stop() -{ - _Mixer->stopBackgroundSound(); - _BackgroundSoundPlayed= false; -} -void CSoundPlugin::startMoveEar() -{ - _PluginAccess->startPositionControl(this, _ListenerPos); -} -void CSoundPlugin::stopMoveEar() -{ - _PluginAccess->stopPositionControl(this); -} - -void CSoundPlugin::update() -{ - // set the user var present in the config file - CConfigFile &cfg = _PluginAccess->getConfigFile(); - try - { - cfg.reparse(); - CConfigFile::CVar v = cfg.getVar("UserVarSim"); - for (uint i=0; isetUserVar(CStringMapper::map(varName), value); - } - } - catch(...) - { - } - - const NLSOUND::UAudioMixer::TBackgroundFlags &flags = _Mixer->getBackgroundFlags();; - _Mixer->update(); -} - - -std::string CSoundPlugin::getStatusString() -{ - char tmp[1024]; - sprintf(tmp, "Sample mem : %7.3f Mo\nTrks/Mut/Ply/Inst : %2u/%2u/%2u/%2u", - _Mixer->getLoadedSampleSize()/(1024.0f*1024.0f), - _Mixer->getUsedTracksCount(), - _Mixer->getMutedPlayingSourcesCount(), - _Mixer->getPlayingSourcesCount(), - _Mixer->getSourcesInstanceCount() - ); - - return std::string(tmp); -} - -void CSoundPlugin::getLoadedSampleBankInfo(std::vector > &result) -{ - _Mixer->getLoadedSampleBankInfo(result); -} - -void CSoundPlugin::onIdle() -{ -} - -bool CSoundPlugin::isActive() -{ - return _PluginActive; -} - -string& CSoundPlugin::getName() -{ - return _PluginName; -} - -bool CSoundPlugin::activatePlugin() -{ - if(!_PluginActive) - { - AFX_MANAGE_STATE(AfxGetStaticModuleState()); - AfxEnableControlContainer(); - - //_DialogFlag->Create(IDD_DIALOG_FLAGS, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); - _DialogFlag->ShowWindow(TRUE); - //_DialogFlag->init(this); - _PluginActive=true; - return true; - } - return false; -} - -bool CSoundPlugin::closePlugin() -{ - if (_PluginActive) - { - //_DialogFlag->CloseWindow(); - _DialogFlag->ShowWindow(FALSE); - _PluginActive=false; - return true; - } - return false; +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdafx.h" +#include "sound_plugin.h" +#include "resource.h" +#include "nel/misc/path.h" +#include "LoadDialog.h" +#include "nel/sound/u_listener.h" + +using namespace NLMISC; +using namespace NLLIGO; +using namespace NLSOUND; +using namespace std; + +CFileDisplayer *SoundPluginLogDisplayer= NULL; + +// vl: important to add the next line or AfxGetApp() will returns 0 after AFX_MANAGE_STATE(AfxGetStaticModuleState()); +CWinApp theApp; + +extern "C" +{ + //void *createSoundPlugin() + void *createPlugin() + { + return new CSoundPlugin(); + } +} + +CSoundPlugin::CSoundPlugin() + : _PluginAccess(0), + _ListenerPos(0,0,0), + LoadDlg(0), + _BackgroundSoundPlayed(false), + _Mixer(NULL) + +{ + NLMISC::createDebug(); + SoundPluginLogDisplayer= new CFileDisplayer("world_editor_sound_plugin.log", true, "WORLD_EDITOR_SOUND_PLUGIN.LOG"); + DebugLog->addDisplayer (SoundPluginLogDisplayer); + InfoLog->addDisplayer (SoundPluginLogDisplayer); + WarningLog->addDisplayer (SoundPluginLogDisplayer); + ErrorLog->addDisplayer (SoundPluginLogDisplayer); + AssertLog->addDisplayer (SoundPluginLogDisplayer); + + nlinfo("Starting sound plugin..."); + +} + + +CSoundPlugin::~CSoundPlugin() +{ +} + +void CSoundPlugin::progress (float progressValue) +{ + char tmp[1024]; + sprintf(tmp, "Initializing mixer : %i%%", int(progressValue * 100)); + LoadDlg->Message = tmp; + LoadDlg->UpdateData(FALSE); + LoadDlg->RedrawWindow(); +} + + +void CSoundPlugin::init(IPluginAccess *pluginAccess) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + AfxEnableControlContainer(); + _PluginAccess = pluginAccess; + _PluginName="Sound Plugin"; + + LoadDlg = new CLoadDialog; + LoadDlg->Create(IDD_DIALOG_LOAD); + LoadDlg->Message = "Initializing mixer"; + LoadDlg->UpdateData(FALSE); + LoadDlg->ShowWindow(SW_SHOW); + LoadDlg->RedrawWindow(); + +// std::string path = "r:/code/ryzom/data/sound"; +// NLMISC::CPath::addSearchPath(path, true, false); + + LoadDlg->Message = "Adding search path"; + LoadDlg->UpdateData(FALSE); + LoadDlg->Invalidate(); + + CConfigFile &cf = pluginAccess->getConfigFile(); + // Add the search path + try + { + CConfigFile::CVar *psearchPath = cf.getVarPtr("SearchPath"); + for (uint i=0; isize(); ++i) + { + std::string path = psearchPath->asString(i); + LoadDlg->Message = (std::string("Adding search path \"")+path+"\"").c_str(); + LoadDlg->UpdateData(FALSE); + LoadDlg->RedrawWindow(); + NLMISC::CPath::addSearchPath(path, true, false); + } + } + catch(...) + { + nlwarning("Error while setting search path"); + } + delete LoadDlg; + LoadDlg = 0; + + ReInit(); + + _DialogFlag = new CDialogFlags(_Mixer); + // open the dialog flag window + _DialogFlag->Create(IDD_DIALOG_FLAGS, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); + _DialogFlag->init(this); + + _DialogFlag->ShowWindow(TRUE); + + _Mixer->getListener()->setOrientation(CVector(0,1,0), CVector(0,0,1)); + + _PluginActive=true; +} + +void CSoundPlugin::ReInit() +{ + CConfigFile &cf = _PluginAccess->getConfigFile(); + std::string packedSheetPath; + CConfigFile::CVar *ppackedSheetPath = cf.getVarPtr("PackedSheetPath"); + packedSheetPath = ppackedSheetPath->asString(); + + LoadDlg = new CLoadDialog; + LoadDlg->Create(IDD_DIALOG_LOAD); + LoadDlg->Message = "Initializing Audio Mixer"; + LoadDlg->UpdateData(FALSE); + LoadDlg->ShowWindow(SW_SHOW); + LoadDlg->RedrawWindow(); + + // If it's a true reinit, must reload primitives + bool mustReloadPrimitives= false; + if (_Mixer != NULL) + { + mustReloadPrimitives= true; + delete _Mixer; + _Mixer = NULL; + } + + // get maxtrack + int maxTrack; + try + { + maxTrack = cf.getVar("MaxTrack").asInt(); + } + catch(...) + { + maxTrack = 32; + } + + // get DriverMod + bool fmodDriver = false; + try + { + fmodDriver = toLower(cf.getVar("DriverSound").asString())=="fmod"; + } + catch(...) + { + fmodDriver = false; + } + + // create the audio mixer. + _Mixer = UAudioMixer::createAudioMixer(); + _Mixer->setSamplePath(cf.getVar("SamplePath").asString()); + _Mixer->setPackedSheetOption(packedSheetPath, true); + try + { + if(fmodDriver) + { + // init FMod, software, no eax + _Mixer->init(maxTrack, false, false, this, false, UAudioMixer::DriverFMod, true); + } + else + { + // init DSound, hardware, eax + _Mixer->init(maxTrack, true, false, this, false, UAudioMixer::DriverAuto, false); + } + } + catch(...) + { + MessageBox(NULL, "Error while initializing audio mixer.\n", "ERROR", MB_ICONERROR); + exit(1); + } + + // Force reinit of all the primitives if reload + if(mustReloadPrimitives) + { + std::vector prims; + _PluginAccess->getAllRootPluginPrimitive(prims); + for(uint i=0;iplayBackgroundSound(); + } + + + delete LoadDlg; + LoadDlg = 0; + + // remove flood of config file reparsing + DebugLog->addNegativeFilter("Adding config file"); +} + +/// The current region has changed. +//void CSoundPlugin::primRegionChanged(const std::vector ®ions) +void CSoundPlugin::primitiveChanged(const NLLIGO::IPrimitive *root) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + // load the first region of each kind : audio, effect and sample. + bool audio = false; + bool effects = false; + bool samples = false; + + _Mixer->loadBackgroundAudioFromPrimitives(*root); + +/* std::vector::const_iterator first(regions.begin()), last(regions.end()); + for (; first != last; ++first) + { + if ((*first)->Name.find("_audio") != std::string::npos && !audio) + { + _Mixer->loadBackgroundSoundFromRegion(*(*first)); + audio = true; + } + else if ((*first)->Name.find("_effects") != std::string::npos && !effects) + { + _Mixer->loadBackgroundEffectsFromRegion(*(*first)); + effects = true; + } + else if ((*first)->Name.find("_samples") != std::string::npos && !samples) + { + _Mixer->loadBackgroundSamplesFromRegion(*(*first)); + samples = true; + } + } +*/ +} +/// The region has been modifed. +/*void CSoundPlugin::primRegionModifed() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); +} +*/ +/// The listener has been moved on the map. +void CSoundPlugin::positionMoved(const NLMISC::CVector &position) +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + _ListenerPos = position; + + _Mixer->setListenerPos(_ListenerPos); +} + +void CSoundPlugin::lostPositionControl() +{ + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + + // update the dialog box. + _DialogFlag->lostPositionControl(); + +} + + +void CSoundPlugin::play() +{ + // set the user var present in the config file + CConfigFile &cfg = _PluginAccess->getConfigFile(); + try + { + cfg.reparse(); + CConfigFile::CVar v = cfg.getVar("UserVarSim"); + for (uint i=0; isetUserVar(CStringMapper::map(varName), value); + } + } + catch(...) + { + } + + _Mixer->playBackgroundSound(); + _BackgroundSoundPlayed= true; +} +void CSoundPlugin::stop() +{ + _Mixer->stopBackgroundSound(); + _BackgroundSoundPlayed= false; +} +void CSoundPlugin::startMoveEar() +{ + _PluginAccess->startPositionControl(this, _ListenerPos); +} +void CSoundPlugin::stopMoveEar() +{ + _PluginAccess->stopPositionControl(this); +} + +void CSoundPlugin::update() +{ + // set the user var present in the config file + CConfigFile &cfg = _PluginAccess->getConfigFile(); + try + { + cfg.reparse(); + CConfigFile::CVar v = cfg.getVar("UserVarSim"); + for (uint i=0; isetUserVar(CStringMapper::map(varName), value); + } + } + catch(...) + { + } + + const NLSOUND::UAudioMixer::TBackgroundFlags &flags = _Mixer->getBackgroundFlags();; + _Mixer->update(); +} + + +std::string CSoundPlugin::getStatusString() +{ + char tmp[1024]; + sprintf(tmp, "Sample mem : %7.3f Mo\nTrks/Mut/Ply/Inst : %2u/%2u/%2u/%2u", + _Mixer->getLoadedSampleSize()/(1024.0f*1024.0f), + _Mixer->getUsedTracksCount(), + _Mixer->getMutedPlayingSourcesCount(), + _Mixer->getPlayingSourcesCount(), + _Mixer->getSourcesInstanceCount() + ); + + return std::string(tmp); +} + +void CSoundPlugin::getLoadedSampleBankInfo(std::vector > &result) +{ + _Mixer->getLoadedSampleBankInfo(result); +} + +void CSoundPlugin::onIdle() +{ +} + +bool CSoundPlugin::isActive() +{ + return _PluginActive; +} + +string& CSoundPlugin::getName() +{ + return _PluginName; +} + +bool CSoundPlugin::activatePlugin() +{ + if(!_PluginActive) + { + AFX_MANAGE_STATE(AfxGetStaticModuleState()); + AfxEnableControlContainer(); + + //_DialogFlag->Create(IDD_DIALOG_FLAGS, CWnd::FromHandle(_PluginAccess->getMainWindow()->m_hWnd)); + _DialogFlag->ShowWindow(TRUE); + //_DialogFlag->init(this); + _PluginActive=true; + return true; + } + return false; +} + +bool CSoundPlugin::closePlugin() +{ + if (_PluginActive) + { + //_DialogFlag->CloseWindow(); + _DialogFlag->ShowWindow(FALSE); + _PluginActive=false; + return true; + } + return false; } \ No newline at end of file diff --git a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/sound_plugin.h b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/sound_plugin.h index 388ae4ada..400207cc7 100644 --- a/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/sound_plugin.h +++ b/code/ryzom/tools/leveldesign/world_editor/world_editor_sound_plugin/sound_plugin.h @@ -1,112 +1,112 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/sound/u_audio_mixer.h" -#include "nel/ligo/primitive.h" -#include "nel/misc/progress_callback.h" -#include "../world_editor/plugin_interface.h" -#include "DialogFlags.h" -#include "nel/sound/u_audio_mixer.h" -#include "LoadDialog.h" - - -class CSoundPlugin : public IPluginCallback, public NLMISC::IProgressCallback -{ -public: - /// Constructor - CSoundPlugin(); - /// Destructor - ~CSoundPlugin(); - - void play(); - void stop(); - void startMoveEar(); - void stopMoveEar(); - - void update(); -// uint getLoadedSampleSize(); - - std::string getStatusString(); - - void getLoadedSampleBankInfo(std::vector > &result); - void ReInit(); - - NLSOUND::UAudioMixer *getMixer() { return _Mixer; }; - IPluginAccess *getPlugingAccess() { return _PluginAccess; }; - void onIdle(); - - virtual bool isActive(); - - virtual bool activatePlugin(); - - virtual bool closePlugin(); - - std::string& getName(); - -private: - // @{ - // \name Overload for IPluginCallback - virtual void init(IPluginAccess *pluginAccess); - - /// The current region has changed. -// virtual void primRegionChanged(const std::vector ®ions); - virtual void primitiveChanged(const NLLIGO::IPrimitive *root); - - /// The region has been modifed. -// virtual void primRegionModifed(); - /// The listener has been moved on the map. - virtual void positionMoved(const NLMISC::CVector &position); - /// The plugin lost the control of the position - virtual void lostPositionControl(); - // @} - - - - std::string _PluginName; - - bool _PluginActive; - - // callback for mixer init progression - void progress (float progressValue); - // Dialog for mixer init progression display - CLoadDialog *LoadDlg; - - /// The world editor interface. - IPluginAccess *_PluginAccess; - - - /// Sound plugin tool bat. -// CToolBar _Toolbar; - - /// Sound plugin dialog. - CDialogFlags *_DialogFlag; - - NLSOUND::UAudioMixer *_Mixer; - - /// the position of the listener. - NLMISC::CVector _ListenerPos; - - /// If play is enabled or not - bool _BackgroundSoundPlayed; -}; - -extern "C" -{ - /// Export the C factory method for dynamic linking.. - //__declspec( dllexport ) void *createSoundPlugin(); - __declspec( dllexport ) void *createPlugin(); - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/sound/u_audio_mixer.h" +#include "nel/ligo/primitive.h" +#include "nel/misc/progress_callback.h" +#include "../world_editor/plugin_interface.h" +#include "DialogFlags.h" +#include "nel/sound/u_audio_mixer.h" +#include "LoadDialog.h" + + +class CSoundPlugin : public IPluginCallback, public NLMISC::IProgressCallback +{ +public: + /// Constructor + CSoundPlugin(); + /// Destructor + ~CSoundPlugin(); + + void play(); + void stop(); + void startMoveEar(); + void stopMoveEar(); + + void update(); +// uint getLoadedSampleSize(); + + std::string getStatusString(); + + void getLoadedSampleBankInfo(std::vector > &result); + void ReInit(); + + NLSOUND::UAudioMixer *getMixer() { return _Mixer; }; + IPluginAccess *getPlugingAccess() { return _PluginAccess; }; + void onIdle(); + + virtual bool isActive(); + + virtual bool activatePlugin(); + + virtual bool closePlugin(); + + std::string& getName(); + +private: + // @{ + // \name Overload for IPluginCallback + virtual void init(IPluginAccess *pluginAccess); + + /// The current region has changed. +// virtual void primRegionChanged(const std::vector ®ions); + virtual void primitiveChanged(const NLLIGO::IPrimitive *root); + + /// The region has been modifed. +// virtual void primRegionModifed(); + /// The listener has been moved on the map. + virtual void positionMoved(const NLMISC::CVector &position); + /// The plugin lost the control of the position + virtual void lostPositionControl(); + // @} + + + + std::string _PluginName; + + bool _PluginActive; + + // callback for mixer init progression + void progress (float progressValue); + // Dialog for mixer init progression display + CLoadDialog *LoadDlg; + + /// The world editor interface. + IPluginAccess *_PluginAccess; + + + /// Sound plugin tool bat. +// CToolBar _Toolbar; + + /// Sound plugin dialog. + CDialogFlags *_DialogFlag; + + NLSOUND::UAudioMixer *_Mixer; + + /// the position of the listener. + NLMISC::CVector _ListenerPos; + + /// If play is enabled or not + bool _BackgroundSoundPlayed; +}; + +extern "C" +{ + /// Export the C factory method for dynamic linking.. + //__declspec( dllexport ) void *createSoundPlugin(); + __declspec( dllexport ) void *createPlugin(); + } \ No newline at end of file diff --git a/code/ryzom/tools/make_alias_file/make_alias_file.cpp b/code/ryzom/tools/make_alias_file/make_alias_file.cpp index 17caf3b9a..387a04a23 100644 --- a/code/ryzom/tools/make_alias_file/make_alias_file.cpp +++ b/code/ryzom/tools/make_alias_file/make_alias_file.cpp @@ -1,249 +1,249 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - - - -// misc -#include "nel/misc/types_nl.h" -#include "nel/misc/sheet_id.h" -#include "nel/misc/config_file.h" - -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" -#include "nel/georges/load_form.h" - -// std -#include -#include - - -#include - - - -using namespace NLMISC; -using namespace std; - - - - -/** - * Class to manage a sheet. - * \author Stephane Coutelas - * \author Nevrax France - * \date 2003 - */ -class CSheet -{ - -public: - - /// Alias - string Alias; - -public: - - /// Constructor - CSheet() {} - - /// Load the values using the george sheet - void readGeorges (const CSmartPtr &form, const CSheetId &sheetId); - - /// Load/Save the values using the serial system - void serial (NLMISC::IStream &s); - - /** - * Event to implement any action when the sheet is no longer existent. - * This method is called when a sheet have been read from the packed sheet - * and the associated sheet file no more exist in the directories. - */ - void removed() {} - - static uint getVersion(); - -private : - - static const uint _Version; -}; - -uint const CSheet::_Version = 1; - - - -//----------------------------------------------- -// readGeorges -// -//----------------------------------------------- -void CSheet::readGeorges (const CSmartPtr &form, const CSheetId &sheetId) -{ - // Load the form with given sheet id - if (form) - { - if( !form->getRootNode().getValueByName(Alias, "Alias", NLGEORGES::UFormElm::NoEval) ) - { - - } - } -} - - -//----------------------------------------------- -// serial -// -//----------------------------------------------- -void CSheet::serial (NLMISC::IStream &s) -{ - s.serial( Alias ); -} - - - -//----------------------------------------------- -// getVersion -// -//----------------------------------------------- -uint CSheet::getVersion () -{ - //return CSheetManager::_AliasFilenameVersion; - return 1; -} - - - - -//----------------------------------------------- -// displayHelp -// -//----------------------------------------------- -void displayHelp() -{ - cout<<"This tool creates a packed file which associates sheet id with sheet alias"< 1 ) - { - displayHelp(); - return EXIT_FAILURE; - } - - // load the cfg - CConfigFile configFile; - string configFileName = "make_alias_file.cfg"; - if(!CFile::fileExists(configFileName)) - { - nlwarning("Config file %s not found",configFileName.c_str()); - return 1; - } - configFile.load(configFileName); - - - // read the sheet paths - vector sheetPaths; - try - { - CConfigFile::CVar& cvSheetPaths = configFile.getVar("SheetPaths"); - sint i; - for( i = 0; i< (sint)cvSheetPaths.size(); ++i) - { - sheetPaths.push_back( cvSheetPaths.asString(i) ); - } - } - catch(const EUnknownVar &) - { - nlwarning("var 'SheetPaths' not found"); - } - - // add the sheet paths - cout<<"adding the sheet paths ..."<::iterator itPath; - for( itPath = sheetPaths.begin(); itPath != sheetPaths.end(); ++itPath ) - { - CPath::addSearchPath(*itPath,true,false); - } - - // read the name that will be used for packed file - string aliasFilename = "alias.packed_sheets"; - try - { - CConfigFile::CVar &cvAliasFilename = configFile.getVar("AliasFilename"); - aliasFilename = cvAliasFilename.asString(); - } - catch(const EUnknownVar &) - { - nlwarning("var 'AliasFilename' not found"); - } - - // read the extensions list of sheets to read - vector extensions; - try - { - CConfigFile::CVar& cvExtensions = configFile.getVar("Extensions"); - sint i; - for( i = 0; i< (sint)cvExtensions.size(); ++i) - { - extensions.push_back( cvExtensions.asString(i) ); - } - } - catch(const EUnknownVar &) - { - nlwarning("var 'Extensions' not found"); - } - - // load form and create packed sheets - cout<<"reading the sheets ..."< sheetMap; - bool updatePackedSheet = true; - createDebug(); // needed to init WarningLog - loadForm (extensions, aliasFilename, sheetMap, updatePackedSheet); - cout<<"finished."<::iterator itAlias; - for( itAlias = sheetMap.begin(); itAlias != sheetMap.end(); ++itAlias ) - { - nlinfo("sheet %s alias = %s",(*itAlias).first.toString().c_str(),(*itAlias).second.Alias.c_str()); - } - */ - - return EXIT_SUCCESS; - -} // main // - - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + + + +// misc +#include "nel/misc/types_nl.h" +#include "nel/misc/sheet_id.h" +#include "nel/misc/config_file.h" + +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" +#include "nel/georges/load_form.h" + +// std +#include +#include + + +#include + + + +using namespace NLMISC; +using namespace std; + + + + +/** + * Class to manage a sheet. + * \author Stephane Coutelas + * \author Nevrax France + * \date 2003 + */ +class CSheet +{ + +public: + + /// Alias + string Alias; + +public: + + /// Constructor + CSheet() {} + + /// Load the values using the george sheet + void readGeorges (const CSmartPtr &form, const CSheetId &sheetId); + + /// Load/Save the values using the serial system + void serial (NLMISC::IStream &s); + + /** + * Event to implement any action when the sheet is no longer existent. + * This method is called when a sheet have been read from the packed sheet + * and the associated sheet file no more exist in the directories. + */ + void removed() {} + + static uint getVersion(); + +private : + + static const uint _Version; +}; + +uint const CSheet::_Version = 1; + + + +//----------------------------------------------- +// readGeorges +// +//----------------------------------------------- +void CSheet::readGeorges (const CSmartPtr &form, const CSheetId &sheetId) +{ + // Load the form with given sheet id + if (form) + { + if( !form->getRootNode().getValueByName(Alias, "Alias", NLGEORGES::UFormElm::NoEval) ) + { + + } + } +} + + +//----------------------------------------------- +// serial +// +//----------------------------------------------- +void CSheet::serial (NLMISC::IStream &s) +{ + s.serial( Alias ); +} + + + +//----------------------------------------------- +// getVersion +// +//----------------------------------------------- +uint CSheet::getVersion () +{ + //return CSheetManager::_AliasFilenameVersion; + return 1; +} + + + + +//----------------------------------------------- +// displayHelp +// +//----------------------------------------------- +void displayHelp() +{ + cout<<"This tool creates a packed file which associates sheet id with sheet alias"< 1 ) + { + displayHelp(); + return EXIT_FAILURE; + } + + // load the cfg + CConfigFile configFile; + string configFileName = "make_alias_file.cfg"; + if(!CFile::fileExists(configFileName)) + { + nlwarning("Config file %s not found",configFileName.c_str()); + return 1; + } + configFile.load(configFileName); + + + // read the sheet paths + vector sheetPaths; + try + { + CConfigFile::CVar& cvSheetPaths = configFile.getVar("SheetPaths"); + sint i; + for( i = 0; i< (sint)cvSheetPaths.size(); ++i) + { + sheetPaths.push_back( cvSheetPaths.asString(i) ); + } + } + catch(const EUnknownVar &) + { + nlwarning("var 'SheetPaths' not found"); + } + + // add the sheet paths + cout<<"adding the sheet paths ..."<::iterator itPath; + for( itPath = sheetPaths.begin(); itPath != sheetPaths.end(); ++itPath ) + { + CPath::addSearchPath(*itPath,true,false); + } + + // read the name that will be used for packed file + string aliasFilename = "alias.packed_sheets"; + try + { + CConfigFile::CVar &cvAliasFilename = configFile.getVar("AliasFilename"); + aliasFilename = cvAliasFilename.asString(); + } + catch(const EUnknownVar &) + { + nlwarning("var 'AliasFilename' not found"); + } + + // read the extensions list of sheets to read + vector extensions; + try + { + CConfigFile::CVar& cvExtensions = configFile.getVar("Extensions"); + sint i; + for( i = 0; i< (sint)cvExtensions.size(); ++i) + { + extensions.push_back( cvExtensions.asString(i) ); + } + } + catch(const EUnknownVar &) + { + nlwarning("var 'Extensions' not found"); + } + + // load form and create packed sheets + cout<<"reading the sheets ..."< sheetMap; + bool updatePackedSheet = true; + createDebug(); // needed to init WarningLog + loadForm (extensions, aliasFilename, sheetMap, updatePackedSheet); + cout<<"finished."<::iterator itAlias; + for( itAlias = sheetMap.begin(); itAlias != sheetMap.end(); ++itAlias ) + { + nlinfo("sheet %s alias = %s",(*itAlias).first.toString().c_str(),(*itAlias).second.Alias.c_str()); + } + */ + + return EXIT_SUCCESS; + +} // main // + + + + diff --git a/code/ryzom/tools/make_anim_by_race/main.cpp b/code/ryzom/tools/make_anim_by_race/main.cpp index eedc1cd90..6400cdcd6 100644 --- a/code/ryzom/tools/make_anim_by_race/main.cpp +++ b/code/ryzom/tools/make_anim_by_race/main.cpp @@ -1,325 +1,325 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "nel/misc/path.h" -#include "nel/misc/file.h" -#include "nel/misc/common.h" -#include "nel/misc/algo.h" - - -using namespace std; -using namespace NLMISC; - - -// *************************************************************************** -void buildRaceAnimNames(std::vector &raceAnimNames, const std::string &animName) -{ - if(animName.compare(0, 3, "fy_")!=0) - { - nlwarning("ERROR: all .anim must begin with fy_"); - exit(-1); - } - - raceAnimNames.resize(4); - raceAnimNames[0]= animName; - raceAnimNames[1]= animName; - raceAnimNames[2]= animName; - raceAnimNames[3]= animName; - raceAnimNames[0].replace(0, 3, "fy_"); - raceAnimNames[1].replace(0, 3, "ma_"); - raceAnimNames[2].replace(0, 3, "tr_"); - raceAnimNames[3].replace(0, 3, "zo_"); - - // Force "" - for(uint i=0;i &raceAnimNames) -{ - // line Must contains Name="filename", else CAN BE A LOAD CHAR ANIMATION!!!! - if(lineLwr.find("name=\"filename\"")==string::npos) - return -1; - - // in the animset, the original file can be a "tr_" ... Not necessarily a "fy_" - for(uint i=0;i &animSetText, uint startBlock, const vector ©Text, uint nameLineInBlock, uint nameIndexInLine, const string &raceAnimName) -{ - // add empty space - animSetText.insert(animSetText.begin()+startBlock, copyText.size(), string()); - - // Fill line by line - for(uint i=0;i", peopleEnum.c_str()); - } - - // copy - animSetText[startBlock+i]= line; - } -} - -// *************************************************************************** -void makeAnimByRace(const std::string &animSetFile, const std::vector &animList) -{ - // *** Read the animset file. - CIFile iFile; - iFile.open(animSetFile, true); - // Read all text - static vector animSetText; - animSetText.clear(); - while(!iFile.eof()) - { - char tmp[50000]; - iFile.getline(tmp, 50000); - animSetText.push_back(tmp); - } - iFile.close(); - - - bool someChangeDone= false; - - // *** For each possible anim - for(uint i=0;i raceAnimNames; - raceAnimNames.clear(); - buildRaceAnimNames(raceAnimNames, toLower(CFile::getFilename(animList[i]))); - - // For each line of the animSet - uint lastStructLine= 0; - bool raceRestrictionFound= false; - for(uint j=0;j TAg? => stop - if(line.find("")!=string::npos) - break; - - // Find a STRUCT start? - if(line.find("")!=string::npos) - { - lastStructLine= j; - raceRestrictionFound= false; - } - - // Find a RaceRestriction? - if( line.find("Name=\"Race Restriction\"")!=string::npos ) - raceRestrictionFound= true; - - // Find the anim name? - string::size_type nameIndexInLine= findAnimName(lineLwr, raceAnimNames); - if(nameIndexInLine!=string::npos) - { - // Find the enclosing struct - nlassert(lastStructLine!=0); - uint startBlock= lastStructLine; - uint nameLineInBlock= j-startBlock; - uint endBlock= 0; - for(uint k=j+1;k")!=string::npos) - { - // endBlock is exclusive - endBlock= k+1; - break; - } - } - - // if not found, abort - if(endBlock==0) - break; - - // if a raceRestriction has been found, no op (already done) - if(raceRestrictionFound) - { - j= endBlock; - } - else - { - // LOG - InfoLog->displayRawNL("%s: Specifying %s by race", - CFile::getFilename(animSetFile).c_str(), - CFile::getFilename(animList[i]).c_str()); - - // *** Start a copy paste ^^ - // Copy - static vector copyText; - copyText.clear(); - for(uint k=startBlock;k, for race selection node (filled later) - if(k==endBlock-1) - copyText.push_back(string()); - copyText.push_back(animSetText[k]); - } - - // erase this part - animSetText.erase(animSetText.begin()+startBlock, animSetText.begin()+endBlock); - uint nextBlock= startBlock; - - // Append for each race - for(uint k=0;k files; - CPath::getPathContent(animDir, false, false, true, files); - // Filter .anim - vector animList; - InfoLog->displayRawNL(""); - InfoLog->displayRawNL("********************"); - InfoLog->displayRawNL("**** .anim list ****"); - InfoLog->displayRawNL("********************"); - for(uint i=0;idisplayRawNL(animList.back().c_str()); - } - - } - - // Get the list of .animset to make by race - files.clear(); - CPath::getPathContent(animSetDir, true, false, true, files); - vector animSetList; - InfoLog->displayRawNL(""); - InfoLog->displayRawNL("*****************************"); - InfoLog->displayRawNL("**** .animation_set list ****"); - InfoLog->displayRawNL("*****************************"); - for(uint i=0;idisplayRawNL(animSetList.back().c_str()); - } - } - - InfoLog->displayRawNL(""); - InfoLog->displayRawNL("**************************"); - InfoLog->displayRawNL("**** Starting Process ****"); - InfoLog->displayRawNL("**************************"); - // For each animset, test if can replace some anim - for(uint i=0;i +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "nel/misc/path.h" +#include "nel/misc/file.h" +#include "nel/misc/common.h" +#include "nel/misc/algo.h" + + +using namespace std; +using namespace NLMISC; + + +// *************************************************************************** +void buildRaceAnimNames(std::vector &raceAnimNames, const std::string &animName) +{ + if(animName.compare(0, 3, "fy_")!=0) + { + nlwarning("ERROR: all .anim must begin with fy_"); + exit(-1); + } + + raceAnimNames.resize(4); + raceAnimNames[0]= animName; + raceAnimNames[1]= animName; + raceAnimNames[2]= animName; + raceAnimNames[3]= animName; + raceAnimNames[0].replace(0, 3, "fy_"); + raceAnimNames[1].replace(0, 3, "ma_"); + raceAnimNames[2].replace(0, 3, "tr_"); + raceAnimNames[3].replace(0, 3, "zo_"); + + // Force "" + for(uint i=0;i &raceAnimNames) +{ + // line Must contains Name="filename", else CAN BE A LOAD CHAR ANIMATION!!!! + if(lineLwr.find("name=\"filename\"")==string::npos) + return -1; + + // in the animset, the original file can be a "tr_" ... Not necessarily a "fy_" + for(uint i=0;i &animSetText, uint startBlock, const vector ©Text, uint nameLineInBlock, uint nameIndexInLine, const string &raceAnimName) +{ + // add empty space + animSetText.insert(animSetText.begin()+startBlock, copyText.size(), string()); + + // Fill line by line + for(uint i=0;i", peopleEnum.c_str()); + } + + // copy + animSetText[startBlock+i]= line; + } +} + +// *************************************************************************** +void makeAnimByRace(const std::string &animSetFile, const std::vector &animList) +{ + // *** Read the animset file. + CIFile iFile; + iFile.open(animSetFile, true); + // Read all text + static vector animSetText; + animSetText.clear(); + while(!iFile.eof()) + { + char tmp[50000]; + iFile.getline(tmp, 50000); + animSetText.push_back(tmp); + } + iFile.close(); + + + bool someChangeDone= false; + + // *** For each possible anim + for(uint i=0;i raceAnimNames; + raceAnimNames.clear(); + buildRaceAnimNames(raceAnimNames, toLower(CFile::getFilename(animList[i]))); + + // For each line of the animSet + uint lastStructLine= 0; + bool raceRestrictionFound= false; + for(uint j=0;j TAg? => stop + if(line.find("")!=string::npos) + break; + + // Find a STRUCT start? + if(line.find("")!=string::npos) + { + lastStructLine= j; + raceRestrictionFound= false; + } + + // Find a RaceRestriction? + if( line.find("Name=\"Race Restriction\"")!=string::npos ) + raceRestrictionFound= true; + + // Find the anim name? + string::size_type nameIndexInLine= findAnimName(lineLwr, raceAnimNames); + if(nameIndexInLine!=string::npos) + { + // Find the enclosing struct + nlassert(lastStructLine!=0); + uint startBlock= lastStructLine; + uint nameLineInBlock= j-startBlock; + uint endBlock= 0; + for(uint k=j+1;k")!=string::npos) + { + // endBlock is exclusive + endBlock= k+1; + break; + } + } + + // if not found, abort + if(endBlock==0) + break; + + // if a raceRestriction has been found, no op (already done) + if(raceRestrictionFound) + { + j= endBlock; + } + else + { + // LOG + InfoLog->displayRawNL("%s: Specifying %s by race", + CFile::getFilename(animSetFile).c_str(), + CFile::getFilename(animList[i]).c_str()); + + // *** Start a copy paste ^^ + // Copy + static vector copyText; + copyText.clear(); + for(uint k=startBlock;k, for race selection node (filled later) + if(k==endBlock-1) + copyText.push_back(string()); + copyText.push_back(animSetText[k]); + } + + // erase this part + animSetText.erase(animSetText.begin()+startBlock, animSetText.begin()+endBlock); + uint nextBlock= startBlock; + + // Append for each race + for(uint k=0;k files; + CPath::getPathContent(animDir, false, false, true, files); + // Filter .anim + vector animList; + InfoLog->displayRawNL(""); + InfoLog->displayRawNL("********************"); + InfoLog->displayRawNL("**** .anim list ****"); + InfoLog->displayRawNL("********************"); + for(uint i=0;idisplayRawNL(animList.back().c_str()); + } + + } + + // Get the list of .animset to make by race + files.clear(); + CPath::getPathContent(animSetDir, true, false, true, files); + vector animSetList; + InfoLog->displayRawNL(""); + InfoLog->displayRawNL("*****************************"); + InfoLog->displayRawNL("**** .animation_set list ****"); + InfoLog->displayRawNL("*****************************"); + for(uint i=0;idisplayRawNL(animSetList.back().c_str()); + } + } + + InfoLog->displayRawNL(""); + InfoLog->displayRawNL("**************************"); + InfoLog->displayRawNL("**** Starting Process ****"); + InfoLog->displayRawNL("**************************"); + // For each animset, test if can replace some anim + for(uint i=0;i -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// *************************************************************************** -/* - This small tool was made for Graphist, to edit automatically *.animation_set sheets, so anims - get correct MeleeImpactDelay data - - It uses an anim.txt file that was generated by inserting code (give at end of this file) - in the client. - - This tool had to be "used one time only". hence its crappiest usage :) -*/ - - -#include "nel/misc/path.h" -#include "nel/misc/file.h" -#include "nel/misc/common.h" -#include "nel/misc/algo.h" - - -using namespace std; -using namespace NLMISC; - - -// *************************************************************************** -// Config -bool ReplaceExistingMeleeImpactDelay= true; -float MeleeImpactTimeFactor= 0.35f; - -// Inited in main() -map StateNameToStateCode; - - -// *************************************************************************** -class CAnimCombatState -{ -public: - void build(const string & line); - - // A1, A2 etc... - string StateCode; - // Mean Animation Time of all sub animations of this state - float MeanAnimTime; - -public: - bool operator<(const CAnimCombatState &o) const {return StateCode States; - -public: - bool operator<(const CAnimCombatSet &o) const {return Name &combatAnimSets) -{ - // look if this animSetFile is in the combat list to patch - string shortName= NLMISC::toLower(CFile::getFilenameWithoutExtension(animSetFile)); - CAnimCombatSet key; - key.Name= shortName; - set::const_iterator it= combatAnimSets.find(key); - if(it == combatAnimSets.end()) - return; - - const CAnimCombatSet ¤tCombatAnimSet= *it; - - InfoLog->displayRawNL("patching %s", animSetFile.c_str()); - - - // *** Read the animset file. - CIFile iFile; - iFile.open(animSetFile, true); - // Read all text - static vector animSetText; - animSetText.clear(); - while(!iFile.eof()) - { - char tmp[50000]; - iFile.getline(tmp, 50000); - animSetText.push_back(tmp); - } - iFile.close(); - - - bool someChangeDone= false; - - // *** Parse the animSet - { - // For each line of the animSet - sint structLevel= 0; - sint meleeImpactDelayLine= -1; - string currentStateName; - for(uint j=0;j TAg? => stop - if(line.find("")!=string::npos) - break; - - // Find a STRUCT start? - if(line.find("")!=string::npos) - { - // if end a state block, may add or replace MeleeDelayImpact - if(structLevel==2 && !currentStateName.empty()) - { - // If the state is not in the combat state, no need to patch anything - static CAnimCombatState key; - // must translate for instance "attack1" to "A1" - key.StateCode= StateNameToStateCode[currentStateName]; - set::const_iterator it= currentCombatAnimSet.States.find(key); - if(it!=currentCombatAnimSet.States.end()) - { - // else take the mean anim time - string format= " "; - string newLine= toString(format.c_str(), it->MeanAnimTime * MeleeImpactTimeFactor); - - // melee impact delay doesn't exist? - if(meleeImpactDelayLine==-1) - { - // add just before this line the Melee Impact Atom - animSetText.insert(animSetText.begin()+j, newLine); - j++; - someChangeDone= true; - } - // else exist and want to replace? - else if(ReplaceExistingMeleeImpactDelay) - { - animSetText[meleeImpactDelayLine]= newLine; - someChangeDone= true; - } - } - } - - // dec struct level - structLevel--; - } - - // if we are in level 2 structure, try to get the line to modify (if exist) - if(structLevel==2) - { - if( line.find("Name=\"MeleeImpactDelay\"")!=string::npos ) - meleeImpactDelayLine= j; - } - } - } - - // *** Write the animset file. - if(someChangeDone) - { - COFile oFile; - oFile.open(animSetFile, false, true); - // Write all text - for(uint i=0;i combatAnimSets; - CIFile animFile; - if(!animFile.open("anim.txt", true)) - { - nlwarning("Can't open anim.txt file. abort"); - return 0; - } - else - { - char tmp[5000]; - CAnimCombatSet lastAnimSet; - // parse all lines - while(!animFile.eof()) - { - animFile.getline(tmp, 5000); - string line= tmp; - if(line.empty()) - continue; - - // new anim set? - if(line[0]!=' ') - { - // insert the last anim state - if(!lastAnimSet.States.empty()) - combatAnimSets.insert(lastAnimSet); - lastAnimSet.States.clear(); - lastAnimSet.Name= line; - } - // new anim state? - else if(!lastAnimSet.Name.empty()) - { - CAnimCombatState state; - state.build(line); - lastAnimSet.States.insert(state); - } - } - - // append the last anim set if needed - if(!lastAnimSet.States.empty()) - combatAnimSets.insert(lastAnimSet); - - animFile.close(); - } - - // *** Get the list of .animset to make by race - vector files; - files.clear(); - CPath::getPathContent(animSetDir, true, false, true, files); - vector animSetList; - InfoLog->displayRawNL(""); - InfoLog->displayRawNL("*****************************"); - InfoLog->displayRawNL("**** .animation_set list ****"); - InfoLog->displayRawNL("*****************************"); - for(uint i=0;idisplayRawNL(animSetList.back().c_str()); - } - } - - // *** Init StateNameToStateCode - StateNameToStateCode["attack1"]= "A1"; - StateNameToStateCode["attack2"]= "A2"; - StateNameToStateCode["walk atk"]= "Wa"; - StateNameToStateCode["run atk"]= "Ra"; - StateNameToStateCode["backward atk"]= "Ba"; - StateNameToStateCode["default atk low"]= "Dl"; - StateNameToStateCode["default atk middle"]= "Dm"; - StateNameToStateCode["default atk high"]= "Dh"; - StateNameToStateCode["powerful atk low"]= "Pl"; - StateNameToStateCode["powerful atk middle"]= "Pm"; - StateNameToStateCode["powerful atk high"]= "Ph"; - StateNameToStateCode["area atk low"]= "Al"; - StateNameToStateCode["area atk middle"]= "Am"; - StateNameToStateCode["area atk high"]= "Ah"; - - - // *** For each animset, test if can replace some anim - InfoLog->displayRawNL(""); - InfoLog->displayRawNL("**************************"); - InfoLog->displayRawNL("**** Starting Process ****"); - InfoLog->displayRawNL("**************************"); - for(uint i=0;ibuild(); - .... - } - - ** insert here *** - - - animSet Sheets and 3D anim data (fauna_animations.bnp and characters_animations.bnp) must be up to date -*/ - - -/* - - // ************************************* - // CODE TO GENERATE MELEE IMPACT DELAY - // ************************************* - CFileDisplayer animLog("anim.txt", true); - TAnimStateId walkAtk= CAnimationStateSheet::getAnimationStateId("walk atk"); - TAnimStateId runAtk= CAnimationStateSheet::getAnimationStateId("run atk"); - TAnimStateId backAtk= CAnimationStateSheet::getAnimationStateId("backward atk"); - TAnimStateId stateCombat[]= {CAnimationStateSheet::Attack1, CAnimationStateSheet::Attack2, - walkAtk, runAtk, backAtk, - CAnimationStateSheet::DefaultAtkLow,CAnimationStateSheet::DefaultAtkHigh, - CAnimationStateSheet::DefaultAtkMiddle,CAnimationStateSheet::PowerfulAtkLow, - CAnimationStateSheet::PowerfulAtkHigh,CAnimationStateSheet::PowerfulAtkMiddle, - CAnimationStateSheet::AreaAtkLow,CAnimationStateSheet::AreaAtkHigh, - CAnimationStateSheet::AreaAtkMiddle}; - string stateCombatCode[]= {"A1", "A2", "Wa", "Ra", "Ba", - "Dl", "Dh", "Dm", "Pl", "Ph", "Pm", "Al", "Ah", "Am"}; - const uint32 nSC= sizeof(stateCombat) / sizeof(stateCombat[0]); - nlctassert(nSC==sizeof(stateCombatCode) / sizeof(stateCombatCode[0])); - { - float roughEval= 0.f; - uint nbRoughEval= 0; - TAnimSet::iterator it= _AnimSet.begin(); - for(;it!=_AnimSet.end();it++) - { - CAnimationSet &animSet= it->second; - bool animSetDisplayed= false; - for(uint i=0;i(animSet.getAnimationState(stateCombat[i])); - if(state) - { - // first compute mean and anim name - float mean= 0.f; - uint nbValid= 0; - string animName; - bool extended= false; - for(uint j=0;jgetNumAnimation();j++) - { - CAnimation *anim= state->getAnimationByIndex(j); - NL3D::UAnimation *anim3d= NULL; - if(anim) - anim3d= _AnimationSet->getAnimation(anim->id()); - if(anim && anim3d) - { - // name - string name= NLMISC::toLower(_AnimationSet->getAnimationName(anim->id())); - if(animName.empty()) - animName= name; - else if(!extended) - { - extended= true; - animName+= ", ..."; - } - - // meanLength and nb - float timeLen= anim3d->getEndTime()-anim3d->getBeginTime(); - mean+= timeLen; - nbValid++; - } - } - if(nbValid) - mean/=nbValid; - - // compute standard and max deviation - float stdDev=0.f, maxDev=0.f; - for(uint j=0;jgetNumAnimation();j++) - { - CAnimation *anim= state->getAnimationByIndex(j); - NL3D::UAnimation *anim3d= NULL; - if(anim) - anim3d= _AnimationSet->getAnimation(anim->id()); - if(anim && anim3d) - { - float timeLen= anim3d->getEndTime()-anim3d->getBeginTime(); - stdDev+= (float)fabs(timeLen - mean); - maxDev= max(maxDev, (float)fabs(timeLen - mean)); - } - } - if(nbValid) - stdDev/= nbValid; - - // valid? - if(nbValid) - { - // display first animSetName - if(!animSetDisplayed) - { - string msg= toString("%s\n", it->first.c_str() ); - animLog.display(CLog::TDisplayInfo(), msg.c_str()); - animSetDisplayed= true; - } - - // then stats for this state - string msg= toString(" %s: mn%.03f, md%.03f, sd%.03f, ev%.03f (%s)\n", stateCombatCode[i].c_str(), - mean, maxDev, stdDev, mean*0.4f, animName.c_str()); - animLog.display(CLog::TDisplayInfo(), msg.c_str()); - - roughEval+= mean; - nbRoughEval++; - } - } - } - } - if(nbRoughEval) - { - roughEval/= nbRoughEval; - nlinfo(" AnimDBG RoughEval: mn%.03f, ev%.03f", - roughEval, roughEval*0.4f); - } - } - // ************************************* - // CODE TO GENERATE MELEE IMPACT DELAY - // ************************************* - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// *************************************************************************** +/* + This small tool was made for Graphist, to edit automatically *.animation_set sheets, so anims + get correct MeleeImpactDelay data + + It uses an anim.txt file that was generated by inserting code (give at end of this file) + in the client. + + This tool had to be "used one time only". hence its crappiest usage :) +*/ + + +#include "nel/misc/path.h" +#include "nel/misc/file.h" +#include "nel/misc/common.h" +#include "nel/misc/algo.h" + + +using namespace std; +using namespace NLMISC; + + +// *************************************************************************** +// Config +bool ReplaceExistingMeleeImpactDelay= true; +float MeleeImpactTimeFactor= 0.35f; + +// Inited in main() +map StateNameToStateCode; + + +// *************************************************************************** +class CAnimCombatState +{ +public: + void build(const string & line); + + // A1, A2 etc... + string StateCode; + // Mean Animation Time of all sub animations of this state + float MeanAnimTime; + +public: + bool operator<(const CAnimCombatState &o) const {return StateCode States; + +public: + bool operator<(const CAnimCombatSet &o) const {return Name &combatAnimSets) +{ + // look if this animSetFile is in the combat list to patch + string shortName= NLMISC::toLower(CFile::getFilenameWithoutExtension(animSetFile)); + CAnimCombatSet key; + key.Name= shortName; + set::const_iterator it= combatAnimSets.find(key); + if(it == combatAnimSets.end()) + return; + + const CAnimCombatSet ¤tCombatAnimSet= *it; + + InfoLog->displayRawNL("patching %s", animSetFile.c_str()); + + + // *** Read the animset file. + CIFile iFile; + iFile.open(animSetFile, true); + // Read all text + static vector animSetText; + animSetText.clear(); + while(!iFile.eof()) + { + char tmp[50000]; + iFile.getline(tmp, 50000); + animSetText.push_back(tmp); + } + iFile.close(); + + + bool someChangeDone= false; + + // *** Parse the animSet + { + // For each line of the animSet + sint structLevel= 0; + sint meleeImpactDelayLine= -1; + string currentStateName; + for(uint j=0;j TAg? => stop + if(line.find("")!=string::npos) + break; + + // Find a STRUCT start? + if(line.find("")!=string::npos) + { + // if end a state block, may add or replace MeleeDelayImpact + if(structLevel==2 && !currentStateName.empty()) + { + // If the state is not in the combat state, no need to patch anything + static CAnimCombatState key; + // must translate for instance "attack1" to "A1" + key.StateCode= StateNameToStateCode[currentStateName]; + set::const_iterator it= currentCombatAnimSet.States.find(key); + if(it!=currentCombatAnimSet.States.end()) + { + // else take the mean anim time + string format= " "; + string newLine= toString(format.c_str(), it->MeanAnimTime * MeleeImpactTimeFactor); + + // melee impact delay doesn't exist? + if(meleeImpactDelayLine==-1) + { + // add just before this line the Melee Impact Atom + animSetText.insert(animSetText.begin()+j, newLine); + j++; + someChangeDone= true; + } + // else exist and want to replace? + else if(ReplaceExistingMeleeImpactDelay) + { + animSetText[meleeImpactDelayLine]= newLine; + someChangeDone= true; + } + } + } + + // dec struct level + structLevel--; + } + + // if we are in level 2 structure, try to get the line to modify (if exist) + if(structLevel==2) + { + if( line.find("Name=\"MeleeImpactDelay\"")!=string::npos ) + meleeImpactDelayLine= j; + } + } + } + + // *** Write the animset file. + if(someChangeDone) + { + COFile oFile; + oFile.open(animSetFile, false, true); + // Write all text + for(uint i=0;i combatAnimSets; + CIFile animFile; + if(!animFile.open("anim.txt", true)) + { + nlwarning("Can't open anim.txt file. abort"); + return 0; + } + else + { + char tmp[5000]; + CAnimCombatSet lastAnimSet; + // parse all lines + while(!animFile.eof()) + { + animFile.getline(tmp, 5000); + string line= tmp; + if(line.empty()) + continue; + + // new anim set? + if(line[0]!=' ') + { + // insert the last anim state + if(!lastAnimSet.States.empty()) + combatAnimSets.insert(lastAnimSet); + lastAnimSet.States.clear(); + lastAnimSet.Name= line; + } + // new anim state? + else if(!lastAnimSet.Name.empty()) + { + CAnimCombatState state; + state.build(line); + lastAnimSet.States.insert(state); + } + } + + // append the last anim set if needed + if(!lastAnimSet.States.empty()) + combatAnimSets.insert(lastAnimSet); + + animFile.close(); + } + + // *** Get the list of .animset to make by race + vector files; + files.clear(); + CPath::getPathContent(animSetDir, true, false, true, files); + vector animSetList; + InfoLog->displayRawNL(""); + InfoLog->displayRawNL("*****************************"); + InfoLog->displayRawNL("**** .animation_set list ****"); + InfoLog->displayRawNL("*****************************"); + for(uint i=0;idisplayRawNL(animSetList.back().c_str()); + } + } + + // *** Init StateNameToStateCode + StateNameToStateCode["attack1"]= "A1"; + StateNameToStateCode["attack2"]= "A2"; + StateNameToStateCode["walk atk"]= "Wa"; + StateNameToStateCode["run atk"]= "Ra"; + StateNameToStateCode["backward atk"]= "Ba"; + StateNameToStateCode["default atk low"]= "Dl"; + StateNameToStateCode["default atk middle"]= "Dm"; + StateNameToStateCode["default atk high"]= "Dh"; + StateNameToStateCode["powerful atk low"]= "Pl"; + StateNameToStateCode["powerful atk middle"]= "Pm"; + StateNameToStateCode["powerful atk high"]= "Ph"; + StateNameToStateCode["area atk low"]= "Al"; + StateNameToStateCode["area atk middle"]= "Am"; + StateNameToStateCode["area atk high"]= "Ah"; + + + // *** For each animset, test if can replace some anim + InfoLog->displayRawNL(""); + InfoLog->displayRawNL("**************************"); + InfoLog->displayRawNL("**** Starting Process ****"); + InfoLog->displayRawNL("**************************"); + for(uint i=0;ibuild(); + .... + } + + ** insert here *** + + + animSet Sheets and 3D anim data (fauna_animations.bnp and characters_animations.bnp) must be up to date +*/ + + +/* + + // ************************************* + // CODE TO GENERATE MELEE IMPACT DELAY + // ************************************* + CFileDisplayer animLog("anim.txt", true); + TAnimStateId walkAtk= CAnimationStateSheet::getAnimationStateId("walk atk"); + TAnimStateId runAtk= CAnimationStateSheet::getAnimationStateId("run atk"); + TAnimStateId backAtk= CAnimationStateSheet::getAnimationStateId("backward atk"); + TAnimStateId stateCombat[]= {CAnimationStateSheet::Attack1, CAnimationStateSheet::Attack2, + walkAtk, runAtk, backAtk, + CAnimationStateSheet::DefaultAtkLow,CAnimationStateSheet::DefaultAtkHigh, + CAnimationStateSheet::DefaultAtkMiddle,CAnimationStateSheet::PowerfulAtkLow, + CAnimationStateSheet::PowerfulAtkHigh,CAnimationStateSheet::PowerfulAtkMiddle, + CAnimationStateSheet::AreaAtkLow,CAnimationStateSheet::AreaAtkHigh, + CAnimationStateSheet::AreaAtkMiddle}; + string stateCombatCode[]= {"A1", "A2", "Wa", "Ra", "Ba", + "Dl", "Dh", "Dm", "Pl", "Ph", "Pm", "Al", "Ah", "Am"}; + const uint32 nSC= sizeof(stateCombat) / sizeof(stateCombat[0]); + nlctassert(nSC==sizeof(stateCombatCode) / sizeof(stateCombatCode[0])); + { + float roughEval= 0.f; + uint nbRoughEval= 0; + TAnimSet::iterator it= _AnimSet.begin(); + for(;it!=_AnimSet.end();it++) + { + CAnimationSet &animSet= it->second; + bool animSetDisplayed= false; + for(uint i=0;i(animSet.getAnimationState(stateCombat[i])); + if(state) + { + // first compute mean and anim name + float mean= 0.f; + uint nbValid= 0; + string animName; + bool extended= false; + for(uint j=0;jgetNumAnimation();j++) + { + CAnimation *anim= state->getAnimationByIndex(j); + NL3D::UAnimation *anim3d= NULL; + if(anim) + anim3d= _AnimationSet->getAnimation(anim->id()); + if(anim && anim3d) + { + // name + string name= NLMISC::toLower(_AnimationSet->getAnimationName(anim->id())); + if(animName.empty()) + animName= name; + else if(!extended) + { + extended= true; + animName+= ", ..."; + } + + // meanLength and nb + float timeLen= anim3d->getEndTime()-anim3d->getBeginTime(); + mean+= timeLen; + nbValid++; + } + } + if(nbValid) + mean/=nbValid; + + // compute standard and max deviation + float stdDev=0.f, maxDev=0.f; + for(uint j=0;jgetNumAnimation();j++) + { + CAnimation *anim= state->getAnimationByIndex(j); + NL3D::UAnimation *anim3d= NULL; + if(anim) + anim3d= _AnimationSet->getAnimation(anim->id()); + if(anim && anim3d) + { + float timeLen= anim3d->getEndTime()-anim3d->getBeginTime(); + stdDev+= (float)fabs(timeLen - mean); + maxDev= max(maxDev, (float)fabs(timeLen - mean)); + } + } + if(nbValid) + stdDev/= nbValid; + + // valid? + if(nbValid) + { + // display first animSetName + if(!animSetDisplayed) + { + string msg= toString("%s\n", it->first.c_str() ); + animLog.display(CLog::TDisplayInfo(), msg.c_str()); + animSetDisplayed= true; + } + + // then stats for this state + string msg= toString(" %s: mn%.03f, md%.03f, sd%.03f, ev%.03f (%s)\n", stateCombatCode[i].c_str(), + mean, maxDev, stdDev, mean*0.4f, animName.c_str()); + animLog.display(CLog::TDisplayInfo(), msg.c_str()); + + roughEval+= mean; + nbRoughEval++; + } + } + } + } + if(nbRoughEval) + { + roughEval/= nbRoughEval; + nlinfo(" AnimDBG RoughEval: mn%.03f, ev%.03f", + roughEval, roughEval*0.4f); + } + } + // ************************************* + // CODE TO GENERATE MELEE IMPACT DELAY + // ************************************* + + */ \ No newline at end of file diff --git a/code/ryzom/tools/occ2huff/occ2huff.cpp b/code/ryzom/tools/occ2huff/occ2huff.cpp index 62997d04c..500e76735 100644 --- a/code/ryzom/tools/occ2huff/occ2huff.cpp +++ b/code/ryzom/tools/occ2huff/occ2huff.cpp @@ -1,270 +1,270 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - - -#include "nel/misc/types_nl.h" -#include "nel/misc/debug.h" -#include "nel/misc/file.h" - -#include "game_share/huffman.h" - -#include -#include -#include - -using namespace std; -using namespace NLMISC; - - -/** - * CStringInfos - * \author Stephane Coutelas - * \author Nevrax France - * \date 2002 - */ -struct CStringInfos -{ - /// string id - string Id; - - /// string - string Str; - - /// occurence of the string - uint32 Occurence; - - /** - * Default constructor - */ - CStringInfos() : Occurence(1) { } - -}; - - - -//----------------------------------------------- -// main -// -//----------------------------------------------- -sint main( sint argc, char ** argv ) -{ - uint currentVersion = 1; - - map base; - - if( argc < 3 ) - { - printf("Create a file associating a string id with a string and its Huffman code\n\n"); - printf("OCC2HUFF [ ...] \n"); - return 1; - } - - // open the id string association file(s) - sint i; - for( i = 1; i < argc - 1; i++ ) - { - printf("Reading string association file '%s'...\n",argv[i]); - - ifstream input1(argv[i], ios::in); - if( !input1.is_open() ) - { - nlwarning("can't open the file %s",argv[i]); - return 1; - } - - // read the tokens and create the string infos - while( !input1.eof() ) - { - // read a line - string line; - getline(input1,line,'\n'); - - // test the line ( there must be at least 2 '"',remove comments if exist ) - sint32 idx = line.find_first_of("#"); - bool hasComments = false; - if( idx != -1 ) - { - line = line.substr(0,idx); - hasComments = true; - } - if( line.size() == 0 ) - { - continue; - } - if( line.find_first_of("\"") == -1 ) - { - if( !hasComments ) - { - nlwarning("Missing string value in the string '%s'",line.c_str()); - return 1; - } - } - if( line.find_first_of("\"") == line.find_last_of("\"") ) - { - if( !hasComments ) - { - nlwarning("Missing a delimiter \" in the string '%s'",line.c_str()); - return 1; - } - } - - // extract string id and string - idx = line.find_first_of(" \t"); - if( idx != -1 ) - { - CStringInfos si; - si.Id = line.substr(0,idx); - - sint32 startIdx = line.find_first_of("\""); - sint32 endIdx = line.find_last_of("\""); - si.Str = line.substr(startIdx+1,endIdx-startIdx-1); - - // add string infos - map::iterator itStr = base.find( si.Id ); - if( itStr == base.end() ) - { - base.insert( make_pair(si.Id,si) ); - } - else - { - nlwarning("The string %s already exists !",si.Id.c_str()); - } - } - } - input1.close(); - } - - // open the id occurence association file - string occfilename = argv[argc-1]; - printf("Reading occurence file '%s'...\n",occfilename.c_str()); - ifstream input2(occfilename.c_str(), ios::in); - if( !input2.is_open() ) - { - nlwarning("Can't open the file %s, set all occurences to 1",argv[argc-1]); - } - else - { - // read the tokens and update the string infos with occurences - while( !input2.eof() ) - { - // read a line - string line; - getline(input2,line,'\n'); - - // test the line - sint32 idx = line.find_first_of("#"); - if( idx != string::npos ) - { - line = line.substr(0,idx); - } - if( line.size() == 0 ) - { - continue; - } - char * buffer = new char[line.size()+1]; - strcpy(buffer,line.c_str()); - - // extract string id and occurence - char * token; - string stoken; - token = strtok(buffer," \t"); - if( token != NULL ) - { - stoken = string( token ); - map::iterator itStr = base.find( stoken ); - if( itStr != base.end() ) - { - token = strtok(NULL," \t"); - (*itStr).second.Occurence = atoi( token ); - if( (*itStr).second.Occurence == 0 ) - { - nlwarning("The occurence of string '%s' is 0 (problem with occurence ?: '%s'), set it to 1",(*itStr).second.Str.c_str(),token); - (*itStr).second.Occurence = 1; - } - } - else - { - nlwarning("The string '%s' is in the .occ but in the txt files!",token); - } - } - delete buffer; - } - input2.close(); - - ofstream output2(occfilename.c_str(), ios::app); - if (output2.is_open()) - { - map::iterator itBase; - for( itBase = base.begin(); itBase != base.end(); ++itBase ) - { - if((*itBase).second.Occurence == 0) - { - output2 << (*itBase).first << " 1" <::iterator itBase; - for( itBase = base.begin(); itBase != base.end(); ++itBase ) - { - huff.add( (*itBase).first,(*itBase).second.Occurence ); - } - huff.build(); - - - // open the output file - string outputFileName = "chat_static.cdb"; - COFile output( outputFileName ); - - // save id|string|occurence - printf("Writing binary file '%s'...\n",outputFileName.c_str()); - output.serialVersion(currentVersion); - uint32 count = base.size(); - output.serial( count ); - vector code; - for( itBase = base.begin(); itBase != base.end(); ++itBase ) - { - if( (*itBase).second.Occurence > 0 ) - { - huff.getCode( (*itBase).first, code ); - output.serial( (*itBase).second.Id ); - output.serial( (*itBase).second.Str ); - output.serial( (*itBase).second.Occurence ); - output.serialCont( code ); - } - } - - // TEST - /*printf("Writing debug text file...\n"); - FILE * outputTest = fopen("chat_static_base_test.log","wt"); - for( itBase = base.begin(); itBase != base.end(); ++itBase ) - { - fprintf(outputTest,"id: %s str: %s occ: %d\n",(*itBase).second.Id.c_str(),(*itBase).second.Str.c_str(), (*itBase).second.Occurence ); - } - fclose(outputTest);*/ - - printf("Process complete.\n"); - - return 0; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + + +#include "nel/misc/types_nl.h" +#include "nel/misc/debug.h" +#include "nel/misc/file.h" + +#include "game_share/huffman.h" + +#include +#include +#include + +using namespace std; +using namespace NLMISC; + + +/** + * CStringInfos + * \author Stephane Coutelas + * \author Nevrax France + * \date 2002 + */ +struct CStringInfos +{ + /// string id + string Id; + + /// string + string Str; + + /// occurence of the string + uint32 Occurence; + + /** + * Default constructor + */ + CStringInfos() : Occurence(1) { } + +}; + + + +//----------------------------------------------- +// main +// +//----------------------------------------------- +sint main( sint argc, char ** argv ) +{ + uint currentVersion = 1; + + map base; + + if( argc < 3 ) + { + printf("Create a file associating a string id with a string and its Huffman code\n\n"); + printf("OCC2HUFF [ ...] \n"); + return 1; + } + + // open the id string association file(s) + sint i; + for( i = 1; i < argc - 1; i++ ) + { + printf("Reading string association file '%s'...\n",argv[i]); + + ifstream input1(argv[i], ios::in); + if( !input1.is_open() ) + { + nlwarning("can't open the file %s",argv[i]); + return 1; + } + + // read the tokens and create the string infos + while( !input1.eof() ) + { + // read a line + string line; + getline(input1,line,'\n'); + + // test the line ( there must be at least 2 '"',remove comments if exist ) + sint32 idx = line.find_first_of("#"); + bool hasComments = false; + if( idx != -1 ) + { + line = line.substr(0,idx); + hasComments = true; + } + if( line.size() == 0 ) + { + continue; + } + if( line.find_first_of("\"") == -1 ) + { + if( !hasComments ) + { + nlwarning("Missing string value in the string '%s'",line.c_str()); + return 1; + } + } + if( line.find_first_of("\"") == line.find_last_of("\"") ) + { + if( !hasComments ) + { + nlwarning("Missing a delimiter \" in the string '%s'",line.c_str()); + return 1; + } + } + + // extract string id and string + idx = line.find_first_of(" \t"); + if( idx != -1 ) + { + CStringInfos si; + si.Id = line.substr(0,idx); + + sint32 startIdx = line.find_first_of("\""); + sint32 endIdx = line.find_last_of("\""); + si.Str = line.substr(startIdx+1,endIdx-startIdx-1); + + // add string infos + map::iterator itStr = base.find( si.Id ); + if( itStr == base.end() ) + { + base.insert( make_pair(si.Id,si) ); + } + else + { + nlwarning("The string %s already exists !",si.Id.c_str()); + } + } + } + input1.close(); + } + + // open the id occurence association file + string occfilename = argv[argc-1]; + printf("Reading occurence file '%s'...\n",occfilename.c_str()); + ifstream input2(occfilename.c_str(), ios::in); + if( !input2.is_open() ) + { + nlwarning("Can't open the file %s, set all occurences to 1",argv[argc-1]); + } + else + { + // read the tokens and update the string infos with occurences + while( !input2.eof() ) + { + // read a line + string line; + getline(input2,line,'\n'); + + // test the line + sint32 idx = line.find_first_of("#"); + if( idx != string::npos ) + { + line = line.substr(0,idx); + } + if( line.size() == 0 ) + { + continue; + } + char * buffer = new char[line.size()+1]; + strcpy(buffer,line.c_str()); + + // extract string id and occurence + char * token; + string stoken; + token = strtok(buffer," \t"); + if( token != NULL ) + { + stoken = string( token ); + map::iterator itStr = base.find( stoken ); + if( itStr != base.end() ) + { + token = strtok(NULL," \t"); + (*itStr).second.Occurence = atoi( token ); + if( (*itStr).second.Occurence == 0 ) + { + nlwarning("The occurence of string '%s' is 0 (problem with occurence ?: '%s'), set it to 1",(*itStr).second.Str.c_str(),token); + (*itStr).second.Occurence = 1; + } + } + else + { + nlwarning("The string '%s' is in the .occ but in the txt files!",token); + } + } + delete buffer; + } + input2.close(); + + ofstream output2(occfilename.c_str(), ios::app); + if (output2.is_open()) + { + map::iterator itBase; + for( itBase = base.begin(); itBase != base.end(); ++itBase ) + { + if((*itBase).second.Occurence == 0) + { + output2 << (*itBase).first << " 1" <::iterator itBase; + for( itBase = base.begin(); itBase != base.end(); ++itBase ) + { + huff.add( (*itBase).first,(*itBase).second.Occurence ); + } + huff.build(); + + + // open the output file + string outputFileName = "chat_static.cdb"; + COFile output( outputFileName ); + + // save id|string|occurence + printf("Writing binary file '%s'...\n",outputFileName.c_str()); + output.serialVersion(currentVersion); + uint32 count = base.size(); + output.serial( count ); + vector code; + for( itBase = base.begin(); itBase != base.end(); ++itBase ) + { + if( (*itBase).second.Occurence > 0 ) + { + huff.getCode( (*itBase).first, code ); + output.serial( (*itBase).second.Id ); + output.serial( (*itBase).second.Str ); + output.serial( (*itBase).second.Occurence ); + output.serialCont( code ); + } + } + + // TEST + /*printf("Writing debug text file...\n"); + FILE * outputTest = fopen("chat_static_base_test.log","wt"); + for( itBase = base.begin(); itBase != base.end(); ++itBase ) + { + fprintf(outputTest,"id: %s str: %s occ: %d\n",(*itBase).second.Id.c_str(),(*itBase).second.Str.c_str(), (*itBase).second.Occurence ); + } + fclose(outputTest);*/ + + printf("Process complete.\n"); + + return 0; +} diff --git a/code/ryzom/tools/patch_gen/patch_gen_common.cpp b/code/ryzom/tools/patch_gen/patch_gen_common.cpp index c746fcd00..90b42ca72 100644 --- a/code/ryzom/tools/patch_gen/patch_gen_common.cpp +++ b/code/ryzom/tools/patch_gen/patch_gen_common.cpp @@ -1,616 +1,616 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//----------------------------------------------------------------------------- -// includes -//----------------------------------------------------------------------------- - -#include - -#include "game_share/bnp_patch.h" -#include "nel/misc/path.h" -#include "nel/misc/file.h" -#include "nel/misc/command.h" -#include "nel/misc/sstring.h" -#include "game_share/singleton_registry.h" - -using namespace std; -using namespace NLMISC; - -#define PERSISTENT_TOKEN_FAMILY RyzomTokenFamily - - -//----------------------------------------------------------------------------- -// Handy utility functions -//----------------------------------------------------------------------------- - -void normalisePackageDescriptionFileName(std::string& fileName) -{ - if (fileName.empty()) - fileName="package_description"; - if (NLMISC::CFile::getExtension(fileName).empty() && fileName[fileName.size()-1]!='.') - fileName+=".xml"; -} - -void GeneratePatch(const std::string& srcFileName,const std::string& destFileName,const std::string& patchFileName) -{ - std::string cmd="xdelta delta"; - cmd+=" "+srcFileName+" "+destFileName+" "+patchFileName; - nlinfo("executing system command: %s",cmd.c_str()); -#ifdef NL_OS_WINDOWS - _spawnlp(_P_WAIT, "xdelta.exe","xdelta.exe","delta",srcFileName.c_str(),destFileName.c_str(),patchFileName.c_str(),NULL); -#else // NL_OS_WINDOWS - sint error = system (cmd.c_str()); - if (error) - nlwarning("'%s' failed with error code %d", cmd.c_str(), error); -#endif // NL_OS_WINDOWS -} - -void ApplyPatch(const std::string& srcFileName,const std::string& destFileName,const std::string& patchFileName=std::string()) -{ - std::string cmd="xdelta patch"; - cmd+=" "+patchFileName+" "+srcFileName+" "+destFileName; - nlinfo("executing system command: %s",cmd.c_str()); -#ifdef NL_OS_WINDOWS - _spawnlp(_P_WAIT, "xdelta.exe","xdelta.exe","patch",patchFileName.c_str(),srcFileName.c_str(),destFileName.c_str(),NULL); -#else // NL_OS_WINDOWS - sint error = system (cmd.c_str()); - if (error) - nlwarning("'%s' failed with error code %d", cmd.c_str(), error); -#endif // NL_OS_WINDOWS -} - -void GenerateLZMA(const std::string sourceFile, const std::string &outputFile) -{ - std::string cmd="lzma e "; - cmd+=" "+sourceFile+" "+outputFile; - nlinfo("executing system command: %s",cmd.c_str()); -#ifdef NL_OS_WINDOWS - _spawnlp(_P_WAIT, "lzma.exe","lzma.exe", "e", sourceFile.c_str(), outputFile.c_str(), NULL); -#else // NL_OS_WINDOWS - sint error = system (cmd.c_str()); - if (error) - nlwarning("'%s' failed with error code %d", cmd.c_str(), error); -#endif // NL_OS_WINDOWS -} - - -//----------------------------------------------------------------------------- -// class CPackageDescription -//----------------------------------------------------------------------------- - -class CPackageDescription: public IVersionNumberGenerator -{ -private: - DECLARE_PERSISTENCE_METHODS - -public: - CPackageDescription(); - - void clear(); - - void setup(const std::string& packageName); - void storeToPdr(CPersistentDataRecord& pdr) const; - - void readIndex(CBNPFileSet& packageIndex) const; - void writeIndex(const CBNPFileSet& packageIndex) const; - - void getCategories(CPersistentDataRecord &pdr) const; - - void updateIndexFileList(CBNPFileSet& packageIndex) const; - void generateClientIndex(CProductDescriptionForClient& theClientPackage,const CBNPFileSet& packageIndex) const; - void addVersion(CBNPFileSet& packageIndex); - void generatePatches(CBNPFileSet& packageIndex) const; - void createDirectories() const; - void buildDefaultFileList(); - - void updatePatchSizes(CBNPFileSet& packageIndex) const; - - // specialisation of IVersionNumberGenerator - void grabVersionNumber(); - uint32 getPackageVersionNumber(); - -private: - CBNPCategorySet _Categories; - std::string _IndexFileName; - std::string _ClientIndexFileName; - std::string _RootDirectory; - std::string _PatchDirectory; - std::string _BnpDirectory; - std::string _RefDirectory; - std::string _NextVersionFile; - - uint32 _NextVersionNumber; - bool _VersionNumberReserved; -}; - - -//----------------------------------------------------------------------------- -// methods CPackageDescription -//----------------------------------------------------------------------------- - -CPackageDescription::CPackageDescription() -{ - clear(); -} - -void CPackageDescription::clear() -{ - _NextVersionNumber= ~0u; - _VersionNumberReserved = false; - _Categories.clear(); - _IndexFileName.clear(); - _ClientIndexFileName.clear(); - _PatchDirectory.clear(); - _BnpDirectory.clear(); - _RefDirectory.clear(); -} - -void CPackageDescription::setup(const std::string& packageName) -{ - nlinfo("Reading package description: %s ...",packageName.c_str()); - - // clear out old contents before reading from input file - clear(); - - // read new contents from input file - static CPersistentDataRecord pdr; - pdr.clear(); - pdr.readFromTxtFile(packageName.c_str()); - apply(pdr); - - // root directory - if (_RootDirectory.empty()) - _RootDirectory= NLMISC::CFile::getPath(packageName); - _RootDirectory= NLMISC::CPath::standardizePath(_RootDirectory,true); - - // patch directory - if (_PatchDirectory.empty()) - _PatchDirectory= _RootDirectory+"patch"; - _PatchDirectory= NLMISC::CPath::standardizePath(_PatchDirectory,true); - - // BNP directory - if (_BnpDirectory.empty()) - _BnpDirectory= _RootDirectory+"bnp"; - _BnpDirectory= NLMISC::CPath::standardizePath(_BnpDirectory,true); - - // ref directory - if (_RefDirectory.empty()) - _RefDirectory= _RootDirectory+"ref"; - _RefDirectory= NLMISC::CPath::standardizePath(_RefDirectory,true); - - // client index file - if (_ClientIndexFileName.empty()) - _ClientIndexFileName= NLMISC::CFile::getFilenameWithoutExtension(packageName)+".idx"; - - // index file - if (_IndexFileName.empty()) - _IndexFileName= NLMISC::CFile::getFilenameWithoutExtension(_ClientIndexFileName)+".hist"; -} - -void CPackageDescription::storeToPdr(CPersistentDataRecord& pdr) const -{ - pdr.clear(); - store(pdr); -} - -void CPackageDescription::readIndex(CBNPFileSet& packageIndex) const -{ - nlinfo("Reading history file: %s ...",(_RootDirectory+_IndexFileName).c_str()); - - // clear out old contents before reading from input file - packageIndex.clear(); - - // read new contents from input file - if (NLMISC::CFile::fileExists(_RootDirectory+_IndexFileName)) - { - static CPersistentDataRecord pdr; - pdr.clear(); - pdr.readFromTxtFile((_RootDirectory+_IndexFileName).c_str()); - packageIndex.apply(pdr); - } -} - -void CPackageDescription::writeIndex(const CBNPFileSet& packageIndex) const -{ - nlinfo("Writing history file: %s ...",(_RootDirectory+_IndexFileName).c_str()); - - // write contents to output file - static CPersistentDataRecordRyzomStore pdr; - pdr.clear(); - packageIndex.store(pdr); - pdr.writeToTxtFile((_RootDirectory+_IndexFileName).c_str()); -} - -void CPackageDescription::getCategories(CPersistentDataRecord &pdr) const -{ - pdr.clear(); - _Categories.store(pdr); -} - -void CPackageDescription::updateIndexFileList(CBNPFileSet& packageIndex) const -{ - nlinfo("Updating file list from package categories (%d files) ...",_Categories.fileCount()); - for (uint32 i=_Categories.fileCount();i--;) - { - const std::string& fileName= _Categories.getFile(i); - packageIndex.addFile(fileName,_Categories.isFileIncremental(fileName)); - - // if the file is flagged as non-incremental then we need to add its refference file too - if (!_Categories.isFileIncremental(fileName)) - { - std::string refName= NLMISC::CFile::getFilenameWithoutExtension(_Categories.getFile(i))+"_.ref"; - packageIndex.addFile(refName); - - // if the ref file doesn't exist then create it by copying the original - if (NLMISC::CFile::fileExists(_BnpDirectory+fileName) && !NLMISC::CFile::fileExists(_BnpDirectory+refName)) - { - NLMISC::CFile::copyFile(_BnpDirectory+refName,_BnpDirectory+fileName); - nlassert(NLMISC::CFile::getFileSize(_BnpDirectory+refName)== NLMISC::CFile::getFileSize(_BnpDirectory+fileName)); - } - } - } -} - -void CPackageDescription::generateClientIndex(CProductDescriptionForClient& theClientPackage,const CBNPFileSet& packageIndex) const -{ - nlinfo("Generating client index: %s ...",(_PatchDirectory+toString("%05u/", packageIndex.getVersionNumber())+_ClientIndexFileName).c_str()); - - // make sure the version sub directory exist - CFile::createDirectory(_PatchDirectory+toString("%05u/", packageIndex.getVersionNumber())); - - // clear out the client package before we start - theClientPackage.clear(); - - // copy the categories using a pdr record - static CPersistentDataRecordRyzomStore pdr; - pdr.clear(); - _Categories.store(pdr); - theClientPackage.setCategories(pdr); - - // copy the files using a pdr record - pdr.clear(); - packageIndex.store(pdr); - theClientPackage.setFiles(pdr); - - // create the output file - pdr.clear(); - theClientPackage.store(pdr); - - std::string newName = _PatchDirectory + toString("%05u/", packageIndex.getVersionNumber()) + NLMISC::CFile::getFilenameWithoutExtension(_ClientIndexFileName); - newName += NLMISC::toString("_%05u", packageIndex.getVersionNumber()); - - pdr.writeToBinFile((newName+".idx").c_str()); - pdr.writeToTxtFile((newName+"_debug.xml").c_str()); -} - -void CPackageDescription::addVersion(CBNPFileSet& packageIndex) -{ - // calculate the last version number in the index file -// nlinfo("Calculating package version number..."); -// uint32 versionNumber= packageIndex.getVersionNumber(); -// nlinfo("Last version number = %d",versionNumber); -// uint32 newVersionNumber= packageIndex.addVersion(_BnpDirectory,versionNumber+1); -// nlinfo("New version number = %d",newVersionNumber); - - // setup the default next version number by scanning the package index for the highest existing version number - nlinfo("Calculating package version number..."); - _NextVersionNumber= packageIndex.getVersionNumber(); - nlinfo("Last version number = %u",_NextVersionNumber); - ++_NextVersionNumber; - - // have the package index check its file list to see if a new version is required - uint32 newVersionNumber= packageIndex.addVersion(_BnpDirectory,_RefDirectory,*this); - nlinfo("Added files for version: %u",newVersionNumber); -} - -void CPackageDescription::generatePatches(CBNPFileSet& packageIndex) const -{ - nlinfo("Generating patches ..."); - - for (uint32 i=packageIndex.fileCount();i--;) - { - // generate file name root - std::string bnpFileName= _BnpDirectory+packageIndex.getFile(i).getFileName(); - std::string refNameRoot= _RefDirectory+NLMISC::CFile::getFilenameWithoutExtension(bnpFileName); - std::string patchNameRoot= _PatchDirectory+NLMISC::CFile::getFilenameWithoutExtension(bnpFileName); - - // if the file has no versions then skip on to the next file - if (packageIndex.getFile(i).versionCount()==0) - continue; - - // get the last version number and the related file name - const CBNPFileVersion& curVersion= packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-1); - std::string curVersionFileName= refNameRoot+NLMISC::toString("_%05u.%s",curVersion.getVersionNumber(),NLMISC::CFile::getExtension(bnpFileName).c_str()); -// std::string patchFileName= patchNameRoot+NLMISC::toString("_%05d.patch",curVersion.getVersionNumber()); - std::string patchFileName= _PatchDirectory+toString("%05u/",curVersion.getVersionNumber())+NLMISC::CFile::getFilenameWithoutExtension(bnpFileName)+toString("_%05u",curVersion.getVersionNumber())+".patch"; - - // get the second last version number and the related file name - std::string prevVersionFileName; - if (packageIndex.getFile(i).versionCount()==1) - { - prevVersionFileName= tmpnam(NULL); - NLMISC::COFile tmpFile(prevVersionFileName); - tmpFile.close(); - } - else - { - const CBNPFileVersion& prevVersion= packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-2); - prevVersionFileName= refNameRoot+NLMISC::toString("_%05u.%s",prevVersion.getVersionNumber(),NLMISC::CFile::getExtension(bnpFileName).c_str()); - } - std::string refVersionFileName= prevVersionFileName; - - // create the subdirectory for this patch number - string versionSubDir = _PatchDirectory+"/"+toString("%05u/", curVersion.getVersionNumber()); - CFile::createDirectory(versionSubDir); - - // generate the lzma packed version of the bnp if needed (lzma file are slow to generate) - string lzmaFile = versionSubDir+CFile::getFilename(bnpFileName)+".lzma"; - if (!CFile::fileExists(lzmaFile)) - { - // build the lzma compression in a temp file (avoid leaving dirty file if the - // process cannot terminate) - GenerateLZMA(bnpFileName, lzmaFile+".tmp"); - // rename the tmp file - CFile::moveFile(lzmaFile.c_str(), (lzmaFile+".tmp").c_str()); - } - - // store the lzma file size in the descriptor - packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-1).set7ZipFileSize(CFile::getFileSize(lzmaFile)); - - // if we need to generate a new patch then do it and create the new ref file - if (!NLMISC::CFile::fileExists(curVersionFileName)) - { - nlinfo("- Creating patch: %s",patchFileName.c_str()); - - // in the case where we compress against a ref file... - if (!_Categories.isFileIncremental(NLMISC::CFile::getFilename(bnpFileName))) - { - // setup the name of the reference file to patch against - refVersionFileName= _BnpDirectory+NLMISC::CFile::getFilenameWithoutExtension(bnpFileName)+"_.ref"; - - // delete the previous patch - because we only need the latest patch for non-incremental files - std::string lastPatch= _PatchDirectory+NLMISC::CFile::getFilenameWithoutExtension(prevVersionFileName)+".patch"; - if (NLMISC::CFile::fileExists(lastPatch.c_str())) - NLMISC::CFile::deleteFile(lastPatch.c_str()); - } - - // call xdelta to generate the patch - GeneratePatch(refVersionFileName, bnpFileName, patchFileName); - nlassert(NLMISC::CFile::fileExists(patchFileName)); - - uint32 nPatchSize = NLMISC::CFile::getFileSize(patchFileName); - packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-1).setPatchSize(nPatchSize); - - // apply the incremental patch to the old ref file to create the new ref file - // and ensure that the new ref file matches the BNP - ApplyPatch(refVersionFileName, curVersionFileName, patchFileName); - nlassert(NLMISC::CFile::fileExists(curVersionFileName)); - nlassert(NLMISC::CFile::thoroughFileCompare(bnpFileName, curVersionFileName)); - } - - // if we have a ref file still hanging about from the previous patch then delete it - if (NLMISC::CFile::fileExists(prevVersionFileName)) - { - NLMISC::CFile::deleteFile(prevVersionFileName); - } - } -} - -void CPackageDescription::createDirectories() const -{ - NLMISC::CFile::createDirectoryTree(_RootDirectory); - NLMISC::CFile::createDirectoryTree(_PatchDirectory); - NLMISC::CFile::createDirectoryTree(_BnpDirectory); - NLMISC::CFile::createDirectoryTree(_RefDirectory); -} - -void CPackageDescription::buildDefaultFileList() -{ - // make sure the default categories exist - CBNPCategory* packedCategory= _Categories.getCategory("main", true); - packedCategory->setOptional(false); - packedCategory->setIncremental(true); - - CBNPCategory* unpackedCategory= _Categories.getCategory("unpacked", true); - unpackedCategory->setUnpackTo("./"); - unpackedCategory->setOptional(false); - unpackedCategory->setIncremental(false); - - CBNPCategory* optionCategory= _Categories.getCategory("optional", true); - optionCategory->setOptional(true); - optionCategory->setIncremental(true); - - // look for BNP files in the BNP directry and add them to the main category - std::vector fileList; - NLMISC::CPath::getPathContent(_BnpDirectory,false,false,true,fileList); - for (uint32 i=0;i") -{ - if (args.size()!=1) - return false; - - createNewProduct(args[0]); - - return true; -} - -NLMISC_COMMAND(updateProduct,"process a package","") -{ - if (args.size()!=1) - return false; - - updateProduct(args[0]); - - return true; -} - -NLMISC_COMMAND(go,"perform a 'createNewProduct' if required and 'updateProduct' on patch_test/test0/test_package.xml","") -{ - if (args.size()!=0) - return false; - - if (!NLMISC::CFile::fileExists("patch_test/test0/test_package.xml")) - createNewProduct("patch_test/test0/test_package.xml"); - updateProduct("patch_test/test0/test_package.xml"); - - return true; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//----------------------------------------------------------------------------- +// includes +//----------------------------------------------------------------------------- + +#include + +#include "game_share/bnp_patch.h" +#include "nel/misc/path.h" +#include "nel/misc/file.h" +#include "nel/misc/command.h" +#include "nel/misc/sstring.h" +#include "game_share/singleton_registry.h" + +using namespace std; +using namespace NLMISC; + +#define PERSISTENT_TOKEN_FAMILY RyzomTokenFamily + + +//----------------------------------------------------------------------------- +// Handy utility functions +//----------------------------------------------------------------------------- + +void normalisePackageDescriptionFileName(std::string& fileName) +{ + if (fileName.empty()) + fileName="package_description"; + if (NLMISC::CFile::getExtension(fileName).empty() && fileName[fileName.size()-1]!='.') + fileName+=".xml"; +} + +void GeneratePatch(const std::string& srcFileName,const std::string& destFileName,const std::string& patchFileName) +{ + std::string cmd="xdelta delta"; + cmd+=" "+srcFileName+" "+destFileName+" "+patchFileName; + nlinfo("executing system command: %s",cmd.c_str()); +#ifdef NL_OS_WINDOWS + _spawnlp(_P_WAIT, "xdelta.exe","xdelta.exe","delta",srcFileName.c_str(),destFileName.c_str(),patchFileName.c_str(),NULL); +#else // NL_OS_WINDOWS + sint error = system (cmd.c_str()); + if (error) + nlwarning("'%s' failed with error code %d", cmd.c_str(), error); +#endif // NL_OS_WINDOWS +} + +void ApplyPatch(const std::string& srcFileName,const std::string& destFileName,const std::string& patchFileName=std::string()) +{ + std::string cmd="xdelta patch"; + cmd+=" "+patchFileName+" "+srcFileName+" "+destFileName; + nlinfo("executing system command: %s",cmd.c_str()); +#ifdef NL_OS_WINDOWS + _spawnlp(_P_WAIT, "xdelta.exe","xdelta.exe","patch",patchFileName.c_str(),srcFileName.c_str(),destFileName.c_str(),NULL); +#else // NL_OS_WINDOWS + sint error = system (cmd.c_str()); + if (error) + nlwarning("'%s' failed with error code %d", cmd.c_str(), error); +#endif // NL_OS_WINDOWS +} + +void GenerateLZMA(const std::string sourceFile, const std::string &outputFile) +{ + std::string cmd="lzma e "; + cmd+=" "+sourceFile+" "+outputFile; + nlinfo("executing system command: %s",cmd.c_str()); +#ifdef NL_OS_WINDOWS + _spawnlp(_P_WAIT, "lzma.exe","lzma.exe", "e", sourceFile.c_str(), outputFile.c_str(), NULL); +#else // NL_OS_WINDOWS + sint error = system (cmd.c_str()); + if (error) + nlwarning("'%s' failed with error code %d", cmd.c_str(), error); +#endif // NL_OS_WINDOWS +} + + +//----------------------------------------------------------------------------- +// class CPackageDescription +//----------------------------------------------------------------------------- + +class CPackageDescription: public IVersionNumberGenerator +{ +private: + DECLARE_PERSISTENCE_METHODS + +public: + CPackageDescription(); + + void clear(); + + void setup(const std::string& packageName); + void storeToPdr(CPersistentDataRecord& pdr) const; + + void readIndex(CBNPFileSet& packageIndex) const; + void writeIndex(const CBNPFileSet& packageIndex) const; + + void getCategories(CPersistentDataRecord &pdr) const; + + void updateIndexFileList(CBNPFileSet& packageIndex) const; + void generateClientIndex(CProductDescriptionForClient& theClientPackage,const CBNPFileSet& packageIndex) const; + void addVersion(CBNPFileSet& packageIndex); + void generatePatches(CBNPFileSet& packageIndex) const; + void createDirectories() const; + void buildDefaultFileList(); + + void updatePatchSizes(CBNPFileSet& packageIndex) const; + + // specialisation of IVersionNumberGenerator + void grabVersionNumber(); + uint32 getPackageVersionNumber(); + +private: + CBNPCategorySet _Categories; + std::string _IndexFileName; + std::string _ClientIndexFileName; + std::string _RootDirectory; + std::string _PatchDirectory; + std::string _BnpDirectory; + std::string _RefDirectory; + std::string _NextVersionFile; + + uint32 _NextVersionNumber; + bool _VersionNumberReserved; +}; + + +//----------------------------------------------------------------------------- +// methods CPackageDescription +//----------------------------------------------------------------------------- + +CPackageDescription::CPackageDescription() +{ + clear(); +} + +void CPackageDescription::clear() +{ + _NextVersionNumber= ~0u; + _VersionNumberReserved = false; + _Categories.clear(); + _IndexFileName.clear(); + _ClientIndexFileName.clear(); + _PatchDirectory.clear(); + _BnpDirectory.clear(); + _RefDirectory.clear(); +} + +void CPackageDescription::setup(const std::string& packageName) +{ + nlinfo("Reading package description: %s ...",packageName.c_str()); + + // clear out old contents before reading from input file + clear(); + + // read new contents from input file + static CPersistentDataRecord pdr; + pdr.clear(); + pdr.readFromTxtFile(packageName.c_str()); + apply(pdr); + + // root directory + if (_RootDirectory.empty()) + _RootDirectory= NLMISC::CFile::getPath(packageName); + _RootDirectory= NLMISC::CPath::standardizePath(_RootDirectory,true); + + // patch directory + if (_PatchDirectory.empty()) + _PatchDirectory= _RootDirectory+"patch"; + _PatchDirectory= NLMISC::CPath::standardizePath(_PatchDirectory,true); + + // BNP directory + if (_BnpDirectory.empty()) + _BnpDirectory= _RootDirectory+"bnp"; + _BnpDirectory= NLMISC::CPath::standardizePath(_BnpDirectory,true); + + // ref directory + if (_RefDirectory.empty()) + _RefDirectory= _RootDirectory+"ref"; + _RefDirectory= NLMISC::CPath::standardizePath(_RefDirectory,true); + + // client index file + if (_ClientIndexFileName.empty()) + _ClientIndexFileName= NLMISC::CFile::getFilenameWithoutExtension(packageName)+".idx"; + + // index file + if (_IndexFileName.empty()) + _IndexFileName= NLMISC::CFile::getFilenameWithoutExtension(_ClientIndexFileName)+".hist"; +} + +void CPackageDescription::storeToPdr(CPersistentDataRecord& pdr) const +{ + pdr.clear(); + store(pdr); +} + +void CPackageDescription::readIndex(CBNPFileSet& packageIndex) const +{ + nlinfo("Reading history file: %s ...",(_RootDirectory+_IndexFileName).c_str()); + + // clear out old contents before reading from input file + packageIndex.clear(); + + // read new contents from input file + if (NLMISC::CFile::fileExists(_RootDirectory+_IndexFileName)) + { + static CPersistentDataRecord pdr; + pdr.clear(); + pdr.readFromTxtFile((_RootDirectory+_IndexFileName).c_str()); + packageIndex.apply(pdr); + } +} + +void CPackageDescription::writeIndex(const CBNPFileSet& packageIndex) const +{ + nlinfo("Writing history file: %s ...",(_RootDirectory+_IndexFileName).c_str()); + + // write contents to output file + static CPersistentDataRecordRyzomStore pdr; + pdr.clear(); + packageIndex.store(pdr); + pdr.writeToTxtFile((_RootDirectory+_IndexFileName).c_str()); +} + +void CPackageDescription::getCategories(CPersistentDataRecord &pdr) const +{ + pdr.clear(); + _Categories.store(pdr); +} + +void CPackageDescription::updateIndexFileList(CBNPFileSet& packageIndex) const +{ + nlinfo("Updating file list from package categories (%d files) ...",_Categories.fileCount()); + for (uint32 i=_Categories.fileCount();i--;) + { + const std::string& fileName= _Categories.getFile(i); + packageIndex.addFile(fileName,_Categories.isFileIncremental(fileName)); + + // if the file is flagged as non-incremental then we need to add its refference file too + if (!_Categories.isFileIncremental(fileName)) + { + std::string refName= NLMISC::CFile::getFilenameWithoutExtension(_Categories.getFile(i))+"_.ref"; + packageIndex.addFile(refName); + + // if the ref file doesn't exist then create it by copying the original + if (NLMISC::CFile::fileExists(_BnpDirectory+fileName) && !NLMISC::CFile::fileExists(_BnpDirectory+refName)) + { + NLMISC::CFile::copyFile(_BnpDirectory+refName,_BnpDirectory+fileName); + nlassert(NLMISC::CFile::getFileSize(_BnpDirectory+refName)== NLMISC::CFile::getFileSize(_BnpDirectory+fileName)); + } + } + } +} + +void CPackageDescription::generateClientIndex(CProductDescriptionForClient& theClientPackage,const CBNPFileSet& packageIndex) const +{ + nlinfo("Generating client index: %s ...",(_PatchDirectory+toString("%05u/", packageIndex.getVersionNumber())+_ClientIndexFileName).c_str()); + + // make sure the version sub directory exist + CFile::createDirectory(_PatchDirectory+toString("%05u/", packageIndex.getVersionNumber())); + + // clear out the client package before we start + theClientPackage.clear(); + + // copy the categories using a pdr record + static CPersistentDataRecordRyzomStore pdr; + pdr.clear(); + _Categories.store(pdr); + theClientPackage.setCategories(pdr); + + // copy the files using a pdr record + pdr.clear(); + packageIndex.store(pdr); + theClientPackage.setFiles(pdr); + + // create the output file + pdr.clear(); + theClientPackage.store(pdr); + + std::string newName = _PatchDirectory + toString("%05u/", packageIndex.getVersionNumber()) + NLMISC::CFile::getFilenameWithoutExtension(_ClientIndexFileName); + newName += NLMISC::toString("_%05u", packageIndex.getVersionNumber()); + + pdr.writeToBinFile((newName+".idx").c_str()); + pdr.writeToTxtFile((newName+"_debug.xml").c_str()); +} + +void CPackageDescription::addVersion(CBNPFileSet& packageIndex) +{ + // calculate the last version number in the index file +// nlinfo("Calculating package version number..."); +// uint32 versionNumber= packageIndex.getVersionNumber(); +// nlinfo("Last version number = %d",versionNumber); +// uint32 newVersionNumber= packageIndex.addVersion(_BnpDirectory,versionNumber+1); +// nlinfo("New version number = %d",newVersionNumber); + + // setup the default next version number by scanning the package index for the highest existing version number + nlinfo("Calculating package version number..."); + _NextVersionNumber= packageIndex.getVersionNumber(); + nlinfo("Last version number = %u",_NextVersionNumber); + ++_NextVersionNumber; + + // have the package index check its file list to see if a new version is required + uint32 newVersionNumber= packageIndex.addVersion(_BnpDirectory,_RefDirectory,*this); + nlinfo("Added files for version: %u",newVersionNumber); +} + +void CPackageDescription::generatePatches(CBNPFileSet& packageIndex) const +{ + nlinfo("Generating patches ..."); + + for (uint32 i=packageIndex.fileCount();i--;) + { + // generate file name root + std::string bnpFileName= _BnpDirectory+packageIndex.getFile(i).getFileName(); + std::string refNameRoot= _RefDirectory+NLMISC::CFile::getFilenameWithoutExtension(bnpFileName); + std::string patchNameRoot= _PatchDirectory+NLMISC::CFile::getFilenameWithoutExtension(bnpFileName); + + // if the file has no versions then skip on to the next file + if (packageIndex.getFile(i).versionCount()==0) + continue; + + // get the last version number and the related file name + const CBNPFileVersion& curVersion= packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-1); + std::string curVersionFileName= refNameRoot+NLMISC::toString("_%05u.%s",curVersion.getVersionNumber(),NLMISC::CFile::getExtension(bnpFileName).c_str()); +// std::string patchFileName= patchNameRoot+NLMISC::toString("_%05d.patch",curVersion.getVersionNumber()); + std::string patchFileName= _PatchDirectory+toString("%05u/",curVersion.getVersionNumber())+NLMISC::CFile::getFilenameWithoutExtension(bnpFileName)+toString("_%05u",curVersion.getVersionNumber())+".patch"; + + // get the second last version number and the related file name + std::string prevVersionFileName; + if (packageIndex.getFile(i).versionCount()==1) + { + prevVersionFileName= tmpnam(NULL); + NLMISC::COFile tmpFile(prevVersionFileName); + tmpFile.close(); + } + else + { + const CBNPFileVersion& prevVersion= packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-2); + prevVersionFileName= refNameRoot+NLMISC::toString("_%05u.%s",prevVersion.getVersionNumber(),NLMISC::CFile::getExtension(bnpFileName).c_str()); + } + std::string refVersionFileName= prevVersionFileName; + + // create the subdirectory for this patch number + string versionSubDir = _PatchDirectory+"/"+toString("%05u/", curVersion.getVersionNumber()); + CFile::createDirectory(versionSubDir); + + // generate the lzma packed version of the bnp if needed (lzma file are slow to generate) + string lzmaFile = versionSubDir+CFile::getFilename(bnpFileName)+".lzma"; + if (!CFile::fileExists(lzmaFile)) + { + // build the lzma compression in a temp file (avoid leaving dirty file if the + // process cannot terminate) + GenerateLZMA(bnpFileName, lzmaFile+".tmp"); + // rename the tmp file + CFile::moveFile(lzmaFile.c_str(), (lzmaFile+".tmp").c_str()); + } + + // store the lzma file size in the descriptor + packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-1).set7ZipFileSize(CFile::getFileSize(lzmaFile)); + + // if we need to generate a new patch then do it and create the new ref file + if (!NLMISC::CFile::fileExists(curVersionFileName)) + { + nlinfo("- Creating patch: %s",patchFileName.c_str()); + + // in the case where we compress against a ref file... + if (!_Categories.isFileIncremental(NLMISC::CFile::getFilename(bnpFileName))) + { + // setup the name of the reference file to patch against + refVersionFileName= _BnpDirectory+NLMISC::CFile::getFilenameWithoutExtension(bnpFileName)+"_.ref"; + + // delete the previous patch - because we only need the latest patch for non-incremental files + std::string lastPatch= _PatchDirectory+NLMISC::CFile::getFilenameWithoutExtension(prevVersionFileName)+".patch"; + if (NLMISC::CFile::fileExists(lastPatch.c_str())) + NLMISC::CFile::deleteFile(lastPatch.c_str()); + } + + // call xdelta to generate the patch + GeneratePatch(refVersionFileName, bnpFileName, patchFileName); + nlassert(NLMISC::CFile::fileExists(patchFileName)); + + uint32 nPatchSize = NLMISC::CFile::getFileSize(patchFileName); + packageIndex.getFile(i).getVersion(packageIndex.getFile(i).versionCount()-1).setPatchSize(nPatchSize); + + // apply the incremental patch to the old ref file to create the new ref file + // and ensure that the new ref file matches the BNP + ApplyPatch(refVersionFileName, curVersionFileName, patchFileName); + nlassert(NLMISC::CFile::fileExists(curVersionFileName)); + nlassert(NLMISC::CFile::thoroughFileCompare(bnpFileName, curVersionFileName)); + } + + // if we have a ref file still hanging about from the previous patch then delete it + if (NLMISC::CFile::fileExists(prevVersionFileName)) + { + NLMISC::CFile::deleteFile(prevVersionFileName); + } + } +} + +void CPackageDescription::createDirectories() const +{ + NLMISC::CFile::createDirectoryTree(_RootDirectory); + NLMISC::CFile::createDirectoryTree(_PatchDirectory); + NLMISC::CFile::createDirectoryTree(_BnpDirectory); + NLMISC::CFile::createDirectoryTree(_RefDirectory); +} + +void CPackageDescription::buildDefaultFileList() +{ + // make sure the default categories exist + CBNPCategory* packedCategory= _Categories.getCategory("main", true); + packedCategory->setOptional(false); + packedCategory->setIncremental(true); + + CBNPCategory* unpackedCategory= _Categories.getCategory("unpacked", true); + unpackedCategory->setUnpackTo("./"); + unpackedCategory->setOptional(false); + unpackedCategory->setIncremental(false); + + CBNPCategory* optionCategory= _Categories.getCategory("optional", true); + optionCategory->setOptional(true); + optionCategory->setIncremental(true); + + // look for BNP files in the BNP directry and add them to the main category + std::vector fileList; + NLMISC::CPath::getPathContent(_BnpDirectory,false,false,true,fileList); + for (uint32 i=0;i") +{ + if (args.size()!=1) + return false; + + createNewProduct(args[0]); + + return true; +} + +NLMISC_COMMAND(updateProduct,"process a package","") +{ + if (args.size()!=1) + return false; + + updateProduct(args[0]); + + return true; +} + +NLMISC_COMMAND(go,"perform a 'createNewProduct' if required and 'updateProduct' on patch_test/test0/test_package.xml","") +{ + if (args.size()!=0) + return false; + + if (!NLMISC::CFile::fileExists("patch_test/test0/test_package.xml")) + createNewProduct("patch_test/test0/test_package.xml"); + updateProduct("patch_test/test0/test_package.xml"); + + return true; +} diff --git a/code/ryzom/tools/patch_gen/patch_gen_main.cpp b/code/ryzom/tools/patch_gen/patch_gen_main.cpp index 80517a673..bc2e6bf66 100644 --- a/code/ryzom/tools/patch_gen/patch_gen_main.cpp +++ b/code/ryzom/tools/patch_gen/patch_gen_main.cpp @@ -1,58 +1,58 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/misc/debug.h" -#include "nel/misc/command.h" -#include "nel/misc/sstring.h" -//#include "game_share/handy_commands.h" - -//----------------------------------------------- -// MAIN -//----------------------------------------------- -int main(int argc,char** argv) -{ - NLMISC::createDebug(); - - // if there are no command line args then display a friendly message and exit - if (argc==1) - { - NLMISC::InfoLog->displayNL("SYNTAX: %s ",argv[0]); - NLMISC::InfoLog->displayNL(""); - NLMISC::InfoLog->displayNL("For a list of valid commands and their paramaters try: %s help",argv[0]); - NLMISC::InfoLog->displayNL(""); - return 0; - } - - // build the command line by concatnating input arguments (separating with spaces) - NLMISC::CSString commandline; - for (int i=1;i1) - commandline+=' '; - commandline+= s; - } - - // have NeL treat the command - NLMISC::ICommand::execute(commandline, *NLMISC::InfoLog); - - return 0; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/misc/debug.h" +#include "nel/misc/command.h" +#include "nel/misc/sstring.h" +//#include "game_share/handy_commands.h" + +//----------------------------------------------- +// MAIN +//----------------------------------------------- +int main(int argc,char** argv) +{ + NLMISC::createDebug(); + + // if there are no command line args then display a friendly message and exit + if (argc==1) + { + NLMISC::InfoLog->displayNL("SYNTAX: %s ",argv[0]); + NLMISC::InfoLog->displayNL(""); + NLMISC::InfoLog->displayNL("For a list of valid commands and their paramaters try: %s help",argv[0]); + NLMISC::InfoLog->displayNL(""); + return 0; + } + + // build the command line by concatnating input arguments (separating with spaces) + NLMISC::CSString commandline; + for (int i=1;i1) + commandline+=' '; + commandline+= s; + } + + // have NeL treat the command + NLMISC::ICommand::execute(commandline, *NLMISC::InfoLog); + + return 0; +} diff --git a/code/ryzom/tools/patch_gen/patch_gen_main.h b/code/ryzom/tools/patch_gen/patch_gen_main.h index c6ad3e746..6bb2c9508 100644 --- a/code/ryzom/tools/patch_gen/patch_gen_main.h +++ b/code/ryzom/tools/patch_gen/patch_gen_main.h @@ -1,20 +1,20 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef PATCH_GEN_MAIN_H -#define PATCH_GEN_MAIN_H - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef PATCH_GEN_MAIN_H +#define PATCH_GEN_MAIN_H + +#endif diff --git a/code/ryzom/tools/patch_gen/patch_gen_service.cpp b/code/ryzom/tools/patch_gen/patch_gen_service.cpp index 063482fd0..b5f2c1ae2 100644 --- a/code/ryzom/tools/patch_gen/patch_gen_service.cpp +++ b/code/ryzom/tools/patch_gen/patch_gen_service.cpp @@ -1,67 +1,67 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/misc/command.h" -#include "nel/misc/variable.h" -#include "nel/misc/common.h" -#include "nel/misc/file.h" - -#include "game_share/ryzom_version.h" -#include "game_share/tick_event_handler.h" -#include "game_share/singleton_registry.h" - -#include "patch_gen_service.h" - -#ifdef NL_OS_WINDOWS -# define NOMINMAX -# include -#endif // NL_OS_WINDOWS - -using namespace std; -using namespace NLMISC; -using namespace NLNET; - - -/* - * Initialise the service - */ -void CPatchGenService::init() -{ - setVersion (RYZOM_VERSION); - CSingletonRegistry::getInstance()->init(); -} - -/* - * Service Update - */ -bool CPatchGenService::update() -{ - CSingletonRegistry::getInstance()->serviceUpdate(); - return true; -} - -/* - * Release - */ -void CPatchGenService::release() -{ - CSingletonRegistry::getInstance()->release(); -} - -//----------------------------------------------- -// NLNET_SERVICE_MAIN -//----------------------------------------------- -NLNET_SERVICE_MAIN( CPatchGenService, "PGS", "patch_gen_service", 0, EmptyCallbackArray, "", "" ); +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/misc/command.h" +#include "nel/misc/variable.h" +#include "nel/misc/common.h" +#include "nel/misc/file.h" + +#include "game_share/ryzom_version.h" +#include "game_share/tick_event_handler.h" +#include "game_share/singleton_registry.h" + +#include "patch_gen_service.h" + +#ifdef NL_OS_WINDOWS +# define NOMINMAX +# include +#endif // NL_OS_WINDOWS + +using namespace std; +using namespace NLMISC; +using namespace NLNET; + + +/* + * Initialise the service + */ +void CPatchGenService::init() +{ + setVersion (RYZOM_VERSION); + CSingletonRegistry::getInstance()->init(); +} + +/* + * Service Update + */ +bool CPatchGenService::update() +{ + CSingletonRegistry::getInstance()->serviceUpdate(); + return true; +} + +/* + * Release + */ +void CPatchGenService::release() +{ + CSingletonRegistry::getInstance()->release(); +} + +//----------------------------------------------- +// NLNET_SERVICE_MAIN +//----------------------------------------------- +NLNET_SERVICE_MAIN( CPatchGenService, "PGS", "patch_gen_service", 0, EmptyCallbackArray, "", "" ); diff --git a/code/ryzom/tools/patch_gen/patch_gen_service.h b/code/ryzom/tools/patch_gen/patch_gen_service.h index 52430d23d..7a5c184da 100644 --- a/code/ryzom/tools/patch_gen/patch_gen_service.h +++ b/code/ryzom/tools/patch_gen/patch_gen_service.h @@ -1,44 +1,44 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef PATCH_GEN_SERVICE_H -#define PATCH_GEN_SERVICE_H - -#include "nel/misc/types_nl.h" -#include "nel/misc/time_nl.h" -#include "nel/misc/common.h" - -#include "nel/net/service.h" - -class CPatchGenService : public NLNET::IService -{ -public : - - /// Initialise the service - void init(); - - /// Update - bool update(); - - /// Tick Update - static void tickUpdate(); - - /// Release - void release(); -}; - - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef PATCH_GEN_SERVICE_H +#define PATCH_GEN_SERVICE_H + +#include "nel/misc/types_nl.h" +#include "nel/misc/time_nl.h" +#include "nel/misc/common.h" + +#include "nel/net/service.h" + +class CPatchGenService : public NLNET::IService +{ +public : + + /// Initialise the service + void init(); + + /// Update + bool update(); + + /// Tick Update + static void tickUpdate(); + + /// Release + void release(); +}; + + +#endif diff --git a/code/ryzom/tools/pd_parser/cpp_output.h b/code/ryzom/tools/pd_parser/cpp_output.h index 14ca586d9..f8ed9c6f8 100644 --- a/code/ryzom/tools/pd_parser/cpp_output.h +++ b/code/ryzom/tools/pd_parser/cpp_output.h @@ -1,931 +1,931 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef RY_PD_CPP_OUTPUT_H -#define RY_PD_CPP_OUTPUT_H - -#include -#include -#include -#include -#include - -#include - -inline std::string lcFirst(std::string str) -{ - if (!str.empty() && str[0]>='A' && str[0]<='Z') - str[0] += 'a'-'A'; - return str; -} - -inline std::string padTab(std::string str, uint sz) -{ - uint i; - uint csize = 0; - - for (i=0; i Methods; - std::string DisplayName; - std::string Description; - std::string Other; - }; - - class SMethodId - { - public: - SMethodId(sint section=-1, sint method=-1, CClassGenerator *generator=NULL) : Section(section), Method(method), Generator(generator) {} - - sint Section; - sint Method; - CClassGenerator *Generator; - - void add(const std::string &instruction); - void setDescription(const std::string &description); - - }; - - /// name - std::string Name; - - /// - std::string Inherit; - - /// sections - std::vector Sections; - - /// in body - std::string Body; - - /// - sint CurrentSection; - - /// - SMethodId CurrentMethod; - - /// - bool StartInline; - - void init(const std::string &name) - { - clear(); - Name = name; - } - - void clear() - { - Name.clear(); - Sections.clear(); - Body.clear(); - Inherit.clear(); - CurrentSection = -1; - } - - - void setSection(const std::string &name) - { - uint i; - for (i=0; i - CCppOutput & operator << (const T& t) - { - addToStream(NLMISC::toString(t).c_str()); - return *this; - } - - /// file description - void setFileHeader(const std::string& filename, const std::string& description) - { - if (_Clean) - { - *this << "/** \\file " << filename << "\n"; - if (!description.empty()) - *this << description << "\n"; - *this << "\n"; - *this << "$Id: cpp_output.h,v 1.15 2004/12/13 17:19:01 legros Exp $\n"; - *this << "*/\n\n"; - } - } - - - -private: - - bool _CppMode; - bool _XmlMode; - bool _NewLine; - sint _Indent; - std::string _Buffer; - bool _DescriptionMode; - bool _Clean; - - std::vector _XmlNodes; - bool _XmlInNode; - bool _XmlLastSlash; - bool _XmlGetNodeName; - bool _XmlCloseNode; - bool _XmlRootNode; - std::string _XmlNodeName; - - /// Stream operator - CCppOutput addToStream (const char* str) - { - _Clean = false; - if (_CppMode) - { - while (*str != '\0') - { - if (!_DescriptionMode && *str == '}') - unindent(); - - bool triggerDescriptionStart = false; - bool triggerDescriptionEnd = false; - - if (!strncmp(str, "/**", 3)) - { - // start description - triggerDescriptionStart = true; - } - - if (_DescriptionMode && !strncmp(str, "*/", 2)) - { - // stop description - triggerDescriptionEnd = true; - } - - bool skipChar = false; - if (*str != '\r') - { - if (_NewLine) - { - if ((*str == ' ' || *str == '\t') && !_DescriptionMode) - { - skipChar = true; - } - else - { - sint i; - for (i=0; i<_Indent; ++i) - _Buffer += '\t'; - _NewLine = false; - - if (_DescriptionMode) - { - _Buffer += " "; - if (!triggerDescriptionEnd) - _Buffer += "* "; - - if (!triggerDescriptionEnd && *str == '*') - { - - skipChar = true; - } - } - } - } - - if (!_DescriptionMode && *str == '{') - indent(); - } - - if (*str == '\n') - { - _NewLine = true; - } - - if (!skipChar) - _Buffer += *str; - - if (triggerDescriptionStart) - _DescriptionMode = true; - if (triggerDescriptionEnd) - _DescriptionMode = false; - - ++str; - } - } - else if (_XmlMode) - { - while (*str != '\0') - { - bool skipChar = false; - bool requireIndent = false; - - if (*str == '<') - { - // - _XmlCloseNode = (str[1] == '/'); - _XmlRootNode = (str[1] == '?'); - _XmlInNode = true; - _XmlGetNodeName = true; - _XmlNodeName.clear(); - - requireIndent = (!_XmlCloseNode && !_XmlRootNode); - if (_XmlCloseNode) - unindent(); - } - else if (*str == '>') - { - _XmlInNode = false; - - if (!_XmlCloseNode && !_XmlRootNode) - { - _XmlNodes.push_back(_XmlNodeName); - } - - if (_XmlCloseNode || _XmlLastSlash) - { - if (_XmlLastSlash) - unindent(); - - nlassert(!_XmlNodes.empty() && _XmlNodes.back() == _XmlNodeName); - _XmlNodes.pop_back(); - } - } - else if (*str == '\n') - { - _NewLine = true; - } - - if (_NewLine) - { - if (*str == ' ' || *str == '\t') - { - skipChar = true; - } - else if (*str != '\n' && *str != '\r') - { - sint i; - for (i=0; i<_Indent; ++i) - _Buffer += '\t'; - _NewLine = false; - } - } - - _XmlLastSlash = (*str == '/'); - - if (_XmlInNode && _XmlGetNodeName && *str != '/' && *str != '<') - { - if (!isalpha(*str)) - _XmlGetNodeName = false; - - if (_XmlGetNodeName) - _XmlNodeName += *str; - } - - if (!skipChar) - _Buffer += *str; - - ++str; - - if (requireIndent) - indent(); - } - } - else - { - _Buffer += str; - } - - return *this; - } - -}; - -// -// Inline implementation -// - -inline void CCppOutput::clear() -{ - _Buffer.clear(); -} - -inline bool searchForId(char* buffer, char** start, char** end) -{ - const char* id = "$Id:"; - uint len = (uint)strlen(id); - for (; *buffer != '\0'; ++buffer) - { - if (strncmp(buffer, id, len) == 0) - { - *start = buffer; - *end = buffer+1; - while (**end != '\0' && **end != '$') - ++(*end); - if (**end != (char)'$') - return false; - - ++(*end); - return true; - } - } - - return false; -} - -inline void CCppOutput::flush(const std::string &fileName) -{ - NLMISC::COFile f; - - bool overwrite = true; - - if (NLMISC::CFile::fileExists(fileName)) - { - NLMISC::CIFile fi; - if (fi.open(fileName)) - { - std::string buffer; - buffer.resize(fi.getFileSize(), '*'); - fi.serialBuffer((uint8*)(&(buffer[0])), fi.getFileSize()); - - // search for $Id: cpp_output.h,v 1.15 2004/12/13 17:19:01 legros Exp $ string in file... - char *searchidstart, *searchidend; - char *replaceidstart, *replaceidend; - - if (searchForId(&(buffer[0]), &replaceidstart, &replaceidend) && - searchForId(&(_Buffer[0]), &searchidstart, &searchidend)) - { - std::string replace = std::string(replaceidstart, replaceidend-replaceidstart); - std::string search = std::string(searchidstart, searchidend-searchidstart); - NLMISC::strFindReplace(_Buffer, search, replace); - } - - overwrite = (buffer != _Buffer); - } - } - - if (overwrite) - { - if (f.open(fileName)) - { - f.serialBuffer((uint8*)(_Buffer.c_str()), (uint)_Buffer.size()); - f.close(); - } - else - { - nlwarning("Unable to open file '%s' for output", fileName.c_str()); - } - } - else - { - nldebug("File '%s' did not changed, skipped", fileName.c_str()); - } - - clear(); -} - -inline void CCppOutput::indent() -{ - ++_Indent; -} - - -inline void CCppOutput::unindent() -{ - --_Indent; - if (_Indent < 0) - _Indent = 0; -} - - - - - - -inline void CClassGenerator::flush(CCppOutput &hFile, CCppOutput &cppFile, CCppOutput &hInlineFile) -{ - hFile << "class " << Name; - if (!Inherit.empty()) - hFile << " : " << Inherit; - hFile << "\n{\n"; - - hInlineFile << "/* -----------------------------------------\n"; - hInlineFile << " * Inline implementation of " << Name << "\n"; - hInlineFile << " * ----------------------------------------- */\n"; - - cppFile << "/* -----------------------------------------\n"; - cppFile << " * Static Implementation of " << Name << "\n"; - cppFile << " * ----------------------------------------- */\n"; - - uint i; - for (i=0; iadd(instruction, *this); -} - -inline void CClassGenerator::SMethodId::setDescription(const std::string &description) -{ - nlassert(Generator != NULL); - Generator->add(description, *this); -} - -inline void CFunctionGenerator::flush(CCppOutput &hFile, CCppOutput &cppFile, CCppOutput &hInlineFile) -{ - std::string inlinekw = (IsInline ? std::string("inline ") : std::string("")); - - if (!Description.empty()) - { - hFile << "\n/**\n" << Description << "\n*/\n"; - } - - hFile << padTab(Type, 32) << lcFirst(Name) << "(" << Proto << ");\n"; - - if (IsInline) - { - hInlineFile << padTab(inlinekw+Type, 32) << lcFirst(Name) << "(" << removeDefaultArgs(Proto) << ")\n"; - hInlineFile << "{\n"; - hInlineFile << Body; - hInlineFile << "}\n\n"; - } - else - { - cppFile << padTab(Type, 32) << lcFirst(Name) << "(" << removeDefaultArgs(Proto) << ")\n"; - cppFile << "{\n"; - cppFile << Body; - cppFile << "}\n\n"; - } -} - - - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef RY_PD_CPP_OUTPUT_H +#define RY_PD_CPP_OUTPUT_H + +#include +#include +#include +#include +#include + +#include + +inline std::string lcFirst(std::string str) +{ + if (!str.empty() && str[0]>='A' && str[0]<='Z') + str[0] += 'a'-'A'; + return str; +} + +inline std::string padTab(std::string str, uint sz) +{ + uint i; + uint csize = 0; + + for (i=0; i Methods; + std::string DisplayName; + std::string Description; + std::string Other; + }; + + class SMethodId + { + public: + SMethodId(sint section=-1, sint method=-1, CClassGenerator *generator=NULL) : Section(section), Method(method), Generator(generator) {} + + sint Section; + sint Method; + CClassGenerator *Generator; + + void add(const std::string &instruction); + void setDescription(const std::string &description); + + }; + + /// name + std::string Name; + + /// + std::string Inherit; + + /// sections + std::vector Sections; + + /// in body + std::string Body; + + /// + sint CurrentSection; + + /// + SMethodId CurrentMethod; + + /// + bool StartInline; + + void init(const std::string &name) + { + clear(); + Name = name; + } + + void clear() + { + Name.clear(); + Sections.clear(); + Body.clear(); + Inherit.clear(); + CurrentSection = -1; + } + + + void setSection(const std::string &name) + { + uint i; + for (i=0; i + CCppOutput & operator << (const T& t) + { + addToStream(NLMISC::toString(t).c_str()); + return *this; + } + + /// file description + void setFileHeader(const std::string& filename, const std::string& description) + { + if (_Clean) + { + *this << "/** \\file " << filename << "\n"; + if (!description.empty()) + *this << description << "\n"; + *this << "\n"; + *this << "$Id: cpp_output.h,v 1.15 2004/12/13 17:19:01 legros Exp $\n"; + *this << "*/\n\n"; + } + } + + + +private: + + bool _CppMode; + bool _XmlMode; + bool _NewLine; + sint _Indent; + std::string _Buffer; + bool _DescriptionMode; + bool _Clean; + + std::vector _XmlNodes; + bool _XmlInNode; + bool _XmlLastSlash; + bool _XmlGetNodeName; + bool _XmlCloseNode; + bool _XmlRootNode; + std::string _XmlNodeName; + + /// Stream operator + CCppOutput addToStream (const char* str) + { + _Clean = false; + if (_CppMode) + { + while (*str != '\0') + { + if (!_DescriptionMode && *str == '}') + unindent(); + + bool triggerDescriptionStart = false; + bool triggerDescriptionEnd = false; + + if (!strncmp(str, "/**", 3)) + { + // start description + triggerDescriptionStart = true; + } + + if (_DescriptionMode && !strncmp(str, "*/", 2)) + { + // stop description + triggerDescriptionEnd = true; + } + + bool skipChar = false; + if (*str != '\r') + { + if (_NewLine) + { + if ((*str == ' ' || *str == '\t') && !_DescriptionMode) + { + skipChar = true; + } + else + { + sint i; + for (i=0; i<_Indent; ++i) + _Buffer += '\t'; + _NewLine = false; + + if (_DescriptionMode) + { + _Buffer += " "; + if (!triggerDescriptionEnd) + _Buffer += "* "; + + if (!triggerDescriptionEnd && *str == '*') + { + + skipChar = true; + } + } + } + } + + if (!_DescriptionMode && *str == '{') + indent(); + } + + if (*str == '\n') + { + _NewLine = true; + } + + if (!skipChar) + _Buffer += *str; + + if (triggerDescriptionStart) + _DescriptionMode = true; + if (triggerDescriptionEnd) + _DescriptionMode = false; + + ++str; + } + } + else if (_XmlMode) + { + while (*str != '\0') + { + bool skipChar = false; + bool requireIndent = false; + + if (*str == '<') + { + // + _XmlCloseNode = (str[1] == '/'); + _XmlRootNode = (str[1] == '?'); + _XmlInNode = true; + _XmlGetNodeName = true; + _XmlNodeName.clear(); + + requireIndent = (!_XmlCloseNode && !_XmlRootNode); + if (_XmlCloseNode) + unindent(); + } + else if (*str == '>') + { + _XmlInNode = false; + + if (!_XmlCloseNode && !_XmlRootNode) + { + _XmlNodes.push_back(_XmlNodeName); + } + + if (_XmlCloseNode || _XmlLastSlash) + { + if (_XmlLastSlash) + unindent(); + + nlassert(!_XmlNodes.empty() && _XmlNodes.back() == _XmlNodeName); + _XmlNodes.pop_back(); + } + } + else if (*str == '\n') + { + _NewLine = true; + } + + if (_NewLine) + { + if (*str == ' ' || *str == '\t') + { + skipChar = true; + } + else if (*str != '\n' && *str != '\r') + { + sint i; + for (i=0; i<_Indent; ++i) + _Buffer += '\t'; + _NewLine = false; + } + } + + _XmlLastSlash = (*str == '/'); + + if (_XmlInNode && _XmlGetNodeName && *str != '/' && *str != '<') + { + if (!isalpha(*str)) + _XmlGetNodeName = false; + + if (_XmlGetNodeName) + _XmlNodeName += *str; + } + + if (!skipChar) + _Buffer += *str; + + ++str; + + if (requireIndent) + indent(); + } + } + else + { + _Buffer += str; + } + + return *this; + } + +}; + +// +// Inline implementation +// + +inline void CCppOutput::clear() +{ + _Buffer.clear(); +} + +inline bool searchForId(char* buffer, char** start, char** end) +{ + const char* id = "$Id:"; + uint len = (uint)strlen(id); + for (; *buffer != '\0'; ++buffer) + { + if (strncmp(buffer, id, len) == 0) + { + *start = buffer; + *end = buffer+1; + while (**end != '\0' && **end != '$') + ++(*end); + if (**end != (char)'$') + return false; + + ++(*end); + return true; + } + } + + return false; +} + +inline void CCppOutput::flush(const std::string &fileName) +{ + NLMISC::COFile f; + + bool overwrite = true; + + if (NLMISC::CFile::fileExists(fileName)) + { + NLMISC::CIFile fi; + if (fi.open(fileName)) + { + std::string buffer; + buffer.resize(fi.getFileSize(), '*'); + fi.serialBuffer((uint8*)(&(buffer[0])), fi.getFileSize()); + + // search for $Id: cpp_output.h,v 1.15 2004/12/13 17:19:01 legros Exp $ string in file... + char *searchidstart, *searchidend; + char *replaceidstart, *replaceidend; + + if (searchForId(&(buffer[0]), &replaceidstart, &replaceidend) && + searchForId(&(_Buffer[0]), &searchidstart, &searchidend)) + { + std::string replace = std::string(replaceidstart, replaceidend-replaceidstart); + std::string search = std::string(searchidstart, searchidend-searchidstart); + NLMISC::strFindReplace(_Buffer, search, replace); + } + + overwrite = (buffer != _Buffer); + } + } + + if (overwrite) + { + if (f.open(fileName)) + { + f.serialBuffer((uint8*)(_Buffer.c_str()), (uint)_Buffer.size()); + f.close(); + } + else + { + nlwarning("Unable to open file '%s' for output", fileName.c_str()); + } + } + else + { + nldebug("File '%s' did not changed, skipped", fileName.c_str()); + } + + clear(); +} + +inline void CCppOutput::indent() +{ + ++_Indent; +} + + +inline void CCppOutput::unindent() +{ + --_Indent; + if (_Indent < 0) + _Indent = 0; +} + + + + + + +inline void CClassGenerator::flush(CCppOutput &hFile, CCppOutput &cppFile, CCppOutput &hInlineFile) +{ + hFile << "class " << Name; + if (!Inherit.empty()) + hFile << " : " << Inherit; + hFile << "\n{\n"; + + hInlineFile << "/* -----------------------------------------\n"; + hInlineFile << " * Inline implementation of " << Name << "\n"; + hInlineFile << " * ----------------------------------------- */\n"; + + cppFile << "/* -----------------------------------------\n"; + cppFile << " * Static Implementation of " << Name << "\n"; + cppFile << " * ----------------------------------------- */\n"; + + uint i; + for (i=0; iadd(instruction, *this); +} + +inline void CClassGenerator::SMethodId::setDescription(const std::string &description) +{ + nlassert(Generator != NULL); + Generator->add(description, *this); +} + +inline void CFunctionGenerator::flush(CCppOutput &hFile, CCppOutput &cppFile, CCppOutput &hInlineFile) +{ + std::string inlinekw = (IsInline ? std::string("inline ") : std::string("")); + + if (!Description.empty()) + { + hFile << "\n/**\n" << Description << "\n*/\n"; + } + + hFile << padTab(Type, 32) << lcFirst(Name) << "(" << Proto << ");\n"; + + if (IsInline) + { + hInlineFile << padTab(inlinekw+Type, 32) << lcFirst(Name) << "(" << removeDefaultArgs(Proto) << ")\n"; + hInlineFile << "{\n"; + hInlineFile << Body; + hInlineFile << "}\n\n"; + } + else + { + cppFile << padTab(Type, 32) << lcFirst(Name) << "(" << removeDefaultArgs(Proto) << ")\n"; + cppFile << "{\n"; + cppFile << Body; + cppFile << "}\n\n"; + } +} + + + +#endif diff --git a/code/ryzom/tools/pd_parser/main.cpp b/code/ryzom/tools/pd_parser/main.cpp index 92b8dd4ce..d181e0c45 100644 --- a/code/ryzom/tools/pd_parser/main.cpp +++ b/code/ryzom/tools/pd_parser/main.cpp @@ -1,134 +1,134 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "parser.h" -#include "templatizer.h" - -using namespace std; -using namespace NLMISC; - -extern CTemplatizer Templatizer; - -int main(int argc, char **argv) -{ - new CApplicationContext; - - string inputfile; - - uint arg; - for (arg=1; (sint)argexecute(); - //Templatizer.eval(); - } - - printf("Code generation done"); - - return 0; - -/* - if (argc != 2) - { - nlwarning("Error: missing input file(s)"); - exit(EXIT_FAILURE); - } - - if (!Templatizer.build("root{}")) - { - exit(EXIT_FAILURE); - } - - - CParseNode *main = parse(argv[1]); - - GenerateCpp = true; - VerboseMode = true; - - if (main) - { - main->execute(); - } - - return 0; -*/ -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "parser.h" +#include "templatizer.h" + +using namespace std; +using namespace NLMISC; + +extern CTemplatizer Templatizer; + +int main(int argc, char **argv) +{ + new CApplicationContext; + + string inputfile; + + uint arg; + for (arg=1; (sint)argexecute(); + //Templatizer.eval(); + } + + printf("Code generation done"); + + return 0; + +/* + if (argc != 2) + { + nlwarning("Error: missing input file(s)"); + exit(EXIT_FAILURE); + } + + if (!Templatizer.build("root{}")) + { + exit(EXIT_FAILURE); + } + + + CParseNode *main = parse(argv[1]); + + GenerateCpp = true; + VerboseMode = true; + + if (main) + { + main->execute(); + } + + return 0; +*/ +} diff --git a/code/ryzom/tools/pd_parser/parse_node.h b/code/ryzom/tools/pd_parser/parse_node.h index 7b5cb4dbb..b1c43fa4a 100644 --- a/code/ryzom/tools/pd_parser/parse_node.h +++ b/code/ryzom/tools/pd_parser/parse_node.h @@ -1,1485 +1,1485 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef RY_PD_PARSE_NODE_H -#define RY_PD_PARSE_NODE_H - -#include "tokenizer.h" -#include "cpp_output.h" -#include "templatizer.h" - -extern CTokenizer Tokenizer; - -extern std::string getFunctionPrefix; -extern std::string setFunctionPrefix; -extern std::string newFunction; -extern std::string deleteFunction; - -extern std::string indexVariable; -extern std::string valueVariable; -extern std::string keyVariable; -extern std::string objectVariable; - -extern std::string staticCreateFunction; -extern std::string staticRemoveFunction; -extern std::string staticSetUserFactoryFunction; -extern std::string staticLoadFunction; -extern std::string staticUnloadFunction; -extern std::string staticGetFunction; - -extern std::string initFunction; -extern std::string destroyFunction; -extern std::string registerFunction; -extern std::string registerAttributesFunction; -extern std::string unregisterFunction; -extern std::string unregisterAttributesFunction; -extern std::string fetchFunction; -extern std::string setParentFunction; -extern std::string setUnnotifiedParentFunction; -extern std::string getTableFunction; -extern std::string unlinkFunction; - -extern std::string staticInitFactoryFunction; -extern std::string staticFactoryFunction; -extern std::string staticFetchFunction; -extern std::string staticInitFunction; - -extern std::string logStartFunction; -extern std::string logStopFunction; - - -class CFileNode; -class CDbNode; -class CTypeNode; -class CClassNode; -class CIndexNode; -class CEnumNode; -class CDimensionNode; -class CLogMsgNode; - -// -class CParseNode -{ -public: - - CParseNode() : Parent(NULL), FileNode(NULL), DbNode(NULL), Env(NULL) {} - - virtual ~CParseNode() - { - uint i; - for (i=0; i Nodes; - CTokenizer::CToken StartToken; - std::string Name; - std::string Description; - - - - /// - virtual bool prolog() { return true; } - virtual bool epilog() { return true; } - - /// - bool execute() - { - if (!prolog()) - return false; - - uint i; - for (i=0; iexecute()) - return false; - - return epilog(); - } - - - - /// Issue error - void error(const std::string &errMsg, const char *errType = "semantic") - { - Tokenizer.error(StartToken, errType, errMsg.c_str() ); - } - - /// - CParseNode* getNode(const std::string &name) - { - uint i; - for (i=0; iName == name) - return Nodes[i]; - return NULL; - } - - /// - void getFileLine(uint &line, uint &col, std::string &file) - { - Tokenizer.getFileLine(StartToken, line, col, file); - } - - /// - CFileNode* getFileNode(); - CDbNode* getDbNode(); - - CFileNode* FileNode; - CDbNode* DbNode; - - CCppOutput& hOutput(); - CCppOutput& cppOutput(); - CCppOutput& inlineOutput(); - - CTypeNode* getTypeNode(const std::string &name, bool genError = true); - CEnumNode* getEnumNode(const std::string &name, bool genError = true); - CDimensionNode* getDimensionNode(const std::string &name, bool genError = true); - CIndexNode* getIndexNode(const std::string &name, bool genError = true); - CClassNode* getClassNode(const std::string &name, bool genError = true); - - CTemplatizerEnv* Env; - template - void setEnv(const std::string& var, const T& val) - { - nlassert(Env != NULL); - Env->set(var, val); - } - void define(const std::string& var) - { - nlassert(Env != NULL); - Env->set(var, 1); - } - void define(bool isdef, const std::string& var) - { - nlassert(Env != NULL); - if (isdef) - Env->set(var, 1); - } -}; - - -// -// -// -class CDbNode : public CParseNode -{ -public: - CDbNode() : DbXml(false), DbSummary(false) {} - - // - bool addTypeNode(const std::string &name, const std::string &displayName = std::string(""), const std::string &defaultValue = std::string("")); - - // - std::vector FileNodes; - std::vector TypeNodes; - std::vector ClassNodes; - std::vector LogNodes; - CCppOutput DbXml; - CCppOutput DbHpp; - CCppOutput DbHppInline; - CCppOutput DbCpp; - - CCppOutput DbSummary; - - std::string MainFile; - - std::string Pch; - - std::vector xmlDescription; - CFunctionGenerator initDb; - CFunctionGenerator readyDb; - CFunctionGenerator updateDb; - CFunctionGenerator releaseDb; - CFunctionGenerator logChatDb; - CFunctionGenerator logTellDb; - - std::set Implemented; - - /// - virtual bool prolog(); - virtual bool epilog(); - - void pass1(); - void pass2(); - void pass3(); - void pass4(); - - void buildClassOrder(std::vector& classesOrder, std::vector& filesOrder); - - void generateClassesDeclaration(); - void generateIncludes(std::vector& filesOrder); - - void generateClassesContent(std::vector& classesOrder); - - void generateLogContent(); - - std::string getDbFile() { return MainFile.empty() ? Name : MainFile; } - - // get file path from this file - std::string getFileNoExtPath(const std::string& file); -}; - -// -// -// -class CIncludeNode; -class CFileNode : public CParseNode -{ -public: - - CFileNode() : SeparatedFlag(false), IncludeStandard(false), IncludePDSLib(false), IncludeDbFile(false), Generate(true) { } - - std::string IncludeAs; - - bool SeparatedFlag; - - CCppOutput Hpp; - CCppOutput HppInline; - CCppOutput Cpp; - - bool IncludeStandard; - bool IncludePDSLib; - bool IncludeDbFile; - std::vector IncludeNodes; - - bool Generate; - - std::set Dependencies; - - void checkDependencies(std::set &beingChecked, - std::set &checkedFiles, - std::vector &filesOrder); - - /// - virtual bool prolog(); - virtual bool epilog(); - - // - virtual bool generateProlog(); - virtual bool generateEpilog(); - - // - void writeFile(); - - // get file path from this file - std::string getFileNoExtPath(const std::string& file); -}; - -// -// -// -class CIncludeNode : public CParseNode -{ -public: - - /// - virtual bool prolog(); -}; - -// -// -// -class CUsePchNode : public CParseNode -{ -public: - - /// - virtual bool prolog(); -}; - -// -// -// -class CCppCodeNode : public CParseNode -{ -public: - - std::string RawCode; - - /// - virtual bool prolog(); -}; - -// -// -// -class CTypeNode : public CParseNode -{ -public: - CTypeNode() : - ToCppType(NULL), - ToStorageType(NULL), - ExternFlag(false), - InternFlag(false), - Id(0) - { - } - - std::string CppType; - std::string StorageType; - std::string DisplayName; - - CParseNode* ToCppType; - CParseNode* ToStorageType; - - bool ExternFlag; - bool InternFlag; - - std::string Temp; - - uint32 Size; - uint Id; - - std::string DefaultValue; - - virtual bool isEnum() { return false; } - virtual bool isDimension() { return false; } - virtual bool isIndex() { return false; } - - virtual std::string checkCode(const std::string& var) { return ""; } - - std::string storageToCpp() - { - if (ToCppType != NULL) - return "__pds_cnv_type_"+NLMISC::toString(Id)+"_s2c"; - else - return "("+CppType+")"; - } - - std::string cppToStorage() - { - if (ToStorageType != NULL) - return "__pds_cnv_type_"+NLMISC::toString(Id)+"_c2s"; - else - return "("+StorageType+")"; - } - - - - std::string castToCpp(const std::string& var) - { - if (CppType != StorageType) - { - return storageToCpp()+"("+var+")"; - } - else - { - return var; - } - } - - std::string castToStorage(const std::string& var) - { - if (CppType != StorageType) - { - return cppToStorage()+"("+var+")"; - } - else - { - return var; - } - } - - std::string getCppType() - { - if (CppType == "CEntityId") - return "NLMISC::CEntityId"; - else if (CppType == "CSheetId") - return "NLMISC::CSheetId"; - else - return CppType; - } - - - - - std::string castToPDS(const std::string& var) - { - if (isEnum()) - { - return "(uint32)"+var; - } - else if (ExternFlag) - { - return "("+StorageType+")"+var; - } - else - { - //return "("+getName()+")"; - return castToStorage(var); - } - } - - std::string castFromUser(const std::string& var) - { - return "("+getName()+")"+var; - } - - - - virtual std::string getName() { return DisplayName.empty() ? Name : DisplayName; } - - std::string getDefaultValue() - { - if (DefaultValue.empty()) - { - if (CppType == "CEntityId") return "NLMISC::CEntityId::Unknown"; - if (CppType == "CSheetId") return "NLMISC::CSheetId::Unknown"; - return castFromUser("0"); - } - else - { - return DefaultValue; - } - } - - - - virtual std::string getPrintfFmt() - { - if (CppType == "CEntityId" || CppType == "CSheetId") - return "%s"; - if (CppType == "double" || CppType == "float") - return "%f"; - if (CppType == "sint64") - return "%\"NL_I64\"d"; - if (CppType == "uint64") - return "%\"NL_I64\"u"; - if (CppType == "sint32" || CppType == "sint16" || CppType == "sint8") - return "%d"; - if (CppType == "uint32" || CppType == "uint16" || CppType == "uint8") - return "%u"; - if (CppType == "char" || CppType == "ucchar") - return "%c"; - if (CppType == "bool") - return "%s"; - return "%d"; - } - - virtual std::string getPrintfVal(const std::string& var) - { - if (CppType == "CEntityId" || CppType == "CSheetId") - return var+".toString()"; - if (CppType == "double" || CppType == "float" || - CppType == "sint64" || CppType == "uint64" || - CppType == "sint32" || CppType == "sint16" || CppType == "sint8" || - CppType == "uint32" || CppType == "uint16" || CppType == "uint8" || - CppType == "char" || CppType == "ucchar") - return var; - if (CppType == "bool") - return "("+var+" ? \"true\" : \"false\")"; - return "(uint32)"+var; - } - - - /// - virtual bool prolog(); - - /// - virtual bool generateContent(); - - virtual void generateApplyCode(CClassGenerator::SMethodId& method, const std::string& token, const std::string& value) - { - method.add("__pdr.pop("+token+", "+value+");"); - } - - virtual void generateStoreCode(CClassGenerator::SMethodId& method, const std::string& token, const std::string& value) - { - method.add("__pdr.push("+token+", "+value+");"); - } -}; - - - - - - - -// -// -// -class CDeclarationNode; -class CCallContext; - -enum TDeclarationType -{ - SimpleType, - SimpleClass, - ForwardRef, - BackRef, - ArrayType, - ArrayClass, - ArrayRef, - Set -}; - -struct CColumn -{ - std::string Name; - uint32 ByteSize; - TDeclarationType Type; - std::string TypeStr; - uint TypeId; -}; - -class CClassNode : public CParseNode -{ -public: - - CClassNode() : - IsBackReferenced(false), - HasInheritance(false), - IsInSet(false), - IsInArray(false), - IsInArrayRef(false), - MappedFlag(false), - DerivatedFlag(false), - HasParent(false), - ParentIsHidden(false), - ForceReference(false), - PDSMapped(false), - MapClass(NULL), - Columns(-1), - Id(0), - HasRowAccess(false), - HasTableAccess(false), - indexUsedInInit(false), - indexUsedInDestroy(false), - indexUsedInFetch(false), - tableAndRowIndicesUsedInFetch(false), - indexUsedInRegister(false), - indexUsedInUnregister(false), - indexUsedInNotifyInit(false), - indexUsedInNotifyRelease(false) - { - } - - std::string Inherited; - std::string ClassKey; - std::string Implements; - std::set Dependencies; - - std::vector ChildrenClasses; - bool IsBackReferenced; - bool HasInheritance; - bool IsInSet; - bool IsInArray; - bool IsInArrayRef; - bool MappedFlag; - bool DerivatedFlag; - bool HasParent; - bool ParentIsHidden; - bool ForceReference; - std::string ParentClass; - std::string Reserve; - - bool PDSMapped; - - CClassNode *MapClass; - - std::vector Init; - std::string InitProto; - std::string InitCallArgs; - - sint Columns; - - uint Id; - - std::vector Attributes; - - bool HasRowAccess; - bool HasTableAccess; - - std::set Friends; - std::set ForwardFriends; - - std::set Legacy; - - /// - virtual bool prolog(); - virtual bool epilog(); - - CDeclarationNode* getDeclarationNode(const std::string &name); - CDeclarationNode* getKey(); - CDeclarationNode* getClassKey(); - CDeclarationNode* getDeclaration(const std::string& name); - - bool useEntityId(); - - void checkClassReferences(); - void fillAttributes(); - void fillRefs(); - void computeFriends(); - - void checkDependencies(std::set &beingChecked, - std::set &checkedClasses, - std::vector &classesOrder); - - void buildInit(); - - void computeAttributesColumns(); - - std::string getId() { return (HasInheritance ? NLMISC::toString("__BaseTable") : NLMISC::toString(Id)); } - - std::string getUserCode(const std::string& name); - - // - - CClassGenerator Gen; - - CClassGenerator::SMethodId InitId; - CClassGenerator::SMethodId DestroyId; - CClassGenerator::SMethodId FetchId; - CClassGenerator::SMethodId RegisterId; - CClassGenerator::SMethodId RegisterAttributesId; - CClassGenerator::SMethodId UnregisterId; - CClassGenerator::SMethodId UnregisterAttributesId; - CClassGenerator::SMethodId SetParentId; - CClassGenerator::SMethodId SetUnnotifiedParentId; - CClassGenerator::SMethodId NotifyInitId; - CClassGenerator::SMethodId NotifyReleaseId; - - CClassGenerator::SMethodId UserInitId; - CClassGenerator::SMethodId UserReleaseId; - - // - CClassGenerator::SMethodId ClearId; - CClassGenerator::SMethodId StoreId; - CClassGenerator::SMethodId ApplyId; - - bool indexUsedInInit; - bool indexUsedInDestroy; - bool indexUsedInFetch; - bool tableAndRowIndicesUsedInFetch; - bool indexUsedInRegister; - bool indexUsedInUnregister; - bool indexUsedInNotifyInit; - bool indexUsedInNotifyRelease; - - bool generateContent(); - void generateContentInCall(CCallContext *context); -}; - -class CDeclarationNode : public CParseNode -{ -public: - - CDeclarationNode() : - InitFillFlag(false), - WriteTriggerFlag(false), - ParentFlag(false), - HiddenFlag(false), - MirroredFlag(false), - ArrayFlag(false), - SetFlag(false), - IsRef(false), - IsType(false), - IsKey(false), - Id(0), - Column(-1), - Columns(-1) - { - } - - bool InitFillFlag; - bool WriteTriggerFlag; - bool ParentFlag; - bool HiddenFlag; - bool MirroredFlag; - - std::string ParentClass; - std::string ParentField; - - std::string Type; - - bool ArrayFlag; - std::string ArrayIndex; - bool SetFlag; - std::string ForwardRefAttribute; - - bool IsRef; - bool IsType; - bool IsKey; - - std::string DefaultValue; - - struct CUserCode - { - std::string Event; - std::string CodeSpecializer; - std::string UserCode; - }; - - std::vector UserCodes; - - std::string getUserCode(const std::string &name, const std::string &specialize = std::string("")) - { - uint i; - // first look for a specialized code - for (i=0; i ColumnList; - - uint Id; - - sint Column; - sint Columns; - - CClassNode* ClassNode; - CClassNode* getParentClass() { return dynamic_cast(Parent); } - - /// - virtual bool prolog(); - virtual bool epilog(); - - // - std::string getFunc() const { return lcFirst(getFunctionPrefix+Name); } - std::string setFunc() const { return lcFirst(setFunctionPrefix+Name); } - std::string newFunc() const { return lcFirst(newFunction+Name); } - std::string deleteFunc() const { return lcFirst(deleteFunction+Name); } - std::string unlinkFunc() const { return lcFirst(unlinkFunction+Name); } - std::string cppName() const { return "_"+Name; } - std::string tokenName() const { return "__Tok"+Name; } - - // - std::string displayPrintfPrefix(); - std::string displayCppCode(std::string replVar = ""); - std::string toUint64(std::string replVar = ""); - - // - void generateContent(CCallContext *context = NULL); - - void generateTypeContent(CCallContext *context = NULL); - void generateClassContent(CCallContext *context = NULL); - void generateBackRefContent(); - void generateForwardRefContent(); - void generateArrayTypeContent(CCallContext *context = NULL); - void generateArrayClassContent(CCallContext *context = NULL); - void generateArrayRefContent(CCallContext *context = NULL); - void generateSetContent(CCallContext *context = NULL); - - - void generateArrayApplyCode(); - void generateArrayStoreCode(); - void generateArrayEndCode(); - - void generateClassPtrApplyCode(const std::string& value); - void generateClassPtrStoreCode(const std::string& value); - - std::string getAccessorName(CCallContext *context, const std::string& accessortype, const std::string& sep = "::"); -}; - - - -// -// -// -class CIndexNode : public CTypeNode -{ -public: - - CIndexNode() - { - CppType = "uint32"; - StorageType = "uint32"; - } - - virtual bool isIndex() { return true; } - - virtual std::string getSizeName() { return Name+"Size"; } - virtual uint getSize() = 0; - - virtual std::string getIndexName(uint32 value) const - { - return NLMISC::toString(value); - } - - virtual std::string getToStringCode(const std::string& var) const - { - return "NLMISC::toString("+var+")"; - } - - virtual std::string getFromStringCode(const std::string& var) const - { - return "atoi("+var+")"; - } - - virtual std::string checkCode(const std::string& var) { return "nlassert("+var+"<"+getSizeName()+");"; } -}; - - -// -// -// -class CEnumNode : public CIndexNode -{ -public: - CEnumNode() : - CurrentValue(0), - MinValue(0), - MaxValue(0) - { - } - - uint32 CurrentValue; - - uint32 MinValue; - uint32 MaxValue; - std::vector > Values; - std::string EndRange; - - virtual bool isEnum() { return true; } - virtual std::string getName() - { - std::string trunc = Name.substr(1); - return "C"+trunc+"::"+(DisplayName.empty() ? Name : DisplayName); - } - - virtual uint getSize() { return MaxValue-MinValue; } - - bool prolog(); - bool epilog(); - - /// - virtual bool generateContent(); - - std::string getIndexName(uint32 value) const - { - std::string result = ""; - - uint i; - for (i=0; i Names; - - bool prolog(); - bool epilog(); -}; - -class CEnumRangeNode : public CEnumNode -{ -public: - - bool prolog(); - bool epilog(); -}; - - - - -// -// -// -class CDimensionNode : public CIndexNode -{ -public: - -public: - CDimensionNode() - { - } - - virtual bool isDimension() { return true; } - std::string getSizeName() { return Name+"Size"; } - - bool prolog(); - bool epilog(); - - sint Dimension; - - virtual uint getSize() { return Dimension; } - - /// - virtual bool generateContent(); -}; - - -// -// -// -class CLogMsgNode : public CParseNode -{ -public: - - CLogMsgNode() : Context(false) - { - } - - bool prolog(); - bool epilog() - { - return true; - } - - std::vector > Params; - std::vector Logs; - - bool Context; - - uint Id; - - void generateContent(); -}; - -class CExtLogTypeNode : public CParseNode -{ -public: - - std::string ExtLogType; - -}; - - - - -// -// -// -class CCallContext -{ -public: - - std::vector Context; - - std::string RootTable; - std::string RootRow; - uint Column; - - CCallContext(CDeclarationNode* decl = NULL) - { - if (decl != NULL) - Context.push_back(decl); - } - - bool hasRootEntityIdKey() - { - CDeclarationNode* k = getRootCaller()->getClassKey(); - if (k != NULL) - { - return (getRootCaller()->getTypeNode(getRootCaller()->getKey()->Type)->CppType == "CEntityId"); - } - return false; - } - - /** - * Generates the name of the pointed variable - * For instance: PhysicalScoresBase, where PhysicalScores is an array and Base is an attribute in this array - * Actually concats all fields names - */ - std::string getCallString() - { - uint i; - std::string res = ""; - for (i=0; iName; - return res; - } - - CClassNode* getRootCaller() - { - return (CClassNode*)Context[0]->Parent; - } - - CDeclarationNode* getRootDeclaration() - { - return Context[0]; - } - - /** - * Generates the access prototype argument list - * Actually only generates indexes for arrays - */ - std::string getDebugCallStringFmt() - { - uint i, idx=0; - std::string res = ""; - - for (i=0; iDeclarationType == ArrayClass || decl->DeclarationType == ArrayType) - { - if (!res.empty()) - res += ", "; - - CTypeNode* tnd = decl->getTypeNode(decl->ArrayIndex); - res += indexVariable+NLMISC::toString(idx++)+"="+tnd->getPrintfFmt(); - } - } - - return res; - } - - - /** - * Generates the access prototype argument list - * Actually only generates indexes for arrays - */ - std::string getDebugCallStringVal() - { - uint i, idx=0; - std::string res = ""; - - for (i=0; iDeclarationType == ArrayClass || decl->DeclarationType == ArrayType) - { - if (!res.empty()) - res += ", "; - - CTypeNode* tnd = decl->getTypeNode(decl->ArrayIndex); - res += tnd->getPrintfVal(indexVariable+NLMISC::toString(idx++)); - } - } - - return res; - } - - - /** - * Generates the access prototype argument list - * Actually only generates indexes for arrays - */ - std::string getCallArgList() - { - std::string res = ""; - uint i, idx=0; - - for (i=0; iDeclarationType == ArrayClass || decl->DeclarationType == ArrayType) - { - if (!res.empty()) - res += ", "; - - CTypeNode* tnd = decl->getTypeNode(decl->ArrayIndex); - res += tnd->getName()+ " "+indexVariable+NLMISC::toString(idx++); - } - } - return res; - } - - /** - * Generates the c++ path to the variable - * For instance: _PhysicalScores[__i0].Base, where PhysicalScores is an array and Base is an attribute in this array - */ - std::string getCallPath() - { - std::string res = ""; - uint i, idx=0; - - for (i=0; icppName(); - - if (decl->DeclarationType == ArrayClass || decl->DeclarationType == ArrayType) - { - res += "["+indexVariable+NLMISC::toString(idx++)+"]"; - } - } - return res; - } - - /** - * Generates the c++ path to the variable - * For instance: _PhysicalScores[__i0].Base, where PhysicalScores is an array and Base is an attribute in this array - */ - std::string getUserCodeContext() - { - std::string res = ""; - uint i; - - if (Context.empty()) - return res; - - res = Context[0]->getParentClass()->Name; - - for (i=0; iName; - - return res; - } - - /** - * Generates check code for all types accessors - */ - std::vector getCheckCode() - { - std::vector res; - uint i, idx=0; - - for (i=0; iDeclarationType == ArrayType || decl->DeclarationType == ArrayRef || decl->DeclarationType == ArrayClass) - { - CIndexNode* ind = decl->getIndexNode(decl->ArrayIndex); - std::string code = ind->checkCode(indexVariable+NLMISC::toString(idx++)); - if (!code.empty()) - res.push_back(code); - } - } - - return res; - } - - /** - * Get current context index - */ - uint getContextIndex() - { - uint i, idx=0; - - for (i=0; iDeclarationType == ArrayClass || decl->DeclarationType == ArrayType) - idx++; - } - return idx-1; - } - - CCallContext getSubContext(CDeclarationNode* decl) - { - CCallContext ctx = *this; - ctx.Context.push_back(decl); - return ctx; - } - - std::string getColumn() - { - std::string res = ""; - uint i, idx=0; - - for (i=0; iColumn != 0) - { - if (!res.empty()) - res += "+"; - res += NLMISC::toString(decl->Column); - } - - if (decl->DeclarationType == ArrayType || decl->DeclarationType == ArrayRef) - { - if (!res.empty()) - res += "+"; - res += indexVariable+NLMISC::toString(idx++); - } - else if (decl->DeclarationType == ArrayClass) - { - if (!res.empty()) - res += "+"; - CClassNode* sub = decl->getClassNode(decl->Type); - res += indexVariable+NLMISC::toString(idx++)+"*"+NLMISC::toString(sub->Columns); - } - } - - if (res.empty()) - res = "0"; - - return res; - } -}; - - - - - - -// -// INLINES -// - -inline CFileNode* CParseNode::getFileNode() -{ - if (FileNode != NULL) - return FileNode; - - CParseNode* node = this; - CFileNode* fnode = NULL; - - while (node != NULL && (fnode = dynamic_cast(node)) == NULL) - node = node->Parent; - - if (fnode == NULL) - error("Can't find file node", "internal"); - - FileNode = fnode; - - return fnode; -} - -inline CDbNode* CParseNode::getDbNode() -{ - if (DbNode != NULL) - return DbNode; - - CParseNode* node = this; - CDbNode* fnode = NULL; - - while (node != NULL && (fnode = dynamic_cast(node)) == NULL) - node = node->Parent; - - if (fnode == NULL) - error("Can't find db node", "internal"); - - DbNode = fnode; - - return fnode; -} - -inline CCppOutput& CParseNode::hOutput() -{ - CFileNode *fnode = getFileNode(); - return fnode->Hpp; -} - -inline CCppOutput& CParseNode::cppOutput() -{ - CFileNode *fnode = getFileNode(); - return fnode->Cpp; -} - -inline CCppOutput& CParseNode::inlineOutput() -{ - CFileNode *fnode = getFileNode(); - return fnode->HppInline; -} - - -inline CTypeNode *CParseNode::getTypeNode(const std::string &name, bool genError) -{ - CDbNode* db = getDbNode(); - uint i; - for (i=0; iTypeNodes.size(); ++i) - if (db->TypeNodes[i]->Name == name) - return db->TypeNodes[i]; - if (genError) - error("Can't find type '"+name+"'"); - return NULL; -} - -inline CEnumNode *CParseNode::getEnumNode(const std::string &name, bool genError) -{ - CEnumNode* node = dynamic_cast(getTypeNode(name, genError)); - if (node == NULL && genError) - error("Can't find enum '"+name+"'"); - return node; -} - -inline CDimensionNode *CParseNode::getDimensionNode(const std::string &name, bool genError) -{ - CDimensionNode* node = dynamic_cast(getTypeNode(name, genError)); - if (node == NULL && genError) - error("Can't find dimension '"+name+"'"); - return node; -} - -inline CIndexNode *CParseNode::getIndexNode(const std::string &name, bool genError) -{ - CIndexNode* node = dynamic_cast(getTypeNode(name, genError)); - if (node == NULL && genError) - error("Can't find index type '"+name+"' (neither enum nor dimension)"); - return node; -} - -inline CClassNode *CParseNode::getClassNode(const std::string &name, bool genError) -{ - CDbNode* db = getDbNode(); - uint i; - for (i=0; iClassNodes.size(); ++i) - if (db->ClassNodes[i]->Name == name) - return db->ClassNodes[i]; - if (genError) - error("Can't find class '"+name+"'"); - return NULL; -} - -inline bool CDbNode::addTypeNode(const std::string &name, const std::string &displayName, const std::string &defaultValue) -{ - CTypeNode *node = new CTypeNode(); - - node->Name = name; - node->DisplayName = displayName; - node->CppType = name; - node->StorageType = name; - - node->ToCppType = NULL; - node->ToStorageType = NULL; - - node->DefaultValue = defaultValue; - - node->ExternFlag = false; - node->InternFlag = true; - node->Parent = this; - - Nodes.insert(Nodes.begin(), node); - - return true; -} - - -inline CDeclarationNode* CClassNode::getDeclarationNode(const std::string &name) -{ - CDeclarationNode *node; - if ((node = dynamic_cast(getNode(name))) == NULL) - error("declaration '"+name+"' not found"); - return node; -} - -inline bool CClassNode::useEntityId() -{ - //return !ClassKey.empty() && getTypeNode(getKey()->Type)->CppType == "CEntityId"; - CDeclarationNode* k = getClassKey(); - return k!=NULL && getTypeNode(k->Type)->CppType == "CEntityId"; -} - -inline CDeclarationNode* CClassNode::getClassKey() -{ - if (ClassKey.empty()) - { - if (Inherited.empty()) - return NULL; - CClassNode* p = getClassNode(Inherited); - return p->getClassKey(); - } - else - { - return getKey(); - } -} - - -inline CDeclarationNode* CClassNode::getKey() -{ - CDeclarationNode* key = NULL; - CClassNode* classNode = this; - while (classNode != NULL) - { - key = dynamic_cast(classNode->getNode(classNode->ClassKey)); - if (key != NULL) - return key; - classNode = getClassNode(Inherited, false); - } - error("key declaration '"+ClassKey+"' not found"); - return NULL; - //return getDeclarationNode(ClassKey); -} - -inline CDeclarationNode* CClassNode::getDeclaration(const std::string& name) -{ - CDeclarationNode* decl = NULL; - CClassNode* classNode = this; - while (classNode != NULL) - { - decl = dynamic_cast(classNode->getNode(name)); - if (decl != NULL) - return decl; - classNode = getClassNode(classNode->Inherited, false); - } - error("declaration '"+name+"' not found"); - return NULL; -} - - - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef RY_PD_PARSE_NODE_H +#define RY_PD_PARSE_NODE_H + +#include "tokenizer.h" +#include "cpp_output.h" +#include "templatizer.h" + +extern CTokenizer Tokenizer; + +extern std::string getFunctionPrefix; +extern std::string setFunctionPrefix; +extern std::string newFunction; +extern std::string deleteFunction; + +extern std::string indexVariable; +extern std::string valueVariable; +extern std::string keyVariable; +extern std::string objectVariable; + +extern std::string staticCreateFunction; +extern std::string staticRemoveFunction; +extern std::string staticSetUserFactoryFunction; +extern std::string staticLoadFunction; +extern std::string staticUnloadFunction; +extern std::string staticGetFunction; + +extern std::string initFunction; +extern std::string destroyFunction; +extern std::string registerFunction; +extern std::string registerAttributesFunction; +extern std::string unregisterFunction; +extern std::string unregisterAttributesFunction; +extern std::string fetchFunction; +extern std::string setParentFunction; +extern std::string setUnnotifiedParentFunction; +extern std::string getTableFunction; +extern std::string unlinkFunction; + +extern std::string staticInitFactoryFunction; +extern std::string staticFactoryFunction; +extern std::string staticFetchFunction; +extern std::string staticInitFunction; + +extern std::string logStartFunction; +extern std::string logStopFunction; + + +class CFileNode; +class CDbNode; +class CTypeNode; +class CClassNode; +class CIndexNode; +class CEnumNode; +class CDimensionNode; +class CLogMsgNode; + +// +class CParseNode +{ +public: + + CParseNode() : Parent(NULL), FileNode(NULL), DbNode(NULL), Env(NULL) {} + + virtual ~CParseNode() + { + uint i; + for (i=0; i Nodes; + CTokenizer::CToken StartToken; + std::string Name; + std::string Description; + + + + /// + virtual bool prolog() { return true; } + virtual bool epilog() { return true; } + + /// + bool execute() + { + if (!prolog()) + return false; + + uint i; + for (i=0; iexecute()) + return false; + + return epilog(); + } + + + + /// Issue error + void error(const std::string &errMsg, const char *errType = "semantic") + { + Tokenizer.error(StartToken, errType, errMsg.c_str() ); + } + + /// + CParseNode* getNode(const std::string &name) + { + uint i; + for (i=0; iName == name) + return Nodes[i]; + return NULL; + } + + /// + void getFileLine(uint &line, uint &col, std::string &file) + { + Tokenizer.getFileLine(StartToken, line, col, file); + } + + /// + CFileNode* getFileNode(); + CDbNode* getDbNode(); + + CFileNode* FileNode; + CDbNode* DbNode; + + CCppOutput& hOutput(); + CCppOutput& cppOutput(); + CCppOutput& inlineOutput(); + + CTypeNode* getTypeNode(const std::string &name, bool genError = true); + CEnumNode* getEnumNode(const std::string &name, bool genError = true); + CDimensionNode* getDimensionNode(const std::string &name, bool genError = true); + CIndexNode* getIndexNode(const std::string &name, bool genError = true); + CClassNode* getClassNode(const std::string &name, bool genError = true); + + CTemplatizerEnv* Env; + template + void setEnv(const std::string& var, const T& val) + { + nlassert(Env != NULL); + Env->set(var, val); + } + void define(const std::string& var) + { + nlassert(Env != NULL); + Env->set(var, 1); + } + void define(bool isdef, const std::string& var) + { + nlassert(Env != NULL); + if (isdef) + Env->set(var, 1); + } +}; + + +// +// +// +class CDbNode : public CParseNode +{ +public: + CDbNode() : DbXml(false), DbSummary(false) {} + + // + bool addTypeNode(const std::string &name, const std::string &displayName = std::string(""), const std::string &defaultValue = std::string("")); + + // + std::vector FileNodes; + std::vector TypeNodes; + std::vector ClassNodes; + std::vector LogNodes; + CCppOutput DbXml; + CCppOutput DbHpp; + CCppOutput DbHppInline; + CCppOutput DbCpp; + + CCppOutput DbSummary; + + std::string MainFile; + + std::string Pch; + + std::vector xmlDescription; + CFunctionGenerator initDb; + CFunctionGenerator readyDb; + CFunctionGenerator updateDb; + CFunctionGenerator releaseDb; + CFunctionGenerator logChatDb; + CFunctionGenerator logTellDb; + + std::set Implemented; + + /// + virtual bool prolog(); + virtual bool epilog(); + + void pass1(); + void pass2(); + void pass3(); + void pass4(); + + void buildClassOrder(std::vector& classesOrder, std::vector& filesOrder); + + void generateClassesDeclaration(); + void generateIncludes(std::vector& filesOrder); + + void generateClassesContent(std::vector& classesOrder); + + void generateLogContent(); + + std::string getDbFile() { return MainFile.empty() ? Name : MainFile; } + + // get file path from this file + std::string getFileNoExtPath(const std::string& file); +}; + +// +// +// +class CIncludeNode; +class CFileNode : public CParseNode +{ +public: + + CFileNode() : SeparatedFlag(false), IncludeStandard(false), IncludePDSLib(false), IncludeDbFile(false), Generate(true) { } + + std::string IncludeAs; + + bool SeparatedFlag; + + CCppOutput Hpp; + CCppOutput HppInline; + CCppOutput Cpp; + + bool IncludeStandard; + bool IncludePDSLib; + bool IncludeDbFile; + std::vector IncludeNodes; + + bool Generate; + + std::set Dependencies; + + void checkDependencies(std::set &beingChecked, + std::set &checkedFiles, + std::vector &filesOrder); + + /// + virtual bool prolog(); + virtual bool epilog(); + + // + virtual bool generateProlog(); + virtual bool generateEpilog(); + + // + void writeFile(); + + // get file path from this file + std::string getFileNoExtPath(const std::string& file); +}; + +// +// +// +class CIncludeNode : public CParseNode +{ +public: + + /// + virtual bool prolog(); +}; + +// +// +// +class CUsePchNode : public CParseNode +{ +public: + + /// + virtual bool prolog(); +}; + +// +// +// +class CCppCodeNode : public CParseNode +{ +public: + + std::string RawCode; + + /// + virtual bool prolog(); +}; + +// +// +// +class CTypeNode : public CParseNode +{ +public: + CTypeNode() : + ToCppType(NULL), + ToStorageType(NULL), + ExternFlag(false), + InternFlag(false), + Id(0) + { + } + + std::string CppType; + std::string StorageType; + std::string DisplayName; + + CParseNode* ToCppType; + CParseNode* ToStorageType; + + bool ExternFlag; + bool InternFlag; + + std::string Temp; + + uint32 Size; + uint Id; + + std::string DefaultValue; + + virtual bool isEnum() { return false; } + virtual bool isDimension() { return false; } + virtual bool isIndex() { return false; } + + virtual std::string checkCode(const std::string& var) { return ""; } + + std::string storageToCpp() + { + if (ToCppType != NULL) + return "__pds_cnv_type_"+NLMISC::toString(Id)+"_s2c"; + else + return "("+CppType+")"; + } + + std::string cppToStorage() + { + if (ToStorageType != NULL) + return "__pds_cnv_type_"+NLMISC::toString(Id)+"_c2s"; + else + return "("+StorageType+")"; + } + + + + std::string castToCpp(const std::string& var) + { + if (CppType != StorageType) + { + return storageToCpp()+"("+var+")"; + } + else + { + return var; + } + } + + std::string castToStorage(const std::string& var) + { + if (CppType != StorageType) + { + return cppToStorage()+"("+var+")"; + } + else + { + return var; + } + } + + std::string getCppType() + { + if (CppType == "CEntityId") + return "NLMISC::CEntityId"; + else if (CppType == "CSheetId") + return "NLMISC::CSheetId"; + else + return CppType; + } + + + + + std::string castToPDS(const std::string& var) + { + if (isEnum()) + { + return "(uint32)"+var; + } + else if (ExternFlag) + { + return "("+StorageType+")"+var; + } + else + { + //return "("+getName()+")"; + return castToStorage(var); + } + } + + std::string castFromUser(const std::string& var) + { + return "("+getName()+")"+var; + } + + + + virtual std::string getName() { return DisplayName.empty() ? Name : DisplayName; } + + std::string getDefaultValue() + { + if (DefaultValue.empty()) + { + if (CppType == "CEntityId") return "NLMISC::CEntityId::Unknown"; + if (CppType == "CSheetId") return "NLMISC::CSheetId::Unknown"; + return castFromUser("0"); + } + else + { + return DefaultValue; + } + } + + + + virtual std::string getPrintfFmt() + { + if (CppType == "CEntityId" || CppType == "CSheetId") + return "%s"; + if (CppType == "double" || CppType == "float") + return "%f"; + if (CppType == "sint64") + return "%\"NL_I64\"d"; + if (CppType == "uint64") + return "%\"NL_I64\"u"; + if (CppType == "sint32" || CppType == "sint16" || CppType == "sint8") + return "%d"; + if (CppType == "uint32" || CppType == "uint16" || CppType == "uint8") + return "%u"; + if (CppType == "char" || CppType == "ucchar") + return "%c"; + if (CppType == "bool") + return "%s"; + return "%d"; + } + + virtual std::string getPrintfVal(const std::string& var) + { + if (CppType == "CEntityId" || CppType == "CSheetId") + return var+".toString()"; + if (CppType == "double" || CppType == "float" || + CppType == "sint64" || CppType == "uint64" || + CppType == "sint32" || CppType == "sint16" || CppType == "sint8" || + CppType == "uint32" || CppType == "uint16" || CppType == "uint8" || + CppType == "char" || CppType == "ucchar") + return var; + if (CppType == "bool") + return "("+var+" ? \"true\" : \"false\")"; + return "(uint32)"+var; + } + + + /// + virtual bool prolog(); + + /// + virtual bool generateContent(); + + virtual void generateApplyCode(CClassGenerator::SMethodId& method, const std::string& token, const std::string& value) + { + method.add("__pdr.pop("+token+", "+value+");"); + } + + virtual void generateStoreCode(CClassGenerator::SMethodId& method, const std::string& token, const std::string& value) + { + method.add("__pdr.push("+token+", "+value+");"); + } +}; + + + + + + + +// +// +// +class CDeclarationNode; +class CCallContext; + +enum TDeclarationType +{ + SimpleType, + SimpleClass, + ForwardRef, + BackRef, + ArrayType, + ArrayClass, + ArrayRef, + Set +}; + +struct CColumn +{ + std::string Name; + uint32 ByteSize; + TDeclarationType Type; + std::string TypeStr; + uint TypeId; +}; + +class CClassNode : public CParseNode +{ +public: + + CClassNode() : + IsBackReferenced(false), + HasInheritance(false), + IsInSet(false), + IsInArray(false), + IsInArrayRef(false), + MappedFlag(false), + DerivatedFlag(false), + HasParent(false), + ParentIsHidden(false), + ForceReference(false), + PDSMapped(false), + MapClass(NULL), + Columns(-1), + Id(0), + HasRowAccess(false), + HasTableAccess(false), + indexUsedInInit(false), + indexUsedInDestroy(false), + indexUsedInFetch(false), + tableAndRowIndicesUsedInFetch(false), + indexUsedInRegister(false), + indexUsedInUnregister(false), + indexUsedInNotifyInit(false), + indexUsedInNotifyRelease(false) + { + } + + std::string Inherited; + std::string ClassKey; + std::string Implements; + std::set Dependencies; + + std::vector ChildrenClasses; + bool IsBackReferenced; + bool HasInheritance; + bool IsInSet; + bool IsInArray; + bool IsInArrayRef; + bool MappedFlag; + bool DerivatedFlag; + bool HasParent; + bool ParentIsHidden; + bool ForceReference; + std::string ParentClass; + std::string Reserve; + + bool PDSMapped; + + CClassNode *MapClass; + + std::vector Init; + std::string InitProto; + std::string InitCallArgs; + + sint Columns; + + uint Id; + + std::vector Attributes; + + bool HasRowAccess; + bool HasTableAccess; + + std::set Friends; + std::set ForwardFriends; + + std::set Legacy; + + /// + virtual bool prolog(); + virtual bool epilog(); + + CDeclarationNode* getDeclarationNode(const std::string &name); + CDeclarationNode* getKey(); + CDeclarationNode* getClassKey(); + CDeclarationNode* getDeclaration(const std::string& name); + + bool useEntityId(); + + void checkClassReferences(); + void fillAttributes(); + void fillRefs(); + void computeFriends(); + + void checkDependencies(std::set &beingChecked, + std::set &checkedClasses, + std::vector &classesOrder); + + void buildInit(); + + void computeAttributesColumns(); + + std::string getId() { return (HasInheritance ? NLMISC::toString("__BaseTable") : NLMISC::toString(Id)); } + + std::string getUserCode(const std::string& name); + + // + + CClassGenerator Gen; + + CClassGenerator::SMethodId InitId; + CClassGenerator::SMethodId DestroyId; + CClassGenerator::SMethodId FetchId; + CClassGenerator::SMethodId RegisterId; + CClassGenerator::SMethodId RegisterAttributesId; + CClassGenerator::SMethodId UnregisterId; + CClassGenerator::SMethodId UnregisterAttributesId; + CClassGenerator::SMethodId SetParentId; + CClassGenerator::SMethodId SetUnnotifiedParentId; + CClassGenerator::SMethodId NotifyInitId; + CClassGenerator::SMethodId NotifyReleaseId; + + CClassGenerator::SMethodId UserInitId; + CClassGenerator::SMethodId UserReleaseId; + + // + CClassGenerator::SMethodId ClearId; + CClassGenerator::SMethodId StoreId; + CClassGenerator::SMethodId ApplyId; + + bool indexUsedInInit; + bool indexUsedInDestroy; + bool indexUsedInFetch; + bool tableAndRowIndicesUsedInFetch; + bool indexUsedInRegister; + bool indexUsedInUnregister; + bool indexUsedInNotifyInit; + bool indexUsedInNotifyRelease; + + bool generateContent(); + void generateContentInCall(CCallContext *context); +}; + +class CDeclarationNode : public CParseNode +{ +public: + + CDeclarationNode() : + InitFillFlag(false), + WriteTriggerFlag(false), + ParentFlag(false), + HiddenFlag(false), + MirroredFlag(false), + ArrayFlag(false), + SetFlag(false), + IsRef(false), + IsType(false), + IsKey(false), + Id(0), + Column(-1), + Columns(-1) + { + } + + bool InitFillFlag; + bool WriteTriggerFlag; + bool ParentFlag; + bool HiddenFlag; + bool MirroredFlag; + + std::string ParentClass; + std::string ParentField; + + std::string Type; + + bool ArrayFlag; + std::string ArrayIndex; + bool SetFlag; + std::string ForwardRefAttribute; + + bool IsRef; + bool IsType; + bool IsKey; + + std::string DefaultValue; + + struct CUserCode + { + std::string Event; + std::string CodeSpecializer; + std::string UserCode; + }; + + std::vector UserCodes; + + std::string getUserCode(const std::string &name, const std::string &specialize = std::string("")) + { + uint i; + // first look for a specialized code + for (i=0; i ColumnList; + + uint Id; + + sint Column; + sint Columns; + + CClassNode* ClassNode; + CClassNode* getParentClass() { return dynamic_cast(Parent); } + + /// + virtual bool prolog(); + virtual bool epilog(); + + // + std::string getFunc() const { return lcFirst(getFunctionPrefix+Name); } + std::string setFunc() const { return lcFirst(setFunctionPrefix+Name); } + std::string newFunc() const { return lcFirst(newFunction+Name); } + std::string deleteFunc() const { return lcFirst(deleteFunction+Name); } + std::string unlinkFunc() const { return lcFirst(unlinkFunction+Name); } + std::string cppName() const { return "_"+Name; } + std::string tokenName() const { return "__Tok"+Name; } + + // + std::string displayPrintfPrefix(); + std::string displayCppCode(std::string replVar = ""); + std::string toUint64(std::string replVar = ""); + + // + void generateContent(CCallContext *context = NULL); + + void generateTypeContent(CCallContext *context = NULL); + void generateClassContent(CCallContext *context = NULL); + void generateBackRefContent(); + void generateForwardRefContent(); + void generateArrayTypeContent(CCallContext *context = NULL); + void generateArrayClassContent(CCallContext *context = NULL); + void generateArrayRefContent(CCallContext *context = NULL); + void generateSetContent(CCallContext *context = NULL); + + + void generateArrayApplyCode(); + void generateArrayStoreCode(); + void generateArrayEndCode(); + + void generateClassPtrApplyCode(const std::string& value); + void generateClassPtrStoreCode(const std::string& value); + + std::string getAccessorName(CCallContext *context, const std::string& accessortype, const std::string& sep = "::"); +}; + + + +// +// +// +class CIndexNode : public CTypeNode +{ +public: + + CIndexNode() + { + CppType = "uint32"; + StorageType = "uint32"; + } + + virtual bool isIndex() { return true; } + + virtual std::string getSizeName() { return Name+"Size"; } + virtual uint getSize() = 0; + + virtual std::string getIndexName(uint32 value) const + { + return NLMISC::toString(value); + } + + virtual std::string getToStringCode(const std::string& var) const + { + return "NLMISC::toString("+var+")"; + } + + virtual std::string getFromStringCode(const std::string& var) const + { + return "atoi("+var+")"; + } + + virtual std::string checkCode(const std::string& var) { return "nlassert("+var+"<"+getSizeName()+");"; } +}; + + +// +// +// +class CEnumNode : public CIndexNode +{ +public: + CEnumNode() : + CurrentValue(0), + MinValue(0), + MaxValue(0) + { + } + + uint32 CurrentValue; + + uint32 MinValue; + uint32 MaxValue; + std::vector > Values; + std::string EndRange; + + virtual bool isEnum() { return true; } + virtual std::string getName() + { + std::string trunc = Name.substr(1); + return "C"+trunc+"::"+(DisplayName.empty() ? Name : DisplayName); + } + + virtual uint getSize() { return MaxValue-MinValue; } + + bool prolog(); + bool epilog(); + + /// + virtual bool generateContent(); + + std::string getIndexName(uint32 value) const + { + std::string result = ""; + + uint i; + for (i=0; i Names; + + bool prolog(); + bool epilog(); +}; + +class CEnumRangeNode : public CEnumNode +{ +public: + + bool prolog(); + bool epilog(); +}; + + + + +// +// +// +class CDimensionNode : public CIndexNode +{ +public: + +public: + CDimensionNode() + { + } + + virtual bool isDimension() { return true; } + std::string getSizeName() { return Name+"Size"; } + + bool prolog(); + bool epilog(); + + sint Dimension; + + virtual uint getSize() { return Dimension; } + + /// + virtual bool generateContent(); +}; + + +// +// +// +class CLogMsgNode : public CParseNode +{ +public: + + CLogMsgNode() : Context(false) + { + } + + bool prolog(); + bool epilog() + { + return true; + } + + std::vector > Params; + std::vector Logs; + + bool Context; + + uint Id; + + void generateContent(); +}; + +class CExtLogTypeNode : public CParseNode +{ +public: + + std::string ExtLogType; + +}; + + + + +// +// +// +class CCallContext +{ +public: + + std::vector Context; + + std::string RootTable; + std::string RootRow; + uint Column; + + CCallContext(CDeclarationNode* decl = NULL) + { + if (decl != NULL) + Context.push_back(decl); + } + + bool hasRootEntityIdKey() + { + CDeclarationNode* k = getRootCaller()->getClassKey(); + if (k != NULL) + { + return (getRootCaller()->getTypeNode(getRootCaller()->getKey()->Type)->CppType == "CEntityId"); + } + return false; + } + + /** + * Generates the name of the pointed variable + * For instance: PhysicalScoresBase, where PhysicalScores is an array and Base is an attribute in this array + * Actually concats all fields names + */ + std::string getCallString() + { + uint i; + std::string res = ""; + for (i=0; iName; + return res; + } + + CClassNode* getRootCaller() + { + return (CClassNode*)Context[0]->Parent; + } + + CDeclarationNode* getRootDeclaration() + { + return Context[0]; + } + + /** + * Generates the access prototype argument list + * Actually only generates indexes for arrays + */ + std::string getDebugCallStringFmt() + { + uint i, idx=0; + std::string res = ""; + + for (i=0; iDeclarationType == ArrayClass || decl->DeclarationType == ArrayType) + { + if (!res.empty()) + res += ", "; + + CTypeNode* tnd = decl->getTypeNode(decl->ArrayIndex); + res += indexVariable+NLMISC::toString(idx++)+"="+tnd->getPrintfFmt(); + } + } + + return res; + } + + + /** + * Generates the access prototype argument list + * Actually only generates indexes for arrays + */ + std::string getDebugCallStringVal() + { + uint i, idx=0; + std::string res = ""; + + for (i=0; iDeclarationType == ArrayClass || decl->DeclarationType == ArrayType) + { + if (!res.empty()) + res += ", "; + + CTypeNode* tnd = decl->getTypeNode(decl->ArrayIndex); + res += tnd->getPrintfVal(indexVariable+NLMISC::toString(idx++)); + } + } + + return res; + } + + + /** + * Generates the access prototype argument list + * Actually only generates indexes for arrays + */ + std::string getCallArgList() + { + std::string res = ""; + uint i, idx=0; + + for (i=0; iDeclarationType == ArrayClass || decl->DeclarationType == ArrayType) + { + if (!res.empty()) + res += ", "; + + CTypeNode* tnd = decl->getTypeNode(decl->ArrayIndex); + res += tnd->getName()+ " "+indexVariable+NLMISC::toString(idx++); + } + } + return res; + } + + /** + * Generates the c++ path to the variable + * For instance: _PhysicalScores[__i0].Base, where PhysicalScores is an array and Base is an attribute in this array + */ + std::string getCallPath() + { + std::string res = ""; + uint i, idx=0; + + for (i=0; icppName(); + + if (decl->DeclarationType == ArrayClass || decl->DeclarationType == ArrayType) + { + res += "["+indexVariable+NLMISC::toString(idx++)+"]"; + } + } + return res; + } + + /** + * Generates the c++ path to the variable + * For instance: _PhysicalScores[__i0].Base, where PhysicalScores is an array and Base is an attribute in this array + */ + std::string getUserCodeContext() + { + std::string res = ""; + uint i; + + if (Context.empty()) + return res; + + res = Context[0]->getParentClass()->Name; + + for (i=0; iName; + + return res; + } + + /** + * Generates check code for all types accessors + */ + std::vector getCheckCode() + { + std::vector res; + uint i, idx=0; + + for (i=0; iDeclarationType == ArrayType || decl->DeclarationType == ArrayRef || decl->DeclarationType == ArrayClass) + { + CIndexNode* ind = decl->getIndexNode(decl->ArrayIndex); + std::string code = ind->checkCode(indexVariable+NLMISC::toString(idx++)); + if (!code.empty()) + res.push_back(code); + } + } + + return res; + } + + /** + * Get current context index + */ + uint getContextIndex() + { + uint i, idx=0; + + for (i=0; iDeclarationType == ArrayClass || decl->DeclarationType == ArrayType) + idx++; + } + return idx-1; + } + + CCallContext getSubContext(CDeclarationNode* decl) + { + CCallContext ctx = *this; + ctx.Context.push_back(decl); + return ctx; + } + + std::string getColumn() + { + std::string res = ""; + uint i, idx=0; + + for (i=0; iColumn != 0) + { + if (!res.empty()) + res += "+"; + res += NLMISC::toString(decl->Column); + } + + if (decl->DeclarationType == ArrayType || decl->DeclarationType == ArrayRef) + { + if (!res.empty()) + res += "+"; + res += indexVariable+NLMISC::toString(idx++); + } + else if (decl->DeclarationType == ArrayClass) + { + if (!res.empty()) + res += "+"; + CClassNode* sub = decl->getClassNode(decl->Type); + res += indexVariable+NLMISC::toString(idx++)+"*"+NLMISC::toString(sub->Columns); + } + } + + if (res.empty()) + res = "0"; + + return res; + } +}; + + + + + + +// +// INLINES +// + +inline CFileNode* CParseNode::getFileNode() +{ + if (FileNode != NULL) + return FileNode; + + CParseNode* node = this; + CFileNode* fnode = NULL; + + while (node != NULL && (fnode = dynamic_cast(node)) == NULL) + node = node->Parent; + + if (fnode == NULL) + error("Can't find file node", "internal"); + + FileNode = fnode; + + return fnode; +} + +inline CDbNode* CParseNode::getDbNode() +{ + if (DbNode != NULL) + return DbNode; + + CParseNode* node = this; + CDbNode* fnode = NULL; + + while (node != NULL && (fnode = dynamic_cast(node)) == NULL) + node = node->Parent; + + if (fnode == NULL) + error("Can't find db node", "internal"); + + DbNode = fnode; + + return fnode; +} + +inline CCppOutput& CParseNode::hOutput() +{ + CFileNode *fnode = getFileNode(); + return fnode->Hpp; +} + +inline CCppOutput& CParseNode::cppOutput() +{ + CFileNode *fnode = getFileNode(); + return fnode->Cpp; +} + +inline CCppOutput& CParseNode::inlineOutput() +{ + CFileNode *fnode = getFileNode(); + return fnode->HppInline; +} + + +inline CTypeNode *CParseNode::getTypeNode(const std::string &name, bool genError) +{ + CDbNode* db = getDbNode(); + uint i; + for (i=0; iTypeNodes.size(); ++i) + if (db->TypeNodes[i]->Name == name) + return db->TypeNodes[i]; + if (genError) + error("Can't find type '"+name+"'"); + return NULL; +} + +inline CEnumNode *CParseNode::getEnumNode(const std::string &name, bool genError) +{ + CEnumNode* node = dynamic_cast(getTypeNode(name, genError)); + if (node == NULL && genError) + error("Can't find enum '"+name+"'"); + return node; +} + +inline CDimensionNode *CParseNode::getDimensionNode(const std::string &name, bool genError) +{ + CDimensionNode* node = dynamic_cast(getTypeNode(name, genError)); + if (node == NULL && genError) + error("Can't find dimension '"+name+"'"); + return node; +} + +inline CIndexNode *CParseNode::getIndexNode(const std::string &name, bool genError) +{ + CIndexNode* node = dynamic_cast(getTypeNode(name, genError)); + if (node == NULL && genError) + error("Can't find index type '"+name+"' (neither enum nor dimension)"); + return node; +} + +inline CClassNode *CParseNode::getClassNode(const std::string &name, bool genError) +{ + CDbNode* db = getDbNode(); + uint i; + for (i=0; iClassNodes.size(); ++i) + if (db->ClassNodes[i]->Name == name) + return db->ClassNodes[i]; + if (genError) + error("Can't find class '"+name+"'"); + return NULL; +} + +inline bool CDbNode::addTypeNode(const std::string &name, const std::string &displayName, const std::string &defaultValue) +{ + CTypeNode *node = new CTypeNode(); + + node->Name = name; + node->DisplayName = displayName; + node->CppType = name; + node->StorageType = name; + + node->ToCppType = NULL; + node->ToStorageType = NULL; + + node->DefaultValue = defaultValue; + + node->ExternFlag = false; + node->InternFlag = true; + node->Parent = this; + + Nodes.insert(Nodes.begin(), node); + + return true; +} + + +inline CDeclarationNode* CClassNode::getDeclarationNode(const std::string &name) +{ + CDeclarationNode *node; + if ((node = dynamic_cast(getNode(name))) == NULL) + error("declaration '"+name+"' not found"); + return node; +} + +inline bool CClassNode::useEntityId() +{ + //return !ClassKey.empty() && getTypeNode(getKey()->Type)->CppType == "CEntityId"; + CDeclarationNode* k = getClassKey(); + return k!=NULL && getTypeNode(k->Type)->CppType == "CEntityId"; +} + +inline CDeclarationNode* CClassNode::getClassKey() +{ + if (ClassKey.empty()) + { + if (Inherited.empty()) + return NULL; + CClassNode* p = getClassNode(Inherited); + return p->getClassKey(); + } + else + { + return getKey(); + } +} + + +inline CDeclarationNode* CClassNode::getKey() +{ + CDeclarationNode* key = NULL; + CClassNode* classNode = this; + while (classNode != NULL) + { + key = dynamic_cast(classNode->getNode(classNode->ClassKey)); + if (key != NULL) + return key; + classNode = getClassNode(Inherited, false); + } + error("key declaration '"+ClassKey+"' not found"); + return NULL; + //return getDeclarationNode(ClassKey); +} + +inline CDeclarationNode* CClassNode::getDeclaration(const std::string& name) +{ + CDeclarationNode* decl = NULL; + CClassNode* classNode = this; + while (classNode != NULL) + { + decl = dynamic_cast(classNode->getNode(name)); + if (decl != NULL) + return decl; + classNode = getClassNode(classNode->Inherited, false); + } + error("declaration '"+name+"' not found"); + return NULL; +} + + + +#endif diff --git a/code/ryzom/tools/pd_parser/parser.cpp b/code/ryzom/tools/pd_parser/parser.cpp index c0ea84bf2..733bad4df 100644 --- a/code/ryzom/tools/pd_parser/parser.cpp +++ b/code/ryzom/tools/pd_parser/parser.cpp @@ -1,4909 +1,4909 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#include "parser.h" -#include "cpp_output.h" -#include "templatizer.h" - -#include "parser_rules.h" - -#include -#include - -using namespace std; -using namespace NLMISC; -//using namespace RY_PDS; - - -bool GenerateCpp = true; -bool GenerateXmlDescription = true; -bool VerboseMode = false; -bool GenerateDebugMessages = false; -bool GenerateHAuto = false; -bool GenerateOnlyLogs = false; - - -CTokenizer Tokenizer; -CTemplatizer Templatizer; -CHashKey HashKey; - -string CurrentEnum; -CEnumNode *CurrentEnumNode = NULL; - -string DbDescriptionVersion("0.0"); - -string formatDescription(const string &str) -{ - string result; - - uint pos = 0; - - while (pos < str.size() && (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\r' || str[pos] == '\n')) - ++pos; - - bool first = true; - - while (pos < str.size()) - { - if (!first) - result += "\n"; - first = false; - - result += "* "; - - while (pos < str.size() && str[pos] != '\n') - result += str[pos++]; - - while (pos < str.size() && (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\r' || str[pos] == '\n')) - ++pos; - } - - return result; -} - -string strReplace(string str, const string &search, const string &replace) -{ - std::string::size_type pos = 0; - while ((pos = str.find(search)) != string::npos) - str.replace(pos, search.size(), replace); - return str; -} - -string xmlSpecialChars(string str) -{ - str = strReplace(str, "&", "&"); - str = strReplace(str, "<", "<"); - str = strReplace(str, ">", ">"); - str = strReplace(str, "\"", """); - str = strReplace(str, "'", "'"); - - return str; -} - -string getFullStdPathNoExt(const string &path) -{ - string dir = NLMISC::toLower(NLMISC::CFile::getPath(path)); - string file = NLMISC::toLower(NLMISC::CFile::getFilenameWithoutExtension(path)); - - return dir.empty() ? file : NLMISC::CPath::standardizePath(dir)+file; -} - -string getFullStdPath(const string &path) -{ - string dir = NLMISC::toLower(NLMISC::CFile::getPath(path)); - string file = NLMISC::toLower(NLMISC::CFile::getFilename(path)); - - return dir.empty() ? file : NLMISC::CPath::standardizePath(dir)+file; -} - -string appendArg(const std::string& firstArgs, const std::string& nextArg) -{ - if (firstArgs.empty()) - return nextArg; - return firstArgs + ", " + nextArg; -} - -/* - * Start parsing - */ -CParseNode *parse(const string &file) -{ - HashKey = getSHA1(file); - - Tokenizer.readFile(file); - - if (Tokenizer.tokenize()) - return parseMain(Tokenizer); - return NULL; -} - - - -/* - * Execute nodes - */ - -// DB Node -bool CDbNode::prolog() -{ - addTypeNode("CSheetId", "NLMISC::CSheetId", "NLMISC::CSheetId::Unknown"); - addTypeNode("CEntityId", "NLMISC::CEntityId", "NLMISC::CEntityId::Unknown"); - addTypeNode("double", "double", "0.0"); - addTypeNode("float", "float", "0.0f"); - addTypeNode("sint64", "sint64", "(sint64)0"); - addTypeNode("uint64", "uint64", "(uint64)0"); - addTypeNode("sint32", "sint32", "0"); - addTypeNode("uint32", "uint32", "0"); - addTypeNode("sint16", "sint16", "0"); - addTypeNode("uint16", "uint16", "0"); - addTypeNode("sint8", "sint8", "0"); - addTypeNode("uint8", "uint8", "0"); - addTypeNode("ucchar", "ucchar", "0"); - addTypeNode("char", "char", "0"); - addTypeNode("bool", "bool", "false"); - - return true; -} - - - -bool inlineAccessors = false; -string getFunctionPrefix = "get"; -string setFunctionPrefix = "set"; -string newFunction = "addTo"; -string deleteFunction = "deleteFrom"; - -string indexVariable = "__i"; -string valueVariable = "__v"; -string keyVariable = "__k"; -string objectVariable = "__o"; - -bool inlineUserInitDefaultCode = false; -string userInitFunction = "init"; -string userReleaseFunction = "release"; - -bool inlineStaticPublic = false; -string staticCreateFunction = "create"; -string staticRemoveFunction = "remove"; -string staticSetUserFactoryFunction = "setFactory"; -string staticLoadFunction = "load"; -string staticUnloadFunction = "unload"; -string staticSetLoadCbFunction = "setLoadCallback"; -string staticGetFunction = "get"; -string staticCastFunction = "cast"; -string staticConstCastFunction = "cast"; -string staticBeginFunction = "begin"; -string staticEndFunction = "end"; - -bool inlineInternal = false; -string initFunction = "pds__init"; -string destroyFunction = "pds__destroy"; -string registerFunction = "pds__register"; -string registerAttributesFunction = "pds__registerAttributes"; -string unregisterFunction = "pds__unregister"; -string unregisterAttributesFunction = "pds__unregisterAttributes"; -string fetchFunction = "pds__fetch"; -string setParentFunction = "pds__setParent"; -string setUnnotifiedParentFunction = "pds__setParentUnnotified"; -string getTableFunction = "pds__getTable"; -string unlinkFunction = "pds__unlink"; -string notifyInitFunction = "pds__notifyInit"; -string notifyReleaseFunction = "pds__notifyRelease"; - -string clearFunction = "clear"; -string storeFunction = "store"; -string applyFunction = "apply"; -string declareTokensFunction = "pds__declareTokens"; - - -bool inlineStaticInternal = false; -string staticInitFactoryFunction = "pds_static__setFactory"; -string staticFactoryFunction = "pds_static__factory"; -string staticFetchFunction = "pds_static__fetch"; -string staticInitFunction = "pds_static__init"; -string staticNotifyLoadFailure = "pds_static__notifyFailure"; -string staticLoadCbAttribute = "__pds__LoadCallback"; - -bool inlineLog = false; -string logStartFunction = "pds__startLog"; -string logStopFunction = "pds__stopLog"; - -string PDSNamespace = "RY_PDS"; -string CPDSLibName = PDSNamespace+"::CPDSLib"; -string objectIndexName = PDSNamespace+"::CObjectIndex"; -string nullIndexName = PDSNamespace+"::CObjectIndex::null()"; -string TTableIndexName = PDSNamespace+"::TTableIndex"; -string TRowIndexName = PDSNamespace+"::TRowIndex"; -string TColumnIndexName = PDSNamespace+"::TColumnIndex"; -string INVALID_TABLE_INDEXName = PDSNamespace+"::INVALID_TABLE_INDEX"; -string INVALID_ROW_INDEXName = PDSNamespace+"::INVALID_ROW_INDEX"; -string indexAllocatorName = PDSNamespace+"::CIndexAllocator"; -string pdBaseDataName = PDSNamespace+"::IPDBaseData"; -//string pdBaseInheritDataName = PDSNamespace+"::IPDBaseInheritData"; -string CPDataName = PDSNamespace+"::CPData"; -string TPDFactoryName = PDSNamespace+"::TPDFactory"; -string TPDFetchName = PDSNamespace+"::TPDFetch"; -string TPDFetchFailureName = PDSNamespace+"::TPDFetchFailure"; - -bool inlineLogFunctions = false; - -string pdslibFunc(const std::string& func) -{ - //return CPDSLibName+"::"+func; - return "PDSLib."+func; -} - -bool CDbNode::epilog() -{ - uint i; - - Env = Templatizer.RootEnv; - setEnv("db", Name); - - string fullfile = getFullStdPathNoExt(MainFile.empty() ? Name : MainFile); - string filename = NLMISC::toLower(NLMISC::CFile::getFilenameWithoutExtension(fullfile)); - - setEnv("filename", filename); - setEnv("fullfilename", fullfile); - setEnv("headerfilename", strReplace(strupr(filename+".h"), ".", "_")); - - DbHpp.setFileHeader(filename+".h", "Initialisation of the "+Name+" database, declarations\n"+Description); - DbCpp.setFileHeader(filename+".cpp", "Initialisation of the "+Name+" database, implementation\n"+Description); - DbHppInline.setFileHeader(filename+"_inline.h", "Initialisation of the "+Name+" database, inline implementation\n"+Description); - - DbSummary << "\n\n"; - DbSummary << "Summary of " << Name << " database classes of database\n"; - DbSummary << "-----------------------------------------------------------------------------\n\n"; - DbSummary << "This file is automatically generated.\n"; - DbSummary << "This is a reminder of all classes generated and methods implemented.\n\n\n"; - - DbSummary << "Database " << Name << " is managed through 4 functions located in " << fullfile << ".h:\n\n"; - - DbSummary << Name << "::init():\n"; - DbSummary << "Initialises database context and connection towards database server (refered as PDS).\n"; - DbSummary << "All user factories must have been set before call to this function.\n"; - DbSummary << "Call this function in service init method.\n\n"; - - DbSummary << Name << "::ready():\n"; - DbSummary << "Tells whether the whole database engine is ready to work.\n"; - DbSummary << "You must not update any value nor call update() unless ready() is true.\n\n"; - - DbSummary << Name << "::update():\n"; - DbSummary << "Updates the database engine and sends updates to the PDS.\n"; - DbSummary << "Call this function each tick, provided ready() returned true.\n\n"; - - DbSummary << Name << "::release():\n"; - DbSummary << "Releases the database engine. Drops all data, closes the connection to the PDS.\n"; - DbSummary << "Call this function in service release method.\n\n"; - - DbSummary << "\n\n"; - DbSummary << "Summary of generated classes for " << Name << "\n\n"; - - DbHpp << "\n#ifndef " << strReplace(strupr(filename+".h"), ".", "_") << "\n"; - DbHpp << "#define " << strReplace(strupr(filename+".h"), ".", "_") << "\n"; - DbHpp << "\n"; - DbHpp << "#include \n"; - DbHpp << "#include \n"; - DbHpp << "\n"; - DbHpp << "namespace " << Name << "\n{\n\n"; - DbHpp.unindent(); - - if (!Pch.empty()) - { - DbCpp << "\n#include \"" << Pch << "\"\n\n"; - } - - DbCpp << "#include \"" << filename << ".h\"\n\n"; - DbCpp << "namespace " << Name << "\n{\n\n"; - DbCpp.unindent(); - - DbCpp << "RY_PDS::CPDSLib PDSLib;\n"; - - DbHppInline << "namespace " << Name << "\n{\n\n"; - DbHppInline.unindent(); - - - uint maxClassId = 0; - for (i=0; i"); - xmlDescription.push_back(""); - //xmlDescription.push_back(""); - xmlDescription.push_back(""); - - pass1(); - - pass2(); - - pass3(); - - // Check dependencies order - vector classesOrder; - vector filesOrder; - buildClassOrder(classesOrder, filesOrder); - - // generate all file prologs - for (i=0; igenerateProlog(); - } - - pass4(); - - // - initDb.init("init"); - initDb.IsInline = false; - initDb.Proto = "uint32 overrideDbId"; - initDb.Type = "void"; - initDb.Description = "Initialise the whole database engine.\nCall this function at service init."; - - readyDb.init("ready"); - readyDb.IsInline = false; - readyDb.Proto = ""; - readyDb.Type = "bool"; - readyDb.Description = "Tells if database engine is ready to work.\nEngine may not be ready because PDS is down, not yet ready\nor message queue to PDS is full."; - - updateDb.init("update"); - updateDb.IsInline = false; - updateDb.Proto = ""; - updateDb.Type = "void"; - updateDb.Description = "Update the database engine.\nCall this method once per tick, only if engine is ready (see also ready() above)."; - - logChatDb.init("logChat"); - logChatDb.IsInline = false; - logChatDb.Proto = "const ucstring& sentence, const NLMISC::CEntityId& from, const std::vector& to"; - logChatDb.Type = "void"; - logChatDb.Description = "Logs chat sentence with sender and receipiants."; - - logTellDb.init("logTell"); - logTellDb.IsInline = false; - logTellDb.Proto = "const ucstring& sentence, const NLMISC::CEntityId& from, const NLMISC::CEntityId& to"; - logTellDb.Type = "void"; - logTellDb.Description = "Logs tell sentence with sender and single recipient (might be player or group)."; - - releaseDb.init("release"); - releaseDb.IsInline = false; - releaseDb.Proto = ""; - releaseDb.Type = "void"; - releaseDb.Description = "Release the whole database engine.\nCall this function at service release."; - - // - generateClassesDeclaration(); - - // - generateClassesContent(classesOrder); - - // - generateLogContent(); - - xmlDescription.push_back(""); - xmlDescription.push_back("");; - - initDb.add("std::string\txmlDescription;"); - - DbXml.setXmlMode(); - - for (i=0; i\tids;"); - logTellDb.add("ids.push_back(to);"); - logTellDb.add(pdslibFunc("logChat")+"(sentence, from, ids);"); - logTellDb.flush(DbHpp, DbCpp, DbHppInline); - - releaseDb.add(pdslibFunc("release")+"();"); - releaseDb.flush(DbHpp, DbCpp, DbHppInline); - - DbHpp << "\n// @}\n\n"; - - DbHpp << "extern RY_PDS::CPDSLib PDSLib;\n"; - - DbHpp.indent(); - DbHpp << "\n} // End of " << Name <<"\n"; - - generateIncludes(filesOrder); - - DbHpp << "\n#include \"" << filename << "_inline.h\"\n\n"; - DbHpp << "\n#endif\n"; - DbHpp.flush(fullfile+".h"); - - DbCpp.indent(); - DbCpp << "\n} // End of " << Name <<"\n"; - DbCpp.flush(fullfile+".cpp"); - - DbHppInline.indent(); - DbHppInline << "\n} // End of " << Name <<"\n"; - DbHppInline.flush(fullfile+"_inline.h"); - - DbSummary.flush(fullfile+"_summary.txt"); - - for (i=0; igenerateEpilog(); - } - - return true; -} - - - -void CDbNode::pass1() -{ - /* - * PASS 1 - * - all type names and class names are known - * -> look for classes in set or backreferences - */ - - uint i; - - uint classId = 0; - uint typeId = 0; - - for (i=0; icheckClassReferences(); - classnd->Id = classId++; - - classnd->getFileNode()->IncludeStandard = true; - classnd->getFileNode()->IncludeDbFile = true; - } - - for (i=0; iId = typeId++; - - uint tsize = 0; - if (typend->StorageType == "bool") tsize = 1; - if (typend->StorageType == "char") tsize = 1; - if (typend->StorageType == "ucchar") tsize = 2; - if (typend->StorageType == "uint8") tsize = 1; - if (typend->StorageType == "sint8") tsize = 1; - if (typend->StorageType == "uint16") tsize = 2; - if (typend->StorageType == "sint16") tsize = 2; - if (typend->StorageType == "uint32") tsize = 4; - if (typend->StorageType == "sint32") tsize = 4; - if (typend->StorageType == "uint64") tsize = 8; - if (typend->StorageType == "sint64") tsize = 8; - if (typend->StorageType == "float") tsize = 4; - if (typend->StorageType == "double") tsize = 8; - if (typend->StorageType == "CEntityId") tsize = 8; - if (typend->StorageType == "CSheetId") tsize = 4; - - typend->Size = tsize; - - string xmlnode = "isEnum()) - { - CEnumNode *enumnd = static_cast(typend); - - xmlnode += " type='enum'>"; - xmlDescription.push_back(xmlnode); - uint j; - for (j=0; jValues.size(); ++j) - xmlDescription.push_back(""); - xmlDescription.push_back(""); - } - else if (typend->isDimension()) - { - CDimensionNode *dimnd = static_cast(typend); - - xmlnode += " type='dimension' dimension='"+toString(dimnd->Dimension)+"'/>"; - xmlDescription.push_back(xmlnode); - } - else - { - xmlnode += " type='type'/>"; - xmlDescription.push_back(xmlnode); - } - } -} - -void CDbNode::pass2() -{ - /* - * PASS 2 - * - class hierarchy, backreferences and in set information are known - * -> fill up attributes - */ - - uint i; - - for (i=0; iInherited.empty() && child->MappedFlag && !child->HasParent) - child->error("class cannot inherit another class and be mapped. Try to map base class instead."); - - if (child->MappedFlag && child->getClassKey() == NULL) - child->error("class is mapped and has no key defined"); - - child->ForceReference = (child->HasInheritance || child->MappedFlag || child->DerivatedFlag || (child->HasParent && !child->ParentIsHidden)); - - if (child->ForceReference && child->ParentIsHidden) - child->error("Parent attribute cannot be hidden because class has inheritance, is mapped or is derivated."); - - child->getFileNode()->IncludePDSLib = true; - - if (!child->Inherited.empty()) - { - CClassNode *icln = child; - CClassNode *lastMapped = (child->MappedFlag ? child : NULL); - while (!icln->Inherited.empty()) - { - icln = getClassNode(icln->Inherited); - if (icln->MappedFlag) - { - if (lastMapped != NULL) - lastMapped->error("class cannot be remapped since parent "+icln->Name+" is already mapped"); - lastMapped = icln; - } - } - - /* - if (icln->MappedFlag) - child->MapClass = icln; - */ - child->MapClass = lastMapped; - } - else if (child->MappedFlag) - { - child->MapClass = child; - } - - child->fillAttributes(); - } -} - - -void CDbNode::pass3() -{ - /* - * PASS 3 - * - attributes are known - * -> fill up backrefs and array/set forwardrefs - */ - - uint i; - - for (i=0; ifillRefs(); - } - - for (i=0; icomputeFriends(); - } -} - -void CDbNode::pass4() -{ - /* - * PASS 4 - * - everything is ok in database descriptor - * -> output c++ code - */ - - uint i; - - for (i=0; iHpp << "\n\n//\n// Typedefs & Enums\n//\n\n"; - } - - for (i=0; iExternFlag || type->InternFlag) - continue; - - type->generateContent(); - - } -} - - - -void CDbNode::generateClassesDeclaration() -{ - uint i; - - DbHpp << "\n//\n"; - DbHpp << "// Global Forward Declarations\n"; - DbHpp << "//\n\n"; - - for (i=0; iName << ";\n"; - } - - DbHpp << "\n"; - DbHpp << "//\n\n"; -} - -void CDbNode::generateIncludes(vector& filesOrder) -{ - uint i; - - DbHpp << "\n//\n"; - DbHpp << "// Includes\n"; - DbHpp << "//\n\n"; - - for (i=0; iSeparatedFlag) - { - filesOrder[i]->setEnv("as", getFileNoExtPath(filesOrder[i]->IncludeAs)); - DbHpp << "#include \"" << getFileNoExtPath(filesOrder[i]->IncludeAs) << ".h\"\n"; - } - } - - DbHpp << "\n"; - - for (i=0; iIncludeDbFile && !filesOrder[i]->SeparatedFlag) - { - filesOrder[i]->define("incinline"); - DbHpp << "#include \"" << getFileNoExtPath(filesOrder[i]->IncludeAs) << "_inline.h\"\n"; - } - } - - DbHpp << "\n"; - DbHpp << "//\n\n"; -} - -void CDbNode::generateClassesContent(vector& classesOrder) -{ - uint i; - - // - // output classes content - // - for (i=0; iId)+", \""+cln->Name+"\");"); - cln->generateContent(); - } -} - -void CDbNode::buildClassOrder(vector& classesOrder, vector& filesOrder) -{ - set checkedClasses; - - uint i; - - for (i=0; i beingChecked; - child->checkDependencies(beingChecked, checkedClasses, classesOrder); - } - - set checkedFiles; - filesOrder.clear(); - - for (i=0; i beingChecked; - child->checkDependencies(beingChecked, checkedFiles, filesOrder); - } - - for (i=0; iEnv = Env->nextArrayNode("files"); - - for (i=0; iEnv = classesOrder[i]->getFileNode()->Env->nextArrayNode("classes"); -} - - -void CDbNode::generateLogContent() -{ - uint logid = 0; - - uint i; - - for (i=0; iId = logid; - logid += (uint)child->Logs.size(); - - child->generateContent(); - } -} - -// get file path from this file -string CDbNode::getFileNoExtPath(const std::string& file) -{ - string thisPath = NLMISC::CFile::getPath(NLMISC::toLower(getDbFile())); - string filePath = NLMISC::CFile::getPath(NLMISC::toLower(file)); - string fileName = NLMISC::CFile::getFilename(NLMISC::toLower(file)); - - if (thisPath == filePath) - return CFile::getFilenameWithoutExtension(fileName); - else - return CPath::standardizePath(filePath)+CFile::getFilenameWithoutExtension(NLMISC::toLower(file)); -} - - - - -// File Node -bool CFileNode::prolog() -{ - CDbNode* db = getDbNode(); - db->FileNodes.push_back(this); - - if (GenerateOnlyLogs) - Generate = false; - - return true; -} - -bool CFileNode::epilog() -{ - return true; -} - -bool CFileNode::generateProlog() -{ - CDbNode* db = getDbNode(); - - if (!db->Description.empty()) - Hpp << db->Description << "\n"; - - string filename = NLMISC::toLower(CFile::getFilenameWithoutExtension(Name)); - - setEnv("fullfilename", getFullStdPathNoExt(Name)); - setEnv("filename", filename); - setEnv("headerfilename", strReplace(strupr(filename+".h"), ".", "_")); - setEnv("description", Description); - - Hpp.setFileHeader(filename+".h", Description); - Cpp.setFileHeader(filename+".cpp", Description); - HppInline.setFileHeader(filename+"_inline.h", Description); - - Hpp << "\n#ifndef " << strReplace(strupr(filename+".h"), ".", "_") << "\n"; - Hpp << "#define " << strReplace(strupr(filename+".h"), ".", "_") << "\n\n"; - - - Hpp << "#include \n"; - Hpp << "#include \n"; - Hpp << "#include \n"; - - if (GenerateHAuto) - { - Hpp << "#include \n"; - } - - if (IncludeStandard) - { - define("incstd"); - Hpp << "#include \n"; - Hpp << "#include \n"; - } - - Hpp << "#include \n"; - Hpp << "#include \n"; - - if (IncludePDSLib) - { - define("incpdslib"); - Hpp << "#include \n"; - Hpp << "#include \n"; - } - Hpp << "\n"; - - if (SeparatedFlag) - { - string fullfile = getFullStdPathNoExt(db->MainFile.empty() ? db->Name : db->MainFile); - string filename = NLMISC::toLower(NLMISC::CFile::getFilenameWithoutExtension(fullfile)); - Hpp << "#include \"" << filename << ".h\"\n"; - Hpp << "\n"; - } - - Hpp << "// User #includes\n"; - uint i; - for (i=0; inextArrayNode("incuser")->set("as", IncludeNodes[i]->Name); - Hpp << "#include \"" << IncludeNodes[i]->Name << "\"\n"; - } - - Hpp << "\nnamespace " << db->Name << "\n{\n\n"; - Hpp.unindent(); - - if (!db->Description.empty()) - HppInline << db->Description; - HppInline << "namespace " << db->Name << "\n{\n\n"; - HppInline.unindent(); - Hpp << "//\n// Forward declarations\n//\n\n"; - - if (!db->Pch.empty()) - { - Cpp << "\n"; - Cpp << "#include \""+db->Pch+"\""; - } - - Cpp << "\n"; - if (SeparatedFlag || !IncludeDbFile) - { - Cpp << "#include \"" << filename << ".h\"\n"; - } - else - { - Cpp << "#include \"" << getFileNoExtPath(getDbNode()->getDbFile()) << ".h\"\n"; - } - - Cpp << "\n"; - Cpp << "namespace " << db->Name << "\n{\n\n"; - Cpp.unindent(); - - return true; -} - -bool CFileNode::generateEpilog() -{ - CDbNode* db = getDbNode(); - - string fullfile = getFullStdPathNoExt(Name); - string filename = NLMISC::toLower(CFile::getFilenameWithoutExtension(Name)); - - Hpp.indent(); - Hpp << "\n} // End of " << db->Name <<"\n"; - - if (!IncludeDbFile || SeparatedFlag) - { - // add inline #include - Hpp << "\n\n//\n// Inline implementations\n//\n\n"; - Hpp << "#include \"" << filename << "_inline.h\"\n"; - } - - Hpp << "\n#endif\n"; - - HppInline.indent(); - HppInline << "\n} // End of " << db->Name <<"\n"; - - Cpp.indent(); - Cpp << "\n} // End of " << db->Name <<"\n"; - - if (Generate) - writeFile(); - - return true; -} - -string CFileNode::getFileNoExtPath(const string& file) -{ - string thisPath = NLMISC::CFile::getPath(NLMISC::toLower(Name)); - string filePath = NLMISC::CFile::getPath(NLMISC::toLower(file)); - string fileName = NLMISC::CFile::getFilename(NLMISC::toLower(file)); - - if (thisPath == filePath) - return CFile::getFilenameWithoutExtension(fileName); - else - return CFile::getFilenameWithoutExtension(NLMISC::toLower(file)); -} - -void CFileNode::writeFile() -{ - string fullfile = getFullStdPathNoExt(Name); - - Hpp.flush(fullfile+".h"); - Cpp.flush(fullfile+".cpp"); - HppInline.flush(fullfile+"_inline.h"); -} - -void CFileNode::checkDependencies(set &beingChecked, - set &checkedFiles, - vector &filesOrder) -{ - if (beingChecked.find(this) != beingChecked.end()) - error("circular dependency in file '"+Name+"'"); - - if (checkedFiles.find(this) != checkedFiles.end()) - return; - - beingChecked.insert(this); - checkedFiles.insert(this); - - set::iterator it; - for (it=Dependencies.begin(); it!=Dependencies.end(); ++it) - { - CFileNode *fileNode = *it; - if (fileNode == this) - continue; - - fileNode->checkDependencies(beingChecked, checkedFiles, filesOrder); - } - - filesOrder.push_back(this); -} - - - - - - - -// Type Node -bool CTypeNode::prolog() -{ - CDbNode* db = getDbNode(); - db->TypeNodes.push_back(this); - - return true; -} - -bool CTypeNode::generateContent() -{ - hOutput() << "/** " << Name << "\n"; - if (!Description.empty()) - { - hOutput() << Description << "\n"; - } - uint line, col; - string file; - getFileLine(line, col, file); - hOutput() << "defined at " << file << ":" << line << "\n"; - hOutput() << "*/\n"; - - hOutput() << "typedef " << getCppType() << " " << Name << ";\n\n"; - - - if (ToCppType != NULL) - { - CCppCodeNode *tocpp = static_cast(ToCppType); - - CFunctionGenerator toCppFunc; - - toCppFunc.init(storageToCpp()); - toCppFunc.setType(getName()); - toCppFunc.IsInline = true; - toCppFunc.Proto = StorageType+" _v"; - - toCppFunc.add(getName()+"\t__res;"); - toCppFunc.add(strReplace(strReplace(tocpp->RawCode, "$("+CppType+")", "__res"), "$("+StorageType+")", "_v")); - toCppFunc.add("return __res;"); - toCppFunc.flush(hOutput(), cppOutput(), inlineOutput()); - } - if (ToStorageType != NULL) - { - CCppCodeNode *tostorage = static_cast(ToStorageType); - - CFunctionGenerator toStorageFunc; - - toStorageFunc.init(cppToStorage()); - toStorageFunc.setType(StorageType); - toStorageFunc.IsInline = true; - toStorageFunc.Proto = getName()+" _v"; - - toStorageFunc.add(StorageType+"\t__res;"); - toStorageFunc.add(strReplace(strReplace(tostorage->RawCode, "$("+StorageType+")", "__res"), "$("+CppType+")", "_v")); - toStorageFunc.add("return __res;"); - toStorageFunc.flush(hOutput(), cppOutput(), inlineOutput()); - } - - hOutput() << "\n"; - - return true; -} - - - -// Include Node -bool CIncludeNode::prolog() -{ - CFileNode* file = getFileNode(); - file->IncludeNodes.push_back(this); - return true; -} - - -// Include Node -bool CUsePchNode::prolog() -{ - CDbNode* db = getDbNode(); - db->Pch = Name; - return true; -} - - -// CppCode Node -bool CCppCodeNode::prolog() -{ - return true; -} - - - - - - -// Dimension Nodes -bool CDimensionNode::prolog() -{ - CDbNode* db = getDbNode(); - db->TypeNodes.push_back(this); - - if (Dimension < 256) - StorageType = "uint8"; - else if (Dimension < 65536) - StorageType = "uint16"; - else - StorageType = "uint32"; - - CppType = "uint32"; - - return true; -} - -bool CDimensionNode::epilog() -{ - return true; -} - -bool CDimensionNode::generateContent() -{ - hOutput() << "/** " << Name << "\n"; - if (!Description.empty()) - { - hOutput() << Description << "\n"; - } - uint line, col; - string file; - getFileLine(line, col, file); - hOutput() << "defined at " << file << ":" << line << "\n"; - hOutput() << "*/\n"; - - hOutput() << "typedef " << CppType << " " << Name << ";\n"; - hOutput() << "const " << getName() << "\t" << getSizeName() << " = " << Dimension << ";\n\n"; - - return true; -} - -// Enum Nodes -bool CEnumNode::prolog() -{ - CDbNode* db = getDbNode(); - db->TypeNodes.push_back(this); - - if (Name.empty() || Name[0] != 'T') - error("enum name '"+Name+"' is invalid, must begin with a 'T'"); - - CurrentValue = 0; - CurrentEnum = Name; - CurrentEnumNode = this; - - MinValue = 0; - MaxValue = 0; - - return true; -} - -bool CEnumNode::epilog() -{ - uint i; - - for (i=0; i(Nodes[i]); - if (!nd) - continue; - Values.insert(Values.end(), nd->Values.begin(), nd->Values.end()); - } - - for (i=0; i Values[i].second) - MinValue = Values[i].second; - if (MaxValue < Values[i].second) - MaxValue = Values[i].second; - } - - CurrentEnumNode = NULL; - return true; -} - -bool CEnumSimpleValueNode::prolog() -{ - CEnumNode *parent = dynamic_cast(Parent); - if (parent != NULL) - { - CurrentValue = parent->CurrentValue; - } - else - { - CurrentValue = 0; - } - uint i; - for (i=0; iValues.push_back(make_pair(Names[i], CurrentValue)); - } - if (parent != NULL) - ++(parent->CurrentValue); - - return true; -} - -bool CEnumSimpleValueNode::epilog() -{ - return true; -} - -bool CEnumRangeNode::prolog() -{ - CEnumNode *parent = dynamic_cast(Parent); - if (parent != NULL) - { - CurrentValue = parent->CurrentValue; - } - else - { - CurrentValue = 0; - } - - CurrentEnumNode->Values.push_back(make_pair(Name, CurrentValue)); - - return true; -} - -bool CEnumRangeNode::epilog() -{ - CEnumNode *parent = dynamic_cast(Parent); - if (parent != NULL) - { - parent->CurrentValue = CurrentValue; - } - - uint i; - for (i=0; i(Nodes[i]); - if (!nd) - continue; - Values.insert(Values.end(), nd->Values.begin(), nd->Values.end()); - } - - if (!EndRange.empty()) - { - CurrentEnumNode->Values.push_back(make_pair(EndRange, CurrentValue)); - } - - return true; -} - - -bool CEnumNode::generateContent() -{ - hOutput() << "/** " << Name << "\n"; - if (!Description.empty()) - { - hOutput() << Description << "\n"; - } - uint line, col; - string file; - getFileLine(line, col, file); - hOutput() << "defined at " << file << ":" << line << "\n"; - hOutput() << "*/\n"; - - string enumTruncName = Name.substr(1); - CClassGenerator gen; - gen.init("C"+enumTruncName); - gen.createPublic("enum", "Enum values", ""); - gen.createPublic("conv", "Conversion methods", "Use these methods to convert from enum value to string (and vice versa)"); - gen.createPrivate("init", "Enum initialisation", ""); - - uint j; - gen.addOther("enum "+Name+"\n", "enum"); - gen.addOther("{\n", "enum"); - for (j=0; j= "+getUnscopedUseSize()+")"); - gen.add("{"); - gen.add("nlwarning(\""+Name+"::toString(): value '%u' is not matched, \\\"Unknown\\\" string returned\", v);"); - gen.add("return _UnknownString;"); - gen.add("}"); - //gen.add(checkCode("v")); - gen.add("if (!_Initialised)"); - gen.add("{"); - gen.add("init();"); - gen.add("}"); - gen.add("return _StrTable[v];"); - - gen.startMethod(getName(), "fromString", "const std::string& v", "conv", false, true, true); - gen.add("if (!_Initialised)"); - gen.add("{"); - gen.add("init();"); - gen.add("}"); - gen.add("if(v==_UnknownString)"); - gen.add("{"); - gen.add("return Unknown;"); - gen.add("}"); - gen.add("const std::map::const_iterator\tit = _ValueMap.find(NLMISC::toLower(v));"); - gen.add("if (it == _ValueMap.end())"); - gen.add("{"); - gen.add("nlwarning(\""+Name+"::toString(): string '%s' is not matched, 'Unknown' enum value returned\", v.c_str());"); - gen.add("return "+getUnknownValue()+";"); - gen.add("}"); - gen.add("return (*it).second;"); - - - gen.startMethod("void", "init", "", "init", false, false, true); - gen.add("_StrTable.clear();"); - gen.add("_ValueMap.clear();"); - gen.add("_StrTable.resize("+toString(getSize()+1)+");"); - gen.add("uint\ti;"); - gen.add("for (i=0; i<"+toString(Values.size())+"; ++i)"); - gen.add("{"); - gen.add("_StrTable["+Name+"Convert[i].Value] = "+Name+"Convert[i].Name;"); - gen.add("_ValueMap[NLMISC::toLower(std::string("+Name+"Convert[i].Name))] = "+Name+"Convert[i].Value;"); - gen.add("}"); - - gen.add("_Initialised = true;"); - - - gen.addAttribute("bool", "_Initialised", "init", true, "false"); - gen.addAttribute("std::string", "_UnknownString", "init", true, "\""+getUnknownValue()+"\""); - gen.addAttribute("std::vector", "_StrTable", "init", true); - gen.addAttribute("std::map", "_ValueMap", "init", true, "", false, "std::map"); - - cppOutput() << "static const struct { char* Name; " << getName() << " Value; } " << Name << "Convert[] =\n"; - cppOutput() << "{\n"; - for (j=0; jClassNodes.push_back(this); - - return true; -} - -bool CClassNode::epilog() -{ - return true; -} - -string CClassNode::getUserCode(const string& name) -{ - uint i; - for (i=0; i(Nodes[i]); - if (!code) - continue; - - if (code->Name == name) - return code->RawCode; - } - - return ""; -} - - -void CClassNode::checkClassReferences() -{ - if (!Implements.empty()) - { - Gen.Inherit += (HasRowAccess ? string(", ") : string(""))+"public "+Implements; - getDbNode()->Implemented.insert(Implements); - } - - - if (!Inherited.empty()) - { - HasInheritance = true; - CClassNode *nd = getClassNode(Inherited); - nd->HasInheritance = true; - nd->ChildrenClasses.push_back(Name); - - Dependencies.insert(nd); - getFileNode()->Dependencies.insert(nd->getFileNode()); - } - - CClassNode* inherit = this; - while (inherit != NULL) - { - if (MappedFlag) - inherit->PDSMapped = true; - - inherit->Legacy.insert(this); - inherit = getClassNode(inherit->Inherited, false); - } - - uint i; - uint id = 0; - for (i=0; i(Nodes[i]); - if (!decl) - continue; - - decl->Id = id++; - - if (decl->ParentFlag) - { - if (HasParent) - decl->error("class '"+Name+"' already has a parent"); - - //if (MappedFlag) - // decl->error("class '"+Name+"' can't have a parent and be mapped at the same time"); - - CClassNode* inherit = this; - while (inherit != NULL) - { - inherit->PDSMapped = false; - inherit = getClassNode(inherit->Inherited, false); - } - - ParentClass = decl->ParentClass; - HasParent = true; - - ParentIsHidden = decl->HiddenFlag; - - decl->getClassNode(decl->ParentClass)->IsBackReferenced = true; - } - else if (decl->SetFlag) - { - decl->getClassNode(decl->Type)->IsInSet = true; - } - } -} - -void CClassNode::fillAttributes() -{ - if (HasParent && !IsBackReferenced && !HasInheritance && !IsInSet && !DerivatedFlag && !MappedFlag) - error("class '"+Name+"' has a parent whereas it is not backreferenced, has no inherited link and is not mapped"); - - uint i; - for (i=0; i(Nodes[i]); - if (!decl) - continue; - - uint j; - for (j=0; j(Nodes[j]) != NULL && Nodes[j]->Name == decl->Name) - decl->error("attribute '"+decl->Name+"' already defined"); - - if (decl->ParentFlag) - { - decl->DeclarationType = BackRef; - } - else if (decl->ArrayFlag) - { - CClassNode *classNd = NULL; - CTypeNode *typeNd = NULL; - - if ( (classNd = decl->getClassNode(decl->Type, false)) ) - { - if (classNd->IsBackReferenced || classNd->ForceReference) - { - if (decl->ForwardRefAttribute.empty()) - decl->error("no forward reference to parent in array declaration, class '"+decl->Type+"' is backref'd or has inheritance"); - - classNd->IsInArrayRef = true; - decl->IsRef = true; - decl->DeclarationType = ArrayRef; - - if (classNd->ParentIsHidden) - Dependencies.insert(classNd); - } - else - { - if (!decl->ForwardRefAttribute.empty()) - decl->error("forward reference declared whereas subclass is not backreferenced and has no inheritance link"); - - Dependencies.insert(classNd); - - classNd->IsInArray = true; - decl->IsRef = false; - decl->DeclarationType = ArrayClass; - } - } - else if ( (typeNd = decl->getTypeNode(decl->Type, false)) ) - { - decl->DeclarationType = ArrayType; - } - else - { - decl->error("type or class '"+decl->Type+"' not found"); - } - } - else if (decl->SetFlag) - { - decl->IsRef = true; - decl->DeclarationType = Set; - } - else - { - CClassNode *classNd = NULL; - CTypeNode *typeNd = NULL; - - if ( (classNd = decl->getClassNode(decl->Type, false)) ) - { - if (classNd->IsBackReferenced || classNd->ForceReference) - { - if (decl->ForwardRefAttribute.empty()) - decl->error("no forward reference to parent in array declaration, class '"+decl->Type+"' is backref'd or has inheritance"); - - decl->IsRef = true; - - decl->DeclarationType = ForwardRef; - } - else - { - if (!decl->ForwardRefAttribute.empty()) - decl->error("forward reference declared whereas subclass is not backreferenced and has no inheritance link"); - - Dependencies.insert(classNd); - - decl->IsRef = false; - - decl->DeclarationType = SimpleClass; - } - } - else if ( (typeNd = decl->getTypeNode(decl->Type, false)) ) - { - decl->IsType = true; - - decl->DeclarationType = SimpleType; - } - else - { - decl->error("type or class '"+decl->Type+"' not found"); - } - } - } - - CDeclarationNode *declNd = getClassKey(); - if (declNd != NULL) - { - if (!declNd->IsType) - error("attribute '"+declNd->Name+"' can't be a key, only simple type allowed"); - - declNd->IsKey = true; - } -} - -void CClassNode::fillRefs() -{ - uint i; - for (i=0; i(Nodes[i]); - if (!decl) - continue; - - switch (decl->DeclarationType) - { - case BackRef: - { - // check parent is a valid class - CClassNode *cln = decl->getClassNode(decl->ParentClass); - CDeclarationNode *dln = dynamic_cast(cln->getNode(decl->ParentField)); - if (!dln) decl->error("attribute '"+decl->ParentField+"' not found in class '"+decl->ParentClass+"'"); - - if (!dln->ArrayFlag && !dln->SetFlag && !ForceReference) - decl->error("back reference 'parent "+decl->ParentClass+":"+decl->ParentField+" "+decl->Name+"' is not forwarded in class '"+decl->ParentClass+"' with an array or a set"); - - if (dln->Type != Name || dln->ForwardRefAttribute != decl->Name) - decl->error("back reference 'parent "+decl->ParentClass+":"+decl->ParentField+" "+decl->Name+"' is not correctly forwarded in class '"+decl->ParentClass+"'"); - - Friends.insert(cln->Name); - } - break; - - case Set: - { - CClassNode *cln = decl->getClassNode(decl->Type); - CDeclarationNode *dln = dynamic_cast(cln->getNode(decl->ForwardRefAttribute)); - if (!dln) decl->error("attribute '"+decl->ForwardRefAttribute+"' not found in class '"+decl->Type+"'"); - - if (!dln->ParentFlag) - decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not backref'd in class '"+decl->Type+"'"); - - if (dln->ParentClass != Name || dln->ParentField != decl->Name) - decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not correctly backref'd in class '"+decl->Type+"'"); - - if (cln->getClassKey() == NULL) - decl->error("class '"+decl->Type+"' has no key defined, whereas it is used in a set"); - - cln->Friends.insert(Name); - ForwardFriends.insert(cln->Name); - } - break; - - case ArrayRef: - { - if (decl->ForwardRefAttribute.empty()) - decl->error("No forward reference defined"); - - CClassNode *cln = decl->getClassNode(decl->Type); - CDeclarationNode *dln = dynamic_cast(cln->getNode(decl->ForwardRefAttribute)); - CTypeNode *tln = decl->getTypeNode(decl->ArrayIndex); - getFileNode()->Dependencies.insert(tln->getFileNode()); - if (!dln) decl->error("attribute '"+decl->ForwardRefAttribute+"' not found in class '"+decl->Type+"'"); - - if (!dln->ParentFlag) - decl->error("array '"+decl->Type+":"+decl->ForwardRefAttribute+"["+decl->ArrayIndex+"] "+decl->Name+"' is not backref'd in class '"+decl->Type+"'"); - - if (dln->ParentClass != Name || dln->ParentField != decl->Name) - decl->error("array '"+decl->Type+":"+decl->ForwardRefAttribute+"["+decl->ArrayIndex+"] "+decl->Name+"' is not correctly backref'd in class '"+decl->Type+"'"); - - if (cln->getClassKey() == NULL) - decl->error("class '"+decl->Type+"' has no key defined, whereas it is used in an array of ref"); - CDeclarationNode *kdn = dynamic_cast(cln->getClassKey()); - if (!kdn) decl->error("attribute '"+cln->ClassKey+"' not found in class '"+cln->Name+"'"); - - if (kdn->Type != decl->ArrayIndex) - decl->error("type in array definition mismatch class '"+cln->Name+"' key definition"); - - cln->Friends.insert(Name); - ForwardFriends.insert(cln->Name); - } - break; - - case ForwardRef: - { - if (decl->ForwardRefAttribute.empty()) - decl->error("No forward reference defined"); - - CClassNode *cln = decl->getClassNode(decl->Type); - CDeclarationNode *dln = dynamic_cast(cln->getNode(decl->ForwardRefAttribute)); - if (!dln) decl->error("attribute '"+decl->ForwardRefAttribute+"' not found in class '"+decl->Type+"'"); - - if (!dln->ParentFlag) - decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not backref'd in class '"+decl->Type+"'"); - - if (dln->ParentClass != Name || dln->ParentField != decl->Name) - decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not correctly backref'd in class '"+decl->Type+"'"); - - cln->Friends.insert(Name); - ForwardFriends.insert(cln->Name); - } - break; - - case ArrayType: - { - CTypeNode *tln = decl->getTypeNode(decl->ArrayIndex); - getFileNode()->Dependencies.insert(tln->getFileNode()); - } - case SimpleType: - break; - - case ArrayClass: - { - CTypeNode *tln = decl->getTypeNode(decl->ArrayIndex); - getFileNode()->Dependencies.insert(tln->getFileNode()); - } - case SimpleClass: - { - CClassNode *cln = decl->getClassNode(decl->Type); - cln->Friends.insert(Name); - } - break; - - default: - decl->error("Can't decide declaration type"); - break; - } - } -} - -void CClassNode::computeFriends() -{ - bool added; - - do - { - added = false; - set::iterator itf, itsf; - - for (itf=Friends.begin(); !added && itf!=Friends.end(); ++itf) - { - CClassNode* pfriend = getClassNode(*itf); - - for (itsf=pfriend->Friends.begin(); !added && itsf!=pfriend->Friends.end(); ++itsf) - { - const string& sfriend = *itsf; - if (Friends.find(*itsf) == Friends.end()) - { - Friends.insert(*itsf); - added = true; - } - } - } - } - while (added); -} - - -void CClassNode::checkDependencies(set &beingChecked, - set &checkedClasses, - vector &classesOrder) -{ - if (beingChecked.find(this) != beingChecked.end()) - error("circular dependency in class '"+Name+"'"); - - if (checkedClasses.find(this) != checkedClasses.end()) - return; - - beingChecked.insert(this); - checkedClasses.insert(this); - - set::iterator it; - for (it=Dependencies.begin(); it!=Dependencies.end(); ++it) - { - CClassNode *classNode = *it; - - classNode->checkDependencies(beingChecked, checkedClasses, classesOrder); - } - - classesOrder.push_back(this); -} - - -// -void CClassNode::buildInit() -{ - CDbNode *db = getDbNode(); - - if (!Init.empty()) - return; - - if (!Inherited.empty()) - { - CClassNode *mother = getClassNode(Inherited); - if (mother) - { - mother->buildInit(); - Init = mother->Init; - - uint i; - for (i=0; iType); - InitProto += "const "+typeNode->getName()+" &"+Init[i]->Name; - InitCallArgs += Init[i]->Name; - } - } - } - - if (!ClassKey.empty()) - { - CDeclarationNode *decl = dynamic_cast(getNode(ClassKey)); - if (decl) - { - Init.push_back(decl); - - if (!InitProto.empty()) - InitProto += ", "; - - CTypeNode* typeNode = getTypeNode(decl->Type); - InitProto += "const "+typeNode->getName()+" &"+decl->Name; - } - } -} - - - - - - -void CClassNode::computeAttributesColumns() -{ - if (Columns >= 0) - return; - - CDbNode *db = getDbNode(); - - Columns = 0; - if (!Inherited.empty()) - { - CClassNode *mother = getClassNode(Inherited); - mother->computeAttributesColumns(); - Columns = mother->Columns; - - Attributes = mother->Attributes; - } - - uint attribId = (uint)Attributes.size(); - uint i; - for (i=0; i(Nodes[i]); - if (decl == NULL) - continue; - - Attributes.push_back(decl); - - decl->Column = Columns; - decl->Id = attribId++; - CColumn col; - - // All for backref, set, forwardref, type - switch (decl->DeclarationType) - { - case ForwardRef: - decl->Columns = 1; - col.Name = decl->Name; - col.Type = ForwardRef; - col.TypeStr = "forwardref"; - col.TypeId = decl->getClassNode(decl->Type)->Id; - col.ByteSize = 8; - decl->ColumnList.push_back(col); - break; - case BackRef: - decl->Columns = 1; - col.Name = decl->Name; - col.Type = BackRef; - col.TypeStr = "backref"; - col.TypeId = decl->getClassNode(decl->ParentClass)->Id; - col.ByteSize = 8; - decl->ColumnList.push_back(col); - break; - case SimpleType: - decl->Columns = 1; - col.Name = decl->Name; - col.Type = SimpleType; - col.TypeStr = "type"; - col.TypeId = decl->getTypeNode(decl->Type)->Id; - col.ByteSize = decl->getTypeNode(decl->Type)->Size; - decl->ColumnList.push_back(col); - break; - case Set: - decl->Columns = 1; - col.Name = decl->Name; - col.Type = Set; - col.TypeStr = "set"; - col.TypeId = decl->getClassNode(decl->Type)->Id; - col.ByteSize = 4; - decl->ColumnList.push_back(col); - break; - case SimpleClass: - { - CClassNode *sub = decl->getClassNode(decl->Type); - sub->computeAttributesColumns(); - decl->Columns = sub->Columns; - - uint i, j; - for (i=0; iAttributes.size(); ++i) - { - CDeclarationNode *attrib = sub->Attributes[i]; - - for (j=0; jColumnList.size(); ++j) - { - col.Name = decl->Name+"."+attrib->ColumnList[j].Name; - col.Type = attrib->ColumnList[j].Type; - col.TypeStr = attrib->ColumnList[j].TypeStr; - col.TypeId = attrib->ColumnList[j].TypeId; - col.ByteSize = attrib->ColumnList[j].ByteSize; - decl->ColumnList.push_back(col); - } - } - } - break; - case ArrayRef: - { - CIndexNode *indexNd = decl->getIndexNode(decl->ArrayIndex); - uint numInEnum = indexNd->getSize(); - decl->Columns = numInEnum; - - uint i; - for (i=0; iName+"["+indexNd->getIndexName(i)+"]"; - col.Type = ForwardRef; - col.TypeStr = "forwardref"; - col.TypeId = decl->getClassNode(decl->Type)->Id; - col.ByteSize = 8; - decl->ColumnList.push_back(col); - } - } - break; - case ArrayType: - { - CIndexNode *indexNd = decl->getIndexNode(decl->ArrayIndex); - uint numInEnum = indexNd->getSize(); - decl->Columns = numInEnum; - - uint i; - for (i=0; iName+"["+indexNd->getIndexName(i)+"]"; - col.Type = SimpleType; - col.TypeStr = "type"; - col.TypeId = decl->getTypeNode(decl->Type)->Id; - col.ByteSize = decl->getTypeNode(decl->Type)->Size; - decl->ColumnList.push_back(col); - } - } - break; - case ArrayClass: - { - CIndexNode *indexNd = decl->getIndexNode(decl->ArrayIndex); - - CClassNode *sub = decl->getClassNode(decl->Type); - sub->computeAttributesColumns(); - - uint numInEnum = indexNd->getSize(); - decl->Columns = numInEnum*sub->Columns; - - uint i, j, k; - for (k=0; kAttributes.size(); ++i) - { - CDeclarationNode *attrib = sub->Attributes[i]; - - for (j=0; jColumnList.size(); ++j) - { - col.Name = decl->Name+"["+indexNd->getIndexName(k)+"]."+attrib->ColumnList[j].Name; - col.Type = attrib->ColumnList[j].Type; - col.TypeStr = attrib->ColumnList[j].TypeStr; - col.TypeId = attrib->ColumnList[j].TypeId; - col.ByteSize = attrib->ColumnList[j].ByteSize; - decl->ColumnList.push_back(col); - } - } - } - } - break; - } - - Columns += decl->Columns; - } -} - - - - - -bool CClassNode::generateContent() -{ - nlassert(Env != NULL); - - uint line, col; - string file; - getFileLine(line, col, file); - - setEnv("name", Name); - if (!Description.empty()) - setEnv("description", Description); - setEnv("deffile", file); - setEnv("defline", line); - - computeAttributesColumns(); - - uint j; - - // - // generate description - // - hOutput() << "/** " << Name << "\n"; - if (!Description.empty()) - hOutput() << Description << "\n"; - - hOutput() << "defined at " << file << ":" << line << "\n"; - hOutput() << "*/\n"; - - CCppOutput& DbSummary = getDbNode()->DbSummary; - DbSummary << "Class " << getDbNode()->Name << "::" << Name << ":\n"; - DbSummary << "----------------------------------------------------------\n"; - DbSummary << "located in file \"" << getFullStdPathNoExt(getFileNode()->Name) << ".h\"\n"; - DbSummary << "defined in file \"" << getFullStdPath(file) << "\"\n"; - DbSummary << "The class contains:\n\n"; - - Gen.init(Name); - Gen.createPublic("methods", "Accessors and Mutators methods", "Use these methods to change a value, add or delete elements."); - Gen.createPublic("map", "Public Management methods", "Use these methods to create, load, unload and get\nan object from database."); - Gen.createPublic("user", "User defined attributes and methods", "This code was verbatim copied from source file"); - Gen.createPublic("construct", "Public constructor", "This constructor is public to allow direct instanciation of the class"); - Gen.createPublic("persist", "Persistent methods declaration", ""); - Gen.createProtected("userinit", "User defined init and release methods", "Overload those methods to implement init and release behaviours"); - Gen.createProtected("attributes", "Attributes", "Don't modify those value manually, use accessors and mutators above"); - Gen.createProtected("internal", "Internal Management methods"); - Gen.createProtected("inherit map"); - Gen.createProtected("factories", "Default Factory and Fetch methods"); - Gen.createProtected("friends"); - - // EGS Compat - // -- begin - - Gen.startRaw("persist", false); - ApplyId = Gen.startMethod("void", applyFunction, "CPersistentDataRecord &__pdr", "persist", false, inlineInternal, false, false, "", HasInheritance); - StoreId = Gen.startMethod("void", storeFunction, "CPersistentDataRecord &__pdr", "persist", true, inlineInternal, false, false, "", HasInheritance); - - ClearId = Gen.startMethod("void", clearFunction, "", "map", false, inlineStaticPublic, false, false, "", HasInheritance); - Gen.setDescription("Clear whole object content but key (delete subobjects if there are, key is left unmodified), default clear value is 0."); - - StoreId.add("uint16\t__Tok_MapKey = __pdr.addString(\"__Key__\");"); - StoreId.add("uint16\t__Tok_MapVal = __pdr.addString(\"__Val__\");"); - StoreId.add("uint16\t__Tok_ClassName = __pdr.addString(\"__Class__\");"); - ApplyId.add("uint16\t__Tok_MapKey = __pdr.addString(\"__Key__\");"); - ApplyId.add("uint16\t__Tok_MapVal = __pdr.addString(\"__Val__\");"); - ApplyId.add("uint16\t__Tok_ClassName = __pdr.addString(\"__Class__\");"); - - if (!Inherited.empty()) - { - StoreId.add("uint16\t__Tok_Parent = __pdr.addString(\"__Parent__\");"); - ApplyId.add("uint16\t__Tok_Parent = __pdr.addString(\"__Parent__\");"); - } - - for (j=0; jParent != this) - continue; - - if (decl->DeclarationType == BackRef) - { - ApplyId.add(decl->cppName()+" = NULL;"); - } - else - { - StoreId.add("uint16\t"+decl->tokenName()+" = __pdr.addString(\""+decl->Name+"\");"); - ApplyId.add("uint16\t"+decl->tokenName()+" = __pdr.addString(\""+decl->Name+"\");"); - } - } - - ApplyId.add("while (!__pdr.isEndOfStruct())"); - ApplyId.add("{"); - ApplyId.add( "if (false) {}"); - - if (!Inherited.empty()) - { - StoreId.add("__pdr.pushStructBegin(__Tok_Parent);"); - StoreId.add(Inherited+"::store(__pdr);"); - StoreId.add("__pdr.pushStructEnd(__Tok_Parent);"); - - ApplyId.add("else if (__pdr.peekNextToken() == __Tok_Parent)"); - ApplyId.add("{"); - ApplyId.add( "__pdr.popStructBegin(__Tok_Parent);"); - ApplyId.add( Inherited+"::apply(__pdr);"); - ApplyId.add( "__pdr.popStructEnd(__Tok_Parent);"); - ApplyId.add("}"); - } - - // -- end - - - for (j=0; j(Nodes[j]); - if (cpp == NULL || !cpp->Name.empty()) - continue; - - Gen.addOther(cpp->RawCode, "user"); - } - - HasRowAccess = false; - HasTableAccess = false; - - if (!Inherited.empty()) - { - setEnv("inherit", Inherited); - setEnv("inheritclass", Inherited); - - Gen.Inherit += "public "+Inherited; - HasRowAccess = true; - HasTableAccess = true; - } - else if (HasInheritance || IsBackReferenced || IsInSet || ForceReference) - { - setEnv("inherit", pdBaseDataName); - - Gen.Inherit += "public "+pdBaseDataName; - HasTableAccess = true; - HasRowAccess = true; - } - - if (Legacy.size() > 1 && HasTableAccess) - { - CClassGenerator::SMethodId castId = Gen.startMethod(Name+"*", staticCastFunction, pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false); - Gen.setDescription("Cast base object to "+Name); - castId.add("switch (obj->getTable())"); - castId.add("{"); - std::set::iterator itl; - for (itl=Legacy.begin(); itl!=Legacy.end(); ++itl) - { - CClassNode* child = (*itl); - castId.add("case "+toString(child->Id)+":"); - } - castId.add("return static_cast<"+Name+"*>(obj);"); - castId.add("}"); - castId.add("return NULL;"); - - CClassGenerator::SMethodId constCastId = Gen.startMethod("const "+Name+"*", staticConstCastFunction, "const "+pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false); - Gen.setDescription("Cast base object to const "+Name); - constCastId.add("switch (obj->getTable())"); - constCastId.add("{"); - for (itl=Legacy.begin(); itl!=Legacy.end(); ++itl) - { - CClassNode* child = (*itl); - constCastId.add("case "+toString(child->Id)+":"); - } - constCastId.add("return static_cast(obj);"); - constCastId.add("}"); - constCastId.add("return NULL;"); - } - else if (Legacy.size() == 1 && HasTableAccess) - { - CClassGenerator::SMethodId castId = Gen.startMethod(Name+"*", staticCastFunction, pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false); - std::set::iterator itl = Legacy.begin(); - Gen.setDescription("Cast base object to "+Name); - castId.add("return (obj->getTable() == "+toString((*itl)->Id)+") ? static_cast<"+Name+"*>(obj) : NULL;"); - - CClassGenerator::SMethodId constCastId = Gen.startMethod("const "+Name+"*", staticConstCastFunction, "const "+pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false); - Gen.setDescription("Cast base object to const "+Name); - constCastId.add("return (obj->getTable() == "+toString((*itl)->Id)+") ? static_cast(obj) : NULL;"); - } - else - { - } - - if (HasRowAccess) - define("hasrowaccess"); - if (HasTableAccess) - define("hastableaccess"); - - if (!Implements.empty()) - { - setEnv("implements", Implements); - Gen.Inherit += (HasRowAccess ? string(", ") : string(""))+"public "+Implements; - } - - // - // generate init method - // - buildInit(); - - setEnv("initproto", InitProto); - - InitId = Gen.startMethod("void", initFunction, InitProto, "internal", false, inlineInternal, false, false, "", HasInheritance); - if (!Inherited.empty()) - { - InitId.add(Inherited + "::" + initFunction + "(" + InitCallArgs + ");"); - setEnv("initcallargs", InitCallArgs); - } - - DestroyId = Gen.startMethod("void", destroyFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); - FetchId = Gen.startMethod("void", fetchFunction, CPDataName+" &data", "internal", false, inlineInternal, false, false, "", HasInheritance); - RegisterId = Gen.startMethod("void", registerFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); - RegisterAttributesId = Gen.startMethod("void", registerAttributesFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); - UnregisterId = Gen.startMethod("void", unregisterFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); - UnregisterAttributesId = Gen.startMethod("void", unregisterAttributesFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); - SetParentId; - SetUnnotifiedParentId; - if (HasParent) - { - SetParentId = Gen.startMethod("void", setParentFunction, ParentClass+"* __parent", "internal", false, inlineInternal); - SetUnnotifiedParentId = Gen.startMethod("void", setUnnotifiedParentFunction, ParentClass+"* __parent", "internal", false, inlineInternal); - } - - if (HasRowAccess && GenerateDebugMessages) - { - DestroyId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": destroy %u:%u\", "+getId()+", __BaseRow);"); - FetchId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": fetch %u:%u\", "+getId()+", __BaseRow);"); - } - - if (!Inherited.empty()) - { - FetchId.add(Inherited+"::"+fetchFunction+"(data);"); - } - - if (DerivatedFlag) - { - UserInitId = Gen.startMethod("void", userInitFunction, "", "userinit", false, inlineUserInitDefaultCode, false, false, "", true); - UserReleaseId = Gen.startMethod("void", userReleaseFunction, "", "userinit", false, inlineUserInitDefaultCode, false, false, "", true); - } - - NotifyInitId = Gen.startMethod("void", notifyInitFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); - string initUCode = getUserCode("onInit"); - if (!Inherited.empty()) - Gen.add(Inherited+"::"+notifyInitFunction+"();"); - if (DerivatedFlag) - Gen.add(userInitFunction+"();"); - if (!initUCode.empty()) - { - Gen.add("{"); - uint line, col; - string file; - getFileLine(line, col, file); - Gen.add("// "+Name+" init user code, defined at "+file+":"+toString(line)); - Gen.add(initUCode); - Gen.add("}"); - } - - NotifyReleaseId = Gen.startMethod("void", notifyReleaseFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); - string releaseUCode = getUserCode("onRelease"); - if (!releaseUCode.empty()) - { - Gen.add("{"); - uint line, col; - string file; - getFileLine(line, col, file); - Gen.add("// "+Name+" release user code, defined at "+file+":"+toString(line)); - Gen.add(releaseUCode); - Gen.add("}"); - } - if (DerivatedFlag) - Gen.add(userReleaseFunction+"();"); - if (!Inherited.empty()) - Gen.add(Inherited+"::"+notifyReleaseFunction+"();"); - else if (HasRowAccess) - Gen.add(pdslibFunc("release")+"("+getId()+", __BaseRow);"); - - if (!Inherited.empty()) - { - DestroyId.add(Inherited+"::"+destroyFunction+"();"); - ClearId.add(Inherited+"::"+clearFunction+"();"); - } - - // - // Generate XML description - // - string xmlnode; - xmlnode += "Id)+"'"; - } - CDeclarationNode *dln = getClassKey(); - if (dln != NULL) - { - xmlnode += " key='"+toString(dln->Id)+"'"; - } - if (MapClass && !MapClass->HasParent) - { - xmlnode += " mapped='"+toString(MapClass->Id)+"'"; - } - if (HasRowAccess) - { -/* - if (!Reserve.empty()) - { - xmlnode += " allocate='"+(Reserve)+"'"; - } - else - { - xmlnode += " allocate='10000'"; - } -*/ - } - xmlnode += " columns='"+toString(Columns)+"'"; - xmlnode += ">"; - getDbNode()->xmlDescription.push_back(xmlnode); - - indexUsedInInit = false; - indexUsedInDestroy = false; - indexUsedInFetch = false; - tableAndRowIndicesUsedInFetch = false; - indexUsedInRegister = false; - indexUsedInUnregister = false; - - // generate code for init of new index - if (HasRowAccess) - { - RegisterId.add("__BaseRow = _IndexAllocator.allocate();"); - if (GenerateDebugMessages) - { - if (MapClass != NULL) - { - CDeclarationNode* key = MapClass->getKey(); - RegisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": register %u:%u, key="+key->displayPrintfPrefix()+"\", "+getId()+", __BaseRow, "+key->displayCppCode()+");"); - } - else - { - RegisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": register %u:%u\", "+getId()+", __BaseRow);"); - } - } - - string oeid; - if (useEntityId()) - { - oeid = ", "+getClassKey()->cppName(); - } - - RegisterId.add(pdslibFunc("allocateRow")+"("+getId()+", __BaseRow, "+(PDSMapped ? MapClass->getKey()->toUint64() : "0")+oeid+");"); - RegisterId.add(registerAttributesFunction + "();"); - - RegisterAttributesId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": registerAttributes %u:%u\", "+getId()+", __BaseRow);"); - - // send key to the pds (if key exists) - if (!ClassKey.empty()) - { - CDeclarationNode *keyNode = getKey(); - CTypeNode *keyTypeNode = getTypeNode(keyNode->Type); - ///// TYPE CAST - RegisterAttributesId.add(pdslibFunc("set")+"("+getId()+", __BaseRow, ("+TColumnIndexName+")("+toString(keyNode->Column)+"), "+keyTypeNode->castToPDS(getKey()->cppName())+");"); - } - - if (!Inherited.empty()) - { - RegisterAttributesId.add(Inherited + "::" + registerAttributesFunction + "();"); - } - - UnregisterAttributesId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unregisterAttributes %u:%u\", "+getId()+", __BaseRow);"); - - if (!Inherited.empty()) - { - UnregisterAttributesId.add(Inherited + "::" + unregisterAttributesFunction + "();"); - } - - if (HasParent) - { - UnregisterAttributesId.add(setParentFunction+"(NULL);"); - } - - if (GenerateDebugMessages) - { - if (MapClass != NULL) - { - CDeclarationNode* key = MapClass->getKey(); - UnregisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unregister %u:%u, key="+key->displayPrintfPrefix()+"\", "+getId()+", __BaseRow, "+key->displayCppCode()+");"); - } - else - UnregisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unregister %u:%u\", "+getId()+", __BaseRow);"); - } - - UnregisterId.add(unregisterAttributesFunction + "();"); - - oeid = ""; - if (useEntityId()) - { - oeid = ", "+getClassKey()->cppName(); - } - - UnregisterId.add(pdslibFunc("deallocateRow")+"("+getId()+", __BaseRow"+oeid+");"); - UnregisterId.add("_IndexAllocator.deallocate(__BaseRow);"); - //UnregisterId.add(destroyFunction+"();"); - } - - // - // add attributes and methods - // - attributes are in private part - // - read accessor are public - // - write accessor are public or delegated in public accessor objects - // - for (j=0; j(Nodes[j]); - if (!dln) - continue; - - dln->Env = Env->nextArrayNode("dcl"); - - dln->generateContent(); - - } - - uint columnId = 0; - - for (j=0; jxmlDescription.push_back("XmlNode+"/>"); - - uint k; - for (k=0; kColumnList.size(); ++k) - { - CColumn &column = dln->ColumnList[k]; - //getDbNode()->xmlDescription.push_back(""); - ++columnId; - } - - //getDbNode()->xmlDescription.push_back(""); - } - - getDbNode()->xmlDescription.push_back(""); - - if (HasTableAccess) - { - Gen.startConstructor("", "construct"); - Gen.add("__BaseTable = "+toString(Id)+";"); - - Gen.startDestructor("construct", true, DerivatedFlag || HasInheritance); - } - - // when inited/fetched a mapped class, map id to object - if (MappedFlag) - { - InitId.add("_Map["+getKey()->getFunc()+"()] = this;"); - FetchId.add("_Map["+getKey()->getFunc()+"()] = this;"); - DestroyId.add("_Map.erase("+getKey()->getFunc()+"());"); - } - - // - // generate IPDBaseData API - // - - if (MappedFlag || DerivatedFlag || HasInheritance || ForceReference) - { - if (DerivatedFlag) - { - Gen.startMethod("void", staticSetUserFactoryFunction, TPDFactoryName+" userFactory", "map", false, inlineStaticPublic, true); - Gen.setDescription("Set user factory for this class (as class is indicated as derived, a home made constructor must be provided)"); - Gen.add(staticInitFactoryFunction+"(userFactory);"); - } - - Gen.startMethod("void", staticInitFactoryFunction, TPDFactoryName+" userFactory", "factories", false, inlineStaticInternal, true); - Gen.add("if (!_FactoryInitialised)"); - Gen.add("{"); - Gen.add(pdslibFunc("registerClass")+"(" + toString(Id) + ", userFactory, "+staticFetchFunction+", "+((MappedFlag && !HasParent) ? staticNotifyLoadFailure : string("NULL"))+");"); - Gen.add("_FactoryInitialised = true;"); - Gen.add("}"); - - Gen.addAttribute("bool", "_FactoryInitialised", "factories", true); - - if (MappedFlag || HasInheritance || ForceReference) - { - // - // create: create an object, then init attributes and register - // - - Gen.startMethod(Name+"*", staticCreateFunction, InitProto, "map", false, inlineStaticPublic, true); - Gen.setDescription("Create an object of the "+Name+" class, and declare it to the PDS."); - if (GenerateDebugMessages) - { - Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": create\");"); - } - if (DerivatedFlag) - { - Gen.add(Name + "\t*"+objectVariable+" = static_cast<" + Name + "*>("+pdslibFunc("create")+"("+toString(Id)+"));"); - } - else - { - Gen.add(Name + "\t*"+objectVariable+" = static_cast<" + Name + "*>("+staticFactoryFunction+"());"); - } - - string str = objectVariable+"->" + initFunction + "("; - uint i; - for (i=0; iName; - str += ");"; - Gen.add(str); - Gen.add(objectVariable+"->" + registerFunction + "();"); -/* - if (MappedFlag) - { - Gen.add("_Map["+MapClass->ClassKey+"] = "+objectVariable+";"); - } -*/ - Gen.add(objectVariable+"->"+notifyInitFunction+"();"); - Gen.add("return "+objectVariable+";"); - } - - if (MappedFlag) - { - CDeclarationNode *dln = (MapClass != NULL ? MapClass->getKey() : NULL); - CTypeNode *keyType = getTypeNode(dln->Type); - - // only authorize remove/load/unload for mapped objects that are roots - if (!HasParent) - { - Gen.startMethod("void", staticRemoveFunction, "const "+keyType->getName()+"& "+dln->Name, "map", false, inlineStaticPublic, true); - Gen.setDescription("Destroy an object from the PDS. Caution! Object will no longer exist in database.\nAlso children (that is objects that belong to this object) are also destroyed."); - if (GenerateDebugMessages) - { - Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": remove "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");"); - } - Gen.add("std::map<" + keyType->getName() + "," + Name + "*>::iterator\tit = _Map.find("+dln->Name+");"); - Gen.add("if (it != _Map.end())"); - Gen.add("{"); - Gen.add(Name + "*\t__o = (*it).second;"); - Gen.add("__o->"+notifyReleaseFunction+"();"); - Gen.add("__o->"+unregisterFunction+"();"); - Gen.add("__o->"+destroyFunction+"();"); - Gen.add("delete __o;"); - //Gen.add("_Map.erase(it);"); - Gen.add("}"); - - Gen.startMethod("void", staticLoadFunction, "const "+keyType->getName()+"& "+dln->Name, "map", false, inlineStaticPublic, true); - Gen.setDescription("Retrieve an object from the database.\nData are sent asynchronously, so the load callback is called when data are ready.\nUse get() to access to the loaded object."); - if (GenerateDebugMessages) - { - Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": load "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");"); - } - Gen.add(pdslibFunc("load")+"("+toString(Id)+", "+dln->toUint64(dln->Name)+");"); - - Gen.startMethod("void", staticSetLoadCbFunction, "void (*callback)(const "+keyType->getName()+"& key, "+Name+"* object)", "map", false, inlineStaticPublic, true); - Gen.setDescription("Setup load callback so client is warned that load succeded or failed."); - Gen.add(staticLoadCbAttribute+" = callback;"); - - Gen.startMethod("void", staticNotifyLoadFailure, "uint64 key", "factories", false, inlineStaticInternal, true); - Gen.add("if ("+staticLoadCbAttribute+" != NULL)"); - Gen.add("{"); - Gen.add(staticLoadCbAttribute+"("+keyType->castFromUser("key")+", NULL);"); - Gen.add("}"); - - Gen.addAttribute("void", staticLoadCbAttribute, "factories", true, "NULL", true, "const "+keyType->getName()+"& key, "+Name+"* object"); - - - // - Gen.startMethod("void", staticUnloadFunction, "const " + keyType->getName() + " &" + dln->Name, "map", false, inlineStaticPublic, true); - Gen.setDescription("Unload an object from the client memory. Object still exists in database and can be retrieved again using load."); - if (GenerateDebugMessages) - { - Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unload "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");"); - } - Gen.add("std::map<" + keyType->getName() + "," + Name + "*>::iterator\tit = _Map.find("+dln->Name+");"); - Gen.add("if (it != _Map.end())"); - Gen.add("{"); - Gen.add(Name + "*\t__o = (*it).second;"); - Gen.add("__o->"+notifyReleaseFunction+"();"); - Gen.add("__o->"+destroyFunction+"();"); - Gen.add("delete __o;"); - //Gen.add("_Map.erase(it);"); - Gen.add("}"); - } - - std::string mapType = "std::map<"+keyType->getName()+", "+Name+"*>"; - - Gen.startMethod(Name+"*", staticGetFunction, "const " + keyType->getName() + " &" + dln->Name, "map", false, inlineStaticPublic, true); - Gen.setDescription("Get an object in client. Object must have been previously loaded from database with a load."); - if (GenerateDebugMessages) - { - Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": get "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");"); - } - Gen.add(mapType+"::iterator\t__it = _Map.find("+dln->Name+");"); - if (GenerateDebugMessages) - { - Gen.add("if (__it == _Map.end())"); - Gen.add("nlwarning(\""+Name+": unable to get %\"NL_I64\"u, not found in map.\", "+dln->toUint64(dln->Name)+");"); - } - Gen.add("return (__it != _Map.end()) ? (*__it).second : NULL;"); - - Gen.startMethod(mapType+"::iterator", staticBeginFunction, "", "map", false, inlineStaticPublic, true); - Gen.setDescription("Return the begin iterator of the global map of "+Name); - Gen.add("return _Map.begin();"); - - Gen.startMethod(mapType+"::iterator", staticEndFunction, "", "map", false, inlineStaticPublic, true); - Gen.setDescription("Return the end iterator of the global map of "+Name); - Gen.add("return _Map.end();"); - } - } - - - // - // generate internal management functions - // - - if (HasRowAccess || MappedFlag) - { - if (MappedFlag) - { - CDeclarationNode *dln = (MappedFlag ? getKey() : NULL); - CTypeNode *keyType = getTypeNode(dln->Type); - Gen.addAttribute("std::map<" + keyType->getName() + "," + Name + "*>", "_Map", "inherit map", true); - } - - Gen.addAttribute(indexAllocatorName, "_IndexAllocator", "factories", true); - - Gen.startMethod("void", staticInitFunction, "", "internal", false, inlineInternal, true, false, "", false); - Gen.add(pdslibFunc("setIndexAllocator")+"("+toString(Id)+", _IndexAllocator);"); - if (MappedFlag || DerivatedFlag || HasInheritance || ForceReference) - { - if (DerivatedFlag) - { - // check factory has been set - Gen.add("nlassertex(_FactoryInitialised, (\"User Factory for class "+Name+" not set!\"));"); - Gen.add("// factory must have been set by user before database init called!"); - Gen.add("// You must provide a factory for the class "+Name+" as it is marked as derived"); - Gen.add("// Call "+getDbNode()->Name+"::"+Name+"::"+staticSetUserFactoryFunction+"() with a factory before any call to "+getDbNode()->Name+"::init()!"); - } - else - { - Gen.add(staticInitFactoryFunction+"("+staticFactoryFunction+");"); - } - } - - getDbNode()->initDb.add(Name+"::"+staticInitFunction+"();"); - - if (ForceReference) - { - if (!DerivatedFlag) // forbid factory function for derivated classes - { - Gen.startMethod(pdBaseDataName+"*", staticFactoryFunction, "", "factories", false, inlineStaticInternal, true); - Gen.add("return new " + Name + "();"); - } - - if (Inherited.empty()) - { - Gen.startMethod("void", staticFetchFunction, pdBaseDataName+" *object, "+CPDataName+" &data", "factories", false, inlineStaticInternal, true); - Gen.add(Name + "\t*"+objectVariable+" = static_cast<" + Name + "*>(object);"); - Gen.add(objectVariable+"->"+fetchFunction+"(data);"); - if (MappedFlag) - { - //Gen.add("_Map["+objectVariable+"->"+getKey()->getFunc()+"()] = "+objectVariable+";"); - if (!HasParent) - { - Gen.add("if ("+staticLoadCbAttribute+" != NULL)"); - Gen.add("{"); - Gen.add(staticLoadCbAttribute+"("+objectVariable+"->"+getKey()->getFunc()+"(), "+objectVariable+");"); - Gen.add("}"); - } - } - Gen.add(objectVariable+"->"+notifyInitFunction+"();"); - } - } - } - - // EGS Compat - // -- begin - - ApplyId.add( "else"); - ApplyId.add( "{"); - ApplyId.add( "nlwarning(\"Skipping unrecognised token: %s\", __pdr.peekNextTokenName().c_str());"); - ApplyId.add( "__pdr.skipData();"); - ApplyId.add( "}"); - ApplyId.add("}"); - - if (MappedFlag && !HasParent) - { - ApplyId.add(notifyInitFunction+"();"); - } - - - //EGSImplId.add("\n#include \"game_share/persistent_data_template.h\""); - //EGSImplId.add("#undef PERSISTENT_CLASS"); - //EGSImplId.add("#undef PERSISTENT_DATA"); - - // -- end - - set::iterator itf; - for (itf=Friends.begin(); itf!=Friends.end(); ++itf) - if (*itf != Name) - Gen.addOther("friend class "+(*itf)+";\n", "friends"); - for (itf=ForwardFriends.begin(); itf!=ForwardFriends.end(); ++itf) - if (*itf != Name) - Gen.addOther("friend class "+(*itf)+";\n", "friends"); - Gen.addOther("friend class "+CPDSLibName+";\n", "friends"); - CDbNode* dbNode = getDbNode(); - Gen.addOther("friend void "+dbNode->Name+"::init(uint32);\n", "friends"); - - Gen.flush(hOutput(), cppOutput(), inlineOutput()); - - DbSummary << "\n\n"; - - return true; -} - -void CClassNode::generateContentInCall(CCallContext *context) -{ - uint j; - for (j=0; j(Nodes[j]); - if (!dln) - continue; - - dln->generateContent(context); - } -} - - - - - - - - - -// Declaration Node -bool CDeclarationNode::prolog() -{ - return true; -} - -bool CDeclarationNode::epilog() -{ - return true; -} - - - -void CDeclarationNode::generateContent(CCallContext *context) -{ - ClassNode = static_cast(Parent); - - nlassert(Env != NULL); - - setEnv("name", Name); - - XmlNode = "name='"+Name+"' id='"+toString(Id)+"' columnid='"+toString(Column)+"' columns='"+toString(Columns)+"'"; - - if (context == NULL) - { - CCppOutput& DbSummary = getDbNode()->DbSummary; - DbSummary << "Attribute " << Name << ":\n"; - } - - switch (DeclarationType) - { - case SimpleType: - generateTypeContent(context); - break; - - case SimpleClass: - generateClassContent(context); - break; - - case BackRef: - generateBackRefContent(); - break; - - case ForwardRef: - generateForwardRefContent(); - break; - - case ArrayType: - generateArrayTypeContent(context); - break; - - case ArrayClass: - generateArrayClassContent(context); - break; - - case ArrayRef: - generateArrayRefContent(context); - break; - - case Set: - generateSetContent(context); - break; - - default: - error("Can't decide declaration type"); - break; - } - - if (context == NULL) - { - ClassNode->Gen.separator("methods"); - } - -} - - - -std::string CDeclarationNode::getAccessorName(CCallContext *context, const std::string& accessortype, const std::string& sep) -{ - return context->getRootCaller()->Name + sep +accessortype + context->getCallString(); -} - - -void CDeclarationNode::generateTypeContent(CCallContext *context) -{ - CClassGenerator& Gen = ClassNode->Gen; - CCppOutput& DbSummary = getDbNode()->DbSummary; - - CClassGenerator::SMethodId &InitId = ClassNode->InitId; - CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; - CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; - CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; - CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; - CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; - CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; - CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; - CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; - CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; - - string UCodeContext; - if (context != NULL) - UCodeContext = context->getUserCodeContext(); - - string onGetUser = getUserCode("onGet", UCodeContext); - string onSetUser = getUserCode("onSet", UCodeContext); - string onChangeUser = getUserCode("onChange", UCodeContext); - - CTypeNode *tnd = getTypeNode(Type); - XmlNode += " type='type' typeid='"+toString(tnd->Id)+"'"; - - setEnv("decltype", "type"); - setEnv("type", tnd->getName()); - define(IsKey, "iskey"); - setEnv("defaultvalue", tnd->getDefaultValue()); - setEnv("checkcode", tnd->checkCode(Name)); - - CCallContext ctx(this); - if (context != NULL) - ctx = context->getSubContext(this); - CClassGenerator &gen = ctx.getRootCaller()->Gen; - - // EGS Compat - // -- begin - - CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; - CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; - - - ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")"); - ApplyId.add("{"); - tnd->generateApplyCode(ApplyId, tokenName(), cppName()); - ApplyId.add("}"); - - tnd->generateStoreCode(StoreId, tokenName(), cppName()); - - // -- end - - CTemplatizerEnv* env = ctx.getRootDeclaration()->Env->nextArrayNode("accessors"); - - env->set("name", Name); - env->set("type", tnd->getName()); - env->set("defaultvalue", tnd->getDefaultValue()); - env->set("checkcode", tnd->checkCode(Name)); - env->define(ctx.getRootCaller()->HasRowAccess, "rowaccess"); - env->define(IsKey, "iskey"); - env->set("rootcallerid", ctx.getRootCaller()->getId()); - env->set("callstr", ctx.getCallString()); - env->set("callargs", ctx.getCallArgList()); - env->set("callpath", ctx.getCallPath()); - env->set("column", ctx.getColumn()); - env->set("valuevar", valueVariable); - env->set("castcpp", tnd->castToCpp(valueVariable)); - env->set("castpds", tnd->castToPDS(valueVariable)); - - vector checks = ctx.getCheckCode(); - for (uint i=0; inextArrayNode("checks")->set("check", checks[i]); - env->nextArrayNode("checks")->set("check", tnd->checkCode(valueVariable)); - - if (!onGetUser.empty()) env->set("onget", onGetUser); - if (!onSetUser.empty()) env->set("onset", onSetUser); - if (!onChangeUser.empty()) env->set("onchange", onChangeUser); - - // - // generate read accessor - // - if (ctx.getRootCaller()->HasRowAccess) - { - string arglist = ctx.getCallArgList(); - - gen.startMethod(tnd->getName(), getFunctionPrefix+ctx.getCallString(), arglist, "methods", true, inlineAccessors); - - DbSummary << "\t" << getFunctionPrefix+ctx.getCallString() << "\n"; - - uint i; - vector checks = ctx.getCheckCode(); - for (i=0; iHasRowAccess && !IsKey) - { - string arglist = ctx.getCallArgList(); - - if (!arglist.empty()) - arglist += ", "; - arglist += tnd->getName()+" "+valueVariable; - gen.startMethod("void", setFunctionPrefix+ctx.getCallString(), appendArg(arglist, "bool forceWrite=false"), "methods", false, inlineAccessors); - - DbSummary << "\t" << setFunctionPrefix << ctx.getCallString() << "\n"; - - if (GenerateHAuto) - { - gen.add("H_AUTO("+getAccessorName(&ctx, setFunctionPrefix, "_")+")"); - } - - if (VerboseMode) - { - string verbStr; - string callStr; - - verbStr = "nlinfo(\"" + ctx.getRootCaller()->Name + "(%d:%d)::" +setFunctionPrefix + ctx.getCallString() + "("; - - callStr = ctx.getDebugCallStringFmt(); - if (!callStr.empty()) - callStr += ", "; - - callStr += valueVariable+"="+tnd->getPrintfFmt(); - - verbStr += callStr; - verbStr += ")\", __BaseTable, __BaseRow, "; - - callStr = ctx.getDebugCallStringVal(); - if (!callStr.empty()) - callStr += ", "; - - callStr += tnd->getPrintfVal(valueVariable); - - verbStr += callStr; - verbStr += ");"; - - gen.add(verbStr); - } - - uint i; - vector checks = ctx.getCheckCode(); - for (i=0; icheckCode(valueVariable)); - - ///// TYPE CAST - if (!onChangeUser.empty()) - { - gen.add("if ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+")"); - gen.add("{"); - gen.add(onChangeUser); - gen.add("}"); - } - if (!onSetUser.empty()) - { - gen.add("{"); - gen.add(onSetUser); - gen.add("}"); - } - if (WriteTriggerFlag) - { - gen.add("if (forceWrite && ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+"))"); - } - else - { - gen.add("if (("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+") || forceWrite)"); - } - gen.add("{"); - bool useEntityId = ctx.hasRootEntityIdKey(); - if (useEntityId) - { - gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+", "+ctx.getRootCaller()->getKey()->cppName()+");"); - } - else - { - gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");"); - } - gen.add("}"); - gen.add(ctx.getCallPath()+" = "+tnd->castToCpp(valueVariable)+";"); - } - - // - // generate attribute - // - Gen.addAttribute(tnd->getName(), cppName(), "attributes"); - - - string defaultValue; - if (!DefaultValue.empty()) - defaultValue = DefaultValue; - else - defaultValue = tnd->getDefaultValue(); - - // - // generate init - // - if (!IsKey) - { - InitId.add(cppName()+" = "+defaultValue+";"); - } - else - { - InitId.add(tnd->checkCode(Name)); - InitId.add(cppName()+" = "+Name+";"); - } - - // - // generate create code - // - - - // - // generate fetch code - // - if (tnd->isEnum()) - FetchId.add("data.serialEnum("+cppName()+");"); - else if (tnd->CppType != tnd->StorageType) - { - FetchId.add("{"); - FetchId.add(tnd->StorageType+"\t_v;"); - FetchId.add("data.serial(_v);"); - FetchId.add(cppName()+" = "+tnd->castToCpp("_v")+";"); - FetchId.add("}"); - } - else - { - FetchId.add("data.serial("+cppName()+");"); - } - - // - // generate clear code - // - if (ctx.getRootCaller()->HasRowAccess && !IsKey) - { - ctx.getRootCaller()->ClearId.add(ctx.getCallPath()+" = "+defaultValue+";"); - ctx.getRootCaller()->ClearId.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(defaultValue)+");"); - } -} - - - - - - - - -void CDeclarationNode::generateClassContent(CCallContext *context) -{ - setEnv("decltype", "class"); - - CClassGenerator &Gen = ClassNode->Gen; - CCppOutput& DbSummary = getDbNode()->DbSummary; - - CClassGenerator::SMethodId &InitId = ClassNode->InitId; - CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; - CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; - CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; - CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; - CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; - CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; - CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; - CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; - CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; - - CClassNode *cnd = getClassNode(Type); - XmlNode += " type='class' classid='"+toString(cnd->Id)+"'"; - - setEnv("type", Type); - - // EGS Compat - // -- begin - - CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; - CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; - - StoreId.add("__pdr.pushStructBegin("+tokenName()+");"); - StoreId.add(cppName()+".store(__pdr);"); - StoreId.add("__pdr.pushStructEnd("+tokenName()+");"); - - ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")"); - ApplyId.add("{"); - ApplyId.add("__pdr.popStructBegin("+tokenName()+");"); - ApplyId.add(cppName()+".apply(__pdr);"); - ApplyId.add("__pdr.popStructEnd("+tokenName()+");"); - ApplyId.add("}"); - - // -- end - - - // - // export class accessors into root caller - // - CCallContext ctx; - if (context != NULL) - ctx = *context; - ctx.Context.push_back(this); - cnd->generateContentInCall(&ctx); - - // - // generate attribute - // - Gen.addAttribute(Type, cppName(), "attributes"); - - // - // generate init - // - InitId.add(cppName()+"."+initFunction+"();"); - - // - // generate create code - // - - // - // generate fetch code - // - FetchId.add(cppName()+"."+fetchFunction+"(data);"); - - // - // generate clear code - // - //ClearId.add(cppName()+"."+clearFunction+"();"); -} - - - - - - -void CDeclarationNode::generateBackRefContent() -{ - setEnv("decltype", "backref"); - define(HiddenFlag, "hidden"); - - CClassGenerator &Gen = ClassNode->Gen; - CCppOutput& DbSummary = getDbNode()->DbSummary; - - CClassGenerator::SMethodId &InitId = ClassNode->InitId; - CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; - CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; - CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; - CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; - CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; - CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; - CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; - CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; - CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; - - CClassNode *cnd = getClassNode(ParentClass); - CDeclarationNode *dnd = cnd->getDeclarationNode(ParentField); - CDeclarationNode *knd = (ClassNode->ClassKey.empty() ? NULL : ClassNode->getKey()); - XmlNode += " type='backref' classid='"+toString(cnd->Id)+"' backreferentid='"+toString(dnd->Id)+"'"; - if (knd != NULL) - XmlNode += " key='"+toString(knd->Id)+"'"; - - setEnv("type", ParentClass); - - // - // generate read accessor - // - Gen.startMethod(ParentClass+"*", getFunc(), "", "methods", false, inlineAccessors); - Gen.add("return "+cppName()+";"); - - Gen.startMethod("const "+ParentClass+"*", getFunc(), "", "methods", true, inlineAccessors); - Gen.add("return "+cppName()+";"); - - DbSummary << "\t" << getFunc() << "\n"; - - // - // generate write accessor - // - - // - // generate attribute - // - Gen.addAttribute(ParentClass+"*", cppName(), "attributes"); - - // - // generate init - // - InitId.add(cppName()+" = NULL;"); - - // - // generate create code - // - - // - // generate fetch code - // - FetchId.add(cppName()+" = NULL;"); - - // - // generate set parent code - // - - bool useId = ClassNode->useEntityId(); - bool parentUseId = cnd->useEntityId(); - - if (parentUseId) - SetParentId.add("NLMISC::CEntityId\tprevId;"); - - if (!HiddenFlag) - { - //SetParentId.add(pdslibFunc("set")+"("+ClassNode->getId()+", getRow(), ("+TColumnIndexName+")("+toString(Column)+"), (__parent != NULL ? "+objectIndexName+"("+(cnd->HasInheritance ? toString("__parent->getTable()") : toString(cnd->Id))+", __parent->getRow()) : "+nullIndexName+"));"); - - SetParentId.add("if ("+cppName()+" != NULL)"); - SetParentId.add("{"); - - if (parentUseId) - SetParentId.add("prevId = "+cppName()+"->"+getFunctionPrefix+cnd->getKey()->Name+"();"); - - if (ClassNode->getClassKey() == NULL) - { - SetParentId.add(cppName()+"->"+dnd->unlinkFunc()+"();"); - } - else - { - SetParentId.add(cppName()+"->"+dnd->unlinkFunc()+"("+ClassNode->getKey()->cppName()+");"); - } - SetParentId.add("}"); - } - else - { - if (parentUseId) - { - SetParentId.add("if ("+cppName()+" != NULL)"); - SetParentId.add("{"); - SetParentId.add("prevId = "+cppName()+"->"+cnd->getKey()->cppName()+";"); - SetParentId.add("}"); - } - } - - string oeid; - string peid; - - if (useId) - oeid = ", "+ClassNode->getKey()->cppName(); - - if (parentUseId) - peid = ", ("+cppName()+" != NULL ? "+cppName()+"->"+getFunctionPrefix+cnd->getKey()->Name+"() : NLMISC::CEntityId::Unknown), prevId"; - - SetParentId.add(cppName()+" = __parent;"); - SetParentId.add(pdslibFunc("setParent")+"("+ClassNode->getId()+", getRow(), ("+TColumnIndexName+")("+toString(Column)+"), (__parent != NULL ? "+objectIndexName+"("+(cnd->HasInheritance ? toString("__parent->getTable()") : toString(cnd->Id))+", __parent->getRow()) : "+nullIndexName+")"+oeid+peid+");"); - - SetUnnotifiedParentId.add(cppName()+" = __parent;"); - -} - - - - - - -void CDeclarationNode::generateClassPtrApplyCode(const std::string& value) -{ - CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; - - ApplyId.add(value+" = NULL;"); - ApplyId.add("if (__pdr.peekNextToken() == __Tok_ClassName)"); - ApplyId.add("{"); - ApplyId.add( "std::string\t__className;"); - ApplyId.add( "__pdr.pop(__Tok_ClassName, __className);"); - ApplyId.add( value+" = "+Type+"::cast("+pdslibFunc("create")+"(__className));"); - ApplyId.add( "if ("+value+" != NULL)"); - ApplyId.add( "{"); - ApplyId.add( "__pdr.popStructBegin("+tokenName()+");"); - ApplyId.add( value+"->apply(__pdr);"); - ApplyId.add( value+"->"+setUnnotifiedParentFunction+"(this);"); - ApplyId.add( "__pdr.popStructEnd("+tokenName()+");"); - ApplyId.add( "}"); - ApplyId.add( "else"); - ApplyId.add( "{"); - ApplyId.add( "__pdr.skipStruct();"); - ApplyId.add( "}"); - ApplyId.add("}"); -} - -void CDeclarationNode::generateClassPtrStoreCode(const std::string& value) -{ - CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; - - StoreId.add("if ("+value+" != NULL)"); - StoreId.add("{"); - StoreId.add( "std::string\t__className = "+pdslibFunc("getClassName")+"("+value+");"); - StoreId.add( "__pdr.push(__Tok_ClassName, __className);"); - StoreId.add( "__pdr.pushStructBegin("+tokenName()+");"); - StoreId.add( value+"->store(__pdr);"); - StoreId.add( "__pdr.pushStructEnd("+tokenName()+");"); - StoreId.add("}"); -} - - - -void CDeclarationNode::generateForwardRefContent() -{ - setEnv("decltype", "forwardref"); - - CClassGenerator &Gen = ClassNode->Gen; - CCppOutput& DbSummary = getDbNode()->DbSummary; - - CClassGenerator::SMethodId &InitId = ClassNode->InitId; - CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; - CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; - CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; - CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; - CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; - CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; - CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; - CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; - CClassGenerator::SMethodId &NotifyInitId = ClassNode->NotifyInitId; - CClassGenerator::SMethodId &NotifyReleaseId = ClassNode->NotifyReleaseId; - - CClassNode *cnd = getClassNode(Type); - CDeclarationNode *dnd = cnd->getDeclarationNode(ForwardRefAttribute); - CDeclarationNode *knd = (cnd->ClassKey.empty() ? NULL : cnd->getKey()); - XmlNode += " type='forwardref' classid='"+toString(cnd->Id)+"' forwardreferedid='"+toString(dnd->Id)+"'"; - if (knd != NULL) - XmlNode += " key='"+toString(knd->Id)+"'"; - - setEnv("type", Type); - - // EGS Compat - // -- begin - - CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; - CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; - - StoreId.add("// store "+Name); - StoreId.add("__pdr.pushStructBegin("+tokenName()+");"); - generateClassPtrStoreCode(cppName()); - StoreId.add("__pdr.pushStructEnd("+tokenName()+");"); - - ApplyId.add("// apply "+Name); - ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")"); - ApplyId.add("{"); - ApplyId.add( "__pdr.popStructBegin("+tokenName()+");"); - generateClassPtrApplyCode(cppName()); - ApplyId.add( "__pdr.popStructEnd("+tokenName()+");"); - ApplyId.add("}"); - - // -- end - - - // - // generate read accessor - // - Gen.startMethod(Type+"*", getFunc(), "", "methods", false, inlineAccessors); - Gen.add("return "+cppName()+";"); - - Gen.startMethod("const "+Type+"*", getFunc(), "", "methods", true, inlineAccessors); - Gen.add("return "+cppName()+";"); - - DbSummary << "\t" << getFunc() << "\n"; - - // - // generate write accessor - // - Gen.startMethod("void", setFunc(), Type+"* "+valueVariable, "methods", false, inlineAccessors); - Gen.add("if ("+cppName()+" != NULL)"); - Gen.add("{"); - Gen.add(cppName()+"->"+setParentFunction+"(NULL);"); - Gen.add("}"); - Gen.add(valueVariable+"->"+setParentFunction+"(this);"); - Gen.add(cppName()+" = "+valueVariable+";"); - - DbSummary << "\t" << setFunc() << "\n"; - - // - // generate attribute - // - Gen.addAttribute(Type+"*", cppName(), "attributes"); - - // - // generate init - // - InitId.add(cppName()+" = NULL;"); - - // - // generate destroy code - // - DestroyId.add("if ("+cppName()+" != NULL)"); - DestroyId.add("{"); - DestroyId.add(Type+"*\t__o = "+cppName()+";"); - DestroyId.add("__o->"+destroyFunction+"();"); - DestroyId.add("delete __o;"); - DestroyId.add("}"); - - // - // generate create code - // - - // - // generate fetch code - // - FetchId.add("// read table and row, create an object, affect to the ref, and fetch it"); - if (!ClassNode->tableAndRowIndicesUsedInFetch) - { - FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;"); - ClassNode->tableAndRowIndicesUsedInFetch = true; - } - FetchId.add(cppName()+" = NULL;"); - FetchId.add("data.serial(tableIndex, rowIndex);"); - FetchId.add("if (rowIndex != "+INVALID_ROW_INDEXName+" && tableIndex != "+INVALID_TABLE_INDEXName+")"); - FetchId.add("{"); - FetchId.add(cppName()+" = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));"); - FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+cppName()+");"); - FetchId.add(cppName()+"->"+fetchFunction+"(data);"); - FetchId.add(cppName()+"->"+setUnnotifiedParentFunction+"(this);"); - FetchId.add("}"); - - // - // generate register/unregister code - // - - UnregisterAttributesId.add("if ("+cppName()+" != NULL)"); - UnregisterAttributesId.add("{"); - UnregisterAttributesId.add(Type+"*\t"+objectVariable+" = "+cppName()+";"); - UnregisterAttributesId.add(objectVariable+"->"+unregisterFunction+"();"); - UnregisterAttributesId.add(objectVariable+"->"+destroyFunction+"();"); - UnregisterAttributesId.add("delete "+objectVariable+";"); - UnregisterAttributesId.add("}"); - - // - // generate init/release notification - // - - NotifyInitId.add("if ("+cppName()+" != NULL)"); - NotifyInitId.add("{"); - NotifyInitId.add(cppName()+"->"+notifyInitFunction+"();"); - NotifyInitId.add("}"); - - NotifyReleaseId.add("if ("+cppName()+" != NULL)"); - NotifyReleaseId.add("{"); - NotifyReleaseId.add(cppName()+"->"+notifyReleaseFunction+"();"); - NotifyReleaseId.add("}"); - - // - // generate unlink code - // - string unlinkProto; - if (cnd->getClassKey() != NULL) - { - CDeclarationNode* kd = cnd->getClassKey(); - CTypeNode* keyType = getTypeNode(kd->Type); - unlinkProto = keyType->getName()+" dummy"; - } - Gen.startMethod("void", unlinkFunc(), unlinkProto, "internal", false, inlineInternal); - Gen.add("{"); - Gen.add(cppName()+" = NULL;"); - Gen.add("}"); - - // - // generate clear code - // - //ClearId.add(cppName()+"->"+setParentFunction+"(NULL);"); - ClearId.add(Type+"*\t"+objectVariable+" = "+cppName()+";"); - ClearId.add(objectVariable+"->"+unregisterFunction+"();"); - ClearId.add(objectVariable+"->"+destroyFunction+"();"); - ClearId.add("delete "+objectVariable+";"); -} - - - -void CDeclarationNode::generateArrayApplyCode() -{ - CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; - - ApplyId.add("// apply "+Name); - ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")"); - ApplyId.add("{"); - ApplyId.add( "__pdr.popStructBegin("+tokenName()+");"); - ApplyId.add( "uint\tindex = 0;"); - ApplyId.add( "while (!__pdr.isEndOfStruct())"); - ApplyId.add( "{"); - - CIndexNode *ind = getIndexNode(ArrayIndex); - if (ind->isEnum()) - { - ApplyId.add("std::string\tindexname;"); - ApplyId.add("__pdr.pop(__Tok_MapKey, indexname);"); - ApplyId.add("index = "+ind->getFromStringCode("indexname")+";"); - } -} - -void CDeclarationNode::generateArrayStoreCode() -{ - CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; - - StoreId.add("// store "+Name); - StoreId.add("__pdr.pushStructBegin("+tokenName()+");"); - CIndexNode *ind = getIndexNode(ArrayIndex); - - StoreId.add("for (uint index=0; index<"+ind->getSizeName()+"; ++index)"); - StoreId.add("{"); - - if (ind->isEnum()) - { - StoreId.add("std::string\tindexname = "+ind->getToStringCode(ind->castFromUser("index"))+";"); - StoreId.add("__pdr.push(__Tok_MapKey, indexname);"); - } -} - - -void CDeclarationNode::generateArrayEndCode() -{ - CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; - CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; - - ApplyId.add( "++index;"); - ApplyId.add( "}"); - ApplyId.add( "__pdr.popStructEnd("+tokenName()+");"); - ApplyId.add("}"); - - StoreId.add("}"); - StoreId.add("__pdr.pushStructEnd("+tokenName()+");"); -} - - - -void CDeclarationNode::generateArrayTypeContent(CCallContext *context) -{ - setEnv("decltype", "arraytype"); - - CClassGenerator &Gen = ClassNode->Gen; - CCppOutput& DbSummary = getDbNode()->DbSummary; - - CClassGenerator::SMethodId &InitId = ClassNode->InitId; - CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; - CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; - CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; - CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; - CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; - CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; - CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; - CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; - CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; - - string UCodeContext; - if (context != NULL) - UCodeContext = context->getUserCodeContext(); - - string onGetUser = getUserCode("onGet", UCodeContext); - string onSetUser = getUserCode("onSet", UCodeContext); - string onChangeUser = getUserCode("onChange", UCodeContext); - - CTypeNode *tnd = getTypeNode(Type); - CIndexNode *ind = getIndexNode(ArrayIndex); - XmlNode += " type='arraytype' typeid='"+toString(tnd->Id)+"' indexid='"+toString(ind->Id)+"'"; - - CCallContext ctx(this); - if (context != NULL) - ctx = context->getSubContext(this); - CClassGenerator &gen = ctx.getRootCaller()->Gen; - - setEnv("type", tnd->getName()); - setEnv("indexsize", ind->getSizeName()); - - // EGS Compat - // -- begin - - CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; - CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; - - generateArrayApplyCode(); - generateArrayStoreCode(); - - ApplyId.add(tnd->getName()+"\tvalue;"); - tnd->generateApplyCode(ApplyId, "__Tok_MapVal", "value"); - ApplyId.add("if (index != "+toString(ind->getSize())+")"); - ApplyId.add("{"); - ApplyId.add( cppName()+"[index] = value;"); - ApplyId.add("}"); - - tnd->generateStoreCode(ApplyId, "__Tok_MapVal", cppName()+"[index]"); - - generateArrayEndCode(); - - // -- end - - - // - // generate read accessor - // - if (ctx.getRootCaller()->HasRowAccess) - { - string arglist = ctx.getCallArgList(); - ctx.getRootCaller()->Gen.startMethod(tnd->getName(), getFunctionPrefix+ctx.getCallString(), arglist, "methods", true, inlineAccessors); - - DbSummary << "\t" << getFunctionPrefix+ctx.getCallString() << "\n"; - - uint i; - vector checks = ctx.getCheckCode(); - for (i=0; iHasRowAccess) - { - string arglist = ctx.getCallArgList(); - if (!arglist.empty()) - arglist += ", "; - arglist += tnd->getName()+" "+valueVariable; - gen.startMethod("void", setFunctionPrefix+ctx.getCallString(), appendArg(arglist, "bool forceWrite=false"), "methods", false, inlineAccessors); - - DbSummary << "\t" << setFunctionPrefix+ctx.getCallString() << "\n"; - - if (GenerateHAuto) - { - gen.add("H_AUTO("+getAccessorName(&ctx, getFunctionPrefix, "_")+")"); - } - - if (VerboseMode) - { - string verbStr; - string callStr; - - verbStr = "nlinfo(\"" + ctx.getRootCaller()->Name + "(%d:%d)::" +setFunctionPrefix + ctx.getCallString() + "("; - - callStr = ctx.getDebugCallStringFmt(); - if (!callStr.empty()) - callStr += ", "; - - callStr += valueVariable+"="+tnd->getPrintfFmt(); - - verbStr += callStr; - verbStr += ")\", __BaseTable, __BaseRow, "; - - callStr = ctx.getDebugCallStringVal(); - if (!callStr.empty()) - callStr += ", "; - - callStr += tnd->getPrintfVal(valueVariable); - - verbStr += callStr; - verbStr += ");"; - - gen.add(verbStr); - } - - uint i; - vector checks = ctx.getCheckCode(); - for (i=0; icheckCode(valueVariable)); - - if (!onChangeUser.empty()) - { - gen.add("if ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+")"); - gen.add("{"); - gen.add(onChangeUser); - gen.add("}"); - } - if (!onSetUser.empty()) - { - gen.add("{"); - gen.add(onGetUser); - gen.add("}"); - } - if (WriteTriggerFlag) - { - gen.add("if (forceWrite && ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+"))"); - } - else - { - gen.add("if (("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+") || forceWrite)"); - } - gen.add("{"); - bool useEntityId = ctx.hasRootEntityIdKey(); - if (useEntityId) - { - gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+", "+ctx.getRootCaller()->getKey()->cppName()+");"); - } - else - { - gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");"); - } - //gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");"); - gen.add("}"); - gen.add(ctx.getCallPath()+" = "+tnd->castToCpp(valueVariable)+";"); - } - - // - // generate attribute - // - Gen.addAttribute(tnd->getName(), cppName()+"["+ind->getSizeName()+"]", "attributes"); - - // - // generate init - // - if (!ClassNode->indexUsedInInit) - { - InitId.add("uint\ti;"); - ClassNode->indexUsedInInit = true; - } - - InitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i] = "+tnd->getDefaultValue()+";"); - - // - // generate create code - // - - // - // generate fetch code - // - if (!ClassNode->indexUsedInFetch) - { - FetchId.add("uint\ti;"); - ClassNode->indexUsedInFetch = true; - } - - if (tnd->isEnum()) - FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\tdata.serialEnum("+cppName()+"[i]);"); - else if (tnd->CppType != tnd->StorageType) - { - FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); - FetchId.add("{"); - FetchId.add(tnd->StorageType+"\t_v;"); - FetchId.add("data.serial(_v);"); - FetchId.add(cppName()+"[i] = "+tnd->castToCpp("_v")+";"); - FetchId.add("}"); - } - else - { - FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\tdata.serial("+cppName()+"[i]);"); - } - - // - // generate clear code - // - if (ctx.getRootCaller()->HasRowAccess) - { - string forIndex = "__i"+toString(ctx.getContextIndex()); - ctx.getRootCaller()->ClearId.add("for (uint "+forIndex+"=0; "+forIndex+"<"+ind->getSizeName()+"; ++"+forIndex+")"); - ctx.getRootCaller()->ClearId.add("{"); - ctx.getRootCaller()->ClearId.add(ctx.getCallPath()+" = "+tnd->getDefaultValue()+";"); - ctx.getRootCaller()->ClearId.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(tnd->getDefaultValue())+");"); - ctx.getRootCaller()->ClearId.add("}"); - } -} - - - - - - -void CDeclarationNode::generateArrayClassContent(CCallContext *context) -{ - setEnv("decltype", "arrayclass"); - - CClassGenerator &Gen = ClassNode->Gen; - CCppOutput& DbSummary = getDbNode()->DbSummary; - - CClassGenerator::SMethodId &InitId = ClassNode->InitId; - CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; - CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; - CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; - CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; - CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; - CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; - CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; - CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; - CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; - - CClassNode *sub = getClassNode(Type); - CIndexNode *ind = getIndexNode(ArrayIndex); - XmlNode += " type='arrayclass' classid='"+toString(sub->Id)+"' indexid='"+toString(ind->Id)+"'"; - - setEnv("type", Type); - setEnv("indexsize", ind->getSizeName()); - - // EGS Compat - // -- begin - - CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; - CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; - - generateArrayApplyCode(); - generateArrayStoreCode(); - -// StoreId.add("__pdr.pushStructBegin("+tokenName()+");"); - StoreId.add("__pdr.pushStructBegin(__Tok_MapVal);"); - StoreId.add(cppName()+"[index].store(__pdr);"); - StoreId.add("__pdr.pushStructEnd(__Tok_MapVal);"); -// StoreId.add("__pdr.pushStructEnd("+tokenName()+");"); - - ApplyId.add("if (index < "+ind->getSizeName()+")"); - ApplyId.add("{"); -// ApplyId.add("__pdr.popStructBegin("+tokenName()+");"); - ApplyId.add("__pdr.popStructBegin(__pdr.peekNextToken());"); - ApplyId.add(cppName()+"[index].apply(__pdr);"); - ApplyId.add("__pdr.popStructEnd(__pdr.peekNextToken());"); -// ApplyId.add("__pdr.popStructEnd("+tokenName()+");"); - ApplyId.add("}"); - ApplyId.add("else"); - ApplyId.add("{"); - ApplyId.add( "__pdr.skipStruct();"); - ApplyId.add("}"); - - generateArrayEndCode(); - - // -- end - - - // - // export class accessors into root caller - // - - CCallContext ctx; - if (context != NULL) - ctx = *context; - ctx.Context.push_back(this); - - if (ctx.getRootCaller()->HasRowAccess) - { - string forIndex = "__i"+toString(ctx.getContextIndex()); - ctx.getRootCaller()->ClearId.add("for (uint "+forIndex+"=0; "+forIndex+"<"+ind->getSizeName()+"; ++"+forIndex+")"); - ctx.getRootCaller()->ClearId.add("{"); - } - - sub->generateContentInCall(&ctx); - - if (ctx.getRootCaller()->HasRowAccess) - { - ctx.getRootCaller()->ClearId.add("}"); - } - - // - // generate attribute - // - Gen.addAttribute(Type, cppName()+"["+ind->getSizeName()+"]", "attributes"); - - // - // generate init - // - - // - // generate create code - // - - // - // generate fetch code - // - if (!ClassNode->indexUsedInFetch) - { - FetchId.add("uint\ti;"); - ClassNode->indexUsedInFetch = true; - } - FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i]."+fetchFunction+"(data);"); - - // - // generate clear code - // -} - - - - - - -void CDeclarationNode::generateArrayRefContent(CCallContext *context) -{ - setEnv("decltype", "arrayref"); - - CClassGenerator &Gen = ClassNode->Gen; - CCppOutput& DbSummary = getDbNode()->DbSummary; - - CClassGenerator::SMethodId &InitId = ClassNode->InitId; - CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; - CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; - CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; - CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; - CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; - CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; - CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; - CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; - CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; - CClassGenerator::SMethodId &NotifyInitId = ClassNode->NotifyInitId; - CClassGenerator::SMethodId &NotifyReleaseId = ClassNode->NotifyReleaseId; - - CClassNode *cnd = getClassNode(Type); - - bool useReference = cnd->ForceReference; - - CDeclarationNode *dnd = cnd->getDeclarationNode(ForwardRefAttribute); - CIndexNode *ind = getIndexNode(ArrayIndex); - CDeclarationNode *knd = cnd->getKey(); - XmlNode += " type='arrayref' classid='"+toString(cnd->Id)+"' forwardreferedid='"+toString(dnd->Id)+"' key='"+toString(knd->Id)+"' indexid='"+toString(ind->Id)+"' allownull='"+(useReference ? "true" : "false")+"'"; - - string arrayType = Type+(useReference ? "*" : ""); - string access = (useReference ? "->" : "."); - - setEnv("type", Type); - setEnv("indexsize", ind->getSizeName()); - define(useReference, "useref"); - - string UCodeContext; - if (context != NULL) - UCodeContext = context->getUserCodeContext(); - - string onChangeUser = getUserCode("onChange", UCodeContext); - - // EGS Compat - // -- begin - - CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; - CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; - - generateArrayStoreCode(); - generateArrayApplyCode(); - - StoreId.add("__pdr.pushStructBegin("+tokenName()+");"); - - ApplyId.add("if (index < "+ind->getSizeName()+")"); - ApplyId.add("{"); - ApplyId.add( "if (__pdr.peekNextToken() == "+tokenName()+")"); - ApplyId.add( "{"); - ApplyId.add( "__pdr.popStructBegin("+tokenName()+");"); - - if (useReference) - { - generateClassPtrStoreCode(cppName()+"[index]"); - - generateClassPtrApplyCode(cppName()+"[index]"); - } - else - { - StoreId.add(cppName()+"[index].store(__pdr);"); - - ApplyId.add(cppName()+"[index].apply(__pdr);"); - ApplyId.add(cppName()+"[index]."+setUnnotifiedParentFunction+"(this);"); - } - - StoreId.add("__pdr.pushStructEnd("+tokenName()+");"); - - ApplyId.add( "__pdr.popStructEnd("+tokenName()+");"); - ApplyId.add( "}"); - ApplyId.add("}"); - ApplyId.add("else"); - ApplyId.add("{"); - ApplyId.add( "__pdr.skipStruct();"); - ApplyId.add("}"); - - generateArrayEndCode(); - - // -- end - - - // - // generate read accessor - // - Gen.startMethod((useReference ? arrayType : Type+"&"), getFunc(), ind->getName()+" "+indexVariable, "methods", false, inlineAccessors); - Gen.add(ind->checkCode(indexVariable)); - Gen.add("return "+cppName()+"["+indexVariable+"];"); - - Gen.startMethod(string("const ")+(useReference ? arrayType : Type+"&"), getFunc(), ind->getName()+" "+indexVariable, "methods", true, inlineAccessors); - Gen.add(ind->checkCode(indexVariable)); - Gen.add("return "+cppName()+"["+indexVariable+"];"); - - DbSummary << "\t" << getFunc() << "\n"; - - // - // generate write accessor - // - if (useReference) - { - Gen.startMethod("void", setFunc(), arrayType+" "+valueVariable, "methods", false, inlineAccessors); - - DbSummary << "\t" << setFunc() << "\n"; - - Gen.add("if ("+valueVariable+" == NULL)\treturn;"); - Gen.add(ind->getName()+"\t"+keyVariable+" = "+valueVariable+"->"+cnd->getKey()->getFunc()+"();"); - Gen.add(ind->checkCode(keyVariable)); - Gen.add(Type+"*\t__prev = "+cppName()+"["+keyVariable+"];"); - Gen.add("if (__prev != NULL)"); - Gen.add("{"); - Gen.add("__prev->"+setParentFunction+"(NULL);"); - if (cnd->MapClass == NULL) - { - Gen.add("__prev->"+unregisterFunction+"();"); - Gen.add("__prev->"+destroyFunction+"();"); - Gen.add("delete __prev;"); - } - Gen.add("}"); - Gen.add(valueVariable+"->"+setParentFunction+"(this);"); - Gen.add(cppName()+"["+keyVariable+"] = "+valueVariable+";"); - } - - if (cnd->MapClass == NULL && useReference && !cnd->HasInheritance && !cnd->DerivatedFlag) - { - Gen.startMethod(Type+"*", newFunc(), ind->getName()+" "+indexVariable, "methods", false, inlineAccessors); - DbSummary << "\t" << newFunc() << "\n"; - Gen.add(ind->checkCode(indexVariable)); - Gen.add(Type+"*\t"+objectVariable+" = new "+Type+"();"); - Gen.add(objectVariable+"->"+initFunction+"("+indexVariable+");"); - Gen.add(objectVariable+"->"+registerFunction+"();"); - Gen.add(setFunc()+"("+objectVariable+");"); - } - - if (cnd->MapClass == NULL && useReference) - { - Gen.startMethod("void", deleteFunc(), ind->getName()+" "+indexVariable, "methods", false, inlineAccessors); - DbSummary << "\t" << deleteFunc() << "\n"; - Gen.add(ind->checkCode(indexVariable)); - Gen.add(Type+"*\t"+objectVariable+" = "+cppName()+"["+indexVariable+"];"); - Gen.add(objectVariable+"->"+setParentFunction+"(NULL);"); - Gen.add(objectVariable+"->"+unregisterFunction+"();"); - Gen.add(objectVariable+"->"+destroyFunction+"();"); - Gen.add("delete "+objectVariable+";"); - } - - // - // generate attribute - // - Gen.addAttribute(arrayType, cppName()+"["+ind->getSizeName()+"]", "attributes"); - - // - // generate init - // - if (!ClassNode->indexUsedInInit) - { - InitId.add("uint\ti;"); - ClassNode->indexUsedInInit = true; - } - if (useReference) - { - InitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i] = NULL;"); - } - else - { - InitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i]."+initFunction+"(("+ind->getName()+")i);"); - } - - // - // generate destroy code - // - if (!ClassNode->indexUsedInDestroy) - { - DestroyId.add("uint\ti;"); - ClassNode->indexUsedInDestroy = true; - } - DestroyId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); - DestroyId.add("{"); - if (useReference) - { - DestroyId.add("if ("+cppName()+"[i] != NULL)"); - DestroyId.add("{"); - DestroyId.add(Type+"*\t"+objectVariable+" = "+cppName()+"[i];"); - DestroyId.add(objectVariable+"->"+destroyFunction+"();"); - DestroyId.add("delete "+objectVariable+";"); - DestroyId.add("}"); - } - else - { - DestroyId.add(cppName()+"[i]."+destroyFunction+"();"); - } - DestroyId.add("}"); - - // - // generate create code - // - - // - // generate fetch code - // - if (useReference) - { - if (!ClassNode->indexUsedInFetch) - { - FetchId.add("uint\ti;"); - ClassNode->indexUsedInFetch = true; - } - if (!ClassNode->tableAndRowIndicesUsedInFetch) - { - FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;"); - ClassNode->tableAndRowIndicesUsedInFetch = true; - } - FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); - FetchId.add("{"); - FetchId.add(cppName()+"[i] = NULL;"); - FetchId.add("// read table and row, create an object, affect to the ref, and fetch it"); - FetchId.add("data.serial(tableIndex, rowIndex);"); - FetchId.add("if (rowIndex != "+INVALID_ROW_INDEXName+" && tableIndex != "+INVALID_TABLE_INDEXName+")"); - FetchId.add("{"); - FetchId.add(cppName()+"[i] = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));"); - FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+cppName()+"[i]);"); - FetchId.add(cppName()+"[i]->"+fetchFunction+"(data);"); - FetchId.add(cppName()+"[i]->"+setUnnotifiedParentFunction+"(this);"); - FetchId.add("}"); - FetchId.add("}"); - } - else - { - if (!ClassNode->indexUsedInFetch) - { - FetchId.add("uint\ti;"); - ClassNode->indexUsedInFetch = true; - } - if (!ClassNode->tableAndRowIndicesUsedInFetch) - { - FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;"); - ClassNode->tableAndRowIndicesUsedInFetch = true; - } - FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); - FetchId.add("{"); - FetchId.add("// read table and row, create an object, affect to the ref, and fetch it"); - FetchId.add("data.serial(tableIndex, rowIndex);"); - FetchId.add("if (rowIndex != "+INVALID_ROW_INDEXName+" && tableIndex != "+INVALID_TABLE_INDEXName+")"); - FetchId.add("{"); - FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, &"+cppName()+"[i]);"); - FetchId.add(cppName()+"[i]."+fetchFunction+"(data);"); - FetchId.add(cppName()+"[i]."+setUnnotifiedParentFunction+"(this);"); - FetchId.add("}"); - FetchId.add("}"); - } - - // - // generate register/unregister code - // - if (!useReference) - { - if (!ClassNode->indexUsedInRegister) - { - RegisterAttributesId.add("uint\ti;"); - ClassNode->indexUsedInRegister = true; - } - RegisterAttributesId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); - RegisterAttributesId.add("{"); - RegisterAttributesId.add(cppName()+"[i]."+registerFunction+"();"); - RegisterAttributesId.add(cppName()+"[i]."+setParentFunction+"(this);"); - RegisterAttributesId.add("}"); - - if (!ClassNode->indexUsedInUnregister) - { - UnregisterAttributesId.add("uint\ti;"); - ClassNode->indexUsedInUnregister = true; - } - UnregisterAttributesId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); - UnregisterAttributesId.add("{"); - UnregisterAttributesId.add(cppName()+"[i]."+unregisterFunction+"();"); - UnregisterAttributesId.add("}"); - } - else - { - if (!ClassNode->indexUsedInUnregister) - { - UnregisterAttributesId.add("uint\ti;"); - ClassNode->indexUsedInUnregister = true; - } - UnregisterAttributesId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); - UnregisterAttributesId.add("{"); - UnregisterAttributesId.add("if ("+cppName()+"[i] != NULL)"); - UnregisterAttributesId.add("{"); - UnregisterAttributesId.add(Type+"*\t"+objectVariable+" = "+cppName()+"[i];"); - UnregisterAttributesId.add(objectVariable+"->"+unregisterFunction+"();"); - UnregisterAttributesId.add(objectVariable+"->"+destroyFunction+"();"); - UnregisterAttributesId.add("delete "+objectVariable+";"); - UnregisterAttributesId.add("}"); - UnregisterAttributesId.add("}"); - } - - // - // generate init/release notification - // - - if (!ClassNode->indexUsedInNotifyInit) - { - NotifyInitId.add("uint\ti;"); - ClassNode->indexUsedInNotifyInit = true; - } - NotifyInitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); - NotifyInitId.add("{"); - - if (!ClassNode->indexUsedInNotifyRelease) - { - NotifyReleaseId.add("uint\ti;"); - ClassNode->indexUsedInNotifyRelease = true; - } - NotifyReleaseId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); - NotifyReleaseId.add("{"); - - if (!useReference) - { - NotifyInitId.add(cppName()+"[i]."+notifyInitFunction+"();"); - - NotifyReleaseId.add(cppName()+"[i]."+notifyReleaseFunction+"();"); - } - else - { - NotifyInitId.add("if ("+cppName()+"[i] != NULL)"); - NotifyInitId.add("{"); - NotifyInitId.add(cppName()+"[i]->"+notifyInitFunction+"();"); - NotifyInitId.add("}"); - - NotifyReleaseId.add("if ("+cppName()+"[i] != NULL)"); - NotifyReleaseId.add("{"); - NotifyReleaseId.add(cppName()+"[i]->"+notifyReleaseFunction+"();"); - NotifyReleaseId.add("}"); - } - - NotifyInitId.add("}"); - NotifyReleaseId.add("}"); - - - // - // generate unlink code - // - if (useReference) - { - Gen.startMethod("void", unlinkFunc(), ind->getName()+" "+keyVariable, "internal", false, inlineInternal); - Gen.add(cppName()+"["+keyVariable+"] = NULL;"); - } - - // - // generate clear code - // - ClearId.add("for (uint i=0; i<"+ind->getSizeName()+"; ++i)"); - ClearId.add("{"); - if (!useReference) - { - ClearId.add(cppName()+"[i]."+clearFunction+"();"); - } - else - { - //ClearId.add(cppName()+"[i]->"+setParentFunction+"(NULL);"); - ClearId.add(Type+"*\t"+objectVariable+" = "+cppName()+"[i];"); - ClearId.add(objectVariable+"->"+unregisterFunction+"();"); - ClearId.add(objectVariable+"->"+destroyFunction+"();"); - ClearId.add("delete "+objectVariable+";"); - } - ClearId.add("}"); -} - - - - - - - -void CDeclarationNode::generateSetContent(CCallContext *context) -{ - setEnv("decltype", "set"); - - CClassGenerator &Gen = ClassNode->Gen; - CCppOutput& DbSummary = getDbNode()->DbSummary; - - CClassGenerator::SMethodId &InitId = ClassNode->InitId; - CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; - CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; - CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; - CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; - CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; - CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; - CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; - CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; - CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; - CClassGenerator::SMethodId &NotifyInitId = ClassNode->NotifyInitId; - CClassGenerator::SMethodId &NotifyReleaseId = ClassNode->NotifyReleaseId; - - CClassNode *sub = getClassNode(Type); - CDeclarationNode *key = sub->getKey(); - CTypeNode *keyType = getTypeNode(key->Type); - - bool useReference = sub->ForceReference; - string access = (useReference ? "->" : "."); - - string onChangeUser = getUserCode("onChange", context != NULL ? context->getUserCodeContext() : ""); - - - string setType = "std::map<"+keyType->getName()+", " + Type + (useReference ? "*" : "") + ">"; - - CDeclarationNode *dnd = sub->getDeclarationNode(ForwardRefAttribute); - XmlNode += " type='set' classid='"+toString(sub->Id)+"' forwardreferedid='"+toString(dnd->Id)+"' key='"+toString(key->Id)+"' "; - - setEnv("type", Type); - setEnv("keytype", keyType->getName()); - define(useReference, "useref"); - - // EGS Compat - // -- begin - - CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; - CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; - - StoreId.add("// store "+Name); - StoreId.add("__pdr.pushStructBegin("+tokenName()+");"); - StoreId.add("for ("+setType+"::const_iterator it="+cppName()+".begin(); it!="+cppName()+".end(); ++it)"); - StoreId.add("{"); - StoreId.add( keyType->getName()+"\tkey = (*it).first;"); - keyType->generateStoreCode(StoreId, "__Tok_MapKey", "key"); - StoreId.add( "__pdr.pushStructBegin(__Tok_MapVal);"); - - if (useReference) - { - generateClassPtrStoreCode("(*it).second"); - } - else - { - StoreId.add("(*it).second.store(__pdr);"); - } - - StoreId.add( "__pdr.pushStructEnd(__Tok_MapVal);"); - StoreId.add("}"); - StoreId.add("__pdr.pushStructEnd("+tokenName()+");"); - StoreId.add("// end of store "+Name); - - ApplyId.add("// apply "+Name); - ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")"); - ApplyId.add("{"); - ApplyId.add( "__pdr.popStructBegin("+tokenName()+");"); - ApplyId.add( "while (!__pdr.isEndOfStruct())"); - ApplyId.add( "{"); - ApplyId.add( keyType->getName()+"\tkey;"); - keyType->generateApplyCode(ApplyId, "__Tok_MapKey", "key"); - - ApplyId.add( "__pdr.popStructBegin(__Tok_MapVal);"); - if (useReference) - { - ApplyId.add( Type+"*\tobj;"); - generateClassPtrApplyCode("obj"); - ApplyId.add( "if (obj != NULL)"); - ApplyId.add( "{"); - ApplyId.add( cppName()+"[key] = obj;"); - ApplyId.add( "}"); - } - else - { - ApplyId.add( Type+"&\tobj = "+cppName()+"[key];"); - ApplyId.add( "obj.apply(__pdr);"); - ApplyId.add( "obj."+setUnnotifiedParentFunction+"(this);"); - } - ApplyId.add( "__pdr.popStructEnd(__Tok_MapVal);"); - ApplyId.add( "}"); - ApplyId.add( "__pdr.popStructEnd("+tokenName()+");"); - ApplyId.add("}"); - ApplyId.add("// end of apply "+Name); - - // -- end - - - // - // generate read accessor - // - Gen.startMethod(Type+"*", getFunc(), "const "+keyType->getName()+"& "+keyVariable, "methods", false, inlineAccessors); - DbSummary << "\t" << getFunc() << "\n"; - Gen.add(setType+"::iterator _it = "+cppName()+".find("+keyVariable+");"); - Gen.add("return (_it=="+cppName()+".end() ? NULL : "+(useReference ? "(*_it).second" : "&((*_it).second)")+");"); - - Gen.startMethod("const "+Type+"*", getFunc(), "const "+keyType->getName()+"& "+keyVariable, "methods", true, inlineAccessors); - Gen.add(setType+"::const_iterator _it = "+cppName()+".find("+keyVariable+");"); - Gen.add("return (_it=="+cppName()+".end() ? NULL : "+(useReference ? "(*_it).second" : "&((*_it).second)")+");"); - - // generate map accessor - string stypedef = "T"+Name+"Map"; - //Gen.addOther("typedef "+setType+"\t"+stypedef+";"); - Gen.startMethod(setType+"::iterator", getFunc()+"Begin", "", "methods", false, inlineAccessors); - Gen.add("return "+cppName()+".begin();"); - DbSummary << "\t" << getFunc() << "Begin" << "\n"; - Gen.startMethod(setType+"::iterator", getFunc()+"End", "", "methods", false, inlineAccessors); - Gen.add("return "+cppName()+".end();"); - DbSummary << "\t" << getFunc() << "End" << "\n"; - Gen.startMethod(setType+"::const_iterator", getFunc()+"Begin", "", "methods", true, inlineAccessors); - Gen.add("return "+cppName()+".begin();"); - Gen.startMethod(setType+"::const_iterator", getFunc()+"End", "", "methods", true, inlineAccessors); - Gen.add("return "+cppName()+".end();"); - Gen.startMethod("const "+setType+" &", getFunc(), "", "methods", true, inlineAccessors); - Gen.add("return "+cppName()+";"); - - // - // generate write accessor - // - if (useReference) - { - Gen.startMethod("void", setFunc(), Type+"* "+valueVariable, "methods", false, inlineAccessors); - DbSummary << "\t" << setFunc() << "\n"; - Gen.add("if ("+valueVariable+" == NULL)\treturn;"); - Gen.add(keyType->getName()+"\t"+keyVariable+" = "+valueVariable+"->"+sub->getKey()->getFunc()+"();"); - Gen.add(setType+"::iterator\t_it = "+cppName()+".find("+keyVariable+");"); - Gen.add("if (_it != "+cppName()+".end())"); - Gen.add("{"); - Gen.add(Type+"*\t__prev = (*_it).second;"); - Gen.add("if (__prev == "+valueVariable+")\treturn;"); - Gen.add("__prev->"+setParentFunction+"(NULL);"); - Gen.add("__prev->"+unregisterFunction+"();"); - Gen.add("__prev->"+destroyFunction+"();"); - Gen.add("delete __prev;"); - Gen.add("}"); - Gen.add(valueVariable+"->"+setParentFunction+"(this);"); - Gen.add(cppName()+"["+keyVariable+"] = "+valueVariable+";"); - if (!onChangeUser.empty()) - { - Gen.add("{"); - Gen.add(onChangeUser); - Gen.add("}"); - } - } - - if (sub->MapClass == NULL && !sub->HasInheritance && !sub->DerivatedFlag) - { - Gen.startMethod(Type+"*", newFunc(), "const "+keyType->getName()+" &"+keyVariable, "methods", false, inlineAccessors); - DbSummary << "\t" << newFunc() << "\n"; - Gen.add(setType+"::iterator\t__it = "+cppName()+".find("+keyVariable+");"); - Gen.add("if (__it == "+cppName()+".end())"); - Gen.add("{"); - Gen.add("__it = "+cppName()+".insert("+setType+"::value_type("+keyVariable+", "+(useReference ? toString("new ") : toString(""))+Type+"())).first;"); - Gen.add(Type+"*\t"+objectVariable+" = "+(useReference ? toString("") : toString("&"))+"((*__it).second);"); - Gen.add(objectVariable+"->"+initFunction+"("+keyVariable+");"); - Gen.add(objectVariable+"->"+registerFunction+"();"); - Gen.add(objectVariable+"->"+setParentFunction+"(this);"); - Gen.add("}"); - if (!onChangeUser.empty()) - { - Gen.add("{"); - Gen.add(onChangeUser); - Gen.add("}"); - } - Gen.add("return "+(useReference ? toString("") : toString("&"))+"((*__it).second);"); - } - - Gen.startMethod("void", deleteFunc(), "const "+keyType->getName()+" &"+keyVariable, "methods", false, inlineAccessors); - DbSummary << "\t" << deleteFunc() << "\n"; - Gen.add(setType+"::iterator\t__it = "+cppName()+".find("+keyVariable+");"); - Gen.add("if (__it == "+cppName()+".end())\treturn;"); - if (useReference) - { - Gen.add(Type+"*\t"+objectVariable+" = (*__it).second;"); - Gen.add(objectVariable+"->"+unregisterFunction+"();"); - Gen.add(objectVariable+"->"+destroyFunction+"();"); - Gen.add("delete "+objectVariable+";"); - } - else - { - Gen.add(Type+"&\t"+objectVariable+" = (*__it).second;"); - Gen.add(objectVariable+"."+unregisterFunction+"();"); - Gen.add(cppName()+".erase(__it);"); - } - if (!onChangeUser.empty()) - { - Gen.add("{"); - Gen.add(onChangeUser); - Gen.add("}"); - } - - // - // generate attribute - // - Gen.addAttribute(setType, cppName(), "attributes"); - - // - // generate init - // - - // - // generate destroy code - // - DestroyId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )"); - DestroyId.add("{"); - DestroyId.add(setType+"::iterator __itr=__it++;"); - if (useReference) - { - DestroyId.add(Type+"*\t"+objectVariable+" = ((*__itr).second);"); - DestroyId.add("if ("+objectVariable+" != NULL)"); - DestroyId.add("{"); - DestroyId.add(objectVariable+"->"+destroyFunction+"();"); - DestroyId.add("delete "+objectVariable+";"); - DestroyId.add("}"); - } - else - { - DestroyId.add("((*__itr).second)."+destroyFunction+"();"); - } - DestroyId.add("}"); - DestroyId.add(cppName()+".clear();"); - - // - // generate create code - // - - // - // generate fetch code - // - if (!ClassNode->tableAndRowIndicesUsedInFetch) - { - FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;"); - ClassNode->tableAndRowIndicesUsedInFetch = true; - } - FetchId.add("do"); - FetchId.add("{"); - FetchId.add("// read table and row, create an object, affect to the ref, and fetch it"); - FetchId.add("data.serial(tableIndex, rowIndex);"); - FetchId.add("if (rowIndex == "+INVALID_ROW_INDEXName+" || tableIndex == "+INVALID_TABLE_INDEXName+")\tbreak;"); - - FetchId.add(keyType->getName()+"\t"+keyVariable+";"); - if (keyType->isEnum()) - { - FetchId.add("data.serialEnum("+keyVariable+");"); - } - else if (keyType->CppType != keyType->StorageType) - { - FetchId.add("{"); - FetchId.add(keyType->StorageType+"\t_v;"); - FetchId.add("data.serial(_v);"); - FetchId.add(keyVariable+" = "+keyType->castToCpp("_v")+";"); - FetchId.add("}"); - } - else - { - FetchId.add("data.serial("+keyVariable+");"); - } - if (useReference) - { - FetchId.add(Type+"*\t"+objectVariable+" = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));"); - FetchId.add(cppName()+".insert(std::make_pair<"+keyType->getName()+","+Type+"*>("+keyVariable+", "+objectVariable+"));"); - } - else - { - FetchId.add(cppName()+".insert(std::make_pair<"+keyType->getName()+","+Type+">("+keyVariable+", "+Type+"()));"); - FetchId.add(Type+"*\t"+objectVariable+" = &("+cppName()+"["+keyVariable+"]);"); - } - FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+objectVariable+");"); - FetchId.add(objectVariable+"->"+fetchFunction+"(data);"); - FetchId.add(objectVariable+"->"+setUnnotifiedParentFunction+"(this);"); - FetchId.add("}"); - FetchId.add("while (true);"); - - // - // generate register/unregister code - // - - UnregisterAttributesId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )"); - UnregisterAttributesId.add("{"); - UnregisterAttributesId.add(setType+"::iterator __itr=__it++;"); - if (useReference) - { - UnregisterAttributesId.add(Type+"*\t"+objectVariable+" = (*__itr).second;"); - UnregisterAttributesId.add(objectVariable+"->"+unregisterFunction+"();"); - UnregisterAttributesId.add(objectVariable+"->"+destroyFunction+"();"); - UnregisterAttributesId.add("delete "+objectVariable+";"); - } - else - { - UnregisterAttributesId.add(Type+"&\t"+objectVariable+" = (*__itr).second;"); - UnregisterAttributesId.add(objectVariable+"."+unregisterFunction+"();"); - } - UnregisterAttributesId.add("}"); - - // - // generate init/release notification - // - - NotifyInitId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )"); - NotifyInitId.add("{"); - NotifyInitId.add(setType+"::iterator __itr=__it++;"); - - NotifyReleaseId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )"); - NotifyReleaseId.add("{"); - NotifyReleaseId.add(setType+"::iterator __itr=__it++;"); - - if (!useReference) - { - NotifyInitId.add("(*__itr).second."+notifyInitFunction+"();"); - NotifyReleaseId.add("(*__itr).second."+notifyReleaseFunction+"();"); - } - else - { - NotifyInitId.add("(*__itr).second->"+notifyInitFunction+"();"); - NotifyReleaseId.add("(*__itr).second->"+notifyReleaseFunction+"();"); - } - - NotifyInitId.add("}"); - NotifyReleaseId.add("}"); - - // - // generate unlink code - // - if (useReference) - { - Gen.startMethod("void", unlinkFunc(), keyType->getName()+" "+keyVariable, "internal", false, inlineInternal); - Gen.add(cppName()+".erase("+keyVariable+");"); - } - - // - // generate clear code - // - ClearId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )"); - ClearId.add("{"); - ClearId.add(setType+"::iterator __itr=__it++;"); - if (!useReference) - { - ClearId.add(Type+"*\t"+objectVariable+" = &((*__itr).second);"); - } - else - { - ClearId.add(Type+"*\t"+objectVariable+" = (*__itr).second;"); - } - //ClearId.add(objectVariable+"->"+setParentFunction+"(NULL);"); - ClearId.add(objectVariable+"->"+unregisterFunction+"();"); - ClearId.add(objectVariable+"->"+destroyFunction+"();"); - if (useReference) - { - ClearId.add("delete "+objectVariable+";"); - } - ClearId.add("}"); - ClearId.add(cppName()+".clear();"); -} - -// -string CDeclarationNode::displayPrintfPrefix() -{ - if (DeclarationType != SimpleType) - error("can't display other declaration than simple type", "internal"); - - CTypeNode* type = getTypeNode(Type); - - if (type->CppType == "CEntityId" || type->CppType == "CSheetId") - return "%s"; - else if (type->CppType == "uint64" || type->CppType == "sint64") - return "%\"NL_I64\"d"; - else if (type->CppType == "float" || type->CppType == "double") - return "%g"; - else - return "%d"; -} - -string CDeclarationNode::displayCppCode(string replVar) -{ - if (DeclarationType != SimpleType) - error("can't display other declaration than simple type", "internal"); - - if (replVar.empty()) - replVar = cppName(); - - CTypeNode* type = getTypeNode(Type); - - if (type->CppType == "CEntityId" || type->CppType == "CSheetId") - return replVar+".toString().c_str()"; - else - return replVar; -} - - -string CDeclarationNode::toUint64(string replVar) -{ - if (DeclarationType != SimpleType) - error("can't display other declaration than simple type", "internal"); - - if (replVar.empty()) - replVar = cppName(); - - CTypeNode* type = getTypeNode(Type); - - if (type->CppType == "CEntityId") - return replVar+".asUint64()"; - else if (type->CppType == "CSheetId") - return "(uint64)("+replVar+".asInt())"; - else - return "(uint64)"+replVar; -} - - - - - -bool CLogMsgNode::prolog() -{ - getDbNode()->LogNodes.push_back(this); - - getFileNode()->IncludeDbFile = true; - getFileNode()->IncludeStandard = true; - getFileNode()->IncludePDSLib = true; - - return true; -} - -void CLogMsgNode::generateContent() -{ - // - uint j; - - CFunctionGenerator logfunc; - CClassGenerator logclass; - string argcall; - - CFunctionGenerator& initDb = getDbNode()->initDb; - - logfunc.init(Name); - logfunc.setType("void"); - logfunc.IsInline = inlineLogFunctions; - - logclass.init("Log"+Name); - logclass.createPublic("pub"); - logclass.createPrivate("priv"); - - CClassGenerator::SMethodId startlogid = logclass.startMethod("void", logStartFunction, "", "priv", false, inlineLogFunctions); - CClassGenerator::SMethodId stoplogid = logclass.startMethod("void", logStopFunction, "", "priv", false, inlineLogFunctions); - startlogid.add(pdslibFunc("pushContext")+"();"); - stoplogid.add(pdslibFunc("popContext")+"();"); - - map params; - - for (j=0; j::iterator, bool> res = params.insert(make_pair(name, tnd)); - if (!res.second) - error("log parameter '"+name+"' already defined"); - - if (!logfunc.Proto.empty()) - logfunc.Proto += ", "; - if (!argcall.empty()) - argcall += ", "; - - logfunc.Proto += tnd->getName()+" "+name; - argcall += name; - } - else if ( (cnd = getClassNode(type, false)) ) - { - pair::iterator, bool> res = params.insert(make_pair(name, cnd)); - if (!res.second) - error("log parameter '"+name+"' already defined"); - - if (!logfunc.Proto.empty()) - logfunc.Proto += ", "; - if (!argcall.empty()) - argcall += ", "; - - logfunc.Proto += "const "+type+"& "+name; - argcall += name; - } - else if (type == "string") - { - CExtLogTypeNode* extnd = new CExtLogTypeNode(); - extnd->ExtLogType = "string"; - pair::iterator, bool> res = params.insert(make_pair(name, extnd)); - if (!res.second) - error("log parameter '"+name+"' already defined"); - - if (!logfunc.Proto.empty()) - logfunc.Proto += ", "; - if (!argcall.empty()) - argcall += ", "; - - logfunc.Proto += "const std::string& "+name; - argcall += name; - } - else - { - error("'"+type+"' not found as a class or a type"); - } - } - - // - initDb.add("// Init "+Name+" log message and parameters"); - - for (j=0; jxmlDescription.push_back(""); - - uint paramNum = 0; - - initDb.add(pdslibFunc("initLog")+"("+toString(logId)+");"); - - while (*cptr != '\0') - { - if (*cptr == '$') - { - ++cptr; - if (*cptr == '\0') - error("log format corrupted in line \""+Logs[j]+"\""); - - if (*cptr == '$') - { - log += "$$"; - ++cptr; - continue; - } - - string param; - string var; - - while (*cptr!='\0' && *cptr!='$' && *cptr!='.') - param += *(cptr++); - - if (*cptr == '\0') - error("log format corrupted in line \""+Logs[j]+"\""); - - if (*cptr == '.') - { - ++cptr; - while (*cptr!='\0' && *cptr!='$') - var += *(cptr++); - } - - if (*cptr != '$') - error("log format corrupted in line \""+Logs[j]+"\""); - - ++cptr; - - map::iterator it = params.find(param); - - if (it == params.end()) - error("'"+param+"' ot found in prototype, at line \""+Logs[j]+"\""); - - CTypeNode *tnd = NULL; - CExtLogTypeNode* extnd = NULL; - - if (var.empty()) - { - // is simple type - tnd = dynamic_cast((*it).second); - extnd = dynamic_cast((*it).second); - if (tnd != NULL) - { - logfunc.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param)+");"); - startlogid.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param)+");"); - } - else if (extnd != NULL && extnd->ExtLogType == "string") - { - logfunc.add(pdslibFunc("logPush")+"("+param+");"); - startlogid.add(pdslibFunc("logPush")+"("+param+");"); - } - else - { - error("misuse of parameter '"+param+"' at line \""+Logs[j]+"\", missing attribute name"); - } - } - else - { - // is class - CClassNode *cnd = dynamic_cast((*it).second); - if (!cnd) - error("misuse of parameter '"+param+"' at line \""+Logs[j]+"\", should be a class"); - - CDeclarationNode *dnd = cnd->getDeclaration(var); - - if (!dnd->IsType) - error("attribute '"+var+"' is not a simple type"); - - tnd = getTypeNode(dnd->Type); - - logfunc.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param+"."+dnd->getFunc()+"()")+");"); - startlogid.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param+"."+dnd->getFunc()+"()")+");"); - } - - if (tnd != NULL) - { - getDbNode()->xmlDescription.push_back(""); - initDb.add(pdslibFunc("initLogParam")+"("+toString(logId)+", "+toString(paramNum)+", "+toString(tnd->Size)+");"); - } - else - { - getDbNode()->xmlDescription.push_back(""); - initDb.add(pdslibFunc("initLogParam")+"("+toString(logId)+", "+toString(paramNum)+", "+toString(sizeof(uint16))+");"); - } - - - log += "$"+toString(paramNum); - - ++paramNum; - } - else - { - log += *(cptr++); - } - } - - getDbNode()->xmlDescription.push_back(""+xmlSpecialChars(log)+""); - getDbNode()->xmlDescription.push_back(""); - } - - logclass.get(startlogid).Proto = logfunc.Proto; - - CClassGenerator::SMethodId construct = logclass.startConstructor(logfunc.Proto, "pub", inlineLogFunctions, ""); - construct.add(logStartFunction+"("+argcall+");"); - CClassGenerator::SMethodId destruct = logclass.startDestructor("pub", inlineLogFunctions); - destruct.add(logStopFunction+"();"); - - CFileNode* file = getFileNode(); - - if (Context) - { - logclass.flush(file->hOutput(), file->cppOutput(), file->inlineOutput()); - file->hOutput() << "\n"; - } - else - { - logfunc.flush(file->hOutput(), file->cppOutput(), file->inlineOutput()); - file->hOutput() << "\n"; - } -} - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "parser.h" +#include "cpp_output.h" +#include "templatizer.h" + +#include "parser_rules.h" + +#include +#include + +using namespace std; +using namespace NLMISC; +//using namespace RY_PDS; + + +bool GenerateCpp = true; +bool GenerateXmlDescription = true; +bool VerboseMode = false; +bool GenerateDebugMessages = false; +bool GenerateHAuto = false; +bool GenerateOnlyLogs = false; + + +CTokenizer Tokenizer; +CTemplatizer Templatizer; +CHashKey HashKey; + +string CurrentEnum; +CEnumNode *CurrentEnumNode = NULL; + +string DbDescriptionVersion("0.0"); + +string formatDescription(const string &str) +{ + string result; + + uint pos = 0; + + while (pos < str.size() && (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\r' || str[pos] == '\n')) + ++pos; + + bool first = true; + + while (pos < str.size()) + { + if (!first) + result += "\n"; + first = false; + + result += "* "; + + while (pos < str.size() && str[pos] != '\n') + result += str[pos++]; + + while (pos < str.size() && (str[pos] == ' ' || str[pos] == '\t' || str[pos] == '\r' || str[pos] == '\n')) + ++pos; + } + + return result; +} + +string strReplace(string str, const string &search, const string &replace) +{ + std::string::size_type pos = 0; + while ((pos = str.find(search)) != string::npos) + str.replace(pos, search.size(), replace); + return str; +} + +string xmlSpecialChars(string str) +{ + str = strReplace(str, "&", "&"); + str = strReplace(str, "<", "<"); + str = strReplace(str, ">", ">"); + str = strReplace(str, "\"", """); + str = strReplace(str, "'", "'"); + + return str; +} + +string getFullStdPathNoExt(const string &path) +{ + string dir = NLMISC::toLower(NLMISC::CFile::getPath(path)); + string file = NLMISC::toLower(NLMISC::CFile::getFilenameWithoutExtension(path)); + + return dir.empty() ? file : NLMISC::CPath::standardizePath(dir)+file; +} + +string getFullStdPath(const string &path) +{ + string dir = NLMISC::toLower(NLMISC::CFile::getPath(path)); + string file = NLMISC::toLower(NLMISC::CFile::getFilename(path)); + + return dir.empty() ? file : NLMISC::CPath::standardizePath(dir)+file; +} + +string appendArg(const std::string& firstArgs, const std::string& nextArg) +{ + if (firstArgs.empty()) + return nextArg; + return firstArgs + ", " + nextArg; +} + +/* + * Start parsing + */ +CParseNode *parse(const string &file) +{ + HashKey = getSHA1(file); + + Tokenizer.readFile(file); + + if (Tokenizer.tokenize()) + return parseMain(Tokenizer); + return NULL; +} + + + +/* + * Execute nodes + */ + +// DB Node +bool CDbNode::prolog() +{ + addTypeNode("CSheetId", "NLMISC::CSheetId", "NLMISC::CSheetId::Unknown"); + addTypeNode("CEntityId", "NLMISC::CEntityId", "NLMISC::CEntityId::Unknown"); + addTypeNode("double", "double", "0.0"); + addTypeNode("float", "float", "0.0f"); + addTypeNode("sint64", "sint64", "(sint64)0"); + addTypeNode("uint64", "uint64", "(uint64)0"); + addTypeNode("sint32", "sint32", "0"); + addTypeNode("uint32", "uint32", "0"); + addTypeNode("sint16", "sint16", "0"); + addTypeNode("uint16", "uint16", "0"); + addTypeNode("sint8", "sint8", "0"); + addTypeNode("uint8", "uint8", "0"); + addTypeNode("ucchar", "ucchar", "0"); + addTypeNode("char", "char", "0"); + addTypeNode("bool", "bool", "false"); + + return true; +} + + + +bool inlineAccessors = false; +string getFunctionPrefix = "get"; +string setFunctionPrefix = "set"; +string newFunction = "addTo"; +string deleteFunction = "deleteFrom"; + +string indexVariable = "__i"; +string valueVariable = "__v"; +string keyVariable = "__k"; +string objectVariable = "__o"; + +bool inlineUserInitDefaultCode = false; +string userInitFunction = "init"; +string userReleaseFunction = "release"; + +bool inlineStaticPublic = false; +string staticCreateFunction = "create"; +string staticRemoveFunction = "remove"; +string staticSetUserFactoryFunction = "setFactory"; +string staticLoadFunction = "load"; +string staticUnloadFunction = "unload"; +string staticSetLoadCbFunction = "setLoadCallback"; +string staticGetFunction = "get"; +string staticCastFunction = "cast"; +string staticConstCastFunction = "cast"; +string staticBeginFunction = "begin"; +string staticEndFunction = "end"; + +bool inlineInternal = false; +string initFunction = "pds__init"; +string destroyFunction = "pds__destroy"; +string registerFunction = "pds__register"; +string registerAttributesFunction = "pds__registerAttributes"; +string unregisterFunction = "pds__unregister"; +string unregisterAttributesFunction = "pds__unregisterAttributes"; +string fetchFunction = "pds__fetch"; +string setParentFunction = "pds__setParent"; +string setUnnotifiedParentFunction = "pds__setParentUnnotified"; +string getTableFunction = "pds__getTable"; +string unlinkFunction = "pds__unlink"; +string notifyInitFunction = "pds__notifyInit"; +string notifyReleaseFunction = "pds__notifyRelease"; + +string clearFunction = "clear"; +string storeFunction = "store"; +string applyFunction = "apply"; +string declareTokensFunction = "pds__declareTokens"; + + +bool inlineStaticInternal = false; +string staticInitFactoryFunction = "pds_static__setFactory"; +string staticFactoryFunction = "pds_static__factory"; +string staticFetchFunction = "pds_static__fetch"; +string staticInitFunction = "pds_static__init"; +string staticNotifyLoadFailure = "pds_static__notifyFailure"; +string staticLoadCbAttribute = "__pds__LoadCallback"; + +bool inlineLog = false; +string logStartFunction = "pds__startLog"; +string logStopFunction = "pds__stopLog"; + +string PDSNamespace = "RY_PDS"; +string CPDSLibName = PDSNamespace+"::CPDSLib"; +string objectIndexName = PDSNamespace+"::CObjectIndex"; +string nullIndexName = PDSNamespace+"::CObjectIndex::null()"; +string TTableIndexName = PDSNamespace+"::TTableIndex"; +string TRowIndexName = PDSNamespace+"::TRowIndex"; +string TColumnIndexName = PDSNamespace+"::TColumnIndex"; +string INVALID_TABLE_INDEXName = PDSNamespace+"::INVALID_TABLE_INDEX"; +string INVALID_ROW_INDEXName = PDSNamespace+"::INVALID_ROW_INDEX"; +string indexAllocatorName = PDSNamespace+"::CIndexAllocator"; +string pdBaseDataName = PDSNamespace+"::IPDBaseData"; +//string pdBaseInheritDataName = PDSNamespace+"::IPDBaseInheritData"; +string CPDataName = PDSNamespace+"::CPData"; +string TPDFactoryName = PDSNamespace+"::TPDFactory"; +string TPDFetchName = PDSNamespace+"::TPDFetch"; +string TPDFetchFailureName = PDSNamespace+"::TPDFetchFailure"; + +bool inlineLogFunctions = false; + +string pdslibFunc(const std::string& func) +{ + //return CPDSLibName+"::"+func; + return "PDSLib."+func; +} + +bool CDbNode::epilog() +{ + uint i; + + Env = Templatizer.RootEnv; + setEnv("db", Name); + + string fullfile = getFullStdPathNoExt(MainFile.empty() ? Name : MainFile); + string filename = NLMISC::toLower(NLMISC::CFile::getFilenameWithoutExtension(fullfile)); + + setEnv("filename", filename); + setEnv("fullfilename", fullfile); + setEnv("headerfilename", strReplace(strupr(filename+".h"), ".", "_")); + + DbHpp.setFileHeader(filename+".h", "Initialisation of the "+Name+" database, declarations\n"+Description); + DbCpp.setFileHeader(filename+".cpp", "Initialisation of the "+Name+" database, implementation\n"+Description); + DbHppInline.setFileHeader(filename+"_inline.h", "Initialisation of the "+Name+" database, inline implementation\n"+Description); + + DbSummary << "\n\n"; + DbSummary << "Summary of " << Name << " database classes of database\n"; + DbSummary << "-----------------------------------------------------------------------------\n\n"; + DbSummary << "This file is automatically generated.\n"; + DbSummary << "This is a reminder of all classes generated and methods implemented.\n\n\n"; + + DbSummary << "Database " << Name << " is managed through 4 functions located in " << fullfile << ".h:\n\n"; + + DbSummary << Name << "::init():\n"; + DbSummary << "Initialises database context and connection towards database server (refered as PDS).\n"; + DbSummary << "All user factories must have been set before call to this function.\n"; + DbSummary << "Call this function in service init method.\n\n"; + + DbSummary << Name << "::ready():\n"; + DbSummary << "Tells whether the whole database engine is ready to work.\n"; + DbSummary << "You must not update any value nor call update() unless ready() is true.\n\n"; + + DbSummary << Name << "::update():\n"; + DbSummary << "Updates the database engine and sends updates to the PDS.\n"; + DbSummary << "Call this function each tick, provided ready() returned true.\n\n"; + + DbSummary << Name << "::release():\n"; + DbSummary << "Releases the database engine. Drops all data, closes the connection to the PDS.\n"; + DbSummary << "Call this function in service release method.\n\n"; + + DbSummary << "\n\n"; + DbSummary << "Summary of generated classes for " << Name << "\n\n"; + + DbHpp << "\n#ifndef " << strReplace(strupr(filename+".h"), ".", "_") << "\n"; + DbHpp << "#define " << strReplace(strupr(filename+".h"), ".", "_") << "\n"; + DbHpp << "\n"; + DbHpp << "#include \n"; + DbHpp << "#include \n"; + DbHpp << "\n"; + DbHpp << "namespace " << Name << "\n{\n\n"; + DbHpp.unindent(); + + if (!Pch.empty()) + { + DbCpp << "\n#include \"" << Pch << "\"\n\n"; + } + + DbCpp << "#include \"" << filename << ".h\"\n\n"; + DbCpp << "namespace " << Name << "\n{\n\n"; + DbCpp.unindent(); + + DbCpp << "RY_PDS::CPDSLib PDSLib;\n"; + + DbHppInline << "namespace " << Name << "\n{\n\n"; + DbHppInline.unindent(); + + + uint maxClassId = 0; + for (i=0; i"); + xmlDescription.push_back(""); + //xmlDescription.push_back(""); + xmlDescription.push_back(""); + + pass1(); + + pass2(); + + pass3(); + + // Check dependencies order + vector classesOrder; + vector filesOrder; + buildClassOrder(classesOrder, filesOrder); + + // generate all file prologs + for (i=0; igenerateProlog(); + } + + pass4(); + + // + initDb.init("init"); + initDb.IsInline = false; + initDb.Proto = "uint32 overrideDbId"; + initDb.Type = "void"; + initDb.Description = "Initialise the whole database engine.\nCall this function at service init."; + + readyDb.init("ready"); + readyDb.IsInline = false; + readyDb.Proto = ""; + readyDb.Type = "bool"; + readyDb.Description = "Tells if database engine is ready to work.\nEngine may not be ready because PDS is down, not yet ready\nor message queue to PDS is full."; + + updateDb.init("update"); + updateDb.IsInline = false; + updateDb.Proto = ""; + updateDb.Type = "void"; + updateDb.Description = "Update the database engine.\nCall this method once per tick, only if engine is ready (see also ready() above)."; + + logChatDb.init("logChat"); + logChatDb.IsInline = false; + logChatDb.Proto = "const ucstring& sentence, const NLMISC::CEntityId& from, const std::vector& to"; + logChatDb.Type = "void"; + logChatDb.Description = "Logs chat sentence with sender and receipiants."; + + logTellDb.init("logTell"); + logTellDb.IsInline = false; + logTellDb.Proto = "const ucstring& sentence, const NLMISC::CEntityId& from, const NLMISC::CEntityId& to"; + logTellDb.Type = "void"; + logTellDb.Description = "Logs tell sentence with sender and single recipient (might be player or group)."; + + releaseDb.init("release"); + releaseDb.IsInline = false; + releaseDb.Proto = ""; + releaseDb.Type = "void"; + releaseDb.Description = "Release the whole database engine.\nCall this function at service release."; + + // + generateClassesDeclaration(); + + // + generateClassesContent(classesOrder); + + // + generateLogContent(); + + xmlDescription.push_back(""); + xmlDescription.push_back("");; + + initDb.add("std::string\txmlDescription;"); + + DbXml.setXmlMode(); + + for (i=0; i\tids;"); + logTellDb.add("ids.push_back(to);"); + logTellDb.add(pdslibFunc("logChat")+"(sentence, from, ids);"); + logTellDb.flush(DbHpp, DbCpp, DbHppInline); + + releaseDb.add(pdslibFunc("release")+"();"); + releaseDb.flush(DbHpp, DbCpp, DbHppInline); + + DbHpp << "\n// @}\n\n"; + + DbHpp << "extern RY_PDS::CPDSLib PDSLib;\n"; + + DbHpp.indent(); + DbHpp << "\n} // End of " << Name <<"\n"; + + generateIncludes(filesOrder); + + DbHpp << "\n#include \"" << filename << "_inline.h\"\n\n"; + DbHpp << "\n#endif\n"; + DbHpp.flush(fullfile+".h"); + + DbCpp.indent(); + DbCpp << "\n} // End of " << Name <<"\n"; + DbCpp.flush(fullfile+".cpp"); + + DbHppInline.indent(); + DbHppInline << "\n} // End of " << Name <<"\n"; + DbHppInline.flush(fullfile+"_inline.h"); + + DbSummary.flush(fullfile+"_summary.txt"); + + for (i=0; igenerateEpilog(); + } + + return true; +} + + + +void CDbNode::pass1() +{ + /* + * PASS 1 + * - all type names and class names are known + * -> look for classes in set or backreferences + */ + + uint i; + + uint classId = 0; + uint typeId = 0; + + for (i=0; icheckClassReferences(); + classnd->Id = classId++; + + classnd->getFileNode()->IncludeStandard = true; + classnd->getFileNode()->IncludeDbFile = true; + } + + for (i=0; iId = typeId++; + + uint tsize = 0; + if (typend->StorageType == "bool") tsize = 1; + if (typend->StorageType == "char") tsize = 1; + if (typend->StorageType == "ucchar") tsize = 2; + if (typend->StorageType == "uint8") tsize = 1; + if (typend->StorageType == "sint8") tsize = 1; + if (typend->StorageType == "uint16") tsize = 2; + if (typend->StorageType == "sint16") tsize = 2; + if (typend->StorageType == "uint32") tsize = 4; + if (typend->StorageType == "sint32") tsize = 4; + if (typend->StorageType == "uint64") tsize = 8; + if (typend->StorageType == "sint64") tsize = 8; + if (typend->StorageType == "float") tsize = 4; + if (typend->StorageType == "double") tsize = 8; + if (typend->StorageType == "CEntityId") tsize = 8; + if (typend->StorageType == "CSheetId") tsize = 4; + + typend->Size = tsize; + + string xmlnode = "isEnum()) + { + CEnumNode *enumnd = static_cast(typend); + + xmlnode += " type='enum'>"; + xmlDescription.push_back(xmlnode); + uint j; + for (j=0; jValues.size(); ++j) + xmlDescription.push_back(""); + xmlDescription.push_back(""); + } + else if (typend->isDimension()) + { + CDimensionNode *dimnd = static_cast(typend); + + xmlnode += " type='dimension' dimension='"+toString(dimnd->Dimension)+"'/>"; + xmlDescription.push_back(xmlnode); + } + else + { + xmlnode += " type='type'/>"; + xmlDescription.push_back(xmlnode); + } + } +} + +void CDbNode::pass2() +{ + /* + * PASS 2 + * - class hierarchy, backreferences and in set information are known + * -> fill up attributes + */ + + uint i; + + for (i=0; iInherited.empty() && child->MappedFlag && !child->HasParent) + child->error("class cannot inherit another class and be mapped. Try to map base class instead."); + + if (child->MappedFlag && child->getClassKey() == NULL) + child->error("class is mapped and has no key defined"); + + child->ForceReference = (child->HasInheritance || child->MappedFlag || child->DerivatedFlag || (child->HasParent && !child->ParentIsHidden)); + + if (child->ForceReference && child->ParentIsHidden) + child->error("Parent attribute cannot be hidden because class has inheritance, is mapped or is derivated."); + + child->getFileNode()->IncludePDSLib = true; + + if (!child->Inherited.empty()) + { + CClassNode *icln = child; + CClassNode *lastMapped = (child->MappedFlag ? child : NULL); + while (!icln->Inherited.empty()) + { + icln = getClassNode(icln->Inherited); + if (icln->MappedFlag) + { + if (lastMapped != NULL) + lastMapped->error("class cannot be remapped since parent "+icln->Name+" is already mapped"); + lastMapped = icln; + } + } + + /* + if (icln->MappedFlag) + child->MapClass = icln; + */ + child->MapClass = lastMapped; + } + else if (child->MappedFlag) + { + child->MapClass = child; + } + + child->fillAttributes(); + } +} + + +void CDbNode::pass3() +{ + /* + * PASS 3 + * - attributes are known + * -> fill up backrefs and array/set forwardrefs + */ + + uint i; + + for (i=0; ifillRefs(); + } + + for (i=0; icomputeFriends(); + } +} + +void CDbNode::pass4() +{ + /* + * PASS 4 + * - everything is ok in database descriptor + * -> output c++ code + */ + + uint i; + + for (i=0; iHpp << "\n\n//\n// Typedefs & Enums\n//\n\n"; + } + + for (i=0; iExternFlag || type->InternFlag) + continue; + + type->generateContent(); + + } +} + + + +void CDbNode::generateClassesDeclaration() +{ + uint i; + + DbHpp << "\n//\n"; + DbHpp << "// Global Forward Declarations\n"; + DbHpp << "//\n\n"; + + for (i=0; iName << ";\n"; + } + + DbHpp << "\n"; + DbHpp << "//\n\n"; +} + +void CDbNode::generateIncludes(vector& filesOrder) +{ + uint i; + + DbHpp << "\n//\n"; + DbHpp << "// Includes\n"; + DbHpp << "//\n\n"; + + for (i=0; iSeparatedFlag) + { + filesOrder[i]->setEnv("as", getFileNoExtPath(filesOrder[i]->IncludeAs)); + DbHpp << "#include \"" << getFileNoExtPath(filesOrder[i]->IncludeAs) << ".h\"\n"; + } + } + + DbHpp << "\n"; + + for (i=0; iIncludeDbFile && !filesOrder[i]->SeparatedFlag) + { + filesOrder[i]->define("incinline"); + DbHpp << "#include \"" << getFileNoExtPath(filesOrder[i]->IncludeAs) << "_inline.h\"\n"; + } + } + + DbHpp << "\n"; + DbHpp << "//\n\n"; +} + +void CDbNode::generateClassesContent(vector& classesOrder) +{ + uint i; + + // + // output classes content + // + for (i=0; iId)+", \""+cln->Name+"\");"); + cln->generateContent(); + } +} + +void CDbNode::buildClassOrder(vector& classesOrder, vector& filesOrder) +{ + set checkedClasses; + + uint i; + + for (i=0; i beingChecked; + child->checkDependencies(beingChecked, checkedClasses, classesOrder); + } + + set checkedFiles; + filesOrder.clear(); + + for (i=0; i beingChecked; + child->checkDependencies(beingChecked, checkedFiles, filesOrder); + } + + for (i=0; iEnv = Env->nextArrayNode("files"); + + for (i=0; iEnv = classesOrder[i]->getFileNode()->Env->nextArrayNode("classes"); +} + + +void CDbNode::generateLogContent() +{ + uint logid = 0; + + uint i; + + for (i=0; iId = logid; + logid += (uint)child->Logs.size(); + + child->generateContent(); + } +} + +// get file path from this file +string CDbNode::getFileNoExtPath(const std::string& file) +{ + string thisPath = NLMISC::CFile::getPath(NLMISC::toLower(getDbFile())); + string filePath = NLMISC::CFile::getPath(NLMISC::toLower(file)); + string fileName = NLMISC::CFile::getFilename(NLMISC::toLower(file)); + + if (thisPath == filePath) + return CFile::getFilenameWithoutExtension(fileName); + else + return CPath::standardizePath(filePath)+CFile::getFilenameWithoutExtension(NLMISC::toLower(file)); +} + + + + +// File Node +bool CFileNode::prolog() +{ + CDbNode* db = getDbNode(); + db->FileNodes.push_back(this); + + if (GenerateOnlyLogs) + Generate = false; + + return true; +} + +bool CFileNode::epilog() +{ + return true; +} + +bool CFileNode::generateProlog() +{ + CDbNode* db = getDbNode(); + + if (!db->Description.empty()) + Hpp << db->Description << "\n"; + + string filename = NLMISC::toLower(CFile::getFilenameWithoutExtension(Name)); + + setEnv("fullfilename", getFullStdPathNoExt(Name)); + setEnv("filename", filename); + setEnv("headerfilename", strReplace(strupr(filename+".h"), ".", "_")); + setEnv("description", Description); + + Hpp.setFileHeader(filename+".h", Description); + Cpp.setFileHeader(filename+".cpp", Description); + HppInline.setFileHeader(filename+"_inline.h", Description); + + Hpp << "\n#ifndef " << strReplace(strupr(filename+".h"), ".", "_") << "\n"; + Hpp << "#define " << strReplace(strupr(filename+".h"), ".", "_") << "\n\n"; + + + Hpp << "#include \n"; + Hpp << "#include \n"; + Hpp << "#include \n"; + + if (GenerateHAuto) + { + Hpp << "#include \n"; + } + + if (IncludeStandard) + { + define("incstd"); + Hpp << "#include \n"; + Hpp << "#include \n"; + } + + Hpp << "#include \n"; + Hpp << "#include \n"; + + if (IncludePDSLib) + { + define("incpdslib"); + Hpp << "#include \n"; + Hpp << "#include \n"; + } + Hpp << "\n"; + + if (SeparatedFlag) + { + string fullfile = getFullStdPathNoExt(db->MainFile.empty() ? db->Name : db->MainFile); + string filename = NLMISC::toLower(NLMISC::CFile::getFilenameWithoutExtension(fullfile)); + Hpp << "#include \"" << filename << ".h\"\n"; + Hpp << "\n"; + } + + Hpp << "// User #includes\n"; + uint i; + for (i=0; inextArrayNode("incuser")->set("as", IncludeNodes[i]->Name); + Hpp << "#include \"" << IncludeNodes[i]->Name << "\"\n"; + } + + Hpp << "\nnamespace " << db->Name << "\n{\n\n"; + Hpp.unindent(); + + if (!db->Description.empty()) + HppInline << db->Description; + HppInline << "namespace " << db->Name << "\n{\n\n"; + HppInline.unindent(); + Hpp << "//\n// Forward declarations\n//\n\n"; + + if (!db->Pch.empty()) + { + Cpp << "\n"; + Cpp << "#include \""+db->Pch+"\""; + } + + Cpp << "\n"; + if (SeparatedFlag || !IncludeDbFile) + { + Cpp << "#include \"" << filename << ".h\"\n"; + } + else + { + Cpp << "#include \"" << getFileNoExtPath(getDbNode()->getDbFile()) << ".h\"\n"; + } + + Cpp << "\n"; + Cpp << "namespace " << db->Name << "\n{\n\n"; + Cpp.unindent(); + + return true; +} + +bool CFileNode::generateEpilog() +{ + CDbNode* db = getDbNode(); + + string fullfile = getFullStdPathNoExt(Name); + string filename = NLMISC::toLower(CFile::getFilenameWithoutExtension(Name)); + + Hpp.indent(); + Hpp << "\n} // End of " << db->Name <<"\n"; + + if (!IncludeDbFile || SeparatedFlag) + { + // add inline #include + Hpp << "\n\n//\n// Inline implementations\n//\n\n"; + Hpp << "#include \"" << filename << "_inline.h\"\n"; + } + + Hpp << "\n#endif\n"; + + HppInline.indent(); + HppInline << "\n} // End of " << db->Name <<"\n"; + + Cpp.indent(); + Cpp << "\n} // End of " << db->Name <<"\n"; + + if (Generate) + writeFile(); + + return true; +} + +string CFileNode::getFileNoExtPath(const string& file) +{ + string thisPath = NLMISC::CFile::getPath(NLMISC::toLower(Name)); + string filePath = NLMISC::CFile::getPath(NLMISC::toLower(file)); + string fileName = NLMISC::CFile::getFilename(NLMISC::toLower(file)); + + if (thisPath == filePath) + return CFile::getFilenameWithoutExtension(fileName); + else + return CFile::getFilenameWithoutExtension(NLMISC::toLower(file)); +} + +void CFileNode::writeFile() +{ + string fullfile = getFullStdPathNoExt(Name); + + Hpp.flush(fullfile+".h"); + Cpp.flush(fullfile+".cpp"); + HppInline.flush(fullfile+"_inline.h"); +} + +void CFileNode::checkDependencies(set &beingChecked, + set &checkedFiles, + vector &filesOrder) +{ + if (beingChecked.find(this) != beingChecked.end()) + error("circular dependency in file '"+Name+"'"); + + if (checkedFiles.find(this) != checkedFiles.end()) + return; + + beingChecked.insert(this); + checkedFiles.insert(this); + + set::iterator it; + for (it=Dependencies.begin(); it!=Dependencies.end(); ++it) + { + CFileNode *fileNode = *it; + if (fileNode == this) + continue; + + fileNode->checkDependencies(beingChecked, checkedFiles, filesOrder); + } + + filesOrder.push_back(this); +} + + + + + + + +// Type Node +bool CTypeNode::prolog() +{ + CDbNode* db = getDbNode(); + db->TypeNodes.push_back(this); + + return true; +} + +bool CTypeNode::generateContent() +{ + hOutput() << "/** " << Name << "\n"; + if (!Description.empty()) + { + hOutput() << Description << "\n"; + } + uint line, col; + string file; + getFileLine(line, col, file); + hOutput() << "defined at " << file << ":" << line << "\n"; + hOutput() << "*/\n"; + + hOutput() << "typedef " << getCppType() << " " << Name << ";\n\n"; + + + if (ToCppType != NULL) + { + CCppCodeNode *tocpp = static_cast(ToCppType); + + CFunctionGenerator toCppFunc; + + toCppFunc.init(storageToCpp()); + toCppFunc.setType(getName()); + toCppFunc.IsInline = true; + toCppFunc.Proto = StorageType+" _v"; + + toCppFunc.add(getName()+"\t__res;"); + toCppFunc.add(strReplace(strReplace(tocpp->RawCode, "$("+CppType+")", "__res"), "$("+StorageType+")", "_v")); + toCppFunc.add("return __res;"); + toCppFunc.flush(hOutput(), cppOutput(), inlineOutput()); + } + if (ToStorageType != NULL) + { + CCppCodeNode *tostorage = static_cast(ToStorageType); + + CFunctionGenerator toStorageFunc; + + toStorageFunc.init(cppToStorage()); + toStorageFunc.setType(StorageType); + toStorageFunc.IsInline = true; + toStorageFunc.Proto = getName()+" _v"; + + toStorageFunc.add(StorageType+"\t__res;"); + toStorageFunc.add(strReplace(strReplace(tostorage->RawCode, "$("+StorageType+")", "__res"), "$("+CppType+")", "_v")); + toStorageFunc.add("return __res;"); + toStorageFunc.flush(hOutput(), cppOutput(), inlineOutput()); + } + + hOutput() << "\n"; + + return true; +} + + + +// Include Node +bool CIncludeNode::prolog() +{ + CFileNode* file = getFileNode(); + file->IncludeNodes.push_back(this); + return true; +} + + +// Include Node +bool CUsePchNode::prolog() +{ + CDbNode* db = getDbNode(); + db->Pch = Name; + return true; +} + + +// CppCode Node +bool CCppCodeNode::prolog() +{ + return true; +} + + + + + + +// Dimension Nodes +bool CDimensionNode::prolog() +{ + CDbNode* db = getDbNode(); + db->TypeNodes.push_back(this); + + if (Dimension < 256) + StorageType = "uint8"; + else if (Dimension < 65536) + StorageType = "uint16"; + else + StorageType = "uint32"; + + CppType = "uint32"; + + return true; +} + +bool CDimensionNode::epilog() +{ + return true; +} + +bool CDimensionNode::generateContent() +{ + hOutput() << "/** " << Name << "\n"; + if (!Description.empty()) + { + hOutput() << Description << "\n"; + } + uint line, col; + string file; + getFileLine(line, col, file); + hOutput() << "defined at " << file << ":" << line << "\n"; + hOutput() << "*/\n"; + + hOutput() << "typedef " << CppType << " " << Name << ";\n"; + hOutput() << "const " << getName() << "\t" << getSizeName() << " = " << Dimension << ";\n\n"; + + return true; +} + +// Enum Nodes +bool CEnumNode::prolog() +{ + CDbNode* db = getDbNode(); + db->TypeNodes.push_back(this); + + if (Name.empty() || Name[0] != 'T') + error("enum name '"+Name+"' is invalid, must begin with a 'T'"); + + CurrentValue = 0; + CurrentEnum = Name; + CurrentEnumNode = this; + + MinValue = 0; + MaxValue = 0; + + return true; +} + +bool CEnumNode::epilog() +{ + uint i; + + for (i=0; i(Nodes[i]); + if (!nd) + continue; + Values.insert(Values.end(), nd->Values.begin(), nd->Values.end()); + } + + for (i=0; i Values[i].second) + MinValue = Values[i].second; + if (MaxValue < Values[i].second) + MaxValue = Values[i].second; + } + + CurrentEnumNode = NULL; + return true; +} + +bool CEnumSimpleValueNode::prolog() +{ + CEnumNode *parent = dynamic_cast(Parent); + if (parent != NULL) + { + CurrentValue = parent->CurrentValue; + } + else + { + CurrentValue = 0; + } + uint i; + for (i=0; iValues.push_back(make_pair(Names[i], CurrentValue)); + } + if (parent != NULL) + ++(parent->CurrentValue); + + return true; +} + +bool CEnumSimpleValueNode::epilog() +{ + return true; +} + +bool CEnumRangeNode::prolog() +{ + CEnumNode *parent = dynamic_cast(Parent); + if (parent != NULL) + { + CurrentValue = parent->CurrentValue; + } + else + { + CurrentValue = 0; + } + + CurrentEnumNode->Values.push_back(make_pair(Name, CurrentValue)); + + return true; +} + +bool CEnumRangeNode::epilog() +{ + CEnumNode *parent = dynamic_cast(Parent); + if (parent != NULL) + { + parent->CurrentValue = CurrentValue; + } + + uint i; + for (i=0; i(Nodes[i]); + if (!nd) + continue; + Values.insert(Values.end(), nd->Values.begin(), nd->Values.end()); + } + + if (!EndRange.empty()) + { + CurrentEnumNode->Values.push_back(make_pair(EndRange, CurrentValue)); + } + + return true; +} + + +bool CEnumNode::generateContent() +{ + hOutput() << "/** " << Name << "\n"; + if (!Description.empty()) + { + hOutput() << Description << "\n"; + } + uint line, col; + string file; + getFileLine(line, col, file); + hOutput() << "defined at " << file << ":" << line << "\n"; + hOutput() << "*/\n"; + + string enumTruncName = Name.substr(1); + CClassGenerator gen; + gen.init("C"+enumTruncName); + gen.createPublic("enum", "Enum values", ""); + gen.createPublic("conv", "Conversion methods", "Use these methods to convert from enum value to string (and vice versa)"); + gen.createPrivate("init", "Enum initialisation", ""); + + uint j; + gen.addOther("enum "+Name+"\n", "enum"); + gen.addOther("{\n", "enum"); + for (j=0; j= "+getUnscopedUseSize()+")"); + gen.add("{"); + gen.add("nlwarning(\""+Name+"::toString(): value '%u' is not matched, \\\"Unknown\\\" string returned\", v);"); + gen.add("return _UnknownString;"); + gen.add("}"); + //gen.add(checkCode("v")); + gen.add("if (!_Initialised)"); + gen.add("{"); + gen.add("init();"); + gen.add("}"); + gen.add("return _StrTable[v];"); + + gen.startMethod(getName(), "fromString", "const std::string& v", "conv", false, true, true); + gen.add("if (!_Initialised)"); + gen.add("{"); + gen.add("init();"); + gen.add("}"); + gen.add("if(v==_UnknownString)"); + gen.add("{"); + gen.add("return Unknown;"); + gen.add("}"); + gen.add("const std::map::const_iterator\tit = _ValueMap.find(NLMISC::toLower(v));"); + gen.add("if (it == _ValueMap.end())"); + gen.add("{"); + gen.add("nlwarning(\""+Name+"::toString(): string '%s' is not matched, 'Unknown' enum value returned\", v.c_str());"); + gen.add("return "+getUnknownValue()+";"); + gen.add("}"); + gen.add("return (*it).second;"); + + + gen.startMethod("void", "init", "", "init", false, false, true); + gen.add("_StrTable.clear();"); + gen.add("_ValueMap.clear();"); + gen.add("_StrTable.resize("+toString(getSize()+1)+");"); + gen.add("uint\ti;"); + gen.add("for (i=0; i<"+toString(Values.size())+"; ++i)"); + gen.add("{"); + gen.add("_StrTable["+Name+"Convert[i].Value] = "+Name+"Convert[i].Name;"); + gen.add("_ValueMap[NLMISC::toLower(std::string("+Name+"Convert[i].Name))] = "+Name+"Convert[i].Value;"); + gen.add("}"); + + gen.add("_Initialised = true;"); + + + gen.addAttribute("bool", "_Initialised", "init", true, "false"); + gen.addAttribute("std::string", "_UnknownString", "init", true, "\""+getUnknownValue()+"\""); + gen.addAttribute("std::vector", "_StrTable", "init", true); + gen.addAttribute("std::map", "_ValueMap", "init", true, "", false, "std::map"); + + cppOutput() << "static const struct { char* Name; " << getName() << " Value; } " << Name << "Convert[] =\n"; + cppOutput() << "{\n"; + for (j=0; jClassNodes.push_back(this); + + return true; +} + +bool CClassNode::epilog() +{ + return true; +} + +string CClassNode::getUserCode(const string& name) +{ + uint i; + for (i=0; i(Nodes[i]); + if (!code) + continue; + + if (code->Name == name) + return code->RawCode; + } + + return ""; +} + + +void CClassNode::checkClassReferences() +{ + if (!Implements.empty()) + { + Gen.Inherit += (HasRowAccess ? string(", ") : string(""))+"public "+Implements; + getDbNode()->Implemented.insert(Implements); + } + + + if (!Inherited.empty()) + { + HasInheritance = true; + CClassNode *nd = getClassNode(Inherited); + nd->HasInheritance = true; + nd->ChildrenClasses.push_back(Name); + + Dependencies.insert(nd); + getFileNode()->Dependencies.insert(nd->getFileNode()); + } + + CClassNode* inherit = this; + while (inherit != NULL) + { + if (MappedFlag) + inherit->PDSMapped = true; + + inherit->Legacy.insert(this); + inherit = getClassNode(inherit->Inherited, false); + } + + uint i; + uint id = 0; + for (i=0; i(Nodes[i]); + if (!decl) + continue; + + decl->Id = id++; + + if (decl->ParentFlag) + { + if (HasParent) + decl->error("class '"+Name+"' already has a parent"); + + //if (MappedFlag) + // decl->error("class '"+Name+"' can't have a parent and be mapped at the same time"); + + CClassNode* inherit = this; + while (inherit != NULL) + { + inherit->PDSMapped = false; + inherit = getClassNode(inherit->Inherited, false); + } + + ParentClass = decl->ParentClass; + HasParent = true; + + ParentIsHidden = decl->HiddenFlag; + + decl->getClassNode(decl->ParentClass)->IsBackReferenced = true; + } + else if (decl->SetFlag) + { + decl->getClassNode(decl->Type)->IsInSet = true; + } + } +} + +void CClassNode::fillAttributes() +{ + if (HasParent && !IsBackReferenced && !HasInheritance && !IsInSet && !DerivatedFlag && !MappedFlag) + error("class '"+Name+"' has a parent whereas it is not backreferenced, has no inherited link and is not mapped"); + + uint i; + for (i=0; i(Nodes[i]); + if (!decl) + continue; + + uint j; + for (j=0; j(Nodes[j]) != NULL && Nodes[j]->Name == decl->Name) + decl->error("attribute '"+decl->Name+"' already defined"); + + if (decl->ParentFlag) + { + decl->DeclarationType = BackRef; + } + else if (decl->ArrayFlag) + { + CClassNode *classNd = NULL; + CTypeNode *typeNd = NULL; + + if ( (classNd = decl->getClassNode(decl->Type, false)) ) + { + if (classNd->IsBackReferenced || classNd->ForceReference) + { + if (decl->ForwardRefAttribute.empty()) + decl->error("no forward reference to parent in array declaration, class '"+decl->Type+"' is backref'd or has inheritance"); + + classNd->IsInArrayRef = true; + decl->IsRef = true; + decl->DeclarationType = ArrayRef; + + if (classNd->ParentIsHidden) + Dependencies.insert(classNd); + } + else + { + if (!decl->ForwardRefAttribute.empty()) + decl->error("forward reference declared whereas subclass is not backreferenced and has no inheritance link"); + + Dependencies.insert(classNd); + + classNd->IsInArray = true; + decl->IsRef = false; + decl->DeclarationType = ArrayClass; + } + } + else if ( (typeNd = decl->getTypeNode(decl->Type, false)) ) + { + decl->DeclarationType = ArrayType; + } + else + { + decl->error("type or class '"+decl->Type+"' not found"); + } + } + else if (decl->SetFlag) + { + decl->IsRef = true; + decl->DeclarationType = Set; + } + else + { + CClassNode *classNd = NULL; + CTypeNode *typeNd = NULL; + + if ( (classNd = decl->getClassNode(decl->Type, false)) ) + { + if (classNd->IsBackReferenced || classNd->ForceReference) + { + if (decl->ForwardRefAttribute.empty()) + decl->error("no forward reference to parent in array declaration, class '"+decl->Type+"' is backref'd or has inheritance"); + + decl->IsRef = true; + + decl->DeclarationType = ForwardRef; + } + else + { + if (!decl->ForwardRefAttribute.empty()) + decl->error("forward reference declared whereas subclass is not backreferenced and has no inheritance link"); + + Dependencies.insert(classNd); + + decl->IsRef = false; + + decl->DeclarationType = SimpleClass; + } + } + else if ( (typeNd = decl->getTypeNode(decl->Type, false)) ) + { + decl->IsType = true; + + decl->DeclarationType = SimpleType; + } + else + { + decl->error("type or class '"+decl->Type+"' not found"); + } + } + } + + CDeclarationNode *declNd = getClassKey(); + if (declNd != NULL) + { + if (!declNd->IsType) + error("attribute '"+declNd->Name+"' can't be a key, only simple type allowed"); + + declNd->IsKey = true; + } +} + +void CClassNode::fillRefs() +{ + uint i; + for (i=0; i(Nodes[i]); + if (!decl) + continue; + + switch (decl->DeclarationType) + { + case BackRef: + { + // check parent is a valid class + CClassNode *cln = decl->getClassNode(decl->ParentClass); + CDeclarationNode *dln = dynamic_cast(cln->getNode(decl->ParentField)); + if (!dln) decl->error("attribute '"+decl->ParentField+"' not found in class '"+decl->ParentClass+"'"); + + if (!dln->ArrayFlag && !dln->SetFlag && !ForceReference) + decl->error("back reference 'parent "+decl->ParentClass+":"+decl->ParentField+" "+decl->Name+"' is not forwarded in class '"+decl->ParentClass+"' with an array or a set"); + + if (dln->Type != Name || dln->ForwardRefAttribute != decl->Name) + decl->error("back reference 'parent "+decl->ParentClass+":"+decl->ParentField+" "+decl->Name+"' is not correctly forwarded in class '"+decl->ParentClass+"'"); + + Friends.insert(cln->Name); + } + break; + + case Set: + { + CClassNode *cln = decl->getClassNode(decl->Type); + CDeclarationNode *dln = dynamic_cast(cln->getNode(decl->ForwardRefAttribute)); + if (!dln) decl->error("attribute '"+decl->ForwardRefAttribute+"' not found in class '"+decl->Type+"'"); + + if (!dln->ParentFlag) + decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not backref'd in class '"+decl->Type+"'"); + + if (dln->ParentClass != Name || dln->ParentField != decl->Name) + decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not correctly backref'd in class '"+decl->Type+"'"); + + if (cln->getClassKey() == NULL) + decl->error("class '"+decl->Type+"' has no key defined, whereas it is used in a set"); + + cln->Friends.insert(Name); + ForwardFriends.insert(cln->Name); + } + break; + + case ArrayRef: + { + if (decl->ForwardRefAttribute.empty()) + decl->error("No forward reference defined"); + + CClassNode *cln = decl->getClassNode(decl->Type); + CDeclarationNode *dln = dynamic_cast(cln->getNode(decl->ForwardRefAttribute)); + CTypeNode *tln = decl->getTypeNode(decl->ArrayIndex); + getFileNode()->Dependencies.insert(tln->getFileNode()); + if (!dln) decl->error("attribute '"+decl->ForwardRefAttribute+"' not found in class '"+decl->Type+"'"); + + if (!dln->ParentFlag) + decl->error("array '"+decl->Type+":"+decl->ForwardRefAttribute+"["+decl->ArrayIndex+"] "+decl->Name+"' is not backref'd in class '"+decl->Type+"'"); + + if (dln->ParentClass != Name || dln->ParentField != decl->Name) + decl->error("array '"+decl->Type+":"+decl->ForwardRefAttribute+"["+decl->ArrayIndex+"] "+decl->Name+"' is not correctly backref'd in class '"+decl->Type+"'"); + + if (cln->getClassKey() == NULL) + decl->error("class '"+decl->Type+"' has no key defined, whereas it is used in an array of ref"); + CDeclarationNode *kdn = dynamic_cast(cln->getClassKey()); + if (!kdn) decl->error("attribute '"+cln->ClassKey+"' not found in class '"+cln->Name+"'"); + + if (kdn->Type != decl->ArrayIndex) + decl->error("type in array definition mismatch class '"+cln->Name+"' key definition"); + + cln->Friends.insert(Name); + ForwardFriends.insert(cln->Name); + } + break; + + case ForwardRef: + { + if (decl->ForwardRefAttribute.empty()) + decl->error("No forward reference defined"); + + CClassNode *cln = decl->getClassNode(decl->Type); + CDeclarationNode *dln = dynamic_cast(cln->getNode(decl->ForwardRefAttribute)); + if (!dln) decl->error("attribute '"+decl->ForwardRefAttribute+"' not found in class '"+decl->Type+"'"); + + if (!dln->ParentFlag) + decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not backref'd in class '"+decl->Type+"'"); + + if (dln->ParentClass != Name || dln->ParentField != decl->Name) + decl->error("set '"+decl->Type+":"+decl->ForwardRefAttribute+"<> "+decl->Name+"' is not correctly backref'd in class '"+decl->Type+"'"); + + cln->Friends.insert(Name); + ForwardFriends.insert(cln->Name); + } + break; + + case ArrayType: + { + CTypeNode *tln = decl->getTypeNode(decl->ArrayIndex); + getFileNode()->Dependencies.insert(tln->getFileNode()); + } + case SimpleType: + break; + + case ArrayClass: + { + CTypeNode *tln = decl->getTypeNode(decl->ArrayIndex); + getFileNode()->Dependencies.insert(tln->getFileNode()); + } + case SimpleClass: + { + CClassNode *cln = decl->getClassNode(decl->Type); + cln->Friends.insert(Name); + } + break; + + default: + decl->error("Can't decide declaration type"); + break; + } + } +} + +void CClassNode::computeFriends() +{ + bool added; + + do + { + added = false; + set::iterator itf, itsf; + + for (itf=Friends.begin(); !added && itf!=Friends.end(); ++itf) + { + CClassNode* pfriend = getClassNode(*itf); + + for (itsf=pfriend->Friends.begin(); !added && itsf!=pfriend->Friends.end(); ++itsf) + { + const string& sfriend = *itsf; + if (Friends.find(*itsf) == Friends.end()) + { + Friends.insert(*itsf); + added = true; + } + } + } + } + while (added); +} + + +void CClassNode::checkDependencies(set &beingChecked, + set &checkedClasses, + vector &classesOrder) +{ + if (beingChecked.find(this) != beingChecked.end()) + error("circular dependency in class '"+Name+"'"); + + if (checkedClasses.find(this) != checkedClasses.end()) + return; + + beingChecked.insert(this); + checkedClasses.insert(this); + + set::iterator it; + for (it=Dependencies.begin(); it!=Dependencies.end(); ++it) + { + CClassNode *classNode = *it; + + classNode->checkDependencies(beingChecked, checkedClasses, classesOrder); + } + + classesOrder.push_back(this); +} + + +// +void CClassNode::buildInit() +{ + CDbNode *db = getDbNode(); + + if (!Init.empty()) + return; + + if (!Inherited.empty()) + { + CClassNode *mother = getClassNode(Inherited); + if (mother) + { + mother->buildInit(); + Init = mother->Init; + + uint i; + for (i=0; iType); + InitProto += "const "+typeNode->getName()+" &"+Init[i]->Name; + InitCallArgs += Init[i]->Name; + } + } + } + + if (!ClassKey.empty()) + { + CDeclarationNode *decl = dynamic_cast(getNode(ClassKey)); + if (decl) + { + Init.push_back(decl); + + if (!InitProto.empty()) + InitProto += ", "; + + CTypeNode* typeNode = getTypeNode(decl->Type); + InitProto += "const "+typeNode->getName()+" &"+decl->Name; + } + } +} + + + + + + +void CClassNode::computeAttributesColumns() +{ + if (Columns >= 0) + return; + + CDbNode *db = getDbNode(); + + Columns = 0; + if (!Inherited.empty()) + { + CClassNode *mother = getClassNode(Inherited); + mother->computeAttributesColumns(); + Columns = mother->Columns; + + Attributes = mother->Attributes; + } + + uint attribId = (uint)Attributes.size(); + uint i; + for (i=0; i(Nodes[i]); + if (decl == NULL) + continue; + + Attributes.push_back(decl); + + decl->Column = Columns; + decl->Id = attribId++; + CColumn col; + + // All for backref, set, forwardref, type + switch (decl->DeclarationType) + { + case ForwardRef: + decl->Columns = 1; + col.Name = decl->Name; + col.Type = ForwardRef; + col.TypeStr = "forwardref"; + col.TypeId = decl->getClassNode(decl->Type)->Id; + col.ByteSize = 8; + decl->ColumnList.push_back(col); + break; + case BackRef: + decl->Columns = 1; + col.Name = decl->Name; + col.Type = BackRef; + col.TypeStr = "backref"; + col.TypeId = decl->getClassNode(decl->ParentClass)->Id; + col.ByteSize = 8; + decl->ColumnList.push_back(col); + break; + case SimpleType: + decl->Columns = 1; + col.Name = decl->Name; + col.Type = SimpleType; + col.TypeStr = "type"; + col.TypeId = decl->getTypeNode(decl->Type)->Id; + col.ByteSize = decl->getTypeNode(decl->Type)->Size; + decl->ColumnList.push_back(col); + break; + case Set: + decl->Columns = 1; + col.Name = decl->Name; + col.Type = Set; + col.TypeStr = "set"; + col.TypeId = decl->getClassNode(decl->Type)->Id; + col.ByteSize = 4; + decl->ColumnList.push_back(col); + break; + case SimpleClass: + { + CClassNode *sub = decl->getClassNode(decl->Type); + sub->computeAttributesColumns(); + decl->Columns = sub->Columns; + + uint i, j; + for (i=0; iAttributes.size(); ++i) + { + CDeclarationNode *attrib = sub->Attributes[i]; + + for (j=0; jColumnList.size(); ++j) + { + col.Name = decl->Name+"."+attrib->ColumnList[j].Name; + col.Type = attrib->ColumnList[j].Type; + col.TypeStr = attrib->ColumnList[j].TypeStr; + col.TypeId = attrib->ColumnList[j].TypeId; + col.ByteSize = attrib->ColumnList[j].ByteSize; + decl->ColumnList.push_back(col); + } + } + } + break; + case ArrayRef: + { + CIndexNode *indexNd = decl->getIndexNode(decl->ArrayIndex); + uint numInEnum = indexNd->getSize(); + decl->Columns = numInEnum; + + uint i; + for (i=0; iName+"["+indexNd->getIndexName(i)+"]"; + col.Type = ForwardRef; + col.TypeStr = "forwardref"; + col.TypeId = decl->getClassNode(decl->Type)->Id; + col.ByteSize = 8; + decl->ColumnList.push_back(col); + } + } + break; + case ArrayType: + { + CIndexNode *indexNd = decl->getIndexNode(decl->ArrayIndex); + uint numInEnum = indexNd->getSize(); + decl->Columns = numInEnum; + + uint i; + for (i=0; iName+"["+indexNd->getIndexName(i)+"]"; + col.Type = SimpleType; + col.TypeStr = "type"; + col.TypeId = decl->getTypeNode(decl->Type)->Id; + col.ByteSize = decl->getTypeNode(decl->Type)->Size; + decl->ColumnList.push_back(col); + } + } + break; + case ArrayClass: + { + CIndexNode *indexNd = decl->getIndexNode(decl->ArrayIndex); + + CClassNode *sub = decl->getClassNode(decl->Type); + sub->computeAttributesColumns(); + + uint numInEnum = indexNd->getSize(); + decl->Columns = numInEnum*sub->Columns; + + uint i, j, k; + for (k=0; kAttributes.size(); ++i) + { + CDeclarationNode *attrib = sub->Attributes[i]; + + for (j=0; jColumnList.size(); ++j) + { + col.Name = decl->Name+"["+indexNd->getIndexName(k)+"]."+attrib->ColumnList[j].Name; + col.Type = attrib->ColumnList[j].Type; + col.TypeStr = attrib->ColumnList[j].TypeStr; + col.TypeId = attrib->ColumnList[j].TypeId; + col.ByteSize = attrib->ColumnList[j].ByteSize; + decl->ColumnList.push_back(col); + } + } + } + } + break; + } + + Columns += decl->Columns; + } +} + + + + + +bool CClassNode::generateContent() +{ + nlassert(Env != NULL); + + uint line, col; + string file; + getFileLine(line, col, file); + + setEnv("name", Name); + if (!Description.empty()) + setEnv("description", Description); + setEnv("deffile", file); + setEnv("defline", line); + + computeAttributesColumns(); + + uint j; + + // + // generate description + // + hOutput() << "/** " << Name << "\n"; + if (!Description.empty()) + hOutput() << Description << "\n"; + + hOutput() << "defined at " << file << ":" << line << "\n"; + hOutput() << "*/\n"; + + CCppOutput& DbSummary = getDbNode()->DbSummary; + DbSummary << "Class " << getDbNode()->Name << "::" << Name << ":\n"; + DbSummary << "----------------------------------------------------------\n"; + DbSummary << "located in file \"" << getFullStdPathNoExt(getFileNode()->Name) << ".h\"\n"; + DbSummary << "defined in file \"" << getFullStdPath(file) << "\"\n"; + DbSummary << "The class contains:\n\n"; + + Gen.init(Name); + Gen.createPublic("methods", "Accessors and Mutators methods", "Use these methods to change a value, add or delete elements."); + Gen.createPublic("map", "Public Management methods", "Use these methods to create, load, unload and get\nan object from database."); + Gen.createPublic("user", "User defined attributes and methods", "This code was verbatim copied from source file"); + Gen.createPublic("construct", "Public constructor", "This constructor is public to allow direct instanciation of the class"); + Gen.createPublic("persist", "Persistent methods declaration", ""); + Gen.createProtected("userinit", "User defined init and release methods", "Overload those methods to implement init and release behaviours"); + Gen.createProtected("attributes", "Attributes", "Don't modify those value manually, use accessors and mutators above"); + Gen.createProtected("internal", "Internal Management methods"); + Gen.createProtected("inherit map"); + Gen.createProtected("factories", "Default Factory and Fetch methods"); + Gen.createProtected("friends"); + + // EGS Compat + // -- begin + + Gen.startRaw("persist", false); + ApplyId = Gen.startMethod("void", applyFunction, "CPersistentDataRecord &__pdr", "persist", false, inlineInternal, false, false, "", HasInheritance); + StoreId = Gen.startMethod("void", storeFunction, "CPersistentDataRecord &__pdr", "persist", true, inlineInternal, false, false, "", HasInheritance); + + ClearId = Gen.startMethod("void", clearFunction, "", "map", false, inlineStaticPublic, false, false, "", HasInheritance); + Gen.setDescription("Clear whole object content but key (delete subobjects if there are, key is left unmodified), default clear value is 0."); + + StoreId.add("uint16\t__Tok_MapKey = __pdr.addString(\"__Key__\");"); + StoreId.add("uint16\t__Tok_MapVal = __pdr.addString(\"__Val__\");"); + StoreId.add("uint16\t__Tok_ClassName = __pdr.addString(\"__Class__\");"); + ApplyId.add("uint16\t__Tok_MapKey = __pdr.addString(\"__Key__\");"); + ApplyId.add("uint16\t__Tok_MapVal = __pdr.addString(\"__Val__\");"); + ApplyId.add("uint16\t__Tok_ClassName = __pdr.addString(\"__Class__\");"); + + if (!Inherited.empty()) + { + StoreId.add("uint16\t__Tok_Parent = __pdr.addString(\"__Parent__\");"); + ApplyId.add("uint16\t__Tok_Parent = __pdr.addString(\"__Parent__\");"); + } + + for (j=0; jParent != this) + continue; + + if (decl->DeclarationType == BackRef) + { + ApplyId.add(decl->cppName()+" = NULL;"); + } + else + { + StoreId.add("uint16\t"+decl->tokenName()+" = __pdr.addString(\""+decl->Name+"\");"); + ApplyId.add("uint16\t"+decl->tokenName()+" = __pdr.addString(\""+decl->Name+"\");"); + } + } + + ApplyId.add("while (!__pdr.isEndOfStruct())"); + ApplyId.add("{"); + ApplyId.add( "if (false) {}"); + + if (!Inherited.empty()) + { + StoreId.add("__pdr.pushStructBegin(__Tok_Parent);"); + StoreId.add(Inherited+"::store(__pdr);"); + StoreId.add("__pdr.pushStructEnd(__Tok_Parent);"); + + ApplyId.add("else if (__pdr.peekNextToken() == __Tok_Parent)"); + ApplyId.add("{"); + ApplyId.add( "__pdr.popStructBegin(__Tok_Parent);"); + ApplyId.add( Inherited+"::apply(__pdr);"); + ApplyId.add( "__pdr.popStructEnd(__Tok_Parent);"); + ApplyId.add("}"); + } + + // -- end + + + for (j=0; j(Nodes[j]); + if (cpp == NULL || !cpp->Name.empty()) + continue; + + Gen.addOther(cpp->RawCode, "user"); + } + + HasRowAccess = false; + HasTableAccess = false; + + if (!Inherited.empty()) + { + setEnv("inherit", Inherited); + setEnv("inheritclass", Inherited); + + Gen.Inherit += "public "+Inherited; + HasRowAccess = true; + HasTableAccess = true; + } + else if (HasInheritance || IsBackReferenced || IsInSet || ForceReference) + { + setEnv("inherit", pdBaseDataName); + + Gen.Inherit += "public "+pdBaseDataName; + HasTableAccess = true; + HasRowAccess = true; + } + + if (Legacy.size() > 1 && HasTableAccess) + { + CClassGenerator::SMethodId castId = Gen.startMethod(Name+"*", staticCastFunction, pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false); + Gen.setDescription("Cast base object to "+Name); + castId.add("switch (obj->getTable())"); + castId.add("{"); + std::set::iterator itl; + for (itl=Legacy.begin(); itl!=Legacy.end(); ++itl) + { + CClassNode* child = (*itl); + castId.add("case "+toString(child->Id)+":"); + } + castId.add("return static_cast<"+Name+"*>(obj);"); + castId.add("}"); + castId.add("return NULL;"); + + CClassGenerator::SMethodId constCastId = Gen.startMethod("const "+Name+"*", staticConstCastFunction, "const "+pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false); + Gen.setDescription("Cast base object to const "+Name); + constCastId.add("switch (obj->getTable())"); + constCastId.add("{"); + for (itl=Legacy.begin(); itl!=Legacy.end(); ++itl) + { + CClassNode* child = (*itl); + constCastId.add("case "+toString(child->Id)+":"); + } + constCastId.add("return static_cast(obj);"); + constCastId.add("}"); + constCastId.add("return NULL;"); + } + else if (Legacy.size() == 1 && HasTableAccess) + { + CClassGenerator::SMethodId castId = Gen.startMethod(Name+"*", staticCastFunction, pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false); + std::set::iterator itl = Legacy.begin(); + Gen.setDescription("Cast base object to "+Name); + castId.add("return (obj->getTable() == "+toString((*itl)->Id)+") ? static_cast<"+Name+"*>(obj) : NULL;"); + + CClassGenerator::SMethodId constCastId = Gen.startMethod("const "+Name+"*", staticConstCastFunction, "const "+pdBaseDataName+"* obj", "map", false, inlineStaticPublic, true, false, "", false, false); + Gen.setDescription("Cast base object to const "+Name); + constCastId.add("return (obj->getTable() == "+toString((*itl)->Id)+") ? static_cast(obj) : NULL;"); + } + else + { + } + + if (HasRowAccess) + define("hasrowaccess"); + if (HasTableAccess) + define("hastableaccess"); + + if (!Implements.empty()) + { + setEnv("implements", Implements); + Gen.Inherit += (HasRowAccess ? string(", ") : string(""))+"public "+Implements; + } + + // + // generate init method + // + buildInit(); + + setEnv("initproto", InitProto); + + InitId = Gen.startMethod("void", initFunction, InitProto, "internal", false, inlineInternal, false, false, "", HasInheritance); + if (!Inherited.empty()) + { + InitId.add(Inherited + "::" + initFunction + "(" + InitCallArgs + ");"); + setEnv("initcallargs", InitCallArgs); + } + + DestroyId = Gen.startMethod("void", destroyFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); + FetchId = Gen.startMethod("void", fetchFunction, CPDataName+" &data", "internal", false, inlineInternal, false, false, "", HasInheritance); + RegisterId = Gen.startMethod("void", registerFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); + RegisterAttributesId = Gen.startMethod("void", registerAttributesFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); + UnregisterId = Gen.startMethod("void", unregisterFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); + UnregisterAttributesId = Gen.startMethod("void", unregisterAttributesFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); + SetParentId; + SetUnnotifiedParentId; + if (HasParent) + { + SetParentId = Gen.startMethod("void", setParentFunction, ParentClass+"* __parent", "internal", false, inlineInternal); + SetUnnotifiedParentId = Gen.startMethod("void", setUnnotifiedParentFunction, ParentClass+"* __parent", "internal", false, inlineInternal); + } + + if (HasRowAccess && GenerateDebugMessages) + { + DestroyId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": destroy %u:%u\", "+getId()+", __BaseRow);"); + FetchId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": fetch %u:%u\", "+getId()+", __BaseRow);"); + } + + if (!Inherited.empty()) + { + FetchId.add(Inherited+"::"+fetchFunction+"(data);"); + } + + if (DerivatedFlag) + { + UserInitId = Gen.startMethod("void", userInitFunction, "", "userinit", false, inlineUserInitDefaultCode, false, false, "", true); + UserReleaseId = Gen.startMethod("void", userReleaseFunction, "", "userinit", false, inlineUserInitDefaultCode, false, false, "", true); + } + + NotifyInitId = Gen.startMethod("void", notifyInitFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); + string initUCode = getUserCode("onInit"); + if (!Inherited.empty()) + Gen.add(Inherited+"::"+notifyInitFunction+"();"); + if (DerivatedFlag) + Gen.add(userInitFunction+"();"); + if (!initUCode.empty()) + { + Gen.add("{"); + uint line, col; + string file; + getFileLine(line, col, file); + Gen.add("// "+Name+" init user code, defined at "+file+":"+toString(line)); + Gen.add(initUCode); + Gen.add("}"); + } + + NotifyReleaseId = Gen.startMethod("void", notifyReleaseFunction, "", "internal", false, inlineInternal, false, false, "", HasInheritance); + string releaseUCode = getUserCode("onRelease"); + if (!releaseUCode.empty()) + { + Gen.add("{"); + uint line, col; + string file; + getFileLine(line, col, file); + Gen.add("// "+Name+" release user code, defined at "+file+":"+toString(line)); + Gen.add(releaseUCode); + Gen.add("}"); + } + if (DerivatedFlag) + Gen.add(userReleaseFunction+"();"); + if (!Inherited.empty()) + Gen.add(Inherited+"::"+notifyReleaseFunction+"();"); + else if (HasRowAccess) + Gen.add(pdslibFunc("release")+"("+getId()+", __BaseRow);"); + + if (!Inherited.empty()) + { + DestroyId.add(Inherited+"::"+destroyFunction+"();"); + ClearId.add(Inherited+"::"+clearFunction+"();"); + } + + // + // Generate XML description + // + string xmlnode; + xmlnode += "Id)+"'"; + } + CDeclarationNode *dln = getClassKey(); + if (dln != NULL) + { + xmlnode += " key='"+toString(dln->Id)+"'"; + } + if (MapClass && !MapClass->HasParent) + { + xmlnode += " mapped='"+toString(MapClass->Id)+"'"; + } + if (HasRowAccess) + { +/* + if (!Reserve.empty()) + { + xmlnode += " allocate='"+(Reserve)+"'"; + } + else + { + xmlnode += " allocate='10000'"; + } +*/ + } + xmlnode += " columns='"+toString(Columns)+"'"; + xmlnode += ">"; + getDbNode()->xmlDescription.push_back(xmlnode); + + indexUsedInInit = false; + indexUsedInDestroy = false; + indexUsedInFetch = false; + tableAndRowIndicesUsedInFetch = false; + indexUsedInRegister = false; + indexUsedInUnregister = false; + + // generate code for init of new index + if (HasRowAccess) + { + RegisterId.add("__BaseRow = _IndexAllocator.allocate();"); + if (GenerateDebugMessages) + { + if (MapClass != NULL) + { + CDeclarationNode* key = MapClass->getKey(); + RegisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": register %u:%u, key="+key->displayPrintfPrefix()+"\", "+getId()+", __BaseRow, "+key->displayCppCode()+");"); + } + else + { + RegisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": register %u:%u\", "+getId()+", __BaseRow);"); + } + } + + string oeid; + if (useEntityId()) + { + oeid = ", "+getClassKey()->cppName(); + } + + RegisterId.add(pdslibFunc("allocateRow")+"("+getId()+", __BaseRow, "+(PDSMapped ? MapClass->getKey()->toUint64() : "0")+oeid+");"); + RegisterId.add(registerAttributesFunction + "();"); + + RegisterAttributesId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": registerAttributes %u:%u\", "+getId()+", __BaseRow);"); + + // send key to the pds (if key exists) + if (!ClassKey.empty()) + { + CDeclarationNode *keyNode = getKey(); + CTypeNode *keyTypeNode = getTypeNode(keyNode->Type); + ///// TYPE CAST + RegisterAttributesId.add(pdslibFunc("set")+"("+getId()+", __BaseRow, ("+TColumnIndexName+")("+toString(keyNode->Column)+"), "+keyTypeNode->castToPDS(getKey()->cppName())+");"); + } + + if (!Inherited.empty()) + { + RegisterAttributesId.add(Inherited + "::" + registerAttributesFunction + "();"); + } + + UnregisterAttributesId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unregisterAttributes %u:%u\", "+getId()+", __BaseRow);"); + + if (!Inherited.empty()) + { + UnregisterAttributesId.add(Inherited + "::" + unregisterAttributesFunction + "();"); + } + + if (HasParent) + { + UnregisterAttributesId.add(setParentFunction+"(NULL);"); + } + + if (GenerateDebugMessages) + { + if (MapClass != NULL) + { + CDeclarationNode* key = MapClass->getKey(); + UnregisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unregister %u:%u, key="+key->displayPrintfPrefix()+"\", "+getId()+", __BaseRow, "+key->displayCppCode()+");"); + } + else + UnregisterId.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unregister %u:%u\", "+getId()+", __BaseRow);"); + } + + UnregisterId.add(unregisterAttributesFunction + "();"); + + oeid = ""; + if (useEntityId()) + { + oeid = ", "+getClassKey()->cppName(); + } + + UnregisterId.add(pdslibFunc("deallocateRow")+"("+getId()+", __BaseRow"+oeid+");"); + UnregisterId.add("_IndexAllocator.deallocate(__BaseRow);"); + //UnregisterId.add(destroyFunction+"();"); + } + + // + // add attributes and methods + // - attributes are in private part + // - read accessor are public + // - write accessor are public or delegated in public accessor objects + // + for (j=0; j(Nodes[j]); + if (!dln) + continue; + + dln->Env = Env->nextArrayNode("dcl"); + + dln->generateContent(); + + } + + uint columnId = 0; + + for (j=0; jxmlDescription.push_back("XmlNode+"/>"); + + uint k; + for (k=0; kColumnList.size(); ++k) + { + CColumn &column = dln->ColumnList[k]; + //getDbNode()->xmlDescription.push_back(""); + ++columnId; + } + + //getDbNode()->xmlDescription.push_back(""); + } + + getDbNode()->xmlDescription.push_back(""); + + if (HasTableAccess) + { + Gen.startConstructor("", "construct"); + Gen.add("__BaseTable = "+toString(Id)+";"); + + Gen.startDestructor("construct", true, DerivatedFlag || HasInheritance); + } + + // when inited/fetched a mapped class, map id to object + if (MappedFlag) + { + InitId.add("_Map["+getKey()->getFunc()+"()] = this;"); + FetchId.add("_Map["+getKey()->getFunc()+"()] = this;"); + DestroyId.add("_Map.erase("+getKey()->getFunc()+"());"); + } + + // + // generate IPDBaseData API + // + + if (MappedFlag || DerivatedFlag || HasInheritance || ForceReference) + { + if (DerivatedFlag) + { + Gen.startMethod("void", staticSetUserFactoryFunction, TPDFactoryName+" userFactory", "map", false, inlineStaticPublic, true); + Gen.setDescription("Set user factory for this class (as class is indicated as derived, a home made constructor must be provided)"); + Gen.add(staticInitFactoryFunction+"(userFactory);"); + } + + Gen.startMethod("void", staticInitFactoryFunction, TPDFactoryName+" userFactory", "factories", false, inlineStaticInternal, true); + Gen.add("if (!_FactoryInitialised)"); + Gen.add("{"); + Gen.add(pdslibFunc("registerClass")+"(" + toString(Id) + ", userFactory, "+staticFetchFunction+", "+((MappedFlag && !HasParent) ? staticNotifyLoadFailure : string("NULL"))+");"); + Gen.add("_FactoryInitialised = true;"); + Gen.add("}"); + + Gen.addAttribute("bool", "_FactoryInitialised", "factories", true); + + if (MappedFlag || HasInheritance || ForceReference) + { + // + // create: create an object, then init attributes and register + // + + Gen.startMethod(Name+"*", staticCreateFunction, InitProto, "map", false, inlineStaticPublic, true); + Gen.setDescription("Create an object of the "+Name+" class, and declare it to the PDS."); + if (GenerateDebugMessages) + { + Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": create\");"); + } + if (DerivatedFlag) + { + Gen.add(Name + "\t*"+objectVariable+" = static_cast<" + Name + "*>("+pdslibFunc("create")+"("+toString(Id)+"));"); + } + else + { + Gen.add(Name + "\t*"+objectVariable+" = static_cast<" + Name + "*>("+staticFactoryFunction+"());"); + } + + string str = objectVariable+"->" + initFunction + "("; + uint i; + for (i=0; iName; + str += ");"; + Gen.add(str); + Gen.add(objectVariable+"->" + registerFunction + "();"); +/* + if (MappedFlag) + { + Gen.add("_Map["+MapClass->ClassKey+"] = "+objectVariable+";"); + } +*/ + Gen.add(objectVariable+"->"+notifyInitFunction+"();"); + Gen.add("return "+objectVariable+";"); + } + + if (MappedFlag) + { + CDeclarationNode *dln = (MapClass != NULL ? MapClass->getKey() : NULL); + CTypeNode *keyType = getTypeNode(dln->Type); + + // only authorize remove/load/unload for mapped objects that are roots + if (!HasParent) + { + Gen.startMethod("void", staticRemoveFunction, "const "+keyType->getName()+"& "+dln->Name, "map", false, inlineStaticPublic, true); + Gen.setDescription("Destroy an object from the PDS. Caution! Object will no longer exist in database.\nAlso children (that is objects that belong to this object) are also destroyed."); + if (GenerateDebugMessages) + { + Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": remove "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");"); + } + Gen.add("std::map<" + keyType->getName() + "," + Name + "*>::iterator\tit = _Map.find("+dln->Name+");"); + Gen.add("if (it != _Map.end())"); + Gen.add("{"); + Gen.add(Name + "*\t__o = (*it).second;"); + Gen.add("__o->"+notifyReleaseFunction+"();"); + Gen.add("__o->"+unregisterFunction+"();"); + Gen.add("__o->"+destroyFunction+"();"); + Gen.add("delete __o;"); + //Gen.add("_Map.erase(it);"); + Gen.add("}"); + + Gen.startMethod("void", staticLoadFunction, "const "+keyType->getName()+"& "+dln->Name, "map", false, inlineStaticPublic, true); + Gen.setDescription("Retrieve an object from the database.\nData are sent asynchronously, so the load callback is called when data are ready.\nUse get() to access to the loaded object."); + if (GenerateDebugMessages) + { + Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": load "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");"); + } + Gen.add(pdslibFunc("load")+"("+toString(Id)+", "+dln->toUint64(dln->Name)+");"); + + Gen.startMethod("void", staticSetLoadCbFunction, "void (*callback)(const "+keyType->getName()+"& key, "+Name+"* object)", "map", false, inlineStaticPublic, true); + Gen.setDescription("Setup load callback so client is warned that load succeded or failed."); + Gen.add(staticLoadCbAttribute+" = callback;"); + + Gen.startMethod("void", staticNotifyLoadFailure, "uint64 key", "factories", false, inlineStaticInternal, true); + Gen.add("if ("+staticLoadCbAttribute+" != NULL)"); + Gen.add("{"); + Gen.add(staticLoadCbAttribute+"("+keyType->castFromUser("key")+", NULL);"); + Gen.add("}"); + + Gen.addAttribute("void", staticLoadCbAttribute, "factories", true, "NULL", true, "const "+keyType->getName()+"& key, "+Name+"* object"); + + + // + Gen.startMethod("void", staticUnloadFunction, "const " + keyType->getName() + " &" + dln->Name, "map", false, inlineStaticPublic, true); + Gen.setDescription("Unload an object from the client memory. Object still exists in database and can be retrieved again using load."); + if (GenerateDebugMessages) + { + Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": unload "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");"); + } + Gen.add("std::map<" + keyType->getName() + "," + Name + "*>::iterator\tit = _Map.find("+dln->Name+");"); + Gen.add("if (it != _Map.end())"); + Gen.add("{"); + Gen.add(Name + "*\t__o = (*it).second;"); + Gen.add("__o->"+notifyReleaseFunction+"();"); + Gen.add("__o->"+destroyFunction+"();"); + Gen.add("delete __o;"); + //Gen.add("_Map.erase(it);"); + Gen.add("}"); + } + + std::string mapType = "std::map<"+keyType->getName()+", "+Name+"*>"; + + Gen.startMethod(Name+"*", staticGetFunction, "const " + keyType->getName() + " &" + dln->Name, "map", false, inlineStaticPublic, true); + Gen.setDescription("Get an object in client. Object must have been previously loaded from database with a load."); + if (GenerateDebugMessages) + { + Gen.add("if (RY_PDS::PDVerbose)\tnldebug(\""+Name+": get "+dln->displayPrintfPrefix()+"\", "+dln->displayCppCode(dln->Name)+");"); + } + Gen.add(mapType+"::iterator\t__it = _Map.find("+dln->Name+");"); + if (GenerateDebugMessages) + { + Gen.add("if (__it == _Map.end())"); + Gen.add("nlwarning(\""+Name+": unable to get %\"NL_I64\"u, not found in map.\", "+dln->toUint64(dln->Name)+");"); + } + Gen.add("return (__it != _Map.end()) ? (*__it).second : NULL;"); + + Gen.startMethod(mapType+"::iterator", staticBeginFunction, "", "map", false, inlineStaticPublic, true); + Gen.setDescription("Return the begin iterator of the global map of "+Name); + Gen.add("return _Map.begin();"); + + Gen.startMethod(mapType+"::iterator", staticEndFunction, "", "map", false, inlineStaticPublic, true); + Gen.setDescription("Return the end iterator of the global map of "+Name); + Gen.add("return _Map.end();"); + } + } + + + // + // generate internal management functions + // + + if (HasRowAccess || MappedFlag) + { + if (MappedFlag) + { + CDeclarationNode *dln = (MappedFlag ? getKey() : NULL); + CTypeNode *keyType = getTypeNode(dln->Type); + Gen.addAttribute("std::map<" + keyType->getName() + "," + Name + "*>", "_Map", "inherit map", true); + } + + Gen.addAttribute(indexAllocatorName, "_IndexAllocator", "factories", true); + + Gen.startMethod("void", staticInitFunction, "", "internal", false, inlineInternal, true, false, "", false); + Gen.add(pdslibFunc("setIndexAllocator")+"("+toString(Id)+", _IndexAllocator);"); + if (MappedFlag || DerivatedFlag || HasInheritance || ForceReference) + { + if (DerivatedFlag) + { + // check factory has been set + Gen.add("nlassertex(_FactoryInitialised, (\"User Factory for class "+Name+" not set!\"));"); + Gen.add("// factory must have been set by user before database init called!"); + Gen.add("// You must provide a factory for the class "+Name+" as it is marked as derived"); + Gen.add("// Call "+getDbNode()->Name+"::"+Name+"::"+staticSetUserFactoryFunction+"() with a factory before any call to "+getDbNode()->Name+"::init()!"); + } + else + { + Gen.add(staticInitFactoryFunction+"("+staticFactoryFunction+");"); + } + } + + getDbNode()->initDb.add(Name+"::"+staticInitFunction+"();"); + + if (ForceReference) + { + if (!DerivatedFlag) // forbid factory function for derivated classes + { + Gen.startMethod(pdBaseDataName+"*", staticFactoryFunction, "", "factories", false, inlineStaticInternal, true); + Gen.add("return new " + Name + "();"); + } + + if (Inherited.empty()) + { + Gen.startMethod("void", staticFetchFunction, pdBaseDataName+" *object, "+CPDataName+" &data", "factories", false, inlineStaticInternal, true); + Gen.add(Name + "\t*"+objectVariable+" = static_cast<" + Name + "*>(object);"); + Gen.add(objectVariable+"->"+fetchFunction+"(data);"); + if (MappedFlag) + { + //Gen.add("_Map["+objectVariable+"->"+getKey()->getFunc()+"()] = "+objectVariable+";"); + if (!HasParent) + { + Gen.add("if ("+staticLoadCbAttribute+" != NULL)"); + Gen.add("{"); + Gen.add(staticLoadCbAttribute+"("+objectVariable+"->"+getKey()->getFunc()+"(), "+objectVariable+");"); + Gen.add("}"); + } + } + Gen.add(objectVariable+"->"+notifyInitFunction+"();"); + } + } + } + + // EGS Compat + // -- begin + + ApplyId.add( "else"); + ApplyId.add( "{"); + ApplyId.add( "nlwarning(\"Skipping unrecognised token: %s\", __pdr.peekNextTokenName().c_str());"); + ApplyId.add( "__pdr.skipData();"); + ApplyId.add( "}"); + ApplyId.add("}"); + + if (MappedFlag && !HasParent) + { + ApplyId.add(notifyInitFunction+"();"); + } + + + //EGSImplId.add("\n#include \"game_share/persistent_data_template.h\""); + //EGSImplId.add("#undef PERSISTENT_CLASS"); + //EGSImplId.add("#undef PERSISTENT_DATA"); + + // -- end + + set::iterator itf; + for (itf=Friends.begin(); itf!=Friends.end(); ++itf) + if (*itf != Name) + Gen.addOther("friend class "+(*itf)+";\n", "friends"); + for (itf=ForwardFriends.begin(); itf!=ForwardFriends.end(); ++itf) + if (*itf != Name) + Gen.addOther("friend class "+(*itf)+";\n", "friends"); + Gen.addOther("friend class "+CPDSLibName+";\n", "friends"); + CDbNode* dbNode = getDbNode(); + Gen.addOther("friend void "+dbNode->Name+"::init(uint32);\n", "friends"); + + Gen.flush(hOutput(), cppOutput(), inlineOutput()); + + DbSummary << "\n\n"; + + return true; +} + +void CClassNode::generateContentInCall(CCallContext *context) +{ + uint j; + for (j=0; j(Nodes[j]); + if (!dln) + continue; + + dln->generateContent(context); + } +} + + + + + + + + + +// Declaration Node +bool CDeclarationNode::prolog() +{ + return true; +} + +bool CDeclarationNode::epilog() +{ + return true; +} + + + +void CDeclarationNode::generateContent(CCallContext *context) +{ + ClassNode = static_cast(Parent); + + nlassert(Env != NULL); + + setEnv("name", Name); + + XmlNode = "name='"+Name+"' id='"+toString(Id)+"' columnid='"+toString(Column)+"' columns='"+toString(Columns)+"'"; + + if (context == NULL) + { + CCppOutput& DbSummary = getDbNode()->DbSummary; + DbSummary << "Attribute " << Name << ":\n"; + } + + switch (DeclarationType) + { + case SimpleType: + generateTypeContent(context); + break; + + case SimpleClass: + generateClassContent(context); + break; + + case BackRef: + generateBackRefContent(); + break; + + case ForwardRef: + generateForwardRefContent(); + break; + + case ArrayType: + generateArrayTypeContent(context); + break; + + case ArrayClass: + generateArrayClassContent(context); + break; + + case ArrayRef: + generateArrayRefContent(context); + break; + + case Set: + generateSetContent(context); + break; + + default: + error("Can't decide declaration type"); + break; + } + + if (context == NULL) + { + ClassNode->Gen.separator("methods"); + } + +} + + + +std::string CDeclarationNode::getAccessorName(CCallContext *context, const std::string& accessortype, const std::string& sep) +{ + return context->getRootCaller()->Name + sep +accessortype + context->getCallString(); +} + + +void CDeclarationNode::generateTypeContent(CCallContext *context) +{ + CClassGenerator& Gen = ClassNode->Gen; + CCppOutput& DbSummary = getDbNode()->DbSummary; + + CClassGenerator::SMethodId &InitId = ClassNode->InitId; + CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; + CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; + CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; + CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; + CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; + CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; + CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; + CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; + CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; + + string UCodeContext; + if (context != NULL) + UCodeContext = context->getUserCodeContext(); + + string onGetUser = getUserCode("onGet", UCodeContext); + string onSetUser = getUserCode("onSet", UCodeContext); + string onChangeUser = getUserCode("onChange", UCodeContext); + + CTypeNode *tnd = getTypeNode(Type); + XmlNode += " type='type' typeid='"+toString(tnd->Id)+"'"; + + setEnv("decltype", "type"); + setEnv("type", tnd->getName()); + define(IsKey, "iskey"); + setEnv("defaultvalue", tnd->getDefaultValue()); + setEnv("checkcode", tnd->checkCode(Name)); + + CCallContext ctx(this); + if (context != NULL) + ctx = context->getSubContext(this); + CClassGenerator &gen = ctx.getRootCaller()->Gen; + + // EGS Compat + // -- begin + + CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; + CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; + + + ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")"); + ApplyId.add("{"); + tnd->generateApplyCode(ApplyId, tokenName(), cppName()); + ApplyId.add("}"); + + tnd->generateStoreCode(StoreId, tokenName(), cppName()); + + // -- end + + CTemplatizerEnv* env = ctx.getRootDeclaration()->Env->nextArrayNode("accessors"); + + env->set("name", Name); + env->set("type", tnd->getName()); + env->set("defaultvalue", tnd->getDefaultValue()); + env->set("checkcode", tnd->checkCode(Name)); + env->define(ctx.getRootCaller()->HasRowAccess, "rowaccess"); + env->define(IsKey, "iskey"); + env->set("rootcallerid", ctx.getRootCaller()->getId()); + env->set("callstr", ctx.getCallString()); + env->set("callargs", ctx.getCallArgList()); + env->set("callpath", ctx.getCallPath()); + env->set("column", ctx.getColumn()); + env->set("valuevar", valueVariable); + env->set("castcpp", tnd->castToCpp(valueVariable)); + env->set("castpds", tnd->castToPDS(valueVariable)); + + vector checks = ctx.getCheckCode(); + for (uint i=0; inextArrayNode("checks")->set("check", checks[i]); + env->nextArrayNode("checks")->set("check", tnd->checkCode(valueVariable)); + + if (!onGetUser.empty()) env->set("onget", onGetUser); + if (!onSetUser.empty()) env->set("onset", onSetUser); + if (!onChangeUser.empty()) env->set("onchange", onChangeUser); + + // + // generate read accessor + // + if (ctx.getRootCaller()->HasRowAccess) + { + string arglist = ctx.getCallArgList(); + + gen.startMethod(tnd->getName(), getFunctionPrefix+ctx.getCallString(), arglist, "methods", true, inlineAccessors); + + DbSummary << "\t" << getFunctionPrefix+ctx.getCallString() << "\n"; + + uint i; + vector checks = ctx.getCheckCode(); + for (i=0; iHasRowAccess && !IsKey) + { + string arglist = ctx.getCallArgList(); + + if (!arglist.empty()) + arglist += ", "; + arglist += tnd->getName()+" "+valueVariable; + gen.startMethod("void", setFunctionPrefix+ctx.getCallString(), appendArg(arglist, "bool forceWrite=false"), "methods", false, inlineAccessors); + + DbSummary << "\t" << setFunctionPrefix << ctx.getCallString() << "\n"; + + if (GenerateHAuto) + { + gen.add("H_AUTO("+getAccessorName(&ctx, setFunctionPrefix, "_")+")"); + } + + if (VerboseMode) + { + string verbStr; + string callStr; + + verbStr = "nlinfo(\"" + ctx.getRootCaller()->Name + "(%d:%d)::" +setFunctionPrefix + ctx.getCallString() + "("; + + callStr = ctx.getDebugCallStringFmt(); + if (!callStr.empty()) + callStr += ", "; + + callStr += valueVariable+"="+tnd->getPrintfFmt(); + + verbStr += callStr; + verbStr += ")\", __BaseTable, __BaseRow, "; + + callStr = ctx.getDebugCallStringVal(); + if (!callStr.empty()) + callStr += ", "; + + callStr += tnd->getPrintfVal(valueVariable); + + verbStr += callStr; + verbStr += ");"; + + gen.add(verbStr); + } + + uint i; + vector checks = ctx.getCheckCode(); + for (i=0; icheckCode(valueVariable)); + + ///// TYPE CAST + if (!onChangeUser.empty()) + { + gen.add("if ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+")"); + gen.add("{"); + gen.add(onChangeUser); + gen.add("}"); + } + if (!onSetUser.empty()) + { + gen.add("{"); + gen.add(onSetUser); + gen.add("}"); + } + if (WriteTriggerFlag) + { + gen.add("if (forceWrite && ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+"))"); + } + else + { + gen.add("if (("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+") || forceWrite)"); + } + gen.add("{"); + bool useEntityId = ctx.hasRootEntityIdKey(); + if (useEntityId) + { + gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+", "+ctx.getRootCaller()->getKey()->cppName()+");"); + } + else + { + gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");"); + } + gen.add("}"); + gen.add(ctx.getCallPath()+" = "+tnd->castToCpp(valueVariable)+";"); + } + + // + // generate attribute + // + Gen.addAttribute(tnd->getName(), cppName(), "attributes"); + + + string defaultValue; + if (!DefaultValue.empty()) + defaultValue = DefaultValue; + else + defaultValue = tnd->getDefaultValue(); + + // + // generate init + // + if (!IsKey) + { + InitId.add(cppName()+" = "+defaultValue+";"); + } + else + { + InitId.add(tnd->checkCode(Name)); + InitId.add(cppName()+" = "+Name+";"); + } + + // + // generate create code + // + + + // + // generate fetch code + // + if (tnd->isEnum()) + FetchId.add("data.serialEnum("+cppName()+");"); + else if (tnd->CppType != tnd->StorageType) + { + FetchId.add("{"); + FetchId.add(tnd->StorageType+"\t_v;"); + FetchId.add("data.serial(_v);"); + FetchId.add(cppName()+" = "+tnd->castToCpp("_v")+";"); + FetchId.add("}"); + } + else + { + FetchId.add("data.serial("+cppName()+");"); + } + + // + // generate clear code + // + if (ctx.getRootCaller()->HasRowAccess && !IsKey) + { + ctx.getRootCaller()->ClearId.add(ctx.getCallPath()+" = "+defaultValue+";"); + ctx.getRootCaller()->ClearId.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(defaultValue)+");"); + } +} + + + + + + + + +void CDeclarationNode::generateClassContent(CCallContext *context) +{ + setEnv("decltype", "class"); + + CClassGenerator &Gen = ClassNode->Gen; + CCppOutput& DbSummary = getDbNode()->DbSummary; + + CClassGenerator::SMethodId &InitId = ClassNode->InitId; + CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; + CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; + CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; + CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; + CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; + CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; + CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; + CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; + CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; + + CClassNode *cnd = getClassNode(Type); + XmlNode += " type='class' classid='"+toString(cnd->Id)+"'"; + + setEnv("type", Type); + + // EGS Compat + // -- begin + + CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; + CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; + + StoreId.add("__pdr.pushStructBegin("+tokenName()+");"); + StoreId.add(cppName()+".store(__pdr);"); + StoreId.add("__pdr.pushStructEnd("+tokenName()+");"); + + ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")"); + ApplyId.add("{"); + ApplyId.add("__pdr.popStructBegin("+tokenName()+");"); + ApplyId.add(cppName()+".apply(__pdr);"); + ApplyId.add("__pdr.popStructEnd("+tokenName()+");"); + ApplyId.add("}"); + + // -- end + + + // + // export class accessors into root caller + // + CCallContext ctx; + if (context != NULL) + ctx = *context; + ctx.Context.push_back(this); + cnd->generateContentInCall(&ctx); + + // + // generate attribute + // + Gen.addAttribute(Type, cppName(), "attributes"); + + // + // generate init + // + InitId.add(cppName()+"."+initFunction+"();"); + + // + // generate create code + // + + // + // generate fetch code + // + FetchId.add(cppName()+"."+fetchFunction+"(data);"); + + // + // generate clear code + // + //ClearId.add(cppName()+"."+clearFunction+"();"); +} + + + + + + +void CDeclarationNode::generateBackRefContent() +{ + setEnv("decltype", "backref"); + define(HiddenFlag, "hidden"); + + CClassGenerator &Gen = ClassNode->Gen; + CCppOutput& DbSummary = getDbNode()->DbSummary; + + CClassGenerator::SMethodId &InitId = ClassNode->InitId; + CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; + CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; + CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; + CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; + CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; + CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; + CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; + CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; + CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; + + CClassNode *cnd = getClassNode(ParentClass); + CDeclarationNode *dnd = cnd->getDeclarationNode(ParentField); + CDeclarationNode *knd = (ClassNode->ClassKey.empty() ? NULL : ClassNode->getKey()); + XmlNode += " type='backref' classid='"+toString(cnd->Id)+"' backreferentid='"+toString(dnd->Id)+"'"; + if (knd != NULL) + XmlNode += " key='"+toString(knd->Id)+"'"; + + setEnv("type", ParentClass); + + // + // generate read accessor + // + Gen.startMethod(ParentClass+"*", getFunc(), "", "methods", false, inlineAccessors); + Gen.add("return "+cppName()+";"); + + Gen.startMethod("const "+ParentClass+"*", getFunc(), "", "methods", true, inlineAccessors); + Gen.add("return "+cppName()+";"); + + DbSummary << "\t" << getFunc() << "\n"; + + // + // generate write accessor + // + + // + // generate attribute + // + Gen.addAttribute(ParentClass+"*", cppName(), "attributes"); + + // + // generate init + // + InitId.add(cppName()+" = NULL;"); + + // + // generate create code + // + + // + // generate fetch code + // + FetchId.add(cppName()+" = NULL;"); + + // + // generate set parent code + // + + bool useId = ClassNode->useEntityId(); + bool parentUseId = cnd->useEntityId(); + + if (parentUseId) + SetParentId.add("NLMISC::CEntityId\tprevId;"); + + if (!HiddenFlag) + { + //SetParentId.add(pdslibFunc("set")+"("+ClassNode->getId()+", getRow(), ("+TColumnIndexName+")("+toString(Column)+"), (__parent != NULL ? "+objectIndexName+"("+(cnd->HasInheritance ? toString("__parent->getTable()") : toString(cnd->Id))+", __parent->getRow()) : "+nullIndexName+"));"); + + SetParentId.add("if ("+cppName()+" != NULL)"); + SetParentId.add("{"); + + if (parentUseId) + SetParentId.add("prevId = "+cppName()+"->"+getFunctionPrefix+cnd->getKey()->Name+"();"); + + if (ClassNode->getClassKey() == NULL) + { + SetParentId.add(cppName()+"->"+dnd->unlinkFunc()+"();"); + } + else + { + SetParentId.add(cppName()+"->"+dnd->unlinkFunc()+"("+ClassNode->getKey()->cppName()+");"); + } + SetParentId.add("}"); + } + else + { + if (parentUseId) + { + SetParentId.add("if ("+cppName()+" != NULL)"); + SetParentId.add("{"); + SetParentId.add("prevId = "+cppName()+"->"+cnd->getKey()->cppName()+";"); + SetParentId.add("}"); + } + } + + string oeid; + string peid; + + if (useId) + oeid = ", "+ClassNode->getKey()->cppName(); + + if (parentUseId) + peid = ", ("+cppName()+" != NULL ? "+cppName()+"->"+getFunctionPrefix+cnd->getKey()->Name+"() : NLMISC::CEntityId::Unknown), prevId"; + + SetParentId.add(cppName()+" = __parent;"); + SetParentId.add(pdslibFunc("setParent")+"("+ClassNode->getId()+", getRow(), ("+TColumnIndexName+")("+toString(Column)+"), (__parent != NULL ? "+objectIndexName+"("+(cnd->HasInheritance ? toString("__parent->getTable()") : toString(cnd->Id))+", __parent->getRow()) : "+nullIndexName+")"+oeid+peid+");"); + + SetUnnotifiedParentId.add(cppName()+" = __parent;"); + +} + + + + + + +void CDeclarationNode::generateClassPtrApplyCode(const std::string& value) +{ + CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; + + ApplyId.add(value+" = NULL;"); + ApplyId.add("if (__pdr.peekNextToken() == __Tok_ClassName)"); + ApplyId.add("{"); + ApplyId.add( "std::string\t__className;"); + ApplyId.add( "__pdr.pop(__Tok_ClassName, __className);"); + ApplyId.add( value+" = "+Type+"::cast("+pdslibFunc("create")+"(__className));"); + ApplyId.add( "if ("+value+" != NULL)"); + ApplyId.add( "{"); + ApplyId.add( "__pdr.popStructBegin("+tokenName()+");"); + ApplyId.add( value+"->apply(__pdr);"); + ApplyId.add( value+"->"+setUnnotifiedParentFunction+"(this);"); + ApplyId.add( "__pdr.popStructEnd("+tokenName()+");"); + ApplyId.add( "}"); + ApplyId.add( "else"); + ApplyId.add( "{"); + ApplyId.add( "__pdr.skipStruct();"); + ApplyId.add( "}"); + ApplyId.add("}"); +} + +void CDeclarationNode::generateClassPtrStoreCode(const std::string& value) +{ + CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; + + StoreId.add("if ("+value+" != NULL)"); + StoreId.add("{"); + StoreId.add( "std::string\t__className = "+pdslibFunc("getClassName")+"("+value+");"); + StoreId.add( "__pdr.push(__Tok_ClassName, __className);"); + StoreId.add( "__pdr.pushStructBegin("+tokenName()+");"); + StoreId.add( value+"->store(__pdr);"); + StoreId.add( "__pdr.pushStructEnd("+tokenName()+");"); + StoreId.add("}"); +} + + + +void CDeclarationNode::generateForwardRefContent() +{ + setEnv("decltype", "forwardref"); + + CClassGenerator &Gen = ClassNode->Gen; + CCppOutput& DbSummary = getDbNode()->DbSummary; + + CClassGenerator::SMethodId &InitId = ClassNode->InitId; + CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; + CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; + CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; + CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; + CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; + CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; + CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; + CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; + CClassGenerator::SMethodId &NotifyInitId = ClassNode->NotifyInitId; + CClassGenerator::SMethodId &NotifyReleaseId = ClassNode->NotifyReleaseId; + + CClassNode *cnd = getClassNode(Type); + CDeclarationNode *dnd = cnd->getDeclarationNode(ForwardRefAttribute); + CDeclarationNode *knd = (cnd->ClassKey.empty() ? NULL : cnd->getKey()); + XmlNode += " type='forwardref' classid='"+toString(cnd->Id)+"' forwardreferedid='"+toString(dnd->Id)+"'"; + if (knd != NULL) + XmlNode += " key='"+toString(knd->Id)+"'"; + + setEnv("type", Type); + + // EGS Compat + // -- begin + + CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; + CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; + + StoreId.add("// store "+Name); + StoreId.add("__pdr.pushStructBegin("+tokenName()+");"); + generateClassPtrStoreCode(cppName()); + StoreId.add("__pdr.pushStructEnd("+tokenName()+");"); + + ApplyId.add("// apply "+Name); + ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")"); + ApplyId.add("{"); + ApplyId.add( "__pdr.popStructBegin("+tokenName()+");"); + generateClassPtrApplyCode(cppName()); + ApplyId.add( "__pdr.popStructEnd("+tokenName()+");"); + ApplyId.add("}"); + + // -- end + + + // + // generate read accessor + // + Gen.startMethod(Type+"*", getFunc(), "", "methods", false, inlineAccessors); + Gen.add("return "+cppName()+";"); + + Gen.startMethod("const "+Type+"*", getFunc(), "", "methods", true, inlineAccessors); + Gen.add("return "+cppName()+";"); + + DbSummary << "\t" << getFunc() << "\n"; + + // + // generate write accessor + // + Gen.startMethod("void", setFunc(), Type+"* "+valueVariable, "methods", false, inlineAccessors); + Gen.add("if ("+cppName()+" != NULL)"); + Gen.add("{"); + Gen.add(cppName()+"->"+setParentFunction+"(NULL);"); + Gen.add("}"); + Gen.add(valueVariable+"->"+setParentFunction+"(this);"); + Gen.add(cppName()+" = "+valueVariable+";"); + + DbSummary << "\t" << setFunc() << "\n"; + + // + // generate attribute + // + Gen.addAttribute(Type+"*", cppName(), "attributes"); + + // + // generate init + // + InitId.add(cppName()+" = NULL;"); + + // + // generate destroy code + // + DestroyId.add("if ("+cppName()+" != NULL)"); + DestroyId.add("{"); + DestroyId.add(Type+"*\t__o = "+cppName()+";"); + DestroyId.add("__o->"+destroyFunction+"();"); + DestroyId.add("delete __o;"); + DestroyId.add("}"); + + // + // generate create code + // + + // + // generate fetch code + // + FetchId.add("// read table and row, create an object, affect to the ref, and fetch it"); + if (!ClassNode->tableAndRowIndicesUsedInFetch) + { + FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;"); + ClassNode->tableAndRowIndicesUsedInFetch = true; + } + FetchId.add(cppName()+" = NULL;"); + FetchId.add("data.serial(tableIndex, rowIndex);"); + FetchId.add("if (rowIndex != "+INVALID_ROW_INDEXName+" && tableIndex != "+INVALID_TABLE_INDEXName+")"); + FetchId.add("{"); + FetchId.add(cppName()+" = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));"); + FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+cppName()+");"); + FetchId.add(cppName()+"->"+fetchFunction+"(data);"); + FetchId.add(cppName()+"->"+setUnnotifiedParentFunction+"(this);"); + FetchId.add("}"); + + // + // generate register/unregister code + // + + UnregisterAttributesId.add("if ("+cppName()+" != NULL)"); + UnregisterAttributesId.add("{"); + UnregisterAttributesId.add(Type+"*\t"+objectVariable+" = "+cppName()+";"); + UnregisterAttributesId.add(objectVariable+"->"+unregisterFunction+"();"); + UnregisterAttributesId.add(objectVariable+"->"+destroyFunction+"();"); + UnregisterAttributesId.add("delete "+objectVariable+";"); + UnregisterAttributesId.add("}"); + + // + // generate init/release notification + // + + NotifyInitId.add("if ("+cppName()+" != NULL)"); + NotifyInitId.add("{"); + NotifyInitId.add(cppName()+"->"+notifyInitFunction+"();"); + NotifyInitId.add("}"); + + NotifyReleaseId.add("if ("+cppName()+" != NULL)"); + NotifyReleaseId.add("{"); + NotifyReleaseId.add(cppName()+"->"+notifyReleaseFunction+"();"); + NotifyReleaseId.add("}"); + + // + // generate unlink code + // + string unlinkProto; + if (cnd->getClassKey() != NULL) + { + CDeclarationNode* kd = cnd->getClassKey(); + CTypeNode* keyType = getTypeNode(kd->Type); + unlinkProto = keyType->getName()+" dummy"; + } + Gen.startMethod("void", unlinkFunc(), unlinkProto, "internal", false, inlineInternal); + Gen.add("{"); + Gen.add(cppName()+" = NULL;"); + Gen.add("}"); + + // + // generate clear code + // + //ClearId.add(cppName()+"->"+setParentFunction+"(NULL);"); + ClearId.add(Type+"*\t"+objectVariable+" = "+cppName()+";"); + ClearId.add(objectVariable+"->"+unregisterFunction+"();"); + ClearId.add(objectVariable+"->"+destroyFunction+"();"); + ClearId.add("delete "+objectVariable+";"); +} + + + +void CDeclarationNode::generateArrayApplyCode() +{ + CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; + + ApplyId.add("// apply "+Name); + ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")"); + ApplyId.add("{"); + ApplyId.add( "__pdr.popStructBegin("+tokenName()+");"); + ApplyId.add( "uint\tindex = 0;"); + ApplyId.add( "while (!__pdr.isEndOfStruct())"); + ApplyId.add( "{"); + + CIndexNode *ind = getIndexNode(ArrayIndex); + if (ind->isEnum()) + { + ApplyId.add("std::string\tindexname;"); + ApplyId.add("__pdr.pop(__Tok_MapKey, indexname);"); + ApplyId.add("index = "+ind->getFromStringCode("indexname")+";"); + } +} + +void CDeclarationNode::generateArrayStoreCode() +{ + CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; + + StoreId.add("// store "+Name); + StoreId.add("__pdr.pushStructBegin("+tokenName()+");"); + CIndexNode *ind = getIndexNode(ArrayIndex); + + StoreId.add("for (uint index=0; index<"+ind->getSizeName()+"; ++index)"); + StoreId.add("{"); + + if (ind->isEnum()) + { + StoreId.add("std::string\tindexname = "+ind->getToStringCode(ind->castFromUser("index"))+";"); + StoreId.add("__pdr.push(__Tok_MapKey, indexname);"); + } +} + + +void CDeclarationNode::generateArrayEndCode() +{ + CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; + CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; + + ApplyId.add( "++index;"); + ApplyId.add( "}"); + ApplyId.add( "__pdr.popStructEnd("+tokenName()+");"); + ApplyId.add("}"); + + StoreId.add("}"); + StoreId.add("__pdr.pushStructEnd("+tokenName()+");"); +} + + + +void CDeclarationNode::generateArrayTypeContent(CCallContext *context) +{ + setEnv("decltype", "arraytype"); + + CClassGenerator &Gen = ClassNode->Gen; + CCppOutput& DbSummary = getDbNode()->DbSummary; + + CClassGenerator::SMethodId &InitId = ClassNode->InitId; + CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; + CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; + CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; + CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; + CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; + CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; + CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; + CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; + CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; + + string UCodeContext; + if (context != NULL) + UCodeContext = context->getUserCodeContext(); + + string onGetUser = getUserCode("onGet", UCodeContext); + string onSetUser = getUserCode("onSet", UCodeContext); + string onChangeUser = getUserCode("onChange", UCodeContext); + + CTypeNode *tnd = getTypeNode(Type); + CIndexNode *ind = getIndexNode(ArrayIndex); + XmlNode += " type='arraytype' typeid='"+toString(tnd->Id)+"' indexid='"+toString(ind->Id)+"'"; + + CCallContext ctx(this); + if (context != NULL) + ctx = context->getSubContext(this); + CClassGenerator &gen = ctx.getRootCaller()->Gen; + + setEnv("type", tnd->getName()); + setEnv("indexsize", ind->getSizeName()); + + // EGS Compat + // -- begin + + CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; + CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; + + generateArrayApplyCode(); + generateArrayStoreCode(); + + ApplyId.add(tnd->getName()+"\tvalue;"); + tnd->generateApplyCode(ApplyId, "__Tok_MapVal", "value"); + ApplyId.add("if (index != "+toString(ind->getSize())+")"); + ApplyId.add("{"); + ApplyId.add( cppName()+"[index] = value;"); + ApplyId.add("}"); + + tnd->generateStoreCode(ApplyId, "__Tok_MapVal", cppName()+"[index]"); + + generateArrayEndCode(); + + // -- end + + + // + // generate read accessor + // + if (ctx.getRootCaller()->HasRowAccess) + { + string arglist = ctx.getCallArgList(); + ctx.getRootCaller()->Gen.startMethod(tnd->getName(), getFunctionPrefix+ctx.getCallString(), arglist, "methods", true, inlineAccessors); + + DbSummary << "\t" << getFunctionPrefix+ctx.getCallString() << "\n"; + + uint i; + vector checks = ctx.getCheckCode(); + for (i=0; iHasRowAccess) + { + string arglist = ctx.getCallArgList(); + if (!arglist.empty()) + arglist += ", "; + arglist += tnd->getName()+" "+valueVariable; + gen.startMethod("void", setFunctionPrefix+ctx.getCallString(), appendArg(arglist, "bool forceWrite=false"), "methods", false, inlineAccessors); + + DbSummary << "\t" << setFunctionPrefix+ctx.getCallString() << "\n"; + + if (GenerateHAuto) + { + gen.add("H_AUTO("+getAccessorName(&ctx, getFunctionPrefix, "_")+")"); + } + + if (VerboseMode) + { + string verbStr; + string callStr; + + verbStr = "nlinfo(\"" + ctx.getRootCaller()->Name + "(%d:%d)::" +setFunctionPrefix + ctx.getCallString() + "("; + + callStr = ctx.getDebugCallStringFmt(); + if (!callStr.empty()) + callStr += ", "; + + callStr += valueVariable+"="+tnd->getPrintfFmt(); + + verbStr += callStr; + verbStr += ")\", __BaseTable, __BaseRow, "; + + callStr = ctx.getDebugCallStringVal(); + if (!callStr.empty()) + callStr += ", "; + + callStr += tnd->getPrintfVal(valueVariable); + + verbStr += callStr; + verbStr += ");"; + + gen.add(verbStr); + } + + uint i; + vector checks = ctx.getCheckCode(); + for (i=0; icheckCode(valueVariable)); + + if (!onChangeUser.empty()) + { + gen.add("if ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+")"); + gen.add("{"); + gen.add(onChangeUser); + gen.add("}"); + } + if (!onSetUser.empty()) + { + gen.add("{"); + gen.add(onGetUser); + gen.add("}"); + } + if (WriteTriggerFlag) + { + gen.add("if (forceWrite && ("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+"))"); + } + else + { + gen.add("if (("+ctx.getCallPath()+" != "+tnd->castToCpp(valueVariable)+") || forceWrite)"); + } + gen.add("{"); + bool useEntityId = ctx.hasRootEntityIdKey(); + if (useEntityId) + { + gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+", "+ctx.getRootCaller()->getKey()->cppName()+");"); + } + else + { + gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");"); + } + //gen.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(valueVariable)+");"); + gen.add("}"); + gen.add(ctx.getCallPath()+" = "+tnd->castToCpp(valueVariable)+";"); + } + + // + // generate attribute + // + Gen.addAttribute(tnd->getName(), cppName()+"["+ind->getSizeName()+"]", "attributes"); + + // + // generate init + // + if (!ClassNode->indexUsedInInit) + { + InitId.add("uint\ti;"); + ClassNode->indexUsedInInit = true; + } + + InitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i] = "+tnd->getDefaultValue()+";"); + + // + // generate create code + // + + // + // generate fetch code + // + if (!ClassNode->indexUsedInFetch) + { + FetchId.add("uint\ti;"); + ClassNode->indexUsedInFetch = true; + } + + if (tnd->isEnum()) + FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\tdata.serialEnum("+cppName()+"[i]);"); + else if (tnd->CppType != tnd->StorageType) + { + FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); + FetchId.add("{"); + FetchId.add(tnd->StorageType+"\t_v;"); + FetchId.add("data.serial(_v);"); + FetchId.add(cppName()+"[i] = "+tnd->castToCpp("_v")+";"); + FetchId.add("}"); + } + else + { + FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\tdata.serial("+cppName()+"[i]);"); + } + + // + // generate clear code + // + if (ctx.getRootCaller()->HasRowAccess) + { + string forIndex = "__i"+toString(ctx.getContextIndex()); + ctx.getRootCaller()->ClearId.add("for (uint "+forIndex+"=0; "+forIndex+"<"+ind->getSizeName()+"; ++"+forIndex+")"); + ctx.getRootCaller()->ClearId.add("{"); + ctx.getRootCaller()->ClearId.add(ctx.getCallPath()+" = "+tnd->getDefaultValue()+";"); + ctx.getRootCaller()->ClearId.add(pdslibFunc("set")+"("+ctx.getRootCaller()->getId()+", __BaseRow, ("+TColumnIndexName+")("+ctx.getColumn()+"), "+tnd->castToPDS(tnd->getDefaultValue())+");"); + ctx.getRootCaller()->ClearId.add("}"); + } +} + + + + + + +void CDeclarationNode::generateArrayClassContent(CCallContext *context) +{ + setEnv("decltype", "arrayclass"); + + CClassGenerator &Gen = ClassNode->Gen; + CCppOutput& DbSummary = getDbNode()->DbSummary; + + CClassGenerator::SMethodId &InitId = ClassNode->InitId; + CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; + CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; + CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; + CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; + CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; + CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; + CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; + CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; + CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; + + CClassNode *sub = getClassNode(Type); + CIndexNode *ind = getIndexNode(ArrayIndex); + XmlNode += " type='arrayclass' classid='"+toString(sub->Id)+"' indexid='"+toString(ind->Id)+"'"; + + setEnv("type", Type); + setEnv("indexsize", ind->getSizeName()); + + // EGS Compat + // -- begin + + CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; + CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; + + generateArrayApplyCode(); + generateArrayStoreCode(); + +// StoreId.add("__pdr.pushStructBegin("+tokenName()+");"); + StoreId.add("__pdr.pushStructBegin(__Tok_MapVal);"); + StoreId.add(cppName()+"[index].store(__pdr);"); + StoreId.add("__pdr.pushStructEnd(__Tok_MapVal);"); +// StoreId.add("__pdr.pushStructEnd("+tokenName()+");"); + + ApplyId.add("if (index < "+ind->getSizeName()+")"); + ApplyId.add("{"); +// ApplyId.add("__pdr.popStructBegin("+tokenName()+");"); + ApplyId.add("__pdr.popStructBegin(__pdr.peekNextToken());"); + ApplyId.add(cppName()+"[index].apply(__pdr);"); + ApplyId.add("__pdr.popStructEnd(__pdr.peekNextToken());"); +// ApplyId.add("__pdr.popStructEnd("+tokenName()+");"); + ApplyId.add("}"); + ApplyId.add("else"); + ApplyId.add("{"); + ApplyId.add( "__pdr.skipStruct();"); + ApplyId.add("}"); + + generateArrayEndCode(); + + // -- end + + + // + // export class accessors into root caller + // + + CCallContext ctx; + if (context != NULL) + ctx = *context; + ctx.Context.push_back(this); + + if (ctx.getRootCaller()->HasRowAccess) + { + string forIndex = "__i"+toString(ctx.getContextIndex()); + ctx.getRootCaller()->ClearId.add("for (uint "+forIndex+"=0; "+forIndex+"<"+ind->getSizeName()+"; ++"+forIndex+")"); + ctx.getRootCaller()->ClearId.add("{"); + } + + sub->generateContentInCall(&ctx); + + if (ctx.getRootCaller()->HasRowAccess) + { + ctx.getRootCaller()->ClearId.add("}"); + } + + // + // generate attribute + // + Gen.addAttribute(Type, cppName()+"["+ind->getSizeName()+"]", "attributes"); + + // + // generate init + // + + // + // generate create code + // + + // + // generate fetch code + // + if (!ClassNode->indexUsedInFetch) + { + FetchId.add("uint\ti;"); + ClassNode->indexUsedInFetch = true; + } + FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i]."+fetchFunction+"(data);"); + + // + // generate clear code + // +} + + + + + + +void CDeclarationNode::generateArrayRefContent(CCallContext *context) +{ + setEnv("decltype", "arrayref"); + + CClassGenerator &Gen = ClassNode->Gen; + CCppOutput& DbSummary = getDbNode()->DbSummary; + + CClassGenerator::SMethodId &InitId = ClassNode->InitId; + CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; + CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; + CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; + CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; + CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; + CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; + CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; + CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; + CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; + CClassGenerator::SMethodId &NotifyInitId = ClassNode->NotifyInitId; + CClassGenerator::SMethodId &NotifyReleaseId = ClassNode->NotifyReleaseId; + + CClassNode *cnd = getClassNode(Type); + + bool useReference = cnd->ForceReference; + + CDeclarationNode *dnd = cnd->getDeclarationNode(ForwardRefAttribute); + CIndexNode *ind = getIndexNode(ArrayIndex); + CDeclarationNode *knd = cnd->getKey(); + XmlNode += " type='arrayref' classid='"+toString(cnd->Id)+"' forwardreferedid='"+toString(dnd->Id)+"' key='"+toString(knd->Id)+"' indexid='"+toString(ind->Id)+"' allownull='"+(useReference ? "true" : "false")+"'"; + + string arrayType = Type+(useReference ? "*" : ""); + string access = (useReference ? "->" : "."); + + setEnv("type", Type); + setEnv("indexsize", ind->getSizeName()); + define(useReference, "useref"); + + string UCodeContext; + if (context != NULL) + UCodeContext = context->getUserCodeContext(); + + string onChangeUser = getUserCode("onChange", UCodeContext); + + // EGS Compat + // -- begin + + CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; + CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; + + generateArrayStoreCode(); + generateArrayApplyCode(); + + StoreId.add("__pdr.pushStructBegin("+tokenName()+");"); + + ApplyId.add("if (index < "+ind->getSizeName()+")"); + ApplyId.add("{"); + ApplyId.add( "if (__pdr.peekNextToken() == "+tokenName()+")"); + ApplyId.add( "{"); + ApplyId.add( "__pdr.popStructBegin("+tokenName()+");"); + + if (useReference) + { + generateClassPtrStoreCode(cppName()+"[index]"); + + generateClassPtrApplyCode(cppName()+"[index]"); + } + else + { + StoreId.add(cppName()+"[index].store(__pdr);"); + + ApplyId.add(cppName()+"[index].apply(__pdr);"); + ApplyId.add(cppName()+"[index]."+setUnnotifiedParentFunction+"(this);"); + } + + StoreId.add("__pdr.pushStructEnd("+tokenName()+");"); + + ApplyId.add( "__pdr.popStructEnd("+tokenName()+");"); + ApplyId.add( "}"); + ApplyId.add("}"); + ApplyId.add("else"); + ApplyId.add("{"); + ApplyId.add( "__pdr.skipStruct();"); + ApplyId.add("}"); + + generateArrayEndCode(); + + // -- end + + + // + // generate read accessor + // + Gen.startMethod((useReference ? arrayType : Type+"&"), getFunc(), ind->getName()+" "+indexVariable, "methods", false, inlineAccessors); + Gen.add(ind->checkCode(indexVariable)); + Gen.add("return "+cppName()+"["+indexVariable+"];"); + + Gen.startMethod(string("const ")+(useReference ? arrayType : Type+"&"), getFunc(), ind->getName()+" "+indexVariable, "methods", true, inlineAccessors); + Gen.add(ind->checkCode(indexVariable)); + Gen.add("return "+cppName()+"["+indexVariable+"];"); + + DbSummary << "\t" << getFunc() << "\n"; + + // + // generate write accessor + // + if (useReference) + { + Gen.startMethod("void", setFunc(), arrayType+" "+valueVariable, "methods", false, inlineAccessors); + + DbSummary << "\t" << setFunc() << "\n"; + + Gen.add("if ("+valueVariable+" == NULL)\treturn;"); + Gen.add(ind->getName()+"\t"+keyVariable+" = "+valueVariable+"->"+cnd->getKey()->getFunc()+"();"); + Gen.add(ind->checkCode(keyVariable)); + Gen.add(Type+"*\t__prev = "+cppName()+"["+keyVariable+"];"); + Gen.add("if (__prev != NULL)"); + Gen.add("{"); + Gen.add("__prev->"+setParentFunction+"(NULL);"); + if (cnd->MapClass == NULL) + { + Gen.add("__prev->"+unregisterFunction+"();"); + Gen.add("__prev->"+destroyFunction+"();"); + Gen.add("delete __prev;"); + } + Gen.add("}"); + Gen.add(valueVariable+"->"+setParentFunction+"(this);"); + Gen.add(cppName()+"["+keyVariable+"] = "+valueVariable+";"); + } + + if (cnd->MapClass == NULL && useReference && !cnd->HasInheritance && !cnd->DerivatedFlag) + { + Gen.startMethod(Type+"*", newFunc(), ind->getName()+" "+indexVariable, "methods", false, inlineAccessors); + DbSummary << "\t" << newFunc() << "\n"; + Gen.add(ind->checkCode(indexVariable)); + Gen.add(Type+"*\t"+objectVariable+" = new "+Type+"();"); + Gen.add(objectVariable+"->"+initFunction+"("+indexVariable+");"); + Gen.add(objectVariable+"->"+registerFunction+"();"); + Gen.add(setFunc()+"("+objectVariable+");"); + } + + if (cnd->MapClass == NULL && useReference) + { + Gen.startMethod("void", deleteFunc(), ind->getName()+" "+indexVariable, "methods", false, inlineAccessors); + DbSummary << "\t" << deleteFunc() << "\n"; + Gen.add(ind->checkCode(indexVariable)); + Gen.add(Type+"*\t"+objectVariable+" = "+cppName()+"["+indexVariable+"];"); + Gen.add(objectVariable+"->"+setParentFunction+"(NULL);"); + Gen.add(objectVariable+"->"+unregisterFunction+"();"); + Gen.add(objectVariable+"->"+destroyFunction+"();"); + Gen.add("delete "+objectVariable+";"); + } + + // + // generate attribute + // + Gen.addAttribute(arrayType, cppName()+"["+ind->getSizeName()+"]", "attributes"); + + // + // generate init + // + if (!ClassNode->indexUsedInInit) + { + InitId.add("uint\ti;"); + ClassNode->indexUsedInInit = true; + } + if (useReference) + { + InitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i] = NULL;"); + } + else + { + InitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)\t"+cppName()+"[i]."+initFunction+"(("+ind->getName()+")i);"); + } + + // + // generate destroy code + // + if (!ClassNode->indexUsedInDestroy) + { + DestroyId.add("uint\ti;"); + ClassNode->indexUsedInDestroy = true; + } + DestroyId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); + DestroyId.add("{"); + if (useReference) + { + DestroyId.add("if ("+cppName()+"[i] != NULL)"); + DestroyId.add("{"); + DestroyId.add(Type+"*\t"+objectVariable+" = "+cppName()+"[i];"); + DestroyId.add(objectVariable+"->"+destroyFunction+"();"); + DestroyId.add("delete "+objectVariable+";"); + DestroyId.add("}"); + } + else + { + DestroyId.add(cppName()+"[i]."+destroyFunction+"();"); + } + DestroyId.add("}"); + + // + // generate create code + // + + // + // generate fetch code + // + if (useReference) + { + if (!ClassNode->indexUsedInFetch) + { + FetchId.add("uint\ti;"); + ClassNode->indexUsedInFetch = true; + } + if (!ClassNode->tableAndRowIndicesUsedInFetch) + { + FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;"); + ClassNode->tableAndRowIndicesUsedInFetch = true; + } + FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); + FetchId.add("{"); + FetchId.add(cppName()+"[i] = NULL;"); + FetchId.add("// read table and row, create an object, affect to the ref, and fetch it"); + FetchId.add("data.serial(tableIndex, rowIndex);"); + FetchId.add("if (rowIndex != "+INVALID_ROW_INDEXName+" && tableIndex != "+INVALID_TABLE_INDEXName+")"); + FetchId.add("{"); + FetchId.add(cppName()+"[i] = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));"); + FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+cppName()+"[i]);"); + FetchId.add(cppName()+"[i]->"+fetchFunction+"(data);"); + FetchId.add(cppName()+"[i]->"+setUnnotifiedParentFunction+"(this);"); + FetchId.add("}"); + FetchId.add("}"); + } + else + { + if (!ClassNode->indexUsedInFetch) + { + FetchId.add("uint\ti;"); + ClassNode->indexUsedInFetch = true; + } + if (!ClassNode->tableAndRowIndicesUsedInFetch) + { + FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;"); + ClassNode->tableAndRowIndicesUsedInFetch = true; + } + FetchId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); + FetchId.add("{"); + FetchId.add("// read table and row, create an object, affect to the ref, and fetch it"); + FetchId.add("data.serial(tableIndex, rowIndex);"); + FetchId.add("if (rowIndex != "+INVALID_ROW_INDEXName+" && tableIndex != "+INVALID_TABLE_INDEXName+")"); + FetchId.add("{"); + FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, &"+cppName()+"[i]);"); + FetchId.add(cppName()+"[i]."+fetchFunction+"(data);"); + FetchId.add(cppName()+"[i]."+setUnnotifiedParentFunction+"(this);"); + FetchId.add("}"); + FetchId.add("}"); + } + + // + // generate register/unregister code + // + if (!useReference) + { + if (!ClassNode->indexUsedInRegister) + { + RegisterAttributesId.add("uint\ti;"); + ClassNode->indexUsedInRegister = true; + } + RegisterAttributesId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); + RegisterAttributesId.add("{"); + RegisterAttributesId.add(cppName()+"[i]."+registerFunction+"();"); + RegisterAttributesId.add(cppName()+"[i]."+setParentFunction+"(this);"); + RegisterAttributesId.add("}"); + + if (!ClassNode->indexUsedInUnregister) + { + UnregisterAttributesId.add("uint\ti;"); + ClassNode->indexUsedInUnregister = true; + } + UnregisterAttributesId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); + UnregisterAttributesId.add("{"); + UnregisterAttributesId.add(cppName()+"[i]."+unregisterFunction+"();"); + UnregisterAttributesId.add("}"); + } + else + { + if (!ClassNode->indexUsedInUnregister) + { + UnregisterAttributesId.add("uint\ti;"); + ClassNode->indexUsedInUnregister = true; + } + UnregisterAttributesId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); + UnregisterAttributesId.add("{"); + UnregisterAttributesId.add("if ("+cppName()+"[i] != NULL)"); + UnregisterAttributesId.add("{"); + UnregisterAttributesId.add(Type+"*\t"+objectVariable+" = "+cppName()+"[i];"); + UnregisterAttributesId.add(objectVariable+"->"+unregisterFunction+"();"); + UnregisterAttributesId.add(objectVariable+"->"+destroyFunction+"();"); + UnregisterAttributesId.add("delete "+objectVariable+";"); + UnregisterAttributesId.add("}"); + UnregisterAttributesId.add("}"); + } + + // + // generate init/release notification + // + + if (!ClassNode->indexUsedInNotifyInit) + { + NotifyInitId.add("uint\ti;"); + ClassNode->indexUsedInNotifyInit = true; + } + NotifyInitId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); + NotifyInitId.add("{"); + + if (!ClassNode->indexUsedInNotifyRelease) + { + NotifyReleaseId.add("uint\ti;"); + ClassNode->indexUsedInNotifyRelease = true; + } + NotifyReleaseId.add("for (i=0; i<"+ind->getSizeName()+"; ++i)"); + NotifyReleaseId.add("{"); + + if (!useReference) + { + NotifyInitId.add(cppName()+"[i]."+notifyInitFunction+"();"); + + NotifyReleaseId.add(cppName()+"[i]."+notifyReleaseFunction+"();"); + } + else + { + NotifyInitId.add("if ("+cppName()+"[i] != NULL)"); + NotifyInitId.add("{"); + NotifyInitId.add(cppName()+"[i]->"+notifyInitFunction+"();"); + NotifyInitId.add("}"); + + NotifyReleaseId.add("if ("+cppName()+"[i] != NULL)"); + NotifyReleaseId.add("{"); + NotifyReleaseId.add(cppName()+"[i]->"+notifyReleaseFunction+"();"); + NotifyReleaseId.add("}"); + } + + NotifyInitId.add("}"); + NotifyReleaseId.add("}"); + + + // + // generate unlink code + // + if (useReference) + { + Gen.startMethod("void", unlinkFunc(), ind->getName()+" "+keyVariable, "internal", false, inlineInternal); + Gen.add(cppName()+"["+keyVariable+"] = NULL;"); + } + + // + // generate clear code + // + ClearId.add("for (uint i=0; i<"+ind->getSizeName()+"; ++i)"); + ClearId.add("{"); + if (!useReference) + { + ClearId.add(cppName()+"[i]."+clearFunction+"();"); + } + else + { + //ClearId.add(cppName()+"[i]->"+setParentFunction+"(NULL);"); + ClearId.add(Type+"*\t"+objectVariable+" = "+cppName()+"[i];"); + ClearId.add(objectVariable+"->"+unregisterFunction+"();"); + ClearId.add(objectVariable+"->"+destroyFunction+"();"); + ClearId.add("delete "+objectVariable+";"); + } + ClearId.add("}"); +} + + + + + + + +void CDeclarationNode::generateSetContent(CCallContext *context) +{ + setEnv("decltype", "set"); + + CClassGenerator &Gen = ClassNode->Gen; + CCppOutput& DbSummary = getDbNode()->DbSummary; + + CClassGenerator::SMethodId &InitId = ClassNode->InitId; + CClassGenerator::SMethodId &ClearId = ClassNode->ClearId; + CClassGenerator::SMethodId &DestroyId = ClassNode->DestroyId; + CClassGenerator::SMethodId &FetchId = ClassNode->FetchId; + CClassGenerator::SMethodId &RegisterId = ClassNode->RegisterId; + CClassGenerator::SMethodId &RegisterAttributesId = ClassNode->RegisterAttributesId; + CClassGenerator::SMethodId &UnregisterId = ClassNode->UnregisterId; + CClassGenerator::SMethodId &UnregisterAttributesId = ClassNode->UnregisterAttributesId; + CClassGenerator::SMethodId &SetParentId = ClassNode->SetParentId; + CClassGenerator::SMethodId &SetUnnotifiedParentId = ClassNode->SetUnnotifiedParentId; + CClassGenerator::SMethodId &NotifyInitId = ClassNode->NotifyInitId; + CClassGenerator::SMethodId &NotifyReleaseId = ClassNode->NotifyReleaseId; + + CClassNode *sub = getClassNode(Type); + CDeclarationNode *key = sub->getKey(); + CTypeNode *keyType = getTypeNode(key->Type); + + bool useReference = sub->ForceReference; + string access = (useReference ? "->" : "."); + + string onChangeUser = getUserCode("onChange", context != NULL ? context->getUserCodeContext() : ""); + + + string setType = "std::map<"+keyType->getName()+", " + Type + (useReference ? "*" : "") + ">"; + + CDeclarationNode *dnd = sub->getDeclarationNode(ForwardRefAttribute); + XmlNode += " type='set' classid='"+toString(sub->Id)+"' forwardreferedid='"+toString(dnd->Id)+"' key='"+toString(key->Id)+"' "; + + setEnv("type", Type); + setEnv("keytype", keyType->getName()); + define(useReference, "useref"); + + // EGS Compat + // -- begin + + CClassGenerator::SMethodId& StoreId = ClassNode->StoreId; + CClassGenerator::SMethodId& ApplyId = ClassNode->ApplyId; + + StoreId.add("// store "+Name); + StoreId.add("__pdr.pushStructBegin("+tokenName()+");"); + StoreId.add("for ("+setType+"::const_iterator it="+cppName()+".begin(); it!="+cppName()+".end(); ++it)"); + StoreId.add("{"); + StoreId.add( keyType->getName()+"\tkey = (*it).first;"); + keyType->generateStoreCode(StoreId, "__Tok_MapKey", "key"); + StoreId.add( "__pdr.pushStructBegin(__Tok_MapVal);"); + + if (useReference) + { + generateClassPtrStoreCode("(*it).second"); + } + else + { + StoreId.add("(*it).second.store(__pdr);"); + } + + StoreId.add( "__pdr.pushStructEnd(__Tok_MapVal);"); + StoreId.add("}"); + StoreId.add("__pdr.pushStructEnd("+tokenName()+");"); + StoreId.add("// end of store "+Name); + + ApplyId.add("// apply "+Name); + ApplyId.add("else if (__pdr.peekNextToken() == "+tokenName()+")"); + ApplyId.add("{"); + ApplyId.add( "__pdr.popStructBegin("+tokenName()+");"); + ApplyId.add( "while (!__pdr.isEndOfStruct())"); + ApplyId.add( "{"); + ApplyId.add( keyType->getName()+"\tkey;"); + keyType->generateApplyCode(ApplyId, "__Tok_MapKey", "key"); + + ApplyId.add( "__pdr.popStructBegin(__Tok_MapVal);"); + if (useReference) + { + ApplyId.add( Type+"*\tobj;"); + generateClassPtrApplyCode("obj"); + ApplyId.add( "if (obj != NULL)"); + ApplyId.add( "{"); + ApplyId.add( cppName()+"[key] = obj;"); + ApplyId.add( "}"); + } + else + { + ApplyId.add( Type+"&\tobj = "+cppName()+"[key];"); + ApplyId.add( "obj.apply(__pdr);"); + ApplyId.add( "obj."+setUnnotifiedParentFunction+"(this);"); + } + ApplyId.add( "__pdr.popStructEnd(__Tok_MapVal);"); + ApplyId.add( "}"); + ApplyId.add( "__pdr.popStructEnd("+tokenName()+");"); + ApplyId.add("}"); + ApplyId.add("// end of apply "+Name); + + // -- end + + + // + // generate read accessor + // + Gen.startMethod(Type+"*", getFunc(), "const "+keyType->getName()+"& "+keyVariable, "methods", false, inlineAccessors); + DbSummary << "\t" << getFunc() << "\n"; + Gen.add(setType+"::iterator _it = "+cppName()+".find("+keyVariable+");"); + Gen.add("return (_it=="+cppName()+".end() ? NULL : "+(useReference ? "(*_it).second" : "&((*_it).second)")+");"); + + Gen.startMethod("const "+Type+"*", getFunc(), "const "+keyType->getName()+"& "+keyVariable, "methods", true, inlineAccessors); + Gen.add(setType+"::const_iterator _it = "+cppName()+".find("+keyVariable+");"); + Gen.add("return (_it=="+cppName()+".end() ? NULL : "+(useReference ? "(*_it).second" : "&((*_it).second)")+");"); + + // generate map accessor + string stypedef = "T"+Name+"Map"; + //Gen.addOther("typedef "+setType+"\t"+stypedef+";"); + Gen.startMethod(setType+"::iterator", getFunc()+"Begin", "", "methods", false, inlineAccessors); + Gen.add("return "+cppName()+".begin();"); + DbSummary << "\t" << getFunc() << "Begin" << "\n"; + Gen.startMethod(setType+"::iterator", getFunc()+"End", "", "methods", false, inlineAccessors); + Gen.add("return "+cppName()+".end();"); + DbSummary << "\t" << getFunc() << "End" << "\n"; + Gen.startMethod(setType+"::const_iterator", getFunc()+"Begin", "", "methods", true, inlineAccessors); + Gen.add("return "+cppName()+".begin();"); + Gen.startMethod(setType+"::const_iterator", getFunc()+"End", "", "methods", true, inlineAccessors); + Gen.add("return "+cppName()+".end();"); + Gen.startMethod("const "+setType+" &", getFunc(), "", "methods", true, inlineAccessors); + Gen.add("return "+cppName()+";"); + + // + // generate write accessor + // + if (useReference) + { + Gen.startMethod("void", setFunc(), Type+"* "+valueVariable, "methods", false, inlineAccessors); + DbSummary << "\t" << setFunc() << "\n"; + Gen.add("if ("+valueVariable+" == NULL)\treturn;"); + Gen.add(keyType->getName()+"\t"+keyVariable+" = "+valueVariable+"->"+sub->getKey()->getFunc()+"();"); + Gen.add(setType+"::iterator\t_it = "+cppName()+".find("+keyVariable+");"); + Gen.add("if (_it != "+cppName()+".end())"); + Gen.add("{"); + Gen.add(Type+"*\t__prev = (*_it).second;"); + Gen.add("if (__prev == "+valueVariable+")\treturn;"); + Gen.add("__prev->"+setParentFunction+"(NULL);"); + Gen.add("__prev->"+unregisterFunction+"();"); + Gen.add("__prev->"+destroyFunction+"();"); + Gen.add("delete __prev;"); + Gen.add("}"); + Gen.add(valueVariable+"->"+setParentFunction+"(this);"); + Gen.add(cppName()+"["+keyVariable+"] = "+valueVariable+";"); + if (!onChangeUser.empty()) + { + Gen.add("{"); + Gen.add(onChangeUser); + Gen.add("}"); + } + } + + if (sub->MapClass == NULL && !sub->HasInheritance && !sub->DerivatedFlag) + { + Gen.startMethod(Type+"*", newFunc(), "const "+keyType->getName()+" &"+keyVariable, "methods", false, inlineAccessors); + DbSummary << "\t" << newFunc() << "\n"; + Gen.add(setType+"::iterator\t__it = "+cppName()+".find("+keyVariable+");"); + Gen.add("if (__it == "+cppName()+".end())"); + Gen.add("{"); + Gen.add("__it = "+cppName()+".insert("+setType+"::value_type("+keyVariable+", "+(useReference ? toString("new ") : toString(""))+Type+"())).first;"); + Gen.add(Type+"*\t"+objectVariable+" = "+(useReference ? toString("") : toString("&"))+"((*__it).second);"); + Gen.add(objectVariable+"->"+initFunction+"("+keyVariable+");"); + Gen.add(objectVariable+"->"+registerFunction+"();"); + Gen.add(objectVariable+"->"+setParentFunction+"(this);"); + Gen.add("}"); + if (!onChangeUser.empty()) + { + Gen.add("{"); + Gen.add(onChangeUser); + Gen.add("}"); + } + Gen.add("return "+(useReference ? toString("") : toString("&"))+"((*__it).second);"); + } + + Gen.startMethod("void", deleteFunc(), "const "+keyType->getName()+" &"+keyVariable, "methods", false, inlineAccessors); + DbSummary << "\t" << deleteFunc() << "\n"; + Gen.add(setType+"::iterator\t__it = "+cppName()+".find("+keyVariable+");"); + Gen.add("if (__it == "+cppName()+".end())\treturn;"); + if (useReference) + { + Gen.add(Type+"*\t"+objectVariable+" = (*__it).second;"); + Gen.add(objectVariable+"->"+unregisterFunction+"();"); + Gen.add(objectVariable+"->"+destroyFunction+"();"); + Gen.add("delete "+objectVariable+";"); + } + else + { + Gen.add(Type+"&\t"+objectVariable+" = (*__it).second;"); + Gen.add(objectVariable+"."+unregisterFunction+"();"); + Gen.add(cppName()+".erase(__it);"); + } + if (!onChangeUser.empty()) + { + Gen.add("{"); + Gen.add(onChangeUser); + Gen.add("}"); + } + + // + // generate attribute + // + Gen.addAttribute(setType, cppName(), "attributes"); + + // + // generate init + // + + // + // generate destroy code + // + DestroyId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )"); + DestroyId.add("{"); + DestroyId.add(setType+"::iterator __itr=__it++;"); + if (useReference) + { + DestroyId.add(Type+"*\t"+objectVariable+" = ((*__itr).second);"); + DestroyId.add("if ("+objectVariable+" != NULL)"); + DestroyId.add("{"); + DestroyId.add(objectVariable+"->"+destroyFunction+"();"); + DestroyId.add("delete "+objectVariable+";"); + DestroyId.add("}"); + } + else + { + DestroyId.add("((*__itr).second)."+destroyFunction+"();"); + } + DestroyId.add("}"); + DestroyId.add(cppName()+".clear();"); + + // + // generate create code + // + + // + // generate fetch code + // + if (!ClassNode->tableAndRowIndicesUsedInFetch) + { + FetchId.add(TTableIndexName+"\ttableIndex;\n"+TRowIndexName+"\trowIndex;"); + ClassNode->tableAndRowIndicesUsedInFetch = true; + } + FetchId.add("do"); + FetchId.add("{"); + FetchId.add("// read table and row, create an object, affect to the ref, and fetch it"); + FetchId.add("data.serial(tableIndex, rowIndex);"); + FetchId.add("if (rowIndex == "+INVALID_ROW_INDEXName+" || tableIndex == "+INVALID_TABLE_INDEXName+")\tbreak;"); + + FetchId.add(keyType->getName()+"\t"+keyVariable+";"); + if (keyType->isEnum()) + { + FetchId.add("data.serialEnum("+keyVariable+");"); + } + else if (keyType->CppType != keyType->StorageType) + { + FetchId.add("{"); + FetchId.add(keyType->StorageType+"\t_v;"); + FetchId.add("data.serial(_v);"); + FetchId.add(keyVariable+" = "+keyType->castToCpp("_v")+";"); + FetchId.add("}"); + } + else + { + FetchId.add("data.serial("+keyVariable+");"); + } + if (useReference) + { + FetchId.add(Type+"*\t"+objectVariable+" = static_cast<"+Type+"*>("+pdslibFunc("create")+"(tableIndex));"); + FetchId.add(cppName()+".insert(std::make_pair<"+keyType->getName()+","+Type+"*>("+keyVariable+", "+objectVariable+"));"); + } + else + { + FetchId.add(cppName()+".insert(std::make_pair<"+keyType->getName()+","+Type+">("+keyVariable+", "+Type+"()));"); + FetchId.add(Type+"*\t"+objectVariable+" = &("+cppName()+"["+keyVariable+"]);"); + } + FetchId.add(pdslibFunc("setRowIndex")+"(rowIndex, "+objectVariable+");"); + FetchId.add(objectVariable+"->"+fetchFunction+"(data);"); + FetchId.add(objectVariable+"->"+setUnnotifiedParentFunction+"(this);"); + FetchId.add("}"); + FetchId.add("while (true);"); + + // + // generate register/unregister code + // + + UnregisterAttributesId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )"); + UnregisterAttributesId.add("{"); + UnregisterAttributesId.add(setType+"::iterator __itr=__it++;"); + if (useReference) + { + UnregisterAttributesId.add(Type+"*\t"+objectVariable+" = (*__itr).second;"); + UnregisterAttributesId.add(objectVariable+"->"+unregisterFunction+"();"); + UnregisterAttributesId.add(objectVariable+"->"+destroyFunction+"();"); + UnregisterAttributesId.add("delete "+objectVariable+";"); + } + else + { + UnregisterAttributesId.add(Type+"&\t"+objectVariable+" = (*__itr).second;"); + UnregisterAttributesId.add(objectVariable+"."+unregisterFunction+"();"); + } + UnregisterAttributesId.add("}"); + + // + // generate init/release notification + // + + NotifyInitId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )"); + NotifyInitId.add("{"); + NotifyInitId.add(setType+"::iterator __itr=__it++;"); + + NotifyReleaseId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )"); + NotifyReleaseId.add("{"); + NotifyReleaseId.add(setType+"::iterator __itr=__it++;"); + + if (!useReference) + { + NotifyInitId.add("(*__itr).second."+notifyInitFunction+"();"); + NotifyReleaseId.add("(*__itr).second."+notifyReleaseFunction+"();"); + } + else + { + NotifyInitId.add("(*__itr).second->"+notifyInitFunction+"();"); + NotifyReleaseId.add("(*__itr).second->"+notifyReleaseFunction+"();"); + } + + NotifyInitId.add("}"); + NotifyReleaseId.add("}"); + + // + // generate unlink code + // + if (useReference) + { + Gen.startMethod("void", unlinkFunc(), keyType->getName()+" "+keyVariable, "internal", false, inlineInternal); + Gen.add(cppName()+".erase("+keyVariable+");"); + } + + // + // generate clear code + // + ClearId.add("for ("+setType+"::iterator __it="+cppName()+".begin(); __it!="+cppName()+".end(); )"); + ClearId.add("{"); + ClearId.add(setType+"::iterator __itr=__it++;"); + if (!useReference) + { + ClearId.add(Type+"*\t"+objectVariable+" = &((*__itr).second);"); + } + else + { + ClearId.add(Type+"*\t"+objectVariable+" = (*__itr).second;"); + } + //ClearId.add(objectVariable+"->"+setParentFunction+"(NULL);"); + ClearId.add(objectVariable+"->"+unregisterFunction+"();"); + ClearId.add(objectVariable+"->"+destroyFunction+"();"); + if (useReference) + { + ClearId.add("delete "+objectVariable+";"); + } + ClearId.add("}"); + ClearId.add(cppName()+".clear();"); +} + +// +string CDeclarationNode::displayPrintfPrefix() +{ + if (DeclarationType != SimpleType) + error("can't display other declaration than simple type", "internal"); + + CTypeNode* type = getTypeNode(Type); + + if (type->CppType == "CEntityId" || type->CppType == "CSheetId") + return "%s"; + else if (type->CppType == "uint64" || type->CppType == "sint64") + return "%\"NL_I64\"d"; + else if (type->CppType == "float" || type->CppType == "double") + return "%g"; + else + return "%d"; +} + +string CDeclarationNode::displayCppCode(string replVar) +{ + if (DeclarationType != SimpleType) + error("can't display other declaration than simple type", "internal"); + + if (replVar.empty()) + replVar = cppName(); + + CTypeNode* type = getTypeNode(Type); + + if (type->CppType == "CEntityId" || type->CppType == "CSheetId") + return replVar+".toString().c_str()"; + else + return replVar; +} + + +string CDeclarationNode::toUint64(string replVar) +{ + if (DeclarationType != SimpleType) + error("can't display other declaration than simple type", "internal"); + + if (replVar.empty()) + replVar = cppName(); + + CTypeNode* type = getTypeNode(Type); + + if (type->CppType == "CEntityId") + return replVar+".asUint64()"; + else if (type->CppType == "CSheetId") + return "(uint64)("+replVar+".asInt())"; + else + return "(uint64)"+replVar; +} + + + + + +bool CLogMsgNode::prolog() +{ + getDbNode()->LogNodes.push_back(this); + + getFileNode()->IncludeDbFile = true; + getFileNode()->IncludeStandard = true; + getFileNode()->IncludePDSLib = true; + + return true; +} + +void CLogMsgNode::generateContent() +{ + // + uint j; + + CFunctionGenerator logfunc; + CClassGenerator logclass; + string argcall; + + CFunctionGenerator& initDb = getDbNode()->initDb; + + logfunc.init(Name); + logfunc.setType("void"); + logfunc.IsInline = inlineLogFunctions; + + logclass.init("Log"+Name); + logclass.createPublic("pub"); + logclass.createPrivate("priv"); + + CClassGenerator::SMethodId startlogid = logclass.startMethod("void", logStartFunction, "", "priv", false, inlineLogFunctions); + CClassGenerator::SMethodId stoplogid = logclass.startMethod("void", logStopFunction, "", "priv", false, inlineLogFunctions); + startlogid.add(pdslibFunc("pushContext")+"();"); + stoplogid.add(pdslibFunc("popContext")+"();"); + + map params; + + for (j=0; j::iterator, bool> res = params.insert(make_pair(name, tnd)); + if (!res.second) + error("log parameter '"+name+"' already defined"); + + if (!logfunc.Proto.empty()) + logfunc.Proto += ", "; + if (!argcall.empty()) + argcall += ", "; + + logfunc.Proto += tnd->getName()+" "+name; + argcall += name; + } + else if ( (cnd = getClassNode(type, false)) ) + { + pair::iterator, bool> res = params.insert(make_pair(name, cnd)); + if (!res.second) + error("log parameter '"+name+"' already defined"); + + if (!logfunc.Proto.empty()) + logfunc.Proto += ", "; + if (!argcall.empty()) + argcall += ", "; + + logfunc.Proto += "const "+type+"& "+name; + argcall += name; + } + else if (type == "string") + { + CExtLogTypeNode* extnd = new CExtLogTypeNode(); + extnd->ExtLogType = "string"; + pair::iterator, bool> res = params.insert(make_pair(name, extnd)); + if (!res.second) + error("log parameter '"+name+"' already defined"); + + if (!logfunc.Proto.empty()) + logfunc.Proto += ", "; + if (!argcall.empty()) + argcall += ", "; + + logfunc.Proto += "const std::string& "+name; + argcall += name; + } + else + { + error("'"+type+"' not found as a class or a type"); + } + } + + // + initDb.add("// Init "+Name+" log message and parameters"); + + for (j=0; jxmlDescription.push_back(""); + + uint paramNum = 0; + + initDb.add(pdslibFunc("initLog")+"("+toString(logId)+");"); + + while (*cptr != '\0') + { + if (*cptr == '$') + { + ++cptr; + if (*cptr == '\0') + error("log format corrupted in line \""+Logs[j]+"\""); + + if (*cptr == '$') + { + log += "$$"; + ++cptr; + continue; + } + + string param; + string var; + + while (*cptr!='\0' && *cptr!='$' && *cptr!='.') + param += *(cptr++); + + if (*cptr == '\0') + error("log format corrupted in line \""+Logs[j]+"\""); + + if (*cptr == '.') + { + ++cptr; + while (*cptr!='\0' && *cptr!='$') + var += *(cptr++); + } + + if (*cptr != '$') + error("log format corrupted in line \""+Logs[j]+"\""); + + ++cptr; + + map::iterator it = params.find(param); + + if (it == params.end()) + error("'"+param+"' ot found in prototype, at line \""+Logs[j]+"\""); + + CTypeNode *tnd = NULL; + CExtLogTypeNode* extnd = NULL; + + if (var.empty()) + { + // is simple type + tnd = dynamic_cast((*it).second); + extnd = dynamic_cast((*it).second); + if (tnd != NULL) + { + logfunc.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param)+");"); + startlogid.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param)+");"); + } + else if (extnd != NULL && extnd->ExtLogType == "string") + { + logfunc.add(pdslibFunc("logPush")+"("+param+");"); + startlogid.add(pdslibFunc("logPush")+"("+param+");"); + } + else + { + error("misuse of parameter '"+param+"' at line \""+Logs[j]+"\", missing attribute name"); + } + } + else + { + // is class + CClassNode *cnd = dynamic_cast((*it).second); + if (!cnd) + error("misuse of parameter '"+param+"' at line \""+Logs[j]+"\", should be a class"); + + CDeclarationNode *dnd = cnd->getDeclaration(var); + + if (!dnd->IsType) + error("attribute '"+var+"' is not a simple type"); + + tnd = getTypeNode(dnd->Type); + + logfunc.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param+"."+dnd->getFunc()+"()")+");"); + startlogid.add(pdslibFunc("logPush")+"("+tnd->castToPDS(param+"."+dnd->getFunc()+"()")+");"); + } + + if (tnd != NULL) + { + getDbNode()->xmlDescription.push_back(""); + initDb.add(pdslibFunc("initLogParam")+"("+toString(logId)+", "+toString(paramNum)+", "+toString(tnd->Size)+");"); + } + else + { + getDbNode()->xmlDescription.push_back(""); + initDb.add(pdslibFunc("initLogParam")+"("+toString(logId)+", "+toString(paramNum)+", "+toString(sizeof(uint16))+");"); + } + + + log += "$"+toString(paramNum); + + ++paramNum; + } + else + { + log += *(cptr++); + } + } + + getDbNode()->xmlDescription.push_back(""+xmlSpecialChars(log)+""); + getDbNode()->xmlDescription.push_back(""); + } + + logclass.get(startlogid).Proto = logfunc.Proto; + + CClassGenerator::SMethodId construct = logclass.startConstructor(logfunc.Proto, "pub", inlineLogFunctions, ""); + construct.add(logStartFunction+"("+argcall+");"); + CClassGenerator::SMethodId destruct = logclass.startDestructor("pub", inlineLogFunctions); + destruct.add(logStopFunction+"();"); + + CFileNode* file = getFileNode(); + + if (Context) + { + logclass.flush(file->hOutput(), file->cppOutput(), file->inlineOutput()); + file->hOutput() << "\n"; + } + else + { + logfunc.flush(file->hOutput(), file->cppOutput(), file->inlineOutput()); + file->hOutput() << "\n"; + } +} + diff --git a/code/ryzom/tools/pd_parser/parser.h b/code/ryzom/tools/pd_parser/parser.h index f52de4f18..fd03e47ee 100644 --- a/code/ryzom/tools/pd_parser/parser.h +++ b/code/ryzom/tools/pd_parser/parser.h @@ -1,32 +1,32 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef RY_PD_PARSER_H -#define RY_PD_PARSER_H - -#include "parser_rules.h" - -extern bool GenerateCpp; -extern bool GenerateXmlDescription; -extern bool VerboseMode; -extern bool GenerateHAuto; -extern bool GenerateDebugMessages; -extern bool GenerateOnlyLogs; - -CParseNode *parse(const std::string &file); - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef RY_PD_PARSER_H +#define RY_PD_PARSER_H + +#include "parser_rules.h" + +extern bool GenerateCpp; +extern bool GenerateXmlDescription; +extern bool VerboseMode; +extern bool GenerateHAuto; +extern bool GenerateDebugMessages; +extern bool GenerateOnlyLogs; + +CParseNode *parse(const std::string &file); + +#endif diff --git a/code/ryzom/tools/pd_parser/parser_rules.cpp b/code/ryzom/tools/pd_parser/parser_rules.cpp index 58f84a1cc..4ae250f59 100644 --- a/code/ryzom/tools/pd_parser/parser_rules.cpp +++ b/code/ryzom/tools/pd_parser/parser_rules.cpp @@ -1,566 +1,566 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - -#include "parser_rules.h" - -/* - * Main Bloc - */ -PARSE_START_NO_DESCRIPTION(Main, CParseNode) - - while (!tokenizer.end()) - { - PARSE_MARK - PARSE_ALTERNATIVE(Db) - PARSE_FAIL - } - -PARSE_END - - -/* - * Db Bloc - */ -PARSE_START(Db, CDbNode) - - PARSE_KEYWORD(Db) - PARSE_MARK - PARSE_IDENTIFIER(Name) - PARSE_MARK - - PARSE_OPT_KEYWORD_IN(String, MainFile); - - PARSE_START_BLOC - - PARSE_MARK - - PARSE_ALTERNATIVE(File) - PARSE_ALTERNATIVE(UsePch) - PARSE_FAIL - - PARSE_MARK - - PARSE_END_BLOC - - PARSE_MARK - -PARSE_END - - -/* - * File Bloc - */ -PARSE_START(File, CFileNode) - - PARSE_OPT_BEFORE(File) - PARSE_OPT_IN(Separated, SeparatedFlag); - PARSE_END_OPT_BEFORE() - - PARSE_KEYWORD(File) - PARSE_MARK - PARSE_STRING(Name) - PARSE_MARK - - main->IncludeAs = main->Name; - - PARSE_OPT_KEYWORD_IN(String, IncludeAs); - - PARSE_START_BLOC - - PARSE_MARK - - PARSE_ALTERNATIVE(Include) - PARSE_ALTERNATIVE(Type) - PARSE_ALTERNATIVE(Class) - PARSE_ALTERNATIVE(Enum) - PARSE_ALTERNATIVE(Dimension) - //PARSE_ALTERNATIVE(CppCode) - PARSE_ALTERNATIVE(LogMsg) - PARSE_ALTERNATIVE(LogContext) - PARSE_FAIL - - PARSE_MARK - - PARSE_END_BLOC - - PARSE_MARK - -PARSE_END - - -/* - * Include Bloc - */ -PARSE_START(Include, CIncludeNode) - - PARSE_KEYWORD(Include) - PARSE_MARK - PARSE_STRING(Name) - PARSE_MARK - -PARSE_END - -/* - * Include Bloc - */ -PARSE_START(UsePch, CUsePchNode) - - PARSE_KEYWORD(UsePch) - PARSE_MARK - PARSE_STRING(Name) - PARSE_MARK - -PARSE_END - - -/* - * Cpp Code Bloc - */ -PARSE_START(CppCode, CCppCodeNode) - - PARSE_OPT_KEYWORD_IN(Identifier, Name) - PARSE_KEYWORD_IN(CppCode, RawCode) - PARSE_MARK - -PARSE_END - - -/* - * Type Bloc - */ -PARSE_START(Type, CTypeNode) - - PARSE_OPT_BEFORE(Type) - PARSE_OPT_IN(Extern, ExternFlag); - PARSE_END_OPT_BEFORE() - - PARSE_KEYWORD(Type) - PARSE_MARK - if (main->ExternFlag) - { - PARSE_SCOPE_IDF(Name) - } - else - { - PARSE_IDENTIFIER(Name) - } - - main->DisplayName = main->Name; - - PARSE_MARK - if (tokenizer.current() == TokenOpenParenthesis) - { - tokenizer.next(); - PARSE_MARK - PARSE_IDENTIFIER(CppType) - PARSE_MARK - PARSE_KEYWORD(Comma) - PARSE_MARK - PARSE_IDENTIFIER(StorageType) - PARSE_MARK - PARSE_KEYWORD(CloseParenthesis) - PARSE_MARK - - if (tokenizer.current() == TokenOpenBrace) - { - tokenizer.next(); - - PARSE_MARK - PARSE_IDENTIFIER(Temp) - if (main->Temp == main->CppType) - { - PARSE_MARK - PARSE_KEYWORD(OpenParenthesis) - PARSE_MARK - PARSE_IDENTIFIER(Temp) - if (main->Temp != main->StorageType) - PARSE_FAIL - PARSE_MARK - PARSE_KEYWORD(CloseParenthesis) - PARSE_MARK - PARSE_NODE(CppCode, ToCppType) - PARSE_MARK - } - else if (main->Temp == main->StorageType) - { - PARSE_MARK - PARSE_KEYWORD(OpenParenthesis) - PARSE_MARK - PARSE_IDENTIFIER(Temp) - if (main->Temp != main->CppType) - PARSE_FAIL - PARSE_MARK - PARSE_KEYWORD(CloseParenthesis) - PARSE_MARK - PARSE_NODE(CppCode, ToStorageType) - PARSE_MARK - } - else - PARSE_FAIL - - if (tokenizer.current() != TokenCloseBrace) - { - PARSE_IDENTIFIER(Temp) - PARSE_MARK - if (main->Temp == main->CppType && main->ToCppType == NULL) - { - PARSE_MARK - PARSE_KEYWORD(OpenParenthesis) - PARSE_MARK - PARSE_IDENTIFIER(Temp) - if (main->Temp != main->StorageType) - PARSE_FAIL - PARSE_MARK - PARSE_KEYWORD(CloseParenthesis) - PARSE_MARK - PARSE_NODE(CppCode, ToCppType) - PARSE_MARK - } - else if (main->Temp == main->StorageType && main->ToStorageType == NULL) - { - PARSE_MARK - PARSE_KEYWORD(OpenParenthesis) - PARSE_MARK - PARSE_IDENTIFIER(Temp) - if (main->Temp != main->CppType) - PARSE_FAIL - PARSE_MARK - PARSE_KEYWORD(CloseParenthesis) - PARSE_MARK - PARSE_NODE(CppCode, ToStorageType) - PARSE_MARK - } - else - PARSE_FAIL - } - - PARSE_KEYWORD(CloseBrace) - } - else - { - PARSE_KEYWORD(SemiColon) - } - } - else - { - PARSE_IDENTIFIER(CppType) - main->StorageType = main->CppType; - PARSE_MARK - PARSE_KEYWORD(SemiColon) - } - - PARSE_MARK - -PARSE_END - - -/* - * Class Bloc - */ -PARSE_START(Class, CClassNode) - - PARSE_OPT_BEFORE(Class) - PARSE_OPT_IN(Mapped, MappedFlag); - PARSE_OPT_IN(Derived, DerivatedFlag); - PARSE_END_OPT_BEFORE() - - PARSE_KEYWORD(Class) - PARSE_MARK - PARSE_IDENTIFIER(Name) - PARSE_MARK - - PARSE_OPT(Colon) - PARSE_MARK - PARSE_IDENTIFIER(Inherited) - PARSE_MARK - PARSE_END_OPT - - PARSE_OPT(Key) - PARSE_MARK - PARSE_KEYWORD(OpenParenthesis) - PARSE_MARK - PARSE_IDENTIFIER(ClassKey) - PARSE_MARK - PARSE_KEYWORD(CloseParenthesis) - PARSE_MARK - PARSE_END_OPT - - PARSE_OPT(Implements) - PARSE_MARK - PARSE_IDENTIFIER(Implements) - PARSE_MARK - PARSE_END_OPT - - PARSE_OPT(Reserve) - PARSE_MARK - PARSE_KEYWORD(OpenParenthesis) - PARSE_MARK - PARSE_IDENTIFIER(Reserve) - PARSE_MARK - PARSE_KEYWORD(CloseParenthesis) - PARSE_MARK - PARSE_END_OPT - - PARSE_START_BLOC - - PARSE_MARK - - PARSE_ALTERNATIVE(CppCode) - PARSE_ALTERNATIVE(Declaration) - PARSE_FAIL - - PARSE_MARK - - PARSE_END_BLOC - - PARSE_MARK - -PARSE_END - - -/* - * Declaration Bloc - */ -PARSE_START(Declaration, CDeclarationNode) - - PARSE_OPT_BEFORE_2(Identifier, ScopedIdentifier) - PARSE_OPT_IN(WriteTrigger, WriteTriggerFlag); - PARSE_OPT_IN(InitFill, InitFillFlag); - PARSE_OPT_IN(Parent, ParentFlag); - PARSE_OPT_IN(Hidden, HiddenFlag); - PARSE_OPT_IN(Mirrored, MirroredFlag); - PARSE_END_OPT_BEFORE() - - if (main->ParentFlag) - { - PARSE_IDENTIFIER(ParentClass); - PARSE_MARK - PARSE_KEYWORD(Colon) - PARSE_MARK - PARSE_IDENTIFIER(ParentField); - PARSE_MARK - PARSE_IDENTIFIER(Name); - PARSE_MARK - } - else - { - PARSE_SCOPE_IDF(Type); - PARSE_MARK - - PARSE_OPT(Colon) - PARSE_MARK - PARSE_IDENTIFIER(ForwardRefAttribute); - PARSE_MARK - PARSE_END_OPT - - PARSE_OPT(OpenBracket) - PARSE_MARK - PARSE_IDENTIFIER(ArrayIndex); - PARSE_MARK - main->ArrayFlag = true; - PARSE_KEYWORD(CloseBracket) - PARSE_MARK - - PARSE_IDENTIFIER(Name); - PARSE_MARK - - PARSE_NEXT_OPT(LessThan) - main->SetFlag = true; - PARSE_MARK - PARSE_KEYWORD(GreaterThan) - PARSE_MARK - - PARSE_IDENTIFIER(Name); - PARSE_MARK - - PARSE_LAST_OPT - - PARSE_IDENTIFIER(Name); - PARSE_MARK - - PARSE_OPT(Equal) - //PARSE_VALUE(DefaultValue) - PARSE_KEYWORD_IN(CppCode, DefaultValue) - PARSE_END_OPT - - PARSE_END_OPT - } - - if (tokenizer.current() == TokenOpenBrace) - { - PARSE_START_BLOC - PARSE_MARK - - CDeclarationNode::CUserCode UCode; - - PARSE_KEYWORD_IN_TEMP(Identifier, UCode.Event) - - PARSE_OPT_LIST(OpenParenthesis, CloseParenthesis) - - std::string UCodeAtom; - PARSE_KEYWORD_IN_TEMP(Identifier, UCodeAtom) - if (!UCode.CodeSpecializer.empty()) - UCode.CodeSpecializer += "."; - UCode.CodeSpecializer += UCodeAtom; - - PARSE_END_OPT_LIST(CloseParenthesis, Dot) - - PARSE_KEYWORD_IN_TEMP(CppCode, UCode.UserCode) - - main->UserCodes.push_back(UCode); - - PARSE_MARK - PARSE_END_BLOC - } - else - { - PARSE_KEYWORD(SemiColon); - } - - PARSE_MARK - -PARSE_END - - -/* - * Enum Bloc - */ -PARSE_START(Enum, CEnumNode) - - PARSE_KEYWORD(Enum) - PARSE_MARK - PARSE_IDENTIFIER(Name) - - PARSE_START_LIST(OpenBrace, CloseBrace) - - PARSE_MARK - - PARSE_ALTERNATIVE(EnumRange) - PARSE_ALTERNATIVE(EnumSimpleValue) - PARSE_FAIL - - PARSE_MARK - - PARSE_END_LIST(CloseBrace, Comma) - - PARSE_OPT_KEYWORD_IN(Identifier, EndRange) - - PARSE_MARK - -PARSE_END - -// -PARSE_START(EnumSimpleValue, CEnumSimpleValueNode) - - PARSE_LIST_KEYWORDS(Identifier, Names, Or) - -PARSE_END - -// -PARSE_START(EnumRange, CEnumRangeNode) - - PARSE_IDENTIFIER(Name) - - PARSE_START_LIST(OpenBrace, CloseBrace) - - PARSE_MARK - - PARSE_ALTERNATIVE(EnumRange) - PARSE_ALTERNATIVE(EnumSimpleValue) - PARSE_FAIL - - PARSE_MARK - - PARSE_END_LIST(CloseBrace, Comma) - PARSE_MARK - - PARSE_OPT_KEYWORD_IN(Identifier, EndRange) - - PARSE_MARK - -PARSE_END - - -/* - * Dimension Bloc - */ -PARSE_START(Dimension, CDimensionNode) - - PARSE_KEYWORD(Dimension) - PARSE_MARK - PARSE_IDENTIFIER(Name) - PARSE_MARK - PARSE_INT(Dimension) - PARSE_MARK - PARSE_KEYWORD(SemiColon); - PARSE_MARK - -PARSE_END - - -/* - * LogMsg Bloc - */ -PARSE_START(LogMsg, CLogMsgNode) - - PARSE_KEYWORD(LogMsg) - PARSE_MARK - PARSE_IDENTIFIER(Name) - PARSE_MARK - - PARSE_KEYWORD(OpenParenthesis) - PARSE_MARK - PARSE_LIST_2_KEYWORDS(Identifier, Identifier, Params, Comma) - PARSE_KEYWORD(CloseParenthesis) - PARSE_MARK - - PARSE_KEYWORD(OpenBrace) - PARSE_MARK - PARSE_LIST_KEYWORDS(String, Logs, Comma) - PARSE_MARK - - PARSE_KEYWORD(CloseBrace) - PARSE_MARK - -PARSE_END - -PARSE_START(LogContext, CLogMsgNode) - - PARSE_KEYWORD(LogContext) - PARSE_MARK - PARSE_IDENTIFIER(Name) - PARSE_MARK - - main->Context = true; - - PARSE_KEYWORD(OpenParenthesis) - PARSE_MARK - PARSE_LIST_2_KEYWORDS(Identifier, Identifier, Params, Comma) - PARSE_KEYWORD(CloseParenthesis) - PARSE_MARK - - PARSE_KEYWORD(OpenBrace) - PARSE_MARK - PARSE_LIST_KEYWORDS(String, Logs, Comma) - PARSE_MARK - - PARSE_KEYWORD(CloseBrace) - PARSE_MARK - -PARSE_END - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#include "parser_rules.h" + +/* + * Main Bloc + */ +PARSE_START_NO_DESCRIPTION(Main, CParseNode) + + while (!tokenizer.end()) + { + PARSE_MARK + PARSE_ALTERNATIVE(Db) + PARSE_FAIL + } + +PARSE_END + + +/* + * Db Bloc + */ +PARSE_START(Db, CDbNode) + + PARSE_KEYWORD(Db) + PARSE_MARK + PARSE_IDENTIFIER(Name) + PARSE_MARK + + PARSE_OPT_KEYWORD_IN(String, MainFile); + + PARSE_START_BLOC + + PARSE_MARK + + PARSE_ALTERNATIVE(File) + PARSE_ALTERNATIVE(UsePch) + PARSE_FAIL + + PARSE_MARK + + PARSE_END_BLOC + + PARSE_MARK + +PARSE_END + + +/* + * File Bloc + */ +PARSE_START(File, CFileNode) + + PARSE_OPT_BEFORE(File) + PARSE_OPT_IN(Separated, SeparatedFlag); + PARSE_END_OPT_BEFORE() + + PARSE_KEYWORD(File) + PARSE_MARK + PARSE_STRING(Name) + PARSE_MARK + + main->IncludeAs = main->Name; + + PARSE_OPT_KEYWORD_IN(String, IncludeAs); + + PARSE_START_BLOC + + PARSE_MARK + + PARSE_ALTERNATIVE(Include) + PARSE_ALTERNATIVE(Type) + PARSE_ALTERNATIVE(Class) + PARSE_ALTERNATIVE(Enum) + PARSE_ALTERNATIVE(Dimension) + //PARSE_ALTERNATIVE(CppCode) + PARSE_ALTERNATIVE(LogMsg) + PARSE_ALTERNATIVE(LogContext) + PARSE_FAIL + + PARSE_MARK + + PARSE_END_BLOC + + PARSE_MARK + +PARSE_END + + +/* + * Include Bloc + */ +PARSE_START(Include, CIncludeNode) + + PARSE_KEYWORD(Include) + PARSE_MARK + PARSE_STRING(Name) + PARSE_MARK + +PARSE_END + +/* + * Include Bloc + */ +PARSE_START(UsePch, CUsePchNode) + + PARSE_KEYWORD(UsePch) + PARSE_MARK + PARSE_STRING(Name) + PARSE_MARK + +PARSE_END + + +/* + * Cpp Code Bloc + */ +PARSE_START(CppCode, CCppCodeNode) + + PARSE_OPT_KEYWORD_IN(Identifier, Name) + PARSE_KEYWORD_IN(CppCode, RawCode) + PARSE_MARK + +PARSE_END + + +/* + * Type Bloc + */ +PARSE_START(Type, CTypeNode) + + PARSE_OPT_BEFORE(Type) + PARSE_OPT_IN(Extern, ExternFlag); + PARSE_END_OPT_BEFORE() + + PARSE_KEYWORD(Type) + PARSE_MARK + if (main->ExternFlag) + { + PARSE_SCOPE_IDF(Name) + } + else + { + PARSE_IDENTIFIER(Name) + } + + main->DisplayName = main->Name; + + PARSE_MARK + if (tokenizer.current() == TokenOpenParenthesis) + { + tokenizer.next(); + PARSE_MARK + PARSE_IDENTIFIER(CppType) + PARSE_MARK + PARSE_KEYWORD(Comma) + PARSE_MARK + PARSE_IDENTIFIER(StorageType) + PARSE_MARK + PARSE_KEYWORD(CloseParenthesis) + PARSE_MARK + + if (tokenizer.current() == TokenOpenBrace) + { + tokenizer.next(); + + PARSE_MARK + PARSE_IDENTIFIER(Temp) + if (main->Temp == main->CppType) + { + PARSE_MARK + PARSE_KEYWORD(OpenParenthesis) + PARSE_MARK + PARSE_IDENTIFIER(Temp) + if (main->Temp != main->StorageType) + PARSE_FAIL + PARSE_MARK + PARSE_KEYWORD(CloseParenthesis) + PARSE_MARK + PARSE_NODE(CppCode, ToCppType) + PARSE_MARK + } + else if (main->Temp == main->StorageType) + { + PARSE_MARK + PARSE_KEYWORD(OpenParenthesis) + PARSE_MARK + PARSE_IDENTIFIER(Temp) + if (main->Temp != main->CppType) + PARSE_FAIL + PARSE_MARK + PARSE_KEYWORD(CloseParenthesis) + PARSE_MARK + PARSE_NODE(CppCode, ToStorageType) + PARSE_MARK + } + else + PARSE_FAIL + + if (tokenizer.current() != TokenCloseBrace) + { + PARSE_IDENTIFIER(Temp) + PARSE_MARK + if (main->Temp == main->CppType && main->ToCppType == NULL) + { + PARSE_MARK + PARSE_KEYWORD(OpenParenthesis) + PARSE_MARK + PARSE_IDENTIFIER(Temp) + if (main->Temp != main->StorageType) + PARSE_FAIL + PARSE_MARK + PARSE_KEYWORD(CloseParenthesis) + PARSE_MARK + PARSE_NODE(CppCode, ToCppType) + PARSE_MARK + } + else if (main->Temp == main->StorageType && main->ToStorageType == NULL) + { + PARSE_MARK + PARSE_KEYWORD(OpenParenthesis) + PARSE_MARK + PARSE_IDENTIFIER(Temp) + if (main->Temp != main->CppType) + PARSE_FAIL + PARSE_MARK + PARSE_KEYWORD(CloseParenthesis) + PARSE_MARK + PARSE_NODE(CppCode, ToStorageType) + PARSE_MARK + } + else + PARSE_FAIL + } + + PARSE_KEYWORD(CloseBrace) + } + else + { + PARSE_KEYWORD(SemiColon) + } + } + else + { + PARSE_IDENTIFIER(CppType) + main->StorageType = main->CppType; + PARSE_MARK + PARSE_KEYWORD(SemiColon) + } + + PARSE_MARK + +PARSE_END + + +/* + * Class Bloc + */ +PARSE_START(Class, CClassNode) + + PARSE_OPT_BEFORE(Class) + PARSE_OPT_IN(Mapped, MappedFlag); + PARSE_OPT_IN(Derived, DerivatedFlag); + PARSE_END_OPT_BEFORE() + + PARSE_KEYWORD(Class) + PARSE_MARK + PARSE_IDENTIFIER(Name) + PARSE_MARK + + PARSE_OPT(Colon) + PARSE_MARK + PARSE_IDENTIFIER(Inherited) + PARSE_MARK + PARSE_END_OPT + + PARSE_OPT(Key) + PARSE_MARK + PARSE_KEYWORD(OpenParenthesis) + PARSE_MARK + PARSE_IDENTIFIER(ClassKey) + PARSE_MARK + PARSE_KEYWORD(CloseParenthesis) + PARSE_MARK + PARSE_END_OPT + + PARSE_OPT(Implements) + PARSE_MARK + PARSE_IDENTIFIER(Implements) + PARSE_MARK + PARSE_END_OPT + + PARSE_OPT(Reserve) + PARSE_MARK + PARSE_KEYWORD(OpenParenthesis) + PARSE_MARK + PARSE_IDENTIFIER(Reserve) + PARSE_MARK + PARSE_KEYWORD(CloseParenthesis) + PARSE_MARK + PARSE_END_OPT + + PARSE_START_BLOC + + PARSE_MARK + + PARSE_ALTERNATIVE(CppCode) + PARSE_ALTERNATIVE(Declaration) + PARSE_FAIL + + PARSE_MARK + + PARSE_END_BLOC + + PARSE_MARK + +PARSE_END + + +/* + * Declaration Bloc + */ +PARSE_START(Declaration, CDeclarationNode) + + PARSE_OPT_BEFORE_2(Identifier, ScopedIdentifier) + PARSE_OPT_IN(WriteTrigger, WriteTriggerFlag); + PARSE_OPT_IN(InitFill, InitFillFlag); + PARSE_OPT_IN(Parent, ParentFlag); + PARSE_OPT_IN(Hidden, HiddenFlag); + PARSE_OPT_IN(Mirrored, MirroredFlag); + PARSE_END_OPT_BEFORE() + + if (main->ParentFlag) + { + PARSE_IDENTIFIER(ParentClass); + PARSE_MARK + PARSE_KEYWORD(Colon) + PARSE_MARK + PARSE_IDENTIFIER(ParentField); + PARSE_MARK + PARSE_IDENTIFIER(Name); + PARSE_MARK + } + else + { + PARSE_SCOPE_IDF(Type); + PARSE_MARK + + PARSE_OPT(Colon) + PARSE_MARK + PARSE_IDENTIFIER(ForwardRefAttribute); + PARSE_MARK + PARSE_END_OPT + + PARSE_OPT(OpenBracket) + PARSE_MARK + PARSE_IDENTIFIER(ArrayIndex); + PARSE_MARK + main->ArrayFlag = true; + PARSE_KEYWORD(CloseBracket) + PARSE_MARK + + PARSE_IDENTIFIER(Name); + PARSE_MARK + + PARSE_NEXT_OPT(LessThan) + main->SetFlag = true; + PARSE_MARK + PARSE_KEYWORD(GreaterThan) + PARSE_MARK + + PARSE_IDENTIFIER(Name); + PARSE_MARK + + PARSE_LAST_OPT + + PARSE_IDENTIFIER(Name); + PARSE_MARK + + PARSE_OPT(Equal) + //PARSE_VALUE(DefaultValue) + PARSE_KEYWORD_IN(CppCode, DefaultValue) + PARSE_END_OPT + + PARSE_END_OPT + } + + if (tokenizer.current() == TokenOpenBrace) + { + PARSE_START_BLOC + PARSE_MARK + + CDeclarationNode::CUserCode UCode; + + PARSE_KEYWORD_IN_TEMP(Identifier, UCode.Event) + + PARSE_OPT_LIST(OpenParenthesis, CloseParenthesis) + + std::string UCodeAtom; + PARSE_KEYWORD_IN_TEMP(Identifier, UCodeAtom) + if (!UCode.CodeSpecializer.empty()) + UCode.CodeSpecializer += "."; + UCode.CodeSpecializer += UCodeAtom; + + PARSE_END_OPT_LIST(CloseParenthesis, Dot) + + PARSE_KEYWORD_IN_TEMP(CppCode, UCode.UserCode) + + main->UserCodes.push_back(UCode); + + PARSE_MARK + PARSE_END_BLOC + } + else + { + PARSE_KEYWORD(SemiColon); + } + + PARSE_MARK + +PARSE_END + + +/* + * Enum Bloc + */ +PARSE_START(Enum, CEnumNode) + + PARSE_KEYWORD(Enum) + PARSE_MARK + PARSE_IDENTIFIER(Name) + + PARSE_START_LIST(OpenBrace, CloseBrace) + + PARSE_MARK + + PARSE_ALTERNATIVE(EnumRange) + PARSE_ALTERNATIVE(EnumSimpleValue) + PARSE_FAIL + + PARSE_MARK + + PARSE_END_LIST(CloseBrace, Comma) + + PARSE_OPT_KEYWORD_IN(Identifier, EndRange) + + PARSE_MARK + +PARSE_END + +// +PARSE_START(EnumSimpleValue, CEnumSimpleValueNode) + + PARSE_LIST_KEYWORDS(Identifier, Names, Or) + +PARSE_END + +// +PARSE_START(EnumRange, CEnumRangeNode) + + PARSE_IDENTIFIER(Name) + + PARSE_START_LIST(OpenBrace, CloseBrace) + + PARSE_MARK + + PARSE_ALTERNATIVE(EnumRange) + PARSE_ALTERNATIVE(EnumSimpleValue) + PARSE_FAIL + + PARSE_MARK + + PARSE_END_LIST(CloseBrace, Comma) + PARSE_MARK + + PARSE_OPT_KEYWORD_IN(Identifier, EndRange) + + PARSE_MARK + +PARSE_END + + +/* + * Dimension Bloc + */ +PARSE_START(Dimension, CDimensionNode) + + PARSE_KEYWORD(Dimension) + PARSE_MARK + PARSE_IDENTIFIER(Name) + PARSE_MARK + PARSE_INT(Dimension) + PARSE_MARK + PARSE_KEYWORD(SemiColon); + PARSE_MARK + +PARSE_END + + +/* + * LogMsg Bloc + */ +PARSE_START(LogMsg, CLogMsgNode) + + PARSE_KEYWORD(LogMsg) + PARSE_MARK + PARSE_IDENTIFIER(Name) + PARSE_MARK + + PARSE_KEYWORD(OpenParenthesis) + PARSE_MARK + PARSE_LIST_2_KEYWORDS(Identifier, Identifier, Params, Comma) + PARSE_KEYWORD(CloseParenthesis) + PARSE_MARK + + PARSE_KEYWORD(OpenBrace) + PARSE_MARK + PARSE_LIST_KEYWORDS(String, Logs, Comma) + PARSE_MARK + + PARSE_KEYWORD(CloseBrace) + PARSE_MARK + +PARSE_END + +PARSE_START(LogContext, CLogMsgNode) + + PARSE_KEYWORD(LogContext) + PARSE_MARK + PARSE_IDENTIFIER(Name) + PARSE_MARK + + main->Context = true; + + PARSE_KEYWORD(OpenParenthesis) + PARSE_MARK + PARSE_LIST_2_KEYWORDS(Identifier, Identifier, Params, Comma) + PARSE_KEYWORD(CloseParenthesis) + PARSE_MARK + + PARSE_KEYWORD(OpenBrace) + PARSE_MARK + PARSE_LIST_KEYWORDS(String, Logs, Comma) + PARSE_MARK + + PARSE_KEYWORD(CloseBrace) + PARSE_MARK + +PARSE_END + diff --git a/code/ryzom/tools/pd_parser/parser_rules.h b/code/ryzom/tools/pd_parser/parser_rules.h index a5840504e..9fbc28899 100644 --- a/code/ryzom/tools/pd_parser/parser_rules.h +++ b/code/ryzom/tools/pd_parser/parser_rules.h @@ -1,416 +1,416 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef RY_PD_PARSE_RULES_H -#define RY_PD_PARSE_RULES_H - -#include "parse_node.h" - -#define DECLARE_PARSE(nodename) CParseNode *parse##nodename(CTokenizer &tokenizer); - - -DECLARE_PARSE(Main) -DECLARE_PARSE(File) -DECLARE_PARSE(Include) -DECLARE_PARSE(UsePch) -DECLARE_PARSE(Db) -DECLARE_PARSE(CppCode) -DECLARE_PARSE(Type) -DECLARE_PARSE(Class) -DECLARE_PARSE(Declaration) -DECLARE_PARSE(Enum) -DECLARE_PARSE(EnumSimpleValue) -DECLARE_PARSE(EnumRange) -DECLARE_PARSE(Dimension) -DECLARE_PARSE(LogMsg) -DECLARE_PARSE(LogContext) - - - -/* - * Parser Help Macros - */ - -/* - * Start node parsing without optional description - * PARSE_START_NO_DESCRIPTION(Main, CParseNode) - * - * ... - * - * PARSE_END - */ -#define PARSE_START_NO_DESCRIPTION(nodename, nodetype) \ -CParseNode *parse##nodename(CTokenizer &tokenizer) \ -{ \ - tokenizer.push(); \ - nodetype *main = new nodetype(); \ - main->StartToken = tokenizer.currentToken(); \ - CParseNode *parsed; \ - parsed = NULL; - -#define PARSE_END \ - return main; \ -} - - -/* - * Start node parsing with optional description - * PARSE_START(Main, CParseNode) - * - * ... - * - * PARSE_END - */ -#define PARSE_START(nodename, nodetype) \ -CParseNode *parse##nodename(CTokenizer &tokenizer) \ -{ \ - tokenizer.push(); \ - nodetype *main = new nodetype(); \ - main->StartToken = tokenizer.currentToken(); \ - CParseNode *parsed; \ - parsed = NULL; \ - PARSE_OPT_KEYWORD_IN(Description, Description) - - -/* - * Lock parsing to the current token. If parse fail later, this will cause - * parser to generate an error after this token. - * PARSE_KEYWORD(Colon) - * PARSE_MARK - */ -#define PARSE_MARK tokenizer.leaveMark(); - - - -/* - * Force the parser to fail and leave current node - */ -#define PARSE_FAIL \ - { \ - delete main; \ - tokenizer.pop(); \ - return NULL; \ - } - -/* - * Parse a given token - * PARSE_KEYWORD(Extern) - */ -#define PARSE_KEYWORD(keyword) \ - { \ - if (tokenizer.end() || tokenizer.current() != Token##keyword) \ - PARSE_FAIL \ - tokenizer.next(); \ - } - -/* - * Parse a token and store value into a string - * PARSE_KEYWORD_IN_TEMP(Identifier, Name) - */ -#define PARSE_KEYWORD_IN_TEMP(keyword, temp) \ - { \ - if (tokenizer.end() || tokenizer.current() != Token##keyword) \ - PARSE_FAIL \ - temp = tokenizer.get(tokenizer.currentToken()); \ - tokenizer.next(); \ - } - -/* - * Parse a token and store value into a node string attribute - * PARSE_KEYWORD_IN(Identifier, Name) where Name is an attribute of the current node - */ -#define PARSE_KEYWORD_IN(keyword, savein) PARSE_KEYWORD_IN_TEMP(keyword, main->savein) - -/* - * Parse a token and push value into a vector of string of the current node - * PARSE_ADD_KEYWORD_IN(Identifier, Names) where Names is a vector of the node - */ -#define PARSE_ADD_KEYWORD_IN(keyword, savein) \ - { \ - if (tokenizer.end() || tokenizer.current() != Token##keyword) \ - PARSE_FAIL \ - main->savein.push_back(tokenizer.get(tokenizer.currentToken())); \ - tokenizer.next(); \ - } - -/* - * Parse a couple of 2 tokens and push them as string into a vector of pair of string of the current node - * PARSE_ADD_2_KEYWORD_IN(Identifier, Identifier, Prototype) where Prototype is a vector > of the node - */ -#define PARSE_ADD_2_KEYWORD_IN(keyword1, keyword2, savein) \ - { \ - if (tokenizer.end() || tokenizer.current() != Token##keyword1) \ - PARSE_FAIL \ - CTokenizer::CToken t1 = tokenizer.currentToken(); \ - tokenizer.next(); \ - if (tokenizer.end() || tokenizer.current() != Token##keyword2) \ - PARSE_FAIL \ - CTokenizer::CToken t2 = tokenizer.currentToken(); \ - tokenizer.next(); \ - main->savein.push_back(std::make_pair(tokenizer.get(t1), tokenizer.get(t2))); \ - } - -/* - * Parse a string into a attribute of the node - * PARSE_STRING(FileName) - */ -#define PARSE_STRING(savein) PARSE_KEYWORD_IN(String, savein) - -/* - * Parse a scoped identifier and store value into an attribute of the node - * PARSE_SCOPE_IDF(ScopedType) where a scoped identifier may be of the form 'Identifier' or 'Identifier::Identifier' - */ -#define PARSE_SCOPE_IDF(savein) \ - { \ - if (tokenizer.end() || (tokenizer.current() != TokenIdentifier && tokenizer.current() != TokenScopedIdentifier)) \ - PARSE_FAIL \ - main->savein = tokenizer.get(tokenizer.currentToken()); \ - tokenizer.next(); \ - } - - -/* - * Parse a single Identifier into a node'a attribute - * PARSE_IDENTIFIER(Name) - */ -#define PARSE_IDENTIFIER(savein) PARSE_KEYWORD_IN(Identifier, savein) - -/* - * Parse a single Identifier and push it to a vector - * PARSE_ADD_IDENTIFIER(Names) - */ -#define PARSE_ADD_IDENTIFIER(savein) PARSE_ADD_KEYWORD_IN(Identifier, savein) - -/* - * Parse a integer and store value (as int) - * PARSE_INT(DefaultIntValue) - */ -#define PARSE_INT(savein) \ - { \ - if (tokenizer.end() || tokenizer.current() != TokenNumber) \ - PARSE_FAIL \ - NLMISC::fromString(tokenizer.get(tokenizer.currentToken()), main->savein); \ - tokenizer.next(); \ - } - -/* - * Parse a value, which may be a string or a number (float/int), and store it as a string - * PARSE_VALUE(DefaultValue) - */ -#define PARSE_VALUE(savein) \ - { \ - if (tokenizer.end() || (tokenizer.current() != TokenIdentifier && tokenizer.current() != TokenNumber && tokenizer.current() != TokenString)) \ - PARSE_FAIL \ - main->savein = tokenizer.get(tokenizer.currentToken()); \ - tokenizer.next(); \ - } - - - - -/* - * Start a bloc of alternative bloc to examine. Parser will examine first alternative, and if parsing fails - * it will examine the second alternative. Usually alternative bloc is ended by a PARSE_FAIL so parsing may examine - * previous following rules... - * PARSE_ALTERNATIVE(Include) - * PARSE_ALTERNATIVE(Type) - * PARSE_ALTERNATIVE(Class) - * PARSE_FAIL // parsing fails if neither Include can be parsed nor Type nor Class - */ -#define PARSE_ALTERNATIVE(nodename) \ - if ( (parsed = parse##nodename(tokenizer)) ) \ - { \ - parsed->Parent = main; \ - main->Nodes.push_back(parsed); \ - } \ - else - -/* - * End a bloc of alternative without failing, usually to allow parsing of optionnal node blocs - */ -#define PARSE_END_ALTERNATIVE() \ - {} - -/* - * Parse a node. This is not an alternative, if node parsing fails, current node parsing fails - * PARSE_NODE(Include) - */ -#define PARSE_NODE(nodename, savein) \ - if ( (main->savein = parse##nodename(tokenizer)) ) \ - { \ - main->savein->Parent = main; \ - } \ - else \ - PARSE_FAIL - - - - -/* - * Start a bloc with '{' - */ -#define PARSE_START_BLOC \ - PARSE_KEYWORD(OpenBrace) \ - while (!tokenizer.end() && tokenizer.current() != TokenCloseBrace) \ - { - -/* - * End a bloc with '}' - */ -#define PARSE_END_BLOC \ - } \ - PARSE_KEYWORD(CloseBrace) - - - -/* - * Parse a list of tokens (unknown yet) separated by special tokens - * PARSE_START_LIST(OpenParenthesis, CloseParenthesis) - * PARSE_ADD_KEYWORD_IN(Identifier, Names) - * PARSE_END_LIST(CloseParenthesis, Comma) - */ -#define PARSE_START_LIST(starttoken, endtoken) \ - PARSE_KEYWORD(starttoken) \ - while (!tokenizer.end() && tokenizer.current() != Token##endtoken) \ - { - -#define PARSE_END_LIST(endtoken, separator) \ - if (tokenizer.end() || tokenizer.current() != Token##separator) \ - break; \ - tokenizer.next(); \ - } \ - PARSE_KEYWORD(endtoken) - - -/* - * Parse an optionnal list, see also PARSE_START_LIST/PARSE_END_LIST - */ -#define PARSE_OPT_LIST(starttoken, endtoken) \ - if (!tokenizer.end() && tokenizer.current() == Token##starttoken) \ - { \ - PARSE_START_LIST(starttoken, endtoken) - -#define PARSE_END_OPT_LIST(endtoken, separator) \ - PARSE_END_LIST(endtoken, separator) \ - } - - -/* - * Repeat parsing between PARSE_OPT_BEFORE and PARSE_END_OPT_BEFORE while next token is not reached - * To be used with PARSE_OPT_IN - * PARSE_OPT_BEFORE(Class) - * PARSE_OPT_IN(Mapped, MappedFlag); - * PARSE_OPT_IN(Derived, DerivedFlag); - * PARSE_END_OPT_BEFORE() - */ -#define PARSE_OPT_BEFORE(token) \ - while (!tokenizer.end() && tokenizer.current() != Token##token) \ - { \ - switch (tokenizer.current()) \ - { - -#define PARSE_OPT_BEFORE_2(token1, token2) \ - while (!tokenizer.end() && tokenizer.current() != Token##token1 && tokenizer.current() != Token##token2) \ - { \ - switch (tokenizer.current()) \ - { - -#define PARSE_OPT_IN(token, flag) \ - case Token##token: \ - if (!main->flag) \ - { \ - main->flag = true; \ - } \ - else \ - { \ - PARSE_FAIL \ - } \ - break; - -#define PARSE_END_OPT_BEFORE() \ - default: \ - PARSE_FAIL \ - break; \ - } \ - tokenizer.next(); \ - } - - -/* - * Parse a list of keywork separated by a given token, and store them into a vector - * see also PARSE_ADD_KEYWORD_IN - */ -#define PARSE_LIST_KEYWORDS(keyword, savein, separator) \ - PARSE_ADD_KEYWORD_IN(keyword, savein) \ - while (!tokenizer.end() && tokenizer.current() == Token##separator) \ - { \ - tokenizer.next(); \ - PARSE_ADD_KEYWORD_IN(keyword, savein) \ - } - -/* - * PArse a list of couple of 2 keywords and store them into a vector > - * see also PARSE_ADD_2_KEYWORD_IN - */ -#define PARSE_LIST_2_KEYWORDS(keyword1, keyword2, savein, separator) \ - PARSE_ADD_2_KEYWORD_IN(keyword1, keyword2, savein) \ - while (!tokenizer.end() && tokenizer.current() == Token##separator) \ - { \ - tokenizer.next(); \ - PARSE_ADD_2_KEYWORD_IN(keyword1, keyword2, savein) \ - } - -#define PARSE_LIST_IDENTIFIERS(starttoken, separator, endtoken, savein) \ - PARSE_START_LIST(starttoken, endtoken) \ - PARSE_ADD_IDENTIFIER(savein) \ - PARSE_END_LIST(endtoken, separator) - - - - - -#define PARSE_OPT(opttoken) \ - if (!tokenizer.end() && tokenizer.current() == Token##opttoken) \ - { \ - tokenizer.next(); \ - -#define PARSE_NEXT_OPT(opttoken) \ - } \ - else if (!tokenizer.end() && tokenizer.current() == Token##opttoken) \ - { \ - tokenizer.next(); \ - -#define PARSE_LAST_OPT \ - } \ - else \ - { - -#define PARSE_END_OPT \ - } - - - -#define PARSE_OPT_KEYWORD_IN(keyword, savein) \ - { \ - if (!tokenizer.end() && tokenizer.current() == Token##keyword) \ - { \ - main->savein = tokenizer.get(tokenizer.currentToken()); \ - tokenizer.next(); \ - } \ - } - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef RY_PD_PARSE_RULES_H +#define RY_PD_PARSE_RULES_H + +#include "parse_node.h" + +#define DECLARE_PARSE(nodename) CParseNode *parse##nodename(CTokenizer &tokenizer); + + +DECLARE_PARSE(Main) +DECLARE_PARSE(File) +DECLARE_PARSE(Include) +DECLARE_PARSE(UsePch) +DECLARE_PARSE(Db) +DECLARE_PARSE(CppCode) +DECLARE_PARSE(Type) +DECLARE_PARSE(Class) +DECLARE_PARSE(Declaration) +DECLARE_PARSE(Enum) +DECLARE_PARSE(EnumSimpleValue) +DECLARE_PARSE(EnumRange) +DECLARE_PARSE(Dimension) +DECLARE_PARSE(LogMsg) +DECLARE_PARSE(LogContext) + + + +/* + * Parser Help Macros + */ + +/* + * Start node parsing without optional description + * PARSE_START_NO_DESCRIPTION(Main, CParseNode) + * + * ... + * + * PARSE_END + */ +#define PARSE_START_NO_DESCRIPTION(nodename, nodetype) \ +CParseNode *parse##nodename(CTokenizer &tokenizer) \ +{ \ + tokenizer.push(); \ + nodetype *main = new nodetype(); \ + main->StartToken = tokenizer.currentToken(); \ + CParseNode *parsed; \ + parsed = NULL; + +#define PARSE_END \ + return main; \ +} + + +/* + * Start node parsing with optional description + * PARSE_START(Main, CParseNode) + * + * ... + * + * PARSE_END + */ +#define PARSE_START(nodename, nodetype) \ +CParseNode *parse##nodename(CTokenizer &tokenizer) \ +{ \ + tokenizer.push(); \ + nodetype *main = new nodetype(); \ + main->StartToken = tokenizer.currentToken(); \ + CParseNode *parsed; \ + parsed = NULL; \ + PARSE_OPT_KEYWORD_IN(Description, Description) + + +/* + * Lock parsing to the current token. If parse fail later, this will cause + * parser to generate an error after this token. + * PARSE_KEYWORD(Colon) + * PARSE_MARK + */ +#define PARSE_MARK tokenizer.leaveMark(); + + + +/* + * Force the parser to fail and leave current node + */ +#define PARSE_FAIL \ + { \ + delete main; \ + tokenizer.pop(); \ + return NULL; \ + } + +/* + * Parse a given token + * PARSE_KEYWORD(Extern) + */ +#define PARSE_KEYWORD(keyword) \ + { \ + if (tokenizer.end() || tokenizer.current() != Token##keyword) \ + PARSE_FAIL \ + tokenizer.next(); \ + } + +/* + * Parse a token and store value into a string + * PARSE_KEYWORD_IN_TEMP(Identifier, Name) + */ +#define PARSE_KEYWORD_IN_TEMP(keyword, temp) \ + { \ + if (tokenizer.end() || tokenizer.current() != Token##keyword) \ + PARSE_FAIL \ + temp = tokenizer.get(tokenizer.currentToken()); \ + tokenizer.next(); \ + } + +/* + * Parse a token and store value into a node string attribute + * PARSE_KEYWORD_IN(Identifier, Name) where Name is an attribute of the current node + */ +#define PARSE_KEYWORD_IN(keyword, savein) PARSE_KEYWORD_IN_TEMP(keyword, main->savein) + +/* + * Parse a token and push value into a vector of string of the current node + * PARSE_ADD_KEYWORD_IN(Identifier, Names) where Names is a vector of the node + */ +#define PARSE_ADD_KEYWORD_IN(keyword, savein) \ + { \ + if (tokenizer.end() || tokenizer.current() != Token##keyword) \ + PARSE_FAIL \ + main->savein.push_back(tokenizer.get(tokenizer.currentToken())); \ + tokenizer.next(); \ + } + +/* + * Parse a couple of 2 tokens and push them as string into a vector of pair of string of the current node + * PARSE_ADD_2_KEYWORD_IN(Identifier, Identifier, Prototype) where Prototype is a vector > of the node + */ +#define PARSE_ADD_2_KEYWORD_IN(keyword1, keyword2, savein) \ + { \ + if (tokenizer.end() || tokenizer.current() != Token##keyword1) \ + PARSE_FAIL \ + CTokenizer::CToken t1 = tokenizer.currentToken(); \ + tokenizer.next(); \ + if (tokenizer.end() || tokenizer.current() != Token##keyword2) \ + PARSE_FAIL \ + CTokenizer::CToken t2 = tokenizer.currentToken(); \ + tokenizer.next(); \ + main->savein.push_back(std::make_pair(tokenizer.get(t1), tokenizer.get(t2))); \ + } + +/* + * Parse a string into a attribute of the node + * PARSE_STRING(FileName) + */ +#define PARSE_STRING(savein) PARSE_KEYWORD_IN(String, savein) + +/* + * Parse a scoped identifier and store value into an attribute of the node + * PARSE_SCOPE_IDF(ScopedType) where a scoped identifier may be of the form 'Identifier' or 'Identifier::Identifier' + */ +#define PARSE_SCOPE_IDF(savein) \ + { \ + if (tokenizer.end() || (tokenizer.current() != TokenIdentifier && tokenizer.current() != TokenScopedIdentifier)) \ + PARSE_FAIL \ + main->savein = tokenizer.get(tokenizer.currentToken()); \ + tokenizer.next(); \ + } + + +/* + * Parse a single Identifier into a node'a attribute + * PARSE_IDENTIFIER(Name) + */ +#define PARSE_IDENTIFIER(savein) PARSE_KEYWORD_IN(Identifier, savein) + +/* + * Parse a single Identifier and push it to a vector + * PARSE_ADD_IDENTIFIER(Names) + */ +#define PARSE_ADD_IDENTIFIER(savein) PARSE_ADD_KEYWORD_IN(Identifier, savein) + +/* + * Parse a integer and store value (as int) + * PARSE_INT(DefaultIntValue) + */ +#define PARSE_INT(savein) \ + { \ + if (tokenizer.end() || tokenizer.current() != TokenNumber) \ + PARSE_FAIL \ + NLMISC::fromString(tokenizer.get(tokenizer.currentToken()), main->savein); \ + tokenizer.next(); \ + } + +/* + * Parse a value, which may be a string or a number (float/int), and store it as a string + * PARSE_VALUE(DefaultValue) + */ +#define PARSE_VALUE(savein) \ + { \ + if (tokenizer.end() || (tokenizer.current() != TokenIdentifier && tokenizer.current() != TokenNumber && tokenizer.current() != TokenString)) \ + PARSE_FAIL \ + main->savein = tokenizer.get(tokenizer.currentToken()); \ + tokenizer.next(); \ + } + + + + +/* + * Start a bloc of alternative bloc to examine. Parser will examine first alternative, and if parsing fails + * it will examine the second alternative. Usually alternative bloc is ended by a PARSE_FAIL so parsing may examine + * previous following rules... + * PARSE_ALTERNATIVE(Include) + * PARSE_ALTERNATIVE(Type) + * PARSE_ALTERNATIVE(Class) + * PARSE_FAIL // parsing fails if neither Include can be parsed nor Type nor Class + */ +#define PARSE_ALTERNATIVE(nodename) \ + if ( (parsed = parse##nodename(tokenizer)) ) \ + { \ + parsed->Parent = main; \ + main->Nodes.push_back(parsed); \ + } \ + else + +/* + * End a bloc of alternative without failing, usually to allow parsing of optionnal node blocs + */ +#define PARSE_END_ALTERNATIVE() \ + {} + +/* + * Parse a node. This is not an alternative, if node parsing fails, current node parsing fails + * PARSE_NODE(Include) + */ +#define PARSE_NODE(nodename, savein) \ + if ( (main->savein = parse##nodename(tokenizer)) ) \ + { \ + main->savein->Parent = main; \ + } \ + else \ + PARSE_FAIL + + + + +/* + * Start a bloc with '{' + */ +#define PARSE_START_BLOC \ + PARSE_KEYWORD(OpenBrace) \ + while (!tokenizer.end() && tokenizer.current() != TokenCloseBrace) \ + { + +/* + * End a bloc with '}' + */ +#define PARSE_END_BLOC \ + } \ + PARSE_KEYWORD(CloseBrace) + + + +/* + * Parse a list of tokens (unknown yet) separated by special tokens + * PARSE_START_LIST(OpenParenthesis, CloseParenthesis) + * PARSE_ADD_KEYWORD_IN(Identifier, Names) + * PARSE_END_LIST(CloseParenthesis, Comma) + */ +#define PARSE_START_LIST(starttoken, endtoken) \ + PARSE_KEYWORD(starttoken) \ + while (!tokenizer.end() && tokenizer.current() != Token##endtoken) \ + { + +#define PARSE_END_LIST(endtoken, separator) \ + if (tokenizer.end() || tokenizer.current() != Token##separator) \ + break; \ + tokenizer.next(); \ + } \ + PARSE_KEYWORD(endtoken) + + +/* + * Parse an optionnal list, see also PARSE_START_LIST/PARSE_END_LIST + */ +#define PARSE_OPT_LIST(starttoken, endtoken) \ + if (!tokenizer.end() && tokenizer.current() == Token##starttoken) \ + { \ + PARSE_START_LIST(starttoken, endtoken) + +#define PARSE_END_OPT_LIST(endtoken, separator) \ + PARSE_END_LIST(endtoken, separator) \ + } + + +/* + * Repeat parsing between PARSE_OPT_BEFORE and PARSE_END_OPT_BEFORE while next token is not reached + * To be used with PARSE_OPT_IN + * PARSE_OPT_BEFORE(Class) + * PARSE_OPT_IN(Mapped, MappedFlag); + * PARSE_OPT_IN(Derived, DerivedFlag); + * PARSE_END_OPT_BEFORE() + */ +#define PARSE_OPT_BEFORE(token) \ + while (!tokenizer.end() && tokenizer.current() != Token##token) \ + { \ + switch (tokenizer.current()) \ + { + +#define PARSE_OPT_BEFORE_2(token1, token2) \ + while (!tokenizer.end() && tokenizer.current() != Token##token1 && tokenizer.current() != Token##token2) \ + { \ + switch (tokenizer.current()) \ + { + +#define PARSE_OPT_IN(token, flag) \ + case Token##token: \ + if (!main->flag) \ + { \ + main->flag = true; \ + } \ + else \ + { \ + PARSE_FAIL \ + } \ + break; + +#define PARSE_END_OPT_BEFORE() \ + default: \ + PARSE_FAIL \ + break; \ + } \ + tokenizer.next(); \ + } + + +/* + * Parse a list of keywork separated by a given token, and store them into a vector + * see also PARSE_ADD_KEYWORD_IN + */ +#define PARSE_LIST_KEYWORDS(keyword, savein, separator) \ + PARSE_ADD_KEYWORD_IN(keyword, savein) \ + while (!tokenizer.end() && tokenizer.current() == Token##separator) \ + { \ + tokenizer.next(); \ + PARSE_ADD_KEYWORD_IN(keyword, savein) \ + } + +/* + * PArse a list of couple of 2 keywords and store them into a vector > + * see also PARSE_ADD_2_KEYWORD_IN + */ +#define PARSE_LIST_2_KEYWORDS(keyword1, keyword2, savein, separator) \ + PARSE_ADD_2_KEYWORD_IN(keyword1, keyword2, savein) \ + while (!tokenizer.end() && tokenizer.current() == Token##separator) \ + { \ + tokenizer.next(); \ + PARSE_ADD_2_KEYWORD_IN(keyword1, keyword2, savein) \ + } + +#define PARSE_LIST_IDENTIFIERS(starttoken, separator, endtoken, savein) \ + PARSE_START_LIST(starttoken, endtoken) \ + PARSE_ADD_IDENTIFIER(savein) \ + PARSE_END_LIST(endtoken, separator) + + + + + +#define PARSE_OPT(opttoken) \ + if (!tokenizer.end() && tokenizer.current() == Token##opttoken) \ + { \ + tokenizer.next(); \ + +#define PARSE_NEXT_OPT(opttoken) \ + } \ + else if (!tokenizer.end() && tokenizer.current() == Token##opttoken) \ + { \ + tokenizer.next(); \ + +#define PARSE_LAST_OPT \ + } \ + else \ + { + +#define PARSE_END_OPT \ + } + + + +#define PARSE_OPT_KEYWORD_IN(keyword, savein) \ + { \ + if (!tokenizer.end() && tokenizer.current() == Token##keyword) \ + { \ + main->savein = tokenizer.get(tokenizer.currentToken()); \ + tokenizer.next(); \ + } \ + } + +#endif diff --git a/code/ryzom/tools/pd_parser/templatizer.cpp b/code/ryzom/tools/pd_parser/templatizer.cpp index 862956abd..cb392ad27 100644 --- a/code/ryzom/tools/pd_parser/templatizer.cpp +++ b/code/ryzom/tools/pd_parser/templatizer.cpp @@ -1,556 +1,556 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "templatizer.h" - - - -bool isBlocStart(CTemplatizerParser t) { return (t.isValid() && t[0] == '{' && t[1] == '{'); } -bool isBlocEnd(CTemplatizerParser t) { return (t.isValid() && t[0] == '}' && t[1] == '}'); } - -enum TTemplatizerToken -{ - BlocStart, - BlocEnd, - OpenParenth, - CloseParenth, - Equal, - Comma, - Arobace, - Dollar, - Quote, - CommentStart, - CommentEnd, - Identifier, - ListIdentifier, - - Unknown -}; - -struct SToken -{ - TTemplatizerToken Token; - const char* Text; -}; - -SToken SimpleTokens[] = -{ - { BlocStart, "{" }, - { BlocEnd, "}" }, - { OpenParenth, "(" }, - { CloseParenth, ")" }, - { Equal, "=" }, - { Arobace, "@" }, - { Dollar, "$" }, - { Comma, "," }, - { Quote, "\"" }, - { CommentStart, "/*" }, - { CommentEnd, "*/" }, -}; - -CTemplatizerParser skipSpace(CTemplatizerParser t) -{ - while (t.isValid() && *t != '\0' && isspace(*t)) - ++t; - return t; -} - -const char* skipSpace(const char* t) -{ - while (t != NULL && *t != '\0' && isspace(*t)) - ++t; - return t; -} - -CTemplatizerParser match(const char* keyword, CTemplatizerParser match) -{ - while (*keyword != '\0' && *match != '\0' && *keyword == *match) - { - ++keyword; - ++match; - } - - return *keyword == '\0' ? match : CTemplatizerParser(); -} - -TTemplatizerToken getToken(CTemplatizerParser& t, bool skipspc, std::string* value = NULL) -{ - if (skipspc) - t = skipSpace(t); - - if (!t.isValid()) - return Unknown; - - uint i; - CTemplatizerParser result; - for (i=0; ieval(RootEnv); - else - return ""; -} - - - - - - - - -/* - * Parse bloc - */ -ITemplatizerBloc* ITemplatizerBloc::parseBloc(CTemplatizerParser& ptr) -{ - std::string blocType; - ITemplatizerBloc* bloc = NULL; - - if (popToken(ptr, Identifier, true, &blocType) || popToken(ptr, ListIdentifier, true, &blocType)) - { - if (blocType == "root") bloc = new CTemplatizerRootBloc(); - else if (blocType == "sub") bloc = new CTemplatizerSubBloc(); - else if (blocType == "loop") bloc = new CTemplatizerLoopBloc(); - else if (blocType == "ifdefenv") bloc = new CTemplatizerIfDefEnvBloc(); - else if (blocType == "ifdef") bloc = new CTemplatizerIfDefBloc(); - else if (blocType == "ifnotdefenv") bloc = new CTemplatizerIfNotDefEnvBloc(); - else if (blocType == "ifnotdef") bloc = new CTemplatizerIfNotDefBloc(); - else if (blocType == "switch") bloc = new CTemplatizerSwitchBloc(); - else if (blocType == "file") bloc = new CTemplatizerFileBloc(); - else if (blocType == "set") bloc = new CTemplatizerSetBloc(); - else if (blocType == "append") bloc = new CTemplatizerAppendBloc(); - else if (blocType == "define") bloc = new CTemplatizerDefineBloc(); - else if (blocType == "if") bloc = new CTemplatizerIfBloc(); - else if (blocType == "ifnot") bloc = new CTemplatizerIfNotBloc(); - else if (blocType == "join") bloc = new CTemplatizerJoinBloc(); - else if (blocType == "class") bloc = new CTemplatizerClassBloc(); - else if (blocType == "object") bloc = new CTemplatizerObjectBloc(); - else if (blocType == "ref") bloc = new CTemplatizerReferenceBloc(); - else if (blocType == "refenv") bloc = new CTemplatizerRefEnvBloc(); - else if (blocType == "breakpoint") bloc = new CTemplatizerBreakpointBloc(); - else bloc = new CTemplatizerUserFunctionBloc(blocType); - - if (bloc == NULL) - { - nlwarning("Templatizer: failed to decode bloc '%s' at line %d", blocType.c_str(), ptr.getLine()); - return NULL; - } - - ptr = bloc->parseHeader(ptr); - - if (!ptr.isValid()) - { - nlwarning("Templatizer: failed to decode header of bloc '%s' at line %d", blocType.c_str(), ptr.getLine()); - delete bloc; - return NULL; - } - - if (bloc->hasInternal()) - { - if (!popToken(ptr, BlocStart, true)) - { - nlwarning("Templatizer: failed to decode start of bloc '%s' at line %d", blocType.c_str(), ptr.getLine()); - delete bloc; - return NULL; - } - - ptr = bloc->parseInternal(ptr); - - if (!ptr.isValid()) - { - nlwarning("Templatizer: failed to parse bloc '%s' at line %d", blocType.c_str(), ptr.getLine()); - delete bloc; - return NULL; - } - - if (!popToken(ptr, BlocEnd, true)) - { - nlwarning("Templatizer: failed to decode end of bloc '%s' at line %d", blocType.c_str(), ptr.getLine()); - delete bloc; - return NULL; - } - } - } - else if (isNextToken(ptr, CommentStart, true)) - { - bloc = new CTemplatizerCommentBloc(); - ptr = bloc->parseInternal(ptr); - if (!ptr.isValid()) - nlwarning("Templatizer: failed to parse bloc 'Comment' at line %d", ptr.getLine()); - } - else if (isNextToken(ptr, Quote, true)) - { - bloc = new CTemplatizerTextBloc(); - ptr = bloc->parseInternal(ptr); - if (!ptr.isValid()) - nlwarning("Templatizer: failed to parse bloc 'Text' at line %d", ptr.getLine()); - } - - if (!ptr.isValid()) - { - delete bloc; - return NULL; - } - - return bloc; -} - -/* - * Parse bloc header - */ -CTemplatizerParser ITemplatizerBloc::parseHeader(CTemplatizerParser ptr) -{ - if (popToken(ptr, OpenParenth, true)) - { - uint currentDefArg = 0; - const char** args = getDefParamList(); - - if (popToken(ptr, CloseParenth, true)) - return ptr; - - do - { - std::string paramName; - if (!popToken(ptr, Identifier, true, ¶mName)) - { - if (args == NULL || args[currentDefArg] == NULL) - { - ptr.invalidate(); - return ptr; - } - - paramName = args[currentDefArg++]; - } - else - { - if (!popToken(ptr, Equal, true)) - { - ptr.invalidate(); - return ptr; - } - } - - ITemplatizerBloc* bloc = parseBloc(ptr); - - if (bloc == NULL) - { - ptr.invalidate(); - return ptr; - } - - Params[paramName] = bloc; - - if (!popToken(ptr, Comma, true)) - break; - } - while (true); - - if (!popToken(ptr, CloseParenth, true)) - { - ptr.invalidate(); - return ptr; - } - } - - return ptr; -} - - -/* - * Parse bloc internal data - */ -CTemplatizerParser ITemplatizerBloc::parseInternal(CTemplatizerParser ptr) -{ - ITemplatizerBloc* bloc = NULL; - do - { - bloc = parseBloc(ptr); - - if (bloc != NULL) - Blocs.push_back(bloc); - } - while (bloc != NULL && *ptr != '\0' && !isBlocEnd(ptr)); - - return ptr; -} - - -/* - * Parse bloc internal data - */ -CTemplatizerParser CTemplatizerTextBloc::parseInternal(CTemplatizerParser ptr) -{ - Text = ""; - - ptr = skipSpace(ptr); - - if (*ptr != '"') - return CTemplatizerParser(); - - ++ptr; - - while (*ptr != '\0' && *ptr != '"') - { - if (*ptr == '\\' && ptr[1] != '\0') - { - ++ptr; - switch (*ptr) - { - case 'n': - Text += '\n'; - break; - case 't': - Text += '\t'; - break; - case '\r': - ++ptr; - if (*ptr == '\n') - ++ptr; - break; - case '\n': - ++ptr; - if (*ptr == '\r') - ++ptr; - break; - default: - Text += *ptr; - break; - } - ++ptr; - } - else - { - if (*ptr != '\r') - Text += *ptr; - ++ptr; - } - } - if (*ptr != '"') - return CTemplatizerParser(); - - return ++ptr; -} - - -/* - * Parse bloc internal data - */ -CTemplatizerParser CTemplatizerCommentBloc::parseInternal(CTemplatizerParser ptr) -{ - ptr = skipSpace(ptr); - - if (!popToken(ptr, CommentStart, true)) - return NULL; - - while (*ptr != '\0' && !isNextToken(ptr, CommentEnd, false)) - ++ptr; - - if (!popToken(ptr, CommentEnd, false)) - { - ptr.invalidate(); - return ptr; - } - - return ptr; -} - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "templatizer.h" + + + +bool isBlocStart(CTemplatizerParser t) { return (t.isValid() && t[0] == '{' && t[1] == '{'); } +bool isBlocEnd(CTemplatizerParser t) { return (t.isValid() && t[0] == '}' && t[1] == '}'); } + +enum TTemplatizerToken +{ + BlocStart, + BlocEnd, + OpenParenth, + CloseParenth, + Equal, + Comma, + Arobace, + Dollar, + Quote, + CommentStart, + CommentEnd, + Identifier, + ListIdentifier, + + Unknown +}; + +struct SToken +{ + TTemplatizerToken Token; + const char* Text; +}; + +SToken SimpleTokens[] = +{ + { BlocStart, "{" }, + { BlocEnd, "}" }, + { OpenParenth, "(" }, + { CloseParenth, ")" }, + { Equal, "=" }, + { Arobace, "@" }, + { Dollar, "$" }, + { Comma, "," }, + { Quote, "\"" }, + { CommentStart, "/*" }, + { CommentEnd, "*/" }, +}; + +CTemplatizerParser skipSpace(CTemplatizerParser t) +{ + while (t.isValid() && *t != '\0' && isspace(*t)) + ++t; + return t; +} + +const char* skipSpace(const char* t) +{ + while (t != NULL && *t != '\0' && isspace(*t)) + ++t; + return t; +} + +CTemplatizerParser match(const char* keyword, CTemplatizerParser match) +{ + while (*keyword != '\0' && *match != '\0' && *keyword == *match) + { + ++keyword; + ++match; + } + + return *keyword == '\0' ? match : CTemplatizerParser(); +} + +TTemplatizerToken getToken(CTemplatizerParser& t, bool skipspc, std::string* value = NULL) +{ + if (skipspc) + t = skipSpace(t); + + if (!t.isValid()) + return Unknown; + + uint i; + CTemplatizerParser result; + for (i=0; ieval(RootEnv); + else + return ""; +} + + + + + + + + +/* + * Parse bloc + */ +ITemplatizerBloc* ITemplatizerBloc::parseBloc(CTemplatizerParser& ptr) +{ + std::string blocType; + ITemplatizerBloc* bloc = NULL; + + if (popToken(ptr, Identifier, true, &blocType) || popToken(ptr, ListIdentifier, true, &blocType)) + { + if (blocType == "root") bloc = new CTemplatizerRootBloc(); + else if (blocType == "sub") bloc = new CTemplatizerSubBloc(); + else if (blocType == "loop") bloc = new CTemplatizerLoopBloc(); + else if (blocType == "ifdefenv") bloc = new CTemplatizerIfDefEnvBloc(); + else if (blocType == "ifdef") bloc = new CTemplatizerIfDefBloc(); + else if (blocType == "ifnotdefenv") bloc = new CTemplatizerIfNotDefEnvBloc(); + else if (blocType == "ifnotdef") bloc = new CTemplatizerIfNotDefBloc(); + else if (blocType == "switch") bloc = new CTemplatizerSwitchBloc(); + else if (blocType == "file") bloc = new CTemplatizerFileBloc(); + else if (blocType == "set") bloc = new CTemplatizerSetBloc(); + else if (blocType == "append") bloc = new CTemplatizerAppendBloc(); + else if (blocType == "define") bloc = new CTemplatizerDefineBloc(); + else if (blocType == "if") bloc = new CTemplatizerIfBloc(); + else if (blocType == "ifnot") bloc = new CTemplatizerIfNotBloc(); + else if (blocType == "join") bloc = new CTemplatizerJoinBloc(); + else if (blocType == "class") bloc = new CTemplatizerClassBloc(); + else if (blocType == "object") bloc = new CTemplatizerObjectBloc(); + else if (blocType == "ref") bloc = new CTemplatizerReferenceBloc(); + else if (blocType == "refenv") bloc = new CTemplatizerRefEnvBloc(); + else if (blocType == "breakpoint") bloc = new CTemplatizerBreakpointBloc(); + else bloc = new CTemplatizerUserFunctionBloc(blocType); + + if (bloc == NULL) + { + nlwarning("Templatizer: failed to decode bloc '%s' at line %d", blocType.c_str(), ptr.getLine()); + return NULL; + } + + ptr = bloc->parseHeader(ptr); + + if (!ptr.isValid()) + { + nlwarning("Templatizer: failed to decode header of bloc '%s' at line %d", blocType.c_str(), ptr.getLine()); + delete bloc; + return NULL; + } + + if (bloc->hasInternal()) + { + if (!popToken(ptr, BlocStart, true)) + { + nlwarning("Templatizer: failed to decode start of bloc '%s' at line %d", blocType.c_str(), ptr.getLine()); + delete bloc; + return NULL; + } + + ptr = bloc->parseInternal(ptr); + + if (!ptr.isValid()) + { + nlwarning("Templatizer: failed to parse bloc '%s' at line %d", blocType.c_str(), ptr.getLine()); + delete bloc; + return NULL; + } + + if (!popToken(ptr, BlocEnd, true)) + { + nlwarning("Templatizer: failed to decode end of bloc '%s' at line %d", blocType.c_str(), ptr.getLine()); + delete bloc; + return NULL; + } + } + } + else if (isNextToken(ptr, CommentStart, true)) + { + bloc = new CTemplatizerCommentBloc(); + ptr = bloc->parseInternal(ptr); + if (!ptr.isValid()) + nlwarning("Templatizer: failed to parse bloc 'Comment' at line %d", ptr.getLine()); + } + else if (isNextToken(ptr, Quote, true)) + { + bloc = new CTemplatizerTextBloc(); + ptr = bloc->parseInternal(ptr); + if (!ptr.isValid()) + nlwarning("Templatizer: failed to parse bloc 'Text' at line %d", ptr.getLine()); + } + + if (!ptr.isValid()) + { + delete bloc; + return NULL; + } + + return bloc; +} + +/* + * Parse bloc header + */ +CTemplatizerParser ITemplatizerBloc::parseHeader(CTemplatizerParser ptr) +{ + if (popToken(ptr, OpenParenth, true)) + { + uint currentDefArg = 0; + const char** args = getDefParamList(); + + if (popToken(ptr, CloseParenth, true)) + return ptr; + + do + { + std::string paramName; + if (!popToken(ptr, Identifier, true, ¶mName)) + { + if (args == NULL || args[currentDefArg] == NULL) + { + ptr.invalidate(); + return ptr; + } + + paramName = args[currentDefArg++]; + } + else + { + if (!popToken(ptr, Equal, true)) + { + ptr.invalidate(); + return ptr; + } + } + + ITemplatizerBloc* bloc = parseBloc(ptr); + + if (bloc == NULL) + { + ptr.invalidate(); + return ptr; + } + + Params[paramName] = bloc; + + if (!popToken(ptr, Comma, true)) + break; + } + while (true); + + if (!popToken(ptr, CloseParenth, true)) + { + ptr.invalidate(); + return ptr; + } + } + + return ptr; +} + + +/* + * Parse bloc internal data + */ +CTemplatizerParser ITemplatizerBloc::parseInternal(CTemplatizerParser ptr) +{ + ITemplatizerBloc* bloc = NULL; + do + { + bloc = parseBloc(ptr); + + if (bloc != NULL) + Blocs.push_back(bloc); + } + while (bloc != NULL && *ptr != '\0' && !isBlocEnd(ptr)); + + return ptr; +} + + +/* + * Parse bloc internal data + */ +CTemplatizerParser CTemplatizerTextBloc::parseInternal(CTemplatizerParser ptr) +{ + Text = ""; + + ptr = skipSpace(ptr); + + if (*ptr != '"') + return CTemplatizerParser(); + + ++ptr; + + while (*ptr != '\0' && *ptr != '"') + { + if (*ptr == '\\' && ptr[1] != '\0') + { + ++ptr; + switch (*ptr) + { + case 'n': + Text += '\n'; + break; + case 't': + Text += '\t'; + break; + case '\r': + ++ptr; + if (*ptr == '\n') + ++ptr; + break; + case '\n': + ++ptr; + if (*ptr == '\r') + ++ptr; + break; + default: + Text += *ptr; + break; + } + ++ptr; + } + else + { + if (*ptr != '\r') + Text += *ptr; + ++ptr; + } + } + if (*ptr != '"') + return CTemplatizerParser(); + + return ++ptr; +} + + +/* + * Parse bloc internal data + */ +CTemplatizerParser CTemplatizerCommentBloc::parseInternal(CTemplatizerParser ptr) +{ + ptr = skipSpace(ptr); + + if (!popToken(ptr, CommentStart, true)) + return NULL; + + while (*ptr != '\0' && !isNextToken(ptr, CommentEnd, false)) + ++ptr; + + if (!popToken(ptr, CommentEnd, false)) + { + ptr.invalidate(); + return ptr; + } + + return ptr; +} + diff --git a/code/ryzom/tools/pd_parser/templatizer.h b/code/ryzom/tools/pd_parser/templatizer.h index 2f661c059..308fdeb2e 100644 --- a/code/ryzom/tools/pd_parser/templatizer.h +++ b/code/ryzom/tools/pd_parser/templatizer.h @@ -1,1357 +1,1357 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NL_TEMPLATIZER_H -#define NL_TEMPLATIZER_H - -#include -#include -#include -#include - -#include -#include -#include - -class ITemplatizerBloc; - -const char EnvSeparator = '/'; - - - - - - - - -/** - * A Templatizer Env - */ -class CTemplatizerEnv : public NLMISC::CEvalNumExpr -{ -public: - - /// Constructor - CTemplatizerEnv(CTemplatizerEnv* parent) : Parent(parent), CurrentArrayNode(0) { } - - /// Destructor - virtual ~CTemplatizerEnv(); - - /// Clear Env - virtual void clear(); - - /// Get value - virtual std::string get(const std::string& name); - - /// Set value - template - void set(const std::string& name, const T& value) - { - std::string::size_type dotpos = name.find(EnvSeparator); - std::string child = name.substr(0, dotpos); - - if (dotpos == std::string::npos) - { - setAsRawText(name, NLMISC::toString(value)); - } - else - { - getEnv(child)->set(name.substr(dotpos+1), value); - } - } - - /// Set a Define - void define(const std::string& name) - { - set(name, 1); - } - - /// Set a Conditional Define - void define(bool isdef, const std::string& name) - { - if (isdef) - set(name, 1); - } - - /// Does Variable exist? - virtual bool exists(const std::string& name) const - { - TValueMap::const_iterator it = Values.find(name); - if (it == Values.end()) - return (Parent == NULL ? false : Parent->exists(name)); - return true; - } - - /// Does Sub Environment exist? - virtual bool envExists(const std::string& name) const - { - std::string::size_type dotpos = name.find(EnvSeparator); - std::string child = name.substr(0, dotpos); - - if (child.empty()) - return true; - - TEnvMap::const_iterator it = Envs.find(child); - if (it == Envs.end()) - return false; - - return (dotpos == std::string::npos) ? true : (*it).second->envExists(name.substr(dotpos+1)); - } - - /// Enter Sub Env, like getEnv() but it doesn't look in parent, and always goes in current env - virtual CTemplatizerEnv* getSubEnv(const std::string& name) - { - std::string::size_type dotpos = name.find(EnvSeparator); - std::string child = name.substr(0, dotpos); - - if (child.empty()) - return this; - - CTemplatizerEnv* env = NULL; - - if (child == ".") - { - env = this; - } - else if (child == "..") - { - env = (Parent != NULL ? Parent : this); - } - else if (child == "...") - { - env = getRootEnv(); - } - else - { - TEnvMap::iterator it = Envs.find(child); - if (it != Envs.end()) - { - env = (*it).second; - } - else - { - env = new CTemplatizerEnv(this); - Envs[child] = env; - } - - } - - return (dotpos == std::string::npos) ? env : env->getSubEnv(name.substr(dotpos+1)); - } - - /// Get Sub Env - virtual CTemplatizerEnv* getEnv(const std::string& name) - { - std::string::size_type dotpos = name.find(EnvSeparator); - std::string child = name.substr(0, dotpos); - - if (child.empty()) - return this; - - if (child == ".") - { - return (dotpos == std::string::npos) ? this : this->getSubEnv(name.substr(dotpos+1)); - } - else if (child == "..") - { - CTemplatizerEnv* env = (Parent != NULL ? Parent : this); - return (dotpos == std::string::npos) ? env : env->getSubEnv(name.substr(dotpos+1)); - } - else if (child == "...") - { - CTemplatizerEnv* env = getRootEnv(); - return (dotpos == std::string::npos) ? env : env->getSubEnv(name.substr(dotpos+1)); - } - else - { - TEnvMap::iterator it = Envs.find(child); - if (it != Envs.end()) - { - return (dotpos == std::string::npos) ? (*it).second : (*it).second->getSubEnv(name.substr(dotpos+1)); - } - else - { - return Parent != NULL ? Parent->getEnv(name) : getSubEnv(name); - } - } - } - - /// Get Sub Env - CTemplatizerEnv* getEnv(uint node) - { - return getEnv(NLMISC::toString("%08X", node)); - } - - /// Evaluate string (string replacement) - virtual std::string eval(const std::string& text); - - /// Get Next Array Node - CTemplatizerEnv* nextArrayNode(const std::string& array) - { - CTemplatizerEnv* aenv = getSubEnv(array); - uint node = (aenv->CurrentArrayNode)++; - return aenv->getSubEnv(NLMISC::toString("%08X", node)); - } - - /// Set Sub Env - virtual void setSubEnv(const std::string& name, CTemplatizerEnv* subenv) - { - Envs[name] = subenv; - } - - /// Get Parent Env - virtual CTemplatizerEnv* getParent() - { - return Parent; - } - -public: - - /// Parent Env - CTemplatizerEnv* Parent; - - typedef std::map TValueMap; - typedef std::map TEnvMap; - - /// Contained Values - TValueMap Values; - - /// Sub Env - TEnvMap Envs; - - /// Get Root Env - virtual CTemplatizerEnv* getRootEnv() - { - CTemplatizerEnv* root = this; - while (root->getParent() != NULL) - root = root->getParent(); - - return root; - } - - /// Current Array Node - uint CurrentArrayNode; - - /// Set As Raw Text - virtual void setAsRawText(const std::string& name, const std::string& text); - - /// Set Value Node - virtual void setValueNode(const std::string& name, ITemplatizerBloc* bloc) - { - Values[name] = bloc; - } - - /// Get Value Node - virtual ITemplatizerBloc* getValueNode(const std::string& name) - { - ITemplatizerBloc* node = NULL; - CTemplatizerEnv* env = NULL; - return getValueNodeAndEnv(name, node, env) ? node : NULL; - } - - /// Get Value Node - virtual bool getValueNodeAndEnv(const std::string& name, ITemplatizerBloc*& node, CTemplatizerEnv*& env) - { - std::string::size_type pos = name.find_last_of(EnvSeparator); - if (pos == std::string::npos) - { - node = getNode(name); - env = this; - while (node == NULL && env != NULL) - { - env = env->getParent(); - if (env != NULL) - node = env->getNode(name); - } - } - else - { - env = getEnv(name.substr(0, pos)); - if (env != NULL) - node = env->getNode(name.substr(pos+1)); - } - - return node != NULL && env != NULL; - } - - virtual ITemplatizerBloc* getNode(const std::string& name) - { - TValueMap::iterator it = Values.find(name); - return it == Values.end() ? NULL : (*it).second; - } - - virtual NLMISC::CEvalNumExpr::TReturnState evalValue (const char *value, double &result, uint32 userData); -}; - - -/** - * A Templatizer Env - */ -class CTemplatizerRefEnv : public CTemplatizerEnv -{ -public: - - /// Constructor - CTemplatizerRefEnv(CTemplatizerEnv* ref) : CTemplatizerEnv(NULL), Reference(ref) { } - - /// Clear Env - virtual void clear() - { - Reference = NULL; - } - - /// Get value - virtual std::string get(const std::string& name) - { - return Reference->get(name); - } - - /// Does Variable exist? - virtual bool exists(const std::string& name) const - { - return Reference->exists(name); - } - - /// Does Sub Environment exist? - virtual bool envExists(const std::string& name) const - { - return Reference->envExists(name); - } - - /// Get Sub Env - virtual CTemplatizerEnv* getEnv(const std::string& name) - { - return Reference->getEnv(name); - } - - /// Evaluate string (string replacement) - virtual std::string eval(const std::string& text) - { - return Reference->eval(text); - } - - /// Enter Sub Env, like getEnv() but it doesn't look in parent, and always goes in current env - virtual CTemplatizerEnv* getSubEnv(const std::string& name) - { - return Reference->getSubEnv(name); - } - - /// Get Parent Env - virtual CTemplatizerEnv* getParent() - { - return Reference->getParent(); - } -public: - - CTemplatizerEnv* Reference; - - /// Get Root Env - virtual CTemplatizerEnv* getRootEnv() - { - return Reference->getRootEnv(); - } - - /// Set As Raw Text - virtual void setAsRawText(const std::string& name, const std::string& text) - { - Reference->setAsRawText(name, text); - } - - /// Set Value Node - virtual void setValueNode(const std::string& name, ITemplatizerBloc* bloc) - { - Reference->setValueNode(name, bloc); - } - - /// Get Value Node - virtual ITemplatizerBloc* getValueNode(const std::string& name) - { - return Reference->getValueNode(name); - } - - /// Get Value Node - virtual bool getValueNodeAndEnv(const std::string& name, ITemplatizerBloc*& node, CTemplatizerEnv*& env) - { - return Reference->getValueNodeAndEnv(name, node, env); - } - - virtual ITemplatizerBloc* getNode(const std::string& name) - { - return Reference->getNode(name); - } -}; - - -/** - * - * \author Benjamin Legros - * \author Nevrax France - * \date 2003 - */ -class CTemplatizer -{ -public: - - /// Constructor - CTemplatizer(); - - /// Destructor - ~CTemplatizer(); - - - - /** - * Build templatizer from text - */ - bool build(const char* text); - - - /** - * Evaluate template and render to string - */ - std::string eval(); - - - /** - * Set Value in env - */ - template - void set(const std::string& var, const T& value) - { - if (RootEnv == NULL) - return; - - std::string::size_type pos = var.find_last_of(EnvSeparator); - - if (pos == std::string::npos) - { - RootEnv->set(var, value); - } - else - { - RootEnv->getEnv(var.substr(0, pos))->set(var.substr(pos+1), value); - } - } - -public: - - ITemplatizerBloc* RootBloc; - - CTemplatizerEnv* RootEnv; - -}; - - - -class CTemplatizerParser -{ -public: - - CTemplatizerParser() : _Buffer(NULL), _Line(0), _Valid(false) { } - CTemplatizerParser(const CTemplatizerParser& ptr) : _Buffer(ptr._Buffer), _Line(ptr._Line), _Valid(ptr._Valid) { } - CTemplatizerParser(const char* buffer, uint linestart = 1) : _Buffer(buffer), _Line(linestart), _Valid(_Buffer != NULL) { } - - char operator * () const { return *_Buffer; } - char operator [] (int i) const { return _Buffer[i]; } - - CTemplatizerParser& operator = (const CTemplatizerParser& ptr) - { - _Buffer = ptr._Buffer; - _Line = ptr._Line; - _Valid = ptr._Valid; - return *this; - } - - CTemplatizerParser& operator ++ () - { - if (*_Buffer == '\0') - return *this; - - if (*_Buffer == '\n') - ++_Line; - - ++_Buffer; - return *this; - } - - CTemplatizerParser operator ++ (int) - { - CTemplatizerParser ret(*this); - ++(*this); - return ret; - } - - void invalidate() { _Valid = false; } - bool isValid() const { return _Valid; } - - uint getLine() const { return _Line; } - -private: - - const char* _Buffer; - - uint _Line; - - bool _Valid; - -}; - - - - -/** - * A Templatizer node - */ -class ITemplatizerBloc -{ -public: - - /// Constructor - ITemplatizerBloc(); - - /// Destructor - virtual ~ITemplatizerBloc(); - - - - /// Evaluate node - virtual std::string eval(CTemplatizerEnv* env) - { - std::string res; - uint i; - for (i=0; ieval(env); - return res; - } - - /// Get Text (assuming this is a raw text bloc) - virtual std::string getText(CTemplatizerEnv* env) - { - return ""; - } - - /// Get Param list - virtual const char** getDefParamList() - { - return NULL; - } - - /// Get Actual Bloc (not a reference) - virtual ITemplatizerBloc* getActualBloc() - { - return this; - } - -public: - - std::string evalParam(const std::string& param, CTemplatizerEnv* env) - { - TParamMap::iterator it = Params.find(param); - if (it == Params.end()) - return ""; - return (*it).second->eval(env); - } - -public: - - /// Bloc types - enum TType - { - Text, - }; - - /// Bloc type - TType Type; - - typedef std::vector TBlocList; - typedef std::map TParamMap; - - /// Params - TParamMap Params; - - /// Sub blocs - TBlocList Blocs; - - - /// Parse bloc - static ITemplatizerBloc* parseBloc(CTemplatizerParser& ptr); - - /// Parse bloc header - virtual CTemplatizerParser parseHeader(CTemplatizerParser ptr); - - /// Parse bloc internal data - virtual CTemplatizerParser parseInternal(CTemplatizerParser ptr); - - /// Has A Internal Bloc of data - virtual bool hasInternal() const { return true; } -}; - - - - - -/// Root Templatizer -class CTemplatizerRootBloc : public ITemplatizerBloc -{ -public: - -}; - -/// Reference Node -class CTemplatizerReferenceBloc : public ITemplatizerBloc -{ -public: - - ITemplatizerBloc* Reference; - - /// Constructor - CTemplatizerReferenceBloc(ITemplatizerBloc* ref = NULL) : Reference(ref) {} - - /// Destructor - virtual ~CTemplatizerReferenceBloc() - { - Reference = NULL; - } - - /// Evaluate node - virtual std::string eval(CTemplatizerEnv* env) - { - std::string name = evalParam("name", env); - std::string ref = evalParam("ref", env); - ITemplatizerBloc* refnode = env->getValueNode(ref); - if (refnode != NULL) - env->setValueNode(name, new CTemplatizerReferenceBloc(refnode)); - else - nlwarning("Failed to create reference on '%s', not found", name.c_str()); - return ""; - } - - /// Get Text (assuming this is a raw text bloc) - virtual std::string getText(CTemplatizerEnv* env) - { - return Reference->getText(env); - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name", "ref" }; - return (const char**)args; - } - - /// Get Actual Bloc (not a reference) - virtual ITemplatizerBloc* getActualBloc() - { - return Reference->getActualBloc(); - } - - /// Has A Internal Bloc of data - virtual bool hasInternal() const { return false; } -}; - - -/// RefEnv Bloc -class CTemplatizerRefEnvBloc : public ITemplatizerBloc -{ -public: - - /// Evaluate node - virtual std::string eval(CTemplatizerEnv* env) - { - std::string name = evalParam("name", env); - std::string ref = evalParam("ref", env); - - CTemplatizerEnv* refenv = env->getEnv(ref); - if (refenv != NULL) - env->setSubEnv(name, new CTemplatizerRefEnv(refenv)); - else - nlwarning("Failed to create reference on env '%s', not found", name.c_str()); - return ""; - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name", "ref" }; - return (const char**)args; - } - - /// Has A Internal Bloc of data - virtual bool hasInternal() const { return false; } -}; - - - - - -/** - * Comment Bloc - */ -class CTemplatizerCommentBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - return ""; - } - - /// Parse bloc internal data - virtual CTemplatizerParser parseInternal(CTemplatizerParser ptr); - -}; - - -/** - * Raw Text Bloc - */ -class CTemplatizerRawTextBloc : public ITemplatizerBloc -{ -public: - - std::string Text; - - virtual std::string eval(CTemplatizerEnv* env) - { - return Text; - } - - virtual std::string getText(CTemplatizerEnv* env) - { - return Text; - } -}; - -// Set As Raw Text -inline void CTemplatizerEnv::setAsRawText(const std::string& name, const std::string& text) -{ - CTemplatizerRawTextBloc* bloc = new CTemplatizerRawTextBloc(); - bloc->Text = text; - setValueNode(name, bloc); -} - -// Get value -inline std::string CTemplatizerEnv::get(const std::string& name) -{ - ITemplatizerBloc* bloc = getValueNode(name); - - return (bloc == NULL) ? std::string("") : bloc->getText(this); -} - -// eval num expr override -inline NLMISC::CEvalNumExpr::TReturnState CTemplatizerEnv::evalValue (const char *value, double &result, uint32 userData) -{ - if (*value != '$') - { - return NLMISC::CEvalNumExpr::ValueError; - } - - std::string strvalue = get(value+1); - - if (sscanf(strvalue.c_str(), "%lf", &result) != 1) - { - result = (strvalue.empty() ? 0.0 : 1.0); - } - - return NLMISC::CEvalNumExpr::NoError; -} - - - -/** - * Text Bloc - */ -class CTemplatizerTextBloc : public ITemplatizerBloc -{ -public: - - std::string Text; - - virtual std::string eval(CTemplatizerEnv* env) - { - return env->eval(Text); - } - - virtual std::string getText(CTemplatizerEnv* env) - { - return env->eval(Text); - } - - /// Parse bloc internal data - virtual CTemplatizerParser parseInternal(CTemplatizerParser ptr); -}; - - - - -/** - * Sub bloc - */ -class CTemplatizerSubBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string subname = evalParam("name", env); - CTemplatizerEnv* subenv = env->getSubEnv(subname); - - return ITemplatizerBloc::eval(subenv); - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name" }; - return (const char**)args; - } -}; - - -/** - * Loop bloc - */ -class CTemplatizerLoopBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string subname = evalParam("name", env); - CTemplatizerEnv* subenv = env->getSubEnv(subname); - - std::string res; - - CTemplatizerEnv::TEnvMap::iterator it; - for (it=subenv->Envs.begin(); it!=subenv->Envs.end(); ++it) - res += ITemplatizerBloc::eval((*it).second); - - return res; - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name" }; - return (const char**)args; - } -}; - - -/** - * IfDefEnv bloc - */ -class CTemplatizerIfDefEnvBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string subname = evalParam("name", env); - std::string evalinsub = evalParam("evalinsub", env); - - if (env->envExists(subname)) - { - sint eval; - NLMISC::fromString(evalinsub, eval); - CTemplatizerEnv* subenv = (eval ? env->getEnv(subname) : env); - return ITemplatizerBloc::eval(subenv); - } - - return ""; - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name", "evalinsub" }; - return (const char**)args; - } -}; - - -/** - * IfDef bloc - */ -class CTemplatizerIfDefBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string varname = evalParam("name", env); - - if (env->exists(varname)) - { - return ITemplatizerBloc::eval(env); - } - - return ""; - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name" }; - return (const char**)args; - } -}; - - -/** - * IfDefEnv bloc - */ -class CTemplatizerIfNotDefEnvBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string subname = evalParam("name", env); - - if (!env->envExists(subname)) - { - return ITemplatizerBloc::eval(env); - } - - return ""; - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name" }; - return (const char**)args; - } -}; - - -/** - * IfDef bloc - */ -class CTemplatizerIfNotDefBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string varname = evalParam("name", env); - - if (!env->exists(varname)) - { - return ITemplatizerBloc::eval(env); - } - - return ""; - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name" }; - return (const char**)args; - } -}; - - -/** - * Switch bloc - */ -class CTemplatizerSwitchBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string switchvalue = evalParam("value", env); - - uint i; - for (i=0; ievalParam("case", env) == switchvalue) - return Blocs[i]->eval(env); - - return ""; - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "value" }; - return (const char**)args; - } -}; - -/** - * File bloc - */ -class CTemplatizerFileBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string clearfile = evalParam("clear", env); - std::string filename = evalParam("name", env); - - std::string result = ITemplatizerBloc::eval(env); - - FILE* f; - f = fopen(filename.c_str(), (clearfile == "true" ? "w" : "a")); - if (f != NULL) - { - fwrite(result.c_str(), 1, result.size(), f); - fclose(f); - } - - return result; - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name" }; - return (const char**)args; - } -}; - -/** - * Set bloc - */ -class CTemplatizerSetBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string var = evalParam("name", env); - std::string result = ITemplatizerBloc::eval(env); - - env->set(var, result); - - return ""; - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name" }; - return (const char**)args; - } -}; - -/** - * Append bloc - */ -class CTemplatizerAppendBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string var = evalParam("name", env); - std::string result = ITemplatizerBloc::eval(env); - - ITemplatizerBloc* bloc = env->getValueNode(var); - if (bloc == NULL) - return ""; - - CTemplatizerRawTextBloc* text = dynamic_cast(bloc->getActualBloc()); - if (text == NULL) - return ""; - - text->Text += result; - - return ""; - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name" }; - return (const char**)args; - } -}; - -/** - * Define Bloc - */ -class CTemplatizerDefineBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string name = evalParam("name", env); - env->setValueNode(name, new CTemplatizerReferenceBloc(this)); - return ""; - } - - virtual std::string getText(CTemplatizerEnv* env) - { - return ITemplatizerBloc::eval(env); - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name" }; - return (const char**)args; - } -}; - -/** - * If Bloc - */ -class CTemplatizerIfBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string value = evalParam("cond", env); - double result; - NLMISC::CEvalNumExpr::TReturnState res = env->evalExpression(value.c_str(), result, NULL); - - if (res == NLMISC::CEvalNumExpr::NoError && result != 0.0) - { - return ITemplatizerBloc::eval(env); - } - else - { - return ""; - } - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "cond" }; - return (const char**)args; - } -}; - -/** - * If Not Bloc - */ -class CTemplatizerIfNotBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string value = evalParam("cond", env); - - if (value.empty()) - { - return ITemplatizerBloc::eval(env); - } - else - { - return ""; - } - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "cond" }; - return (const char**)args; - } -}; - -/** - * Join bloc - */ -class CTemplatizerJoinBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string sep = evalParam("separator", env); - - std::string res; - uint i; - for (i=0; ieval(env); - - if (token.empty()) - continue; - - if (!res.empty()) - res += sep; - - res += token; - } - return res; - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "separator" }; - return (const char**)args; - } -}; - -/** - * User Defined function call - */ -class CTemplatizerUserFunctionBloc : public ITemplatizerBloc -{ -public: - - CTemplatizerUserFunctionBloc(const std::string& name) : Name(name) {} - - std::string Name; - - virtual std::string eval(CTemplatizerEnv* env) - { - ITemplatizerBloc* func = NULL; - CTemplatizerEnv* fenv = NULL; - if (!env->getValueNodeAndEnv(Name, func, fenv)) - { - nlwarning("Unknown user function '%s'", Name.c_str()); - return ""; - } - - // subenv is child of object env, not of current env - CTemplatizerEnv* subenv = new CTemplatizerEnv(fenv); - - // deport params in subenv - // \todo : eval param in current env - TParamMap::iterator it; - for (it=Params.begin(); it!=Params.end(); ++it) - subenv->setAsRawText((*it).first, (*it).second->getText(env)); - //subenv->setValueNode((*it).first, new CTemplatizerReferenceBloc((*it).second)); - - std::string res = func->getText(subenv); - - delete subenv; - - return res; - } - - /// Get Param list - virtual const char** getDefParamList() - { - return NULL; - } - - /// Has A Internal Bloc of data - virtual bool hasInternal() const - { - return false; - } -}; - -/** - * Class - */ -class CTemplatizerClassBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string name = evalParam("name", env); - env->setValueNode(name, new CTemplatizerReferenceBloc(this)); - return ""; - } - - virtual std::string instantiate(CTemplatizerEnv* env) - { - return ITemplatizerBloc::eval(env); - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name" }; - return (const char**)args; - } -}; - -/** - * Class - */ -class CTemplatizerObjectBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string classname = evalParam("class", env); - std::string name = evalParam("name", env); - - ITemplatizerBloc* bloc = env->getValueNode(classname); - if (bloc == NULL) - { - nlwarning("Unknown class '%s'", classname.c_str()); - return ""; - } - - CTemplatizerClassBloc* classbloc = dynamic_cast(bloc->getActualBloc()); - if (classbloc == NULL) - { - nlwarning("object '%s' is not a class", classname.c_str()); - return ""; - } - - CTemplatizerEnv* objectenv = env->getSubEnv(name); - objectenv->clear(); - - return classbloc->instantiate(objectenv); - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "class", "name" }; - return (const char**)args; - } - - /// Has A Internal Bloc of data - virtual bool hasInternal() const { return false; } -}; - - -/** - * Breakpoint - */ -class CTemplatizerBreakpointBloc : public ITemplatizerBloc -{ -public: - - virtual std::string eval(CTemplatizerEnv* env) - { - std::string value = evalParam("name", env); - return ""; - } - - /// Get Param list - virtual const char** getDefParamList() - { - static const char* args[] = { "name" }; - return (const char**)args; - } -}; - - -#endif // NL_TEMPLATIZER_H - -/* End of templatizer.h */ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef NL_TEMPLATIZER_H +#define NL_TEMPLATIZER_H + +#include +#include +#include +#include + +#include +#include +#include + +class ITemplatizerBloc; + +const char EnvSeparator = '/'; + + + + + + + + +/** + * A Templatizer Env + */ +class CTemplatizerEnv : public NLMISC::CEvalNumExpr +{ +public: + + /// Constructor + CTemplatizerEnv(CTemplatizerEnv* parent) : Parent(parent), CurrentArrayNode(0) { } + + /// Destructor + virtual ~CTemplatizerEnv(); + + /// Clear Env + virtual void clear(); + + /// Get value + virtual std::string get(const std::string& name); + + /// Set value + template + void set(const std::string& name, const T& value) + { + std::string::size_type dotpos = name.find(EnvSeparator); + std::string child = name.substr(0, dotpos); + + if (dotpos == std::string::npos) + { + setAsRawText(name, NLMISC::toString(value)); + } + else + { + getEnv(child)->set(name.substr(dotpos+1), value); + } + } + + /// Set a Define + void define(const std::string& name) + { + set(name, 1); + } + + /// Set a Conditional Define + void define(bool isdef, const std::string& name) + { + if (isdef) + set(name, 1); + } + + /// Does Variable exist? + virtual bool exists(const std::string& name) const + { + TValueMap::const_iterator it = Values.find(name); + if (it == Values.end()) + return (Parent == NULL ? false : Parent->exists(name)); + return true; + } + + /// Does Sub Environment exist? + virtual bool envExists(const std::string& name) const + { + std::string::size_type dotpos = name.find(EnvSeparator); + std::string child = name.substr(0, dotpos); + + if (child.empty()) + return true; + + TEnvMap::const_iterator it = Envs.find(child); + if (it == Envs.end()) + return false; + + return (dotpos == std::string::npos) ? true : (*it).second->envExists(name.substr(dotpos+1)); + } + + /// Enter Sub Env, like getEnv() but it doesn't look in parent, and always goes in current env + virtual CTemplatizerEnv* getSubEnv(const std::string& name) + { + std::string::size_type dotpos = name.find(EnvSeparator); + std::string child = name.substr(0, dotpos); + + if (child.empty()) + return this; + + CTemplatizerEnv* env = NULL; + + if (child == ".") + { + env = this; + } + else if (child == "..") + { + env = (Parent != NULL ? Parent : this); + } + else if (child == "...") + { + env = getRootEnv(); + } + else + { + TEnvMap::iterator it = Envs.find(child); + if (it != Envs.end()) + { + env = (*it).second; + } + else + { + env = new CTemplatizerEnv(this); + Envs[child] = env; + } + + } + + return (dotpos == std::string::npos) ? env : env->getSubEnv(name.substr(dotpos+1)); + } + + /// Get Sub Env + virtual CTemplatizerEnv* getEnv(const std::string& name) + { + std::string::size_type dotpos = name.find(EnvSeparator); + std::string child = name.substr(0, dotpos); + + if (child.empty()) + return this; + + if (child == ".") + { + return (dotpos == std::string::npos) ? this : this->getSubEnv(name.substr(dotpos+1)); + } + else if (child == "..") + { + CTemplatizerEnv* env = (Parent != NULL ? Parent : this); + return (dotpos == std::string::npos) ? env : env->getSubEnv(name.substr(dotpos+1)); + } + else if (child == "...") + { + CTemplatizerEnv* env = getRootEnv(); + return (dotpos == std::string::npos) ? env : env->getSubEnv(name.substr(dotpos+1)); + } + else + { + TEnvMap::iterator it = Envs.find(child); + if (it != Envs.end()) + { + return (dotpos == std::string::npos) ? (*it).second : (*it).second->getSubEnv(name.substr(dotpos+1)); + } + else + { + return Parent != NULL ? Parent->getEnv(name) : getSubEnv(name); + } + } + } + + /// Get Sub Env + CTemplatizerEnv* getEnv(uint node) + { + return getEnv(NLMISC::toString("%08X", node)); + } + + /// Evaluate string (string replacement) + virtual std::string eval(const std::string& text); + + /// Get Next Array Node + CTemplatizerEnv* nextArrayNode(const std::string& array) + { + CTemplatizerEnv* aenv = getSubEnv(array); + uint node = (aenv->CurrentArrayNode)++; + return aenv->getSubEnv(NLMISC::toString("%08X", node)); + } + + /// Set Sub Env + virtual void setSubEnv(const std::string& name, CTemplatizerEnv* subenv) + { + Envs[name] = subenv; + } + + /// Get Parent Env + virtual CTemplatizerEnv* getParent() + { + return Parent; + } + +public: + + /// Parent Env + CTemplatizerEnv* Parent; + + typedef std::map TValueMap; + typedef std::map TEnvMap; + + /// Contained Values + TValueMap Values; + + /// Sub Env + TEnvMap Envs; + + /// Get Root Env + virtual CTemplatizerEnv* getRootEnv() + { + CTemplatizerEnv* root = this; + while (root->getParent() != NULL) + root = root->getParent(); + + return root; + } + + /// Current Array Node + uint CurrentArrayNode; + + /// Set As Raw Text + virtual void setAsRawText(const std::string& name, const std::string& text); + + /// Set Value Node + virtual void setValueNode(const std::string& name, ITemplatizerBloc* bloc) + { + Values[name] = bloc; + } + + /// Get Value Node + virtual ITemplatizerBloc* getValueNode(const std::string& name) + { + ITemplatizerBloc* node = NULL; + CTemplatizerEnv* env = NULL; + return getValueNodeAndEnv(name, node, env) ? node : NULL; + } + + /// Get Value Node + virtual bool getValueNodeAndEnv(const std::string& name, ITemplatizerBloc*& node, CTemplatizerEnv*& env) + { + std::string::size_type pos = name.find_last_of(EnvSeparator); + if (pos == std::string::npos) + { + node = getNode(name); + env = this; + while (node == NULL && env != NULL) + { + env = env->getParent(); + if (env != NULL) + node = env->getNode(name); + } + } + else + { + env = getEnv(name.substr(0, pos)); + if (env != NULL) + node = env->getNode(name.substr(pos+1)); + } + + return node != NULL && env != NULL; + } + + virtual ITemplatizerBloc* getNode(const std::string& name) + { + TValueMap::iterator it = Values.find(name); + return it == Values.end() ? NULL : (*it).second; + } + + virtual NLMISC::CEvalNumExpr::TReturnState evalValue (const char *value, double &result, uint32 userData); +}; + + +/** + * A Templatizer Env + */ +class CTemplatizerRefEnv : public CTemplatizerEnv +{ +public: + + /// Constructor + CTemplatizerRefEnv(CTemplatizerEnv* ref) : CTemplatizerEnv(NULL), Reference(ref) { } + + /// Clear Env + virtual void clear() + { + Reference = NULL; + } + + /// Get value + virtual std::string get(const std::string& name) + { + return Reference->get(name); + } + + /// Does Variable exist? + virtual bool exists(const std::string& name) const + { + return Reference->exists(name); + } + + /// Does Sub Environment exist? + virtual bool envExists(const std::string& name) const + { + return Reference->envExists(name); + } + + /// Get Sub Env + virtual CTemplatizerEnv* getEnv(const std::string& name) + { + return Reference->getEnv(name); + } + + /// Evaluate string (string replacement) + virtual std::string eval(const std::string& text) + { + return Reference->eval(text); + } + + /// Enter Sub Env, like getEnv() but it doesn't look in parent, and always goes in current env + virtual CTemplatizerEnv* getSubEnv(const std::string& name) + { + return Reference->getSubEnv(name); + } + + /// Get Parent Env + virtual CTemplatizerEnv* getParent() + { + return Reference->getParent(); + } +public: + + CTemplatizerEnv* Reference; + + /// Get Root Env + virtual CTemplatizerEnv* getRootEnv() + { + return Reference->getRootEnv(); + } + + /// Set As Raw Text + virtual void setAsRawText(const std::string& name, const std::string& text) + { + Reference->setAsRawText(name, text); + } + + /// Set Value Node + virtual void setValueNode(const std::string& name, ITemplatizerBloc* bloc) + { + Reference->setValueNode(name, bloc); + } + + /// Get Value Node + virtual ITemplatizerBloc* getValueNode(const std::string& name) + { + return Reference->getValueNode(name); + } + + /// Get Value Node + virtual bool getValueNodeAndEnv(const std::string& name, ITemplatizerBloc*& node, CTemplatizerEnv*& env) + { + return Reference->getValueNodeAndEnv(name, node, env); + } + + virtual ITemplatizerBloc* getNode(const std::string& name) + { + return Reference->getNode(name); + } +}; + + +/** + * + * \author Benjamin Legros + * \author Nevrax France + * \date 2003 + */ +class CTemplatizer +{ +public: + + /// Constructor + CTemplatizer(); + + /// Destructor + ~CTemplatizer(); + + + + /** + * Build templatizer from text + */ + bool build(const char* text); + + + /** + * Evaluate template and render to string + */ + std::string eval(); + + + /** + * Set Value in env + */ + template + void set(const std::string& var, const T& value) + { + if (RootEnv == NULL) + return; + + std::string::size_type pos = var.find_last_of(EnvSeparator); + + if (pos == std::string::npos) + { + RootEnv->set(var, value); + } + else + { + RootEnv->getEnv(var.substr(0, pos))->set(var.substr(pos+1), value); + } + } + +public: + + ITemplatizerBloc* RootBloc; + + CTemplatizerEnv* RootEnv; + +}; + + + +class CTemplatizerParser +{ +public: + + CTemplatizerParser() : _Buffer(NULL), _Line(0), _Valid(false) { } + CTemplatizerParser(const CTemplatizerParser& ptr) : _Buffer(ptr._Buffer), _Line(ptr._Line), _Valid(ptr._Valid) { } + CTemplatizerParser(const char* buffer, uint linestart = 1) : _Buffer(buffer), _Line(linestart), _Valid(_Buffer != NULL) { } + + char operator * () const { return *_Buffer; } + char operator [] (int i) const { return _Buffer[i]; } + + CTemplatizerParser& operator = (const CTemplatizerParser& ptr) + { + _Buffer = ptr._Buffer; + _Line = ptr._Line; + _Valid = ptr._Valid; + return *this; + } + + CTemplatizerParser& operator ++ () + { + if (*_Buffer == '\0') + return *this; + + if (*_Buffer == '\n') + ++_Line; + + ++_Buffer; + return *this; + } + + CTemplatizerParser operator ++ (int) + { + CTemplatizerParser ret(*this); + ++(*this); + return ret; + } + + void invalidate() { _Valid = false; } + bool isValid() const { return _Valid; } + + uint getLine() const { return _Line; } + +private: + + const char* _Buffer; + + uint _Line; + + bool _Valid; + +}; + + + + +/** + * A Templatizer node + */ +class ITemplatizerBloc +{ +public: + + /// Constructor + ITemplatizerBloc(); + + /// Destructor + virtual ~ITemplatizerBloc(); + + + + /// Evaluate node + virtual std::string eval(CTemplatizerEnv* env) + { + std::string res; + uint i; + for (i=0; ieval(env); + return res; + } + + /// Get Text (assuming this is a raw text bloc) + virtual std::string getText(CTemplatizerEnv* env) + { + return ""; + } + + /// Get Param list + virtual const char** getDefParamList() + { + return NULL; + } + + /// Get Actual Bloc (not a reference) + virtual ITemplatizerBloc* getActualBloc() + { + return this; + } + +public: + + std::string evalParam(const std::string& param, CTemplatizerEnv* env) + { + TParamMap::iterator it = Params.find(param); + if (it == Params.end()) + return ""; + return (*it).second->eval(env); + } + +public: + + /// Bloc types + enum TType + { + Text, + }; + + /// Bloc type + TType Type; + + typedef std::vector TBlocList; + typedef std::map TParamMap; + + /// Params + TParamMap Params; + + /// Sub blocs + TBlocList Blocs; + + + /// Parse bloc + static ITemplatizerBloc* parseBloc(CTemplatizerParser& ptr); + + /// Parse bloc header + virtual CTemplatizerParser parseHeader(CTemplatizerParser ptr); + + /// Parse bloc internal data + virtual CTemplatizerParser parseInternal(CTemplatizerParser ptr); + + /// Has A Internal Bloc of data + virtual bool hasInternal() const { return true; } +}; + + + + + +/// Root Templatizer +class CTemplatizerRootBloc : public ITemplatizerBloc +{ +public: + +}; + +/// Reference Node +class CTemplatizerReferenceBloc : public ITemplatizerBloc +{ +public: + + ITemplatizerBloc* Reference; + + /// Constructor + CTemplatizerReferenceBloc(ITemplatizerBloc* ref = NULL) : Reference(ref) {} + + /// Destructor + virtual ~CTemplatizerReferenceBloc() + { + Reference = NULL; + } + + /// Evaluate node + virtual std::string eval(CTemplatizerEnv* env) + { + std::string name = evalParam("name", env); + std::string ref = evalParam("ref", env); + ITemplatizerBloc* refnode = env->getValueNode(ref); + if (refnode != NULL) + env->setValueNode(name, new CTemplatizerReferenceBloc(refnode)); + else + nlwarning("Failed to create reference on '%s', not found", name.c_str()); + return ""; + } + + /// Get Text (assuming this is a raw text bloc) + virtual std::string getText(CTemplatizerEnv* env) + { + return Reference->getText(env); + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name", "ref" }; + return (const char**)args; + } + + /// Get Actual Bloc (not a reference) + virtual ITemplatizerBloc* getActualBloc() + { + return Reference->getActualBloc(); + } + + /// Has A Internal Bloc of data + virtual bool hasInternal() const { return false; } +}; + + +/// RefEnv Bloc +class CTemplatizerRefEnvBloc : public ITemplatizerBloc +{ +public: + + /// Evaluate node + virtual std::string eval(CTemplatizerEnv* env) + { + std::string name = evalParam("name", env); + std::string ref = evalParam("ref", env); + + CTemplatizerEnv* refenv = env->getEnv(ref); + if (refenv != NULL) + env->setSubEnv(name, new CTemplatizerRefEnv(refenv)); + else + nlwarning("Failed to create reference on env '%s', not found", name.c_str()); + return ""; + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name", "ref" }; + return (const char**)args; + } + + /// Has A Internal Bloc of data + virtual bool hasInternal() const { return false; } +}; + + + + + +/** + * Comment Bloc + */ +class CTemplatizerCommentBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + return ""; + } + + /// Parse bloc internal data + virtual CTemplatizerParser parseInternal(CTemplatizerParser ptr); + +}; + + +/** + * Raw Text Bloc + */ +class CTemplatizerRawTextBloc : public ITemplatizerBloc +{ +public: + + std::string Text; + + virtual std::string eval(CTemplatizerEnv* env) + { + return Text; + } + + virtual std::string getText(CTemplatizerEnv* env) + { + return Text; + } +}; + +// Set As Raw Text +inline void CTemplatizerEnv::setAsRawText(const std::string& name, const std::string& text) +{ + CTemplatizerRawTextBloc* bloc = new CTemplatizerRawTextBloc(); + bloc->Text = text; + setValueNode(name, bloc); +} + +// Get value +inline std::string CTemplatizerEnv::get(const std::string& name) +{ + ITemplatizerBloc* bloc = getValueNode(name); + + return (bloc == NULL) ? std::string("") : bloc->getText(this); +} + +// eval num expr override +inline NLMISC::CEvalNumExpr::TReturnState CTemplatizerEnv::evalValue (const char *value, double &result, uint32 userData) +{ + if (*value != '$') + { + return NLMISC::CEvalNumExpr::ValueError; + } + + std::string strvalue = get(value+1); + + if (sscanf(strvalue.c_str(), "%lf", &result) != 1) + { + result = (strvalue.empty() ? 0.0 : 1.0); + } + + return NLMISC::CEvalNumExpr::NoError; +} + + + +/** + * Text Bloc + */ +class CTemplatizerTextBloc : public ITemplatizerBloc +{ +public: + + std::string Text; + + virtual std::string eval(CTemplatizerEnv* env) + { + return env->eval(Text); + } + + virtual std::string getText(CTemplatizerEnv* env) + { + return env->eval(Text); + } + + /// Parse bloc internal data + virtual CTemplatizerParser parseInternal(CTemplatizerParser ptr); +}; + + + + +/** + * Sub bloc + */ +class CTemplatizerSubBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string subname = evalParam("name", env); + CTemplatizerEnv* subenv = env->getSubEnv(subname); + + return ITemplatizerBloc::eval(subenv); + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name" }; + return (const char**)args; + } +}; + + +/** + * Loop bloc + */ +class CTemplatizerLoopBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string subname = evalParam("name", env); + CTemplatizerEnv* subenv = env->getSubEnv(subname); + + std::string res; + + CTemplatizerEnv::TEnvMap::iterator it; + for (it=subenv->Envs.begin(); it!=subenv->Envs.end(); ++it) + res += ITemplatizerBloc::eval((*it).second); + + return res; + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name" }; + return (const char**)args; + } +}; + + +/** + * IfDefEnv bloc + */ +class CTemplatizerIfDefEnvBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string subname = evalParam("name", env); + std::string evalinsub = evalParam("evalinsub", env); + + if (env->envExists(subname)) + { + sint eval; + NLMISC::fromString(evalinsub, eval); + CTemplatizerEnv* subenv = (eval ? env->getEnv(subname) : env); + return ITemplatizerBloc::eval(subenv); + } + + return ""; + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name", "evalinsub" }; + return (const char**)args; + } +}; + + +/** + * IfDef bloc + */ +class CTemplatizerIfDefBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string varname = evalParam("name", env); + + if (env->exists(varname)) + { + return ITemplatizerBloc::eval(env); + } + + return ""; + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name" }; + return (const char**)args; + } +}; + + +/** + * IfDefEnv bloc + */ +class CTemplatizerIfNotDefEnvBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string subname = evalParam("name", env); + + if (!env->envExists(subname)) + { + return ITemplatizerBloc::eval(env); + } + + return ""; + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name" }; + return (const char**)args; + } +}; + + +/** + * IfDef bloc + */ +class CTemplatizerIfNotDefBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string varname = evalParam("name", env); + + if (!env->exists(varname)) + { + return ITemplatizerBloc::eval(env); + } + + return ""; + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name" }; + return (const char**)args; + } +}; + + +/** + * Switch bloc + */ +class CTemplatizerSwitchBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string switchvalue = evalParam("value", env); + + uint i; + for (i=0; ievalParam("case", env) == switchvalue) + return Blocs[i]->eval(env); + + return ""; + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "value" }; + return (const char**)args; + } +}; + +/** + * File bloc + */ +class CTemplatizerFileBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string clearfile = evalParam("clear", env); + std::string filename = evalParam("name", env); + + std::string result = ITemplatizerBloc::eval(env); + + FILE* f; + f = fopen(filename.c_str(), (clearfile == "true" ? "w" : "a")); + if (f != NULL) + { + fwrite(result.c_str(), 1, result.size(), f); + fclose(f); + } + + return result; + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name" }; + return (const char**)args; + } +}; + +/** + * Set bloc + */ +class CTemplatizerSetBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string var = evalParam("name", env); + std::string result = ITemplatizerBloc::eval(env); + + env->set(var, result); + + return ""; + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name" }; + return (const char**)args; + } +}; + +/** + * Append bloc + */ +class CTemplatizerAppendBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string var = evalParam("name", env); + std::string result = ITemplatizerBloc::eval(env); + + ITemplatizerBloc* bloc = env->getValueNode(var); + if (bloc == NULL) + return ""; + + CTemplatizerRawTextBloc* text = dynamic_cast(bloc->getActualBloc()); + if (text == NULL) + return ""; + + text->Text += result; + + return ""; + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name" }; + return (const char**)args; + } +}; + +/** + * Define Bloc + */ +class CTemplatizerDefineBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string name = evalParam("name", env); + env->setValueNode(name, new CTemplatizerReferenceBloc(this)); + return ""; + } + + virtual std::string getText(CTemplatizerEnv* env) + { + return ITemplatizerBloc::eval(env); + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name" }; + return (const char**)args; + } +}; + +/** + * If Bloc + */ +class CTemplatizerIfBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string value = evalParam("cond", env); + double result; + NLMISC::CEvalNumExpr::TReturnState res = env->evalExpression(value.c_str(), result, NULL); + + if (res == NLMISC::CEvalNumExpr::NoError && result != 0.0) + { + return ITemplatizerBloc::eval(env); + } + else + { + return ""; + } + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "cond" }; + return (const char**)args; + } +}; + +/** + * If Not Bloc + */ +class CTemplatizerIfNotBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string value = evalParam("cond", env); + + if (value.empty()) + { + return ITemplatizerBloc::eval(env); + } + else + { + return ""; + } + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "cond" }; + return (const char**)args; + } +}; + +/** + * Join bloc + */ +class CTemplatizerJoinBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string sep = evalParam("separator", env); + + std::string res; + uint i; + for (i=0; ieval(env); + + if (token.empty()) + continue; + + if (!res.empty()) + res += sep; + + res += token; + } + return res; + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "separator" }; + return (const char**)args; + } +}; + +/** + * User Defined function call + */ +class CTemplatizerUserFunctionBloc : public ITemplatizerBloc +{ +public: + + CTemplatizerUserFunctionBloc(const std::string& name) : Name(name) {} + + std::string Name; + + virtual std::string eval(CTemplatizerEnv* env) + { + ITemplatizerBloc* func = NULL; + CTemplatizerEnv* fenv = NULL; + if (!env->getValueNodeAndEnv(Name, func, fenv)) + { + nlwarning("Unknown user function '%s'", Name.c_str()); + return ""; + } + + // subenv is child of object env, not of current env + CTemplatizerEnv* subenv = new CTemplatizerEnv(fenv); + + // deport params in subenv + // \todo : eval param in current env + TParamMap::iterator it; + for (it=Params.begin(); it!=Params.end(); ++it) + subenv->setAsRawText((*it).first, (*it).second->getText(env)); + //subenv->setValueNode((*it).first, new CTemplatizerReferenceBloc((*it).second)); + + std::string res = func->getText(subenv); + + delete subenv; + + return res; + } + + /// Get Param list + virtual const char** getDefParamList() + { + return NULL; + } + + /// Has A Internal Bloc of data + virtual bool hasInternal() const + { + return false; + } +}; + +/** + * Class + */ +class CTemplatizerClassBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string name = evalParam("name", env); + env->setValueNode(name, new CTemplatizerReferenceBloc(this)); + return ""; + } + + virtual std::string instantiate(CTemplatizerEnv* env) + { + return ITemplatizerBloc::eval(env); + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name" }; + return (const char**)args; + } +}; + +/** + * Class + */ +class CTemplatizerObjectBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string classname = evalParam("class", env); + std::string name = evalParam("name", env); + + ITemplatizerBloc* bloc = env->getValueNode(classname); + if (bloc == NULL) + { + nlwarning("Unknown class '%s'", classname.c_str()); + return ""; + } + + CTemplatizerClassBloc* classbloc = dynamic_cast(bloc->getActualBloc()); + if (classbloc == NULL) + { + nlwarning("object '%s' is not a class", classname.c_str()); + return ""; + } + + CTemplatizerEnv* objectenv = env->getSubEnv(name); + objectenv->clear(); + + return classbloc->instantiate(objectenv); + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "class", "name" }; + return (const char**)args; + } + + /// Has A Internal Bloc of data + virtual bool hasInternal() const { return false; } +}; + + +/** + * Breakpoint + */ +class CTemplatizerBreakpointBloc : public ITemplatizerBloc +{ +public: + + virtual std::string eval(CTemplatizerEnv* env) + { + std::string value = evalParam("name", env); + return ""; + } + + /// Get Param list + virtual const char** getDefParamList() + { + static const char* args[] = { "name" }; + return (const char**)args; + } +}; + + +#endif // NL_TEMPLATIZER_H + +/* End of templatizer.h */ diff --git a/code/ryzom/tools/pd_parser/tokenizer.h b/code/ryzom/tools/pd_parser/tokenizer.h index f71c8704a..c1816989a 100644 --- a/code/ryzom/tools/pd_parser/tokenizer.h +++ b/code/ryzom/tools/pd_parser/tokenizer.h @@ -1,783 +1,783 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef RY_PD_TOKENIZER_H -#define RY_PD_TOKENIZER_H - -// Nel Misc -#include "nel/misc/types_nl.h" -#include -#include - -// STL -#include -#include -#include -#include - - -enum TToken -{ - TokenUnknown, - TokenEOF, - - TokenIncludeScript, - - TokenIdentifier, - TokenScopedIdentifier, - TokenRefineScope, - TokenNumber, - TokenString, - TokenCppCode, - TokenSlash, - TokenDescription, - - TokenOpenBrace, - TokenCloseBrace, - TokenOpenParenthesis, - TokenCloseParenthesis, - TokenOpenBracket, - TokenCloseBracket, - TokenLessThan, - TokenGreaterThan, - TokenEqual, - TokenComma, - TokenDot, - TokenColon, - TokenSemiColon, - TokenMinus, - TokenPlus, - TokenTimes, - TokenAntiSlash, - TokenMod, - TokenSharp, - TokenAnd, - TokenOr, - TokenCirc, - TokenInterrog, - TokenExclam, - - TokenClass, - TokenEnum, - TokenDimension, - TokenParent, - TokenFlag, - TokenFile, - TokenDb, - TokenType, - TokenKey, - TokenHidden, - TokenExtern, - TokenMirrored, - TokenImplements, - TokenMapped, - TokenDerived, - TokenInitFill, - TokenReserve, - TokenInclude, - TokenWriteTrigger, - TokenSeparated, - - TokenUsePch, - - TokenLogMsg, - TokenLogContext, -}; - - -class CTokenizer -{ -public: - - class CToken - { - public: - CToken(uint start = 0, uint end = 0, TToken token = TokenUnknown, CTokenizer* tokenizer = NULL) : Tokenizer(tokenizer), Start(start), End(end), Token(token) {} - CToken(CTokenizer* tokenizer) : Tokenizer(tokenizer), Start(0), End(0), Token(TokenUnknown) {} - - CTokenizer* Tokenizer; - uint Start; - uint End; - TToken Token; - - std::string get() const { return Tokenizer->get(*this); } - }; - - CTokenizer() : _Buffer(NULL), _Size(0), _CurrentToken(0) { } - - CTokenizer(const std::string &text) - { - init(text); - } - - ~CTokenizer() - { - clear(); - } - - /// Init - void readFile(const std::string &filename) - { - clear(); - - NLMISC::CIFile f; - if (!f.open(filename)) - return; - - uint size = f.getFileSize(); - char *buffer = new char[size+1]; - f.serialBuffer((uint8*)buffer, size); - buffer[size] = '\0'; - - f.close(); - - _File = filename; - - init(std::string(buffer)); - - delete buffer; - } - - /// Init - void init(const std::string &text) - { - _Str = text; - init(_Str.c_str()); - } - - /// Init - void init(const char* text, uint size = 0) - { - _Size = (size > 0 ? size : (uint)strlen(text)); - _Buffer = text; - nlassert(_Buffer != NULL); - _TempToken.Start = 0; - _TempToken.End = 0; - _CurrentToken = 0; - _Mark = 0; - - initOneLetterTokens(); - initKeywords(); - } - - /// - bool tokenize() - { - while (true) - { - CToken token = nextToken(); - - nlassert(token.Tokenizer != NULL); - - if (token.Token == TokenUnknown) - return false; - - if (token.Token == TokenEOF) - break; - - if (token.Token == TokenIncludeScript) - { - CToken scriptFile = nextToken(); - if (scriptFile.Token != TokenString) - error(scriptFile); - - std::string file = scriptFile.get(); - - CTokenizer* sub = new CTokenizer(); - _Includes.push_back(sub); - sub->readFile(file); - if (!sub->tokenize()) - return false; - _Tokens.insert(_Tokens.end(), sub->_Tokens.begin(), sub->_Tokens.end()); - } - else - { - _Tokens.push_back(token); - } - } - - std::vector::iterator it; - for (it=_Tokens.begin(); it!=_Tokens.end(); ++it) - { - if ((*it).Token == TokenIdentifier) - { - std::vector::iterator startit = it; - std::vector::iterator endit = it; - while ((++it) != _Tokens.end() && - (*it).Token == TokenRefineScope && - (*it).Tokenizer == (*startit).Tokenizer && - (++it) != _Tokens.end() && - (*it).Token == TokenIdentifier && - (*it).Tokenizer == (*startit).Tokenizer) - { - endit = it; - } - if (endit != startit) - { - CToken newToken(this); - newToken.Token = TokenScopedIdentifier; - newToken.Start = (*startit).Start; - newToken.End = (*endit).End; - ++endit; - it = _Tokens.erase(startit, endit); - it = _Tokens.insert(it, newToken); - } - } - } - - return true; - } - - /// - bool next() - { - ++_CurrentToken; - return (!end()); - } - - /// - const CToken ¤tToken() const - { - nlassert(!end()); - return _Tokens[_CurrentToken]; - } - - /// - TToken current() const - { - return currentToken().Token; - } - - /// - bool end() const - { - return _CurrentToken >= _Tokens.size(); - } - - /// - void push() - { - _Stack.push_back(_CurrentToken); - } - - /// - void pop() - { - nlassert(!_Stack.empty()); - _CurrentToken = _Stack.back(); - if (_CurrentToken < _Mark) - error(_Tokens[_Mark], "parse"); - _Stack.pop_back(); - } - - /// - void leaveMark() - { - _Mark = _CurrentToken; - } - - /// get token text - std::string get(const CToken &token) const - { - nlassert(token.Tokenizer != NULL); - - if (token.Tokenizer != this) - return token.Tokenizer->get(token); - - std::string str(_Buffer+token.Start, token.End-token.Start); - if (token.Token == TokenString) - { - std::string::size_type pos = 0; - while ((pos = str.find('\\', pos)) != std::string::npos) - { - if (pos+1 == str.size()) - break; - switch (str[pos+1]) - { - case 'n': - str.erase(pos, 2); - str.insert(pos, "\n"); - break; - case 'r': - str.erase(pos, 2); - str.insert(pos, "\r"); - break; - case 't': - str.erase(pos, 2); - str.insert(pos, "\t"); - break; - default: - str.erase(pos, 1); - ++pos; - break; - } - } - } - return str; - } - - /// get file, line - void getFileLine(const CToken& token, uint &line, uint &col, std::string &file) - { - nlassert(token.Tokenizer != NULL); - - if (token.Tokenizer != this) - { - token.Tokenizer->getFileLine(token, line, col, file); - return; - } - - file = _File; - - uint n = 0; - uint pos = token.Start; - - line = 1; - col = 1; - - while (n < pos) - { - if (_Buffer[n] == '\0') - break; - if (_Buffer[n] == '\t') - col += 4; - else if (_Buffer[n] != '\r') - ++col; - if (_Buffer[n] == '\n') - ++line, col = 1; - - ++n; - } - } - - /// error at - void error(const CToken& token, const char *errType = "syntax", const char *errMsg = NULL) - { - if (token.Tokenizer != this && token.Tokenizer != NULL) - { - token.Tokenizer->error(token, errType, errMsg); - return; - } - - uint pos = token.Start; - uint n = 0; - uint line = 1, col = 1; - uint lineStartAt = 0, lineEndAt; - - while (n < pos) - { - if (_Buffer[n] == '\0') - break; - if (_Buffer[n] == '\t') - col += 4; - else if (_Buffer[n] != '\r') - ++col; - else - lineStartAt = n+1; - if (_Buffer[n] == '\n') - ++line, col = 1, lineStartAt = n+1; - - ++n; - } - - lineEndAt = n; - while (_Buffer[lineEndAt] != '\0' && _Buffer[lineEndAt] != '\n' && _Buffer[lineEndAt] != '\r') - ++lineEndAt; - - NLMISC::createDebug (); - - std::string errorMsg = NLMISC::toString("PD_PARSE: file %s, %s error at line %d, column %d%s%s", _File.c_str(), errType, line, col, (errMsg != NULL ? ": " : ""), (errMsg != NULL ? errMsg : "")); - - NLMISC::ErrorLog->displayRawNL("%s", errorMsg.c_str()); - std::string extr(_Buffer+lineStartAt, lineEndAt-lineStartAt); - NLMISC::ErrorLog->displayRawNL("%s", extr.c_str()); - uint i; - for (i=0; idisplayRawNL("%s", extr.c_str()); - nlerror("%s", errorMsg.c_str()); - } - -private: - - /// Original text - std::string _Str; - - /// Parsed buffer - const char *_Buffer; - - /// Buffer size - uint _Size; - - /// Keywords - std::map _Keywords; - - /// One letter tokens - TToken _OneLetterTokens[256]; - - /// List of tokens - std::vector _Tokens; - - /// Current token - uint _CurrentToken; - - /// State stack - std::vector _Stack; - - /// Currently used token - CToken _TempToken; - - /// Mark - uint _Mark; - - /// Loaded file - std::string _File; - - /// Subtokenizers - std::vector _Includes; - - - void clear() - { - _Str.clear(); - _Size = 0; - _TempToken.Start = 0; - _TempToken.End = 0; - _Buffer = NULL; - _Mark = 0; - _File.clear(); - } - - - CToken nextToken() - { - skipSpaces(); - if (posAtEnd()) - return CToken(0, 0, TokenEOF, this); - - _TempToken.Start = _TempToken.End; - _TempToken.Token = TokenUnknown; - _TempToken.Tokenizer = this; - - char parse = popChar(); - - if (isalpha(parse) || parse == '_') - { - // identifier - while (!posAtEnd() && (isalnum(parse = getChar()) || parse == '_')) - popChar(); - - std::map::iterator it; - _TempToken.Token = ((it = _Keywords.find(get(_TempToken))) != _Keywords.end() ? (*it).second : TokenIdentifier); - } - else if (isdigit(parse)) - { - // number - while (!posAtEnd() && isdigit(getChar())) - popChar(); - - _TempToken.Token = TokenNumber; - } - else if (parse == '"') - { - // string - do - { - if (posAtEnd()) - error(_TempToken); - - parse = popChar(); - if (parse == '"') - break; - - if (parse == '\\') - { - if (posAtEnd()) - error(_TempToken); - parse = popChar(); - } - } - while (true); - _TempToken.Token = TokenString; - return CToken(_TempToken.Start+1, _TempToken.End-1, _TempToken.Token, this); - } - else if (parse == '@') - { - if (posAtEnd()) - error(_TempToken); - - parse = popChar(); - - if (parse == '[') - { - // user code - do - { - if (posAtEnd()) - error(_TempToken); - - parse = popChar(); - if (parse == ']') - { - if (posAtEnd()) - error(_TempToken); - if (popChar() == '@') - break; - else - pushChar(); - } - } - while (true); - - uint startTrim = _TempToken.Start+2; - uint endTrim = _TempToken.End-2; - - while (startTrim < endTrim && (isspace(_Buffer[startTrim]) || _Buffer[startTrim] == '\r')) - ++startTrim; - while (startTrim < endTrim && (isspace(_Buffer[endTrim-1]) || _Buffer[endTrim-1] == '\r')) - --endTrim; - - _TempToken.Token = TokenCppCode; - return CToken(startTrim, endTrim, _TempToken.Token, this); - } - else if (parse == '/') - { - // description - do - { - if (posAtEnd()) - error(_TempToken); - - parse = popChar(); - if (parse == '/') - { - if (posAtEnd()) - error(_TempToken); - if (popChar() == '@') - break; - else - pushChar(); - } - } - while (true); - - uint startTrim = _TempToken.Start+2; - uint endTrim = _TempToken.End-2; - - while (startTrim < endTrim && (isspace(_Buffer[startTrim]) || _Buffer[startTrim] == '\r')) - ++startTrim; - while (startTrim < endTrim && (isspace(_Buffer[endTrim-1]) || _Buffer[endTrim-1] == '\r')) - --endTrim; - - _TempToken.Token = TokenDescription; - return CToken(startTrim, endTrim, _TempToken.Token, this); - } - else - { - error(_TempToken); - } - } - else if (parse == '/') - { - _TempToken.Token = TokenSlash; - if (!posAtEnd()) - { - parse = popChar(); - if (parse == '/') - { - // skip to end of line - while (!posAtEnd() && (parse = popChar()) != '\n' && parse != '\r') - ; - return nextToken(); - } - else if (parse == '*') - { - // skip to comment close - while (true) - { - if (posAtEnd()) - error(_TempToken); - - parse = popChar(); - if (parse == '*') - { - if (posAtEnd()) - error(_TempToken); - if (popChar() == '/') - break; - else - pushChar(); - } - } - return nextToken(); - } - else - { - pushChar(); - } - } - } - else if (parse == ':') - { - if (posAtEnd()) - _TempToken.Token = TokenColon; - else - { - parse = popChar(); - if (parse == ':') - { - _TempToken.Token = TokenRefineScope; - } - else - { - pushChar(); - _TempToken.Token = TokenColon; - } - } - } - else if (getOLToken(parse) != TokenUnknown) - _TempToken.Token = getOLToken(parse); - - if (_TempToken.Token == TokenUnknown) - error(_TempToken); - - return _TempToken; - } - - - bool posAtEnd() const - { - return _TempToken.End >= _Size; - } - - /// reset the buffer - void reset() - { - _TempToken.End = 0; - } - - /// skip spaces - void skipSpaces() - { - while (!posAtEnd() && isspace(_Buffer[_TempToken.End])) - ++(_TempToken.End); - } - - /// pop char - char popChar() - { - nlassert(!posAtEnd()); - return _Buffer[(_TempToken.End)++]; - } - - /// get char - char getChar() - { - nlassert(!posAtEnd()); - return _Buffer[_TempToken.End]; - } - - /// push char - void pushChar() - { - nlassert(_TempToken.End > 0); - --(_TempToken.End); - } - - /// init one letter tokens - void initOneLetterTokens() - { - uint i; - for (i=0; i<256; ++i) - _OneLetterTokens[i] = TokenUnknown; - - setOLToken('{', TokenOpenBrace); - setOLToken('}', TokenCloseBrace); - setOLToken('(', TokenOpenParenthesis); - setOLToken(')', TokenCloseParenthesis); - setOLToken('[', TokenOpenBracket); - setOLToken(']', TokenCloseBracket); - setOLToken('<', TokenLessThan); - setOLToken('>', TokenGreaterThan); - setOLToken('=', TokenEqual); - setOLToken(',', TokenComma); - setOLToken('.', TokenDot); - setOLToken(':', TokenColon); - setOLToken(';', TokenSemiColon); - setOLToken('-', TokenMinus); - setOLToken('+', TokenPlus); - setOLToken('*', TokenTimes); - setOLToken('\\', TokenAntiSlash); - setOLToken('%', TokenMod); - setOLToken('#', TokenSharp); - setOLToken('&', TokenAnd); - setOLToken('|', TokenOr); - setOLToken('^', TokenCirc); - setOLToken('?', TokenInterrog); - setOLToken('!', TokenExclam); - } - - /// set one letter token - void setOLToken(char c, TToken token) - { - _OneLetterTokens[(uint)c] = token; - } - - /// set one letter token - TToken getOLToken(char c) const - { - return _OneLetterTokens[(uint)c]; - } - - /// init keywords - void initKeywords() - { - _Keywords.clear(); - - _Keywords["verbatim"] = TokenIncludeScript; - - _Keywords["class"] = TokenClass; - _Keywords["enum"] = TokenEnum; - _Keywords["dimension"] = TokenDimension; - _Keywords["parent"] = TokenParent; - _Keywords["flag"] = TokenFlag; - _Keywords["file"] = TokenFile; - _Keywords["db"] = TokenDb; - _Keywords["type"] = TokenType; - _Keywords["key"] = TokenKey; - _Keywords["hidden"] = TokenHidden; - _Keywords["extern"] = TokenExtern; - _Keywords["mirrored"] = TokenMirrored; - _Keywords["implements"] = TokenImplements; - _Keywords["mapped"] = TokenMapped; - _Keywords["derived"] = TokenDerived; - _Keywords["initfill"] = TokenInitFill; - _Keywords["logmsg"] = TokenLogMsg; - _Keywords["logcontext"] = TokenLogContext; - _Keywords["reserve"] = TokenReserve; - _Keywords["include"] = TokenInclude; - _Keywords["usepch"] = TokenUsePch; - _Keywords["writetriggered"] = TokenWriteTrigger; - _Keywords["separated"] = TokenSeparated; - } -}; - - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef RY_PD_TOKENIZER_H +#define RY_PD_TOKENIZER_H + +// Nel Misc +#include "nel/misc/types_nl.h" +#include +#include + +// STL +#include +#include +#include +#include + + +enum TToken +{ + TokenUnknown, + TokenEOF, + + TokenIncludeScript, + + TokenIdentifier, + TokenScopedIdentifier, + TokenRefineScope, + TokenNumber, + TokenString, + TokenCppCode, + TokenSlash, + TokenDescription, + + TokenOpenBrace, + TokenCloseBrace, + TokenOpenParenthesis, + TokenCloseParenthesis, + TokenOpenBracket, + TokenCloseBracket, + TokenLessThan, + TokenGreaterThan, + TokenEqual, + TokenComma, + TokenDot, + TokenColon, + TokenSemiColon, + TokenMinus, + TokenPlus, + TokenTimes, + TokenAntiSlash, + TokenMod, + TokenSharp, + TokenAnd, + TokenOr, + TokenCirc, + TokenInterrog, + TokenExclam, + + TokenClass, + TokenEnum, + TokenDimension, + TokenParent, + TokenFlag, + TokenFile, + TokenDb, + TokenType, + TokenKey, + TokenHidden, + TokenExtern, + TokenMirrored, + TokenImplements, + TokenMapped, + TokenDerived, + TokenInitFill, + TokenReserve, + TokenInclude, + TokenWriteTrigger, + TokenSeparated, + + TokenUsePch, + + TokenLogMsg, + TokenLogContext, +}; + + +class CTokenizer +{ +public: + + class CToken + { + public: + CToken(uint start = 0, uint end = 0, TToken token = TokenUnknown, CTokenizer* tokenizer = NULL) : Tokenizer(tokenizer), Start(start), End(end), Token(token) {} + CToken(CTokenizer* tokenizer) : Tokenizer(tokenizer), Start(0), End(0), Token(TokenUnknown) {} + + CTokenizer* Tokenizer; + uint Start; + uint End; + TToken Token; + + std::string get() const { return Tokenizer->get(*this); } + }; + + CTokenizer() : _Buffer(NULL), _Size(0), _CurrentToken(0) { } + + CTokenizer(const std::string &text) + { + init(text); + } + + ~CTokenizer() + { + clear(); + } + + /// Init + void readFile(const std::string &filename) + { + clear(); + + NLMISC::CIFile f; + if (!f.open(filename)) + return; + + uint size = f.getFileSize(); + char *buffer = new char[size+1]; + f.serialBuffer((uint8*)buffer, size); + buffer[size] = '\0'; + + f.close(); + + _File = filename; + + init(std::string(buffer)); + + delete buffer; + } + + /// Init + void init(const std::string &text) + { + _Str = text; + init(_Str.c_str()); + } + + /// Init + void init(const char* text, uint size = 0) + { + _Size = (size > 0 ? size : (uint)strlen(text)); + _Buffer = text; + nlassert(_Buffer != NULL); + _TempToken.Start = 0; + _TempToken.End = 0; + _CurrentToken = 0; + _Mark = 0; + + initOneLetterTokens(); + initKeywords(); + } + + /// + bool tokenize() + { + while (true) + { + CToken token = nextToken(); + + nlassert(token.Tokenizer != NULL); + + if (token.Token == TokenUnknown) + return false; + + if (token.Token == TokenEOF) + break; + + if (token.Token == TokenIncludeScript) + { + CToken scriptFile = nextToken(); + if (scriptFile.Token != TokenString) + error(scriptFile); + + std::string file = scriptFile.get(); + + CTokenizer* sub = new CTokenizer(); + _Includes.push_back(sub); + sub->readFile(file); + if (!sub->tokenize()) + return false; + _Tokens.insert(_Tokens.end(), sub->_Tokens.begin(), sub->_Tokens.end()); + } + else + { + _Tokens.push_back(token); + } + } + + std::vector::iterator it; + for (it=_Tokens.begin(); it!=_Tokens.end(); ++it) + { + if ((*it).Token == TokenIdentifier) + { + std::vector::iterator startit = it; + std::vector::iterator endit = it; + while ((++it) != _Tokens.end() && + (*it).Token == TokenRefineScope && + (*it).Tokenizer == (*startit).Tokenizer && + (++it) != _Tokens.end() && + (*it).Token == TokenIdentifier && + (*it).Tokenizer == (*startit).Tokenizer) + { + endit = it; + } + if (endit != startit) + { + CToken newToken(this); + newToken.Token = TokenScopedIdentifier; + newToken.Start = (*startit).Start; + newToken.End = (*endit).End; + ++endit; + it = _Tokens.erase(startit, endit); + it = _Tokens.insert(it, newToken); + } + } + } + + return true; + } + + /// + bool next() + { + ++_CurrentToken; + return (!end()); + } + + /// + const CToken ¤tToken() const + { + nlassert(!end()); + return _Tokens[_CurrentToken]; + } + + /// + TToken current() const + { + return currentToken().Token; + } + + /// + bool end() const + { + return _CurrentToken >= _Tokens.size(); + } + + /// + void push() + { + _Stack.push_back(_CurrentToken); + } + + /// + void pop() + { + nlassert(!_Stack.empty()); + _CurrentToken = _Stack.back(); + if (_CurrentToken < _Mark) + error(_Tokens[_Mark], "parse"); + _Stack.pop_back(); + } + + /// + void leaveMark() + { + _Mark = _CurrentToken; + } + + /// get token text + std::string get(const CToken &token) const + { + nlassert(token.Tokenizer != NULL); + + if (token.Tokenizer != this) + return token.Tokenizer->get(token); + + std::string str(_Buffer+token.Start, token.End-token.Start); + if (token.Token == TokenString) + { + std::string::size_type pos = 0; + while ((pos = str.find('\\', pos)) != std::string::npos) + { + if (pos+1 == str.size()) + break; + switch (str[pos+1]) + { + case 'n': + str.erase(pos, 2); + str.insert(pos, "\n"); + break; + case 'r': + str.erase(pos, 2); + str.insert(pos, "\r"); + break; + case 't': + str.erase(pos, 2); + str.insert(pos, "\t"); + break; + default: + str.erase(pos, 1); + ++pos; + break; + } + } + } + return str; + } + + /// get file, line + void getFileLine(const CToken& token, uint &line, uint &col, std::string &file) + { + nlassert(token.Tokenizer != NULL); + + if (token.Tokenizer != this) + { + token.Tokenizer->getFileLine(token, line, col, file); + return; + } + + file = _File; + + uint n = 0; + uint pos = token.Start; + + line = 1; + col = 1; + + while (n < pos) + { + if (_Buffer[n] == '\0') + break; + if (_Buffer[n] == '\t') + col += 4; + else if (_Buffer[n] != '\r') + ++col; + if (_Buffer[n] == '\n') + ++line, col = 1; + + ++n; + } + } + + /// error at + void error(const CToken& token, const char *errType = "syntax", const char *errMsg = NULL) + { + if (token.Tokenizer != this && token.Tokenizer != NULL) + { + token.Tokenizer->error(token, errType, errMsg); + return; + } + + uint pos = token.Start; + uint n = 0; + uint line = 1, col = 1; + uint lineStartAt = 0, lineEndAt; + + while (n < pos) + { + if (_Buffer[n] == '\0') + break; + if (_Buffer[n] == '\t') + col += 4; + else if (_Buffer[n] != '\r') + ++col; + else + lineStartAt = n+1; + if (_Buffer[n] == '\n') + ++line, col = 1, lineStartAt = n+1; + + ++n; + } + + lineEndAt = n; + while (_Buffer[lineEndAt] != '\0' && _Buffer[lineEndAt] != '\n' && _Buffer[lineEndAt] != '\r') + ++lineEndAt; + + NLMISC::createDebug (); + + std::string errorMsg = NLMISC::toString("PD_PARSE: file %s, %s error at line %d, column %d%s%s", _File.c_str(), errType, line, col, (errMsg != NULL ? ": " : ""), (errMsg != NULL ? errMsg : "")); + + NLMISC::ErrorLog->displayRawNL("%s", errorMsg.c_str()); + std::string extr(_Buffer+lineStartAt, lineEndAt-lineStartAt); + NLMISC::ErrorLog->displayRawNL("%s", extr.c_str()); + uint i; + for (i=0; idisplayRawNL("%s", extr.c_str()); + nlerror("%s", errorMsg.c_str()); + } + +private: + + /// Original text + std::string _Str; + + /// Parsed buffer + const char *_Buffer; + + /// Buffer size + uint _Size; + + /// Keywords + std::map _Keywords; + + /// One letter tokens + TToken _OneLetterTokens[256]; + + /// List of tokens + std::vector _Tokens; + + /// Current token + uint _CurrentToken; + + /// State stack + std::vector _Stack; + + /// Currently used token + CToken _TempToken; + + /// Mark + uint _Mark; + + /// Loaded file + std::string _File; + + /// Subtokenizers + std::vector _Includes; + + + void clear() + { + _Str.clear(); + _Size = 0; + _TempToken.Start = 0; + _TempToken.End = 0; + _Buffer = NULL; + _Mark = 0; + _File.clear(); + } + + + CToken nextToken() + { + skipSpaces(); + if (posAtEnd()) + return CToken(0, 0, TokenEOF, this); + + _TempToken.Start = _TempToken.End; + _TempToken.Token = TokenUnknown; + _TempToken.Tokenizer = this; + + char parse = popChar(); + + if (isalpha(parse) || parse == '_') + { + // identifier + while (!posAtEnd() && (isalnum(parse = getChar()) || parse == '_')) + popChar(); + + std::map::iterator it; + _TempToken.Token = ((it = _Keywords.find(get(_TempToken))) != _Keywords.end() ? (*it).second : TokenIdentifier); + } + else if (isdigit(parse)) + { + // number + while (!posAtEnd() && isdigit(getChar())) + popChar(); + + _TempToken.Token = TokenNumber; + } + else if (parse == '"') + { + // string + do + { + if (posAtEnd()) + error(_TempToken); + + parse = popChar(); + if (parse == '"') + break; + + if (parse == '\\') + { + if (posAtEnd()) + error(_TempToken); + parse = popChar(); + } + } + while (true); + _TempToken.Token = TokenString; + return CToken(_TempToken.Start+1, _TempToken.End-1, _TempToken.Token, this); + } + else if (parse == '@') + { + if (posAtEnd()) + error(_TempToken); + + parse = popChar(); + + if (parse == '[') + { + // user code + do + { + if (posAtEnd()) + error(_TempToken); + + parse = popChar(); + if (parse == ']') + { + if (posAtEnd()) + error(_TempToken); + if (popChar() == '@') + break; + else + pushChar(); + } + } + while (true); + + uint startTrim = _TempToken.Start+2; + uint endTrim = _TempToken.End-2; + + while (startTrim < endTrim && (isspace(_Buffer[startTrim]) || _Buffer[startTrim] == '\r')) + ++startTrim; + while (startTrim < endTrim && (isspace(_Buffer[endTrim-1]) || _Buffer[endTrim-1] == '\r')) + --endTrim; + + _TempToken.Token = TokenCppCode; + return CToken(startTrim, endTrim, _TempToken.Token, this); + } + else if (parse == '/') + { + // description + do + { + if (posAtEnd()) + error(_TempToken); + + parse = popChar(); + if (parse == '/') + { + if (posAtEnd()) + error(_TempToken); + if (popChar() == '@') + break; + else + pushChar(); + } + } + while (true); + + uint startTrim = _TempToken.Start+2; + uint endTrim = _TempToken.End-2; + + while (startTrim < endTrim && (isspace(_Buffer[startTrim]) || _Buffer[startTrim] == '\r')) + ++startTrim; + while (startTrim < endTrim && (isspace(_Buffer[endTrim-1]) || _Buffer[endTrim-1] == '\r')) + --endTrim; + + _TempToken.Token = TokenDescription; + return CToken(startTrim, endTrim, _TempToken.Token, this); + } + else + { + error(_TempToken); + } + } + else if (parse == '/') + { + _TempToken.Token = TokenSlash; + if (!posAtEnd()) + { + parse = popChar(); + if (parse == '/') + { + // skip to end of line + while (!posAtEnd() && (parse = popChar()) != '\n' && parse != '\r') + ; + return nextToken(); + } + else if (parse == '*') + { + // skip to comment close + while (true) + { + if (posAtEnd()) + error(_TempToken); + + parse = popChar(); + if (parse == '*') + { + if (posAtEnd()) + error(_TempToken); + if (popChar() == '/') + break; + else + pushChar(); + } + } + return nextToken(); + } + else + { + pushChar(); + } + } + } + else if (parse == ':') + { + if (posAtEnd()) + _TempToken.Token = TokenColon; + else + { + parse = popChar(); + if (parse == ':') + { + _TempToken.Token = TokenRefineScope; + } + else + { + pushChar(); + _TempToken.Token = TokenColon; + } + } + } + else if (getOLToken(parse) != TokenUnknown) + _TempToken.Token = getOLToken(parse); + + if (_TempToken.Token == TokenUnknown) + error(_TempToken); + + return _TempToken; + } + + + bool posAtEnd() const + { + return _TempToken.End >= _Size; + } + + /// reset the buffer + void reset() + { + _TempToken.End = 0; + } + + /// skip spaces + void skipSpaces() + { + while (!posAtEnd() && isspace(_Buffer[_TempToken.End])) + ++(_TempToken.End); + } + + /// pop char + char popChar() + { + nlassert(!posAtEnd()); + return _Buffer[(_TempToken.End)++]; + } + + /// get char + char getChar() + { + nlassert(!posAtEnd()); + return _Buffer[_TempToken.End]; + } + + /// push char + void pushChar() + { + nlassert(_TempToken.End > 0); + --(_TempToken.End); + } + + /// init one letter tokens + void initOneLetterTokens() + { + uint i; + for (i=0; i<256; ++i) + _OneLetterTokens[i] = TokenUnknown; + + setOLToken('{', TokenOpenBrace); + setOLToken('}', TokenCloseBrace); + setOLToken('(', TokenOpenParenthesis); + setOLToken(')', TokenCloseParenthesis); + setOLToken('[', TokenOpenBracket); + setOLToken(']', TokenCloseBracket); + setOLToken('<', TokenLessThan); + setOLToken('>', TokenGreaterThan); + setOLToken('=', TokenEqual); + setOLToken(',', TokenComma); + setOLToken('.', TokenDot); + setOLToken(':', TokenColon); + setOLToken(';', TokenSemiColon); + setOLToken('-', TokenMinus); + setOLToken('+', TokenPlus); + setOLToken('*', TokenTimes); + setOLToken('\\', TokenAntiSlash); + setOLToken('%', TokenMod); + setOLToken('#', TokenSharp); + setOLToken('&', TokenAnd); + setOLToken('|', TokenOr); + setOLToken('^', TokenCirc); + setOLToken('?', TokenInterrog); + setOLToken('!', TokenExclam); + } + + /// set one letter token + void setOLToken(char c, TToken token) + { + _OneLetterTokens[(uint)c] = token; + } + + /// set one letter token + TToken getOLToken(char c) const + { + return _OneLetterTokens[(uint)c]; + } + + /// init keywords + void initKeywords() + { + _Keywords.clear(); + + _Keywords["verbatim"] = TokenIncludeScript; + + _Keywords["class"] = TokenClass; + _Keywords["enum"] = TokenEnum; + _Keywords["dimension"] = TokenDimension; + _Keywords["parent"] = TokenParent; + _Keywords["flag"] = TokenFlag; + _Keywords["file"] = TokenFile; + _Keywords["db"] = TokenDb; + _Keywords["type"] = TokenType; + _Keywords["key"] = TokenKey; + _Keywords["hidden"] = TokenHidden; + _Keywords["extern"] = TokenExtern; + _Keywords["mirrored"] = TokenMirrored; + _Keywords["implements"] = TokenImplements; + _Keywords["mapped"] = TokenMapped; + _Keywords["derived"] = TokenDerived; + _Keywords["initfill"] = TokenInitFill; + _Keywords["logmsg"] = TokenLogMsg; + _Keywords["logcontext"] = TokenLogContext; + _Keywords["reserve"] = TokenReserve; + _Keywords["include"] = TokenInclude; + _Keywords["usepch"] = TokenUsePch; + _Keywords["writetriggered"] = TokenWriteTrigger; + _Keywords["separated"] = TokenSeparated; + } +}; + + +#endif diff --git a/code/ryzom/tools/pdr_util/pdr_util.cpp b/code/ryzom/tools/pdr_util/pdr_util.cpp index 96a6653a1..367fe6e92 100644 --- a/code/ryzom/tools/pdr_util/pdr_util.cpp +++ b/code/ryzom/tools/pdr_util/pdr_util.cpp @@ -1,299 +1,299 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/misc/types_nl.h" -#include "nel/misc/path.h" -#include "nel/misc/sheet_id.h" -#include -#include -#include "game_share/persistent_data.h" - -using namespace std; -using namespace NLMISC; - -int main(int argc, char *argv[]) -{ - NLMISC::CApplicationContext context; - - if (argc == 1) - { - printf("Usage : %s [-s] [-x|-b|-t] [-o] inputFileName\n", argv[0]); - printf(" -s : must contains the path where the sheet_id.bin can be found\n"); - printf(" You could ignore this param is the sheet_id.bin can be found in the local directory\n"); - printf(" -x : convert a binary pdr to XML format (exclude -b -t)\n"); - printf(" -t : convert a binary pdr to text line format (exclude -b -x)\n"); - printf(" -b : convert a XML or text pdr to binary format (exclude -x -t)\n"); - printf(" -o : output filename\n"); - return -1; - } - - enum TConvMode - { - cm_undefined, - cm_to_xml, - cm_to_binary, - cm_to_txt, - }; - - enum TSourceFormat - { - sf_undefined, - sf_xml, - sf_txt - }; - - TConvMode mode = cm_undefined; - TSourceFormat sourceFormat = sf_undefined; - string sheetIdPath; - string fileName; - vector filenames; - string outputFileName; - - vector args(argv, argv+argc); - - for (uint i=1; i= 2 && args[i][0] == '-') - { - string paramValue = args[i].substr(2); - - switch (args[i][1]) - { - case 's': - sheetIdPath = paramValue; - break; - case 'x': - mode = cm_to_xml; - break; - case 't': - mode = cm_to_txt; - break; - case 'b': - mode = cm_to_binary; - break; - case 'o': - outputFileName = paramValue; - break; - default: - fprintf(stderr, "Unknown parameter '%s'", args[i].c_str()); - return -1; - } - } - else if(!args[i].empty()) - { - filenames.push_back(args[i]); - } -/* - if (i == args.size()-1) - { - // last param, must be the filename - if (args[i].empty() || args[i][0] == '-') - { - fprintf(stderr, "Invalid or missing filename '%s'\n", args[i].c_str()); - return -1; - } - - fileName = args[i]; - } - else - { - if (args[i].empty() || args[i][0] != '-' || args[i].size() < 2) - { - fprintf(stderr, "Invalid param '%s'\n", args[i].c_str()); - return -1; - } - - string paramValue = args[i].substr(2); - - switch (args[i][1]) - { - case 's': - sheetIdPath = paramValue; - break; - case 'x': - mode = cm_to_xml; - break; - case 't': - mode = cm_to_txt; - break; - case 'b': - mode = cm_to_binary; - break; - case 'o': - outputFileName = paramValue; - default: - fprintf(stderr, "Unknown parameter '%s'", args[i].c_str()); - return -1; - } - } -*/ - } - - // init the sheet id - if (!sheetIdPath.empty()) - { - CPath::addSearchPath(sheetIdPath, false, false); - } - - CSheetId::init(false); - - for(uint f = 0; f < filenames.size(); f++) - { - fileName = filenames[f]; - - if (!CFile::isExists(fileName)) - { - fprintf(stderr, "Couldn't find file '%s'", fileName.c_str()); -// return -1; - continue; - } - - if (mode == cm_undefined) - { - // try to automatically determine conversion mode - if (fileName.find(".xml") == (fileName.size() - 4)) - { - printf("Choosing XML->BINARY conversion mode"); - mode = cm_to_binary; - } - else if (fileName.find(".txt") == (fileName.size() -4)) - { - printf("Choosing TXT->BINARY conversion mode"); - mode = cm_to_binary; - } - else if (fileName.find(".bin") == (fileName.size() -4)) - { - printf("Choosing BINARY->XML conversion mode"); - mode = cm_to_xml; - } - else - { - fprintf(stderr, "Missing conversion mode flag (-x|-b|-t) and can't deduce mode from filename extension"); -// return -1; - continue; - } - } - - // determine source format when concerting to binary - if (mode == cm_to_binary) - { - if (fileName.find(".xml") == (fileName.size() - 4)) - { - printf("Source file is in XML format"); - sourceFormat = sf_xml; - } -/* else if (fileName.find(".txt") == (fileName.size() -4)) - { - printf("Source file is in TXT format"); - sourceFormat = sf_txt; - } -*/ else - { - fprintf(stderr, "Invalid source format, only support '.xml' files"); -// return -1; - continue; - } - } - - if (outputFileName.empty() || filenames.size() > 1) - { - // build a output name - outputFileName = fileName; - string inExt; - string outExt; - - if (mode == cm_to_binary) - { - if (sourceFormat == sf_txt) - inExt = ".txt"; - else - inExt = ".xml"; - outExt = ".bin"; - } - else if (mode == cm_to_xml) - { - outExt = ".xml"; - inExt = ".bin"; - } - else if (mode == cm_to_txt) - { - outExt = ".txt"; - inExt = ".bin"; - } - - if (outputFileName.find(inExt) == (outputFileName.size()-inExt.size())) - { - // remove input ext from output filename - outputFileName = outputFileName.substr(0, outputFileName.size()-inExt.size()); - } - // append output extension - outputFileName += outExt; - } - - static CPersistentDataRecord pdr; - pdr.clear(); - - switch(mode) - { - case cm_to_binary: - if (sourceFormat == sf_txt) - { - printf("Converting from txt to bin is currently unpossible ! use xml format"); -// return -1; - continue; -// printf("Converting '%s' (TXT) to '%s' (BINARY)\n", fileName.c_str(), outputFileName.c_str() ); - } - else - printf("Converting '%s' (XML) to '%s' (BINARY)\n", fileName.c_str(), outputFileName.c_str() ); - if (!pdr.readFromTxtFile(fileName.c_str())) - goto failureRead; - if (!pdr.writeToBinFile(outputFileName.c_str())) - goto failureWrite; - break; - - case cm_to_xml: - printf("Converting '%s' (BINARY) to '%s' (XML)\n", fileName.c_str(), outputFileName.c_str() ); - if (!pdr.readFromBinFile(fileName.c_str())) - goto failureRead; - if (!pdr.writeToTxtFile(outputFileName.c_str(), CPersistentDataRecord::XML_STRING)) - goto failureWrite; - break; - - case cm_to_txt: - printf("Converting '%s' (BINARY) to '%s' (TXT)\n", fileName.c_str(), outputFileName.c_str() ); - if (!pdr.readFromBinFile(fileName.c_str())) - goto failureRead; - if (!pdr.writeToTxtFile(outputFileName.c_str(), CPersistentDataRecord::LINES_STRING)) - goto failureWrite; - break; - default: - break; - } - -// return 0; - continue; - -failureRead: - fprintf(stderr, "Error while reading '%s', conversion aborted", fileName.c_str()); -// return -1; - continue; -failureWrite: - fprintf(stderr, "Error while writing '%s', conversion aborted", outputFileName.c_str()); -// return -1; - continue; - } - -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/misc/types_nl.h" +#include "nel/misc/path.h" +#include "nel/misc/sheet_id.h" +#include +#include +#include "game_share/persistent_data.h" + +using namespace std; +using namespace NLMISC; + +int main(int argc, char *argv[]) +{ + NLMISC::CApplicationContext context; + + if (argc == 1) + { + printf("Usage : %s [-s] [-x|-b|-t] [-o] inputFileName\n", argv[0]); + printf(" -s : must contains the path where the sheet_id.bin can be found\n"); + printf(" You could ignore this param is the sheet_id.bin can be found in the local directory\n"); + printf(" -x : convert a binary pdr to XML format (exclude -b -t)\n"); + printf(" -t : convert a binary pdr to text line format (exclude -b -x)\n"); + printf(" -b : convert a XML or text pdr to binary format (exclude -x -t)\n"); + printf(" -o : output filename\n"); + return -1; + } + + enum TConvMode + { + cm_undefined, + cm_to_xml, + cm_to_binary, + cm_to_txt, + }; + + enum TSourceFormat + { + sf_undefined, + sf_xml, + sf_txt + }; + + TConvMode mode = cm_undefined; + TSourceFormat sourceFormat = sf_undefined; + string sheetIdPath; + string fileName; + vector filenames; + string outputFileName; + + vector args(argv, argv+argc); + + for (uint i=1; i= 2 && args[i][0] == '-') + { + string paramValue = args[i].substr(2); + + switch (args[i][1]) + { + case 's': + sheetIdPath = paramValue; + break; + case 'x': + mode = cm_to_xml; + break; + case 't': + mode = cm_to_txt; + break; + case 'b': + mode = cm_to_binary; + break; + case 'o': + outputFileName = paramValue; + break; + default: + fprintf(stderr, "Unknown parameter '%s'", args[i].c_str()); + return -1; + } + } + else if(!args[i].empty()) + { + filenames.push_back(args[i]); + } +/* + if (i == args.size()-1) + { + // last param, must be the filename + if (args[i].empty() || args[i][0] == '-') + { + fprintf(stderr, "Invalid or missing filename '%s'\n", args[i].c_str()); + return -1; + } + + fileName = args[i]; + } + else + { + if (args[i].empty() || args[i][0] != '-' || args[i].size() < 2) + { + fprintf(stderr, "Invalid param '%s'\n", args[i].c_str()); + return -1; + } + + string paramValue = args[i].substr(2); + + switch (args[i][1]) + { + case 's': + sheetIdPath = paramValue; + break; + case 'x': + mode = cm_to_xml; + break; + case 't': + mode = cm_to_txt; + break; + case 'b': + mode = cm_to_binary; + break; + case 'o': + outputFileName = paramValue; + default: + fprintf(stderr, "Unknown parameter '%s'", args[i].c_str()); + return -1; + } + } +*/ + } + + // init the sheet id + if (!sheetIdPath.empty()) + { + CPath::addSearchPath(sheetIdPath, false, false); + } + + CSheetId::init(false); + + for(uint f = 0; f < filenames.size(); f++) + { + fileName = filenames[f]; + + if (!CFile::isExists(fileName)) + { + fprintf(stderr, "Couldn't find file '%s'", fileName.c_str()); +// return -1; + continue; + } + + if (mode == cm_undefined) + { + // try to automatically determine conversion mode + if (fileName.find(".xml") == (fileName.size() - 4)) + { + printf("Choosing XML->BINARY conversion mode"); + mode = cm_to_binary; + } + else if (fileName.find(".txt") == (fileName.size() -4)) + { + printf("Choosing TXT->BINARY conversion mode"); + mode = cm_to_binary; + } + else if (fileName.find(".bin") == (fileName.size() -4)) + { + printf("Choosing BINARY->XML conversion mode"); + mode = cm_to_xml; + } + else + { + fprintf(stderr, "Missing conversion mode flag (-x|-b|-t) and can't deduce mode from filename extension"); +// return -1; + continue; + } + } + + // determine source format when concerting to binary + if (mode == cm_to_binary) + { + if (fileName.find(".xml") == (fileName.size() - 4)) + { + printf("Source file is in XML format"); + sourceFormat = sf_xml; + } +/* else if (fileName.find(".txt") == (fileName.size() -4)) + { + printf("Source file is in TXT format"); + sourceFormat = sf_txt; + } +*/ else + { + fprintf(stderr, "Invalid source format, only support '.xml' files"); +// return -1; + continue; + } + } + + if (outputFileName.empty() || filenames.size() > 1) + { + // build a output name + outputFileName = fileName; + string inExt; + string outExt; + + if (mode == cm_to_binary) + { + if (sourceFormat == sf_txt) + inExt = ".txt"; + else + inExt = ".xml"; + outExt = ".bin"; + } + else if (mode == cm_to_xml) + { + outExt = ".xml"; + inExt = ".bin"; + } + else if (mode == cm_to_txt) + { + outExt = ".txt"; + inExt = ".bin"; + } + + if (outputFileName.find(inExt) == (outputFileName.size()-inExt.size())) + { + // remove input ext from output filename + outputFileName = outputFileName.substr(0, outputFileName.size()-inExt.size()); + } + // append output extension + outputFileName += outExt; + } + + static CPersistentDataRecord pdr; + pdr.clear(); + + switch(mode) + { + case cm_to_binary: + if (sourceFormat == sf_txt) + { + printf("Converting from txt to bin is currently unpossible ! use xml format"); +// return -1; + continue; +// printf("Converting '%s' (TXT) to '%s' (BINARY)\n", fileName.c_str(), outputFileName.c_str() ); + } + else + printf("Converting '%s' (XML) to '%s' (BINARY)\n", fileName.c_str(), outputFileName.c_str() ); + if (!pdr.readFromTxtFile(fileName.c_str())) + goto failureRead; + if (!pdr.writeToBinFile(outputFileName.c_str())) + goto failureWrite; + break; + + case cm_to_xml: + printf("Converting '%s' (BINARY) to '%s' (XML)\n", fileName.c_str(), outputFileName.c_str() ); + if (!pdr.readFromBinFile(fileName.c_str())) + goto failureRead; + if (!pdr.writeToTxtFile(outputFileName.c_str(), CPersistentDataRecord::XML_STRING)) + goto failureWrite; + break; + + case cm_to_txt: + printf("Converting '%s' (BINARY) to '%s' (TXT)\n", fileName.c_str(), outputFileName.c_str() ); + if (!pdr.readFromBinFile(fileName.c_str())) + goto failureRead; + if (!pdr.writeToTxtFile(outputFileName.c_str(), CPersistentDataRecord::LINES_STRING)) + goto failureWrite; + break; + default: + break; + } + +// return 0; + continue; + +failureRead: + fprintf(stderr, "Error while reading '%s', conversion aborted", fileName.c_str()); +// return -1; + continue; +failureWrite: + fprintf(stderr, "Error while writing '%s', conversion aborted", outputFileName.c_str()); +// return -1; + continue; + } + +} diff --git a/code/ryzom/tools/phrase_generator/StdAfx.cpp b/code/ryzom/tools/phrase_generator/StdAfx.cpp index 8b3c99546..a23d968fa 100644 --- a/code/ryzom/tools/phrase_generator/StdAfx.cpp +++ b/code/ryzom/tools/phrase_generator/StdAfx.cpp @@ -1,24 +1,24 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.cpp : source file that includes just the standard includes -// phrase_generator.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.cpp : source file that includes just the standard includes +// phrase_generator.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/code/ryzom/tools/phrase_generator/StdAfx.h b/code/ryzom/tools/phrase_generator/StdAfx.h index 5458c4221..701ded3f4 100644 --- a/code/ryzom/tools/phrase_generator/StdAfx.h +++ b/code/ryzom/tools/phrase_generator/StdAfx.h @@ -1,35 +1,35 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__E4E9FDB9_D40D_4476_BDE3_54897C6406BF__INCLUDED_) -#define AFX_STDAFX_H__E4E9FDB9_D40D_4476_BDE3_54897C6406BF__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - - -// TODO: reference additional headers your program requires here - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__E4E9FDB9_D40D_4476_BDE3_54897C6406BF__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__E4E9FDB9_D40D_4476_BDE3_54897C6406BF__INCLUDED_) +#define AFX_STDAFX_H__E4E9FDB9_D40D_4476_BDE3_54897C6406BF__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__E4E9FDB9_D40D_4476_BDE3_54897C6406BF__INCLUDED_) diff --git a/code/ryzom/tools/phrase_generator/phrase_generator.cpp b/code/ryzom/tools/phrase_generator/phrase_generator.cpp index 6f7a6d737..6fa71e9ae 100644 --- a/code/ryzom/tools/phrase_generator/phrase_generator.cpp +++ b/code/ryzom/tools/phrase_generator/phrase_generator.cpp @@ -1,2756 +1,2756 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// phrase_generator.cpp : Defines the entry point for the console application. - -// - -//-b -p r:\code\ryzom\data_leveldesign -o r:/code/ryzom/data_leveldesign/leveldesign/game_element/sphrase/magic/ magic_bricks.csv -d -m -// -p r:\code\ryzom\data_leveldesign -o r:/code/ryzom/data_leveldesign/leveldesign/game_element/sphrase/magic/ magic_bricks.csv -d -m - -#include "stdafx.h" - - - - - -// Misc -#include -#include "nel/misc/path.h" -#include "nel/misc/file.h" -#include "nel/misc/smart_ptr.h" -#include "nel/misc/command.h" -#include "nel/misc/path.h" -#include -#include -#include "nel/misc/algo.h" -#include "nel/misc/words_dictionary.h" -// Georges -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" -#include "nel/georges/u_form_dfn.h" -#include "nel/georges/u_form_loader.h" -#include "nel/georges/u_type.h" -// Georges, bypassing interface -#include "georges/stdgeorges.h" -#include "georges/form.h" -// Game share -//#include "game_share/xml.h" -// Unicode language file -// C -#include -#include -#include -#include -// stl -#include - -#include "skill_tree.h" - -using namespace NLMISC; -using namespace NLGEORGES; -using namespace std; - - -typedef vector vs; -typedef map< string, string > mss; -typedef map< string, vs > msvs; - -bool GenerateBrickProgression = false; -bool ProduceDocFromExistingPhrases = false; -bool MultipleDocFiles = false; -bool Hypertext = true; -string PhrasePath = "r:/code/ryzom/data_leveldesign/leveldesign/game_element/sphrase/"; -uint NbSheetsGenTries = 0; -uint NbSheetsWritten = 0; -uint NbSheetsRead = 0; -uint NbSheetsRejected = 0; - - -bool UseBricks; - -const string brSheetType = "sbrick"; -const string phSheetType = "sphrase"; -const string PHRASE_MAGIC_PREFIX = "abm_"; // action bricks magic (bm for brick filter) - -struct CBrickInfo -{ - CBrickInfo( const string& ls="", const string& t="", - const vs& props=vs() ) : - LearnSkills(ls), Text(t), Props(props) {} - - string LearnSkills; - string Text; // UTF-8 - vs Props; -}; - - -vs OptionBricks, CounterpartBricks, AllBricks, PhrasesWithInvalidCost, InvalidPhrases; -set UsedCounterpartBricks, UsedCounterpartBrickFamiliesInPhrase; -map SabrinaCosts; -map PhraseSabrinaCosts; -map PhraseCastable; -map BrickInfo; -mss TextToBrick; -multimap< uint, pair > Progression; // phrase code, min. skill -mss PhraseNames, PhraseTitles; -vector ValidPhrases; -set UsedBricks, GeneratedPhrases; -map GrammarMandatParamBrickFamilies, GrammarOptionCreditBrickFamilies; -UFormLoader *FormLoader; -vector PhraseDocFiles( 26 ); -string DocFileName,DocFileNameRoot; -msvs Phrases; -map SkillNameToMaxSkill; -map PhraseCodeToLink; -CWordsDictionary Dico; -CStaticSkillsTree SkillsTree; - - -/* - * - */ -string inputSheetPath; -bool inputSheetPathLoaded = false; -map inputSheetPathContent; // short filename without ext, full filename with path - - -//----------------------------------------------- -// getBrickTypeLetterRPos -// -//----------------------------------------------- -uint getBrickTypeLetterRPos( string& brick ) -{ - /* - uint i =0; - while( i=0 && (isdigit(brick[i]) || brick[i]=='_') ) - i--; - - return (brick.size() - i + 1); - -} // getBrickTypeLetterRPos // - - - - -//----------------------------------------------- -// loadSheetPath -// -// from georges2csv -//----------------------------------------------- -void loadSheetPath() -{ - if (inputSheetPathLoaded) - return; - - NLMISC::createDebug(); - NLMISC::WarningLog->addNegativeFilter( "CPath::insertFileInMap" ); - - CPath::addSearchPath(inputSheetPath, true, false); // for Georges to work properly - - vector files; - CPath::getPathContent (inputSheetPath, true, false, true, files); - - uint i; - for (i=0; i& v, CLog *log=DebugLog ) -{ - if ( ! title.empty() ) - log->displayRaw( "%s: ", title.c_str() ); - vector::const_iterator ist; - for ( ist=v.begin(); ist!=v.end(); ++ist ) - log->displayRaw( "%s ", (*ist).c_str() ); - log->displayRawNL( "" ); -} - - -/* - * - */ -class CStrIComparator : public binary_function -{ -public: - bool operator() ( const string& s1, const string& s2 ) const - { - return (nlstricmp( s1, s2 ) == 0); - } -}; - - -/* - * - */ -uint getIndexFromString( const string& s, const vector& v, bool displayWarning=true ) -{ - if ( v.empty() ) - { - nlwarning( "Can't find '%s' in empty array", s.c_str() ); - return ~0; - } - else - { - vector::const_iterator ist = find_if( v.begin(), v.end(), bind2nd(CStrIComparator(), s) ); - if ( ist == v.end() ) - { - if ( displayWarning ) - { - nlwarning( "Can't find '%s' in:", s.c_str() ); - displayList( "", v, WarningLog ); - } - return ~0; - } - else - return ist - v.begin(); - } -} - - -//----------------------------------------------- -// Erase every carriage returns of the string -// -//----------------------------------------------- -void eraseCarriageReturns( string& s ) -{ - const char CR = '\n'; - string::size_type p = s.find( CR ); - while ( (p=s.find( CR )) != string::npos ) - s.erase( p, 1 ); -} // - - - -// First param: vector of indices of columns matching wantedColumnNames -// Second param: vector of fields matching wantedColumnNames -typedef void (*TDeliveryCallback) ( mss& ); - - -//----------------------------------------------- -// loadCSVFile -// -//----------------------------------------------- -void loadCSVFile( const char *filename, TDeliveryCallback deliveryCallback ) -{ - char lineBuffer[2048]; - FILE *file; - const char *SEPARATOR = ";"; - vector args; - vector::iterator iarg; - - if ( (file = fopen( filename, "r" )) == NULL ) - { - nlwarning( "Can't find file %s", filename ); - } - else - { - // Read first line as header with column names - lineBuffer[0] = '\0'; - fgets( lineBuffer, 2048, file ); - explode( lineBuffer, SEPARATOR, args ); - - // Store column names (and get rid of carriage returns!) - vector < string > columnNames; - mss valuesByName; - for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) - { - eraseCarriageReturns( *iarg ); - columnNames.push_back( *iarg ); - valuesByName.insert( make_pair( *iarg, string("") ) ); - } - - // for each line, deliver the value of the fields - while ( ! feof(file) ) - { - // Get from file - lineBuffer[0] = '\0'; - fgets( lineBuffer, 2048, file ); - explode( lineBuffer, SEPARATOR, args ); - - // Set values (and get rid of carriage returns!) - for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) - { - eraseCarriageReturns( *iarg ); - valuesByName[columnNames[iarg-args.begin()]] = *iarg; - } - - // Deliver the wanted fields - deliveryCallback( valuesByName ); - } - } - -} // loadCSVFile // - - -//set Skills; - - -//----------------------------------------------- -// brickDeliveryCallback -// -// Fetch brick code and sabrina cost -// - AllBricks -// - BrickInfo -// - OptionBricks -// - CounterpartBricks -// - SabrinaCosts -//----------------------------------------------- -void brickDeliveryCallback( mss& values ) -{ - string s = values["Brick_id"]; - if ( s.empty() ) - { - s = values["FILE"]; - if ( s.empty() ) - s = values["fileName"]; - } - - string brick = CFile::getFilenameWithoutExtension( s ); - strupr( brick ); - if ( brick.empty() ) - { - nlwarning(" can't get root filename of %s",s.c_str()); - return; - } - - string sc = values["Basics.SabrinaCost"]; - string ls = values["Basics.LearnRequiresOneOfSkills"]; - string txt = values["name"]; // TODO: only for combat - string fmn = values["familyName"]; - string propIdent = "Basics.Property"; - - if ( UseBricks ) - { - AllBricks.push_back( brick ); - string name = (txt.empty()) ? fmn : txt; - vs props; - - // Find all Basics.Property N (assumes they are subsequent) - mss::const_iterator imv = values.find( propIdent + " 0" ); - for ( ; imv!=values.end(); ++imv ) - { - const string& colName = (*imv).first; - const string& v = (*imv).second; - if ( colName.find( propIdent ) != string::npos ) - { - if ( v != "NULL" && !v.empty() ) - props.push_back( v ); - } - else - break; - } - BrickInfo.insert( make_pair( brick, CBrickInfo( ls, name, props ) ) ); - } - - // Store brick in right container - string::size_type p = brick.size() - getBrickTypeLetterRPos(brick); - if ( ((sint)p) >= 0 ) - { - switch ( brick[p] ) - { - case 'O': OptionBricks.push_back( brick ); - break; - case 'C': CounterpartBricks.push_back( brick ); - break; - } - } - else - { - nlwarning( "Invalid brick code: %s", brick.c_str() ); - return; - } - - // Store cost - sint sabrinaCost; - if ( sc.empty() ) - { - nldebug( "No sabrina cost for %s, assuming cost 0", brick.c_str() ); - sabrinaCost = 0; - } - else - { - sabrinaCost = atoi( sc.c_str() ); - } - SabrinaCosts.insert( make_pair( brick, sabrinaCost ) ); - - /* // Quick hack to generate skill codes - string skill = brick.substr( 1, p-1 ); - if ( ! skill.empty() ) - Skills.insert( skill );*/ - -} // brickDeliveryCallback // - - - -//----------------------------------------------- -// loadBricks -// -//----------------------------------------------- -void loadBricks( const char* filename ) -{ - loadCSVFile( filename, brickDeliveryCallback ); - if ( ProduceDocFromExistingPhrases ) - nlinfo( "Loaded %u option bricks, %u counterpart bricks, %u sabrina costs", OptionBricks.size(), CounterpartBricks.size(), SabrinaCosts.size() ); - else if ( UseBricks ) - nlinfo( "Loaded %u bricks", AllBricks.size() ); - - /*set::const_iterator iss; - for ( iss=Skills.begin(); iss!=Skills.end(); ++iss ) - { - const string& skill = (*iss); - InfoLog->displayRawNL( " ", skill.c_str(), skill.c_str() ); - }*/ - -} // loadBricks // - - -/* - * - */ -string getRootBrickForOptionOrCredit( const string& ob ) -{ - // Extract brick code radix - string::size_type p = ob.size() - getBrickTypeLetterRPos(const_cast(ob)); - if ( (ob.size() <= getBrickTypeLetterRPos(const_cast(ob))) || - ((ob[p] != 'O') && (ob[p] != 'C')) ) - nlerror( "%s is not an option or credit brick", ob.c_str() ); - string radix = ob.substr( 0, p ); - - // Append root brick suffix - return radix + "PA01"; -} - - -/* - * - */ -string getBrickFamily( const string& b ) -{ - if ( b.size() >= getBrickTypeLetterRPos(const_cast(b))+2 ) - { - string::size_type p = b.size() - getBrickTypeLetterRPos(const_cast(b)); - return b.substr( 0, p+2 ); - } - return string(); -} - - -/* - * - */ -bool isFromBrickFamily( const string& brick, const string& fam ) -{ - return nlstricmp( brick.substr( 0, fam.size() ), fam ) == 0; -} - - -/* - * - */ -string getFirstBrickOfFamily( const string& family ) -{ - vs::const_iterator ib; - for ( ib=AllBricks.begin(); ib!=AllBricks.end(); ++ib ) - { - const string& brick = *ib; - if ( isFromBrickFamily( brick, family ) ) - return brick; - } - return string(); -} - - -/* - * - */ -vs getAllBricksOfFamily( const string& family ) -{ - vs res; - vs::const_iterator ib; - for ( ib=AllBricks.begin(); ib!=AllBricks.end(); ++ib ) - { - const string& brick = *ib; - if ( isFromBrickFamily( brick, family ) ) - res.push_back( brick ); - } - return res; -} - - -/* - * - */ -uint getCompatibleCounterpartBrickForCost( uint phraseCost, vs& phrase ) -{ - //nlinfo( "Searching credit for cost %u", phraseCost ); - - // Get the lowest matching counterpart brick - uint minHigherCounterpartValue = ~0, maxLowerCounterpartValue = 0, counterpartValue; - vs::const_iterator icb, iPerfectMatch = CounterpartBricks.end(), iMinCb = CounterpartBricks.end(), iMaxCb = CounterpartBricks.end(); - for ( icb=CounterpartBricks.begin(); icb!=CounterpartBricks.end(); ++icb) - { - const string& cb = *icb; - - // Skip if family already used in current phrase - if ( UsedCounterpartBrickFamiliesInPhrase.find( getBrickFamily( cb ) ) != UsedCounterpartBrickFamiliesInPhrase.end() ) - continue; - - counterpartValue = abs( SabrinaCosts[cb] ); - //nldebug( "Trying with credit %u", counterpartValue ); - if ( counterpartValue == phraseCost ) - { - // Perfect match, check if not already taken - if ( UsedCounterpartBricks.insert( cb ).second ) - { - UsedCounterpartBrickFamiliesInPhrase.insert( getBrickFamily( cb ) ); - phrase.push_back( cb ); - return counterpartValue; - } - else - { - // If already taken, we will come back to it later - iPerfectMatch = icb; - } - } - else if ( counterpartValue > phraseCost ) - { - // Higher => get the minimum - if ( counterpartValue < minHigherCounterpartValue ) - { - minHigherCounterpartValue = counterpartValue; - iMinCb = icb; - } - } - else // counterpartValue < phraseCost : store the max - { - if ( counterpartValue >= maxLowerCounterpartValue ) - { - maxLowerCounterpartValue = counterpartValue; - iMaxCb = icb; - } - } - } - if ( iPerfectMatch != CounterpartBricks.end() ) - { - // We skipped a perfect match in order to try to get a new value. But none found. Now get back to the last value. - phrase.push_back( *iPerfectMatch ); - UsedCounterpartBrickFamiliesInPhrase.insert( getBrickFamily( *iPerfectMatch ) ); - return abs( SabrinaCosts[*iPerfectMatch] ); - } - else if ( iMinCb == CounterpartBricks.end() ) - { - if ( iMaxCb == CounterpartBricks.end() ) - { - nlerror( "No matching counterpart" ); - return ~0; - } - else - { - // No phrase possible with only one (more) counterpart, try with the max and more (recurse) - UsedCounterpartBricks.insert( *iMaxCb ); - UsedCounterpartBrickFamiliesInPhrase.insert( getBrickFamily( *iMaxCb ) ); - phrase.push_back( *iMaxCb ); - return maxLowerCounterpartValue + getCompatibleCounterpartBrickForCost( phraseCost - maxLowerCounterpartValue, phrase ); - } - } - else - { - // Phrase possible with one (more) counterpart - UsedCounterpartBricks.insert( *iMinCb ); - UsedCounterpartBrickFamiliesInPhrase.insert( getBrickFamily( *iMinCb ) ); - phrase.push_back( *iMinCb ); - return minHigherCounterpartValue; - } -} - - -/* - * - */ -void getCompatibleCounterpartBricks( vs& phrase ) -{ - // Calculate the cost of the phrase - sint phraseCost = 0; - string phraseStr; - vs::const_iterator ip; - for ( ip=phrase.begin(); ip!=phrase.end(); ++ip ) - { - const string& brick = *ip; - sint sabrinaCost; - map::const_iterator isc = SabrinaCosts.find( brick ); - if ( isc != SabrinaCosts.end() ) - sabrinaCost = (*isc).second; - else - sabrinaCost = 0; - phraseCost += sabrinaCost; - phraseStr += brick + " "; - } - - // Find matching counterpart(s), only 1 per family - UsedCounterpartBrickFamiliesInPhrase.clear(); - uint counterpartValue = getCompatibleCounterpartBrickForCost( phraseCost, phrase ); - - displayList( toString( "+%3u -%3u", phraseCost, counterpartValue ), phrase ); -} - - -/* - * - */ -/*void getCompatiblePhraseByCounterpart( const string& counterpartBrick, vs& phrase ) -{ - sint sabrinaCost = SabrinaCosts[counterpartBrick]; - - // Assuming root brick cost is zero! - vs::const_iterator iob; - for ( iob=OptionBricks.begin(); iob!=OptionBricks.end(); ++iob ) - { - // TODO: Find the highest cost that is lower or equal than the counterpart value - const string& ob = *iob; - if ( SabrinaCosts[ob] <= SabrinaCosts[counterpartBrick] ) - break; // currently, take the first found - } - if ( iob != OptionBricks.end() ) - { - string rb = getRootBrickForOptionOrCredit( *iob ); - phrase.push_back( rb ); - phrase.push_back( *iob ); - phrase.push_back( counterpartBrick ); - nldebug( "%s %s %s: +%u -%u", rb.c_str(), (*iob).c_str(), counterpartBrick.c_str(), - SabrinaCosts[rb]+SabrinaCosts[*iob], SabrinaCosts[counterpartBrick] ); - } - else - nlwarning( "No matching phrase for counterpart %s", counterpartBrick.c_str() ); -}*/ - - -/* - * Clear the form to reuse it (and all contents below node) - */ -void clearSheet( CForm *form, UFormElm* node ) -{ - ((CFormElm*)node)->clean(); - form->clean(); -} - - - -/* - * - */ -inline void explodeBrickAndParameters( const string& brickAndParams, vs& bricks ) -{ - explode( brickAndParams, " ", bricks ); -} - - -/* - * - */ -string getBrickType( const string& brick ) -{ - if ( brick.size() < 4 ) - return "INVALID TYPE in " + brick; - else - { - switch ( brick[brick.size()-getBrickTypeLetterRPos(const_cast(brick))] ) - { - case 'P': return "Root"; - break; - case 'E': return "Effect"; - break; - case 'O': return "Option"; - break; - case 'M': return "Modifier"; - break; - case 'C': return "Credit"; - break; - default: - return "INVALID TYPE in " + brick; - } - } -} - - -//----------------------------------------------- -// printBrickInfo -// -//----------------------------------------------- -void printBrickInfo( FILE *htmlfile, const string& brick, const string& grammarError, sint& sabrinaCost, uint& minSkillValue, string& minSkill ) -{ - minSkill.clear(); - string b = brick; - strupr( b ); - string brickType = getBrickType( b ); - sint sc = (brickType=="Credit") ? -abs( SabrinaCosts[b] ) : SabrinaCosts[b]; - CBrickInfo& bInfo = BrickInfo[b]; - fprintf( htmlfile, "
  • %s %s %s
    \n", brickType.c_str(), b.c_str(), bInfo.Text.c_str() ); - if ( ! grammarError.empty() ) - { - fprintf( htmlfile, "%s
    \n", grammarError.c_str() ); - } - else - { - fprintf( htmlfile, "Sabrina Cost: %d
    \n", sc ); - if( !bInfo.LearnSkills.empty() ) - { - fprintf( htmlfile, "Skills required: %s
    \n", bInfo.LearnSkills.c_str() ); - } - if( bInfo.Props.size() ) - { - fprintf( htmlfile, "Properties:" ); - for ( vs::const_iterator ip = bInfo.Props.begin(); ip!=bInfo.Props.end(); ++ip ) - { - fprintf( htmlfile, " %s", (*ip) ); - } - } - } - fprintf( htmlfile, "
  • \n" ); - - // Calculate sabrina cost & skill value - sabrinaCost = sc; - if ( bInfo.LearnSkills.empty() ) - minSkillValue = 0; - else - { - minSkillValue = ~0; - vector skillsAndValues; - explode( bInfo.LearnSkills, ":", skillsAndValues, true ); - vector skillValues( skillsAndValues.size(), ~0 ); - vector::iterator isv; - for ( isv=skillsAndValues.begin(); isv!=skillsAndValues.end(); ++isv ) - { - const string& sav = *isv; - string::size_type p = sav.find( ' ' ); - if ( (p == string::npos) || (sav.size() == p+1) ) - nlwarning( "Invalid LearnRequiresOneOfSkills value '%s'", sav.c_str() ); - else - { - uint sv = atoi( sav.substr( p+1 ).c_str() ); - skillValues[isv-skillsAndValues.begin()] = sv; - if ( sv < minSkillValue ) - minSkillValue = sv; - } - } - - for ( isv=skillsAndValues.begin(); isv!=skillsAndValues.end(); ++isv ) - { - if ( skillValues[isv-skillsAndValues.begin()] == minSkillValue ) - { - string& sav = *isv; - if ( (! sav.empty()) && (sav[0] != 'S') ) - sav = 'S' + sav; - if ( minSkill.find( sav ) == string::npos ) - { - if ( ! minSkill.empty() ) - minSkill += ", "; - minSkill += sav; - } - } - } - } - -} // printBrickInfo // - - -//----------------------------------------------- -// loadBrickGrammar -// -//----------------------------------------------- -void loadBrickGrammar() -{ - uint nbRootBricks = 0; - vs::const_iterator ib; - for ( ib=AllBricks.begin(); ib!=AllBricks.end(); ++ib ) - { - string brick = *ib; - strupr( brick ); - if ( brick.size() >= 4 ) - { - char brickType = brick[brick.size()-getBrickTypeLetterRPos(brick)]; - - /*// As the root bricks may be absent from the table, deduce them (obsolete) - if ( brickType == 'O' ) - { - string rootBrick = getRootBrickForOptionOrCredit( brick ); - if ( GrammarOptionCreditBrickFamilies.find( rootBrick ) == GrammarOptionCreditBrickFamilies.end() ) - { - brick = rootBrick; - brickType = 'P'; - } - else - { - continue; - } - }*/ - - // If not skipped by previous 'continue' - if ( (brickType == 'P') || (brickType == 'E') || (brickType == 'O' ) ) // root, effect, option - { - NLMISC::CSmartPtr form = (CForm*)FormLoader->loadForm( (strlwr(static_cast(brick))+"."+brSheetType).c_str() ); - if ( ! form ) - { - nlwarning( "Can't load sheet %s", ((strlwr(static_cast(brick)))+"."+phSheetType).c_str() ); - continue; - } - for ( uint i=0; i!=12; ++i ) - { - string value; - form->getRootNode().getValueByName( value, toString( "Mandatory.f%u", i ).c_str() ); - if ( (! value.empty()) && (value != "Unknown") ) - { - GrammarMandatParamBrickFamilies[brick].push_back( value ); - } - } - if ( brickType == 'O' ) - { - for ( uint i=0; i!=4; ++i ) - { - string value; - form->getRootNode().getValueByName( value, toString( "Parameter.f%u", i ).c_str() ); - if ( (! value.empty()) && (value != "Unknown") ) - { - GrammarMandatParamBrickFamilies[brick].push_back( value ); - } - } - } - if ( brickType == 'P' ) // root - { - ++nbRootBricks; - for ( uint i=0; i!=32; ++i ) - { - string value; - form->getRootNode().getValueByName( value, toString( "Optional.f%u", i ).c_str() ); - if ( (! value.empty()) && (value != "Unknown") ) - { - GrammarOptionCreditBrickFamilies[brick].push_back( value ); - } - } - for ( uint i=0; i!=12; ++i ) - { - string value; - form->getRootNode().getValueByName( value, toString( "Credit.f%u", i ).c_str() ); - if ( (! value.empty()) && (value != "Unknown") ) - { - GrammarOptionCreditBrickFamilies[brick].push_back( value ); - } - } - } - } - } - else - { - nlwarning( "Invalid brick code %s", brick.c_str() ); - } - } - nlinfo( "%u bricks have mandatory/parameter grammar rules", GrammarMandatParamBrickFamilies.size() ); - nlinfo( "%u bricks have option/credit grammar rules", GrammarOptionCreditBrickFamilies.size() ); - nlinfo( "Found or deduced %u root bricks", nbRootBricks ); - -} // loadBrickGrammar // - - - -//----------------------------------------------- -// loadPhraseTitles -// -//----------------------------------------------- -void loadPhraseTitles() -{ - STRING_MANAGER::TWorksheet worksheet; - STRING_MANAGER::loadExcelSheet( "r:/code/ryzom/translation/translated/sphrase_words_en.txt", worksheet ); - uint cp, cn; - if ( worksheet.findCol( ucstring("sphrase ID"), cp ) && worksheet.findCol( ucstring("name"), cn ) ) - { - for ( std::vector::iterator ip = worksheet.begin(); ip!=worksheet.end(); ++ip ) - { - if ( ip == worksheet.begin() ) // skip first row - continue; - STRING_MANAGER::TWorksheet::TRow& row = *ip; - PhraseTitles.insert( make_pair( strlwr(row[cp].toString()), row[cn].toUtf8() ) ); - } - } - else - nlwarning( "sphrase ID or name not found" ); - - nlinfo( "Loaded %u phrase titles", PhraseTitles.size() ); - -} // loadPhraseTitles // - - -//----------------------------------------------- -// loadBrickTitles -// -//----------------------------------------------- -void loadBrickTitles() -{ - STRING_MANAGER::TWorksheet worksheet; - STRING_MANAGER::loadExcelSheet( "r:/code/ryzom/translation/translated/sbrick_words_en.txt", worksheet ); - uint cp, cn, nbTitles = 0; - if ( worksheet.findCol( ucstring("sbrick ID"), cp ) && worksheet.findCol( ucstring("name"), cn ) ) - { - for ( std::vector::iterator ip = worksheet.begin(); ip!=worksheet.end(); ++ip ) - { - if ( ip == worksheet.begin() ) // skip first row - continue; - STRING_MANAGER::TWorksheet::TRow& row = *ip; - BrickInfo[strupr(row[cp].toString())].Text = row[cn].toUtf8();; - ++nbTitles; - } - } - else - nlwarning( "sbrick ID or name not found" ); - - nlinfo( "Loaded %u brick titles", nbTitles ); - -} // loadBrickTitles // - - -/* - * - */ -void getChildrenBricks( const string& brick, vs& chFamilies ) -{ - chFamilies = GrammarMandatParamBrickFamilies[brick]; -} - - -/* - * - */ -void addError( string& errorStr, string& newError, uint& nbGrammarErrors ) -{ - if ( ! errorStr.empty() ) - errorStr += "
    "; - errorStr += newError; - ++nbGrammarErrors; -} - - -/* - * - */ -void checkOptionOrCreditCompatibility( string& errorStr, const string& currentBrick, const string& rootBrick, uint& nbGrammarErrors ) -{ - string brick = currentBrick; - strupr( brick ); - if ( brick.size() >= 4 && brick[1]!='C' && brick[1]!='H') // C & H for craft and harvest - { - char brickType = brick[brick.size()-getBrickTypeLetterRPos(brick)]; - if ( (brickType == 'O') || (brickType == 'C') ) - { - string rootBrick = getRootBrickForOptionOrCredit( brick ); - const vs& compatibleOptionOrCredits = GrammarOptionCreditBrickFamilies[rootBrick]; - vs::const_iterator ic; - for ( ic=compatibleOptionOrCredits.begin(); ic!=compatibleOptionOrCredits.end(); ++ic ) - { - if ( isFromBrickFamily( brick, (*ic) ) ) - break; - } - if ( ic == compatibleOptionOrCredits.end() ) - { - addError( errorStr, toString( "This family is not compatible with options/credits of root %s", rootBrick.c_str() ), nbGrammarErrors ); - } - } - } -} - - -/* - * Preconditions: - * - grammarErrors.size() == phrase.size() - * - r < phrase.size() - * - * Note: does not check that all bricks should have a different family - */ -void checkGrammar( const vs& phrase, uint& r, vs& grammarErrors, uint& nbGrammarErrors, const string& rootBrick, bool readNext=true ) -{ - uint origR = r; - string grammarBrick = phrase[origR]; - strupr( grammarBrick ); - - // Check option/credit - checkOptionOrCreditCompatibility( grammarErrors[r], phrase[r], rootBrick, nbGrammarErrors ); - - // Check mandatory/parameter - vs chFamilies; - getChildrenBricks( grammarBrick, chFamilies ); - ++r; - for ( vs::const_iterator icf=chFamilies.begin(); icf!=chFamilies.end(); ++icf ) - { - // Detect incomplete phrase - if ( r >= phrase.size() ) - { - addError( grammarErrors[origR], "Missing mandatory/parameter " + (*icf) + " at the end", nbGrammarErrors ); - break; - } - - // Detect wrong brick family - if ( isFromBrickFamily( phrase[r], (*icf) ) ) - { - // Check grammar using child as root - checkGrammar( phrase, r, grammarErrors, nbGrammarErrors, phrase[r], false ); - } - else - { - addError( grammarErrors[r], "Error: " + (*icf) + " expected (mandatory/parameter of " + grammarBrick + ")", nbGrammarErrors ); - ++r; - } - } - - // Next - if ( readNext && (r < phrase.size()) ) - { - checkGrammar( phrase, r, grammarErrors, nbGrammarErrors, rootBrick ); - } -} - - -/* - * - */ -char getDocFileLetter( const string& sheetName ) -{ - // skip abm_mt_, abm_ml_... - char letter = 'a'; - uint nbUnderscoresToSkip = 2, nbUnderscoresFound = 0; - for ( uint c=0; c!=sheetName.size(); ++c ) - { - if ( nbUnderscoresFound == nbUnderscoresToSkip ) - { - letter = sheetName[c]; - break; - } - if ( sheetName[c] == '_' ) - ++nbUnderscoresFound; - } - return tolower( letter ); -} - - -//----------------------------------------------- -// testPhraseGrammarAndProduceDoc -// -//----------------------------------------------- -bool testPhraseGrammarAndProduceDoc( const string& sheetName, const vs& phrase ) -{ - string filename = strlwr( sheetName ) + "." + phSheetType; - string phraseStatus; - bool isPhraseCorrect = true; - const char *rejectedstr = "(grammatically invalid)"; - - // Check grammar for this phrase - vs grammarErrors( phrase.size() ); - uint nbGrammarErrors = 0, r = 0; - checkGrammar( phrase, r, grammarErrors, nbGrammarErrors, phrase[0] ); - if ( nbGrammarErrors != 0 ) - { - InvalidPhrases.push_back( sheetName ); - isPhraseCorrect = false; - phraseStatus = rejectedstr; - } - - // Look-up phrase title - string phraseTitle = PhraseTitles[sheetName]; - - // Output phrase description - char letter = 'a'; - if ( (! MultipleDocFiles) && (sheetName.size() > 3) ) - { - letter = tolower( sheetName[3] ); - } - else - { - letter = getDocFileLetter( sheetName ); - } - if ( letter < 'a' ) - letter = 'a'; - else if ( letter > 'z' ) - letter = 'z'; - FILE *htmlFile = PhraseDocFiles[letter - 'a']; - sint sabrinaCost; - fprintf( htmlFile, "

    %s %s %s

      \n", sheetName.c_str(), filename.c_str(), phraseTitle.c_str(), phraseStatus.c_str() ); - vector minBrickSkills( phrase.size() ); - vector minBrickSkillValues( phrase.size(), 0 ); - string brickMinSkill, maxSkill; - sint posCost = 0, negCost = 0, totalCost; - uint maxSkillValue = 0, brickMinSkillValue; - for ( uint i=0; i!=phrase.size(); ++i ) - { - printBrickInfo( htmlFile, phrase[i], grammarErrors[i], sabrinaCost, brickMinSkillValue, brickMinSkill ); - if ( sabrinaCost > 0 ) - posCost += sabrinaCost; - else - negCost += sabrinaCost; - minBrickSkillValues[i] = brickMinSkillValue; - minBrickSkills[i] = brickMinSkill; - if ( brickMinSkillValue > maxSkillValue ) - maxSkillValue = brickMinSkillValue; - } - for ( uint i=0; i!=phrase.size(); ++i ) - { - if ( minBrickSkillValues[i] == maxSkillValue ) - { - if ( maxSkill.find( minBrickSkills[i] ) == string::npos ) - { - if ( ! maxSkill.empty() ) - maxSkill += "; "; - maxSkill += minBrickSkills[i]; - } - } - } - if ( phrase.size() > 1 ) - { - string effectOrOptionBrick = phrase[1]; - strupr( effectOrOptionBrick ); - if ( ! PhraseNames.insert( make_pair( sheetName, BrickInfo[effectOrOptionBrick].Text ) ).second ) - nlwarning( "Found duplicate phrase %s", sheetName.c_str() ); - } - Progression.insert( make_pair( maxSkillValue, make_pair( sheetName, maxSkill ) ) ); - totalCost = posCost + negCost; - PhraseSabrinaCosts.insert( make_pair(sheetName,totalCost) ); - char *redbegin = "", *redend = ""; - if ( totalCost > 0 ) - { - map::const_iterator itCastable = PhraseCastable.find(sheetName); - if( itCastable != PhraseCastable.end() ) - { - if( (*itCastable).second ) - { - redbegin = ""; - redend = ""; - PhrasesWithInvalidCost.push_back( sheetName ); - isPhraseCorrect = false; - } - } - } - fprintf( htmlFile, "
    • %sTotal sabrina cost: +%d %d = %d%s
    • \n", redbegin, posCost, negCost, totalCost, redend ); - fprintf( htmlFile, "
    • Minimum skill value required: %d
    • \n", maxSkillValue ); - fprintf( htmlFile, "

    \n" ); - if ( ! isPhraseCorrect ) - { - ++NbSheetsRejected; - } - return isPhraseCorrect; - -} // testPhraseGrammarAndProduceDoc // - - - - - -/* - * - */ -inline bool isSeparator( char c ) -{ - return (c == ' ') || (c == '\t'); -} - - - -//----------------------------------------------- -// produceDocFromExistingPhrases -// -// - Phrases -//----------------------------------------------- -void produceDocFromExistingPhrases() -{ - vs files; - CPath::getPathContent( PhrasePath, true, false, true, files ); - - NbSheetsRead = 0; - for ( vs::const_iterator ip=files.begin(); ip!=files.end(); ++ip ) - { - if ( CFile::getExtension( *ip ) == phSheetType ) - { - // Read george sheet - NLMISC::CSmartPtr form = (UForm*)FormLoader->loadForm( (*ip).c_str() ); - if ( ! form ) - nlerror( "Can't load sheet %s", (*ip).c_str() ); - - // Get the bricks of the phrase - vs phrase; - for ( uint i=0; i!=100; ++i ) - { - string value; - form->getRootNode().getValueByName( value, toString( "brick %u", i ).c_str() ); - if ( !value.empty() ) - { - strupr( value ); - phrase.push_back( CFile::getFilenameWithoutExtension( value ) ); - } - } - - Phrases.insert( make_pair(CFile::getFilenameWithoutExtension( *ip ), phrase) ); - - // look if phrase is castable - bool castable; - form->getRootNode().getValueByName( castable, "castable"); - PhraseCastable.insert( make_pair(CFile::getFilenameWithoutExtension( *ip ), castable) ); - - // Test grammar and produce doc - testPhraseGrammarAndProduceDoc( CFile::getFilenameWithoutExtension( *ip ), phrase ); - - ++NbSheetsRead; - } - } - nlinfo( "Total: %u phrases", NbSheetsRead ); - -} // produceDocFromExistingPhrases // - - -/* - * - */ -string getLink( const string& phrase ) -{ - string res; - if ( MultipleDocFiles && (! phrase.empty()) ) - { - res += DocFileName + "_" + getDocFileLetter( phrase ) + ".html"; - } - else - { - res += DocFileName + ".html"; - } - res += "#" + phrase; - //nlinfo( "%s", res.c_str() ); - return res; -} - - -/* - * - */ -void usage(char *argv0, FILE *out) -{ - fprintf(out, "\n"); - fprintf(out, "Syntax: %s [-p ] [-o ] [-b] [-d] [-m] [-n]\n", argv0); - fprintf(out, "-o: output phrase path (or input if -d is set)\n"); - fprintf(out, "-b: produce doc about brick learning infos\n"); - fprintf(out, "-d: browse existing phrases in (and subdirs) and produce doc\n"); - fprintf(out, "-m: multiple doc html files, alphabetically (use with -g,-c,-d with numerous phrases)\n"); - fprintf(out, "-n: no hypertext (don't produce links phrases)\n"); - - fprintf(out, "\n"); -} - - - - -//----------------------------------------------- -// makeIndexFile -// -//----------------------------------------------- -void makeIndexFile() -{ - FILE * indexFile = fopen( ("_" + DocFileNameRoot + "_INDEX.html").c_str(), "wt" ); - if( indexFile ) - { - fprintf( indexFile, ("\n\nSummary of " + DocFileNameRoot + "\n\n").c_str() ); - - DocFileName = DocFileNameRoot + "_actions"; - - if ( MultipleDocFiles ) - { - // One HTML file per alphabet letter - for ( uint l=0; l!=26; ++l ) - { - string filename = toString( "%s_%c.html", DocFileName.c_str(), 'a'+l ); - PhraseDocFiles[l] = fopen( filename.c_str(), "wt" ); - fprintf( PhraseDocFiles[l], ("\n\n" + DocFileName + toString( " - %c", (char)('A'+l) ) + "\n\n").c_str() ); - fprintf( indexFile, ("" + (char)('A'+l) + " ").c_str() ); - } - } - else - { - // One single HTML file - fprintf( indexFile, ("Go to action details").c_str() ); - PhraseDocFiles[0] = fopen( (DocFileName + ".html").c_str(), "wt" ); - fprintf( PhraseDocFiles[0], ("\n\n" + DocFileName + "\n\n").c_str() ); - for ( uint l=1; l!=26; ++l ) - { - PhraseDocFiles[l] = PhraseDocFiles[0]; - } - } - fprintf( indexFile, ("
    Go to action by skill value\n").c_str() ); - fprintf( indexFile, ("
    Go to action by skill value (detail)\n").c_str() ); - fprintf( indexFile, ("
    Go to action by skill
    \n").c_str() ); - - if( GenerateBrickProgression ) - { - fprintf( indexFile, ("

    Go to brick list
    \n").c_str() ); - } - - produceDocFromExistingPhrases(); - - for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) - { - const string& phraseCode = (*ip).second.first; - string link = Hypertext ? toString( "%s", getLink(phraseCode).c_str(), phraseCode.c_str() ) : "" + phraseCode + ""; - PhraseCodeToLink.insert( make_pair(phraseCode,link) ); - } - - // Summary (errors in phrases) - fprintf( indexFile, "
    \n" ); - fprintf( indexFile, ("Summary of " + DocFileName + "
    \n").c_str() ); - if ( NbSheetsGenTries != 0 ) - fprintf( indexFile, "

    %u valid sheets written on %u

    \n", NbSheetsWritten, NbSheetsGenTries ); - if ( NbSheetsRead != 0 ) - fprintf( indexFile, "

    %u sheets read

    \n", NbSheetsRead ); - fprintf( indexFile, "

    %u invalid sheets rejected", NbSheetsRejected ); - if ( ! PhrasesWithInvalidCost.empty() ) - { - fprintf( indexFile, "

    Phrases with invalid sabrina cost:
    \n" ); - for ( vs::const_iterator iip=PhrasesWithInvalidCost.begin(); iip!=PhrasesWithInvalidCost.end(); ++iip ) - { - string link = Hypertext ? toString( "%s", getLink(*iip).c_str(), (*iip).c_str() ) : "" + (*iip) + ""; - fprintf( indexFile, "%s
    \n", link.c_str() ); - } - fprintf( indexFile, "

    \n" ); - } - else - { - fprintf( indexFile, "

    All phrases have valid sabrina cost.

    \n" ); - } - if ( ! InvalidPhrases.empty() ) - { - fprintf( indexFile, "

    Grammatically invalid phrases:
    \n" ); - for ( vs::const_iterator iip=InvalidPhrases.begin(); iip!=InvalidPhrases.end(); ++iip ) - { - string link = Hypertext ? toString( "%s", getLink(*iip).c_str(), (*iip).c_str() ) : "" + (*iip) + ""; - fprintf( indexFile, "%s
    \n", link.c_str() ); - } - fprintf( indexFile, "

    \n" ); - } - else - { - fprintf( indexFile, "

    All phrases are grammatically valid.

    \n" ); - } - fprintf( indexFile, "\n" ); - fclose( indexFile ); - - if ( MultipleDocFiles ) - { - for ( uint l=0; l!=26; ++l ) - { - fprintf( PhraseDocFiles[l], "\n" ); - fclose( PhraseDocFiles[l] ); - } - } - else - { - fprintf( PhraseDocFiles[0], "\n" ); - fclose( PhraseDocFiles[0] ); - } - } - -} // makeIndexFile // - - -//----------------------------------------------- -// makeActionsBySkillGroupFile -// -//----------------------------------------------- -void makeActionsBySkillGroupFile() -{ - // progression by skill - FILE * actionsBySkillGroupFile = fopen( (DocFileName + "__by_skill.html").c_str(), "wt" ); - if( actionsBySkillGroupFile ) - { - fprintf( actionsBySkillGroupFile, ("\n\nProgression of " + DocFileName + "\n\n").c_str() ); - fprintf( actionsBySkillGroupFile, "
    \n" ); - fprintf( actionsBySkillGroupFile, "

    ACTIONS BY SKILL GROUP:
    \n

    "; - if ( c == keyColumn ) - s += key; // key should be a substr of toString( c ) - else - { - if ( lightMode ) - s += "\""; - else - s += columnToString( c ); - } - s += "
    "; + if ( c == keyColumn ) + s += key; // key should be a substr of toString( c ) + else + { + if ( lightMode ) + s += "\""; + else + s += columnToString( c ); + } + s += "
    \n" ); - map > phrasesBySkill; - for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) - { - const string& phraseCode = (*ip).second.first; - string skillName = (*ip).second.second.substr(0,(*ip).second.second.find(" ")); - string skillValueStr = (*ip).second.second.substr((*ip).second.second.find(" ")+1,(*ip).second.second.size()-(*ip).second.second.find(" ")-1); - uint skillValue = atoi(skillValueStr.c_str()); - - map >::iterator it = phrasesBySkill.find(skillName); - if( it != phrasesBySkill.end() ) - { - (*it).second.insert(make_pair(skillValue,phraseCode)); - } - else - { - multimap m; - m.insert(make_pair(skillValue,phraseCode)); - phrasesBySkill.insert( make_pair(skillName,m) ); - } - } - - map >::iterator itPhrasesBySkill; - for( itPhrasesBySkill = phrasesBySkill.begin(); itPhrasesBySkill != phrasesBySkill.end(); ++itPhrasesBySkill ) - { - CVectorSString dicoResult; - Dico.lookup( (*itPhrasesBySkill).first, dicoResult, true ); - if( !dicoResult.empty() ) - fprintf( actionsBySkillGroupFile, "\n", (*itPhrasesBySkill).first.c_str(),dicoResult[0].c_str()); - else - fprintf( actionsBySkillGroupFile, "\n", (*itPhrasesBySkill).first.c_str(),(*itPhrasesBySkill).first.c_str()); - } - for( itPhrasesBySkill = phrasesBySkill.begin(); itPhrasesBySkill != phrasesBySkill.end(); ++itPhrasesBySkill ) - { - CVectorSString dicoResult; - Dico.lookup( (*itPhrasesBySkill).first, dicoResult, true ); - if( !dicoResult.empty() ) - fprintf( actionsBySkillGroupFile, "\n", (*itPhrasesBySkill).first.c_str(), dicoResult[0].c_str() ); - else - fprintf( actionsBySkillGroupFile, "\n", (*itPhrasesBySkill).first.c_str(),(*itPhrasesBySkill).first.c_str() ); - - multimap::iterator it; - for( it = (*itPhrasesBySkill).second.begin(); it != (*itPhrasesBySkill).second.end(); ++it ) - { - fprintf( actionsBySkillGroupFile, "\n", (*it).first, PhraseCodeToLink[(*it).second].c_str(), PhraseTitles[(*it).second].c_str()); - } - } - fprintf( actionsBySkillGroupFile, "
    %s
    %s
    %s
    %s
    %d%s%s

    \n" ); - fprintf( actionsBySkillGroupFile, "\n" ); - fclose( actionsBySkillGroupFile ); - } - -} // makeActionsBySkillGroupFile // - - - -//----------------------------------------------- -// makeActionsBySkillValueFile -// -//----------------------------------------------- -void makeActionsBySkillValueFile() -{ - FILE * actionsBySkillValueFile = fopen( (DocFileName + "__by_skill_value.html").c_str(), "wt" ); - if( actionsBySkillValueFile ) - { - fprintf( actionsBySkillValueFile, ("\n\nProgression of " + DocFileName + "\n\n").c_str() ); - - // Progression (phrases sorted by skill value) - fprintf( actionsBySkillValueFile, "
    \n" ); - fprintf( actionsBySkillValueFile, "

    ACTIONS BY SKILL VALUE: [detail]\n

    \n",(DocFileName + "__by_skill_value_detail.html").c_str() ); - fprintf( actionsBySkillValueFile, "\n"); - map phraseCodeToLink; - for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) - { - const string& phraseCode = (*ip).second.first; - fprintf( actionsBySkillValueFile, "\n", PhraseCodeToLink[phraseCode].c_str(), /*newbrickTitle.c_str(),*/ PhraseTitles[phraseCode].c_str(), (*ip).second.second.c_str() ); - } - fprintf( actionsBySkillValueFile, "
    FileNameSkill needed
    %s%s%s

    \n" ); - fprintf( actionsBySkillValueFile, "\n" ); - fclose( actionsBySkillValueFile ); - } - -} // makeActionsBySkillValueFile // - - -//----------------------------------------------- -// makeActionsBySkillValueDetailFile -// -//----------------------------------------------- -void makeActionsBySkillValueDetailFile() -{ - FILE * actionsBySkillValueDetailFile = fopen( (DocFileName + "__by_skill_value_detail.html").c_str(), "wt" ); - if( actionsBySkillValueDetailFile ) - { - fprintf( actionsBySkillValueDetailFile, ("\n\nProgression of " + DocFileName + "\n\n").c_str() ); - - // Progression summary (phrases sorted by skill value) - fprintf( actionsBySkillValueDetailFile, "
    \n" ); - fprintf( actionsBySkillValueDetailFile, "

    ACTIONS BY SKILL VALUE:
    \n

    \n" ); - fprintf( actionsBySkillValueDetailFile, "\n"); - - set effects; - map > effectAndModifiers; - for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) - { - const string& phraseCode = (*ip).second.first; - fprintf( actionsBySkillValueDetailFile, "",PhraseCodeToLink[phraseCode].c_str(), PhraseTitles[phraseCode].c_str(), (*ip).second.second.c_str(),PhraseSabrinaCosts[phraseCode]); - - msvs::iterator itPhrases = Phrases.find( phraseCode ); - if( itPhrases != Phrases.end() ) - { - string effect; - uint modifierCount = 0; - uint creditCount = 0; - for( uint i = 0; i<(*itPhrases).second.size(); ++i ) - { - string brick = (*itPhrases).second[i]; - string color; - switch ( brick[brick.size()-getBrickTypeLetterRPos(brick)] ) - { - case 'P': color = "Black"; - break; - case 'E': - { - color = "Brown"; - effects.insert(brick); - if( effectAndModifiers.find(brick) == effectAndModifiers.end() ) - { - set s; - effectAndModifiers.insert( make_pair(brick,s) ); - } - effect = brick; - } - break; - case 'O': color = "Green"; - break; - case 'M': - { - color = "Blue"; - effectAndModifiers[effect].insert(brick); - modifierCount++; - } - break; - case 'C': color = "Red"; creditCount++; - break; - default: - color = "Black"; - } - string text = BrickInfo[brick].Text; - if( text.empty() ) - { - text = strlwr(brick); - nlwarning("%s not found in BrickInfo",brick.c_str()); - } - else - { - if(text.find("$|sap")!=-1) - { - text = text.substr(0,text.size()-5); - string str = brick.substr(brick.size()-5,5); - text += toString(atoi(str.c_str())); - } - } - fprintf( actionsBySkillValueDetailFile, "",color.c_str(),text.c_str()); - } - } - else - { - nlerror("not found : %s",phraseCode.c_str()); - } - fprintf( actionsBySkillValueDetailFile, "\n"); - } - fprintf( actionsBySkillValueDetailFile, "
    FileNameSkill needed
    Sabrina costBricks ...
    %s%s%s%d%s

    \n" ); - fprintf( actionsBySkillValueDetailFile, "\n" ); - fclose( actionsBySkillValueDetailFile ); - } - -} // makeActionsBySkillValueDetailFile // - - -//----------------------------------------------- -// validateBrick -// -//----------------------------------------------- -bool validateBrick( const string& brk ) -{ - if(brk[1]=='C') return true; - if(brk[1]=='F') return true; - if(brk[1]=='H') return true; - if(brk[1]=='M') return true; - if(brk[1]=='S') return true; - return false; - -} // validateBrick // - - - -//----------------------------------------------- -// makeSkillTreeFile -// -//----------------------------------------------- -void makeSkillTreeFile( char filter, string skillFamily, bool withTraduction ) -{ - vector > skillsArray; - skillsArray.resize(6); // 6 tranches de skill - uint i; - for( i = 0; i maxLine ) - { - maxLine = skillsArray[i].size(); - } - } - - string filename = skillFamily + "_skill_tree.html"; - string filenameWithTraduction = skillFamily + "_skill_tree_detailed.html"; - FILE * skillTreeFile; - if( withTraduction ) - skillTreeFile = fopen( filenameWithTraduction.c_str(), "wt" ); - else - skillTreeFile = fopen( filename.c_str(), "wt" ); - fprintf( skillTreeFile,"\n"); - fprintf( skillTreeFile,"\n"); - fprintf( skillTreeFile,"SKILL TREE ( %s )\n",skillFamily.c_str()); - fprintf( skillTreeFile,"\n"); - if( withTraduction ) - fprintf( skillTreeFile,"SKILL TREE ( %s )\n",skillFamily.c_str()); - else - fprintf( skillTreeFile,"SKILL TREE ( %s ) [display traduction]
    \n",skillFamily.c_str(),filenameWithTraduction.c_str()); - fprintf( skillTreeFile,"
    \n"); - fprintf( skillTreeFile,"\n"); - - uint j; - // print line by line - for( j=0; j"); - // for each column - for( i=0; i::iterator itSkillcode; - for( itSkillcode = skillsArray[i].begin(), p=0; itSkillcode != skillsArray[i].end() && p%s : ???",(*itSkillcode).first.c_str()); - else - fprintf( skillTreeFile,"",dicoResult[0].c_str()); - } - else - fprintf( skillTreeFile,"",(*itSkillcode).first.c_str()); - } - else - fprintf( skillTreeFile,""); - } - fprintf( skillTreeFile,"\n"); - } - - fprintf( skillTreeFile, "
    0 to 2020 to 5050 to 100100 to 150150 to 200200 to 250
    %s%s

    \n" ); - fprintf( skillTreeFile, "\n" ); - fclose( skillTreeFile ); - -} // makeSkillTreeFile // - - - - - -//----------------------------------------------- -// MAIN -// -//----------------------------------------------- -int main(int argc, char* argv[]) -{ - // parse command line - const char *inputFilename = NULL; - for ( uint i=1; (sint)i!=argc; i++ ) - { - const char *arg = argv[i]; - if ( arg[0] == '-' ) - { - switch ( arg[1] ) - { - case 'p': - ++i; - if ( (sint)i == argc ) - { - fprintf( stderr, "Missing after -p option\n" ); - usage( argv[0], stderr ); - exit( 0 ); - } - inputSheetPath = argv[i]; - break; - case 'o': - ++i; - if ( (sint)i == argc ) - { - fprintf( stderr, "Missing after -o option\n" ); - usage( argv[0], stderr ); - exit( 0 ); - } - PhrasePath = argv[i]; - if ( PhrasePath[PhrasePath.size()-1] != '/' ) - PhrasePath += '/'; - break; - case 'b' : - GenerateBrickProgression = true; - break; - case 'd': - ProduceDocFromExistingPhrases = true; - break; - case 'm': - MultipleDocFiles = true; - break; - case 'n': - Hypertext = false; - break; - } - } - else - { - if ( CFile::getExtension(arg) == "csv" ) - { - inputFilename = arg; - } - else - nlerror( "Unrecognized extension in %s", arg ); - - } - } - - Dico.init(); - - loadSheetPath(); - FormLoader = UFormLoader::createLoader(); - CSheetId::init(); - - CSheetId skillTreeSheet("skills.skill_tree"); - CSmartPtr skillTreeForm = FormLoader->loadForm( "skills.skill_tree" ); - SkillsTree.readGeorges( skillTreeForm, skillTreeSheet ); - - - makeSkillTreeFile('C',"craft", false); - makeSkillTreeFile('F',"fight", false); - makeSkillTreeFile('H',"forage", false); - makeSkillTreeFile('M',"magic", false); - - makeSkillTreeFile('C',"craft", true); - makeSkillTreeFile('F',"fight", true); - makeSkillTreeFile('H',"forage", true); - makeSkillTreeFile('M',"magic", true); - - - // Load bricks from the csv - UseBricks = ProduceDocFromExistingPhrases; - if ( UseBricks ) - { - if ( ! inputFilename ) - { - usage( argv[0], stderr ); - exit( 0 ); - } - loadBricks( inputFilename ); - } - - - // Phrases - if ( ProduceDocFromExistingPhrases ) - { - loadBrickGrammar(); - loadBrickTitles(); - loadPhraseTitles(); - - DocFileNameRoot = toString( "%s", CFile::getFilenameWithoutExtension( inputFilename ).c_str() ); - - // index - makeIndexFile(); - - // progression by skill - makeActionsBySkillGroupFile(); - - // Progression (phrases sorted by skill value) - makeActionsBySkillValueFile(); - - // Progression (phrases sorted by skill value + detail) - makeActionsBySkillValueDetailFile(); - - } - - - if( GenerateBrickProgression ) - { - map > > levelToBrick; - - map phraseToSkill; - - for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) - { - const string& phraseCode = (*ip).second.first; - - string skillTmp = (*ip).second.second.c_str(); - - phraseToSkill.insert( make_pair(phraseCode,skillTmp) ); - - if(skillTmp.empty()==false) - { - // get skill - string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); - - // get level - string levelStr; - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - if(levelStr.find(".")!=-1) levelStr = levelStr.substr(0,levelStr.size()-1); - uint level = atoi(levelStr.c_str()); - - - map > >::iterator itLvl = levelToBrick.find(level); - if( itLvl == levelToBrick.end() ) - { - set s; - map > mp; - mp.insert(make_pair(skill,s)); - levelToBrick.insert(make_pair(level,mp)); - } - else - { - if( (*itLvl).second.find(skill) == (*itLvl).second.end() ) - { - set s; - (*itLvl).second.insert( make_pair(skill,s) ); - } - } - - msvs::iterator itPhrases = Phrases.find( phraseCode ); - if( itPhrases != Phrases.end() ) - { - string effect; - for( uint i = 0; i<(*itPhrases).second.size(); ++i ) - { - string brick = (*itPhrases).second[i]; - - if( levelToBrick[level][skill].find(brick) == levelToBrick[level][skill].end() ) - { - levelToBrick[level][skill].insert(brick); - } - } - } - } - } - - - - - // get family & color - map brickToColor; - map brickToFamily; - map::iterator itBInf; - for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) - { - string brk = (*itBInf).first; - - if(!validateBrick(brk)) continue; - - string color; - string family; - if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='M' ) - { - color = "Blue"; - family = "Modifier"; - } - if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='C' ) - { - color = "Red"; - family = "Credit"; - } - if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='O' ) - { - color = "Green"; - family = "Option"; - } - if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='P' ) - { - color = "Black"; - family = "Root"; - } - if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='E' ) - { - color = "Brown"; - family = "Effect"; - } - - brickToColor.insert(make_pair(brk,color)); - brickToFamily.insert(make_pair(brk,family)); - } - - // get phrases where the brick can be found - map > brickToPhrases; - msvs::iterator itPhrases; - for( itPhrases=Phrases.begin(); itPhrases!=Phrases.end(); ++itPhrases ) - { - for( uint i = 0; i<(*itPhrases).second.size(); ++i ) - { - string brick = (*itPhrases).second[i]; - if( brickToPhrases.find(brick)==brickToPhrases.end() ) - { - map m; - - m.insert(make_pair((*itPhrases).first,phraseToSkill[(*itPhrases).first])); - brickToPhrases.insert(make_pair(brick,m)); - } - else - { - brickToPhrases[brick].insert(make_pair((*itPhrases).first,phraseToSkill[(*itPhrases).first])); - } - } - } - - // get skill when a brick is learnt - map brickToLearnSkill; - map >::iterator itLearn; - for( itLearn=brickToPhrases.begin(); itLearn!=brickToPhrases.end(); ++itLearn ) - { - string minSkill; - uint minLevel = 250; - - mss::iterator itPh; - for( itPh=(*itLearn).second.begin(); itPh!=(*itLearn).second.end(); ++itPh ) - { - string skillTmp = (*itPh).second; - string levelStr; - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - uint level = atoi(levelStr.c_str()); - - if( level\n"); - fprintf( brickPhraseDocFile_m,"\n"); - fprintf( brickPhraseDocFile_m,"Brick phrases\n"); - fprintf( brickPhraseDocFile_m,"\n"); - fprintf( brickPhraseDocFile_m,"
    \n"); - - filename = DocFileNameRoot + "_c.html"; - FILE * brickPhraseDocFile_c = fopen( filename.c_str(), "wt" ); - fprintf( brickPhraseDocFile_c,"\n"); - fprintf( brickPhraseDocFile_c,"\n"); - fprintf( brickPhraseDocFile_c,"Brick phrases\n"); - fprintf( brickPhraseDocFile_c,"\n"); - fprintf( brickPhraseDocFile_c,"
    \n"); - - filename = DocFileNameRoot + "_o.html"; - FILE * brickPhraseDocFile_o = fopen( filename.c_str(), "wt" ); - fprintf( brickPhraseDocFile_o,"\n"); - fprintf( brickPhraseDocFile_o,"\n"); - fprintf( brickPhraseDocFile_o,"Brick phrases\n"); - fprintf( brickPhraseDocFile_o,"\n"); - fprintf( brickPhraseDocFile_o,"
    \n"); - - filename = DocFileNameRoot + "_p.html"; - FILE * brickPhraseDocFile_p = fopen( filename.c_str(), "wt" ); - fprintf( brickPhraseDocFile_p,"\n"); - fprintf( brickPhraseDocFile_p,"\n"); - fprintf( brickPhraseDocFile_p,"Brick phrases\n"); - fprintf( brickPhraseDocFile_p,"\n"); - fprintf( brickPhraseDocFile_p,"
    \n"); - - filename = DocFileNameRoot + "_e.html"; - FILE * brickPhraseDocFile_e = fopen( filename.c_str(), "wt" ); - fprintf( brickPhraseDocFile_e,"\n"); - fprintf( brickPhraseDocFile_e,"\n"); - fprintf( brickPhraseDocFile_e,"Brick phrases\n"); - fprintf( brickPhraseDocFile_e,"\n"); - fprintf( brickPhraseDocFile_e,"
    \n"); - - for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) - { - string brk = (*itBInf).first; - - if(!validateBrick(brk)) continue; - - string code = strlwr(brk.c_str()); - - if(brickToFamily[brk]=="Modifier") - fprintf( brickPhraseDocFile_m,"\n",brk.c_str(),code.c_str()); - if(brickToFamily[brk]=="Credit") - fprintf( brickPhraseDocFile_c,"\n",brk.c_str(),code.c_str()); - if(brickToFamily[brk]=="Option") - fprintf( brickPhraseDocFile_o,"\n",brk.c_str(),code.c_str()); - if(brickToFamily[brk]=="Effect") - fprintf( brickPhraseDocFile_e,"\n",brk.c_str(),code.c_str()); - if(brickToFamily[brk]=="Root") - fprintf( brickPhraseDocFile_p,"\n",brk.c_str(),code.c_str()); - - map >::iterator itPhrases = brickToPhrases.find(brk); - if( itPhrases != brickToPhrases.end() ) - { - map::iterator itPh; - for( itPh=(*itPhrases).second.begin(); itPh!=(*itPhrases).second.end(); ++itPh ) - { - if(brickToFamily[brk]=="Modifier") - fprintf( brickPhraseDocFile_m,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); - if(brickToFamily[brk]=="Credit") - fprintf( brickPhraseDocFile_c,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); - if(brickToFamily[brk]=="Option") - fprintf( brickPhraseDocFile_o,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); - if(brickToFamily[brk]=="Effect") - fprintf( brickPhraseDocFile_e,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); - if(brickToFamily[brk]=="Root") - fprintf( brickPhraseDocFile_p,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); - } - } - } - fprintf( brickPhraseDocFile_m, "
    %s
    %s
    %s
    %s
    %s
    %s
    %s
    %s
    %s
    %s

    \n" ); - fprintf( brickPhraseDocFile_m, "\n" ); - fclose( brickPhraseDocFile_m ); - - fprintf( brickPhraseDocFile_c, "

    \n" ); - fprintf( brickPhraseDocFile_c, "\n" ); - fclose( brickPhraseDocFile_c ); - - fprintf( brickPhraseDocFile_o, "

    \n" ); - fprintf( brickPhraseDocFile_o, "\n" ); - fclose( brickPhraseDocFile_o ); - - fprintf( brickPhraseDocFile_e, "

    \n" ); - fprintf( brickPhraseDocFile_e, "\n" ); - fclose( brickPhraseDocFile_e ); - - fprintf( brickPhraseDocFile_p, "

    \n" ); - fprintf( brickPhraseDocFile_p, "\n" ); - fclose( brickPhraseDocFile_p ); - - - // CODE - - // write header and title bar - filename = DocFileNameRoot + ".html"; - FILE * brickDocFile = fopen( filename.c_str(), "wt" ); - fprintf( brickDocFile,"\n"); - fprintf( brickDocFile,"\n"); - fprintf( brickDocFile,"Bricks infos\n"); - fprintf( brickDocFile,"\n"); - fprintf( brickDocFile,"
    \n"); - fprintf( brickDocFile,"\n"); - fprintf( brickDocFile,"\n"); - fprintf( brickDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickDocFile,"\n"); - fprintf( brickDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickDocFile,"\n"); - fprintf( brickDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickDocFile,"\n"); - fprintf( brickDocFile,"\n"); - - - // write infos - for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) - { - string brk = (*itBInf).first; - - if(!validateBrick(brk)) continue; - - string skillTmp = (*itBInf).second.LearnSkills; - string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); - CVectorSString dicoResult; - Dico.lookup( skill, dicoResult, true ); - if(dicoResult.empty()) continue; - - // color - string color = brickToColor[brk]; - - // code - string code = strlwr(brk.c_str()); - fprintf( brickDocFile, "\n",color.c_str(),code.c_str()); - - // name - string name = (*itBInf).second.Text; - fprintf( brickDocFile, "\n",name.c_str()); - - // family - string family = brickToFamily[brk]; - fprintf( brickDocFile, "\n",color.c_str(),family.c_str()); - - // required skill name - fprintf( brickDocFile, "\n",dicoResult[0].c_str()); - - // required skill value - string levelStr; - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - fprintf( brickDocFile, "\n",levelStr.c_str()); - - // learn skill name - string learnSkillTmp = brickToLearnSkill[brk]; - skill = learnSkillTmp.substr(0,learnSkillTmp.find_first_of(" ")); - fprintf( brickDocFile, "\n",skill.c_str()); - - // learn skill value - if( learnSkillTmp.find(";") != -1 ) - { - sint idx = learnSkillTmp.find_first_of(" "); - levelStr = learnSkillTmp.substr(idx+1,learnSkillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = learnSkillTmp.find_first_of(" "); - levelStr = learnSkillTmp.substr(idx+1,learnSkillTmp.size()-idx); - } - fprintf( brickDocFile, "\n",levelStr.c_str()); - - - // phrase list - fprintf( brickDocFile, "\n"); - } - fprintf( brickDocFile, "
    *Code*NameFamilyRequired Skill NameRequired Skill ValueLearn Skill NameLearn Skill ValueFound In Phrases
    %s%s%s%s%s%s%s"); - map >::iterator itPhrases = brickToPhrases.find(brk); - if( itPhrases != brickToPhrases.end() ) - { - map::iterator itPh; - uint i; - for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) - { - if( MultipleDocFiles ) - fprintf( brickDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); - else - fprintf( brickDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); - } - if( i==2 ) - { - char type = family[0]; - fprintf( brickDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); - } - } - - fprintf( brickDocFile, "

    \n" ); - fprintf( brickDocFile, "\n" ); - fclose( brickDocFile ); - - - - // NAME - - // write header and title bar - filename = DocFileNameRoot + "_name.html"; - FILE * brickNameDocFile = fopen( filename.c_str(), "wt" ); - fprintf( brickNameDocFile,"\n"); - fprintf( brickNameDocFile,"\n"); - fprintf( brickNameDocFile,"Bricks infos\n"); - fprintf( brickNameDocFile,"\n"); - fprintf( brickNameDocFile,"
    \n"); - fprintf( brickNameDocFile,"\n"); - fprintf( brickNameDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickNameDocFile,"\n"); - fprintf( brickNameDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickNameDocFile,"\n"); - fprintf( brickNameDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickNameDocFile,"\n"); - fprintf( brickNameDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickNameDocFile,"\n"); - fprintf( brickNameDocFile,"\n"); - - map nameToCode; - for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) - { - string brk = (*itBInf).first; - - if(!validateBrick(brk)) continue; - - // code - string code = strlwr(brk.c_str()); - - // name - string name = (*itBInf).second.Text; - if( !name.empty()) - nameToCode.insert( make_pair(name,brk) ); - } - - mss::iterator itNTC; - for( itNTC=nameToCode.begin(); itNTC!=nameToCode.end(); ++itNTC ) - { - itBInf=BrickInfo.find((*itNTC).second); - - string brk = (*itBInf).first; - - if(!validateBrick(brk)) continue; - - string skillTmp = (*itBInf).second.LearnSkills; - string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); - CVectorSString dicoResult; - Dico.lookup( skill, dicoResult, true ); - if(dicoResult.empty()) continue; - - // color - string color = brickToColor[brk]; - - // code - string code = strlwr(brk.c_str()); - fprintf( brickNameDocFile, "\n",color.c_str(),code.c_str()); - - // name - string name = (*itBInf).second.Text; - fprintf( brickNameDocFile, "\n",name.c_str()); - - // family - string family = brickToFamily[brk]; - fprintf( brickNameDocFile, "\n",color.c_str(),family.c_str()); - - // required skill name - fprintf( brickNameDocFile, "\n",dicoResult[0].c_str()); - - // required skill value - string levelStr; - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - fprintf( brickNameDocFile, "\n",levelStr.c_str()); - - // learn skill name - skillTmp = brickToLearnSkill[brk]; - skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); - fprintf( brickNameDocFile, "\n",skill.c_str()); - - // learn skill value - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - fprintf( brickNameDocFile, "\n",levelStr.c_str()); - - - // phrase list - fprintf( brickNameDocFile, "\n"); - - } - - fprintf( brickNameDocFile, "
    Code*Name*FamilyRequired Skill NameRequired Skill ValueLearn Skill NameLearn Skill ValueFound In Phrases
    %s%s%s%s%s%s%s"); - map >::iterator itPhrases = brickToPhrases.find(brk); - if( itPhrases != brickToPhrases.end() ) - { - map::iterator itPh; - uint i; - for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) - { - if( MultipleDocFiles ) - fprintf( brickNameDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); - else - fprintf( brickNameDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); - } - if( i==2 ) - { - char type = family[0]; - fprintf( brickNameDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); - } - } - - fprintf( brickNameDocFile, "

    \n" ); - fprintf( brickNameDocFile, "\n" ); - fclose( brickNameDocFile ); - - - - - // FAMILY - - // write header and title bar - filename = DocFileNameRoot + "_family.html"; - FILE * brickFamilyDocFile = fopen( filename.c_str(), "wt" ); - fprintf( brickFamilyDocFile,"\n"); - fprintf( brickFamilyDocFile,"\n"); - fprintf( brickFamilyDocFile,"Bricks infos\n"); - fprintf( brickFamilyDocFile,"\n"); - fprintf( brickFamilyDocFile,"
    \n"); - fprintf( brickFamilyDocFile,"\n"); - fprintf( brickFamilyDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickFamilyDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickFamilyDocFile,"\n"); - fprintf( brickFamilyDocFile,"\n"); - fprintf( brickFamilyDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickFamilyDocFile,"\n"); - fprintf( brickFamilyDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickFamilyDocFile,"\n"); - fprintf( brickFamilyDocFile,"\n"); - - - // write infos - multimap familyToCode; - for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) - { - string brk = (*itBInf).first; - - if(!validateBrick(brk)) continue; - - // family - string family = brickToFamily[brk]; - - familyToCode.insert( make_pair(family,brk) ); - } - - multimap::iterator itFTC; - for( itFTC=familyToCode.begin(); itFTC!=familyToCode.end(); ++itFTC ) - { - itBInf=BrickInfo.find((*itFTC).second); - - string brk = (*itBInf).first; - - if(!validateBrick(brk)) continue; - - string skillTmp = (*itBInf).second.LearnSkills; - string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); - CVectorSString dicoResult; - Dico.lookup( skill, dicoResult, true ); - if(dicoResult.empty()) continue; - - // color - string color = brickToColor[brk]; - - // code - string code = strlwr(brk.c_str()); - fprintf( brickFamilyDocFile, "\n",color.c_str(),code.c_str()); - - // name - string name = (*itBInf).second.Text; - fprintf( brickFamilyDocFile, "\n",name.c_str()); - - // family - string family = brickToFamily[brk]; - fprintf( brickFamilyDocFile, "\n",color.c_str(),family.c_str()); - - // required skill name - fprintf( brickFamilyDocFile, "\n",dicoResult[0].c_str()); - - // required skill value - string levelStr; - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - fprintf( brickFamilyDocFile, "\n",levelStr.c_str()); - - // learn skill name - skillTmp = brickToLearnSkill[brk]; - skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); - fprintf( brickFamilyDocFile, "\n",skill.c_str()); - - // learn skill value - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - fprintf( brickFamilyDocFile, "\n",levelStr.c_str()); - - - // phrase list - fprintf( brickFamilyDocFile, "\n"); - } - fprintf( brickFamilyDocFile, "
    CodeName*Family*Required Skill NameRequired Skill ValueLearn Skill NameLearn Skill ValueFound In Phrases
    %s%s%s%s%s%s%s"); - map >::iterator itPhrases = brickToPhrases.find(brk); - if( itPhrases != brickToPhrases.end() ) - { - map::iterator itPh; - uint i; - for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) - { - if( MultipleDocFiles ) - fprintf( brickFamilyDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); - else - fprintf( brickFamilyDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); - } - if( i==2 ) - { - char type = family[0]; - fprintf( brickFamilyDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); - } - } - - fprintf( brickFamilyDocFile, "

    \n" ); - fprintf( brickFamilyDocFile, "\n" ); - fclose( brickFamilyDocFile ); - - - - - // REQUIRED SKILL VALUE - - // write header and title bar - filename = DocFileNameRoot + "_required_skill_value.html"; - FILE * brickRequiredDocFile = fopen( filename.c_str(), "wt" ); - fprintf( brickRequiredDocFile,"\n"); - fprintf( brickRequiredDocFile,"\n"); - fprintf( brickRequiredDocFile,"Bricks infos\n"); - fprintf( brickRequiredDocFile,"\n"); - fprintf( brickRequiredDocFile,"
    \n"); - fprintf( brickRequiredDocFile,"\n"); - fprintf( brickRequiredDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickRequiredDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickRequiredDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickRequiredDocFile,"\n"); - fprintf( brickRequiredDocFile,"\n"); - fprintf( brickRequiredDocFile,"\n"); - fprintf( brickRequiredDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickRequiredDocFile,"\n"); - fprintf( brickRequiredDocFile,"\n"); - - - // write infos - multimap requiredSkillValueToCode; - for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) - { - string brk = (*itBInf).first; - - if(!validateBrick(brk)) continue; - - // required skill value - string skillTmp = (*itBInf).second.LearnSkills; - string levelStr; - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - uint level = atoi(levelStr.c_str()); - - requiredSkillValueToCode.insert( make_pair(level,brk) ); - } - - multimap::iterator itRTC; - for( itRTC=requiredSkillValueToCode.begin(); itRTC!=requiredSkillValueToCode.end(); ++itRTC ) - { - itBInf=BrickInfo.find((*itRTC).second); - - string brk = (*itBInf).first; - - if(!validateBrick(brk)) continue; - - string skillTmp = (*itBInf).second.LearnSkills; - string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); - CVectorSString dicoResult; - Dico.lookup( skill, dicoResult, true ); - if(dicoResult.empty()) continue; - - // color - string color = brickToColor[brk]; - - // code - string code = strlwr(brk.c_str()); - fprintf( brickRequiredDocFile, "\n",color.c_str(),code.c_str()); - - // name - string name = (*itBInf).second.Text; - fprintf( brickRequiredDocFile, "\n",name.c_str()); - - // family - string family = brickToFamily[brk]; - fprintf( brickRequiredDocFile, "\n",color.c_str(),family.c_str()); - - // required skill name - fprintf( brickRequiredDocFile, "\n",dicoResult[0].c_str()); - - // required skill value - string levelStr; - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - fprintf( brickRequiredDocFile, "\n",levelStr.c_str()); - - // learn skill name - skillTmp = brickToLearnSkill[brk]; - skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); - fprintf( brickRequiredDocFile, "\n",skill.c_str()); - - // learn skill value - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - fprintf( brickRequiredDocFile, "\n",levelStr.c_str()); - - - // phrase list - fprintf( brickRequiredDocFile, "\n"); - } - fprintf( brickRequiredDocFile, "
    CodeNameFamilyRequired Skill Name*Required Skill Value*Learn Skill NameLearn Skill ValueFound In Phrases
    %s%s%s%s%s%s%s"); - map >::iterator itPhrases = brickToPhrases.find(brk); - if( itPhrases != brickToPhrases.end() ) - { - map::iterator itPh; - uint i; - for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) - { - if( MultipleDocFiles ) - fprintf( brickRequiredDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); - else - fprintf( brickRequiredDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); - } - if( i==2 ) - { - char type = family[0]; - fprintf( brickRequiredDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); - } - } - - fprintf( brickRequiredDocFile, "

    \n" ); - fprintf( brickRequiredDocFile, "\n" ); - fclose( brickRequiredDocFile ); - - - - // LEARN SKILL VALUE - - // write header and title bar - filename = DocFileNameRoot + "_learn_skill_value.html"; - FILE * brickLearnDocFile = fopen( filename.c_str(), "wt" ); - fprintf( brickLearnDocFile,"\n"); - fprintf( brickLearnDocFile,"\n"); - fprintf( brickLearnDocFile,"Bricks infos\n"); - fprintf( brickLearnDocFile,"\n"); - fprintf( brickLearnDocFile,"
    \n"); - fprintf( brickLearnDocFile,"\n"); - fprintf( brickLearnDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickLearnDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickLearnDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickLearnDocFile,"\n"); - fprintf( brickLearnDocFile,"\n",DocFileNameRoot.c_str()); - fprintf( brickLearnDocFile,"\n"); - fprintf( brickLearnDocFile,"\n"); - fprintf( brickLearnDocFile,"\n"); - fprintf( brickLearnDocFile,"\n"); - - - // write infos - multimap learnSkillValueToCode; - for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) - { - string brk = (*itBInf).first; - - if(!validateBrick(brk)) continue; - - // learn skill value - string skillTmp = brickToLearnSkill[brk]; - string levelStr; - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - uint level = atoi(levelStr.c_str()); - - learnSkillValueToCode.insert( make_pair(level,brk) ); - } - - multimap::iterator itLTC; - for( itLTC=learnSkillValueToCode.begin(); itLTC!=learnSkillValueToCode.end(); ++itLTC ) - { - itBInf=BrickInfo.find((*itLTC).second); - - string brk = (*itBInf).first; - - if(!validateBrick(brk)) continue; - - string skillTmp = (*itBInf).second.LearnSkills; - string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); - CVectorSString dicoResult; - Dico.lookup( skill, dicoResult, true ); - if(dicoResult.empty()) continue; - - // color - string color = brickToColor[brk]; - - // code - string code = strlwr(brk.c_str()); - fprintf( brickLearnDocFile, "\n",color.c_str(),code.c_str()); - - // name - string name = (*itBInf).second.Text; - fprintf( brickLearnDocFile, "\n",name.c_str()); - - // family - string family = brickToFamily[brk]; - fprintf( brickLearnDocFile, "\n",color.c_str(),family.c_str()); - - // required skill name - fprintf( brickLearnDocFile, "\n",dicoResult[0].c_str()); - - // required skill value - string levelStr; - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - fprintf( brickLearnDocFile, "\n",levelStr.c_str()); - - // learn skill name - skillTmp = brickToLearnSkill[brk]; - skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); - fprintf( brickLearnDocFile, "\n",skill.c_str()); - - // learn skill value - if( skillTmp.find(";") != -1 ) - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); - } - else - { - sint idx = skillTmp.find_first_of(" "); - levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); - } - fprintf( brickLearnDocFile, "\n",levelStr.c_str()); - - - // phrase list - fprintf( brickLearnDocFile, "\n"); - } - fprintf( brickLearnDocFile, "
    CodeNameFamilyRequired Skill NameRequired Skill ValueLearn Skill Name*Learn Skill Value*Found In Phrases
    %s%s%s%s%s%s%s"); - map >::iterator itPhrases = brickToPhrases.find(brk); - if( itPhrases != brickToPhrases.end() ) - { - map::iterator itPh; - uint i; - for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) - { - if( MultipleDocFiles ) - fprintf( brickLearnDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); - else - fprintf( brickLearnDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); - } - if( i==2 ) - { - char type = family[0]; - fprintf( brickLearnDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); - } - } - - fprintf( brickLearnDocFile, "

    \n" ); - fprintf( brickLearnDocFile, "\n" ); - fclose( brickLearnDocFile ); - - } - - - return 0; - -} // main // - - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// phrase_generator.cpp : Defines the entry point for the console application. + +// + +//-b -p r:\code\ryzom\data_leveldesign -o r:/code/ryzom/data_leveldesign/leveldesign/game_element/sphrase/magic/ magic_bricks.csv -d -m +// -p r:\code\ryzom\data_leveldesign -o r:/code/ryzom/data_leveldesign/leveldesign/game_element/sphrase/magic/ magic_bricks.csv -d -m + +#include "stdafx.h" + + + + + +// Misc +#include +#include "nel/misc/path.h" +#include "nel/misc/file.h" +#include "nel/misc/smart_ptr.h" +#include "nel/misc/command.h" +#include "nel/misc/path.h" +#include +#include +#include "nel/misc/algo.h" +#include "nel/misc/words_dictionary.h" +// Georges +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" +#include "nel/georges/u_form_dfn.h" +#include "nel/georges/u_form_loader.h" +#include "nel/georges/u_type.h" +// Georges, bypassing interface +#include "georges/stdgeorges.h" +#include "georges/form.h" +// Game share +//#include "game_share/xml.h" +// Unicode language file +// C +#include +#include +#include +#include +// stl +#include + +#include "skill_tree.h" + +using namespace NLMISC; +using namespace NLGEORGES; +using namespace std; + + +typedef vector vs; +typedef map< string, string > mss; +typedef map< string, vs > msvs; + +bool GenerateBrickProgression = false; +bool ProduceDocFromExistingPhrases = false; +bool MultipleDocFiles = false; +bool Hypertext = true; +string PhrasePath = "r:/code/ryzom/data_leveldesign/leveldesign/game_element/sphrase/"; +uint NbSheetsGenTries = 0; +uint NbSheetsWritten = 0; +uint NbSheetsRead = 0; +uint NbSheetsRejected = 0; + + +bool UseBricks; + +const string brSheetType = "sbrick"; +const string phSheetType = "sphrase"; +const string PHRASE_MAGIC_PREFIX = "abm_"; // action bricks magic (bm for brick filter) + +struct CBrickInfo +{ + CBrickInfo( const string& ls="", const string& t="", + const vs& props=vs() ) : + LearnSkills(ls), Text(t), Props(props) {} + + string LearnSkills; + string Text; // UTF-8 + vs Props; +}; + + +vs OptionBricks, CounterpartBricks, AllBricks, PhrasesWithInvalidCost, InvalidPhrases; +set UsedCounterpartBricks, UsedCounterpartBrickFamiliesInPhrase; +map SabrinaCosts; +map PhraseSabrinaCosts; +map PhraseCastable; +map BrickInfo; +mss TextToBrick; +multimap< uint, pair > Progression; // phrase code, min. skill +mss PhraseNames, PhraseTitles; +vector ValidPhrases; +set UsedBricks, GeneratedPhrases; +map GrammarMandatParamBrickFamilies, GrammarOptionCreditBrickFamilies; +UFormLoader *FormLoader; +vector PhraseDocFiles( 26 ); +string DocFileName,DocFileNameRoot; +msvs Phrases; +map SkillNameToMaxSkill; +map PhraseCodeToLink; +CWordsDictionary Dico; +CStaticSkillsTree SkillsTree; + + +/* + * + */ +string inputSheetPath; +bool inputSheetPathLoaded = false; +map inputSheetPathContent; // short filename without ext, full filename with path + + +//----------------------------------------------- +// getBrickTypeLetterRPos +// +//----------------------------------------------- +uint getBrickTypeLetterRPos( string& brick ) +{ + /* + uint i =0; + while( i=0 && (isdigit(brick[i]) || brick[i]=='_') ) + i--; + + return (brick.size() - i + 1); + +} // getBrickTypeLetterRPos // + + + + +//----------------------------------------------- +// loadSheetPath +// +// from georges2csv +//----------------------------------------------- +void loadSheetPath() +{ + if (inputSheetPathLoaded) + return; + + NLMISC::createDebug(); + NLMISC::WarningLog->addNegativeFilter( "CPath::insertFileInMap" ); + + CPath::addSearchPath(inputSheetPath, true, false); // for Georges to work properly + + vector files; + CPath::getPathContent (inputSheetPath, true, false, true, files); + + uint i; + for (i=0; i& v, CLog *log=DebugLog ) +{ + if ( ! title.empty() ) + log->displayRaw( "%s: ", title.c_str() ); + vector::const_iterator ist; + for ( ist=v.begin(); ist!=v.end(); ++ist ) + log->displayRaw( "%s ", (*ist).c_str() ); + log->displayRawNL( "" ); +} + + +/* + * + */ +class CStrIComparator : public binary_function +{ +public: + bool operator() ( const string& s1, const string& s2 ) const + { + return (nlstricmp( s1, s2 ) == 0); + } +}; + + +/* + * + */ +uint getIndexFromString( const string& s, const vector& v, bool displayWarning=true ) +{ + if ( v.empty() ) + { + nlwarning( "Can't find '%s' in empty array", s.c_str() ); + return ~0; + } + else + { + vector::const_iterator ist = find_if( v.begin(), v.end(), bind2nd(CStrIComparator(), s) ); + if ( ist == v.end() ) + { + if ( displayWarning ) + { + nlwarning( "Can't find '%s' in:", s.c_str() ); + displayList( "", v, WarningLog ); + } + return ~0; + } + else + return ist - v.begin(); + } +} + + +//----------------------------------------------- +// Erase every carriage returns of the string +// +//----------------------------------------------- +void eraseCarriageReturns( string& s ) +{ + const char CR = '\n'; + string::size_type p = s.find( CR ); + while ( (p=s.find( CR )) != string::npos ) + s.erase( p, 1 ); +} // + + + +// First param: vector of indices of columns matching wantedColumnNames +// Second param: vector of fields matching wantedColumnNames +typedef void (*TDeliveryCallback) ( mss& ); + + +//----------------------------------------------- +// loadCSVFile +// +//----------------------------------------------- +void loadCSVFile( const char *filename, TDeliveryCallback deliveryCallback ) +{ + char lineBuffer[2048]; + FILE *file; + const char *SEPARATOR = ";"; + vector args; + vector::iterator iarg; + + if ( (file = fopen( filename, "r" )) == NULL ) + { + nlwarning( "Can't find file %s", filename ); + } + else + { + // Read first line as header with column names + lineBuffer[0] = '\0'; + fgets( lineBuffer, 2048, file ); + explode( lineBuffer, SEPARATOR, args ); + + // Store column names (and get rid of carriage returns!) + vector < string > columnNames; + mss valuesByName; + for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) + { + eraseCarriageReturns( *iarg ); + columnNames.push_back( *iarg ); + valuesByName.insert( make_pair( *iarg, string("") ) ); + } + + // for each line, deliver the value of the fields + while ( ! feof(file) ) + { + // Get from file + lineBuffer[0] = '\0'; + fgets( lineBuffer, 2048, file ); + explode( lineBuffer, SEPARATOR, args ); + + // Set values (and get rid of carriage returns!) + for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) + { + eraseCarriageReturns( *iarg ); + valuesByName[columnNames[iarg-args.begin()]] = *iarg; + } + + // Deliver the wanted fields + deliveryCallback( valuesByName ); + } + } + +} // loadCSVFile // + + +//set Skills; + + +//----------------------------------------------- +// brickDeliveryCallback +// +// Fetch brick code and sabrina cost +// - AllBricks +// - BrickInfo +// - OptionBricks +// - CounterpartBricks +// - SabrinaCosts +//----------------------------------------------- +void brickDeliveryCallback( mss& values ) +{ + string s = values["Brick_id"]; + if ( s.empty() ) + { + s = values["FILE"]; + if ( s.empty() ) + s = values["fileName"]; + } + + string brick = CFile::getFilenameWithoutExtension( s ); + strupr( brick ); + if ( brick.empty() ) + { + nlwarning(" can't get root filename of %s",s.c_str()); + return; + } + + string sc = values["Basics.SabrinaCost"]; + string ls = values["Basics.LearnRequiresOneOfSkills"]; + string txt = values["name"]; // TODO: only for combat + string fmn = values["familyName"]; + string propIdent = "Basics.Property"; + + if ( UseBricks ) + { + AllBricks.push_back( brick ); + string name = (txt.empty()) ? fmn : txt; + vs props; + + // Find all Basics.Property N (assumes they are subsequent) + mss::const_iterator imv = values.find( propIdent + " 0" ); + for ( ; imv!=values.end(); ++imv ) + { + const string& colName = (*imv).first; + const string& v = (*imv).second; + if ( colName.find( propIdent ) != string::npos ) + { + if ( v != "NULL" && !v.empty() ) + props.push_back( v ); + } + else + break; + } + BrickInfo.insert( make_pair( brick, CBrickInfo( ls, name, props ) ) ); + } + + // Store brick in right container + string::size_type p = brick.size() - getBrickTypeLetterRPos(brick); + if ( ((sint)p) >= 0 ) + { + switch ( brick[p] ) + { + case 'O': OptionBricks.push_back( brick ); + break; + case 'C': CounterpartBricks.push_back( brick ); + break; + } + } + else + { + nlwarning( "Invalid brick code: %s", brick.c_str() ); + return; + } + + // Store cost + sint sabrinaCost; + if ( sc.empty() ) + { + nldebug( "No sabrina cost for %s, assuming cost 0", brick.c_str() ); + sabrinaCost = 0; + } + else + { + sabrinaCost = atoi( sc.c_str() ); + } + SabrinaCosts.insert( make_pair( brick, sabrinaCost ) ); + + /* // Quick hack to generate skill codes + string skill = brick.substr( 1, p-1 ); + if ( ! skill.empty() ) + Skills.insert( skill );*/ + +} // brickDeliveryCallback // + + + +//----------------------------------------------- +// loadBricks +// +//----------------------------------------------- +void loadBricks( const char* filename ) +{ + loadCSVFile( filename, brickDeliveryCallback ); + if ( ProduceDocFromExistingPhrases ) + nlinfo( "Loaded %u option bricks, %u counterpart bricks, %u sabrina costs", OptionBricks.size(), CounterpartBricks.size(), SabrinaCosts.size() ); + else if ( UseBricks ) + nlinfo( "Loaded %u bricks", AllBricks.size() ); + + /*set::const_iterator iss; + for ( iss=Skills.begin(); iss!=Skills.end(); ++iss ) + { + const string& skill = (*iss); + InfoLog->displayRawNL( " ", skill.c_str(), skill.c_str() ); + }*/ + +} // loadBricks // + + +/* + * + */ +string getRootBrickForOptionOrCredit( const string& ob ) +{ + // Extract brick code radix + string::size_type p = ob.size() - getBrickTypeLetterRPos(const_cast(ob)); + if ( (ob.size() <= getBrickTypeLetterRPos(const_cast(ob))) || + ((ob[p] != 'O') && (ob[p] != 'C')) ) + nlerror( "%s is not an option or credit brick", ob.c_str() ); + string radix = ob.substr( 0, p ); + + // Append root brick suffix + return radix + "PA01"; +} + + +/* + * + */ +string getBrickFamily( const string& b ) +{ + if ( b.size() >= getBrickTypeLetterRPos(const_cast(b))+2 ) + { + string::size_type p = b.size() - getBrickTypeLetterRPos(const_cast(b)); + return b.substr( 0, p+2 ); + } + return string(); +} + + +/* + * + */ +bool isFromBrickFamily( const string& brick, const string& fam ) +{ + return nlstricmp( brick.substr( 0, fam.size() ), fam ) == 0; +} + + +/* + * + */ +string getFirstBrickOfFamily( const string& family ) +{ + vs::const_iterator ib; + for ( ib=AllBricks.begin(); ib!=AllBricks.end(); ++ib ) + { + const string& brick = *ib; + if ( isFromBrickFamily( brick, family ) ) + return brick; + } + return string(); +} + + +/* + * + */ +vs getAllBricksOfFamily( const string& family ) +{ + vs res; + vs::const_iterator ib; + for ( ib=AllBricks.begin(); ib!=AllBricks.end(); ++ib ) + { + const string& brick = *ib; + if ( isFromBrickFamily( brick, family ) ) + res.push_back( brick ); + } + return res; +} + + +/* + * + */ +uint getCompatibleCounterpartBrickForCost( uint phraseCost, vs& phrase ) +{ + //nlinfo( "Searching credit for cost %u", phraseCost ); + + // Get the lowest matching counterpart brick + uint minHigherCounterpartValue = ~0, maxLowerCounterpartValue = 0, counterpartValue; + vs::const_iterator icb, iPerfectMatch = CounterpartBricks.end(), iMinCb = CounterpartBricks.end(), iMaxCb = CounterpartBricks.end(); + for ( icb=CounterpartBricks.begin(); icb!=CounterpartBricks.end(); ++icb) + { + const string& cb = *icb; + + // Skip if family already used in current phrase + if ( UsedCounterpartBrickFamiliesInPhrase.find( getBrickFamily( cb ) ) != UsedCounterpartBrickFamiliesInPhrase.end() ) + continue; + + counterpartValue = abs( SabrinaCosts[cb] ); + //nldebug( "Trying with credit %u", counterpartValue ); + if ( counterpartValue == phraseCost ) + { + // Perfect match, check if not already taken + if ( UsedCounterpartBricks.insert( cb ).second ) + { + UsedCounterpartBrickFamiliesInPhrase.insert( getBrickFamily( cb ) ); + phrase.push_back( cb ); + return counterpartValue; + } + else + { + // If already taken, we will come back to it later + iPerfectMatch = icb; + } + } + else if ( counterpartValue > phraseCost ) + { + // Higher => get the minimum + if ( counterpartValue < minHigherCounterpartValue ) + { + minHigherCounterpartValue = counterpartValue; + iMinCb = icb; + } + } + else // counterpartValue < phraseCost : store the max + { + if ( counterpartValue >= maxLowerCounterpartValue ) + { + maxLowerCounterpartValue = counterpartValue; + iMaxCb = icb; + } + } + } + if ( iPerfectMatch != CounterpartBricks.end() ) + { + // We skipped a perfect match in order to try to get a new value. But none found. Now get back to the last value. + phrase.push_back( *iPerfectMatch ); + UsedCounterpartBrickFamiliesInPhrase.insert( getBrickFamily( *iPerfectMatch ) ); + return abs( SabrinaCosts[*iPerfectMatch] ); + } + else if ( iMinCb == CounterpartBricks.end() ) + { + if ( iMaxCb == CounterpartBricks.end() ) + { + nlerror( "No matching counterpart" ); + return ~0; + } + else + { + // No phrase possible with only one (more) counterpart, try with the max and more (recurse) + UsedCounterpartBricks.insert( *iMaxCb ); + UsedCounterpartBrickFamiliesInPhrase.insert( getBrickFamily( *iMaxCb ) ); + phrase.push_back( *iMaxCb ); + return maxLowerCounterpartValue + getCompatibleCounterpartBrickForCost( phraseCost - maxLowerCounterpartValue, phrase ); + } + } + else + { + // Phrase possible with one (more) counterpart + UsedCounterpartBricks.insert( *iMinCb ); + UsedCounterpartBrickFamiliesInPhrase.insert( getBrickFamily( *iMinCb ) ); + phrase.push_back( *iMinCb ); + return minHigherCounterpartValue; + } +} + + +/* + * + */ +void getCompatibleCounterpartBricks( vs& phrase ) +{ + // Calculate the cost of the phrase + sint phraseCost = 0; + string phraseStr; + vs::const_iterator ip; + for ( ip=phrase.begin(); ip!=phrase.end(); ++ip ) + { + const string& brick = *ip; + sint sabrinaCost; + map::const_iterator isc = SabrinaCosts.find( brick ); + if ( isc != SabrinaCosts.end() ) + sabrinaCost = (*isc).second; + else + sabrinaCost = 0; + phraseCost += sabrinaCost; + phraseStr += brick + " "; + } + + // Find matching counterpart(s), only 1 per family + UsedCounterpartBrickFamiliesInPhrase.clear(); + uint counterpartValue = getCompatibleCounterpartBrickForCost( phraseCost, phrase ); + + displayList( toString( "+%3u -%3u", phraseCost, counterpartValue ), phrase ); +} + + +/* + * + */ +/*void getCompatiblePhraseByCounterpart( const string& counterpartBrick, vs& phrase ) +{ + sint sabrinaCost = SabrinaCosts[counterpartBrick]; + + // Assuming root brick cost is zero! + vs::const_iterator iob; + for ( iob=OptionBricks.begin(); iob!=OptionBricks.end(); ++iob ) + { + // TODO: Find the highest cost that is lower or equal than the counterpart value + const string& ob = *iob; + if ( SabrinaCosts[ob] <= SabrinaCosts[counterpartBrick] ) + break; // currently, take the first found + } + if ( iob != OptionBricks.end() ) + { + string rb = getRootBrickForOptionOrCredit( *iob ); + phrase.push_back( rb ); + phrase.push_back( *iob ); + phrase.push_back( counterpartBrick ); + nldebug( "%s %s %s: +%u -%u", rb.c_str(), (*iob).c_str(), counterpartBrick.c_str(), + SabrinaCosts[rb]+SabrinaCosts[*iob], SabrinaCosts[counterpartBrick] ); + } + else + nlwarning( "No matching phrase for counterpart %s", counterpartBrick.c_str() ); +}*/ + + +/* + * Clear the form to reuse it (and all contents below node) + */ +void clearSheet( CForm *form, UFormElm* node ) +{ + ((CFormElm*)node)->clean(); + form->clean(); +} + + + +/* + * + */ +inline void explodeBrickAndParameters( const string& brickAndParams, vs& bricks ) +{ + explode( brickAndParams, " ", bricks ); +} + + +/* + * + */ +string getBrickType( const string& brick ) +{ + if ( brick.size() < 4 ) + return "INVALID TYPE in " + brick; + else + { + switch ( brick[brick.size()-getBrickTypeLetterRPos(const_cast(brick))] ) + { + case 'P': return "Root"; + break; + case 'E': return "Effect"; + break; + case 'O': return "Option"; + break; + case 'M': return "Modifier"; + break; + case 'C': return "Credit"; + break; + default: + return "INVALID TYPE in " + brick; + } + } +} + + +//----------------------------------------------- +// printBrickInfo +// +//----------------------------------------------- +void printBrickInfo( FILE *htmlfile, const string& brick, const string& grammarError, sint& sabrinaCost, uint& minSkillValue, string& minSkill ) +{ + minSkill.clear(); + string b = brick; + strupr( b ); + string brickType = getBrickType( b ); + sint sc = (brickType=="Credit") ? -abs( SabrinaCosts[b] ) : SabrinaCosts[b]; + CBrickInfo& bInfo = BrickInfo[b]; + fprintf( htmlfile, "
  • %s %s %s
    \n", brickType.c_str(), b.c_str(), bInfo.Text.c_str() ); + if ( ! grammarError.empty() ) + { + fprintf( htmlfile, "%s
    \n", grammarError.c_str() ); + } + else + { + fprintf( htmlfile, "Sabrina Cost: %d
    \n", sc ); + if( !bInfo.LearnSkills.empty() ) + { + fprintf( htmlfile, "Skills required: %s
    \n", bInfo.LearnSkills.c_str() ); + } + if( bInfo.Props.size() ) + { + fprintf( htmlfile, "Properties:" ); + for ( vs::const_iterator ip = bInfo.Props.begin(); ip!=bInfo.Props.end(); ++ip ) + { + fprintf( htmlfile, " %s", (*ip) ); + } + } + } + fprintf( htmlfile, "
  • \n" ); + + // Calculate sabrina cost & skill value + sabrinaCost = sc; + if ( bInfo.LearnSkills.empty() ) + minSkillValue = 0; + else + { + minSkillValue = ~0; + vector skillsAndValues; + explode( bInfo.LearnSkills, ":", skillsAndValues, true ); + vector skillValues( skillsAndValues.size(), ~0 ); + vector::iterator isv; + for ( isv=skillsAndValues.begin(); isv!=skillsAndValues.end(); ++isv ) + { + const string& sav = *isv; + string::size_type p = sav.find( ' ' ); + if ( (p == string::npos) || (sav.size() == p+1) ) + nlwarning( "Invalid LearnRequiresOneOfSkills value '%s'", sav.c_str() ); + else + { + uint sv = atoi( sav.substr( p+1 ).c_str() ); + skillValues[isv-skillsAndValues.begin()] = sv; + if ( sv < minSkillValue ) + minSkillValue = sv; + } + } + + for ( isv=skillsAndValues.begin(); isv!=skillsAndValues.end(); ++isv ) + { + if ( skillValues[isv-skillsAndValues.begin()] == minSkillValue ) + { + string& sav = *isv; + if ( (! sav.empty()) && (sav[0] != 'S') ) + sav = 'S' + sav; + if ( minSkill.find( sav ) == string::npos ) + { + if ( ! minSkill.empty() ) + minSkill += ", "; + minSkill += sav; + } + } + } + } + +} // printBrickInfo // + + +//----------------------------------------------- +// loadBrickGrammar +// +//----------------------------------------------- +void loadBrickGrammar() +{ + uint nbRootBricks = 0; + vs::const_iterator ib; + for ( ib=AllBricks.begin(); ib!=AllBricks.end(); ++ib ) + { + string brick = *ib; + strupr( brick ); + if ( brick.size() >= 4 ) + { + char brickType = brick[brick.size()-getBrickTypeLetterRPos(brick)]; + + /*// As the root bricks may be absent from the table, deduce them (obsolete) + if ( brickType == 'O' ) + { + string rootBrick = getRootBrickForOptionOrCredit( brick ); + if ( GrammarOptionCreditBrickFamilies.find( rootBrick ) == GrammarOptionCreditBrickFamilies.end() ) + { + brick = rootBrick; + brickType = 'P'; + } + else + { + continue; + } + }*/ + + // If not skipped by previous 'continue' + if ( (brickType == 'P') || (brickType == 'E') || (brickType == 'O' ) ) // root, effect, option + { + NLMISC::CSmartPtr form = (CForm*)FormLoader->loadForm( (strlwr(static_cast(brick))+"."+brSheetType).c_str() ); + if ( ! form ) + { + nlwarning( "Can't load sheet %s", ((strlwr(static_cast(brick)))+"."+phSheetType).c_str() ); + continue; + } + for ( uint i=0; i!=12; ++i ) + { + string value; + form->getRootNode().getValueByName( value, toString( "Mandatory.f%u", i ).c_str() ); + if ( (! value.empty()) && (value != "Unknown") ) + { + GrammarMandatParamBrickFamilies[brick].push_back( value ); + } + } + if ( brickType == 'O' ) + { + for ( uint i=0; i!=4; ++i ) + { + string value; + form->getRootNode().getValueByName( value, toString( "Parameter.f%u", i ).c_str() ); + if ( (! value.empty()) && (value != "Unknown") ) + { + GrammarMandatParamBrickFamilies[brick].push_back( value ); + } + } + } + if ( brickType == 'P' ) // root + { + ++nbRootBricks; + for ( uint i=0; i!=32; ++i ) + { + string value; + form->getRootNode().getValueByName( value, toString( "Optional.f%u", i ).c_str() ); + if ( (! value.empty()) && (value != "Unknown") ) + { + GrammarOptionCreditBrickFamilies[brick].push_back( value ); + } + } + for ( uint i=0; i!=12; ++i ) + { + string value; + form->getRootNode().getValueByName( value, toString( "Credit.f%u", i ).c_str() ); + if ( (! value.empty()) && (value != "Unknown") ) + { + GrammarOptionCreditBrickFamilies[brick].push_back( value ); + } + } + } + } + } + else + { + nlwarning( "Invalid brick code %s", brick.c_str() ); + } + } + nlinfo( "%u bricks have mandatory/parameter grammar rules", GrammarMandatParamBrickFamilies.size() ); + nlinfo( "%u bricks have option/credit grammar rules", GrammarOptionCreditBrickFamilies.size() ); + nlinfo( "Found or deduced %u root bricks", nbRootBricks ); + +} // loadBrickGrammar // + + + +//----------------------------------------------- +// loadPhraseTitles +// +//----------------------------------------------- +void loadPhraseTitles() +{ + STRING_MANAGER::TWorksheet worksheet; + STRING_MANAGER::loadExcelSheet( "r:/code/ryzom/translation/translated/sphrase_words_en.txt", worksheet ); + uint cp, cn; + if ( worksheet.findCol( ucstring("sphrase ID"), cp ) && worksheet.findCol( ucstring("name"), cn ) ) + { + for ( std::vector::iterator ip = worksheet.begin(); ip!=worksheet.end(); ++ip ) + { + if ( ip == worksheet.begin() ) // skip first row + continue; + STRING_MANAGER::TWorksheet::TRow& row = *ip; + PhraseTitles.insert( make_pair( strlwr(row[cp].toString()), row[cn].toUtf8() ) ); + } + } + else + nlwarning( "sphrase ID or name not found" ); + + nlinfo( "Loaded %u phrase titles", PhraseTitles.size() ); + +} // loadPhraseTitles // + + +//----------------------------------------------- +// loadBrickTitles +// +//----------------------------------------------- +void loadBrickTitles() +{ + STRING_MANAGER::TWorksheet worksheet; + STRING_MANAGER::loadExcelSheet( "r:/code/ryzom/translation/translated/sbrick_words_en.txt", worksheet ); + uint cp, cn, nbTitles = 0; + if ( worksheet.findCol( ucstring("sbrick ID"), cp ) && worksheet.findCol( ucstring("name"), cn ) ) + { + for ( std::vector::iterator ip = worksheet.begin(); ip!=worksheet.end(); ++ip ) + { + if ( ip == worksheet.begin() ) // skip first row + continue; + STRING_MANAGER::TWorksheet::TRow& row = *ip; + BrickInfo[strupr(row[cp].toString())].Text = row[cn].toUtf8();; + ++nbTitles; + } + } + else + nlwarning( "sbrick ID or name not found" ); + + nlinfo( "Loaded %u brick titles", nbTitles ); + +} // loadBrickTitles // + + +/* + * + */ +void getChildrenBricks( const string& brick, vs& chFamilies ) +{ + chFamilies = GrammarMandatParamBrickFamilies[brick]; +} + + +/* + * + */ +void addError( string& errorStr, string& newError, uint& nbGrammarErrors ) +{ + if ( ! errorStr.empty() ) + errorStr += "
    "; + errorStr += newError; + ++nbGrammarErrors; +} + + +/* + * + */ +void checkOptionOrCreditCompatibility( string& errorStr, const string& currentBrick, const string& rootBrick, uint& nbGrammarErrors ) +{ + string brick = currentBrick; + strupr( brick ); + if ( brick.size() >= 4 && brick[1]!='C' && brick[1]!='H') // C & H for craft and harvest + { + char brickType = brick[brick.size()-getBrickTypeLetterRPos(brick)]; + if ( (brickType == 'O') || (brickType == 'C') ) + { + string rootBrick = getRootBrickForOptionOrCredit( brick ); + const vs& compatibleOptionOrCredits = GrammarOptionCreditBrickFamilies[rootBrick]; + vs::const_iterator ic; + for ( ic=compatibleOptionOrCredits.begin(); ic!=compatibleOptionOrCredits.end(); ++ic ) + { + if ( isFromBrickFamily( brick, (*ic) ) ) + break; + } + if ( ic == compatibleOptionOrCredits.end() ) + { + addError( errorStr, toString( "This family is not compatible with options/credits of root %s", rootBrick.c_str() ), nbGrammarErrors ); + } + } + } +} + + +/* + * Preconditions: + * - grammarErrors.size() == phrase.size() + * - r < phrase.size() + * + * Note: does not check that all bricks should have a different family + */ +void checkGrammar( const vs& phrase, uint& r, vs& grammarErrors, uint& nbGrammarErrors, const string& rootBrick, bool readNext=true ) +{ + uint origR = r; + string grammarBrick = phrase[origR]; + strupr( grammarBrick ); + + // Check option/credit + checkOptionOrCreditCompatibility( grammarErrors[r], phrase[r], rootBrick, nbGrammarErrors ); + + // Check mandatory/parameter + vs chFamilies; + getChildrenBricks( grammarBrick, chFamilies ); + ++r; + for ( vs::const_iterator icf=chFamilies.begin(); icf!=chFamilies.end(); ++icf ) + { + // Detect incomplete phrase + if ( r >= phrase.size() ) + { + addError( grammarErrors[origR], "Missing mandatory/parameter " + (*icf) + " at the end", nbGrammarErrors ); + break; + } + + // Detect wrong brick family + if ( isFromBrickFamily( phrase[r], (*icf) ) ) + { + // Check grammar using child as root + checkGrammar( phrase, r, grammarErrors, nbGrammarErrors, phrase[r], false ); + } + else + { + addError( grammarErrors[r], "Error: " + (*icf) + " expected (mandatory/parameter of " + grammarBrick + ")", nbGrammarErrors ); + ++r; + } + } + + // Next + if ( readNext && (r < phrase.size()) ) + { + checkGrammar( phrase, r, grammarErrors, nbGrammarErrors, rootBrick ); + } +} + + +/* + * + */ +char getDocFileLetter( const string& sheetName ) +{ + // skip abm_mt_, abm_ml_... + char letter = 'a'; + uint nbUnderscoresToSkip = 2, nbUnderscoresFound = 0; + for ( uint c=0; c!=sheetName.size(); ++c ) + { + if ( nbUnderscoresFound == nbUnderscoresToSkip ) + { + letter = sheetName[c]; + break; + } + if ( sheetName[c] == '_' ) + ++nbUnderscoresFound; + } + return tolower( letter ); +} + + +//----------------------------------------------- +// testPhraseGrammarAndProduceDoc +// +//----------------------------------------------- +bool testPhraseGrammarAndProduceDoc( const string& sheetName, const vs& phrase ) +{ + string filename = strlwr( sheetName ) + "." + phSheetType; + string phraseStatus; + bool isPhraseCorrect = true; + const char *rejectedstr = "(grammatically invalid)"; + + // Check grammar for this phrase + vs grammarErrors( phrase.size() ); + uint nbGrammarErrors = 0, r = 0; + checkGrammar( phrase, r, grammarErrors, nbGrammarErrors, phrase[0] ); + if ( nbGrammarErrors != 0 ) + { + InvalidPhrases.push_back( sheetName ); + isPhraseCorrect = false; + phraseStatus = rejectedstr; + } + + // Look-up phrase title + string phraseTitle = PhraseTitles[sheetName]; + + // Output phrase description + char letter = 'a'; + if ( (! MultipleDocFiles) && (sheetName.size() > 3) ) + { + letter = tolower( sheetName[3] ); + } + else + { + letter = getDocFileLetter( sheetName ); + } + if ( letter < 'a' ) + letter = 'a'; + else if ( letter > 'z' ) + letter = 'z'; + FILE *htmlFile = PhraseDocFiles[letter - 'a']; + sint sabrinaCost; + fprintf( htmlFile, "

    %s %s %s

      \n", sheetName.c_str(), filename.c_str(), phraseTitle.c_str(), phraseStatus.c_str() ); + vector minBrickSkills( phrase.size() ); + vector minBrickSkillValues( phrase.size(), 0 ); + string brickMinSkill, maxSkill; + sint posCost = 0, negCost = 0, totalCost; + uint maxSkillValue = 0, brickMinSkillValue; + for ( uint i=0; i!=phrase.size(); ++i ) + { + printBrickInfo( htmlFile, phrase[i], grammarErrors[i], sabrinaCost, brickMinSkillValue, brickMinSkill ); + if ( sabrinaCost > 0 ) + posCost += sabrinaCost; + else + negCost += sabrinaCost; + minBrickSkillValues[i] = brickMinSkillValue; + minBrickSkills[i] = brickMinSkill; + if ( brickMinSkillValue > maxSkillValue ) + maxSkillValue = brickMinSkillValue; + } + for ( uint i=0; i!=phrase.size(); ++i ) + { + if ( minBrickSkillValues[i] == maxSkillValue ) + { + if ( maxSkill.find( minBrickSkills[i] ) == string::npos ) + { + if ( ! maxSkill.empty() ) + maxSkill += "; "; + maxSkill += minBrickSkills[i]; + } + } + } + if ( phrase.size() > 1 ) + { + string effectOrOptionBrick = phrase[1]; + strupr( effectOrOptionBrick ); + if ( ! PhraseNames.insert( make_pair( sheetName, BrickInfo[effectOrOptionBrick].Text ) ).second ) + nlwarning( "Found duplicate phrase %s", sheetName.c_str() ); + } + Progression.insert( make_pair( maxSkillValue, make_pair( sheetName, maxSkill ) ) ); + totalCost = posCost + negCost; + PhraseSabrinaCosts.insert( make_pair(sheetName,totalCost) ); + char *redbegin = "", *redend = ""; + if ( totalCost > 0 ) + { + map::const_iterator itCastable = PhraseCastable.find(sheetName); + if( itCastable != PhraseCastable.end() ) + { + if( (*itCastable).second ) + { + redbegin = ""; + redend = ""; + PhrasesWithInvalidCost.push_back( sheetName ); + isPhraseCorrect = false; + } + } + } + fprintf( htmlFile, "
    • %sTotal sabrina cost: +%d %d = %d%s
    • \n", redbegin, posCost, negCost, totalCost, redend ); + fprintf( htmlFile, "
    • Minimum skill value required: %d
    • \n", maxSkillValue ); + fprintf( htmlFile, "

    \n" ); + if ( ! isPhraseCorrect ) + { + ++NbSheetsRejected; + } + return isPhraseCorrect; + +} // testPhraseGrammarAndProduceDoc // + + + + + +/* + * + */ +inline bool isSeparator( char c ) +{ + return (c == ' ') || (c == '\t'); +} + + + +//----------------------------------------------- +// produceDocFromExistingPhrases +// +// - Phrases +//----------------------------------------------- +void produceDocFromExistingPhrases() +{ + vs files; + CPath::getPathContent( PhrasePath, true, false, true, files ); + + NbSheetsRead = 0; + for ( vs::const_iterator ip=files.begin(); ip!=files.end(); ++ip ) + { + if ( CFile::getExtension( *ip ) == phSheetType ) + { + // Read george sheet + NLMISC::CSmartPtr form = (UForm*)FormLoader->loadForm( (*ip).c_str() ); + if ( ! form ) + nlerror( "Can't load sheet %s", (*ip).c_str() ); + + // Get the bricks of the phrase + vs phrase; + for ( uint i=0; i!=100; ++i ) + { + string value; + form->getRootNode().getValueByName( value, toString( "brick %u", i ).c_str() ); + if ( !value.empty() ) + { + strupr( value ); + phrase.push_back( CFile::getFilenameWithoutExtension( value ) ); + } + } + + Phrases.insert( make_pair(CFile::getFilenameWithoutExtension( *ip ), phrase) ); + + // look if phrase is castable + bool castable; + form->getRootNode().getValueByName( castable, "castable"); + PhraseCastable.insert( make_pair(CFile::getFilenameWithoutExtension( *ip ), castable) ); + + // Test grammar and produce doc + testPhraseGrammarAndProduceDoc( CFile::getFilenameWithoutExtension( *ip ), phrase ); + + ++NbSheetsRead; + } + } + nlinfo( "Total: %u phrases", NbSheetsRead ); + +} // produceDocFromExistingPhrases // + + +/* + * + */ +string getLink( const string& phrase ) +{ + string res; + if ( MultipleDocFiles && (! phrase.empty()) ) + { + res += DocFileName + "_" + getDocFileLetter( phrase ) + ".html"; + } + else + { + res += DocFileName + ".html"; + } + res += "#" + phrase; + //nlinfo( "%s", res.c_str() ); + return res; +} + + +/* + * + */ +void usage(char *argv0, FILE *out) +{ + fprintf(out, "\n"); + fprintf(out, "Syntax: %s [-p ] [-o ] [-b] [-d] [-m] [-n]\n", argv0); + fprintf(out, "-o: output phrase path (or input if -d is set)\n"); + fprintf(out, "-b: produce doc about brick learning infos\n"); + fprintf(out, "-d: browse existing phrases in (and subdirs) and produce doc\n"); + fprintf(out, "-m: multiple doc html files, alphabetically (use with -g,-c,-d with numerous phrases)\n"); + fprintf(out, "-n: no hypertext (don't produce links phrases)\n"); + + fprintf(out, "\n"); +} + + + + +//----------------------------------------------- +// makeIndexFile +// +//----------------------------------------------- +void makeIndexFile() +{ + FILE * indexFile = fopen( ("_" + DocFileNameRoot + "_INDEX.html").c_str(), "wt" ); + if( indexFile ) + { + fprintf( indexFile, ("\n\nSummary of " + DocFileNameRoot + "\n\n").c_str() ); + + DocFileName = DocFileNameRoot + "_actions"; + + if ( MultipleDocFiles ) + { + // One HTML file per alphabet letter + for ( uint l=0; l!=26; ++l ) + { + string filename = toString( "%s_%c.html", DocFileName.c_str(), 'a'+l ); + PhraseDocFiles[l] = fopen( filename.c_str(), "wt" ); + fprintf( PhraseDocFiles[l], ("\n\n" + DocFileName + toString( " - %c", (char)('A'+l) ) + "\n\n").c_str() ); + fprintf( indexFile, ("" + (char)('A'+l) + " ").c_str() ); + } + } + else + { + // One single HTML file + fprintf( indexFile, ("Go to action details").c_str() ); + PhraseDocFiles[0] = fopen( (DocFileName + ".html").c_str(), "wt" ); + fprintf( PhraseDocFiles[0], ("\n\n" + DocFileName + "\n\n").c_str() ); + for ( uint l=1; l!=26; ++l ) + { + PhraseDocFiles[l] = PhraseDocFiles[0]; + } + } + fprintf( indexFile, ("
    Go to action by skill value\n").c_str() ); + fprintf( indexFile, ("
    Go to action by skill value (detail)\n").c_str() ); + fprintf( indexFile, ("
    Go to action by skill
    \n").c_str() ); + + if( GenerateBrickProgression ) + { + fprintf( indexFile, ("

    Go to brick list
    \n").c_str() ); + } + + produceDocFromExistingPhrases(); + + for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) + { + const string& phraseCode = (*ip).second.first; + string link = Hypertext ? toString( "%s", getLink(phraseCode).c_str(), phraseCode.c_str() ) : "" + phraseCode + ""; + PhraseCodeToLink.insert( make_pair(phraseCode,link) ); + } + + // Summary (errors in phrases) + fprintf( indexFile, "
    \n" ); + fprintf( indexFile, ("Summary of " + DocFileName + "
    \n").c_str() ); + if ( NbSheetsGenTries != 0 ) + fprintf( indexFile, "

    %u valid sheets written on %u

    \n", NbSheetsWritten, NbSheetsGenTries ); + if ( NbSheetsRead != 0 ) + fprintf( indexFile, "

    %u sheets read

    \n", NbSheetsRead ); + fprintf( indexFile, "

    %u invalid sheets rejected", NbSheetsRejected ); + if ( ! PhrasesWithInvalidCost.empty() ) + { + fprintf( indexFile, "

    Phrases with invalid sabrina cost:
    \n" ); + for ( vs::const_iterator iip=PhrasesWithInvalidCost.begin(); iip!=PhrasesWithInvalidCost.end(); ++iip ) + { + string link = Hypertext ? toString( "%s", getLink(*iip).c_str(), (*iip).c_str() ) : "" + (*iip) + ""; + fprintf( indexFile, "%s
    \n", link.c_str() ); + } + fprintf( indexFile, "

    \n" ); + } + else + { + fprintf( indexFile, "

    All phrases have valid sabrina cost.

    \n" ); + } + if ( ! InvalidPhrases.empty() ) + { + fprintf( indexFile, "

    Grammatically invalid phrases:
    \n" ); + for ( vs::const_iterator iip=InvalidPhrases.begin(); iip!=InvalidPhrases.end(); ++iip ) + { + string link = Hypertext ? toString( "%s", getLink(*iip).c_str(), (*iip).c_str() ) : "" + (*iip) + ""; + fprintf( indexFile, "%s
    \n", link.c_str() ); + } + fprintf( indexFile, "

    \n" ); + } + else + { + fprintf( indexFile, "

    All phrases are grammatically valid.

    \n" ); + } + fprintf( indexFile, "\n" ); + fclose( indexFile ); + + if ( MultipleDocFiles ) + { + for ( uint l=0; l!=26; ++l ) + { + fprintf( PhraseDocFiles[l], "\n" ); + fclose( PhraseDocFiles[l] ); + } + } + else + { + fprintf( PhraseDocFiles[0], "\n" ); + fclose( PhraseDocFiles[0] ); + } + } + +} // makeIndexFile // + + +//----------------------------------------------- +// makeActionsBySkillGroupFile +// +//----------------------------------------------- +void makeActionsBySkillGroupFile() +{ + // progression by skill + FILE * actionsBySkillGroupFile = fopen( (DocFileName + "__by_skill.html").c_str(), "wt" ); + if( actionsBySkillGroupFile ) + { + fprintf( actionsBySkillGroupFile, ("\n\nProgression of " + DocFileName + "\n\n").c_str() ); + fprintf( actionsBySkillGroupFile, "
    \n" ); + fprintf( actionsBySkillGroupFile, "

    ACTIONS BY SKILL GROUP:
    \n

    \n" ); + map > phrasesBySkill; + for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) + { + const string& phraseCode = (*ip).second.first; + string skillName = (*ip).second.second.substr(0,(*ip).second.second.find(" ")); + string skillValueStr = (*ip).second.second.substr((*ip).second.second.find(" ")+1,(*ip).second.second.size()-(*ip).second.second.find(" ")-1); + uint skillValue = atoi(skillValueStr.c_str()); + + map >::iterator it = phrasesBySkill.find(skillName); + if( it != phrasesBySkill.end() ) + { + (*it).second.insert(make_pair(skillValue,phraseCode)); + } + else + { + multimap m; + m.insert(make_pair(skillValue,phraseCode)); + phrasesBySkill.insert( make_pair(skillName,m) ); + } + } + + map >::iterator itPhrasesBySkill; + for( itPhrasesBySkill = phrasesBySkill.begin(); itPhrasesBySkill != phrasesBySkill.end(); ++itPhrasesBySkill ) + { + CVectorSString dicoResult; + Dico.lookup( (*itPhrasesBySkill).first, dicoResult, true ); + if( !dicoResult.empty() ) + fprintf( actionsBySkillGroupFile, "\n", (*itPhrasesBySkill).first.c_str(),dicoResult[0].c_str()); + else + fprintf( actionsBySkillGroupFile, "\n", (*itPhrasesBySkill).first.c_str(),(*itPhrasesBySkill).first.c_str()); + } + for( itPhrasesBySkill = phrasesBySkill.begin(); itPhrasesBySkill != phrasesBySkill.end(); ++itPhrasesBySkill ) + { + CVectorSString dicoResult; + Dico.lookup( (*itPhrasesBySkill).first, dicoResult, true ); + if( !dicoResult.empty() ) + fprintf( actionsBySkillGroupFile, "\n", (*itPhrasesBySkill).first.c_str(), dicoResult[0].c_str() ); + else + fprintf( actionsBySkillGroupFile, "\n", (*itPhrasesBySkill).first.c_str(),(*itPhrasesBySkill).first.c_str() ); + + multimap::iterator it; + for( it = (*itPhrasesBySkill).second.begin(); it != (*itPhrasesBySkill).second.end(); ++it ) + { + fprintf( actionsBySkillGroupFile, "\n", (*it).first, PhraseCodeToLink[(*it).second].c_str(), PhraseTitles[(*it).second].c_str()); + } + } + fprintf( actionsBySkillGroupFile, "
    %s
    %s
    %s
    %s
    %d%s%s

    \n" ); + fprintf( actionsBySkillGroupFile, "\n" ); + fclose( actionsBySkillGroupFile ); + } + +} // makeActionsBySkillGroupFile // + + + +//----------------------------------------------- +// makeActionsBySkillValueFile +// +//----------------------------------------------- +void makeActionsBySkillValueFile() +{ + FILE * actionsBySkillValueFile = fopen( (DocFileName + "__by_skill_value.html").c_str(), "wt" ); + if( actionsBySkillValueFile ) + { + fprintf( actionsBySkillValueFile, ("\n\nProgression of " + DocFileName + "\n\n").c_str() ); + + // Progression (phrases sorted by skill value) + fprintf( actionsBySkillValueFile, "
    \n" ); + fprintf( actionsBySkillValueFile, "

    ACTIONS BY SKILL VALUE: [detail]\n

    \n",(DocFileName + "__by_skill_value_detail.html").c_str() ); + fprintf( actionsBySkillValueFile, "\n"); + map phraseCodeToLink; + for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) + { + const string& phraseCode = (*ip).second.first; + fprintf( actionsBySkillValueFile, "\n", PhraseCodeToLink[phraseCode].c_str(), /*newbrickTitle.c_str(),*/ PhraseTitles[phraseCode].c_str(), (*ip).second.second.c_str() ); + } + fprintf( actionsBySkillValueFile, "
    FileNameSkill needed
    %s%s%s

    \n" ); + fprintf( actionsBySkillValueFile, "\n" ); + fclose( actionsBySkillValueFile ); + } + +} // makeActionsBySkillValueFile // + + +//----------------------------------------------- +// makeActionsBySkillValueDetailFile +// +//----------------------------------------------- +void makeActionsBySkillValueDetailFile() +{ + FILE * actionsBySkillValueDetailFile = fopen( (DocFileName + "__by_skill_value_detail.html").c_str(), "wt" ); + if( actionsBySkillValueDetailFile ) + { + fprintf( actionsBySkillValueDetailFile, ("\n\nProgression of " + DocFileName + "\n\n").c_str() ); + + // Progression summary (phrases sorted by skill value) + fprintf( actionsBySkillValueDetailFile, "
    \n" ); + fprintf( actionsBySkillValueDetailFile, "

    ACTIONS BY SKILL VALUE:
    \n

    \n" ); + fprintf( actionsBySkillValueDetailFile, "\n"); + + set effects; + map > effectAndModifiers; + for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) + { + const string& phraseCode = (*ip).second.first; + fprintf( actionsBySkillValueDetailFile, "",PhraseCodeToLink[phraseCode].c_str(), PhraseTitles[phraseCode].c_str(), (*ip).second.second.c_str(),PhraseSabrinaCosts[phraseCode]); + + msvs::iterator itPhrases = Phrases.find( phraseCode ); + if( itPhrases != Phrases.end() ) + { + string effect; + uint modifierCount = 0; + uint creditCount = 0; + for( uint i = 0; i<(*itPhrases).second.size(); ++i ) + { + string brick = (*itPhrases).second[i]; + string color; + switch ( brick[brick.size()-getBrickTypeLetterRPos(brick)] ) + { + case 'P': color = "Black"; + break; + case 'E': + { + color = "Brown"; + effects.insert(brick); + if( effectAndModifiers.find(brick) == effectAndModifiers.end() ) + { + set s; + effectAndModifiers.insert( make_pair(brick,s) ); + } + effect = brick; + } + break; + case 'O': color = "Green"; + break; + case 'M': + { + color = "Blue"; + effectAndModifiers[effect].insert(brick); + modifierCount++; + } + break; + case 'C': color = "Red"; creditCount++; + break; + default: + color = "Black"; + } + string text = BrickInfo[brick].Text; + if( text.empty() ) + { + text = strlwr(brick); + nlwarning("%s not found in BrickInfo",brick.c_str()); + } + else + { + if(text.find("$|sap")!=-1) + { + text = text.substr(0,text.size()-5); + string str = brick.substr(brick.size()-5,5); + text += toString(atoi(str.c_str())); + } + } + fprintf( actionsBySkillValueDetailFile, "",color.c_str(),text.c_str()); + } + } + else + { + nlerror("not found : %s",phraseCode.c_str()); + } + fprintf( actionsBySkillValueDetailFile, "\n"); + } + fprintf( actionsBySkillValueDetailFile, "
    FileNameSkill needed
    Sabrina costBricks ...
    %s%s%s%d%s

    \n" ); + fprintf( actionsBySkillValueDetailFile, "\n" ); + fclose( actionsBySkillValueDetailFile ); + } + +} // makeActionsBySkillValueDetailFile // + + +//----------------------------------------------- +// validateBrick +// +//----------------------------------------------- +bool validateBrick( const string& brk ) +{ + if(brk[1]=='C') return true; + if(brk[1]=='F') return true; + if(brk[1]=='H') return true; + if(brk[1]=='M') return true; + if(brk[1]=='S') return true; + return false; + +} // validateBrick // + + + +//----------------------------------------------- +// makeSkillTreeFile +// +//----------------------------------------------- +void makeSkillTreeFile( char filter, string skillFamily, bool withTraduction ) +{ + vector > skillsArray; + skillsArray.resize(6); // 6 tranches de skill + uint i; + for( i = 0; i maxLine ) + { + maxLine = skillsArray[i].size(); + } + } + + string filename = skillFamily + "_skill_tree.html"; + string filenameWithTraduction = skillFamily + "_skill_tree_detailed.html"; + FILE * skillTreeFile; + if( withTraduction ) + skillTreeFile = fopen( filenameWithTraduction.c_str(), "wt" ); + else + skillTreeFile = fopen( filename.c_str(), "wt" ); + fprintf( skillTreeFile,"\n"); + fprintf( skillTreeFile,"\n"); + fprintf( skillTreeFile,"SKILL TREE ( %s )\n",skillFamily.c_str()); + fprintf( skillTreeFile,"\n"); + if( withTraduction ) + fprintf( skillTreeFile,"SKILL TREE ( %s )\n",skillFamily.c_str()); + else + fprintf( skillTreeFile,"SKILL TREE ( %s ) [display traduction]
    \n",skillFamily.c_str(),filenameWithTraduction.c_str()); + fprintf( skillTreeFile,"
    \n"); + fprintf( skillTreeFile,"\n"); + + uint j; + // print line by line + for( j=0; j"); + // for each column + for( i=0; i::iterator itSkillcode; + for( itSkillcode = skillsArray[i].begin(), p=0; itSkillcode != skillsArray[i].end() && p%s : ???",(*itSkillcode).first.c_str()); + else + fprintf( skillTreeFile,"",dicoResult[0].c_str()); + } + else + fprintf( skillTreeFile,"",(*itSkillcode).first.c_str()); + } + else + fprintf( skillTreeFile,""); + } + fprintf( skillTreeFile,"\n"); + } + + fprintf( skillTreeFile, "
    0 to 2020 to 5050 to 100100 to 150150 to 200200 to 250
    %s%s

    \n" ); + fprintf( skillTreeFile, "\n" ); + fclose( skillTreeFile ); + +} // makeSkillTreeFile // + + + + + +//----------------------------------------------- +// MAIN +// +//----------------------------------------------- +int main(int argc, char* argv[]) +{ + // parse command line + const char *inputFilename = NULL; + for ( uint i=1; (sint)i!=argc; i++ ) + { + const char *arg = argv[i]; + if ( arg[0] == '-' ) + { + switch ( arg[1] ) + { + case 'p': + ++i; + if ( (sint)i == argc ) + { + fprintf( stderr, "Missing after -p option\n" ); + usage( argv[0], stderr ); + exit( 0 ); + } + inputSheetPath = argv[i]; + break; + case 'o': + ++i; + if ( (sint)i == argc ) + { + fprintf( stderr, "Missing after -o option\n" ); + usage( argv[0], stderr ); + exit( 0 ); + } + PhrasePath = argv[i]; + if ( PhrasePath[PhrasePath.size()-1] != '/' ) + PhrasePath += '/'; + break; + case 'b' : + GenerateBrickProgression = true; + break; + case 'd': + ProduceDocFromExistingPhrases = true; + break; + case 'm': + MultipleDocFiles = true; + break; + case 'n': + Hypertext = false; + break; + } + } + else + { + if ( CFile::getExtension(arg) == "csv" ) + { + inputFilename = arg; + } + else + nlerror( "Unrecognized extension in %s", arg ); + + } + } + + Dico.init(); + + loadSheetPath(); + FormLoader = UFormLoader::createLoader(); + CSheetId::init(); + + CSheetId skillTreeSheet("skills.skill_tree"); + CSmartPtr skillTreeForm = FormLoader->loadForm( "skills.skill_tree" ); + SkillsTree.readGeorges( skillTreeForm, skillTreeSheet ); + + + makeSkillTreeFile('C',"craft", false); + makeSkillTreeFile('F',"fight", false); + makeSkillTreeFile('H',"forage", false); + makeSkillTreeFile('M',"magic", false); + + makeSkillTreeFile('C',"craft", true); + makeSkillTreeFile('F',"fight", true); + makeSkillTreeFile('H',"forage", true); + makeSkillTreeFile('M',"magic", true); + + + // Load bricks from the csv + UseBricks = ProduceDocFromExistingPhrases; + if ( UseBricks ) + { + if ( ! inputFilename ) + { + usage( argv[0], stderr ); + exit( 0 ); + } + loadBricks( inputFilename ); + } + + + // Phrases + if ( ProduceDocFromExistingPhrases ) + { + loadBrickGrammar(); + loadBrickTitles(); + loadPhraseTitles(); + + DocFileNameRoot = toString( "%s", CFile::getFilenameWithoutExtension( inputFilename ).c_str() ); + + // index + makeIndexFile(); + + // progression by skill + makeActionsBySkillGroupFile(); + + // Progression (phrases sorted by skill value) + makeActionsBySkillValueFile(); + + // Progression (phrases sorted by skill value + detail) + makeActionsBySkillValueDetailFile(); + + } + + + if( GenerateBrickProgression ) + { + map > > levelToBrick; + + map phraseToSkill; + + for ( map< uint, pair >::const_iterator ip=Progression.begin(); ip!=Progression.end(); ++ip ) + { + const string& phraseCode = (*ip).second.first; + + string skillTmp = (*ip).second.second.c_str(); + + phraseToSkill.insert( make_pair(phraseCode,skillTmp) ); + + if(skillTmp.empty()==false) + { + // get skill + string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); + + // get level + string levelStr; + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + if(levelStr.find(".")!=-1) levelStr = levelStr.substr(0,levelStr.size()-1); + uint level = atoi(levelStr.c_str()); + + + map > >::iterator itLvl = levelToBrick.find(level); + if( itLvl == levelToBrick.end() ) + { + set s; + map > mp; + mp.insert(make_pair(skill,s)); + levelToBrick.insert(make_pair(level,mp)); + } + else + { + if( (*itLvl).second.find(skill) == (*itLvl).second.end() ) + { + set s; + (*itLvl).second.insert( make_pair(skill,s) ); + } + } + + msvs::iterator itPhrases = Phrases.find( phraseCode ); + if( itPhrases != Phrases.end() ) + { + string effect; + for( uint i = 0; i<(*itPhrases).second.size(); ++i ) + { + string brick = (*itPhrases).second[i]; + + if( levelToBrick[level][skill].find(brick) == levelToBrick[level][skill].end() ) + { + levelToBrick[level][skill].insert(brick); + } + } + } + } + } + + + + + // get family & color + map brickToColor; + map brickToFamily; + map::iterator itBInf; + for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) + { + string brk = (*itBInf).first; + + if(!validateBrick(brk)) continue; + + string color; + string family; + if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='M' ) + { + color = "Blue"; + family = "Modifier"; + } + if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='C' ) + { + color = "Red"; + family = "Credit"; + } + if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='O' ) + { + color = "Green"; + family = "Option"; + } + if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='P' ) + { + color = "Black"; + family = "Root"; + } + if( brk[brk.size()-getBrickTypeLetterRPos(brk)] =='E' ) + { + color = "Brown"; + family = "Effect"; + } + + brickToColor.insert(make_pair(brk,color)); + brickToFamily.insert(make_pair(brk,family)); + } + + // get phrases where the brick can be found + map > brickToPhrases; + msvs::iterator itPhrases; + for( itPhrases=Phrases.begin(); itPhrases!=Phrases.end(); ++itPhrases ) + { + for( uint i = 0; i<(*itPhrases).second.size(); ++i ) + { + string brick = (*itPhrases).second[i]; + if( brickToPhrases.find(brick)==brickToPhrases.end() ) + { + map m; + + m.insert(make_pair((*itPhrases).first,phraseToSkill[(*itPhrases).first])); + brickToPhrases.insert(make_pair(brick,m)); + } + else + { + brickToPhrases[brick].insert(make_pair((*itPhrases).first,phraseToSkill[(*itPhrases).first])); + } + } + } + + // get skill when a brick is learnt + map brickToLearnSkill; + map >::iterator itLearn; + for( itLearn=brickToPhrases.begin(); itLearn!=brickToPhrases.end(); ++itLearn ) + { + string minSkill; + uint minLevel = 250; + + mss::iterator itPh; + for( itPh=(*itLearn).second.begin(); itPh!=(*itLearn).second.end(); ++itPh ) + { + string skillTmp = (*itPh).second; + string levelStr; + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + uint level = atoi(levelStr.c_str()); + + if( level\n"); + fprintf( brickPhraseDocFile_m,"\n"); + fprintf( brickPhraseDocFile_m,"Brick phrases\n"); + fprintf( brickPhraseDocFile_m,"\n"); + fprintf( brickPhraseDocFile_m,"
    \n"); + + filename = DocFileNameRoot + "_c.html"; + FILE * brickPhraseDocFile_c = fopen( filename.c_str(), "wt" ); + fprintf( brickPhraseDocFile_c,"\n"); + fprintf( brickPhraseDocFile_c,"\n"); + fprintf( brickPhraseDocFile_c,"Brick phrases\n"); + fprintf( brickPhraseDocFile_c,"\n"); + fprintf( brickPhraseDocFile_c,"
    \n"); + + filename = DocFileNameRoot + "_o.html"; + FILE * brickPhraseDocFile_o = fopen( filename.c_str(), "wt" ); + fprintf( brickPhraseDocFile_o,"\n"); + fprintf( brickPhraseDocFile_o,"\n"); + fprintf( brickPhraseDocFile_o,"Brick phrases\n"); + fprintf( brickPhraseDocFile_o,"\n"); + fprintf( brickPhraseDocFile_o,"
    \n"); + + filename = DocFileNameRoot + "_p.html"; + FILE * brickPhraseDocFile_p = fopen( filename.c_str(), "wt" ); + fprintf( brickPhraseDocFile_p,"\n"); + fprintf( brickPhraseDocFile_p,"\n"); + fprintf( brickPhraseDocFile_p,"Brick phrases\n"); + fprintf( brickPhraseDocFile_p,"\n"); + fprintf( brickPhraseDocFile_p,"
    \n"); + + filename = DocFileNameRoot + "_e.html"; + FILE * brickPhraseDocFile_e = fopen( filename.c_str(), "wt" ); + fprintf( brickPhraseDocFile_e,"\n"); + fprintf( brickPhraseDocFile_e,"\n"); + fprintf( brickPhraseDocFile_e,"Brick phrases\n"); + fprintf( brickPhraseDocFile_e,"\n"); + fprintf( brickPhraseDocFile_e,"
    \n"); + + for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) + { + string brk = (*itBInf).first; + + if(!validateBrick(brk)) continue; + + string code = strlwr(brk.c_str()); + + if(brickToFamily[brk]=="Modifier") + fprintf( brickPhraseDocFile_m,"\n",brk.c_str(),code.c_str()); + if(brickToFamily[brk]=="Credit") + fprintf( brickPhraseDocFile_c,"\n",brk.c_str(),code.c_str()); + if(brickToFamily[brk]=="Option") + fprintf( brickPhraseDocFile_o,"\n",brk.c_str(),code.c_str()); + if(brickToFamily[brk]=="Effect") + fprintf( brickPhraseDocFile_e,"\n",brk.c_str(),code.c_str()); + if(brickToFamily[brk]=="Root") + fprintf( brickPhraseDocFile_p,"\n",brk.c_str(),code.c_str()); + + map >::iterator itPhrases = brickToPhrases.find(brk); + if( itPhrases != brickToPhrases.end() ) + { + map::iterator itPh; + for( itPh=(*itPhrases).second.begin(); itPh!=(*itPhrases).second.end(); ++itPh ) + { + if(brickToFamily[brk]=="Modifier") + fprintf( brickPhraseDocFile_m,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); + if(brickToFamily[brk]=="Credit") + fprintf( brickPhraseDocFile_c,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); + if(brickToFamily[brk]=="Option") + fprintf( brickPhraseDocFile_o,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); + if(brickToFamily[brk]=="Effect") + fprintf( brickPhraseDocFile_e,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); + if(brickToFamily[brk]=="Root") + fprintf( brickPhraseDocFile_p,"\n",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); + } + } + } + fprintf( brickPhraseDocFile_m, "
    %s
    %s
    %s
    %s
    %s
    %s
    %s
    %s
    %s
    %s

    \n" ); + fprintf( brickPhraseDocFile_m, "\n" ); + fclose( brickPhraseDocFile_m ); + + fprintf( brickPhraseDocFile_c, "

    \n" ); + fprintf( brickPhraseDocFile_c, "\n" ); + fclose( brickPhraseDocFile_c ); + + fprintf( brickPhraseDocFile_o, "

    \n" ); + fprintf( brickPhraseDocFile_o, "\n" ); + fclose( brickPhraseDocFile_o ); + + fprintf( brickPhraseDocFile_e, "

    \n" ); + fprintf( brickPhraseDocFile_e, "\n" ); + fclose( brickPhraseDocFile_e ); + + fprintf( brickPhraseDocFile_p, "

    \n" ); + fprintf( brickPhraseDocFile_p, "\n" ); + fclose( brickPhraseDocFile_p ); + + + // CODE + + // write header and title bar + filename = DocFileNameRoot + ".html"; + FILE * brickDocFile = fopen( filename.c_str(), "wt" ); + fprintf( brickDocFile,"\n"); + fprintf( brickDocFile,"\n"); + fprintf( brickDocFile,"Bricks infos\n"); + fprintf( brickDocFile,"\n"); + fprintf( brickDocFile,"
    \n"); + fprintf( brickDocFile,"\n"); + fprintf( brickDocFile,"\n"); + fprintf( brickDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickDocFile,"\n"); + fprintf( brickDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickDocFile,"\n"); + fprintf( brickDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickDocFile,"\n"); + fprintf( brickDocFile,"\n"); + + + // write infos + for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) + { + string brk = (*itBInf).first; + + if(!validateBrick(brk)) continue; + + string skillTmp = (*itBInf).second.LearnSkills; + string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); + CVectorSString dicoResult; + Dico.lookup( skill, dicoResult, true ); + if(dicoResult.empty()) continue; + + // color + string color = brickToColor[brk]; + + // code + string code = strlwr(brk.c_str()); + fprintf( brickDocFile, "\n",color.c_str(),code.c_str()); + + // name + string name = (*itBInf).second.Text; + fprintf( brickDocFile, "\n",name.c_str()); + + // family + string family = brickToFamily[brk]; + fprintf( brickDocFile, "\n",color.c_str(),family.c_str()); + + // required skill name + fprintf( brickDocFile, "\n",dicoResult[0].c_str()); + + // required skill value + string levelStr; + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + fprintf( brickDocFile, "\n",levelStr.c_str()); + + // learn skill name + string learnSkillTmp = brickToLearnSkill[brk]; + skill = learnSkillTmp.substr(0,learnSkillTmp.find_first_of(" ")); + fprintf( brickDocFile, "\n",skill.c_str()); + + // learn skill value + if( learnSkillTmp.find(";") != -1 ) + { + sint idx = learnSkillTmp.find_first_of(" "); + levelStr = learnSkillTmp.substr(idx+1,learnSkillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = learnSkillTmp.find_first_of(" "); + levelStr = learnSkillTmp.substr(idx+1,learnSkillTmp.size()-idx); + } + fprintf( brickDocFile, "\n",levelStr.c_str()); + + + // phrase list + fprintf( brickDocFile, "\n"); + } + fprintf( brickDocFile, "
    *Code*NameFamilyRequired Skill NameRequired Skill ValueLearn Skill NameLearn Skill ValueFound In Phrases
    %s%s%s%s%s%s%s"); + map >::iterator itPhrases = brickToPhrases.find(brk); + if( itPhrases != brickToPhrases.end() ) + { + map::iterator itPh; + uint i; + for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) + { + if( MultipleDocFiles ) + fprintf( brickDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); + else + fprintf( brickDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); + } + if( i==2 ) + { + char type = family[0]; + fprintf( brickDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); + } + } + + fprintf( brickDocFile, "

    \n" ); + fprintf( brickDocFile, "\n" ); + fclose( brickDocFile ); + + + + // NAME + + // write header and title bar + filename = DocFileNameRoot + "_name.html"; + FILE * brickNameDocFile = fopen( filename.c_str(), "wt" ); + fprintf( brickNameDocFile,"\n"); + fprintf( brickNameDocFile,"\n"); + fprintf( brickNameDocFile,"Bricks infos\n"); + fprintf( brickNameDocFile,"\n"); + fprintf( brickNameDocFile,"
    \n"); + fprintf( brickNameDocFile,"\n"); + fprintf( brickNameDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickNameDocFile,"\n"); + fprintf( brickNameDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickNameDocFile,"\n"); + fprintf( brickNameDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickNameDocFile,"\n"); + fprintf( brickNameDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickNameDocFile,"\n"); + fprintf( brickNameDocFile,"\n"); + + map nameToCode; + for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) + { + string brk = (*itBInf).first; + + if(!validateBrick(brk)) continue; + + // code + string code = strlwr(brk.c_str()); + + // name + string name = (*itBInf).second.Text; + if( !name.empty()) + nameToCode.insert( make_pair(name,brk) ); + } + + mss::iterator itNTC; + for( itNTC=nameToCode.begin(); itNTC!=nameToCode.end(); ++itNTC ) + { + itBInf=BrickInfo.find((*itNTC).second); + + string brk = (*itBInf).first; + + if(!validateBrick(brk)) continue; + + string skillTmp = (*itBInf).second.LearnSkills; + string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); + CVectorSString dicoResult; + Dico.lookup( skill, dicoResult, true ); + if(dicoResult.empty()) continue; + + // color + string color = brickToColor[brk]; + + // code + string code = strlwr(brk.c_str()); + fprintf( brickNameDocFile, "\n",color.c_str(),code.c_str()); + + // name + string name = (*itBInf).second.Text; + fprintf( brickNameDocFile, "\n",name.c_str()); + + // family + string family = brickToFamily[brk]; + fprintf( brickNameDocFile, "\n",color.c_str(),family.c_str()); + + // required skill name + fprintf( brickNameDocFile, "\n",dicoResult[0].c_str()); + + // required skill value + string levelStr; + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + fprintf( brickNameDocFile, "\n",levelStr.c_str()); + + // learn skill name + skillTmp = brickToLearnSkill[brk]; + skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); + fprintf( brickNameDocFile, "\n",skill.c_str()); + + // learn skill value + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + fprintf( brickNameDocFile, "\n",levelStr.c_str()); + + + // phrase list + fprintf( brickNameDocFile, "\n"); + + } + + fprintf( brickNameDocFile, "
    Code*Name*FamilyRequired Skill NameRequired Skill ValueLearn Skill NameLearn Skill ValueFound In Phrases
    %s%s%s%s%s%s%s"); + map >::iterator itPhrases = brickToPhrases.find(brk); + if( itPhrases != brickToPhrases.end() ) + { + map::iterator itPh; + uint i; + for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) + { + if( MultipleDocFiles ) + fprintf( brickNameDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); + else + fprintf( brickNameDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); + } + if( i==2 ) + { + char type = family[0]; + fprintf( brickNameDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); + } + } + + fprintf( brickNameDocFile, "

    \n" ); + fprintf( brickNameDocFile, "\n" ); + fclose( brickNameDocFile ); + + + + + // FAMILY + + // write header and title bar + filename = DocFileNameRoot + "_family.html"; + FILE * brickFamilyDocFile = fopen( filename.c_str(), "wt" ); + fprintf( brickFamilyDocFile,"\n"); + fprintf( brickFamilyDocFile,"\n"); + fprintf( brickFamilyDocFile,"Bricks infos\n"); + fprintf( brickFamilyDocFile,"\n"); + fprintf( brickFamilyDocFile,"
    \n"); + fprintf( brickFamilyDocFile,"\n"); + fprintf( brickFamilyDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickFamilyDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickFamilyDocFile,"\n"); + fprintf( brickFamilyDocFile,"\n"); + fprintf( brickFamilyDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickFamilyDocFile,"\n"); + fprintf( brickFamilyDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickFamilyDocFile,"\n"); + fprintf( brickFamilyDocFile,"\n"); + + + // write infos + multimap familyToCode; + for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) + { + string brk = (*itBInf).first; + + if(!validateBrick(brk)) continue; + + // family + string family = brickToFamily[brk]; + + familyToCode.insert( make_pair(family,brk) ); + } + + multimap::iterator itFTC; + for( itFTC=familyToCode.begin(); itFTC!=familyToCode.end(); ++itFTC ) + { + itBInf=BrickInfo.find((*itFTC).second); + + string brk = (*itBInf).first; + + if(!validateBrick(brk)) continue; + + string skillTmp = (*itBInf).second.LearnSkills; + string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); + CVectorSString dicoResult; + Dico.lookup( skill, dicoResult, true ); + if(dicoResult.empty()) continue; + + // color + string color = brickToColor[brk]; + + // code + string code = strlwr(brk.c_str()); + fprintf( brickFamilyDocFile, "\n",color.c_str(),code.c_str()); + + // name + string name = (*itBInf).second.Text; + fprintf( brickFamilyDocFile, "\n",name.c_str()); + + // family + string family = brickToFamily[brk]; + fprintf( brickFamilyDocFile, "\n",color.c_str(),family.c_str()); + + // required skill name + fprintf( brickFamilyDocFile, "\n",dicoResult[0].c_str()); + + // required skill value + string levelStr; + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + fprintf( brickFamilyDocFile, "\n",levelStr.c_str()); + + // learn skill name + skillTmp = brickToLearnSkill[brk]; + skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); + fprintf( brickFamilyDocFile, "\n",skill.c_str()); + + // learn skill value + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + fprintf( brickFamilyDocFile, "\n",levelStr.c_str()); + + + // phrase list + fprintf( brickFamilyDocFile, "\n"); + } + fprintf( brickFamilyDocFile, "
    CodeName*Family*Required Skill NameRequired Skill ValueLearn Skill NameLearn Skill ValueFound In Phrases
    %s%s%s%s%s%s%s"); + map >::iterator itPhrases = brickToPhrases.find(brk); + if( itPhrases != brickToPhrases.end() ) + { + map::iterator itPh; + uint i; + for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) + { + if( MultipleDocFiles ) + fprintf( brickFamilyDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); + else + fprintf( brickFamilyDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); + } + if( i==2 ) + { + char type = family[0]; + fprintf( brickFamilyDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); + } + } + + fprintf( brickFamilyDocFile, "

    \n" ); + fprintf( brickFamilyDocFile, "\n" ); + fclose( brickFamilyDocFile ); + + + + + // REQUIRED SKILL VALUE + + // write header and title bar + filename = DocFileNameRoot + "_required_skill_value.html"; + FILE * brickRequiredDocFile = fopen( filename.c_str(), "wt" ); + fprintf( brickRequiredDocFile,"\n"); + fprintf( brickRequiredDocFile,"\n"); + fprintf( brickRequiredDocFile,"Bricks infos\n"); + fprintf( brickRequiredDocFile,"\n"); + fprintf( brickRequiredDocFile,"
    \n"); + fprintf( brickRequiredDocFile,"\n"); + fprintf( brickRequiredDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickRequiredDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickRequiredDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickRequiredDocFile,"\n"); + fprintf( brickRequiredDocFile,"\n"); + fprintf( brickRequiredDocFile,"\n"); + fprintf( brickRequiredDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickRequiredDocFile,"\n"); + fprintf( brickRequiredDocFile,"\n"); + + + // write infos + multimap requiredSkillValueToCode; + for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) + { + string brk = (*itBInf).first; + + if(!validateBrick(brk)) continue; + + // required skill value + string skillTmp = (*itBInf).second.LearnSkills; + string levelStr; + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + uint level = atoi(levelStr.c_str()); + + requiredSkillValueToCode.insert( make_pair(level,brk) ); + } + + multimap::iterator itRTC; + for( itRTC=requiredSkillValueToCode.begin(); itRTC!=requiredSkillValueToCode.end(); ++itRTC ) + { + itBInf=BrickInfo.find((*itRTC).second); + + string brk = (*itBInf).first; + + if(!validateBrick(brk)) continue; + + string skillTmp = (*itBInf).second.LearnSkills; + string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); + CVectorSString dicoResult; + Dico.lookup( skill, dicoResult, true ); + if(dicoResult.empty()) continue; + + // color + string color = brickToColor[brk]; + + // code + string code = strlwr(brk.c_str()); + fprintf( brickRequiredDocFile, "\n",color.c_str(),code.c_str()); + + // name + string name = (*itBInf).second.Text; + fprintf( brickRequiredDocFile, "\n",name.c_str()); + + // family + string family = brickToFamily[brk]; + fprintf( brickRequiredDocFile, "\n",color.c_str(),family.c_str()); + + // required skill name + fprintf( brickRequiredDocFile, "\n",dicoResult[0].c_str()); + + // required skill value + string levelStr; + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + fprintf( brickRequiredDocFile, "\n",levelStr.c_str()); + + // learn skill name + skillTmp = brickToLearnSkill[brk]; + skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); + fprintf( brickRequiredDocFile, "\n",skill.c_str()); + + // learn skill value + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + fprintf( brickRequiredDocFile, "\n",levelStr.c_str()); + + + // phrase list + fprintf( brickRequiredDocFile, "\n"); + } + fprintf( brickRequiredDocFile, "
    CodeNameFamilyRequired Skill Name*Required Skill Value*Learn Skill NameLearn Skill ValueFound In Phrases
    %s%s%s%s%s%s%s"); + map >::iterator itPhrases = brickToPhrases.find(brk); + if( itPhrases != brickToPhrases.end() ) + { + map::iterator itPh; + uint i; + for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) + { + if( MultipleDocFiles ) + fprintf( brickRequiredDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); + else + fprintf( brickRequiredDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); + } + if( i==2 ) + { + char type = family[0]; + fprintf( brickRequiredDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); + } + } + + fprintf( brickRequiredDocFile, "

    \n" ); + fprintf( brickRequiredDocFile, "\n" ); + fclose( brickRequiredDocFile ); + + + + // LEARN SKILL VALUE + + // write header and title bar + filename = DocFileNameRoot + "_learn_skill_value.html"; + FILE * brickLearnDocFile = fopen( filename.c_str(), "wt" ); + fprintf( brickLearnDocFile,"\n"); + fprintf( brickLearnDocFile,"\n"); + fprintf( brickLearnDocFile,"Bricks infos\n"); + fprintf( brickLearnDocFile,"\n"); + fprintf( brickLearnDocFile,"
    \n"); + fprintf( brickLearnDocFile,"\n"); + fprintf( brickLearnDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickLearnDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickLearnDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickLearnDocFile,"\n"); + fprintf( brickLearnDocFile,"\n",DocFileNameRoot.c_str()); + fprintf( brickLearnDocFile,"\n"); + fprintf( brickLearnDocFile,"\n"); + fprintf( brickLearnDocFile,"\n"); + fprintf( brickLearnDocFile,"\n"); + + + // write infos + multimap learnSkillValueToCode; + for( itBInf=BrickInfo.begin(); itBInf!=BrickInfo.end(); ++itBInf ) + { + string brk = (*itBInf).first; + + if(!validateBrick(brk)) continue; + + // learn skill value + string skillTmp = brickToLearnSkill[brk]; + string levelStr; + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + uint level = atoi(levelStr.c_str()); + + learnSkillValueToCode.insert( make_pair(level,brk) ); + } + + multimap::iterator itLTC; + for( itLTC=learnSkillValueToCode.begin(); itLTC!=learnSkillValueToCode.end(); ++itLTC ) + { + itBInf=BrickInfo.find((*itLTC).second); + + string brk = (*itBInf).first; + + if(!validateBrick(brk)) continue; + + string skillTmp = (*itBInf).second.LearnSkills; + string skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); + CVectorSString dicoResult; + Dico.lookup( skill, dicoResult, true ); + if(dicoResult.empty()) continue; + + // color + string color = brickToColor[brk]; + + // code + string code = strlwr(brk.c_str()); + fprintf( brickLearnDocFile, "\n",color.c_str(),code.c_str()); + + // name + string name = (*itBInf).second.Text; + fprintf( brickLearnDocFile, "\n",name.c_str()); + + // family + string family = brickToFamily[brk]; + fprintf( brickLearnDocFile, "\n",color.c_str(),family.c_str()); + + // required skill name + fprintf( brickLearnDocFile, "\n",dicoResult[0].c_str()); + + // required skill value + string levelStr; + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + fprintf( brickLearnDocFile, "\n",levelStr.c_str()); + + // learn skill name + skillTmp = brickToLearnSkill[brk]; + skill = skillTmp.substr(0,skillTmp.find_first_of(" ")); + fprintf( brickLearnDocFile, "\n",skill.c_str()); + + // learn skill value + if( skillTmp.find(";") != -1 ) + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.find_first_of(";")-idx-1); + } + else + { + sint idx = skillTmp.find_first_of(" "); + levelStr = skillTmp.substr(idx+1,skillTmp.size()-idx); + } + fprintf( brickLearnDocFile, "\n",levelStr.c_str()); + + + // phrase list + fprintf( brickLearnDocFile, "\n"); + } + fprintf( brickLearnDocFile, "
    CodeNameFamilyRequired Skill NameRequired Skill ValueLearn Skill Name*Learn Skill Value*Found In Phrases
    %s%s%s%s%s%s%s"); + map >::iterator itPhrases = brickToPhrases.find(brk); + if( itPhrases != brickToPhrases.end() ) + { + map::iterator itPh; + uint i; + for( itPh=(*itPhrases).second.begin(),i=0; itPh!=(*itPhrases).second.end() && i<2; ++itPh,++i ) + { + if( MultipleDocFiles ) + fprintf( brickLearnDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first[7],(*itPh).first.c_str(),(*itPh).first.c_str()); + else + fprintf( brickLearnDocFile,"%s,  ",DocFileName.c_str(),(*itPh).first.c_str(),(*itPh).first.c_str()); + } + if( i==2 ) + { + char type = family[0]; + fprintf( brickLearnDocFile,"[...]",DocFileNameRoot.c_str(),type,brk.c_str()); + } + } + + fprintf( brickLearnDocFile, "

    \n" ); + fprintf( brickLearnDocFile, "\n" ); + fclose( brickLearnDocFile ); + + } + + + return 0; + +} // main // + + + + diff --git a/code/ryzom/tools/phrase_generator/skill_tree.cpp b/code/ryzom/tools/phrase_generator/skill_tree.cpp index 149ae81f9..d1ef6f101 100644 --- a/code/ryzom/tools/phrase_generator/skill_tree.cpp +++ b/code/ryzom/tools/phrase_generator/skill_tree.cpp @@ -1,130 +1,130 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "skill_tree.h" - -using namespace std; -using namespace NLMISC; -using namespace NLGEORGES; - - -//----------------------------------------------- -// readGeorges for CStaticSkillsTree -// -//----------------------------------------------- -void CStaticSkillsTree::readGeorges( const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId ) -{ - if( form ) - { - UFormElm& root = form->getRootNode(); - - UFormElm *arraySkillElt = NULL; - if( root.getNodeByName( &arraySkillElt, "SkillData" ) ) - { - if( arraySkillElt ) - { - uint NbSkills; - nlverify( arraySkillElt->getArraySize( NbSkills ) ); - - nlassertex( NbSkills == SKILLS::NUM_SKILLS, ("(%u != %u) Please synchronise game_share/skill.* with leveldesign/game_element/xp_table/skills.skill_tree (use skill_extractor.exe)", NbSkills, SKILLS::NUM_SKILLS)); - - SkillsTree.resize( NbSkills ); - - for( uint i = 0; i < NbSkills; ++i ) - { - UFormElm* SkillElt = NULL; - if( ! ( arraySkillElt->getArrayNode( &SkillElt, i ) && SkillElt ) ) - { - nlwarning(" can't get array node of SkillElt in sheet %s", sheetId.toString().c_str() ); - } - else - { - // Skill - string SkillName; - SkillElt->getValueByName( SkillName, "Skill" ); - SKILLS::ESkills skill = SKILLS::toSkill( SkillName ); - nlassert( skill != SKILLS::unknown ); - if (skill == SKILLS::unknown) - { - continue; - } - SkillsTree[ skill ].Skill = skill; - - if( ! SkillElt->getValueByName( SkillsTree[ skill ].SkillCode, "SkillCode" ) ) - { - nlwarning(" can't get node SkillCode in sheet %s", sheetId.toString().c_str() ); - } - - // Skill Code - if( ! SkillElt->getValueByName( SkillsTree[ skill ].SkillCode, "SkillCode" ) ) - { - nlwarning(" can't get node SkillCode in sheet %s", sheetId.toString().c_str() ); - } - - // Max skill value - if( ! SkillElt->getValueByName( SkillsTree[ skill ].MaxSkillValue, "MaxSkillValue" ) ) - { - nlwarning(" can't get node MaxSkillValue in sheet %s", sheetId.toString().c_str() ); - } - - // Type of stage - if( ! SkillElt->getValueByName( SkillsTree[ skill ].StageType, "Type of Stage" ) ) - { - nlwarning(" can't get node 'Type of Stage' in sheet %s", sheetId.toString().c_str() ); - } - - // ParentSkill - if( ! SkillElt->getValueByName( SkillName, "ParentSkill" ) ) - { - nlwarning(" can't get node ParentSkills in sheet %s", sheetId.toString().c_str() ); - } - else - { - SkillsTree[ skill ].ParentSkill = SKILLS::toSkill( SkillName ); - } - - // ChildSkills - UFormElm *arrayChildSkillElt = NULL; - if( SkillElt->getNodeByName( &arrayChildSkillElt, "ChildSkills" ) ) - { - if( arrayChildSkillElt ) - { - uint NbChildSkills; - nlverify( arrayChildSkillElt->getArraySize( NbChildSkills ) ); - - SkillsTree[ skill ].ChildSkills.resize( NbChildSkills ); - - for( uint i = 0; i < NbChildSkills; ++i ) - { - string childSkillName; - arrayChildSkillElt->getArrayValue( childSkillName, i ); - SKILLS::ESkills childSkill = SKILLS::toSkill( childSkillName ); - nlassert( childSkill != SKILLS::unknown ); - if (skill == SKILLS::unknown) - { - continue; - } - SkillsTree[ skill ].ChildSkills[ i ] = childSkill; - } - } - } - } - } - } - } - } -} - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "skill_tree.h" + +using namespace std; +using namespace NLMISC; +using namespace NLGEORGES; + + +//----------------------------------------------- +// readGeorges for CStaticSkillsTree +// +//----------------------------------------------- +void CStaticSkillsTree::readGeorges( const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId ) +{ + if( form ) + { + UFormElm& root = form->getRootNode(); + + UFormElm *arraySkillElt = NULL; + if( root.getNodeByName( &arraySkillElt, "SkillData" ) ) + { + if( arraySkillElt ) + { + uint NbSkills; + nlverify( arraySkillElt->getArraySize( NbSkills ) ); + + nlassertex( NbSkills == SKILLS::NUM_SKILLS, ("(%u != %u) Please synchronise game_share/skill.* with leveldesign/game_element/xp_table/skills.skill_tree (use skill_extractor.exe)", NbSkills, SKILLS::NUM_SKILLS)); + + SkillsTree.resize( NbSkills ); + + for( uint i = 0; i < NbSkills; ++i ) + { + UFormElm* SkillElt = NULL; + if( ! ( arraySkillElt->getArrayNode( &SkillElt, i ) && SkillElt ) ) + { + nlwarning(" can't get array node of SkillElt in sheet %s", sheetId.toString().c_str() ); + } + else + { + // Skill + string SkillName; + SkillElt->getValueByName( SkillName, "Skill" ); + SKILLS::ESkills skill = SKILLS::toSkill( SkillName ); + nlassert( skill != SKILLS::unknown ); + if (skill == SKILLS::unknown) + { + continue; + } + SkillsTree[ skill ].Skill = skill; + + if( ! SkillElt->getValueByName( SkillsTree[ skill ].SkillCode, "SkillCode" ) ) + { + nlwarning(" can't get node SkillCode in sheet %s", sheetId.toString().c_str() ); + } + + // Skill Code + if( ! SkillElt->getValueByName( SkillsTree[ skill ].SkillCode, "SkillCode" ) ) + { + nlwarning(" can't get node SkillCode in sheet %s", sheetId.toString().c_str() ); + } + + // Max skill value + if( ! SkillElt->getValueByName( SkillsTree[ skill ].MaxSkillValue, "MaxSkillValue" ) ) + { + nlwarning(" can't get node MaxSkillValue in sheet %s", sheetId.toString().c_str() ); + } + + // Type of stage + if( ! SkillElt->getValueByName( SkillsTree[ skill ].StageType, "Type of Stage" ) ) + { + nlwarning(" can't get node 'Type of Stage' in sheet %s", sheetId.toString().c_str() ); + } + + // ParentSkill + if( ! SkillElt->getValueByName( SkillName, "ParentSkill" ) ) + { + nlwarning(" can't get node ParentSkills in sheet %s", sheetId.toString().c_str() ); + } + else + { + SkillsTree[ skill ].ParentSkill = SKILLS::toSkill( SkillName ); + } + + // ChildSkills + UFormElm *arrayChildSkillElt = NULL; + if( SkillElt->getNodeByName( &arrayChildSkillElt, "ChildSkills" ) ) + { + if( arrayChildSkillElt ) + { + uint NbChildSkills; + nlverify( arrayChildSkillElt->getArraySize( NbChildSkills ) ); + + SkillsTree[ skill ].ChildSkills.resize( NbChildSkills ); + + for( uint i = 0; i < NbChildSkills; ++i ) + { + string childSkillName; + arrayChildSkillElt->getArrayValue( childSkillName, i ); + SKILLS::ESkills childSkill = SKILLS::toSkill( childSkillName ); + nlassert( childSkill != SKILLS::unknown ); + if (skill == SKILLS::unknown) + { + continue; + } + SkillsTree[ skill ].ChildSkills[ i ] = childSkill; + } + } + } + } + } + } + } + } +} + diff --git a/code/ryzom/tools/phrase_generator/skill_tree.h b/code/ryzom/tools/phrase_generator/skill_tree.h index e8e4f7d1a..2839d35a3 100644 --- a/code/ryzom/tools/phrase_generator/skill_tree.h +++ b/code/ryzom/tools/phrase_generator/skill_tree.h @@ -1,108 +1,108 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef SKILL_TREE_H -#define SKILL_TREE_H - -// Misc -#include "nel/misc/types_nl.h" -#include "nel/misc/stream.h" -#include "nel/misc/smart_ptr.h" -#include "nel/misc/sheet_id.h" - -// Georges -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" -//#include "nel/georges/u_form_dfn.h" -//#include "nel/georges/u_form_loader.h" -//#include "nel/georges/u_type.h" - -#include "game_share/skills.h" - -#include -#include - - -/** - * CStaticSkillsTree - * - * \author Alain Saffray - * \author Nevrax France - * \date 2002 - */ -class CStaticSkillsTree -{ -public : - struct SSkillData - { - SKILLS::ESkills Skill; - std::string SkillCode; - uint16 MaxSkillValue; - uint16 StageType; - SKILLS::ESkills ParentSkill; - std::vector ChildSkills; - - void serial(class NLMISC::IStream &f) throw(NLMISC::EStream) - { - f.serialEnum( Skill ); - f.serial( SkillCode ); - f.serial( MaxSkillValue ); - f.serial( StageType ); - f.serialEnum( ParentSkill ); - - if( f.isReading() ) - { - uint16 size; - f.serial( size ); - ChildSkills.resize( size ); - for( uint i = 0; i < size; ++i ) - { - f.serialEnum( ChildSkills[ i ] ); - } - } - else - { - uint16 size = ChildSkills.size(); - f.serial( size ); - for( std::vector::iterator it = ChildSkills.begin(); it != ChildSkills.end(); ++it ) - { - f.serialEnum( (*it) ); - } - } - } - }; - - /// read sheet - virtual void readGeorges( const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId ); - - // return the version of this class, increments this value when the content of this class changed - static uint getVersion () { return 1 + ( SKILLS::NUM_SKILLS << 16 ); } - - /// serialize - void serial(class NLMISC::IStream &f) throw(NLMISC::EStream) { f.serialCont( SkillsTree ); } - - /// destructor - virtual ~CStaticSkillsTree() {} - - /// called when the sheet is removed - void removed() {} - - std::vector< SSkillData > SkillsTree; -}; - -#endif // SKILL_TREE_H - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SKILL_TREE_H +#define SKILL_TREE_H + +// Misc +#include "nel/misc/types_nl.h" +#include "nel/misc/stream.h" +#include "nel/misc/smart_ptr.h" +#include "nel/misc/sheet_id.h" + +// Georges +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" +//#include "nel/georges/u_form_dfn.h" +//#include "nel/georges/u_form_loader.h" +//#include "nel/georges/u_type.h" + +#include "game_share/skills.h" + +#include +#include + + +/** + * CStaticSkillsTree + * + * \author Alain Saffray + * \author Nevrax France + * \date 2002 + */ +class CStaticSkillsTree +{ +public : + struct SSkillData + { + SKILLS::ESkills Skill; + std::string SkillCode; + uint16 MaxSkillValue; + uint16 StageType; + SKILLS::ESkills ParentSkill; + std::vector ChildSkills; + + void serial(class NLMISC::IStream &f) throw(NLMISC::EStream) + { + f.serialEnum( Skill ); + f.serial( SkillCode ); + f.serial( MaxSkillValue ); + f.serial( StageType ); + f.serialEnum( ParentSkill ); + + if( f.isReading() ) + { + uint16 size; + f.serial( size ); + ChildSkills.resize( size ); + for( uint i = 0; i < size; ++i ) + { + f.serialEnum( ChildSkills[ i ] ); + } + } + else + { + uint16 size = ChildSkills.size(); + f.serial( size ); + for( std::vector::iterator it = ChildSkills.begin(); it != ChildSkills.end(); ++it ) + { + f.serialEnum( (*it) ); + } + } + } + }; + + /// read sheet + virtual void readGeorges( const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId ); + + // return the version of this class, increments this value when the content of this class changed + static uint getVersion () { return 1 + ( SKILLS::NUM_SKILLS << 16 ); } + + /// serialize + void serial(class NLMISC::IStream &f) throw(NLMISC::EStream) { f.serialCont( SkillsTree ); } + + /// destructor + virtual ~CStaticSkillsTree() {} + + /// called when the sheet is removed + void removed() {} + + std::vector< SSkillData > SkillsTree; +}; + +#endif // SKILL_TREE_H + /* End of skill_tree.h */ \ No newline at end of file diff --git a/code/ryzom/tools/phrase_generator/sstring.h b/code/ryzom/tools/phrase_generator/sstring.h index 21faee6f1..a86005a95 100644 --- a/code/ryzom/tools/phrase_generator/sstring.h +++ b/code/ryzom/tools/phrase_generator/sstring.h @@ -1,538 +1,538 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef PDSLIB_STRING_H -#define PDSLIB_STRING_H - -#include - - -class CSString: public std::string -{ -public: - CSString() - { - } - - CSString(const char *s) - { - *(std::string *)this=s; - } - - CSString(const std::string &s) - { - *(std::string *)this=s; - } - - CSString(char c) - { - *(std::string *)this=c; - } - - CSString(int i,const char *fmt="%d") - { - char buf[1024]; - sprintf(buf,fmt,i); - *this=buf; - } - - CSString(unsigned u,const char *fmt="%u") - { - char buf[1024]; - sprintf(buf,fmt,u); - *this=buf; - } - - CSString(double d,const char *fmt="%f") - { - char buf[1024]; - sprintf(buf,fmt,d); - *this=buf; - } - - CSString(const char *s,const char *fmt) - { - char buf[1024]; - sprintf(buf,fmt,s); - *this=buf; - } - - CSString(const std::string &s,const char *fmt) - { - char buf[1024]; - sprintf(buf,fmt,s.c_str()); - *this=buf; - } - - char operator*() - { - if (empty()) - return 0; - return (*this)[0]; - } - - // return the n right hand most characters of a string - CSString right(unsigned count) const - { - if (count>=size()) - return *this; - return substr(size()-count); - } - - // return the string minus the n right hand most characters of a string - CSString rightCrop(unsigned count) const - { - if (count>=size()) - return CSString(); - return substr(0,size()-count); - } - - // return the n left hand most characters of a string - CSString left(unsigned count) const - { - return substr(0,count); - } - - // return the string minus the n left hand most characters of a string - CSString leftCrop(unsigned count) const - { - if (count>=size()) - return CSString(); - return substr(count); - } - - // return sub string up to but not including first instance of given character - CSString splitTo(char c,bool truncateThis=false) - { - unsigned i; - CSString result; - for (i=0;i='A' && (*this)[i]<='Z') || ((*this)[i]>='a' && (*this)[i]<='z') || - ((*this)[i]>='0' && (*this)[i]<='9') || (*this)[i]=='_') - { - // copy out an alpha-numeric string - for (;i<(*this).size() && - ( ((*this)[i]>='A' && (*this)[i]<='Z') || ((*this)[i]>='a' && (*this)[i]<='z') || - ((*this)[i]>='0' && (*this)[i]<='9') || (*this)[i]=='_') - ;++i) - result+=(*this)[i]; - } - else - { - // just take the first character of the input - result=(*this)[i]; - ++i; - } - - // remove the result string from the input string if so desired - if (truncateThis) - { - if (i(this)->firstWord(); - } - - // return sub string up to but not including first instance of given character - CSString tailFromFirstWord() const - { - CSString hold=*this; - hold.firstWord(true); - return hold; - } - - // count the number of words (or quote delimited sub-strings) in a string - unsigned countWords() const - { - unsigned count=0; - CSString hold=strip(); - while (!hold.empty()) - { - hold=hold.tailFromFirstWord().strip(); - ++count; - } - return count; - } - - // count the number of words (or quote delimited sub-strings) in a string - CSString word(unsigned idx) const - { - CSString hold=strip(); - - for (unsigned count=0;count(this)->firstWordOrWords(); - } - - // return sub string up to but not including first instance of given character - CSString tailFromFirstWordOrWords() const - { - CSString hold=*this; - hold.firstWordOrWords(true); - return hold; - } - - // count the number of words (or quote delimited sub-strings) in a string - unsigned countWordOrWords() const - { - unsigned count=0; - CSString hold=strip(); - while (!hold.empty()) - { - hold=hold.tailFromFirstWordOrWords().strip(); - ++count; - } - return count; - } - - // count the number of words (or quote delimited sub-strings) in a string - CSString wordOrWords(unsigned idx) const - { - CSString hold=strip(); - - for (unsigned count=0;count=0 && isWhiteSpace((*this)[j]); --j) {} - for (i=0; i='a' && c<='z') - c^=('a'^'A'); - result+=c; - } - return result; - } - - // making a lower case copy of a string - CSString toLower() const - { - CSString result; - std::string::const_iterator it; - for (it=begin();it!=end();++it) - { - char c=(*it); - if (c>='A' && c<='Z') - c^=('a'^'A'); - result+=c; - } - return result; - } - - // replacing all occurences of one string with another - CSString replace(const char *toFind,const char *replacement) const - { - // just bypass the problems that can cause a crash... - if (toFind==NULL || *toFind==0) - return *this; - - unsigned i,j; - CSString result; - for (i=0;isize()) - return size(); - - unsigned i,j; - for (i=startLocation;i bool atoi(C& result) const - { - result=::atoi(c_str()); - return (result!=0 || *this=="0"); - } - unsigned atoi() const - { - return ::atoi(c_str()); - } - - // a couple of handy atof routines... - template bool atof(C& result) const - { - result=::atof(c_str()); - return (result!=0 || *this=="0"); - } - double atof() const - { - return ::atof(c_str()); - } - - // case insensitive string compare - bool operator==(const std::string &other) const - { - return stricmp(c_str(),other.c_str())==0; - } - - // case insesnsitive string compare - bool operator!=(const std::string &other) const - { - return !(*this==other); - } -}; - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef PDSLIB_STRING_H +#define PDSLIB_STRING_H + +#include + + +class CSString: public std::string +{ +public: + CSString() + { + } + + CSString(const char *s) + { + *(std::string *)this=s; + } + + CSString(const std::string &s) + { + *(std::string *)this=s; + } + + CSString(char c) + { + *(std::string *)this=c; + } + + CSString(int i,const char *fmt="%d") + { + char buf[1024]; + sprintf(buf,fmt,i); + *this=buf; + } + + CSString(unsigned u,const char *fmt="%u") + { + char buf[1024]; + sprintf(buf,fmt,u); + *this=buf; + } + + CSString(double d,const char *fmt="%f") + { + char buf[1024]; + sprintf(buf,fmt,d); + *this=buf; + } + + CSString(const char *s,const char *fmt) + { + char buf[1024]; + sprintf(buf,fmt,s); + *this=buf; + } + + CSString(const std::string &s,const char *fmt) + { + char buf[1024]; + sprintf(buf,fmt,s.c_str()); + *this=buf; + } + + char operator*() + { + if (empty()) + return 0; + return (*this)[0]; + } + + // return the n right hand most characters of a string + CSString right(unsigned count) const + { + if (count>=size()) + return *this; + return substr(size()-count); + } + + // return the string minus the n right hand most characters of a string + CSString rightCrop(unsigned count) const + { + if (count>=size()) + return CSString(); + return substr(0,size()-count); + } + + // return the n left hand most characters of a string + CSString left(unsigned count) const + { + return substr(0,count); + } + + // return the string minus the n left hand most characters of a string + CSString leftCrop(unsigned count) const + { + if (count>=size()) + return CSString(); + return substr(count); + } + + // return sub string up to but not including first instance of given character + CSString splitTo(char c,bool truncateThis=false) + { + unsigned i; + CSString result; + for (i=0;i='A' && (*this)[i]<='Z') || ((*this)[i]>='a' && (*this)[i]<='z') || + ((*this)[i]>='0' && (*this)[i]<='9') || (*this)[i]=='_') + { + // copy out an alpha-numeric string + for (;i<(*this).size() && + ( ((*this)[i]>='A' && (*this)[i]<='Z') || ((*this)[i]>='a' && (*this)[i]<='z') || + ((*this)[i]>='0' && (*this)[i]<='9') || (*this)[i]=='_') + ;++i) + result+=(*this)[i]; + } + else + { + // just take the first character of the input + result=(*this)[i]; + ++i; + } + + // remove the result string from the input string if so desired + if (truncateThis) + { + if (i(this)->firstWord(); + } + + // return sub string up to but not including first instance of given character + CSString tailFromFirstWord() const + { + CSString hold=*this; + hold.firstWord(true); + return hold; + } + + // count the number of words (or quote delimited sub-strings) in a string + unsigned countWords() const + { + unsigned count=0; + CSString hold=strip(); + while (!hold.empty()) + { + hold=hold.tailFromFirstWord().strip(); + ++count; + } + return count; + } + + // count the number of words (or quote delimited sub-strings) in a string + CSString word(unsigned idx) const + { + CSString hold=strip(); + + for (unsigned count=0;count(this)->firstWordOrWords(); + } + + // return sub string up to but not including first instance of given character + CSString tailFromFirstWordOrWords() const + { + CSString hold=*this; + hold.firstWordOrWords(true); + return hold; + } + + // count the number of words (or quote delimited sub-strings) in a string + unsigned countWordOrWords() const + { + unsigned count=0; + CSString hold=strip(); + while (!hold.empty()) + { + hold=hold.tailFromFirstWordOrWords().strip(); + ++count; + } + return count; + } + + // count the number of words (or quote delimited sub-strings) in a string + CSString wordOrWords(unsigned idx) const + { + CSString hold=strip(); + + for (unsigned count=0;count=0 && isWhiteSpace((*this)[j]); --j) {} + for (i=0; i='a' && c<='z') + c^=('a'^'A'); + result+=c; + } + return result; + } + + // making a lower case copy of a string + CSString toLower() const + { + CSString result; + std::string::const_iterator it; + for (it=begin();it!=end();++it) + { + char c=(*it); + if (c>='A' && c<='Z') + c^=('a'^'A'); + result+=c; + } + return result; + } + + // replacing all occurences of one string with another + CSString replace(const char *toFind,const char *replacement) const + { + // just bypass the problems that can cause a crash... + if (toFind==NULL || *toFind==0) + return *this; + + unsigned i,j; + CSString result; + for (i=0;isize()) + return size(); + + unsigned i,j; + for (i=startLocation;i bool atoi(C& result) const + { + result=::atoi(c_str()); + return (result!=0 || *this=="0"); + } + unsigned atoi() const + { + return ::atoi(c_str()); + } + + // a couple of handy atof routines... + template bool atof(C& result) const + { + result=::atof(c_str()); + return (result!=0 || *this=="0"); + } + double atof() const + { + return ::atof(c_str()); + } + + // case insensitive string compare + bool operator==(const std::string &other) const + { + return stricmp(c_str(),other.c_str())==0; + } + + // case insesnsitive string compare + bool operator!=(const std::string &other) const + { + return !(*this==other); + } +}; + +#endif diff --git a/code/ryzom/tools/reynolds/reynolds_manager.cpp b/code/ryzom/tools/reynolds/reynolds_manager.cpp index e9c0ac5b6..b005aac5f 100644 --- a/code/ryzom/tools/reynolds/reynolds_manager.cpp +++ b/code/ryzom/tools/reynolds/reynolds_manager.cpp @@ -1,461 +1,461 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - -#include "stdpch.h" - -#include "reynolds_manager.h" - -#include "nel/georges/u_form_loader.h" -#include "nel/georges/load_form.h" - -using namespace std; -using namespace NLMISC; -using namespace NLPACS; -using namespace NLGEORGES; - - -/* - * Manager variables - */ - -// Continents -CContinentContainer CReynoldsManager::_Continents; - -// Track Map, all tracks referenced, held by a simple pointer so when no one references a track, it is deleted -CReynoldsManager::TTrackMap CReynoldsManager::_TrackMap; - -// Controlled Track Map, only controlled tracks, held by a smart pointer -CReynoldsManager::TControlledTrackMap CReynoldsManager::_ControlledTrackMap; - -// Command interface -CReynoldsManager::ICommandInterface *CReynoldsManager::_CommandInterface = NULL; - -// User init callback -CReynoldsManager::TUserCallback CReynoldsManager::_UserInitCallback = NULL; - -// User motion callback -CReynoldsManager::TUserMotionCallback CReynoldsManager::_UserMotionCallback = NULL; - -// User release callback -CReynoldsManager::TUserCallback CReynoldsManager::_UserReleaseCallback = NULL; - -// Georges sheets -map CReynoldsManager::_Sheets; - -// Sheets initialised ? -bool CReynoldsManager::_Initialised; - -// Current internal cycle -uint32 CReynoldsManager::_Cycle; - -/* - * Manager methods - */ - - -// ------------------------------------ -// Constructor -CReynoldsManager::CReynoldsManager() -{ - nlerror("CReynoldsManager: static library, must not be instanciated !"); -} - - - -// ------------------------------------ -// Init -void CReynoldsManager::init(const std::string &packSheetFile) -{ - _Continents.init(100, 100, 8.0, 1); - - initSheets(packSheetFile); - - _Cycle = 0; -} - -// ------------------------------------ -// Update -void CReynoldsManager::update(double dt) -{ - TControlledTrackMap::iterator it; - for (it=_ControlledTrackMap.begin(); it!=_ControlledTrackMap.end(); ++it) - { - CTrack *track = (CTrack*)((*it).second); - track->update(dt); - } - - ++_Cycle; -} - -// ------------------------------------ -// Release -void CReynoldsManager::release() -{ - _Continents.clear(); - - _ControlledTrackMap.clear(); - - if (!_TrackMap.empty()) - { - nlwarning("ReynoldsLib:CReynoldsManager:release(): TrackMap not empty at release !!"); - - TTrackMap::iterator it; - for (it=_TrackMap.begin(); it!=_TrackMap.end(); ++it) - delete (*it).second; - - _TrackMap.clear(); - } -} - - - -// ------------------------------------ -// Load continent -void CReynoldsManager::loadContinent(const std::string &name, const std::string &file, sint index) -{ - _Continents.loadContinent(name, file, index); -} - - - - - -// ------------------------------------ -// Create Track -CTrack *CReynoldsManager::createTrack(const CEntityId &entity) -{ - // look for the target, and create a new track if not found - TTrackMap::iterator itt = _TrackMap.find(entity); - if (itt == _TrackMap.end()) - { - CTrack *track = new CTrack(); - pair res = _TrackMap.insert(TTrackMap::value_type(entity, track)); - itt = res.first; - - requestSheet(entity); - } - return (*itt).second; -} - -// ------------------------------------ -// Remove Track from map -void CReynoldsManager::removeTrackFromMap(const CEntityId &entity) -{ - _TrackMap.erase(entity); -} - - - - - - - - -// ------------------------------------ -// Follow -void CReynoldsManager::follow(const NLMISC::CEntityId &entity, const NLMISC::CEntityId &target) -{ - // look for the track, and create a new one if not found -- in both maps - CTrack *etrack = createTrack(entity); - - TControlledTrackMap::iterator ite = _ControlledTrackMap.find(entity); - if (ite == _ControlledTrackMap.end()) - _ControlledTrackMap.insert(TControlledTrackMap::value_type(entity, etrack)); - - // look for the target, and create a new track if not found - CTrack *ttrack = createTrack(target); - - nldebug("ReynoldsLib:CReynoldsManager:follow(): %s now follows %s", entity.toString().c_str(), target.toString().c_str()); - - // let entity follow the target - etrack->follow(ttrack); -} - -// ------------------------------------ -// Go to -void CReynoldsManager::goTo(const NLMISC::CEntityId &entity, const NLMISC::CVectorD &position) -{ - // look for the track, and create a new one if not found -- in both maps - CTrack *etrack = createTrack(entity); - - TControlledTrackMap::iterator ite = _ControlledTrackMap.find(entity); - if (ite == _ControlledTrackMap.end()) - _ControlledTrackMap.insert(TControlledTrackMap::value_type(entity, etrack)); - - // create a fake track for point position - static uint i = 0; - CEntityId id(0, i++, 0, 0); - CTrack *pointTo = createTrack(id); - pointTo->setStatic(); - pointTo->setId(id, CSheetId::Unknown); - pointTo->setPosition(position, 0.0f); - - nldebug("ReynoldsLib:CReynoldsManager:goTo(): %s now goes to (%.1f,%.1f)", entity.toString().c_str(), position.x, position.y); - - // let entity follow the target - etrack->follow(pointTo); -} - -// ------------------------------------ -// Stop -void CReynoldsManager::leaveMove(const NLMISC::CEntityId &entity) -{ - TControlledTrackMap::iterator ite = _ControlledTrackMap.find(entity); - if (ite == _ControlledTrackMap.end()) - { - nlwarning("ReynoldsLib:CReynoldsManager:leaveMove(): undefined entity %s", entity.toString().c_str()); - return; - } - - nldebug("ReynoldsLib:CReynoldsManager:leaveMove(): %s control left", entity.toString().c_str()); - - (*ite).second->leave(); - _ControlledTrackMap.erase(ite); -} - -// ------------------------------------ -// Destroy -void CReynoldsManager::destroy(const NLMISC::CEntityId &entity) -{ - CTrack *track = getTrack(entity); - if (track != NULL) - track->forceRelease(); - - if (track != NULL && track->hasControlOwned()) - track->leave(); - - _ControlledTrackMap.erase(entity); -} - - - - - - -// ------------------------------------ -// Request Sheet -void CReynoldsManager::requestSheet(const NLMISC::CEntityId &entity) -{ - if (!checkInterface()) - return; - - _CommandInterface->requestSheet(entity); -} - -// ------------------------------------ -// Request Position -void CReynoldsManager::requestPosition(const NLMISC::CEntityId &entity) -{ - if (!checkInterface()) - return; - - _CommandInterface->requestPosition(entity); -} - -// ------------------------------------ -// Request Position Updates -void CReynoldsManager::requestPositionUpdates(const NLMISC::CEntityId &entity) -{ - if (!checkInterface()) - return; - - _CommandInterface->requestPositionUpdates(entity); -} - -// ------------------------------------ -// Unrequest Position Updates -void CReynoldsManager::unrequestPositionUpdates(const NLMISC::CEntityId &entity) -{ - if (!checkInterface()) - return; - - _CommandInterface->unrequestPositionUpdates(entity); -} - -// ------------------------------------ -// Request Vision -void CReynoldsManager::requestVision(const NLMISC::CEntityId &entity) -{ - if (!checkInterface()) - return; - - _CommandInterface->requestVision(entity); -} - -// ------------------------------------ -// Unrequest Vision -void CReynoldsManager::unrequestVision(const NLMISC::CEntityId &entity) -{ - if (!checkInterface()) - return; - - _CommandInterface->unrequestVision(entity); -} - - -// ------------------------------------ -// Updated position -void CReynoldsManager::updatedPosition(const CEntityId &entity, const CVectorD &position, float heading) -{ - if (_CommandInterface != NULL) - _CommandInterface->updatePosition(entity, position, heading); -} - -// ------------------------------------ -// Updated state -void CReynoldsManager::stateChanged(const CEntityId &entity, CTrackBase::TTrackState state) -{ - if (_CommandInterface != NULL) - _CommandInterface->stateChanged(entity, state); -} - - -// ------------------------------------ -// TrackStop -void CReynoldsManager::trackStop(CTrack *track) -{ - if (checkInterface()) - _CommandInterface->stopTrack(track->getId()); - - // remove track from controlled tracks - _ControlledTrackMap.erase(track->getId()); -} - - -// ------------------------------------ -// Create Move primitive -void CReynoldsManager::createMovePrimitive(const NLMISC::CVectorD &pos, NLPACS::UMovePrimitive *&primitive, NLPACS::UMoveContainer *&container) -{ - primitive = NULL; - container = NULL; - - uint8 continent = _Continents.findContinent(pos); - if (continent == -1) - { - nlwarning("ReynoldsLib:CReynoldsManager:createMovePrimitive(): unable to create move primitive"); - return; - } - - container = _Continents.getMoveContainer(continent); - primitive = container->addNonCollisionablePrimitive(); -} - - - - - -// ------------------------------------ -// Set Sheet -void CReynoldsManager::setSheet(const NLMISC::CEntityId &id, const NLMISC::CSheetId &sheet) -{ - CTrack *track = getTrack(id); - if (track == NULL) - { - nlwarning("ReynoldsLib:CReynoldsManager:setSheet(): Track %s not found", id.toString().c_str()); - return; - } - - if (track->hasId()) - { - nlwarning("ReynoldsLib:CReynoldsManager:setSheet(): Track %s already has an Id", id.toString().c_str()); - return; - } - - track->setId(id, sheet); -} - -// ------------------------------------ -// Set Position -void CReynoldsManager::setPosition(const NLMISC::CEntityId &id, const NLMISC::CVectorD &position, float heading) -{ - CTrack *track = getTrack(id); - if (track == NULL) - { - nlwarning("ReynoldsLib:CReynoldsManager:setPosition(): Track %s not found", id.toString().c_str()); - return; - } - - track->setPosition(position, heading); -} - -// ------------------------------------ -// Set Vision -void CReynoldsManager::setVision(const NLMISC::CEntityId &id, const std::vector &in, const std::vector &out) -{ - CTrack *track = getTrack(id); - if (track == NULL) - { - nlwarning("ReynoldsLib:CReynoldsManager:setVision(): Track %s not found", id.toString().c_str()); - return; - } - - track->updateVision(in, out); -} - -// ------------------------------------ -// Set Vision -void CReynoldsManager::setVision(const NLMISC::CEntityId &id, const std::vector &vision) -{ - CTrack *track = getTrack(id); - if (track == NULL) - { - nlwarning("ReynoldsLib:CReynoldsManager:setVision(): Track %s not found", id.toString().c_str()); - return; - } - - track->updateVision(vision); -} - - - - -//------------------------------------------------------------------------- -// Init Sheets -void CReynoldsManager::initSheets(const std::string &packSheetFile) -{ - if (_Initialised) - return; - - std::vector filters; - filters.push_back("creature"); - filters.push_back("player"); - - loadForm(filters, packSheetFile, _Sheets); - - _Initialised=true; -} - - -//------------------------------------------------------------------------- -// Lookup Sheet -const CTrack::CSheet *CReynoldsManager::lookup(const CSheetId &id) -{ - nlassert(_Initialised); - - // setup an iterator and lookup the sheet id in the map - std::map::iterator it; - it=_Sheets.find(id); - - // if we found a valid entry return a pointer to the creature record otherwise 0 - if (it != _Sheets.end()) - return &((*it).second); - else - return NULL; -} - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#include "stdpch.h" + +#include "reynolds_manager.h" + +#include "nel/georges/u_form_loader.h" +#include "nel/georges/load_form.h" + +using namespace std; +using namespace NLMISC; +using namespace NLPACS; +using namespace NLGEORGES; + + +/* + * Manager variables + */ + +// Continents +CContinentContainer CReynoldsManager::_Continents; + +// Track Map, all tracks referenced, held by a simple pointer so when no one references a track, it is deleted +CReynoldsManager::TTrackMap CReynoldsManager::_TrackMap; + +// Controlled Track Map, only controlled tracks, held by a smart pointer +CReynoldsManager::TControlledTrackMap CReynoldsManager::_ControlledTrackMap; + +// Command interface +CReynoldsManager::ICommandInterface *CReynoldsManager::_CommandInterface = NULL; + +// User init callback +CReynoldsManager::TUserCallback CReynoldsManager::_UserInitCallback = NULL; + +// User motion callback +CReynoldsManager::TUserMotionCallback CReynoldsManager::_UserMotionCallback = NULL; + +// User release callback +CReynoldsManager::TUserCallback CReynoldsManager::_UserReleaseCallback = NULL; + +// Georges sheets +map CReynoldsManager::_Sheets; + +// Sheets initialised ? +bool CReynoldsManager::_Initialised; + +// Current internal cycle +uint32 CReynoldsManager::_Cycle; + +/* + * Manager methods + */ + + +// ------------------------------------ +// Constructor +CReynoldsManager::CReynoldsManager() +{ + nlerror("CReynoldsManager: static library, must not be instanciated !"); +} + + + +// ------------------------------------ +// Init +void CReynoldsManager::init(const std::string &packSheetFile) +{ + _Continents.init(100, 100, 8.0, 1); + + initSheets(packSheetFile); + + _Cycle = 0; +} + +// ------------------------------------ +// Update +void CReynoldsManager::update(double dt) +{ + TControlledTrackMap::iterator it; + for (it=_ControlledTrackMap.begin(); it!=_ControlledTrackMap.end(); ++it) + { + CTrack *track = (CTrack*)((*it).second); + track->update(dt); + } + + ++_Cycle; +} + +// ------------------------------------ +// Release +void CReynoldsManager::release() +{ + _Continents.clear(); + + _ControlledTrackMap.clear(); + + if (!_TrackMap.empty()) + { + nlwarning("ReynoldsLib:CReynoldsManager:release(): TrackMap not empty at release !!"); + + TTrackMap::iterator it; + for (it=_TrackMap.begin(); it!=_TrackMap.end(); ++it) + delete (*it).second; + + _TrackMap.clear(); + } +} + + + +// ------------------------------------ +// Load continent +void CReynoldsManager::loadContinent(const std::string &name, const std::string &file, sint index) +{ + _Continents.loadContinent(name, file, index); +} + + + + + +// ------------------------------------ +// Create Track +CTrack *CReynoldsManager::createTrack(const CEntityId &entity) +{ + // look for the target, and create a new track if not found + TTrackMap::iterator itt = _TrackMap.find(entity); + if (itt == _TrackMap.end()) + { + CTrack *track = new CTrack(); + pair res = _TrackMap.insert(TTrackMap::value_type(entity, track)); + itt = res.first; + + requestSheet(entity); + } + return (*itt).second; +} + +// ------------------------------------ +// Remove Track from map +void CReynoldsManager::removeTrackFromMap(const CEntityId &entity) +{ + _TrackMap.erase(entity); +} + + + + + + + + +// ------------------------------------ +// Follow +void CReynoldsManager::follow(const NLMISC::CEntityId &entity, const NLMISC::CEntityId &target) +{ + // look for the track, and create a new one if not found -- in both maps + CTrack *etrack = createTrack(entity); + + TControlledTrackMap::iterator ite = _ControlledTrackMap.find(entity); + if (ite == _ControlledTrackMap.end()) + _ControlledTrackMap.insert(TControlledTrackMap::value_type(entity, etrack)); + + // look for the target, and create a new track if not found + CTrack *ttrack = createTrack(target); + + nldebug("ReynoldsLib:CReynoldsManager:follow(): %s now follows %s", entity.toString().c_str(), target.toString().c_str()); + + // let entity follow the target + etrack->follow(ttrack); +} + +// ------------------------------------ +// Go to +void CReynoldsManager::goTo(const NLMISC::CEntityId &entity, const NLMISC::CVectorD &position) +{ + // look for the track, and create a new one if not found -- in both maps + CTrack *etrack = createTrack(entity); + + TControlledTrackMap::iterator ite = _ControlledTrackMap.find(entity); + if (ite == _ControlledTrackMap.end()) + _ControlledTrackMap.insert(TControlledTrackMap::value_type(entity, etrack)); + + // create a fake track for point position + static uint i = 0; + CEntityId id(0, i++, 0, 0); + CTrack *pointTo = createTrack(id); + pointTo->setStatic(); + pointTo->setId(id, CSheetId::Unknown); + pointTo->setPosition(position, 0.0f); + + nldebug("ReynoldsLib:CReynoldsManager:goTo(): %s now goes to (%.1f,%.1f)", entity.toString().c_str(), position.x, position.y); + + // let entity follow the target + etrack->follow(pointTo); +} + +// ------------------------------------ +// Stop +void CReynoldsManager::leaveMove(const NLMISC::CEntityId &entity) +{ + TControlledTrackMap::iterator ite = _ControlledTrackMap.find(entity); + if (ite == _ControlledTrackMap.end()) + { + nlwarning("ReynoldsLib:CReynoldsManager:leaveMove(): undefined entity %s", entity.toString().c_str()); + return; + } + + nldebug("ReynoldsLib:CReynoldsManager:leaveMove(): %s control left", entity.toString().c_str()); + + (*ite).second->leave(); + _ControlledTrackMap.erase(ite); +} + +// ------------------------------------ +// Destroy +void CReynoldsManager::destroy(const NLMISC::CEntityId &entity) +{ + CTrack *track = getTrack(entity); + if (track != NULL) + track->forceRelease(); + + if (track != NULL && track->hasControlOwned()) + track->leave(); + + _ControlledTrackMap.erase(entity); +} + + + + + + +// ------------------------------------ +// Request Sheet +void CReynoldsManager::requestSheet(const NLMISC::CEntityId &entity) +{ + if (!checkInterface()) + return; + + _CommandInterface->requestSheet(entity); +} + +// ------------------------------------ +// Request Position +void CReynoldsManager::requestPosition(const NLMISC::CEntityId &entity) +{ + if (!checkInterface()) + return; + + _CommandInterface->requestPosition(entity); +} + +// ------------------------------------ +// Request Position Updates +void CReynoldsManager::requestPositionUpdates(const NLMISC::CEntityId &entity) +{ + if (!checkInterface()) + return; + + _CommandInterface->requestPositionUpdates(entity); +} + +// ------------------------------------ +// Unrequest Position Updates +void CReynoldsManager::unrequestPositionUpdates(const NLMISC::CEntityId &entity) +{ + if (!checkInterface()) + return; + + _CommandInterface->unrequestPositionUpdates(entity); +} + +// ------------------------------------ +// Request Vision +void CReynoldsManager::requestVision(const NLMISC::CEntityId &entity) +{ + if (!checkInterface()) + return; + + _CommandInterface->requestVision(entity); +} + +// ------------------------------------ +// Unrequest Vision +void CReynoldsManager::unrequestVision(const NLMISC::CEntityId &entity) +{ + if (!checkInterface()) + return; + + _CommandInterface->unrequestVision(entity); +} + + +// ------------------------------------ +// Updated position +void CReynoldsManager::updatedPosition(const CEntityId &entity, const CVectorD &position, float heading) +{ + if (_CommandInterface != NULL) + _CommandInterface->updatePosition(entity, position, heading); +} + +// ------------------------------------ +// Updated state +void CReynoldsManager::stateChanged(const CEntityId &entity, CTrackBase::TTrackState state) +{ + if (_CommandInterface != NULL) + _CommandInterface->stateChanged(entity, state); +} + + +// ------------------------------------ +// TrackStop +void CReynoldsManager::trackStop(CTrack *track) +{ + if (checkInterface()) + _CommandInterface->stopTrack(track->getId()); + + // remove track from controlled tracks + _ControlledTrackMap.erase(track->getId()); +} + + +// ------------------------------------ +// Create Move primitive +void CReynoldsManager::createMovePrimitive(const NLMISC::CVectorD &pos, NLPACS::UMovePrimitive *&primitive, NLPACS::UMoveContainer *&container) +{ + primitive = NULL; + container = NULL; + + uint8 continent = _Continents.findContinent(pos); + if (continent == -1) + { + nlwarning("ReynoldsLib:CReynoldsManager:createMovePrimitive(): unable to create move primitive"); + return; + } + + container = _Continents.getMoveContainer(continent); + primitive = container->addNonCollisionablePrimitive(); +} + + + + + +// ------------------------------------ +// Set Sheet +void CReynoldsManager::setSheet(const NLMISC::CEntityId &id, const NLMISC::CSheetId &sheet) +{ + CTrack *track = getTrack(id); + if (track == NULL) + { + nlwarning("ReynoldsLib:CReynoldsManager:setSheet(): Track %s not found", id.toString().c_str()); + return; + } + + if (track->hasId()) + { + nlwarning("ReynoldsLib:CReynoldsManager:setSheet(): Track %s already has an Id", id.toString().c_str()); + return; + } + + track->setId(id, sheet); +} + +// ------------------------------------ +// Set Position +void CReynoldsManager::setPosition(const NLMISC::CEntityId &id, const NLMISC::CVectorD &position, float heading) +{ + CTrack *track = getTrack(id); + if (track == NULL) + { + nlwarning("ReynoldsLib:CReynoldsManager:setPosition(): Track %s not found", id.toString().c_str()); + return; + } + + track->setPosition(position, heading); +} + +// ------------------------------------ +// Set Vision +void CReynoldsManager::setVision(const NLMISC::CEntityId &id, const std::vector &in, const std::vector &out) +{ + CTrack *track = getTrack(id); + if (track == NULL) + { + nlwarning("ReynoldsLib:CReynoldsManager:setVision(): Track %s not found", id.toString().c_str()); + return; + } + + track->updateVision(in, out); +} + +// ------------------------------------ +// Set Vision +void CReynoldsManager::setVision(const NLMISC::CEntityId &id, const std::vector &vision) +{ + CTrack *track = getTrack(id); + if (track == NULL) + { + nlwarning("ReynoldsLib:CReynoldsManager:setVision(): Track %s not found", id.toString().c_str()); + return; + } + + track->updateVision(vision); +} + + + + +//------------------------------------------------------------------------- +// Init Sheets +void CReynoldsManager::initSheets(const std::string &packSheetFile) +{ + if (_Initialised) + return; + + std::vector filters; + filters.push_back("creature"); + filters.push_back("player"); + + loadForm(filters, packSheetFile, _Sheets); + + _Initialised=true; +} + + +//------------------------------------------------------------------------- +// Lookup Sheet +const CTrack::CSheet *CReynoldsManager::lookup(const CSheetId &id) +{ + nlassert(_Initialised); + + // setup an iterator and lookup the sheet id in the map + std::map::iterator it; + it=_Sheets.find(id); + + // if we found a valid entry return a pointer to the creature record otherwise 0 + if (it != _Sheets.end()) + return &((*it).second); + else + return NULL; +} + + diff --git a/code/ryzom/tools/reynolds/reynolds_manager.h b/code/ryzom/tools/reynolds/reynolds_manager.h index 7a36dbde4..78f2eae2f 100644 --- a/code/ryzom/tools/reynolds/reynolds_manager.h +++ b/code/ryzom/tools/reynolds/reynolds_manager.h @@ -1,351 +1,351 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - -#ifndef NL_REYNOLDS_MANAGER_H -#define NL_REYNOLDS_MANAGER_H - -// NeL -#include "nel/misc/types_nl.h" -#include "nel/misc/smart_ptr.h" - -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" - -// Game share -#include "game_share/continent_container.h" - -// ReynoldsLib -#include "track.h" - -// Stl -#include - - - - -/** - * Track manager - * \author Benjamin Legros - * \author Nevrax France - * \date 2002 - */ -class CReynoldsManager -{ - friend CTrack::~CTrack(); - -public: - - /** - * User Motion controlled Callback type - * \param track is the base track - */ - typedef void (*TUserCallback) (CTrackBase *track); - - /** - * User Motion Callback type - * Called each time a controlled track is updated - * \param track is the base track - * \param motion is the current motion to be applied -- WARNING do not crash this value, only add or substract value to it - */ - typedef void (*TUserMotionCallback) (CTrackBase *track, NLMISC::CVectorD &motion); - - - /// The command interface - class ICommandInterface - { - public: - /** - * Called when manager needs a sheet for an entity. - * Reply using setSheet(CEntityId) - */ - virtual void requestSheet(const NLMISC::CEntityId &id) = 0; - - /** - * Called when manager needs a position for an entity. - * Reply using setPosition(CEntityId) - */ - virtual void requestPosition(const NLMISC::CEntityId &id) = 0; - - /** - * Called when manager needs a position to be updated evently - * Reply using setPosition(CEntityId) evently - */ - virtual void requestPositionUpdates(const NLMISC::CEntityId &id) = 0; - - /** - * Called when manager doesn't need more position updates - */ - virtual void unrequestPositionUpdates(const NLMISC::CEntityId &id) = 0; - - /** - * Called when manager needs an entity vision to be updated evently - * Reply using setVision() evently - */ - virtual void requestVision(const NLMISC::CEntityId &id) = 0; - - /** - * Called when manager doesn't need more entity vision updates - */ - virtual void unrequestVision(const NLMISC::CEntityId &id) = 0; - - /** - * Called when a track position is updated - */ - virtual void updatePosition(const NLMISC::CEntityId &id, const NLMISC::CVectorD &position, float &heading) = 0; - - /** - * Called when track state changed - */ - virtual void stateChanged(const NLMISC::CEntityId &id, CTrackBase::TTrackState state) = 0; - - /** - * Called when manager leave control of an entity - */ - virtual void stopTrack(const NLMISC::CEntityId &id) = 0; - }; - -public: - - /// @name Reynolds Manager inits/update/release - //@{ - - /// Init - static void init(const std::string &packSheetFile = "reynolds.packed_sheets"); - - - /// Load continent - static void loadContinent(const std::string &name, const std::string &file, sint index); - - /// Set Sheet request callback - static void setCommandInterface(ICommandInterface *commandInterface) { _CommandInterface = commandInterface; } - - /// Set User init callback - static void setUserInitCallback(TUserCallback cb) { _UserInitCallback = cb; } - - /// Set User motion callback - static void setUserMotionCallback(TUserMotionCallback cb) { _UserMotionCallback = cb; } - - /// Set User release callback - static void setUserReleaseCallback(TUserCallback cb) { _UserReleaseCallback = cb; } - - /// Update - static void update(double dt = 0.1); - - - /// Release - static void release(); - - //@} - - - - - /// @name Control methods over tracks - //@{ - - /// Follow - static void follow(const NLMISC::CEntityId &entity, const NLMISC::CEntityId &target); - - /// Go to - static void goTo(const NLMISC::CEntityId &entity, const NLMISC::CVectorD &position); - - /// Stop - static void leaveMove(const NLMISC::CEntityId &entity); - - /// Destroy a track - static void destroy(const NLMISC::CEntityId &entity); - - //@} - - - - - /// @name Tracks requests and state towards interface - //@{ - - /// Request Sheet - static void requestSheet(const NLMISC::CEntityId &entity); - - /// Request Position - static void requestPosition(const NLMISC::CEntityId &entity); - - /// Request Position Updates - static void requestPositionUpdates(const NLMISC::CEntityId &entity); - - /// Unrequest Position Updates - static void unrequestPositionUpdates(const NLMISC::CEntityId &entity); - - /// Request Vision - static void requestVision(const NLMISC::CEntityId &entity); - - /// Unrequest Vision - static void unrequestVision(const NLMISC::CEntityId &entity); - - /// Track stopped following - static void trackStop(CTrack *track); - - /// Updated position - static void updatedPosition(const NLMISC::CEntityId &entity, const NLMISC::CVectorD &position, float heading); - - /// Updated state - static void stateChanged(const NLMISC::CEntityId &entity, CTrackBase::TTrackState state); - - - - /// User init - static void initUserMotion(CTrack *track) - { - if (_UserInitCallback != NULL) - _UserInitCallback((CTrackBase*)track); - } - - /// User move - static void applyUserMotion(CTrack *track, NLMISC::CVectorD &motion) - { - if (_UserMotionCallback != NULL) - _UserMotionCallback((CTrackBase*)track, motion); - } - - /// User release - static void releaseUserMotion(CTrack *track) - { - if (_UserReleaseCallback != NULL) - _UserReleaseCallback((CTrackBase*)track); - } - - - - /// Create Move primitive - static void createMovePrimitive(const NLMISC::CVectorD &pos, NLPACS::UMovePrimitive *&primitive, NLPACS::UMoveContainer *&container); - - /// Lookup a sheet - static const CTrack::CSheet *lookup(const NLMISC::CSheetId &sheet); - - //@} - - - - - /// @name Answers to tracks requests - //@{ - - /// Set Sheet - static void setSheet(const NLMISC::CEntityId &id, const NLMISC::CSheetId &sheet); - - /// Set Position - static void setPosition(const NLMISC::CEntityId &id, const NLMISC::CVectorD &position, float heading); - - /// Update Vision - static void setVision(const NLMISC::CEntityId &id, const std::vector &in, const std::vector &out); - - /// Update Vision - static void setVision(const NLMISC::CEntityId &id, const std::vector &vision); - - /// Get a track - static CTrack *getTrack(const NLMISC::CEntityId &entity) - { - TTrackMap::iterator it = _TrackMap.find(entity); - return (it == _TrackMap.end()) ? NULL : (*it).second; - } - - /// Get cycle - static uint32 getCycle() { return _Cycle; } - - //@} - - - - - /// Create a non controlled track, referenced in _TrackMap - static CTrack *createTrack(const NLMISC::CEntityId &entity); - - -protected: - - /// Constructor. Not to be used. - CReynoldsManager(); - - /// Remove a track from the whole map -- only called by the CTrack destructor - static void removeTrackFromMap(const NLMISC::CEntityId &entity); - - /// Checks interface is ok - static bool checkInterface() - { - if (_CommandInterface == NULL) - { - nlwarning("CReynoldsLib:checkInterface(): CommandInterface not set"); - return false; - } - return true; - } - - /// Init sheets - static void initSheets(const std::string &packSheetFilnamePrefix); - - -protected: - - /// Whole track container - typedef std::map TTrackMap; - - /// Only controlled track container - typedef std::map > TControlledTrackMap; - - - - -protected: - - /// Continents - static CContinentContainer _Continents; - - /// Track Map, all tracks referenced, held by a simple pointer so when no one references a track, it is deleted - static TTrackMap _TrackMap; - - /// Controlled Track Map, only controlled tracks, held by a smart pointer - static TControlledTrackMap _ControlledTrackMap; - - - /// Georges sheets - static std::map _Sheets; - - /// Sheets initialised ? - static bool _Initialised; - - - /// Command interface - static ICommandInterface *_CommandInterface; - - /// User init callback - static TUserCallback _UserInitCallback; - - /// User motion callback - static TUserMotionCallback _UserMotionCallback; - - /// User release callback - static TUserCallback _UserReleaseCallback; - - - /// Current internal cycle - static uint32 _Cycle; -}; - - -#endif // NL_REYNOLDS_MANAGER_H - -/* End of reynolds_manager.h */ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef NL_REYNOLDS_MANAGER_H +#define NL_REYNOLDS_MANAGER_H + +// NeL +#include "nel/misc/types_nl.h" +#include "nel/misc/smart_ptr.h" + +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" + +// Game share +#include "game_share/continent_container.h" + +// ReynoldsLib +#include "track.h" + +// Stl +#include + + + + +/** + * Track manager + * \author Benjamin Legros + * \author Nevrax France + * \date 2002 + */ +class CReynoldsManager +{ + friend CTrack::~CTrack(); + +public: + + /** + * User Motion controlled Callback type + * \param track is the base track + */ + typedef void (*TUserCallback) (CTrackBase *track); + + /** + * User Motion Callback type + * Called each time a controlled track is updated + * \param track is the base track + * \param motion is the current motion to be applied -- WARNING do not crash this value, only add or substract value to it + */ + typedef void (*TUserMotionCallback) (CTrackBase *track, NLMISC::CVectorD &motion); + + + /// The command interface + class ICommandInterface + { + public: + /** + * Called when manager needs a sheet for an entity. + * Reply using setSheet(CEntityId) + */ + virtual void requestSheet(const NLMISC::CEntityId &id) = 0; + + /** + * Called when manager needs a position for an entity. + * Reply using setPosition(CEntityId) + */ + virtual void requestPosition(const NLMISC::CEntityId &id) = 0; + + /** + * Called when manager needs a position to be updated evently + * Reply using setPosition(CEntityId) evently + */ + virtual void requestPositionUpdates(const NLMISC::CEntityId &id) = 0; + + /** + * Called when manager doesn't need more position updates + */ + virtual void unrequestPositionUpdates(const NLMISC::CEntityId &id) = 0; + + /** + * Called when manager needs an entity vision to be updated evently + * Reply using setVision() evently + */ + virtual void requestVision(const NLMISC::CEntityId &id) = 0; + + /** + * Called when manager doesn't need more entity vision updates + */ + virtual void unrequestVision(const NLMISC::CEntityId &id) = 0; + + /** + * Called when a track position is updated + */ + virtual void updatePosition(const NLMISC::CEntityId &id, const NLMISC::CVectorD &position, float &heading) = 0; + + /** + * Called when track state changed + */ + virtual void stateChanged(const NLMISC::CEntityId &id, CTrackBase::TTrackState state) = 0; + + /** + * Called when manager leave control of an entity + */ + virtual void stopTrack(const NLMISC::CEntityId &id) = 0; + }; + +public: + + /// @name Reynolds Manager inits/update/release + //@{ + + /// Init + static void init(const std::string &packSheetFile = "reynolds.packed_sheets"); + + + /// Load continent + static void loadContinent(const std::string &name, const std::string &file, sint index); + + /// Set Sheet request callback + static void setCommandInterface(ICommandInterface *commandInterface) { _CommandInterface = commandInterface; } + + /// Set User init callback + static void setUserInitCallback(TUserCallback cb) { _UserInitCallback = cb; } + + /// Set User motion callback + static void setUserMotionCallback(TUserMotionCallback cb) { _UserMotionCallback = cb; } + + /// Set User release callback + static void setUserReleaseCallback(TUserCallback cb) { _UserReleaseCallback = cb; } + + /// Update + static void update(double dt = 0.1); + + + /// Release + static void release(); + + //@} + + + + + /// @name Control methods over tracks + //@{ + + /// Follow + static void follow(const NLMISC::CEntityId &entity, const NLMISC::CEntityId &target); + + /// Go to + static void goTo(const NLMISC::CEntityId &entity, const NLMISC::CVectorD &position); + + /// Stop + static void leaveMove(const NLMISC::CEntityId &entity); + + /// Destroy a track + static void destroy(const NLMISC::CEntityId &entity); + + //@} + + + + + /// @name Tracks requests and state towards interface + //@{ + + /// Request Sheet + static void requestSheet(const NLMISC::CEntityId &entity); + + /// Request Position + static void requestPosition(const NLMISC::CEntityId &entity); + + /// Request Position Updates + static void requestPositionUpdates(const NLMISC::CEntityId &entity); + + /// Unrequest Position Updates + static void unrequestPositionUpdates(const NLMISC::CEntityId &entity); + + /// Request Vision + static void requestVision(const NLMISC::CEntityId &entity); + + /// Unrequest Vision + static void unrequestVision(const NLMISC::CEntityId &entity); + + /// Track stopped following + static void trackStop(CTrack *track); + + /// Updated position + static void updatedPosition(const NLMISC::CEntityId &entity, const NLMISC::CVectorD &position, float heading); + + /// Updated state + static void stateChanged(const NLMISC::CEntityId &entity, CTrackBase::TTrackState state); + + + + /// User init + static void initUserMotion(CTrack *track) + { + if (_UserInitCallback != NULL) + _UserInitCallback((CTrackBase*)track); + } + + /// User move + static void applyUserMotion(CTrack *track, NLMISC::CVectorD &motion) + { + if (_UserMotionCallback != NULL) + _UserMotionCallback((CTrackBase*)track, motion); + } + + /// User release + static void releaseUserMotion(CTrack *track) + { + if (_UserReleaseCallback != NULL) + _UserReleaseCallback((CTrackBase*)track); + } + + + + /// Create Move primitive + static void createMovePrimitive(const NLMISC::CVectorD &pos, NLPACS::UMovePrimitive *&primitive, NLPACS::UMoveContainer *&container); + + /// Lookup a sheet + static const CTrack::CSheet *lookup(const NLMISC::CSheetId &sheet); + + //@} + + + + + /// @name Answers to tracks requests + //@{ + + /// Set Sheet + static void setSheet(const NLMISC::CEntityId &id, const NLMISC::CSheetId &sheet); + + /// Set Position + static void setPosition(const NLMISC::CEntityId &id, const NLMISC::CVectorD &position, float heading); + + /// Update Vision + static void setVision(const NLMISC::CEntityId &id, const std::vector &in, const std::vector &out); + + /// Update Vision + static void setVision(const NLMISC::CEntityId &id, const std::vector &vision); + + /// Get a track + static CTrack *getTrack(const NLMISC::CEntityId &entity) + { + TTrackMap::iterator it = _TrackMap.find(entity); + return (it == _TrackMap.end()) ? NULL : (*it).second; + } + + /// Get cycle + static uint32 getCycle() { return _Cycle; } + + //@} + + + + + /// Create a non controlled track, referenced in _TrackMap + static CTrack *createTrack(const NLMISC::CEntityId &entity); + + +protected: + + /// Constructor. Not to be used. + CReynoldsManager(); + + /// Remove a track from the whole map -- only called by the CTrack destructor + static void removeTrackFromMap(const NLMISC::CEntityId &entity); + + /// Checks interface is ok + static bool checkInterface() + { + if (_CommandInterface == NULL) + { + nlwarning("CReynoldsLib:checkInterface(): CommandInterface not set"); + return false; + } + return true; + } + + /// Init sheets + static void initSheets(const std::string &packSheetFilnamePrefix); + + +protected: + + /// Whole track container + typedef std::map TTrackMap; + + /// Only controlled track container + typedef std::map > TControlledTrackMap; + + + + +protected: + + /// Continents + static CContinentContainer _Continents; + + /// Track Map, all tracks referenced, held by a simple pointer so when no one references a track, it is deleted + static TTrackMap _TrackMap; + + /// Controlled Track Map, only controlled tracks, held by a smart pointer + static TControlledTrackMap _ControlledTrackMap; + + + /// Georges sheets + static std::map _Sheets; + + /// Sheets initialised ? + static bool _Initialised; + + + /// Command interface + static ICommandInterface *_CommandInterface; + + /// User init callback + static TUserCallback _UserInitCallback; + + /// User motion callback + static TUserMotionCallback _UserMotionCallback; + + /// User release callback + static TUserCallback _UserReleaseCallback; + + + /// Current internal cycle + static uint32 _Cycle; +}; + + +#endif // NL_REYNOLDS_MANAGER_H + +/* End of reynolds_manager.h */ diff --git a/code/ryzom/tools/reynolds/stdpch.cpp b/code/ryzom/tools/reynolds/stdpch.cpp index d4b14ffe2..a3d45576c 100644 --- a/code/ryzom/tools/reynolds/stdpch.cpp +++ b/code/ryzom/tools/reynolds/stdpch.cpp @@ -1,17 +1,17 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "stdpch.h" +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "stdpch.h" diff --git a/code/ryzom/tools/reynolds/stdpch.h b/code/ryzom/tools/reynolds/stdpch.h index 43d1fe8f7..c8852b724 100644 --- a/code/ryzom/tools/reynolds/stdpch.h +++ b/code/ryzom/tools/reynolds/stdpch.h @@ -1,46 +1,46 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -//#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "reynolds_manager.h" -#include "track.h" +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "reynolds_manager.h" +#include "track.h" diff --git a/code/ryzom/tools/reynolds/track.cpp b/code/ryzom/tools/reynolds/track.cpp index 86c06df9f..880081c67 100644 --- a/code/ryzom/tools/reynolds/track.cpp +++ b/code/ryzom/tools/reynolds/track.cpp @@ -1,545 +1,545 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - -#include "stdpch.h" - -#include "track.h" -#include "reynolds_manager.h" - -using namespace std; -using namespace NLMISC; -using namespace NLPACS; - - -// ------------------------------------ -// Attraction/Repulsion functions - -// strong repulsion limited -inline double softPointing(double dist, double strength, double amp = 1.0) -{ - return amp*atan(strength*dist)/1.5707963268; -} - -// strong repulsion limited -inline double softTargetting(double dist, double moderateDist, double strength, double amp = 1.0) -{ - return amp*( atan(strength*(dist-moderateDist-0.2)) + atan(strength*(dist-moderateDist+0.2)) )/3.1415927; -} - -// strong repulsion limited -inline double softRepulse(double dist, double moderateDist, double strength, double amp = 1.0) -{ - return amp*(0.5 - atan(strength*(dist-moderateDist)-1.0)/3.1415927); -} - - - -// Required target spacing -double CTrack::TargetSpacing = 0.5; - -// Target attraction strength -double CTrack::TargetAttraction = 3.0; - -// Target attraction amplification -double CTrack::TargetAmp = 2.0; - -// Fast obstacle exclusion distance -double CTrack::ObstacleExcludeDistance = 6.0; - -// Required obstacle spacing -double CTrack::ObstacleSpacing = 0.5; - -// Obstacle repulsion strength -double CTrack::ObstacleRepulsion = 3.0; - -// Obstacle repulsion amplification -double CTrack::ObstacleAmp = 2.0; - - -// Minimum motion distance -double CTrack::MinimumMotion = 0.2; - -// Lock distance threshold -double CTrack::LockThreshold = 0.1; - -// Lose distance threshold -double CTrack::LoseThreshold = 2.0; - -// Stabilise cycle -uint32 CTrack::StabiliseCycle = 5; - - -// The default sheet -CTrack::CSheet CTrack::CSheet::DefaultSheet; - - - - - -// ------------------------------------ -// Destructor -CTrack::~CTrack() -{ - nldebug("ReynoldsLib:CTrack:~CTrack(): Delete Track %s", _Id.toString().c_str()); - - // remove this track from the manager map - CReynoldsManager::removeTrackFromMap(_Id); - - // delete move primitive - deleteMovePrimitive(); - - nldebug("ReynoldsLib:CTrack:~CTrack(): Track %s deleted", _Id.toString().c_str()); -} - -// ------------------------------------ -// Init track -void CTrack::setId(const NLMISC::CEntityId &id, const NLMISC::CSheetId &sheet) -{ - _Id = id; - _SheetId = sheet; - _HasId = true; - _IdRequested = false; - - _Sheet = CReynoldsManager::lookup(_SheetId); - if (_Sheet == NULL) - _Sheet = &(CSheet::DefaultSheet); -} - - -// ------------------------------------ -// Follow -void CTrack::follow(CTrack *followed) -{ - acquireControl(); - acquireVision(); - - _Followed = followed; -} - -// ------------------------------------ -// Leave -void CTrack::leave() -{ - releaseControl(); - releaseVision(); - - _Followed = NULL; - - // warn reynolds manager the track left its target - CReynoldsManager::trackStop(this); -} - - - - -// ------------------------------------ -// Update -void CTrack::update(double dt) -{ - // do not update not owned tracks - if (!_OwnControl) - return; - - // check if target is forced to leave - CTrack *target = (CTrack*)_Followed; - if (target == NULL || target->_ForceRelease) - { - leave(); - return; - } - - // check if entity has id - if (!hasId() || !hasPosition()) - return; - - // check if has a move primitive - if (_MovePrimitive == NULL) - { - createMovePrimitive(); - // if failed, just leave - if (_MovePrimitive == NULL) - leave(); - return; - } - - // if target hasn't position and is not owned by manager, request for position updates - if (!target->isValid()) - return; - - // motion - CVectorD motion(CVectorD::Null); - CVectorD heading; - - - // -------------------------- - // move toward target - double targetObjective; - if (target->isStatic()) - { - CVectorD vdist; - double ddist; - - ddist = rawDistance(target, vdist); - heading = vdist; - - targetObjective = ddist; - - double strength = softPointing(ddist, TargetAttraction, TargetAmp); - - motion += (vdist * (_Sheet->RunSpeed*dt*strength/(ddist+0.01))); - } - else - { - CVectorD vdist; - double ddist; - - double cdist = contactDistance(target, vdist, ddist); - - targetObjective = cdist-TargetSpacing; - - double strength = softTargetting(cdist, TargetSpacing, TargetAttraction, TargetAmp); - - motion += (vdist * (_Sheet->RunSpeed*dt*strength/(ddist+0.01))); - } - - - // -------------------------- - // check target not lost - if (_State == TargetLocked && - targetObjective > LoseThreshold) - { - _State = TargetLost; - CReynoldsManager::stateChanged(_Id, _State); - leave(); - return; - } - - - // -------------------------- - // check target reachable - const double SmoothFactor = 0.7; - double tddelta = (_LastTargetDistance<0) ? _SmoothedTargetDistanceDelta : _LastTargetDistance-targetObjective; - _SmoothedTargetDistanceDelta = _SmoothedTargetDistanceDelta*SmoothFactor + tddelta*(1.0-SmoothFactor); - _LastTargetDistance = targetObjective; - - // if actor seems not to move fast enough, leave - if (_State == MovingTowardsTarget && - _SmoothedTargetDistanceDelta < 0.1 && - targetObjective > 1.0) - { - _State = TargetUnreachable; - CReynoldsManager::stateChanged(_Id, _State); - leave(); - return; - } - - - - // -------------------------- - // avoid obstacles in vision - TVision::iterator itv; - for (itv=_Vision.begin(); itv!=_Vision.end(); ) - { - CTrack *obstacle = (CTrack*)((*itv).second); - - // if obstacle is forced to be release, delete it - if (obstacle->_ForceRelease) - { - TVision::iterator itr = itv++; - _Vision.erase(itr); - continue; - } - - // if obstacle not yet ready, don't avoid it - if (!obstacle->isValid()) - continue; - - // don't avoid static obstacles (virtual tracks) - if (!obstacle->isStatic()) - { - CVectorD vdist; - double ddist; - - ddist = rawDistance(obstacle, vdist); - - if (ddist > ObstacleExcludeDistance) - continue; - - double cdist = contactDistanceWithRawDistance(obstacle, vdist, ddist); - double strength = softRepulse(cdist, ObstacleSpacing, ObstacleRepulsion, ObstacleAmp); - - motion -= (vdist * (_Sheet->WalkSpeed*dt*strength/(ddist+0.01))); - } - - ++itv; - } - - // -------------------------- - // avoid walls - CVectorD front = motion.normed(); - CVectorD lateral(-front.y, front.x, 0.0); - CVectorD normal; - float thetaProbe = frand(3.1415926535f) - 1.570796f; - - if (!_MoveContainer->testMove(_MovePrimitive, front*cos(thetaProbe)*2.0 + lateral*sin(thetaProbe)*1.0, 1, 0, &normal)) - motion += normal*_Sheet->WalkSpeed*dt; - - - - - - // -------------------------- - // other motion applied by user - CReynoldsManager::applyUserMotion(this, motion); - - - - - - // -------------------------- - // Do move - double motionNorm = motion.norm(); - - // check if enough motion - if (motionNorm < MinimumMotion) - { - if (targetObjective < LockThreshold && - _State == MovingTowardsTarget && - CReynoldsManager::getCycle()-_LastMoveCycle > StabiliseCycle) - { - _State = TargetLocked; - CReynoldsManager::stateChanged(_Id, _State); - } - return; - } - - // reset last moving cycle - _LastMoveCycle = CReynoldsManager::getCycle(); - - // renorm motion if needed - if (motionNorm > dt*_Sheet->RunSpeed) - motion *= dt*_Sheet->RunSpeed/motionNorm; - - // eval move - _MovePrimitive->move(motion, 0); - _MoveContainer->evalNCPrimitiveCollision(1, _MovePrimitive, 0); - - // store new position/heading - _Heading = (float)atan2(heading.y, heading.x); - _Position = _MovePrimitive->getFinalPosition(0); -} - - - -// ------------------------------------ -// Update vision -void CTrack::updateVision(const std::vector &in, const std::vector &out) -{ - uint i; - - // add new in vision - for (i=0; i >(in[i], newin)); - } - - // remove old of vision - for (i=0; i &vision) -{ - uint i; - - // add new in vision - TVision copy = _Vision; - _Vision.clear(); - for (i=0; i >(vision[i], newin)); - } -} - - - - - - -// ------------------------------------ -// Acquire Control -void CTrack::acquireControl() -{ - // set state to moving - _State = MovingTowardsTarget; - CReynoldsManager::stateChanged(_Id, _State); - - if (_OwnControl) - return; - - // unrequest for position updates if necessary - if (_PositionUpdatesRequested) - { - CReynoldsManager::unrequestPositionUpdates(_Id); - _PositionUpdatesRequested = false; - } - - // invalidate position - invalidPosition(); - - // and request for valid position - CReynoldsManager::requestPosition(_Id); - - // init user motion - CReynoldsManager::initUserMotion(this); - - _OwnControl = true; - - // init last move cycle - _LastMoveCycle = CReynoldsManager::getCycle(); -} - -// ------------------------------------ -// Release Control -void CTrack::releaseControl() -{ - // invalidate position - invalidPosition(); - - // remove primitive - deleteMovePrimitive(); - - // release user motion - CReynoldsManager::releaseUserMotion(this); - - // set state to moving - _State = Idle; - CReynoldsManager::stateChanged(_Id, _State); - - _OwnControl = false; -} - - -// ------------------------------------ -// Acquire vision -void CTrack::acquireVision() -{ - if (_ReceiveVision) - return; - - _ReceiveVision = true; - CReynoldsManager::requestVision(_Id); -} - -// ------------------------------------ -// Release vision -void CTrack::releaseVision() -{ - if (!_ReceiveVision) - return; - - _ReceiveVision = false; - CReynoldsManager::unrequestVision(_Id); -} - - - - -// ------------------------------------ -// Create Move primitive -void CTrack::createMovePrimitive() -{ - if (!hasPosition()) - { - nlwarning("ReynoldsLib:CTrack:createMovePrimitive(): Can't create move primitive, Track %s has no valid position", _Id.toString().c_str()); - return; - } - - if (!hasId()) - { - nlwarning("ReynoldsLib:CTrack:createMovePrimitive(): Can't create move primitive, Track %s has no valid id", _Id.toString().c_str()); - return; - } - - deleteMovePrimitive(); - - CReynoldsManager::createMovePrimitive(_Position, _MovePrimitive, _MoveContainer); - - _MovePrimitive->setPrimitiveType(UMovePrimitive::_2DOrientedCylinder); - _MovePrimitive->setReactionType(UMovePrimitive::Slide); - _MovePrimitive->setTriggerType(UMovePrimitive::NotATrigger); - _MovePrimitive->setCollisionMask(0); - _MovePrimitive->setOcclusionMask(0); - _MovePrimitive->setObstacle(false); - _MovePrimitive->setDontSnapToGround(false); - _MovePrimitive->setRadius(_Sheet->Radius); - _MovePrimitive->setHeight(_Sheet->Height); - - _MovePrimitive->insertInWorldImage(0); - _MovePrimitive->setGlobalPosition(_Position, 0); - _MovePrimitive->setOrientation(_Heading, 0); - _MoveContainer->evalCollision(1, 0); -} - -// ------------------------------------ -// Delete Move primitive -void CTrack::deleteMovePrimitive() -{ - if (_MovePrimitive != NULL) - { - if (_MoveContainer == NULL) - { - nlwarning("ReynoldsLib:CTrack:deleteMovePrimitive(): Track %s has a MovePrimitive, but MoveContainer not set", _Id.toString().c_str()); - } - else - { - _MoveContainer->removePrimitive(_MovePrimitive); - } - } - - _MovePrimitive = NULL; - _MoveContainer = NULL; -} - -// ------------------------------------ -// Request Id -void CTrack::requestId() -{ - _IdRequested = true; - CReynoldsManager::requestSheet(_Id); -} - -// ------------------------------------ -// Request Position -void CTrack::requestPositionUpdates() -{ - _PositionUpdatesRequested = true; - CReynoldsManager::requestPositionUpdates(_Id); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#include "stdpch.h" + +#include "track.h" +#include "reynolds_manager.h" + +using namespace std; +using namespace NLMISC; +using namespace NLPACS; + + +// ------------------------------------ +// Attraction/Repulsion functions + +// strong repulsion limited +inline double softPointing(double dist, double strength, double amp = 1.0) +{ + return amp*atan(strength*dist)/1.5707963268; +} + +// strong repulsion limited +inline double softTargetting(double dist, double moderateDist, double strength, double amp = 1.0) +{ + return amp*( atan(strength*(dist-moderateDist-0.2)) + atan(strength*(dist-moderateDist+0.2)) )/3.1415927; +} + +// strong repulsion limited +inline double softRepulse(double dist, double moderateDist, double strength, double amp = 1.0) +{ + return amp*(0.5 - atan(strength*(dist-moderateDist)-1.0)/3.1415927); +} + + + +// Required target spacing +double CTrack::TargetSpacing = 0.5; + +// Target attraction strength +double CTrack::TargetAttraction = 3.0; + +// Target attraction amplification +double CTrack::TargetAmp = 2.0; + +// Fast obstacle exclusion distance +double CTrack::ObstacleExcludeDistance = 6.0; + +// Required obstacle spacing +double CTrack::ObstacleSpacing = 0.5; + +// Obstacle repulsion strength +double CTrack::ObstacleRepulsion = 3.0; + +// Obstacle repulsion amplification +double CTrack::ObstacleAmp = 2.0; + + +// Minimum motion distance +double CTrack::MinimumMotion = 0.2; + +// Lock distance threshold +double CTrack::LockThreshold = 0.1; + +// Lose distance threshold +double CTrack::LoseThreshold = 2.0; + +// Stabilise cycle +uint32 CTrack::StabiliseCycle = 5; + + +// The default sheet +CTrack::CSheet CTrack::CSheet::DefaultSheet; + + + + + +// ------------------------------------ +// Destructor +CTrack::~CTrack() +{ + nldebug("ReynoldsLib:CTrack:~CTrack(): Delete Track %s", _Id.toString().c_str()); + + // remove this track from the manager map + CReynoldsManager::removeTrackFromMap(_Id); + + // delete move primitive + deleteMovePrimitive(); + + nldebug("ReynoldsLib:CTrack:~CTrack(): Track %s deleted", _Id.toString().c_str()); +} + +// ------------------------------------ +// Init track +void CTrack::setId(const NLMISC::CEntityId &id, const NLMISC::CSheetId &sheet) +{ + _Id = id; + _SheetId = sheet; + _HasId = true; + _IdRequested = false; + + _Sheet = CReynoldsManager::lookup(_SheetId); + if (_Sheet == NULL) + _Sheet = &(CSheet::DefaultSheet); +} + + +// ------------------------------------ +// Follow +void CTrack::follow(CTrack *followed) +{ + acquireControl(); + acquireVision(); + + _Followed = followed; +} + +// ------------------------------------ +// Leave +void CTrack::leave() +{ + releaseControl(); + releaseVision(); + + _Followed = NULL; + + // warn reynolds manager the track left its target + CReynoldsManager::trackStop(this); +} + + + + +// ------------------------------------ +// Update +void CTrack::update(double dt) +{ + // do not update not owned tracks + if (!_OwnControl) + return; + + // check if target is forced to leave + CTrack *target = (CTrack*)_Followed; + if (target == NULL || target->_ForceRelease) + { + leave(); + return; + } + + // check if entity has id + if (!hasId() || !hasPosition()) + return; + + // check if has a move primitive + if (_MovePrimitive == NULL) + { + createMovePrimitive(); + // if failed, just leave + if (_MovePrimitive == NULL) + leave(); + return; + } + + // if target hasn't position and is not owned by manager, request for position updates + if (!target->isValid()) + return; + + // motion + CVectorD motion(CVectorD::Null); + CVectorD heading; + + + // -------------------------- + // move toward target + double targetObjective; + if (target->isStatic()) + { + CVectorD vdist; + double ddist; + + ddist = rawDistance(target, vdist); + heading = vdist; + + targetObjective = ddist; + + double strength = softPointing(ddist, TargetAttraction, TargetAmp); + + motion += (vdist * (_Sheet->RunSpeed*dt*strength/(ddist+0.01))); + } + else + { + CVectorD vdist; + double ddist; + + double cdist = contactDistance(target, vdist, ddist); + + targetObjective = cdist-TargetSpacing; + + double strength = softTargetting(cdist, TargetSpacing, TargetAttraction, TargetAmp); + + motion += (vdist * (_Sheet->RunSpeed*dt*strength/(ddist+0.01))); + } + + + // -------------------------- + // check target not lost + if (_State == TargetLocked && + targetObjective > LoseThreshold) + { + _State = TargetLost; + CReynoldsManager::stateChanged(_Id, _State); + leave(); + return; + } + + + // -------------------------- + // check target reachable + const double SmoothFactor = 0.7; + double tddelta = (_LastTargetDistance<0) ? _SmoothedTargetDistanceDelta : _LastTargetDistance-targetObjective; + _SmoothedTargetDistanceDelta = _SmoothedTargetDistanceDelta*SmoothFactor + tddelta*(1.0-SmoothFactor); + _LastTargetDistance = targetObjective; + + // if actor seems not to move fast enough, leave + if (_State == MovingTowardsTarget && + _SmoothedTargetDistanceDelta < 0.1 && + targetObjective > 1.0) + { + _State = TargetUnreachable; + CReynoldsManager::stateChanged(_Id, _State); + leave(); + return; + } + + + + // -------------------------- + // avoid obstacles in vision + TVision::iterator itv; + for (itv=_Vision.begin(); itv!=_Vision.end(); ) + { + CTrack *obstacle = (CTrack*)((*itv).second); + + // if obstacle is forced to be release, delete it + if (obstacle->_ForceRelease) + { + TVision::iterator itr = itv++; + _Vision.erase(itr); + continue; + } + + // if obstacle not yet ready, don't avoid it + if (!obstacle->isValid()) + continue; + + // don't avoid static obstacles (virtual tracks) + if (!obstacle->isStatic()) + { + CVectorD vdist; + double ddist; + + ddist = rawDistance(obstacle, vdist); + + if (ddist > ObstacleExcludeDistance) + continue; + + double cdist = contactDistanceWithRawDistance(obstacle, vdist, ddist); + double strength = softRepulse(cdist, ObstacleSpacing, ObstacleRepulsion, ObstacleAmp); + + motion -= (vdist * (_Sheet->WalkSpeed*dt*strength/(ddist+0.01))); + } + + ++itv; + } + + // -------------------------- + // avoid walls + CVectorD front = motion.normed(); + CVectorD lateral(-front.y, front.x, 0.0); + CVectorD normal; + float thetaProbe = frand(3.1415926535f) - 1.570796f; + + if (!_MoveContainer->testMove(_MovePrimitive, front*cos(thetaProbe)*2.0 + lateral*sin(thetaProbe)*1.0, 1, 0, &normal)) + motion += normal*_Sheet->WalkSpeed*dt; + + + + + + // -------------------------- + // other motion applied by user + CReynoldsManager::applyUserMotion(this, motion); + + + + + + // -------------------------- + // Do move + double motionNorm = motion.norm(); + + // check if enough motion + if (motionNorm < MinimumMotion) + { + if (targetObjective < LockThreshold && + _State == MovingTowardsTarget && + CReynoldsManager::getCycle()-_LastMoveCycle > StabiliseCycle) + { + _State = TargetLocked; + CReynoldsManager::stateChanged(_Id, _State); + } + return; + } + + // reset last moving cycle + _LastMoveCycle = CReynoldsManager::getCycle(); + + // renorm motion if needed + if (motionNorm > dt*_Sheet->RunSpeed) + motion *= dt*_Sheet->RunSpeed/motionNorm; + + // eval move + _MovePrimitive->move(motion, 0); + _MoveContainer->evalNCPrimitiveCollision(1, _MovePrimitive, 0); + + // store new position/heading + _Heading = (float)atan2(heading.y, heading.x); + _Position = _MovePrimitive->getFinalPosition(0); +} + + + +// ------------------------------------ +// Update vision +void CTrack::updateVision(const std::vector &in, const std::vector &out) +{ + uint i; + + // add new in vision + for (i=0; i >(in[i], newin)); + } + + // remove old of vision + for (i=0; i &vision) +{ + uint i; + + // add new in vision + TVision copy = _Vision; + _Vision.clear(); + for (i=0; i >(vision[i], newin)); + } +} + + + + + + +// ------------------------------------ +// Acquire Control +void CTrack::acquireControl() +{ + // set state to moving + _State = MovingTowardsTarget; + CReynoldsManager::stateChanged(_Id, _State); + + if (_OwnControl) + return; + + // unrequest for position updates if necessary + if (_PositionUpdatesRequested) + { + CReynoldsManager::unrequestPositionUpdates(_Id); + _PositionUpdatesRequested = false; + } + + // invalidate position + invalidPosition(); + + // and request for valid position + CReynoldsManager::requestPosition(_Id); + + // init user motion + CReynoldsManager::initUserMotion(this); + + _OwnControl = true; + + // init last move cycle + _LastMoveCycle = CReynoldsManager::getCycle(); +} + +// ------------------------------------ +// Release Control +void CTrack::releaseControl() +{ + // invalidate position + invalidPosition(); + + // remove primitive + deleteMovePrimitive(); + + // release user motion + CReynoldsManager::releaseUserMotion(this); + + // set state to moving + _State = Idle; + CReynoldsManager::stateChanged(_Id, _State); + + _OwnControl = false; +} + + +// ------------------------------------ +// Acquire vision +void CTrack::acquireVision() +{ + if (_ReceiveVision) + return; + + _ReceiveVision = true; + CReynoldsManager::requestVision(_Id); +} + +// ------------------------------------ +// Release vision +void CTrack::releaseVision() +{ + if (!_ReceiveVision) + return; + + _ReceiveVision = false; + CReynoldsManager::unrequestVision(_Id); +} + + + + +// ------------------------------------ +// Create Move primitive +void CTrack::createMovePrimitive() +{ + if (!hasPosition()) + { + nlwarning("ReynoldsLib:CTrack:createMovePrimitive(): Can't create move primitive, Track %s has no valid position", _Id.toString().c_str()); + return; + } + + if (!hasId()) + { + nlwarning("ReynoldsLib:CTrack:createMovePrimitive(): Can't create move primitive, Track %s has no valid id", _Id.toString().c_str()); + return; + } + + deleteMovePrimitive(); + + CReynoldsManager::createMovePrimitive(_Position, _MovePrimitive, _MoveContainer); + + _MovePrimitive->setPrimitiveType(UMovePrimitive::_2DOrientedCylinder); + _MovePrimitive->setReactionType(UMovePrimitive::Slide); + _MovePrimitive->setTriggerType(UMovePrimitive::NotATrigger); + _MovePrimitive->setCollisionMask(0); + _MovePrimitive->setOcclusionMask(0); + _MovePrimitive->setObstacle(false); + _MovePrimitive->setDontSnapToGround(false); + _MovePrimitive->setRadius(_Sheet->Radius); + _MovePrimitive->setHeight(_Sheet->Height); + + _MovePrimitive->insertInWorldImage(0); + _MovePrimitive->setGlobalPosition(_Position, 0); + _MovePrimitive->setOrientation(_Heading, 0); + _MoveContainer->evalCollision(1, 0); +} + +// ------------------------------------ +// Delete Move primitive +void CTrack::deleteMovePrimitive() +{ + if (_MovePrimitive != NULL) + { + if (_MoveContainer == NULL) + { + nlwarning("ReynoldsLib:CTrack:deleteMovePrimitive(): Track %s has a MovePrimitive, but MoveContainer not set", _Id.toString().c_str()); + } + else + { + _MoveContainer->removePrimitive(_MovePrimitive); + } + } + + _MovePrimitive = NULL; + _MoveContainer = NULL; +} + +// ------------------------------------ +// Request Id +void CTrack::requestId() +{ + _IdRequested = true; + CReynoldsManager::requestSheet(_Id); +} + +// ------------------------------------ +// Request Position +void CTrack::requestPositionUpdates() +{ + _PositionUpdatesRequested = true; + CReynoldsManager::requestPositionUpdates(_Id); +} diff --git a/code/ryzom/tools/reynolds/track.h b/code/ryzom/tools/reynolds/track.h index 0c48cee1a..943ac4ffc 100644 --- a/code/ryzom/tools/reynolds/track.h +++ b/code/ryzom/tools/reynolds/track.h @@ -1,503 +1,503 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - -#ifndef NL_TRACK_H -#define NL_TRACK_H - -#include "nel/misc/types_nl.h" -#include "nel/misc/smart_ptr.h" -#include "nel/misc/vector.h" -#include "nel/misc/vectord.h" -#include "nel/misc/entity_id.h" -#include "nel/misc/sheet_id.h" - -#include "nel/pacs/u_move_container.h" -#include "nel/pacs/u_move_primitive.h" - -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" - - -/** - * The base class for moving entity - * \author Benjamin Legros - * \author Nevrax France - * \date 2002 - */ -class CTrackBase -{ -public: - /// State type - enum TTrackState - { - Idle = 0, // not controlled yet - MovingTowardsTarget, // first step of motion, moving towards target - TargetLocked, // close to target, locked - TargetLost, // target moved away, can't reach it any longer - TargetUnreachable // can't reach target, too far or too many obstacles on the way - }; - - /// Get Id - virtual const NLMISC::CEntityId &getId() const = 0; - - /// Get SheetId - virtual const NLMISC::CSheetId &getSheetId() const = 0; - - /// Has Id ? - virtual bool hasId() const = 0; - - /// Get track Position - virtual void getPosition(NLMISC::CVectorD &pos, float &heading) const = 0; - - /// Has Position ? - virtual bool hasPosition() const = 0; - - /// Set user data - virtual void setUserData(void *data) = 0; - - /// Get user data - virtual void *getUserData() = 0; - - /// Get Track state - virtual TTrackState getTrackState() const = 0; -}; - -/** - * A track that represents a moving point - * \author Benjamin Legros - * \author Nevrax France - * \date 2002 - */ -class CTrack : public CTrackBase, public NLMISC::CRefCount -{ -public: - /** - * The sheet type read by Georges - */ - class CSheet - { - public: - CSheet(): WalkSpeed(1.3f), RunSpeed(6.0f), Radius(0.5f), Height(2.0f), Length(1.0), Width(1.0) {} - - /// The Walk speed of the entity - float WalkSpeed; - /// The Run speed of the entity - float RunSpeed; - /// The Pacs radius of the entity - float Radius; - /// The Height radius of the entity - float Height; - /// The Animation length of the entity - float Length; - /// The Width length of the entity - float Width; - - void readGeorges (const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId) - { - // the form was found so read the true values from George - form->getRootNode ().getValueByName (WalkSpeed, "Basics.MovementSpeeds.WalkSpeed"); - form->getRootNode ().getValueByName (RunSpeed, "Basics.MovementSpeeds.RunSpeed"); - form->getRootNode ().getValueByName (Radius, "Collision.CollisionRadius"); - form->getRootNode ().getValueByName (Height, "Collision.Height"); - form->getRootNode ().getValueByName (Width, "Collision.Width"); - form->getRootNode ().getValueByName (Length, "Collision.Length"); - } - - void serial (NLMISC::IStream &s) - { - s.serial (WalkSpeed, RunSpeed); - s.serial (Radius, Height); - s.serial (Length, Width); - } - - static uint getVersion () { return 1; } - - /// The default sheet - static CSheet DefaultSheet; - }; - -public: - - /// Constructor - CTrack() : _OwnControl(NULL), _MoveContainer(NULL), _MovePrimitive(NULL), - _Id(NLMISC::CEntityId::Unknown), _SheetId(NLMISC::CSheetId::Unknown), _Sheet(NULL), _Followed(NULL), - _HasPosition(false), _HasId(false), _IdRequested(false), _PositionUpdatesRequested(false), _IsStatic(false), - _ForceRelease(false), _ReceiveVision(false), _UserData(NULL), _State(Idle), - _SmoothedTargetDistanceDelta(3.0), _LastTargetDistance(-1.0) - - { - } - - /// Destructor - ~CTrack(); - - /// Init track - void setId(const NLMISC::CEntityId &id, const NLMISC::CSheetId &sheet); - - /// Get Id - const NLMISC::CEntityId &getId() const - { - return _Id; - } - - /// Get SheetId - const NLMISC::CSheetId &getSheetId() const - { - return _SheetId; - } - - /// Get SheetId - const CSheet *getSheet() const - { - return _Sheet; - } - - /// Has Id ? - bool hasId() const - { - return _HasId; - } - - - - /// Update track position - void setPosition(const NLMISC::CVectorD &pos, float heading) - { - // don't allow more than one position to be set when control is owned - if (_HasPosition && _OwnControl) - return; - _Position = pos; - _Heading = heading; - _HasPosition = true; - } - - /// Get track Position - void getPosition(NLMISC::CVectorD &pos, float &heading) const - { - if (_HasPosition) - { - pos = _Position; - heading = _Heading; - } - else - { - nlwarning("ReynoldsLib:CTrack:getPosition(): Track %s position not yet set", _Id.toString().c_str()); - } - } - - /// Set Static state - void setStatic(bool isstatic = true) - { - _IsStatic = isstatic; - } - - - - /// Has Control Owned ? - bool hasControlOwned() const - { - return _OwnControl; - } - - /// Has Position ? - bool hasPosition() const - { - return _HasPosition; - } - - /// Invalid position - void invalidPosition() - { - _HasPosition = false; - } - - /// Is static ? - bool isStatic() const - { - return _IsStatic; - } - - - - /// Follow - void follow(CTrack *followed); - - /// Leave - void leave(); - - /// Update - void update(double dt); - - /// Update vision - void updateVision(const std::vector &in, const std::vector &out); - - /// Update vision - void updateVision(const std::vector &vision); - - /// Force release - void forceRelease() { _ForceRelease = true; } - - - - /// Get current state - TTrackState getTrackState() const { return _State; } - - - - - /// Set user data - void setUserData(void *data) { _UserData = data; } - - /// Get user data - void *getUserData() { return _UserData; } - - - - - - - /// Get contact distance - double rawDistance(const CTrack *other, NLMISC::CVectorD &distance) const - { - distance = other->_Position - _Position; - distance.z = 0.0; - return distance.norm(); - } - - /// Get contact distance - double contactDistance(const CTrack *other, NLMISC::CVectorD &distance, double &rawdistance) const - { - rawdistance = rawDistance(other, distance); - return contactDistanceWithRawDistance(other, distance, rawdistance); - } - - /// Get contact distance - double contactDistanceWithRawDistance(const CTrack *other, NLMISC::CVectorD &distance, double &rawdistance) const - { - double theta = atan2(distance.y, distance.x); - double theta1 = _Heading - theta; - double theta2 = other->_Heading - theta + 3.1415926535; - - float l1 = _Sheet->Length, - w1 = _Sheet->Width; - float l2 = other->_Sheet->Length, - w2 = other->_Sheet->Width; - - double r1 = 0.5 * sqrt( l1*l1 + (w1*w1-l1*l1)*NLMISC::sqr(sin(theta1)) ); - double r2 = 0.5 * sqrt( l2*l2 + (w2*w2-l2*l2)*NLMISC::sqr(sin(theta2)) ); - - return rawdistance - r1 - r2; - } - - - -protected: - - /// Own Control - void acquireControl(); - - /// Release Control - void releaseControl(); - - /// Acquire vision - void acquireVision(); - - /// Release vision - void releaseVision(); - - /// Create Move primitive - void createMovePrimitive(); - - /// Delete Move primitive - void deleteMovePrimitive(); - - /// Check has position (ask for it if necessary) - bool isValid() - { - if (!hasId()) - return false; - - if (!hasPosition()) - { - if (!hasControlOwned() && !_PositionUpdatesRequested) - requestPositionUpdates(); - return false; - } - return true; - } - - /// Request Id - void requestId(); - - /// Request Position - void requestPositionUpdates(); - -protected: - - - /// @name Track Id - //@{ - - /// Has Id - bool _HasId; - - /// Id Requested - bool _IdRequested; - - /// Entity Id - NLMISC::CEntityId _Id; - - /// Sheet Id - NLMISC::CSheetId _SheetId; - - /// Sheet - const CSheet *_Sheet; - - /// Is static - bool _IsStatic; - - //@} - - - - /// @name Track Position Control - //@{ - - /// Own control - bool _OwnControl; - - /// Has Position - bool _HasPosition; - - /// Id Requested - bool _PositionUpdatesRequested; - - /// Position - NLMISC::CVectorD _Position; - - /// Heading - float _Heading; - - /// Followed track - NLMISC::CSmartPtr _Followed; - - //@} - - - - /// @name Track PACS - //@{ - - /// Move Container - NLPACS::UMoveContainer *_MoveContainer; - - /// Move Primitive - NLPACS::UMovePrimitive *_MovePrimitive; - - //@} - - - - /// @name Misc - //@{ - - /// Force release - bool _ForceRelease; - - /// Vision container - typedef std::map > TVision; - - /// Vision - TVision _Vision; - - /// Receive vision - bool _ReceiveVision; - - /// User data - void *_UserData; - - /// Track state - TTrackState _State; - - /// Last move cycle - uint32 _LastMoveCycle; - - /// Last target distance - double _LastTargetDistance; - - /// Smoothed target distance - double _SmoothedTargetDistanceDelta; - - //@} - -public: - /// @name Target attraction control - //@{ - - /// Required target spacing - static double TargetSpacing; - - /// Target attraction strength - static double TargetAttraction; - - /// Target attraction amplification - static double TargetAmp; - - //@} - - - /// @name Obstacle repulsion control - //@{ - - /// Fast obstacle exclusion distance - static double ObstacleExcludeDistance; - - /// Required obstacle spacing - static double ObstacleSpacing; - - /// Obstacle repulsion strength - static double ObstacleRepulsion; - - /// Obstacle repulsion amplification - static double ObstacleAmp; - - //@} - - - /// @name Track motion control - //@{ - - /// Minimum motion distance - static double MinimumMotion; - - /// Lock distance threshold - static double LockThreshold; - - /// Lose distance threshold - static double LoseThreshold; - - /// Stabilise cycle - static uint32 StabiliseCycle; - - //@} -}; - - -#endif // NL_TRACK_H - -/* End of track.h */ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef NL_TRACK_H +#define NL_TRACK_H + +#include "nel/misc/types_nl.h" +#include "nel/misc/smart_ptr.h" +#include "nel/misc/vector.h" +#include "nel/misc/vectord.h" +#include "nel/misc/entity_id.h" +#include "nel/misc/sheet_id.h" + +#include "nel/pacs/u_move_container.h" +#include "nel/pacs/u_move_primitive.h" + +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" + + +/** + * The base class for moving entity + * \author Benjamin Legros + * \author Nevrax France + * \date 2002 + */ +class CTrackBase +{ +public: + /// State type + enum TTrackState + { + Idle = 0, // not controlled yet + MovingTowardsTarget, // first step of motion, moving towards target + TargetLocked, // close to target, locked + TargetLost, // target moved away, can't reach it any longer + TargetUnreachable // can't reach target, too far or too many obstacles on the way + }; + + /// Get Id + virtual const NLMISC::CEntityId &getId() const = 0; + + /// Get SheetId + virtual const NLMISC::CSheetId &getSheetId() const = 0; + + /// Has Id ? + virtual bool hasId() const = 0; + + /// Get track Position + virtual void getPosition(NLMISC::CVectorD &pos, float &heading) const = 0; + + /// Has Position ? + virtual bool hasPosition() const = 0; + + /// Set user data + virtual void setUserData(void *data) = 0; + + /// Get user data + virtual void *getUserData() = 0; + + /// Get Track state + virtual TTrackState getTrackState() const = 0; +}; + +/** + * A track that represents a moving point + * \author Benjamin Legros + * \author Nevrax France + * \date 2002 + */ +class CTrack : public CTrackBase, public NLMISC::CRefCount +{ +public: + /** + * The sheet type read by Georges + */ + class CSheet + { + public: + CSheet(): WalkSpeed(1.3f), RunSpeed(6.0f), Radius(0.5f), Height(2.0f), Length(1.0), Width(1.0) {} + + /// The Walk speed of the entity + float WalkSpeed; + /// The Run speed of the entity + float RunSpeed; + /// The Pacs radius of the entity + float Radius; + /// The Height radius of the entity + float Height; + /// The Animation length of the entity + float Length; + /// The Width length of the entity + float Width; + + void readGeorges (const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId) + { + // the form was found so read the true values from George + form->getRootNode ().getValueByName (WalkSpeed, "Basics.MovementSpeeds.WalkSpeed"); + form->getRootNode ().getValueByName (RunSpeed, "Basics.MovementSpeeds.RunSpeed"); + form->getRootNode ().getValueByName (Radius, "Collision.CollisionRadius"); + form->getRootNode ().getValueByName (Height, "Collision.Height"); + form->getRootNode ().getValueByName (Width, "Collision.Width"); + form->getRootNode ().getValueByName (Length, "Collision.Length"); + } + + void serial (NLMISC::IStream &s) + { + s.serial (WalkSpeed, RunSpeed); + s.serial (Radius, Height); + s.serial (Length, Width); + } + + static uint getVersion () { return 1; } + + /// The default sheet + static CSheet DefaultSheet; + }; + +public: + + /// Constructor + CTrack() : _OwnControl(NULL), _MoveContainer(NULL), _MovePrimitive(NULL), + _Id(NLMISC::CEntityId::Unknown), _SheetId(NLMISC::CSheetId::Unknown), _Sheet(NULL), _Followed(NULL), + _HasPosition(false), _HasId(false), _IdRequested(false), _PositionUpdatesRequested(false), _IsStatic(false), + _ForceRelease(false), _ReceiveVision(false), _UserData(NULL), _State(Idle), + _SmoothedTargetDistanceDelta(3.0), _LastTargetDistance(-1.0) + + { + } + + /// Destructor + ~CTrack(); + + /// Init track + void setId(const NLMISC::CEntityId &id, const NLMISC::CSheetId &sheet); + + /// Get Id + const NLMISC::CEntityId &getId() const + { + return _Id; + } + + /// Get SheetId + const NLMISC::CSheetId &getSheetId() const + { + return _SheetId; + } + + /// Get SheetId + const CSheet *getSheet() const + { + return _Sheet; + } + + /// Has Id ? + bool hasId() const + { + return _HasId; + } + + + + /// Update track position + void setPosition(const NLMISC::CVectorD &pos, float heading) + { + // don't allow more than one position to be set when control is owned + if (_HasPosition && _OwnControl) + return; + _Position = pos; + _Heading = heading; + _HasPosition = true; + } + + /// Get track Position + void getPosition(NLMISC::CVectorD &pos, float &heading) const + { + if (_HasPosition) + { + pos = _Position; + heading = _Heading; + } + else + { + nlwarning("ReynoldsLib:CTrack:getPosition(): Track %s position not yet set", _Id.toString().c_str()); + } + } + + /// Set Static state + void setStatic(bool isstatic = true) + { + _IsStatic = isstatic; + } + + + + /// Has Control Owned ? + bool hasControlOwned() const + { + return _OwnControl; + } + + /// Has Position ? + bool hasPosition() const + { + return _HasPosition; + } + + /// Invalid position + void invalidPosition() + { + _HasPosition = false; + } + + /// Is static ? + bool isStatic() const + { + return _IsStatic; + } + + + + /// Follow + void follow(CTrack *followed); + + /// Leave + void leave(); + + /// Update + void update(double dt); + + /// Update vision + void updateVision(const std::vector &in, const std::vector &out); + + /// Update vision + void updateVision(const std::vector &vision); + + /// Force release + void forceRelease() { _ForceRelease = true; } + + + + /// Get current state + TTrackState getTrackState() const { return _State; } + + + + + /// Set user data + void setUserData(void *data) { _UserData = data; } + + /// Get user data + void *getUserData() { return _UserData; } + + + + + + + /// Get contact distance + double rawDistance(const CTrack *other, NLMISC::CVectorD &distance) const + { + distance = other->_Position - _Position; + distance.z = 0.0; + return distance.norm(); + } + + /// Get contact distance + double contactDistance(const CTrack *other, NLMISC::CVectorD &distance, double &rawdistance) const + { + rawdistance = rawDistance(other, distance); + return contactDistanceWithRawDistance(other, distance, rawdistance); + } + + /// Get contact distance + double contactDistanceWithRawDistance(const CTrack *other, NLMISC::CVectorD &distance, double &rawdistance) const + { + double theta = atan2(distance.y, distance.x); + double theta1 = _Heading - theta; + double theta2 = other->_Heading - theta + 3.1415926535; + + float l1 = _Sheet->Length, + w1 = _Sheet->Width; + float l2 = other->_Sheet->Length, + w2 = other->_Sheet->Width; + + double r1 = 0.5 * sqrt( l1*l1 + (w1*w1-l1*l1)*NLMISC::sqr(sin(theta1)) ); + double r2 = 0.5 * sqrt( l2*l2 + (w2*w2-l2*l2)*NLMISC::sqr(sin(theta2)) ); + + return rawdistance - r1 - r2; + } + + + +protected: + + /// Own Control + void acquireControl(); + + /// Release Control + void releaseControl(); + + /// Acquire vision + void acquireVision(); + + /// Release vision + void releaseVision(); + + /// Create Move primitive + void createMovePrimitive(); + + /// Delete Move primitive + void deleteMovePrimitive(); + + /// Check has position (ask for it if necessary) + bool isValid() + { + if (!hasId()) + return false; + + if (!hasPosition()) + { + if (!hasControlOwned() && !_PositionUpdatesRequested) + requestPositionUpdates(); + return false; + } + return true; + } + + /// Request Id + void requestId(); + + /// Request Position + void requestPositionUpdates(); + +protected: + + + /// @name Track Id + //@{ + + /// Has Id + bool _HasId; + + /// Id Requested + bool _IdRequested; + + /// Entity Id + NLMISC::CEntityId _Id; + + /// Sheet Id + NLMISC::CSheetId _SheetId; + + /// Sheet + const CSheet *_Sheet; + + /// Is static + bool _IsStatic; + + //@} + + + + /// @name Track Position Control + //@{ + + /// Own control + bool _OwnControl; + + /// Has Position + bool _HasPosition; + + /// Id Requested + bool _PositionUpdatesRequested; + + /// Position + NLMISC::CVectorD _Position; + + /// Heading + float _Heading; + + /// Followed track + NLMISC::CSmartPtr _Followed; + + //@} + + + + /// @name Track PACS + //@{ + + /// Move Container + NLPACS::UMoveContainer *_MoveContainer; + + /// Move Primitive + NLPACS::UMovePrimitive *_MovePrimitive; + + //@} + + + + /// @name Misc + //@{ + + /// Force release + bool _ForceRelease; + + /// Vision container + typedef std::map > TVision; + + /// Vision + TVision _Vision; + + /// Receive vision + bool _ReceiveVision; + + /// User data + void *_UserData; + + /// Track state + TTrackState _State; + + /// Last move cycle + uint32 _LastMoveCycle; + + /// Last target distance + double _LastTargetDistance; + + /// Smoothed target distance + double _SmoothedTargetDistanceDelta; + + //@} + +public: + /// @name Target attraction control + //@{ + + /// Required target spacing + static double TargetSpacing; + + /// Target attraction strength + static double TargetAttraction; + + /// Target attraction amplification + static double TargetAmp; + + //@} + + + /// @name Obstacle repulsion control + //@{ + + /// Fast obstacle exclusion distance + static double ObstacleExcludeDistance; + + /// Required obstacle spacing + static double ObstacleSpacing; + + /// Obstacle repulsion strength + static double ObstacleRepulsion; + + /// Obstacle repulsion amplification + static double ObstacleAmp; + + //@} + + + /// @name Track motion control + //@{ + + /// Minimum motion distance + static double MinimumMotion; + + /// Lock distance threshold + static double LockThreshold; + + /// Lose distance threshold + static double LoseThreshold; + + /// Stabilise cycle + static uint32 StabiliseCycle; + + //@} +}; + + +#endif // NL_TRACK_H + +/* End of track.h */ diff --git a/code/ryzom/tools/server/admin/docs/shard_restart/Hd36.xml b/code/ryzom/tools/server/admin/docs/shard_restart/Hd36.xml index 07626db3b..b313e1bc3 100644 --- a/code/ryzom/tools/server/admin/docs/shard_restart/Hd36.xml +++ b/code/ryzom/tools/server/admin/docs/shard_restart/Hd36.xml @@ -1,819 +1,819 @@ - - - Drawing1 - - - - - - - 1. Login to the Ryzom Admin tool. - - 3.346456692913386 - 11.318897637795276 - - - - Click the 'Main' button at the top right of the screen to get a view something like this: - - 3.346456692913386 - 10.925196850393698 - - - - - 3.444881889763779 - 8.471653543307085 - - - - - - - - 2. Select the shard that you want to restart - - 3.346456692913386 - 11.318897637795274 - - - - - 3.343110236220473 - 8.865354330708659 - - - - - 0.590551181102362 - 9.566929133858269 - - - - - 3.809004357293814 - 9.571398391822701 - - - - - - - - 3. Click the 'lock shard' button to take control of the shard that you've selected - - - - 4.227356009930337 - 11.111767279090113 - - - - - 3.343110236220473 - 8.865354330708659 - - - - The pink 'restart sequence' button will appear - - 3.354717958339129 - 6.200787401574803 - - - - - 3.349803149606298 - 3.747244094488188 - - - - - 1.722440944881890 - 9.999999999999998 - - - - - 4.330657900600900 - 10.004469257964431 - - - - - 2.283464566929134 - 4.881889763779529 - - - - - 4.645618530522161 - 4.886359021743961 - - - - - - - - 4. Click on the 'restart sequence' button - - 3.346456692913385 - 11.515748031496063 - - - - - 3.343110236220473 - 9.055118110236219 - - - - You will be prompted to continue: - - 3.346456692913386 - 6.387357830271215 - - - - - 2.449803149606299 - 5.487795275590552 - - - - The restart sequence interface will appear below the shard services. It should have the following appearance: - - 5.216535433070866 - 4.429133858267717 - - - - - 3.349803149606297 - 1.961417322834646 - - - - - 2.283464566929134 - 10.196850393700787 - - - - - 4.645618530522159 - 10.201319651665219 - - - - - 3.661417322834646 - 0.866141732283465 - - - - - 6.545224829734759 - 0.791870832767583 - - - - - - - - 5. Click on the 'Stop the Shard' button - - - 3.346456692913385 - 11.391951006124234 - - - - - 3.343110236220473 - 9.055118110236219 - - - - You will be prompted to continue - - 3.344887613645888 - 6.397637795275591 - - - - - 1.950590551181103 - 5.487795275590552 - - - - WARNING: Pressing this button has a direct effect on the game. Don't press this button unless you are sure of what you're doing. - - 3.346456692913385 - 4.330708661417323 - - - - - 3.011811023622047 - 8.759842519685039 - - - - - 5.492075223435546 - 8.764311777649471 - - - - Pressing OK here will broadcast a message to all players who are logged in telling them that shard will be shut down and will prevent new players from logging in. - - 3.838582677165354 - 3.740157480314961 - - - - - 6.215551181102361 - 8.671259842519685 - - - - - 6.539640283161631 - 8.517154135620743 - - - - Clicking the ‘Cancel’ Button will close the ‘Restart Interface’ without any effect on the shard - - 8.169291338582674 - 8.169291338582676 - - - - - - - - During this time messages are broadcast to the players warning them that the game shard is going to be stopped and that they should log out - - 6.200787401574803 - 11.122047244094491 - - - - This sequence starts automatically when the 'Step 1' timer reaches zero. -During this time persistent data is saved and the game services shut down cleanly - - 5.413385826771653 - 7.677165354330715 - - - - When the 'Step 2' timer reaches zero, the 'Running State' column should read 'stopped' for all services. - - 4.291338582677165 - 4.232283464566931 - - - - - 3.346456692913385 - 8.654330708661423 - - - - - 3.021653543307086 - 9.874803149606306 - - - - - 3.444881889763779 - 5.121456692913391 - - - - - 3.441535433070867 - 1.835236220472441 - - - - 6. Wait for the shutdown sequence to begin - - 4.133858267716535 - 11.515748031496065 - - - - 7. Wait for the shutdown sequence to go through. - - 6.003937007874015 - 8.169291338582683 - - - - If this is not the case then the developers should be contacted and you should click the ‘Give Up, Shard cannot be started’ button. - - 5.452755905511811 - -0.688976377952756 - - - - - 3.349803149606298 - -2.319291338582677 - - - - - 5.841535433070866 - -2.834645669291338 - - - - - 6.559988609262317 - -2.830176411326904 - - - - - 6.235236220472441 - 9.881889763779526 - - - - - 6.539640283161631 - 9.716890432038076 - - - - - 5.511760262805623 - 9.879272407570738 - - - - Clicking the ‘Cancel’ Button will abort the shutdown sequence and allow players to login to the shard - - 8.169291338582676 - 9.350393700787400 - - - - - - - - 8. Start the start sequence by pressing the '1/4 - Start Low Level' button. - - 4.232283464566929 - 11.278433945756781 - - - - The services will start launching - - 4.232283464566929 - 7.972440944881889 - - - - - 3.349803149606299 - 9.688582677165352 - - - - 9. Click on the shard name every few seconds or so to update the view until the 'ts', 'ms' and 'rns' services are all running. - - 7.244094488188976 - 2.854330708661416 - - - - - 3.343110236220473 - 5.518897637795275 - - - - - 2.175196850393701 - 9.389763779527558 - - - - - 4.684988609262318 - 9.394233037491990 - - - - - 1.279527559055118 - 4.694881889763780 - - - - - 4.104279947844995 - 4.886359021743958 - - - - - 1.269685039370079 - 3.799212598425196 - - - - - 4.104279947844995 - 3.803681856389628 - - - - - 1.269685039370079 - 4.330708661417321 - - - - - 4.104279947844995 - 4.335177919381754 - - - - The 'running state' and 'state' columns for these services should both read 'online' and the 'Report' column should read '01s' -This step should only take a few seconds - - 6.240157480314960 - 2.362204724409448 - - - - If the states don't update correctly then the developers should be contacted and you should click the ‘Give Up, Shard cannot be started’ button. - - 6.240157480314960 - 1.870078740157480 - - - - - 3.349803149606299 - 0.239763779527558 - - - - - 5.841535433070867 - -0.275590551181102 - - - - - 6.559988609262317 - -0.271121293216669 - - - - - - - - 10. Click on the '2/4 - Start Mid Level' button to continue the start sequence - - 4.133858267716535 - 11.278433945756781 - - - - - 3.349803149606299 - 9.688582677165353 - - - - The main game services will be started... they will take a minute or two to initialise so patience is required. - - 5.708661417322834 - 8.169291338582678 - - - - 11. Click on the shard name every few seconds or so to update the view until the 'egs', 'ios' and 'gpms' services are all running. - - 7.677165354330708 - 7.578740157480314 - - - - - 2.155511811023622 - 9.251968503937007 - - - - - 4.675146089577279 - 9.256437761901440 - - - - The 'running state' and 'state' columns for these services should both read 'online' and the 'Report' column should read '01s' -This step will generally take one or two minutes but may be a little longer. It should not exceed 5 minutes. - - 7.775590551181102 - 7.086614173228346 - - - - - 3.444881889763779 - 4.520472440944881 - - - - If the states don't update correctly then the developers should be contacted and you should click the ‘Give Up, Shard cannot be started’ button. - - 6.240157480314961 - 2.066929133858268 - - - - - 3.448228346456693 - 0.436614173228346 - - - - - - - - 12. Click on the '3/4 - Start High Level' button to continue the start sequence - - 4.822834645669291 - 11.318897637795274 - - - - - 3.343110236220473 - 9.688582677165353 - - - - The AI services will be started... they will take a minute or so to initialise - - 4.960629921259843 - 7.972440944881889 - - - - 13. Click on the shard name every few seconds or so to update the view until the 'ais' services are all running. - - 6.062992125984252 - 2.854330708661417 - - - - - 3.343110236220472 - 5.518897637795275 - - - - - 2.155511811023622 - 9.114173228346456 - - - - - 4.675146089577279 - 9.118642486310888 - - - - - 1.427165354330709 - 6.131889763779526 - - - - - 4.281158906272716 - 6.110971265772092 - - - - The 'running state' and 'state' columns for these services should both read 'online' and the 'Report' column should read '01s' -This step should take roughly one minute. - - 6.496062992125983 - 2.362204724409448 - - - - If the states don't update correctly then the developers should be contacted and you should click the ‘Give Up, Shard cannot be started’ button. - - 6.240157480314960 - 1.870078740157481 - - - - - 3.448228346456692 - 0.239763779527558 - - - - - - - - 14. Click on the '4/4 - Start Top Level' button to continue the start sequence - - 5.669291338582677 - 11.318897637795276 - - - - - 3.343110236220473 - 9.688582677165353 - - - - The Front end communication services will be started - - 4.232283464566929 - 7.972440944881889 - - - - 15. Click on the shard name every few seconds or so to update the view until ALL services are running. - - 6.099628492123085 - 7.381889763779527 - - - - - 2.145669291338582 - 8.956692913385828 - - - - - 4.675146089577279 - 8.961162171350260 - - - - The 'running state' and 'state' columns for ALL services should both read 'online' and the 'Report' column should read '01s' -NOTE: The RWS service state will read ‘open’ when the other services read ‘online’. -This step should only take a few seconds. - - 5.416119539372975 - 6.786526684164478 - - - - If the states don't update correctly then the developers should be contacted and you should click the ‘Give Up, Shard cannot be started’ button. - - 6.240157480314961 - 1.476377952755906 - - - - - 3.448228346456693 - -0.153937007874017 - - - - - 3.444881889763779 - 4.047047244094488 - - - - - - - - 16. Click on the 'Hand Over to Customer Support' button to finish the start sequence - - 4.566929133858268 - 11.318897637795276 - - - - - 3.343110236220473 - 9.688582677165353 - - - - The shard is now open in restricted mode - the customer support team can log in and check that everything is ok before the shard opens -The customer support volunteers can now open the shard to the players when they are ready - - 4.035433070866141 - 7.785870516185478 - - - - 17. Click on the 'Done' button to exit the 'restart sequence' interface - - 4.232283464566930 - 6.988188976377953 - - - - - 3.349803149606299 - 4.591141732283464 - - - - - 2.942913385826772 - 8.818897637795274 - - - - - 5.472390184065468 - 8.823366895759707 - - - - - 6.240157480314961 - 3.011811023622048 - - - - - 6.564909869104838 - 3.016280281586480 - - - - - - - - 18. Click on the 'Unlock Shard' button to finish - - 3.346456692913386 - 11.278433945756781 - - - - - 3.349803149606299 - 8.921850393700787 - - - - You should be back to a view that looks something like this: - - 3.346456692913386 - 6.397637795275590 - - - - - 3.349803149606299 - 4.000590551181102 - - - - - 1.771653543307087 - 10.019685039370080 - - - - - 4.379870499026097 - 10.004469257964434 - - - - - - + + + Drawing1 + + + + + + + 1. Login to the Ryzom Admin tool. + + 3.346456692913386 + 11.318897637795276 + + + + Click the 'Main' button at the top right of the screen to get a view something like this: + + 3.346456692913386 + 10.925196850393698 + + + + + 3.444881889763779 + 8.471653543307085 + + + + + + + + 2. Select the shard that you want to restart + + 3.346456692913386 + 11.318897637795274 + + + + + 3.343110236220473 + 8.865354330708659 + + + + + 0.590551181102362 + 9.566929133858269 + + + + + 3.809004357293814 + 9.571398391822701 + + + + + + + + 3. Click the 'lock shard' button to take control of the shard that you've selected + + + + 4.227356009930337 + 11.111767279090113 + + + + + 3.343110236220473 + 8.865354330708659 + + + + The pink 'restart sequence' button will appear + + 3.354717958339129 + 6.200787401574803 + + + + + 3.349803149606298 + 3.747244094488188 + + + + + 1.722440944881890 + 9.999999999999998 + + + + + 4.330657900600900 + 10.004469257964431 + + + + + 2.283464566929134 + 4.881889763779529 + + + + + 4.645618530522161 + 4.886359021743961 + + + + + + + + 4. Click on the 'restart sequence' button + + 3.346456692913385 + 11.515748031496063 + + + + + 3.343110236220473 + 9.055118110236219 + + + + You will be prompted to continue: + + 3.346456692913386 + 6.387357830271215 + + + + + 2.449803149606299 + 5.487795275590552 + + + + The restart sequence interface will appear below the shard services. It should have the following appearance: + + 5.216535433070866 + 4.429133858267717 + + + + + 3.349803149606297 + 1.961417322834646 + + + + + 2.283464566929134 + 10.196850393700787 + + + + + 4.645618530522159 + 10.201319651665219 + + + + + 3.661417322834646 + 0.866141732283465 + + + + + 6.545224829734759 + 0.791870832767583 + + + + + + + + 5. Click on the 'Stop the Shard' button + + + 3.346456692913385 + 11.391951006124234 + + + + + 3.343110236220473 + 9.055118110236219 + + + + You will be prompted to continue + + 3.344887613645888 + 6.397637795275591 + + + + + 1.950590551181103 + 5.487795275590552 + + + + WARNING: Pressing this button has a direct effect on the game. Don't press this button unless you are sure of what you're doing. + + 3.346456692913385 + 4.330708661417323 + + + + + 3.011811023622047 + 8.759842519685039 + + + + + 5.492075223435546 + 8.764311777649471 + + + + Pressing OK here will broadcast a message to all players who are logged in telling them that shard will be shut down and will prevent new players from logging in. + + 3.838582677165354 + 3.740157480314961 + + + + + 6.215551181102361 + 8.671259842519685 + + + + + 6.539640283161631 + 8.517154135620743 + + + + Clicking the ‘Cancel’ Button will close the ‘Restart Interface’ without any effect on the shard + + 8.169291338582674 + 8.169291338582676 + + + + + + + + During this time messages are broadcast to the players warning them that the game shard is going to be stopped and that they should log out + + 6.200787401574803 + 11.122047244094491 + + + + This sequence starts automatically when the 'Step 1' timer reaches zero. +During this time persistent data is saved and the game services shut down cleanly + + 5.413385826771653 + 7.677165354330715 + + + + When the 'Step 2' timer reaches zero, the 'Running State' column should read 'stopped' for all services. + + 4.291338582677165 + 4.232283464566931 + + + + + 3.346456692913385 + 8.654330708661423 + + + + + 3.021653543307086 + 9.874803149606306 + + + + + 3.444881889763779 + 5.121456692913391 + + + + + 3.441535433070867 + 1.835236220472441 + + + + 6. Wait for the shutdown sequence to begin + + 4.133858267716535 + 11.515748031496065 + + + + 7. Wait for the shutdown sequence to go through. + + 6.003937007874015 + 8.169291338582683 + + + + If this is not the case then the developers should be contacted and you should click the ‘Give Up, Shard cannot be started’ button. + + 5.452755905511811 + -0.688976377952756 + + + + + 3.349803149606298 + -2.319291338582677 + + + + + 5.841535433070866 + -2.834645669291338 + + + + + 6.559988609262317 + -2.830176411326904 + + + + + 6.235236220472441 + 9.881889763779526 + + + + + 6.539640283161631 + 9.716890432038076 + + + + + 5.511760262805623 + 9.879272407570738 + + + + Clicking the ‘Cancel’ Button will abort the shutdown sequence and allow players to login to the shard + + 8.169291338582676 + 9.350393700787400 + + + + + + + + 8. Start the start sequence by pressing the '1/4 - Start Low Level' button. + + 4.232283464566929 + 11.278433945756781 + + + + The services will start launching + + 4.232283464566929 + 7.972440944881889 + + + + + 3.349803149606299 + 9.688582677165352 + + + + 9. Click on the shard name every few seconds or so to update the view until the 'ts', 'ms' and 'rns' services are all running. + + 7.244094488188976 + 2.854330708661416 + + + + + 3.343110236220473 + 5.518897637795275 + + + + + 2.175196850393701 + 9.389763779527558 + + + + + 4.684988609262318 + 9.394233037491990 + + + + + 1.279527559055118 + 4.694881889763780 + + + + + 4.104279947844995 + 4.886359021743958 + + + + + 1.269685039370079 + 3.799212598425196 + + + + + 4.104279947844995 + 3.803681856389628 + + + + + 1.269685039370079 + 4.330708661417321 + + + + + 4.104279947844995 + 4.335177919381754 + + + + The 'running state' and 'state' columns for these services should both read 'online' and the 'Report' column should read '01s' +This step should only take a few seconds + + 6.240157480314960 + 2.362204724409448 + + + + If the states don't update correctly then the developers should be contacted and you should click the ‘Give Up, Shard cannot be started’ button. + + 6.240157480314960 + 1.870078740157480 + + + + + 3.349803149606299 + 0.239763779527558 + + + + + 5.841535433070867 + -0.275590551181102 + + + + + 6.559988609262317 + -0.271121293216669 + + + + + + + + 10. Click on the '2/4 - Start Mid Level' button to continue the start sequence + + 4.133858267716535 + 11.278433945756781 + + + + + 3.349803149606299 + 9.688582677165353 + + + + The main game services will be started... they will take a minute or two to initialise so patience is required. + + 5.708661417322834 + 8.169291338582678 + + + + 11. Click on the shard name every few seconds or so to update the view until the 'egs', 'ios' and 'gpms' services are all running. + + 7.677165354330708 + 7.578740157480314 + + + + + 2.155511811023622 + 9.251968503937007 + + + + + 4.675146089577279 + 9.256437761901440 + + + + The 'running state' and 'state' columns for these services should both read 'online' and the 'Report' column should read '01s' +This step will generally take one or two minutes but may be a little longer. It should not exceed 5 minutes. + + 7.775590551181102 + 7.086614173228346 + + + + + 3.444881889763779 + 4.520472440944881 + + + + If the states don't update correctly then the developers should be contacted and you should click the ‘Give Up, Shard cannot be started’ button. + + 6.240157480314961 + 2.066929133858268 + + + + + 3.448228346456693 + 0.436614173228346 + + + + + + + + 12. Click on the '3/4 - Start High Level' button to continue the start sequence + + 4.822834645669291 + 11.318897637795274 + + + + + 3.343110236220473 + 9.688582677165353 + + + + The AI services will be started... they will take a minute or so to initialise + + 4.960629921259843 + 7.972440944881889 + + + + 13. Click on the shard name every few seconds or so to update the view until the 'ais' services are all running. + + 6.062992125984252 + 2.854330708661417 + + + + + 3.343110236220472 + 5.518897637795275 + + + + + 2.155511811023622 + 9.114173228346456 + + + + + 4.675146089577279 + 9.118642486310888 + + + + + 1.427165354330709 + 6.131889763779526 + + + + + 4.281158906272716 + 6.110971265772092 + + + + The 'running state' and 'state' columns for these services should both read 'online' and the 'Report' column should read '01s' +This step should take roughly one minute. + + 6.496062992125983 + 2.362204724409448 + + + + If the states don't update correctly then the developers should be contacted and you should click the ‘Give Up, Shard cannot be started’ button. + + 6.240157480314960 + 1.870078740157481 + + + + + 3.448228346456692 + 0.239763779527558 + + + + + + + + 14. Click on the '4/4 - Start Top Level' button to continue the start sequence + + 5.669291338582677 + 11.318897637795276 + + + + + 3.343110236220473 + 9.688582677165353 + + + + The Front end communication services will be started + + 4.232283464566929 + 7.972440944881889 + + + + 15. Click on the shard name every few seconds or so to update the view until ALL services are running. + + 6.099628492123085 + 7.381889763779527 + + + + + 2.145669291338582 + 8.956692913385828 + + + + + 4.675146089577279 + 8.961162171350260 + + + + The 'running state' and 'state' columns for ALL services should both read 'online' and the 'Report' column should read '01s' +NOTE: The RWS service state will read ‘open’ when the other services read ‘online’. +This step should only take a few seconds. + + 5.416119539372975 + 6.786526684164478 + + + + If the states don't update correctly then the developers should be contacted and you should click the ‘Give Up, Shard cannot be started’ button. + + 6.240157480314961 + 1.476377952755906 + + + + + 3.448228346456693 + -0.153937007874017 + + + + + 3.444881889763779 + 4.047047244094488 + + + + + + + + 16. Click on the 'Hand Over to Customer Support' button to finish the start sequence + + 4.566929133858268 + 11.318897637795276 + + + + + 3.343110236220473 + 9.688582677165353 + + + + The shard is now open in restricted mode - the customer support team can log in and check that everything is ok before the shard opens +The customer support volunteers can now open the shard to the players when they are ready + + 4.035433070866141 + 7.785870516185478 + + + + 17. Click on the 'Done' button to exit the 'restart sequence' interface + + 4.232283464566930 + 6.988188976377953 + + + + + 3.349803149606299 + 4.591141732283464 + + + + + 2.942913385826772 + 8.818897637795274 + + + + + 5.472390184065468 + 8.823366895759707 + + + + + 6.240157480314961 + 3.011811023622048 + + + + + 6.564909869104838 + 3.016280281586480 + + + + + + + + 18. Click on the 'Unlock Shard' button to finish + + 3.346456692913386 + 11.278433945756781 + + + + + 3.349803149606299 + 8.921850393700787 + + + + You should be back to a view that looks something like this: + + 3.346456692913386 + 6.397637795275590 + + + + + 3.349803149606299 + 4.000590551181102 + + + + + 1.771653543307087 + 10.019685039370080 + + + + + 4.379870499026097 + 10.004469257964434 + + + + + + diff --git a/code/ryzom/tools/server/ai_build_wmap/build_proximity_maps.cpp b/code/ryzom/tools/server/ai_build_wmap/build_proximity_maps.cpp index 74a92024f..5cb7c6922 100644 --- a/code/ryzom/tools/server/ai_build_wmap/build_proximity_maps.cpp +++ b/code/ryzom/tools/server/ai_build_wmap/build_proximity_maps.cpp @@ -1,724 +1,724 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -//------------------------------------------------------------------------------------------------- -// includes -//------------------------------------------------------------------------------------------------- - -// Nel misc -#include "nel/misc/types_nl.h" -#include "nel/misc/command.h" -#include "nel/misc/path.h" -#include "nel/misc/sstring.h" -#include "nel/misc/file.h" - -// Game share -#include "server_share/bmp4image.h" - -// AI share -#include "ai_share/world_map.h" - - -//------------------------------------------------------------------------------------------------- -// using namespaces... -//------------------------------------------------------------------------------------------------- - -using namespace std; -using namespace NLMISC; -using namespace RYAI_MAP_CRUNCH; - - -//------------------------------------------------------------------------------------------------- -// External variables... -//------------------------------------------------------------------------------------------------- - -extern string OutputPath; - - -//------------------------------------------------------------------------------------------------- -// Local type definitions -//------------------------------------------------------------------------------------------------- - -typedef uint16 TBufferEntry; -typedef std::vector TBuffer; -typedef std::vector TOffsetsVector; - - -//------------------------------------------------------------------------------------------------- -// class CProximityZone -//------------------------------------------------------------------------------------------------- - -class CProximityZone -{ -public: - typedef std::vector TOffsets; - - // ctor - // scanWidth and scanHeight define the dimentions of the buffer that this zone is being extracted from - // xOffset and yOffset are for re-mapping coordinates from buffer-relative to absolute ryzom world coordinates - CProximityZone(uint32 scanWidth=0,uint32 scanHeight=0,sint32 xOffset=0, sint32 yOffset=0); - - // add an 'accessible position' to a zone (offset is y*scanWidth+x) - bool add(uint32 offset); - - // zone dimention accessors (note that zone dimentions line up with 160x160 world zones) - // note that this means that the zone bounds may extend outside the scan area - uint32 getZoneWidth() const; - uint32 getZoneHeight() const; - sint32 getZoneXMin() const; - sint32 getZoneYMin() const; - uint32 getZoneXMax() const; - uint32 getZoneYMax() const; - - // read accessors for the ryzom world coordinate offsets - sint32 getXOffset() const; - sint32 getYOffset() const; - - // read accessors for the bounding limits that define the area occupied by the accessible points - uint32 getBoundXMin() const; - uint32 getBoundYMin() const; - uint32 getBoundXMax() const; - uint32 getBoundYMax() const; - - // read accessor for the _Offsets vector - // this is a vector of offsets into the scan area. It needs to be remapped to zone offsets - // via the remapOffset() routine in order to be used to index into a zone buffer - const TOffsets& getOffsets() const; - - // remap a scan buffer offset to a zone offset by decomposing into x and y parts and - // subtracting getZoneXMin() and getZoneYMin() - uint32 remapOffset(uint32 bufferOffset) const; - -private: - // parameters setup at construction time, giving info on the context that we're in - uint32 _ScanWidth; - uint32 _ScanHeight; - sint32 _XOffset; - sint32 _YOffset; - uint32 _MaxOffset; - - // the vector of points that are part of this zone - TOffsets _Offsets; - - // the min and max coords of the points that are part of this zone - uint32 _XMax; - uint32 _XMin; - uint32 _YMax; - uint32 _YMin; -}; - - -//------------------------------------------------------------------------------------------------- -// class CProximityMapBuffer -//------------------------------------------------------------------------------------------------- - -class CProximityMapBuffer -{ -public: - typedef std::vector TZones; - - // load a cwmap2 file and setup this object from its contents - // the 'name' parameter is the full file name of the file to load with path and extension - void load(const std::string& name); - - // scan the buffer to generate the set of non-connecting zones that it contains - void calculateZones(TZones& zones); - - // generate the proximity map for a given zone - void generateZoneProximityMap(const CProximityZone& zone,TBuffer& zoneBuffer); - - // read accessors... - const TBuffer& getBuffer() const; - uint32 getScanHeight() const; - uint32 getScanWidth() const; - -private: - // private routine used by generateZoneProximityMap() to setup the zoneBuffer with the accessible points set - void _prepareBufferForZoneProximityMap(const CProximityZone& zone,TBuffer& zoneBuffer,TOffsetsVector& accessiblePoints); - -private: - // the width and heilght of the scan zone (ie the dimentions of the buffer) - uint32 _ScanWidth; - uint32 _ScanHeight; - - // vector representing 2d array of points [_ScanHeight][_ScanWidth] - TBuffer _Buffer; - - // buffer coordinate to world coordinate offsets... - sint32 _XOffset; - sint32 _YOffset; -}; - - -//------------------------------------------------------------------------------------------------- -// Handy utility routines -//------------------------------------------------------------------------------------------------- - -static void writeProximityBufferToTgaFile(const std::string& fileName,const TBuffer& buffer,uint32 scanWidth,uint32 scanHeight) -{ - uint imageWidth = (scanWidth+15)&~15; - uint imageHeight = (scanHeight); - - CTGAImageGrey tgaImage; - tgaImage.setup((uint16)imageWidth, (uint16)imageHeight, fileName, 0, 0); - for (uint32 y=0;y255*5)?255:value/5); - } - tgaImage.writeLine(); - } -} - -static void processProximityBuffer(const TBuffer& inputBuffer, uint32 lineLength, TBuffer& resultBuffer) -{ - // a couple of constants to control the range over which our degressive filter is to be applied - const uint32 smallValue= 2*5; - const uint32 bigValue= 15*5; - - // determine numer of lines in the buffer... - uint32 numLines= (uint32)inputBuffer.size()/ lineLength; - - // clear out the result buffer and reset all values to 5*255, remembering that this is the correct value for the image edges - resultBuffer.clear(); - resultBuffer.resize(inputBuffer.size(),(TBufferEntry)5*255); - - for (uint32 y=1;ybigValue) value=5*255; - else value= (uint32)(((1.0-cos(3.14159265359*(float(value-smallValue)/(float)(bigValue-smallValue))))/2.0)*float(5*255)); - - // store the value into the result buffer - resultBuffer[offset]= (TBufferEntry)value; - } - } -} - - -//------------------------------------------------------------------------------------------------- -// methods CProximityZone -//------------------------------------------------------------------------------------------------- - -CProximityZone::CProximityZone(uint32 scanWidth,uint32 scanHeight,sint32 xOffset, sint32 yOffset) -{ - _ScanWidth = scanWidth; - _ScanHeight = scanHeight; - _XOffset = xOffset; - _YOffset = yOffset; - - _MaxOffset = scanWidth * scanHeight -1; - - _XMin = ~0u; - _YMin = ~0u; - _XMax = 0; - _YMax = 0; -} - -bool CProximityZone::add(uint32 offset) -{ - // make sure the requested point is in the zone - if (offset>_MaxOffset) - return false; - - // calculate the x and y coordinates of the point - uint32 y= offset/ _ScanWidth; - uint32 x= offset% _ScanWidth; - - // update the bounding coordinates for this zone - if (x<_XMin) _XMin= x; - if (x>_XMax) _XMax= x; - if (y<_YMin) _YMin= y; - if (y>_YMax) _YMax= y; - - // add the point to the vector of points - _Offsets.push_back(offset); - return true; -} - -const CProximityZone::TOffsets& CProximityZone::getOffsets() const -{ - return _Offsets; -} - -uint32 CProximityZone::getZoneWidth() const -{ - return getZoneXMax()- getZoneXMin() +1; -} - -uint32 CProximityZone::getZoneHeight() const -{ - return getZoneYMax()- getZoneYMin() +1; -} - -sint32 CProximityZone::getZoneXMin() const -{ - return (_XMin+_XOffset)/160*160-_XOffset; -} - -sint32 CProximityZone::getZoneYMin() const -{ - return (_YMin+_YOffset)/160*160-_YOffset; -} - -uint32 CProximityZone::getZoneXMax() const -{ - return (((_XMax+_XOffset)/160+1)*160)-_XOffset-1; -} - -uint32 CProximityZone::getZoneYMax() const -{ - return (((_YMax+_YOffset)/160+1)*160)-_YOffset-1; -} - -sint32 CProximityZone::getXOffset() const -{ - return _XOffset+getZoneXMin(); -} - -sint32 CProximityZone::getYOffset() const -{ - return _YOffset+getZoneYMin(); -} - -uint32 CProximityZone::getBoundXMin() const -{ - return _XMin-getZoneXMin(); -} - -uint32 CProximityZone::getBoundYMin() const -{ - return _YMin-getZoneYMin(); -} - -uint32 CProximityZone::getBoundXMax() const -{ - return _XMax-getZoneXMin(); -} - -uint32 CProximityZone::getBoundYMax() const -{ - return _YMax-getZoneYMin(); -} - -uint32 CProximityZone::remapOffset(uint32 bufferOffset) const -{ - // decompose input coordinates into x and y parts - uint32 bufferX= bufferOffset% _ScanWidth; - uint32 bufferY= bufferOffset/ _ScanWidth; - - // remap the offset from a _Buffer-relative offset to a zone-relative offset - return bufferX-getZoneXMin()+ (bufferY-getZoneYMin())*getZoneWidth(); -} - - -//------------------------------------------------------------------------------------------------- -// methods CProximityMapBuffer -//------------------------------------------------------------------------------------------------- - -void CProximityMapBuffer::load(const std::string& name) -{ - // load the AI collision map file - CWorldMap worldMap; - CIFile f(name); - f.serial(worldMap); - - // lookup the map bounds - CMapPosition min, max; - worldMap.getBounds(min, max); - - // calculate a handful of constants relating to the bounds of the image... - _ScanWidth = max.x()-min.x(); - _ScanHeight = max.y()-min.y(); - _XOffset= min.x(); - _YOffset= max.y(); - - // redimension buffer to correct size - _Buffer.resize(_ScanWidth*_ScanHeight); - - // setup a position variable to mark the start point of each line - CMapPosition scanpos(min.x(),min.y()); - - // iterate over the scan area looking for points that are accessible - for (uint32 y=0; y<_ScanHeight; ++y, scanpos = scanpos.getStepN()) - { - CMapPosition pos(scanpos); - - // scan a line of the map - for (uint32 x=0; x<_ScanWidth; ++x, pos = pos.getStepE()) - { - bool isAccessible= false; - // if the cell pointer is NULL it means that the 16x16 cell in question is inaccessible - if (worldMap.getRootCellCst(pos) != NULL) - { - // run through the surfaces in the cell looking for a match for this position (may be as many as 3 surfaces per cell max) - for (uint32 ns=0; ns<3; ++ns) - { - isAccessible |= worldMap.getSafeWorldPosition(pos, CSlot(ns)).isValid(); - } - } - // setup the next pixel in the output buffers... - _Buffer[y*_ScanWidth+x]= (isAccessible? 0: (TBufferEntry)~0u); - } - } -} - -void CProximityMapBuffer::calculateZones(TZones& zones) -{ - // clear out the result buffer before starting work - zones.clear(); - - // setup a container to hold the accessible points within this buffer - typedef std::set TAccessiblePoints; - TAccessiblePoints accessiblePoints; - - // start by building the set of all accessible points - for (uint32 i=0;i<_Buffer.size();++i) - { - if (_Buffer[i]==0) - accessiblePoints.insert(i); - } - - // while there are still points remaining in the set we must have another zone to process - while (!accessiblePoints.empty()) - { - // append a new zone to the zones vector and get a refference to it - zones.push_back( CProximityZone(_ScanWidth,_ScanHeight,_XOffset,_YOffset) ); - CProximityZone& theZone= zones.back(); - - // setup a todo list representing points that are part of the surface that we are dealing with - // that haven't yet been treated to check for neighbours, etc - std::vector todo; - - // get hold of the first point in the accessilbe points set and push it onto the todo list - todo.push_back(*accessiblePoints.begin()); - accessiblePoints.erase(todo.back()); - - // while we have more points to deal with ... - while (!todo.empty()) - { - // pop the next point off the todo list - uint32 thePoint= todo.back(); - todo.pop_back(); - - // add the point to the zone - theZone.add(thePoint); - - // a little macro for the code to perform for each movement test... - #define TEST_MOVE(xoffs,yoffs)\ - {\ - TAccessiblePoints::iterator it= accessiblePoints.find(thePoint+xoffs+_ScanWidth*yoffs);\ - if (it!=accessiblePoints.end())\ - {\ - todo.push_back(*it);\ - accessiblePoints.erase(it);\ - }\ - } - - // N, S, W, E moves - TEST_MOVE( 0, 1); - TEST_MOVE( 0,-1); - TEST_MOVE( 1, 0); - TEST_MOVE(-1, 0); - - // NW, NE, WS, SE moves - TEST_MOVE( 1, 1); - TEST_MOVE(-1, 1); - TEST_MOVE( 1,-1); - TEST_MOVE(-1,-1); - - #undef TEST_MOVE - } - } - - nlinfo("Found %u zones",zones.size()); -} - -void CProximityMapBuffer::_prepareBufferForZoneProximityMap(const CProximityZone& zone,TBuffer& zoneBuffer,TOffsetsVector& accessiblePoints) -{ - // the length of runs that we consider too short to deal with... - const uint32 shortRunLength=5; - - // redimention and initialise the zone buffer - uint32 zoneWidth= zone.getZoneWidth(); - uint32 zoneHeight= zone.getZoneHeight(); - zoneBuffer.clear(); - zoneBuffer.resize(zoneWidth*zoneHeight,(TBufferEntry)~0u); - - // setup the buffer's accessible points and prime vects[0] with the set of accessible points in the zone buffer - for (uint32 i=0;istartOffset && zoneBuffer[endOffset]!=0; endOffset-= zoneWidth) {} - - for (uint32 offset=startOffset, marker=startOffset;offset<=endOffset;offset+=zoneWidth) - { - // see if this is an accessible position - if (zoneBuffer[offset]==0) - { - // look to see whether this position follows a short run of inaccessible positions - sint32 inaccessibleRunLength= (offset-marker)/zoneWidth-1; - if (inaccessibleRunLength>0 && inaccessibleRunLength<=shortRunLength) - { - // flag all of the points in this run as belonging to a short run in y - for (uint32 j=marker+zoneWidth;jstartOffset && zoneBuffer[endOffset]!=0; --endOffset) {} - - for (uint32 offset=startOffset, marker=startOffset;offset<=endOffset;++offset) - { - // see if this is an accessible position - if (zoneBuffer[offset]==0) - { - // look to see whether this position follows a short run of inaccessible positions - sint32 inaccessibleRunLength= offset-marker-1; - if (inaccessibleRunLength>0 && inaccessibleRunLength<=shortRunLength) - { - // flag all of the points in this run as belonging to a short run in y - for (uint32 j=marker+1;j(newDist))\ - {\ - zoneBuffer[newVal]=(newDist);\ - vects[(newDist)&15].push_back(newVal);\ - ++entriesToTreat;\ - }\ - }\ - } - - // N, S, W, E moves - TEST_MOVE( 0, 1,dist+5); - TEST_MOVE( 0,-1,dist+5); - TEST_MOVE( 1, 0,dist+5); - TEST_MOVE(-1, 0,dist+5); - - // NW, NE, WS, SE moves - TEST_MOVE( 1, 1,dist+7); - TEST_MOVE(-1, 1,dist+7); - TEST_MOVE( 1,-1,dist+7); - TEST_MOVE(-1,-1,dist+7); - - // NNW, NNE, SSW, SSE moves - TEST_MOVE( 1, 2,dist+11); - TEST_MOVE(-1, 2,dist+11); - TEST_MOVE( 1,-2,dist+11); - TEST_MOVE(-1,-2,dist+11); - - // WNW, WSW, ENE, ESE moves - TEST_MOVE( 2, 1,dist+11); - TEST_MOVE(-2, 1,dist+11); - TEST_MOVE( 2,-1,dist+11); - TEST_MOVE(-2,-1,dist+11); - - #undef TEST_MOVE - } - - // clear out the vector - entriesToTreat-= (uint32)vect.size(); - vect.clear(); - } -} - -const TBuffer& CProximityMapBuffer::getBuffer() const -{ - return _Buffer; -} - -uint32 CProximityMapBuffer::getScanHeight() const -{ - return _ScanHeight; -} - -uint32 CProximityMapBuffer::getScanWidth() const -{ - return _ScanWidth; -} - - -//------------------------------------------------------------------------------------------------- -// NLMISC_COMMAND pacsBuildProximityMap -//------------------------------------------------------------------------------------------------- - -NLMISC_COMMAND(pacsBuildProximityMap,"build a set of proximity maps from a cwmap2 file","") -{ - // deal with command arguments - nlinfo("Building proximity map..."); - if(args.size()<1) - return false; - const std::string& name= args[0]; - - // load the collision map file and generate our buffer from it - CProximityMapBuffer buffer; - string ext = CFile::getExtension(name); - if (ext == "") - ext = "cwmap2"; - string fileName= OutputPath+CFile::getFilenameWithoutExtension(name)+"."+ext; - nlinfo("Building proximity map: Loading cwmap2 file: %s",fileName.c_str()); - buffer.load(fileName); - - // generate a tga file from the buffer contents - nlinfo("Building proximity map: Writing accessibilty file: %s",(OutputPath+name+"_accessible.tga").c_str()); - writeProximityBufferToTgaFile(OutputPath+name+"_accessible.tga",buffer.getBuffer(),buffer.getScanWidth(),buffer.getScanHeight()); - - // divide space up into non-connecting zones - nlinfo("Building proximity map: Dividing accessible space into zones"); - CProximityMapBuffer::TZones zones; - buffer.calculateZones(zones); - - // setup a string to contain the proximity zone list (in csv format) - NLMISC::CSString proximityZoneList="idx,x_offset,y_offset,width,height,xmin,ymin,xmax,ymax\n"; - - // generate proximity info for inaccessible points in each zone - for (uint32 i=0;i +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +//------------------------------------------------------------------------------------------------- +// includes +//------------------------------------------------------------------------------------------------- + +// Nel misc +#include "nel/misc/types_nl.h" +#include "nel/misc/command.h" +#include "nel/misc/path.h" +#include "nel/misc/sstring.h" +#include "nel/misc/file.h" + +// Game share +#include "server_share/bmp4image.h" + +// AI share +#include "ai_share/world_map.h" + + +//------------------------------------------------------------------------------------------------- +// using namespaces... +//------------------------------------------------------------------------------------------------- + +using namespace std; +using namespace NLMISC; +using namespace RYAI_MAP_CRUNCH; + + +//------------------------------------------------------------------------------------------------- +// External variables... +//------------------------------------------------------------------------------------------------- + +extern string OutputPath; + + +//------------------------------------------------------------------------------------------------- +// Local type definitions +//------------------------------------------------------------------------------------------------- + +typedef uint16 TBufferEntry; +typedef std::vector TBuffer; +typedef std::vector TOffsetsVector; + + +//------------------------------------------------------------------------------------------------- +// class CProximityZone +//------------------------------------------------------------------------------------------------- + +class CProximityZone +{ +public: + typedef std::vector TOffsets; + + // ctor + // scanWidth and scanHeight define the dimentions of the buffer that this zone is being extracted from + // xOffset and yOffset are for re-mapping coordinates from buffer-relative to absolute ryzom world coordinates + CProximityZone(uint32 scanWidth=0,uint32 scanHeight=0,sint32 xOffset=0, sint32 yOffset=0); + + // add an 'accessible position' to a zone (offset is y*scanWidth+x) + bool add(uint32 offset); + + // zone dimention accessors (note that zone dimentions line up with 160x160 world zones) + // note that this means that the zone bounds may extend outside the scan area + uint32 getZoneWidth() const; + uint32 getZoneHeight() const; + sint32 getZoneXMin() const; + sint32 getZoneYMin() const; + uint32 getZoneXMax() const; + uint32 getZoneYMax() const; + + // read accessors for the ryzom world coordinate offsets + sint32 getXOffset() const; + sint32 getYOffset() const; + + // read accessors for the bounding limits that define the area occupied by the accessible points + uint32 getBoundXMin() const; + uint32 getBoundYMin() const; + uint32 getBoundXMax() const; + uint32 getBoundYMax() const; + + // read accessor for the _Offsets vector + // this is a vector of offsets into the scan area. It needs to be remapped to zone offsets + // via the remapOffset() routine in order to be used to index into a zone buffer + const TOffsets& getOffsets() const; + + // remap a scan buffer offset to a zone offset by decomposing into x and y parts and + // subtracting getZoneXMin() and getZoneYMin() + uint32 remapOffset(uint32 bufferOffset) const; + +private: + // parameters setup at construction time, giving info on the context that we're in + uint32 _ScanWidth; + uint32 _ScanHeight; + sint32 _XOffset; + sint32 _YOffset; + uint32 _MaxOffset; + + // the vector of points that are part of this zone + TOffsets _Offsets; + + // the min and max coords of the points that are part of this zone + uint32 _XMax; + uint32 _XMin; + uint32 _YMax; + uint32 _YMin; +}; + + +//------------------------------------------------------------------------------------------------- +// class CProximityMapBuffer +//------------------------------------------------------------------------------------------------- + +class CProximityMapBuffer +{ +public: + typedef std::vector TZones; + + // load a cwmap2 file and setup this object from its contents + // the 'name' parameter is the full file name of the file to load with path and extension + void load(const std::string& name); + + // scan the buffer to generate the set of non-connecting zones that it contains + void calculateZones(TZones& zones); + + // generate the proximity map for a given zone + void generateZoneProximityMap(const CProximityZone& zone,TBuffer& zoneBuffer); + + // read accessors... + const TBuffer& getBuffer() const; + uint32 getScanHeight() const; + uint32 getScanWidth() const; + +private: + // private routine used by generateZoneProximityMap() to setup the zoneBuffer with the accessible points set + void _prepareBufferForZoneProximityMap(const CProximityZone& zone,TBuffer& zoneBuffer,TOffsetsVector& accessiblePoints); + +private: + // the width and heilght of the scan zone (ie the dimentions of the buffer) + uint32 _ScanWidth; + uint32 _ScanHeight; + + // vector representing 2d array of points [_ScanHeight][_ScanWidth] + TBuffer _Buffer; + + // buffer coordinate to world coordinate offsets... + sint32 _XOffset; + sint32 _YOffset; +}; + + +//------------------------------------------------------------------------------------------------- +// Handy utility routines +//------------------------------------------------------------------------------------------------- + +static void writeProximityBufferToTgaFile(const std::string& fileName,const TBuffer& buffer,uint32 scanWidth,uint32 scanHeight) +{ + uint imageWidth = (scanWidth+15)&~15; + uint imageHeight = (scanHeight); + + CTGAImageGrey tgaImage; + tgaImage.setup((uint16)imageWidth, (uint16)imageHeight, fileName, 0, 0); + for (uint32 y=0;y255*5)?255:value/5); + } + tgaImage.writeLine(); + } +} + +static void processProximityBuffer(const TBuffer& inputBuffer, uint32 lineLength, TBuffer& resultBuffer) +{ + // a couple of constants to control the range over which our degressive filter is to be applied + const uint32 smallValue= 2*5; + const uint32 bigValue= 15*5; + + // determine numer of lines in the buffer... + uint32 numLines= (uint32)inputBuffer.size()/ lineLength; + + // clear out the result buffer and reset all values to 5*255, remembering that this is the correct value for the image edges + resultBuffer.clear(); + resultBuffer.resize(inputBuffer.size(),(TBufferEntry)5*255); + + for (uint32 y=1;ybigValue) value=5*255; + else value= (uint32)(((1.0-cos(3.14159265359*(float(value-smallValue)/(float)(bigValue-smallValue))))/2.0)*float(5*255)); + + // store the value into the result buffer + resultBuffer[offset]= (TBufferEntry)value; + } + } +} + + +//------------------------------------------------------------------------------------------------- +// methods CProximityZone +//------------------------------------------------------------------------------------------------- + +CProximityZone::CProximityZone(uint32 scanWidth,uint32 scanHeight,sint32 xOffset, sint32 yOffset) +{ + _ScanWidth = scanWidth; + _ScanHeight = scanHeight; + _XOffset = xOffset; + _YOffset = yOffset; + + _MaxOffset = scanWidth * scanHeight -1; + + _XMin = ~0u; + _YMin = ~0u; + _XMax = 0; + _YMax = 0; +} + +bool CProximityZone::add(uint32 offset) +{ + // make sure the requested point is in the zone + if (offset>_MaxOffset) + return false; + + // calculate the x and y coordinates of the point + uint32 y= offset/ _ScanWidth; + uint32 x= offset% _ScanWidth; + + // update the bounding coordinates for this zone + if (x<_XMin) _XMin= x; + if (x>_XMax) _XMax= x; + if (y<_YMin) _YMin= y; + if (y>_YMax) _YMax= y; + + // add the point to the vector of points + _Offsets.push_back(offset); + return true; +} + +const CProximityZone::TOffsets& CProximityZone::getOffsets() const +{ + return _Offsets; +} + +uint32 CProximityZone::getZoneWidth() const +{ + return getZoneXMax()- getZoneXMin() +1; +} + +uint32 CProximityZone::getZoneHeight() const +{ + return getZoneYMax()- getZoneYMin() +1; +} + +sint32 CProximityZone::getZoneXMin() const +{ + return (_XMin+_XOffset)/160*160-_XOffset; +} + +sint32 CProximityZone::getZoneYMin() const +{ + return (_YMin+_YOffset)/160*160-_YOffset; +} + +uint32 CProximityZone::getZoneXMax() const +{ + return (((_XMax+_XOffset)/160+1)*160)-_XOffset-1; +} + +uint32 CProximityZone::getZoneYMax() const +{ + return (((_YMax+_YOffset)/160+1)*160)-_YOffset-1; +} + +sint32 CProximityZone::getXOffset() const +{ + return _XOffset+getZoneXMin(); +} + +sint32 CProximityZone::getYOffset() const +{ + return _YOffset+getZoneYMin(); +} + +uint32 CProximityZone::getBoundXMin() const +{ + return _XMin-getZoneXMin(); +} + +uint32 CProximityZone::getBoundYMin() const +{ + return _YMin-getZoneYMin(); +} + +uint32 CProximityZone::getBoundXMax() const +{ + return _XMax-getZoneXMin(); +} + +uint32 CProximityZone::getBoundYMax() const +{ + return _YMax-getZoneYMin(); +} + +uint32 CProximityZone::remapOffset(uint32 bufferOffset) const +{ + // decompose input coordinates into x and y parts + uint32 bufferX= bufferOffset% _ScanWidth; + uint32 bufferY= bufferOffset/ _ScanWidth; + + // remap the offset from a _Buffer-relative offset to a zone-relative offset + return bufferX-getZoneXMin()+ (bufferY-getZoneYMin())*getZoneWidth(); +} + + +//------------------------------------------------------------------------------------------------- +// methods CProximityMapBuffer +//------------------------------------------------------------------------------------------------- + +void CProximityMapBuffer::load(const std::string& name) +{ + // load the AI collision map file + CWorldMap worldMap; + CIFile f(name); + f.serial(worldMap); + + // lookup the map bounds + CMapPosition min, max; + worldMap.getBounds(min, max); + + // calculate a handful of constants relating to the bounds of the image... + _ScanWidth = max.x()-min.x(); + _ScanHeight = max.y()-min.y(); + _XOffset= min.x(); + _YOffset= max.y(); + + // redimension buffer to correct size + _Buffer.resize(_ScanWidth*_ScanHeight); + + // setup a position variable to mark the start point of each line + CMapPosition scanpos(min.x(),min.y()); + + // iterate over the scan area looking for points that are accessible + for (uint32 y=0; y<_ScanHeight; ++y, scanpos = scanpos.getStepN()) + { + CMapPosition pos(scanpos); + + // scan a line of the map + for (uint32 x=0; x<_ScanWidth; ++x, pos = pos.getStepE()) + { + bool isAccessible= false; + // if the cell pointer is NULL it means that the 16x16 cell in question is inaccessible + if (worldMap.getRootCellCst(pos) != NULL) + { + // run through the surfaces in the cell looking for a match for this position (may be as many as 3 surfaces per cell max) + for (uint32 ns=0; ns<3; ++ns) + { + isAccessible |= worldMap.getSafeWorldPosition(pos, CSlot(ns)).isValid(); + } + } + // setup the next pixel in the output buffers... + _Buffer[y*_ScanWidth+x]= (isAccessible? 0: (TBufferEntry)~0u); + } + } +} + +void CProximityMapBuffer::calculateZones(TZones& zones) +{ + // clear out the result buffer before starting work + zones.clear(); + + // setup a container to hold the accessible points within this buffer + typedef std::set TAccessiblePoints; + TAccessiblePoints accessiblePoints; + + // start by building the set of all accessible points + for (uint32 i=0;i<_Buffer.size();++i) + { + if (_Buffer[i]==0) + accessiblePoints.insert(i); + } + + // while there are still points remaining in the set we must have another zone to process + while (!accessiblePoints.empty()) + { + // append a new zone to the zones vector and get a refference to it + zones.push_back( CProximityZone(_ScanWidth,_ScanHeight,_XOffset,_YOffset) ); + CProximityZone& theZone= zones.back(); + + // setup a todo list representing points that are part of the surface that we are dealing with + // that haven't yet been treated to check for neighbours, etc + std::vector todo; + + // get hold of the first point in the accessilbe points set and push it onto the todo list + todo.push_back(*accessiblePoints.begin()); + accessiblePoints.erase(todo.back()); + + // while we have more points to deal with ... + while (!todo.empty()) + { + // pop the next point off the todo list + uint32 thePoint= todo.back(); + todo.pop_back(); + + // add the point to the zone + theZone.add(thePoint); + + // a little macro for the code to perform for each movement test... + #define TEST_MOVE(xoffs,yoffs)\ + {\ + TAccessiblePoints::iterator it= accessiblePoints.find(thePoint+xoffs+_ScanWidth*yoffs);\ + if (it!=accessiblePoints.end())\ + {\ + todo.push_back(*it);\ + accessiblePoints.erase(it);\ + }\ + } + + // N, S, W, E moves + TEST_MOVE( 0, 1); + TEST_MOVE( 0,-1); + TEST_MOVE( 1, 0); + TEST_MOVE(-1, 0); + + // NW, NE, WS, SE moves + TEST_MOVE( 1, 1); + TEST_MOVE(-1, 1); + TEST_MOVE( 1,-1); + TEST_MOVE(-1,-1); + + #undef TEST_MOVE + } + } + + nlinfo("Found %u zones",zones.size()); +} + +void CProximityMapBuffer::_prepareBufferForZoneProximityMap(const CProximityZone& zone,TBuffer& zoneBuffer,TOffsetsVector& accessiblePoints) +{ + // the length of runs that we consider too short to deal with... + const uint32 shortRunLength=5; + + // redimention and initialise the zone buffer + uint32 zoneWidth= zone.getZoneWidth(); + uint32 zoneHeight= zone.getZoneHeight(); + zoneBuffer.clear(); + zoneBuffer.resize(zoneWidth*zoneHeight,(TBufferEntry)~0u); + + // setup the buffer's accessible points and prime vects[0] with the set of accessible points in the zone buffer + for (uint32 i=0;istartOffset && zoneBuffer[endOffset]!=0; endOffset-= zoneWidth) {} + + for (uint32 offset=startOffset, marker=startOffset;offset<=endOffset;offset+=zoneWidth) + { + // see if this is an accessible position + if (zoneBuffer[offset]==0) + { + // look to see whether this position follows a short run of inaccessible positions + sint32 inaccessibleRunLength= (offset-marker)/zoneWidth-1; + if (inaccessibleRunLength>0 && inaccessibleRunLength<=shortRunLength) + { + // flag all of the points in this run as belonging to a short run in y + for (uint32 j=marker+zoneWidth;jstartOffset && zoneBuffer[endOffset]!=0; --endOffset) {} + + for (uint32 offset=startOffset, marker=startOffset;offset<=endOffset;++offset) + { + // see if this is an accessible position + if (zoneBuffer[offset]==0) + { + // look to see whether this position follows a short run of inaccessible positions + sint32 inaccessibleRunLength= offset-marker-1; + if (inaccessibleRunLength>0 && inaccessibleRunLength<=shortRunLength) + { + // flag all of the points in this run as belonging to a short run in y + for (uint32 j=marker+1;j(newDist))\ + {\ + zoneBuffer[newVal]=(newDist);\ + vects[(newDist)&15].push_back(newVal);\ + ++entriesToTreat;\ + }\ + }\ + } + + // N, S, W, E moves + TEST_MOVE( 0, 1,dist+5); + TEST_MOVE( 0,-1,dist+5); + TEST_MOVE( 1, 0,dist+5); + TEST_MOVE(-1, 0,dist+5); + + // NW, NE, WS, SE moves + TEST_MOVE( 1, 1,dist+7); + TEST_MOVE(-1, 1,dist+7); + TEST_MOVE( 1,-1,dist+7); + TEST_MOVE(-1,-1,dist+7); + + // NNW, NNE, SSW, SSE moves + TEST_MOVE( 1, 2,dist+11); + TEST_MOVE(-1, 2,dist+11); + TEST_MOVE( 1,-2,dist+11); + TEST_MOVE(-1,-2,dist+11); + + // WNW, WSW, ENE, ESE moves + TEST_MOVE( 2, 1,dist+11); + TEST_MOVE(-2, 1,dist+11); + TEST_MOVE( 2,-1,dist+11); + TEST_MOVE(-2,-1,dist+11); + + #undef TEST_MOVE + } + + // clear out the vector + entriesToTreat-= (uint32)vect.size(); + vect.clear(); + } +} + +const TBuffer& CProximityMapBuffer::getBuffer() const +{ + return _Buffer; +} + +uint32 CProximityMapBuffer::getScanHeight() const +{ + return _ScanHeight; +} + +uint32 CProximityMapBuffer::getScanWidth() const +{ + return _ScanWidth; +} + + +//------------------------------------------------------------------------------------------------- +// NLMISC_COMMAND pacsBuildProximityMap +//------------------------------------------------------------------------------------------------- + +NLMISC_COMMAND(pacsBuildProximityMap,"build a set of proximity maps from a cwmap2 file","") +{ + // deal with command arguments + nlinfo("Building proximity map..."); + if(args.size()<1) + return false; + const std::string& name= args[0]; + + // load the collision map file and generate our buffer from it + CProximityMapBuffer buffer; + string ext = CFile::getExtension(name); + if (ext == "") + ext = "cwmap2"; + string fileName= OutputPath+CFile::getFilenameWithoutExtension(name)+"."+ext; + nlinfo("Building proximity map: Loading cwmap2 file: %s",fileName.c_str()); + buffer.load(fileName); + + // generate a tga file from the buffer contents + nlinfo("Building proximity map: Writing accessibilty file: %s",(OutputPath+name+"_accessible.tga").c_str()); + writeProximityBufferToTgaFile(OutputPath+name+"_accessible.tga",buffer.getBuffer(),buffer.getScanWidth(),buffer.getScanHeight()); + + // divide space up into non-connecting zones + nlinfo("Building proximity map: Dividing accessible space into zones"); + CProximityMapBuffer::TZones zones; + buffer.calculateZones(zones); + + // setup a string to contain the proximity zone list (in csv format) + NLMISC::CSString proximityZoneList="idx,x_offset,y_offset,width,height,xmin,ymin,xmax,ymax\n"; + + // generate proximity info for inaccessible points in each zone + for (uint32 i=0;i -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - -#include "nel/misc/types_nl.h" -#include "nel/misc/common.h" -#include "nel/misc/debug.h" -#include "nel/misc/command.h" -#include "nel/misc/config_file.h" - -#include "nel/misc/path.h" - -using namespace std; -using namespace NLMISC; - -extern string OutputPath; -extern vector PacsPrimPath; -extern vector LookupPath; -extern vector LookupNoRecursePath; - -sint main(sint argc, char **argv) -{ - createDebug(); - - CConfigFile cf; - CConfigFile::CVar *var; - - cf.load(string("ai_build_wmap.cfg")); - - // - var = cf.getVarPtr("Paths"); - if (var != NULL) - { - for (uint i=0; i < var->size(); ++i) - LookupPath.push_back(var->asString(i)); - } - - var = cf.getVarPtr("NoRecursePaths"); - if (var != NULL) - { - for (uint i=0; i < var->size(); ++i) - LookupNoRecursePath.push_back(var->asString(i)); - } - - var = cf.getVarPtr("PacsPrimPaths"); - if (var != NULL) - { - for (uint i=0; i < var->size(); ++i) - PacsPrimPath.push_back(var->asString(i)); - } - - var = cf.getVarPtr("OutputPath"); - if (var != NULL) - { - OutputPath = CPath::standardizePath(var->asString()); - } - - - vector commands; - var = cf.getVarPtr("Commands"); - if (var != NULL) - { - for (uint i=0; i < var->size(); ++i) - commands.push_back(var->asString(i)); - } - - string cmd; - for (sint i=1; i < argc; ++i) - { - if (string(argv[i]) == string("-")) - { - if (cmd != "") - { - commands.push_back(cmd); - cmd = ""; - } - } - else - { - if (cmd != "") - cmd += ' '; - cmd += argv[i]; - } - } - - if (cmd != "") - commands.push_back(cmd); - - NLMISC::createDebug (); - nlinfo("Running commands:"); - - for (uint i=0; i +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#include "nel/misc/types_nl.h" +#include "nel/misc/common.h" +#include "nel/misc/debug.h" +#include "nel/misc/command.h" +#include "nel/misc/config_file.h" + +#include "nel/misc/path.h" + +using namespace std; +using namespace NLMISC; + +extern string OutputPath; +extern vector PacsPrimPath; +extern vector LookupPath; +extern vector LookupNoRecursePath; + +sint main(sint argc, char **argv) +{ + createDebug(); + + CConfigFile cf; + CConfigFile::CVar *var; + + cf.load(string("ai_build_wmap.cfg")); + + // + var = cf.getVarPtr("Paths"); + if (var != NULL) + { + for (uint i=0; i < var->size(); ++i) + LookupPath.push_back(var->asString(i)); + } + + var = cf.getVarPtr("NoRecursePaths"); + if (var != NULL) + { + for (uint i=0; i < var->size(); ++i) + LookupNoRecursePath.push_back(var->asString(i)); + } + + var = cf.getVarPtr("PacsPrimPaths"); + if (var != NULL) + { + for (uint i=0; i < var->size(); ++i) + PacsPrimPath.push_back(var->asString(i)); + } + + var = cf.getVarPtr("OutputPath"); + if (var != NULL) + { + OutputPath = CPath::standardizePath(var->asString()); + } + + + vector commands; + var = cf.getVarPtr("Commands"); + if (var != NULL) + { + for (uint i=0; i < var->size(); ++i) + commands.push_back(var->asString(i)); + } + + string cmd; + for (sint i=1; i < argc; ++i) + { + if (string(argv[i]) == string("-")) + { + if (cmd != "") + { + commands.push_back(cmd); + cmd = ""; + } + } + else + { + if (cmd != "") + cmd += ' '; + cmd += argv[i]; + } + } + + if (cmd != "") + commands.push_back(cmd); + + NLMISC::createDebug (); + nlinfo("Running commands:"); + + for (uint i=0; i -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// CodeFast.cpp : Defines the entry point for the console application. -// - -/* - - TODO - - re-do 'case' parser to look for anything with a '::' sub-string - - build handy command line behaviour - - test ... test ... outfile timestamp on no change test... - -*/ -#include "nel/misc/types_nl.h" - -#include -#include -#include -#include -#include -#include - -class COutputFile -{ -public: - enum TParamType { STRING, INT, FLOAT }; - - // ctor - COutputFile(const char *filename); - - // input string parsers - void processString(const std::string &s); - void processCase(const std::string &s); - - void addStruct(const std::string &name,const std::string &qualifiers); - void addStructEntry(const std::string ¶mName,const std::string &className,TParamType type,const std::string &defaultValue,const std::string &comment); - - void addEnum(const std::string &name); - void addEnumEntry(const std::string &entry); - - void display() const; - void generateOutput() const; - void generateEnumOutput(std::string &outbuff) const; - -private: - std::string _FileName; - - struct CStructParam - { - std::string _Name; - std::string _Class; - TParamType _Type; - std::string _DefaultValue; - std::string _Comment; - }; - - struct CStruct - { - std::string _Name; - std::string _Qualifiers; - std::vector _Params; - - void display() const; - void generateOutput(std::string &outbuff) const; - }; - - std::vector _Structures; - std::vector _Enums; - std::vector _EnumEntries; - - unsigned _OpenStruct; // the index of the last open structure -}; - -inline COutputFile::COutputFile(const char *filename) -{ - _OpenStruct=~0u; - _FileName=filename; - - // display the string - printf("OUTPUT FILE: %s\n",filename); -} - -inline void COutputFile::processString(const std::string &s) -{ - /* - special strings: - 'ENUM' - 'STRUCT' - '-'('s'|'i'|'f') ['='] ['//'] - */ - - // see whether we have a struct parameter - if (s.size()>5 && s[0]=='-') - { - // start by parsing the 'type' character - if ( (s[1]!='s' && s[1]!='i' && s[1]!='f') || (s[2]!=' ' && s[2]!='\t') ) - { - printf("Ignoring structure parameter due to bad type (should be 's','i' or 'f'): %s",s.c_str()); - return; - } - COutputFile::TParamType type= s[1]=='i'? COutputFile::INT: s[1]=='s'? COutputFile::STRING: FLOAT; - - // skip space after the 'type' character - unsigned i=2; - while ( i7 && (s[6]==' ' || s[6]=='\t')) - if ((s[0]|('a'^'A')=='s') && (s[1]|('a'^'A')=='t') && (s[2]|('a'^'A')=='r') && - (s[3]|('a'^'A')=='u') && (s[4]|('a'^'A')=='c') && (s[5]|('a'^'A')=='t')) - { - // we have a struct so skip the first 6 letters + opening spaces - unsigned i=7; - while (i5 && (s[4]==' ' || s[4]=='\t')) - if ((s[0]|('a'^'A')=='e') && (s[1]|('a'^'A')=='n') && (s[2]|('a'^'A')=='u') && (s[3]|('a'^'A')=='m')) - { - // we have an enum so skip the first 4 letters + opening spaces - unsigned i=5; - while (i=_Structures.size()) - { - printf("Failed to add structure entry (%s) due to lack of open structure!\n",paramName.c_str()); - return; - } - - unsigned paramCount=_Structures[_OpenStruct]._Params.size(); - _Structures[_OpenStruct]._Params.resize(paramCount+1); - COutputFile::CStructParam ¶m= _Structures[_OpenStruct]._Params[paramCount]; - param._Class=className; - param._Comment=comment; - param._DefaultValue=defaultValue; - param._Name=paramName; - param._Type=type; -} - -inline void COutputFile::addEnum(const std::string &name) -{ - unsigned i; - for (i=0; i<_Enums.size();++i) - if (name==_Enums[i]) - { - printf("Warning: Double declaration of enum: %s\n",name.c_str()); - return; - } - _Enums.resize(i+1); - _Enums[i]=name; -} - -inline void COutputFile::addEnumEntry(const std::string &entry) -{ - // see whether this entry already exists and don't add a second time of this is the case - for (unsigned i=_EnumEntries.size();i--;) - if (_EnumEntries[i]==entry) - return; - - // entry not found in existing values in vector so append it - _EnumEntries.push_back(entry); -} - -void COutputFile::display() const -{ - unsigned i; - - // display the filename - printf("\nFILE: %s\n",_FileName.c_str()); - - // display the set of structures - for (i=0;i<_Structures.size();++i) - { - if (i==_OpenStruct) - printf("\n* "); - else - printf("\n "); - _Structures[i].display(); - } - - // display the set of Enums - for (i=0;i<_Enums.size();++i) - { - printf("\nENUM: %s\n",_Enums[i].c_str()); - - unsigned j; - for (j=0;j<_EnumEntries.size();++j) - { - if (_EnumEntries[j].substr(0,_Enums[i].size()+2)==_Enums[i]+"::") - printf("=> %s\n",_EnumEntries[j].substr(_Enums[i].size()+2).c_str()); - } - } -} - -void COutputFile::generateEnumOutput(std::string &outbuff) const -{ - unsigned i; - - // output the set of Enums - for (i=0;i<_Enums.size();++i) - { - // open the enum - outbuff+="class "; - outbuff+=_Enums[i]+"\n"; - outbuff+="{\n"; - outbuff+="public:\n"; - outbuff+="\tenum TValueType\n"; - outbuff+="\t{\n"; - - // add values to the enum - unsigned j; - for (j=0;j<_EnumEntries.size();++j) - { - if (_EnumEntries[j].substr(0,_Enums[i].size()+2)==_Enums[i]+"::") - { - outbuff+="\t\t"; - outbuff+=_EnumEntries[j].substr(_Enums[i].size()+2); - outbuff+=",\n"; - } - } - - // close the enum - outbuff+="\t\tNUM_VALUES,\n"; - outbuff+="\t\tBAD_VALUE= NUM_VALUES\n"; - outbuff+="\t};\n"; - outbuff+="\n"; - - // IId: a template id interface class - outbuff+="\tclass IId : public NLMISC::CRefCount\n"; - outbuff+="\t{\n"; - outbuff+="\tpublic:\n"; - outbuff+="\t\tIId() : ParsedOk(false) { }\n"; - outbuff+="\t\tTValueType id() const\t{ return _Id; }\n"; - outbuff+="\t\tvoid convertInput(std::vector &args, const std::string &input)\n"; - outbuff+="\t\t{\n"; - outbuff+="\t\t\tunsigned i=0,j=0;\n"; - outbuff+="\t\t\twhile (i < input.size())\n"; - outbuff+="\t\t\t{\n"; - outbuff+="\t\t\t\tj=i;\n"; - outbuff+="\t\t\t\twhile( i type='%s' class='%s' name='%s' default='%s' comment='%s'\n", - _Params[i]._Type==COutputFile::INT? "INT": _Params[i]._Type==COutputFile::STRING? "STR": "FLO", - _Params[i]._Class.c_str(), - _Params[i]._Name.c_str(), - _Params[i]._DefaultValue.c_str(), - _Params[i]._Comment.c_str()); - } -} - -void COutputFile::CStruct::generateOutput(std::string &outbuff) const -{ - // open the structure - outbuff+="struct "; - outbuff+=_Name+" : public TBrickParam::IId\n"; - outbuff+="{\n"; - - // declare structure data parameters - unsigned i; - for (i=0;i<_Params.size();++i) - { - outbuff+="\t"; - outbuff+=_Params[i]._Comment+"\n"; - outbuff+="\t"; - outbuff+=_Params[i]._Class+" "+_Params[i]._Name+";\n"; - } - outbuff+="\n"; - - // default constructor - outbuff+="\t"; - outbuff+=_Name; - if (_Params.size() > 0) - { - outbuff+="():\n"; - for (i=0;i<_Params.size();++i) - { - outbuff+="\t\t"; - outbuff+=_Params[i]._Name+"("+_Params[i]._DefaultValue; - if (i != (_Params.size()-1)) - outbuff+="),\n"; - else - outbuff+=")\n"; - } - } - else - { - outbuff+="()\n"; - } - outbuff+="\t{\n"; - outbuff+="\t\t_Id = "+_Qualifiers+";\n"; - outbuff+="\t}\n"; - outbuff+="\n"; - - // constructor from string - outbuff+="\t"; - outbuff+=_Name; - outbuff+="(const std::string&str)\n"; - outbuff+="\t{\n"; - outbuff+="\t\t*this="; - outbuff+=_Name+"();\n"; - outbuff+="\t\t*this=str;\n"; - outbuff+="\t}\n"; - outbuff+="\n"; - - // '=' operator from string - outbuff+="\tconst "; - outbuff+=_Name+"& operator=(const std::string& input)\n"; - outbuff+="\t{\n"; - outbuff+="\t\tstd::vector args;\n"; - outbuff+="\t\tconvertInput(args, input);\n"; - outbuff+="\n"; - outbuff+="\t\tif (args.size()!="; - if (_Params.size()>100) outbuff+=('0'+((_Params.size()/100)%10)); - if (_Params.size()>10) outbuff+=('0'+((_Params.size()/10)%10)); - outbuff+=('0'+(_Params.size()%10)); - outbuff+=")\n"; - outbuff+="\t\t\treturn *this;\n"; - outbuff+="\n"; - outbuff+="\t\tParsedOk=true;\n"; - for (i=0;i<_Params.size();++i) - { - outbuff+="\t\t"; - outbuff+=_Params[i]._Name+"="; - if (_Params[i]._Type==COutputFile::INT) outbuff+="atoi("; - if (_Params[i]._Type==COutputFile::FLOAT) outbuff+="(float)atof("; - outbuff+="args["; - if (i>100) outbuff+=('0'+((i/100)%10)); - if (i>10) outbuff+=('0'+((i/10)%10)); - outbuff+=('0'+(i%10)); - if (_Params[i]._Type==COutputFile::INT || _Params[i]._Type==COutputFile::FLOAT) - outbuff+="].c_str());\n"; - else - outbuff+="].c_str();\n"; - } - outbuff+="\n"; - outbuff+="\t\treturn *this;\n"; - outbuff+="\t}\n"; - - // close the struct - outbuff+="};\n\n\n"; -} - - -void processInputFile(const char *infile,COutputFile &outputFile) -{ - // open the input file - FILE *inf=fopen(infile,"rb"); - assert(inf!=NULL); - - // allocate a RAM buffer for input file - unsigned filesize=filelength(fileno(inf)); - char *inbuff=(char *)malloc(filesize+1); - assert(inbuff!=NULL); - - // read the file into the RAM buffer and '0' terminate - fread(inbuff,filesize,1,inf); - inbuff[filesize]=0; - - // housekeeping - fclose(inf); - - // scan the data read into the input buffer for special strings - for (unsigned i=0;i %s\n",srcFile.c_str(),dstFile.c_str()); - printf("===================================\n\n"); - - // instantiate the output buffer - COutputFile outputFile(dstFile.c_str()); - - // parse the source file - processInputFile(srcFile.c_str(),outputFile); - - // display the list of information extracted from the source file - outputFile.display(); - - // generate the target file - outputFile.generateOutput(); - } - return 0; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// CodeFast.cpp : Defines the entry point for the console application. +// + +/* + + TODO + - re-do 'case' parser to look for anything with a '::' sub-string + - build handy command line behaviour + - test ... test ... outfile timestamp on no change test... + +*/ +#include "nel/misc/types_nl.h" + +#include +#include +#include +#include +#include +#include + +class COutputFile +{ +public: + enum TParamType { STRING, INT, FLOAT }; + + // ctor + COutputFile(const char *filename); + + // input string parsers + void processString(const std::string &s); + void processCase(const std::string &s); + + void addStruct(const std::string &name,const std::string &qualifiers); + void addStructEntry(const std::string ¶mName,const std::string &className,TParamType type,const std::string &defaultValue,const std::string &comment); + + void addEnum(const std::string &name); + void addEnumEntry(const std::string &entry); + + void display() const; + void generateOutput() const; + void generateEnumOutput(std::string &outbuff) const; + +private: + std::string _FileName; + + struct CStructParam + { + std::string _Name; + std::string _Class; + TParamType _Type; + std::string _DefaultValue; + std::string _Comment; + }; + + struct CStruct + { + std::string _Name; + std::string _Qualifiers; + std::vector _Params; + + void display() const; + void generateOutput(std::string &outbuff) const; + }; + + std::vector _Structures; + std::vector _Enums; + std::vector _EnumEntries; + + unsigned _OpenStruct; // the index of the last open structure +}; + +inline COutputFile::COutputFile(const char *filename) +{ + _OpenStruct=~0u; + _FileName=filename; + + // display the string + printf("OUTPUT FILE: %s\n",filename); +} + +inline void COutputFile::processString(const std::string &s) +{ + /* + special strings: + 'ENUM' + 'STRUCT' + '-'('s'|'i'|'f') ['='] ['//'] + */ + + // see whether we have a struct parameter + if (s.size()>5 && s[0]=='-') + { + // start by parsing the 'type' character + if ( (s[1]!='s' && s[1]!='i' && s[1]!='f') || (s[2]!=' ' && s[2]!='\t') ) + { + printf("Ignoring structure parameter due to bad type (should be 's','i' or 'f'): %s",s.c_str()); + return; + } + COutputFile::TParamType type= s[1]=='i'? COutputFile::INT: s[1]=='s'? COutputFile::STRING: FLOAT; + + // skip space after the 'type' character + unsigned i=2; + while ( i7 && (s[6]==' ' || s[6]=='\t')) + if ((s[0]|('a'^'A')=='s') && (s[1]|('a'^'A')=='t') && (s[2]|('a'^'A')=='r') && + (s[3]|('a'^'A')=='u') && (s[4]|('a'^'A')=='c') && (s[5]|('a'^'A')=='t')) + { + // we have a struct so skip the first 6 letters + opening spaces + unsigned i=7; + while (i5 && (s[4]==' ' || s[4]=='\t')) + if ((s[0]|('a'^'A')=='e') && (s[1]|('a'^'A')=='n') && (s[2]|('a'^'A')=='u') && (s[3]|('a'^'A')=='m')) + { + // we have an enum so skip the first 4 letters + opening spaces + unsigned i=5; + while (i=_Structures.size()) + { + printf("Failed to add structure entry (%s) due to lack of open structure!\n",paramName.c_str()); + return; + } + + unsigned paramCount=_Structures[_OpenStruct]._Params.size(); + _Structures[_OpenStruct]._Params.resize(paramCount+1); + COutputFile::CStructParam ¶m= _Structures[_OpenStruct]._Params[paramCount]; + param._Class=className; + param._Comment=comment; + param._DefaultValue=defaultValue; + param._Name=paramName; + param._Type=type; +} + +inline void COutputFile::addEnum(const std::string &name) +{ + unsigned i; + for (i=0; i<_Enums.size();++i) + if (name==_Enums[i]) + { + printf("Warning: Double declaration of enum: %s\n",name.c_str()); + return; + } + _Enums.resize(i+1); + _Enums[i]=name; +} + +inline void COutputFile::addEnumEntry(const std::string &entry) +{ + // see whether this entry already exists and don't add a second time of this is the case + for (unsigned i=_EnumEntries.size();i--;) + if (_EnumEntries[i]==entry) + return; + + // entry not found in existing values in vector so append it + _EnumEntries.push_back(entry); +} + +void COutputFile::display() const +{ + unsigned i; + + // display the filename + printf("\nFILE: %s\n",_FileName.c_str()); + + // display the set of structures + for (i=0;i<_Structures.size();++i) + { + if (i==_OpenStruct) + printf("\n* "); + else + printf("\n "); + _Structures[i].display(); + } + + // display the set of Enums + for (i=0;i<_Enums.size();++i) + { + printf("\nENUM: %s\n",_Enums[i].c_str()); + + unsigned j; + for (j=0;j<_EnumEntries.size();++j) + { + if (_EnumEntries[j].substr(0,_Enums[i].size()+2)==_Enums[i]+"::") + printf("=> %s\n",_EnumEntries[j].substr(_Enums[i].size()+2).c_str()); + } + } +} + +void COutputFile::generateEnumOutput(std::string &outbuff) const +{ + unsigned i; + + // output the set of Enums + for (i=0;i<_Enums.size();++i) + { + // open the enum + outbuff+="class "; + outbuff+=_Enums[i]+"\n"; + outbuff+="{\n"; + outbuff+="public:\n"; + outbuff+="\tenum TValueType\n"; + outbuff+="\t{\n"; + + // add values to the enum + unsigned j; + for (j=0;j<_EnumEntries.size();++j) + { + if (_EnumEntries[j].substr(0,_Enums[i].size()+2)==_Enums[i]+"::") + { + outbuff+="\t\t"; + outbuff+=_EnumEntries[j].substr(_Enums[i].size()+2); + outbuff+=",\n"; + } + } + + // close the enum + outbuff+="\t\tNUM_VALUES,\n"; + outbuff+="\t\tBAD_VALUE= NUM_VALUES\n"; + outbuff+="\t};\n"; + outbuff+="\n"; + + // IId: a template id interface class + outbuff+="\tclass IId : public NLMISC::CRefCount\n"; + outbuff+="\t{\n"; + outbuff+="\tpublic:\n"; + outbuff+="\t\tIId() : ParsedOk(false) { }\n"; + outbuff+="\t\tTValueType id() const\t{ return _Id; }\n"; + outbuff+="\t\tvoid convertInput(std::vector &args, const std::string &input)\n"; + outbuff+="\t\t{\n"; + outbuff+="\t\t\tunsigned i=0,j=0;\n"; + outbuff+="\t\t\twhile (i < input.size())\n"; + outbuff+="\t\t\t{\n"; + outbuff+="\t\t\t\tj=i;\n"; + outbuff+="\t\t\t\twhile( i type='%s' class='%s' name='%s' default='%s' comment='%s'\n", + _Params[i]._Type==COutputFile::INT? "INT": _Params[i]._Type==COutputFile::STRING? "STR": "FLO", + _Params[i]._Class.c_str(), + _Params[i]._Name.c_str(), + _Params[i]._DefaultValue.c_str(), + _Params[i]._Comment.c_str()); + } +} + +void COutputFile::CStruct::generateOutput(std::string &outbuff) const +{ + // open the structure + outbuff+="struct "; + outbuff+=_Name+" : public TBrickParam::IId\n"; + outbuff+="{\n"; + + // declare structure data parameters + unsigned i; + for (i=0;i<_Params.size();++i) + { + outbuff+="\t"; + outbuff+=_Params[i]._Comment+"\n"; + outbuff+="\t"; + outbuff+=_Params[i]._Class+" "+_Params[i]._Name+";\n"; + } + outbuff+="\n"; + + // default constructor + outbuff+="\t"; + outbuff+=_Name; + if (_Params.size() > 0) + { + outbuff+="():\n"; + for (i=0;i<_Params.size();++i) + { + outbuff+="\t\t"; + outbuff+=_Params[i]._Name+"("+_Params[i]._DefaultValue; + if (i != (_Params.size()-1)) + outbuff+="),\n"; + else + outbuff+=")\n"; + } + } + else + { + outbuff+="()\n"; + } + outbuff+="\t{\n"; + outbuff+="\t\t_Id = "+_Qualifiers+";\n"; + outbuff+="\t}\n"; + outbuff+="\n"; + + // constructor from string + outbuff+="\t"; + outbuff+=_Name; + outbuff+="(const std::string&str)\n"; + outbuff+="\t{\n"; + outbuff+="\t\t*this="; + outbuff+=_Name+"();\n"; + outbuff+="\t\t*this=str;\n"; + outbuff+="\t}\n"; + outbuff+="\n"; + + // '=' operator from string + outbuff+="\tconst "; + outbuff+=_Name+"& operator=(const std::string& input)\n"; + outbuff+="\t{\n"; + outbuff+="\t\tstd::vector args;\n"; + outbuff+="\t\tconvertInput(args, input);\n"; + outbuff+="\n"; + outbuff+="\t\tif (args.size()!="; + if (_Params.size()>100) outbuff+=('0'+((_Params.size()/100)%10)); + if (_Params.size()>10) outbuff+=('0'+((_Params.size()/10)%10)); + outbuff+=('0'+(_Params.size()%10)); + outbuff+=")\n"; + outbuff+="\t\t\treturn *this;\n"; + outbuff+="\n"; + outbuff+="\t\tParsedOk=true;\n"; + for (i=0;i<_Params.size();++i) + { + outbuff+="\t\t"; + outbuff+=_Params[i]._Name+"="; + if (_Params[i]._Type==COutputFile::INT) outbuff+="atoi("; + if (_Params[i]._Type==COutputFile::FLOAT) outbuff+="(float)atof("; + outbuff+="args["; + if (i>100) outbuff+=('0'+((i/100)%10)); + if (i>10) outbuff+=('0'+((i/10)%10)); + outbuff+=('0'+(i%10)); + if (_Params[i]._Type==COutputFile::INT || _Params[i]._Type==COutputFile::FLOAT) + outbuff+="].c_str());\n"; + else + outbuff+="].c_str();\n"; + } + outbuff+="\n"; + outbuff+="\t\treturn *this;\n"; + outbuff+="\t}\n"; + + // close the struct + outbuff+="};\n\n\n"; +} + + +void processInputFile(const char *infile,COutputFile &outputFile) +{ + // open the input file + FILE *inf=fopen(infile,"rb"); + assert(inf!=NULL); + + // allocate a RAM buffer for input file + unsigned filesize=filelength(fileno(inf)); + char *inbuff=(char *)malloc(filesize+1); + assert(inbuff!=NULL); + + // read the file into the RAM buffer and '0' terminate + fread(inbuff,filesize,1,inf); + inbuff[filesize]=0; + + // housekeeping + fclose(inf); + + // scan the data read into the input buffer for special strings + for (unsigned i=0;i %s\n",srcFile.c_str(),dstFile.c_str()); + printf("===================================\n\n"); + + // instantiate the output buffer + COutputFile outputFile(dstFile.c_str()); + + // parse the source file + processInputFile(srcFile.c_str(),outputFile); + + // display the list of information extracted from the source file + outputFile.display(); + + // generate the target file + outputFile.generateOutput(); + } + return 0; +} diff --git a/code/ryzom/tools/server/build_spell_sheet/build_spell_sheet.cpp b/code/ryzom/tools/server/build_spell_sheet/build_spell_sheet.cpp index ac2d96963..5e892410b 100644 --- a/code/ryzom/tools/server/build_spell_sheet/build_spell_sheet.cpp +++ b/code/ryzom/tools/server/build_spell_sheet/build_spell_sheet.cpp @@ -1,552 +1,552 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - - -#include "nel/misc/config_file.h" -#include "nel/misc/file.h" -#include "nel/misc/o_xml.h" -#include "nel/misc/path.h" -#include "nel/misc/algo.h" -#include - -using namespace NLMISC; - - -/** This app generates sheets of all spell in ryzom - * Each spell is composed of a projectile and an impact part - * ... - */ - - -// write a sheet atom -static writeAtom(IStream &f, const std::string &name, const std::string &value) -{ - f.xmlPushBegin("ATOM"); - f.xmlSetAttrib("Name"); - std::string nameNotConst = name; - f.serial(nameNotConst); - f.xmlSetAttrib("Value"); - std::string valueNotConst = value; - f.serial(valueNotConst); - f.xmlPushEnd(); - f.xmlPop(); -} - -//**************************************************************************************************************************** -/** - * A set of user params - */ -class CUserParams -{ -public: - enum { NumUserParams = 4 }; - std::string UserParam[NumUserParams]; - bool empty() const - { - for(uint k = 0; k < NumUserParams; ++k) - { - if (!UserParam[k].empty()) return false; - } - return true; - } -public: - void serial(IStream &f) throw(EStream) - { - for(uint k = 0; k < NumUserParams; ++k) - { - if (!UserParam[k].empty()) writeAtom(f, toString("UserParam%d", (int) k), UserParam[k]); - } - } -}; - -//**************************************************************************************************************************** -/** a single fx and its parameters - */ -class CFX -{ -public: - std::string PSName; - CUserParams UserParams; -public: - bool empty() const - { - return PSName.empty() && UserParams.empty(); - } - void serial(IStream &f) throw(EStream) - { - if (!PSName.empty()) writeAtom(f, "PSName", PSName); - UserParams.serial(f); - } -}; - -//**************************************************************************************************************************** -/** A set of fx - */ -class CFXSet -{ -public: - enum { NumFX = 4 }; - CFX FX[NumFX]; -public: - bool empty() const - { - for(uint k = 0; k < NumFX; ++k) - { - if (!FX[k].empty()) return false; - } - return true; - } - void serial(IStream &f) throw(EStream) - { - for(uint k = 0; k < NumFX; ++k) - { - if (!FX[k].empty()) - { - f.xmlPushBegin("STRUCT"); - f.xmlSetAttrib("Name"); - std::string name = toString("FX%d", (int) k).c_str(); - f.serial(name); - f.xmlPushEnd(); - FX[k].serial(f); - f.xmlPop(); - } - } - } - void setUserParams(const CUserParams ¶ms) - { - for(uint k = 0; k < NumFX; ++k) - { - FX[k].UserParams = params; - } - } -}; - -//**************************************************************************************************************************** -/** A spell sheet, with some args defined - */ -class CSpellSheet -{ -public: - std::vector Parents; - CFXSet Projectile; - CFXSet Impact; -public: - // write that spell as a sheet - void writeSheet(const std::string &sheetName) - { - COFile f; - if (!f.open(sheetName, false, true)) - { - nlwarning("Can't write %s", sheetName.c_str()); - return; - } - try - { - COXml xmlStreamOut; - xmlStreamOut.init(&f); - xmlStreamOut.xmlPushBegin("FORM"); - - IStream &xmlStream = xmlStreamOut; - - /* - std::string revision = "$revision$"; - xmlStream.xmlSerial(revision, "Revision"); - std::string state = "modified"; - xmlStream.xmlSerial(state, "State"); - */ - xmlStream.xmlSetAttrib("Revision"); - std::string revision = "$revision$"; - xmlStream.serial(revision); - xmlStream.xmlSetAttrib("State"); - std::string state = "modified"; - xmlStream.serial(state); - xmlStream.xmlPushEnd(); - // write parent list - for(uint k = 0; k < Parents.size(); ++k) - { - xmlStream.xmlPushBegin("PARENT"); - xmlStream.xmlSetAttrib("Filename"); - xmlStream.serial(Parents[k]); - xmlStream.xmlPushEnd(); - xmlStream.xmlPop(); - } - if (!Projectile.empty() || !Impact.empty()) - { - xmlStream.xmlPush("STRUCT"); - if (!Projectile.empty()) - { - xmlStream.xmlPushBegin("STRUCT"); - xmlStream.xmlSetAttrib("Name"); - std::string name = "Projectile"; - xmlStream.serial(name); - xmlStream.xmlPushEnd(); - Projectile.serial(xmlStream); - xmlStream.xmlPop(); - } - if (!Impact.empty()) - { - xmlStream.xmlPushBegin("STRUCT"); - xmlStream.xmlSetAttrib("Name"); - std::string name = "Impact"; - xmlStream.serial(name); - xmlStream.xmlPushEnd(); - Impact.serial(xmlStream); - xmlStream.xmlPop(); - } - xmlStream.xmlPop(); - } - else - { - xmlStream.xmlPush("STRUCT"); - xmlStream.xmlPop(); - } - xmlStream.xmlPop(); - } - catch(const EStream &) - { - nlwarning("Cant write %s", sheetName.c_str()); - } - } -}; -//**************************************************************************************************************************** -/** Generate list of spell - */ -static void generateSpellList(CConfigFile &cf, const std::string &sheetName) -{ - CConfigFile::CVar *spellList = cf.getVarPtr("spell_list"); - if (!spellList) - { - nlwarning("Can't read spell list"); - return; - } - COFile f; - if (!f.open(sheetName, false, true)) - { - nlwarning("Can't write %s", sheetName.c_str()); - return; - } - try - { - COXml xmlStreamOut; - xmlStreamOut.init(&f); - xmlStreamOut.xmlPush("FORM"); - IStream &xmlStream = xmlStreamOut; - xmlStream.xmlPush("STRUCT"); - xmlStream.xmlPushBegin("ARRAY"); - xmlStream.xmlSetAttrib("Name"); - std::string name = "List"; - xmlStream.serial(name); - xmlStream.xmlPushEnd(); - for(uint k = 0; k < (uint) spellList->size(); ++k) - { - std::vector result; - NLMISC::splitString(spellList->asString(k), "|", result); - if (result.size() < 2) - { - nlwarning("Should provide at list spell name and id"); - } - xmlStream.xmlPush("STRUCT"); - writeAtom(xmlStream, "ID", result[1]); - writeAtom(xmlStream, "SheetBaseName", result[0]); - xmlStream.xmlPop(); - } - xmlStream.xmlPop(); // STRUCT - xmlStream.xmlPop(); // FORM - } - catch(const EStream &) - { - nlwarning("Cant write %s", sheetName.c_str()); - } -} - -//**************************************************************************************************************************** -int main(int argc, char* argv[]) -{ - if (argc < 2) - { - nlwarning("Usage : %s config_file_name.cfg", argv[0]); - return -1; - } - CConfigFile cf; - try - { - cf.load(argv[1]); - } - catch(const NLMISC::EConfigFile &) - { - nlwarning("Error in config file %s", argv[1]); - return -1; - } - catch(...) - { - nlwarning("Can't read config file %s", argv[1]); - return -1; - } - // output for sheets - std::string outputPath; - CConfigFile::CVar *outputPathVar = cf.getVarPtr("output_path"); - if (outputPathVar) - { - outputPath = outputPathVar->asString() + "/"; - } - // output for 'levels' parents - std::string levelParentsPath; - CConfigFile::CVar *levelParentsPathVar = cf.getVarPtr("level_parents"); - if (levelParentsPathVar) - { - levelParentsPath = levelParentsPathVar->asString() + "/"; - } - // output for projectile parents - std::string projectileParentsPath; - CConfigFile::CVar *projectileParentsPathVar = cf.getVarPtr("projectile_base"); - if (projectileParentsPathVar) - { - projectileParentsPath= projectileParentsPathVar->asString() + "/"; - } - // output for 'projectile by level and mode' parents - std::string projectileByLevelAndModeParentsPath; - CConfigFile::CVar *projectileByLevelAndModeParentsPathVar = cf.getVarPtr("projectile_by_level_and_mode_parents"); - if (projectileByLevelAndModeParentsPathVar) - { - projectileByLevelAndModeParentsPath = projectileByLevelAndModeParentsPathVar->asString() + "/"; - } - // output for 'base spells' parents - std::string baseSpellPath; - CConfigFile::CVar *baseSpellPathVar = cf.getVarPtr("spell_base"); - if (baseSpellPathVar) - { - baseSpellPath = baseSpellPathVar->asString() + "/"; - } - // output for 'spell by levels' parents - std::string spellByLevelParentsPath; - CConfigFile::CVar *spellByLevelParentsPathVar = cf.getVarPtr("spell_by_level_parents"); - if (spellByLevelParentsPathVar) - { - spellByLevelParentsPath = spellByLevelParentsPathVar->asString() + "/"; - } - // output for 'final spell' - std::string finalSpellPath; - CConfigFile::CVar *finalSpellPathVar = cf.getVarPtr("final_spells"); - if (finalSpellPathVar) - { - finalSpellPath = finalSpellPathVar->asString() + "/"; - } - - - - // read number of levels - CConfigFile::CVar *numLevelVar = cf.getVarPtr("num_levels"); - if (!numLevelVar) - { - nlwarning("Can't read number of spell levels"); - return -1; - } - uint numSpellLevels = numLevelVar->asInt(); - - std::vector userParams(numSpellLevels); - - // read user params set for each level - for(uint level = 0; level < numSpellLevels; ++level) - { - std::string varName = toString("user_params_level%d", (int) (level + 1)); - CConfigFile::CVar *up = cf.getVarPtr(varName); - if (!up) - { - nlwarning("Can't read var %s", varName.c_str()); - } - else - { - for(uint k = 0; k < CUserParams::NumUserParams; ++k) - { - userParams[level].UserParam[k] = up->asString(k); - } - } - } - - // read types of spells (offensif, curatif ...) - CConfigFile::CVar *spellTypesList = cf.getVarPtr("spell_types"); - if (!spellTypesList) - { - nlwarning("Can't read types of spells"); - return -1; - } - // read modes of spells - CConfigFile::CVar *spellModesList = cf.getVarPtr("spell_modes"); - - // read name of ps for projectiles - std::vector projPSNames; - projPSNames.resize(spellTypesList->size() * spellModesList->size()); - CConfigFile::CVar *projectileNames = cf.getVarPtr("projectile_fx"); - if (projectileNames) - { - for(uint k = 0; k < (uint) projectileNames->size(); ++k) - { - // entry are expected to have the following form : - // "type|mode|fx_name.ps" - std::vector params; - NLMISC::splitString(projectileNames->asString(k), "|", params); - if (params.size() != 3) - { - nlwarning("Bad param for projectile ps name : %s", projectileNames->asString(k).c_str()); - } - else - { - bool found = false; - // find the mode - for (uint mode = 0; mode < (uint) spellModesList->size(); ++mode) - { - if (spellModesList->asString(mode) == params[1]) - { - for (uint type = 0; type < (uint) spellTypesList->size(); ++type) - { - if (spellTypesList->asString(type) == params[0]) - { - projPSNames[type + mode * spellTypesList->size()] = params[2]; - //nlwarning("%s : found", projectileNames->asString(k).c_str()); - found = true; - break; - } - } - if (found) break; - } - } - //if (!found) nlwarning("%s : not found", projectileNames->asString(k).c_str()); - } - } - } - - nlinfo("Generate projectiles parent sheets..."); - // gen projectiles base sheet - CSpellSheet baseProjectileSheet; - baseProjectileSheet.writeSheet(outputPath + projectileParentsPath + "_projectile_base.spell"); - // gen projectiles parent sheets - for(uint type = 0; type < (uint) spellTypesList->size(); ++type) - { - for(uint mode = 0; mode < (uint) spellModesList->size(); ++mode) - { - std::string sheetName = "_projectile_" + spellTypesList->asString(type) + "_" + spellModesList->asString(mode) + ".spell"; - CSpellSheet ss; - ss.Parents.push_back("_projectile_base.spell"); - // affect ps name if known - ss.Projectile.FX[0].PSName = projPSNames[type + mode * spellTypesList->size()]; - ss.writeSheet(outputPath + projectileParentsPath + sheetName); - } - } - - nlinfo("Generate sheets by level..."); - // generate sheets by level - for(uint level = 0; level < numSpellLevels; ++level) - { - // gen projectiles by level sheets (parent sheets) - std::string sheetName = toString("_projectile_lvl%d.spell", (int) (level + 1)); - CSpellSheet projectileSheet; - projectileSheet.Projectile.setUserParams(userParams[level]); - projectileSheet.writeSheet(outputPath + levelParentsPath + sheetName); - // gen impact level sheets - sheetName = toString("_impact_lvl%d.spell", (int) (level + 1)); - CSpellSheet impactSheet; - impactSheet.Impact.setUserParams(userParams[level]); - impactSheet.writeSheet(outputPath + levelParentsPath + sheetName); - - } - - nlinfo("Generate projectile list (by mode, type and levels)..."); - // generate projectile list (by mode, type and levels) - for(uint type = 0; type < (uint) spellTypesList->size(); ++type) - { - for(uint mode = 0; mode < (uint) spellModesList->size(); ++mode) - { - for(uint level = 0; level < (uint) numSpellLevels; ++level) - { - CSpellSheet ss; - ss.Parents.resize(2); - ss.Parents[0] = toString("_projectile_lvl%d.spell", (int) (level + 1)); // inherit level - ss.Parents[1] = "_projectile_" + spellTypesList->asString(type) + "_" + spellModesList->asString(mode) + ".spell"; // inherit mode and type - std::string sheetName = "_projectile_" + spellTypesList->asString(type) + "_" + spellModesList->asString(mode) + toString("_lvl%d.spell", (int) (level + 1)); - ss.writeSheet(outputPath + projectileByLevelAndModeParentsPath + sheetName); - } - } - } - // - nlinfo("Generate spell list..."); - // read list of spells - // the string format for spells is : "sheet_name|ps_name" - // the name of the particle system is optionnal - CConfigFile::CVar *spellList = cf.getVarPtr("spell_list"); - if (!spellList) - { - nlwarning("Can't read spell list"); - return -1; - } - for(uint k = 0; k < (uint) spellList->size(); ++k) - { - std::string spellName = spellList->asString(k); - std::vector result; - NLMISC::splitString(spellName, "|", result); - if (result.size() < 3) - { - nlwarning("Should provide at least spell name, id and mode"); - } - else - { - // generate parent sheet - CSpellSheet baseSpellSheet; - if (result.size() > 3) - { - baseSpellSheet.Impact.FX[0].PSName = result[3]; - } - baseSpellSheet.writeSheet(outputPath + baseSpellPath + "_" + result[0] + ".spell"); - // generate child sheet - // - by spell level - // - by spell type (chain, bomb, spray ...) - - // save spells by level - for(uint level = 0; level < numSpellLevels; ++level) - { - CSpellSheet leveledSpell; - leveledSpell.Parents.resize(2); - leveledSpell.Parents[0] = "_" + result[0] + ".spell"; - leveledSpell.Parents[1] = toString("_impact_lvl%d.spell", (int) (level + 1)); - leveledSpell.writeSheet(outputPath + spellByLevelParentsPath + "_" + result[0] + toString("_lvl%d.spell", (int) (level + 1))); - } - - // save spell with good projectile and level - for(uint level = 0; level < numSpellLevels; ++level) - { - for(uint mode = 0; mode < (uint) spellModesList->size(); ++mode) - { - CSpellSheet finalSheet; - finalSheet.Parents.resize(2); - finalSheet.Parents[0] = "_" + result[0] + toString("_lvl%d.spell", (int) (level + 1)); - finalSheet.Parents[1] = "_projectile_" + result[2] + "_" + spellModesList->asString(mode) + toString("_lvl%d.spell", (int) (level + 1)); - //finalSheet.writeSheet(outputPath + finalSpellPath + result[0] + toString("_lvl%d_", (int) (level + 1)) + result[2] + "_" + spellModesList->asString(mode) + ".spell"); - finalSheet.writeSheet(outputPath + finalSpellPath + result[0] + "_" + spellModesList->asString(mode) + toString("_lvl%d", (int) (level + 1)) + ".spell"); - } - } - } - } - // generate spell list with their ids - CConfigFile::CVar *spellListFile = cf.getVarPtr("spell_list_file"); - if (spellListFile) - { - generateSpellList(cf, outputPath + spellListFile->asString()); - } - nlinfo("Done"); - return 0; -} - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + + +#include "nel/misc/config_file.h" +#include "nel/misc/file.h" +#include "nel/misc/o_xml.h" +#include "nel/misc/path.h" +#include "nel/misc/algo.h" +#include + +using namespace NLMISC; + + +/** This app generates sheets of all spell in ryzom + * Each spell is composed of a projectile and an impact part + * ... + */ + + +// write a sheet atom +static writeAtom(IStream &f, const std::string &name, const std::string &value) +{ + f.xmlPushBegin("ATOM"); + f.xmlSetAttrib("Name"); + std::string nameNotConst = name; + f.serial(nameNotConst); + f.xmlSetAttrib("Value"); + std::string valueNotConst = value; + f.serial(valueNotConst); + f.xmlPushEnd(); + f.xmlPop(); +} + +//**************************************************************************************************************************** +/** + * A set of user params + */ +class CUserParams +{ +public: + enum { NumUserParams = 4 }; + std::string UserParam[NumUserParams]; + bool empty() const + { + for(uint k = 0; k < NumUserParams; ++k) + { + if (!UserParam[k].empty()) return false; + } + return true; + } +public: + void serial(IStream &f) throw(EStream) + { + for(uint k = 0; k < NumUserParams; ++k) + { + if (!UserParam[k].empty()) writeAtom(f, toString("UserParam%d", (int) k), UserParam[k]); + } + } +}; + +//**************************************************************************************************************************** +/** a single fx and its parameters + */ +class CFX +{ +public: + std::string PSName; + CUserParams UserParams; +public: + bool empty() const + { + return PSName.empty() && UserParams.empty(); + } + void serial(IStream &f) throw(EStream) + { + if (!PSName.empty()) writeAtom(f, "PSName", PSName); + UserParams.serial(f); + } +}; + +//**************************************************************************************************************************** +/** A set of fx + */ +class CFXSet +{ +public: + enum { NumFX = 4 }; + CFX FX[NumFX]; +public: + bool empty() const + { + for(uint k = 0; k < NumFX; ++k) + { + if (!FX[k].empty()) return false; + } + return true; + } + void serial(IStream &f) throw(EStream) + { + for(uint k = 0; k < NumFX; ++k) + { + if (!FX[k].empty()) + { + f.xmlPushBegin("STRUCT"); + f.xmlSetAttrib("Name"); + std::string name = toString("FX%d", (int) k).c_str(); + f.serial(name); + f.xmlPushEnd(); + FX[k].serial(f); + f.xmlPop(); + } + } + } + void setUserParams(const CUserParams ¶ms) + { + for(uint k = 0; k < NumFX; ++k) + { + FX[k].UserParams = params; + } + } +}; + +//**************************************************************************************************************************** +/** A spell sheet, with some args defined + */ +class CSpellSheet +{ +public: + std::vector Parents; + CFXSet Projectile; + CFXSet Impact; +public: + // write that spell as a sheet + void writeSheet(const std::string &sheetName) + { + COFile f; + if (!f.open(sheetName, false, true)) + { + nlwarning("Can't write %s", sheetName.c_str()); + return; + } + try + { + COXml xmlStreamOut; + xmlStreamOut.init(&f); + xmlStreamOut.xmlPushBegin("FORM"); + + IStream &xmlStream = xmlStreamOut; + + /* + std::string revision = "$revision$"; + xmlStream.xmlSerial(revision, "Revision"); + std::string state = "modified"; + xmlStream.xmlSerial(state, "State"); + */ + xmlStream.xmlSetAttrib("Revision"); + std::string revision = "$revision$"; + xmlStream.serial(revision); + xmlStream.xmlSetAttrib("State"); + std::string state = "modified"; + xmlStream.serial(state); + xmlStream.xmlPushEnd(); + // write parent list + for(uint k = 0; k < Parents.size(); ++k) + { + xmlStream.xmlPushBegin("PARENT"); + xmlStream.xmlSetAttrib("Filename"); + xmlStream.serial(Parents[k]); + xmlStream.xmlPushEnd(); + xmlStream.xmlPop(); + } + if (!Projectile.empty() || !Impact.empty()) + { + xmlStream.xmlPush("STRUCT"); + if (!Projectile.empty()) + { + xmlStream.xmlPushBegin("STRUCT"); + xmlStream.xmlSetAttrib("Name"); + std::string name = "Projectile"; + xmlStream.serial(name); + xmlStream.xmlPushEnd(); + Projectile.serial(xmlStream); + xmlStream.xmlPop(); + } + if (!Impact.empty()) + { + xmlStream.xmlPushBegin("STRUCT"); + xmlStream.xmlSetAttrib("Name"); + std::string name = "Impact"; + xmlStream.serial(name); + xmlStream.xmlPushEnd(); + Impact.serial(xmlStream); + xmlStream.xmlPop(); + } + xmlStream.xmlPop(); + } + else + { + xmlStream.xmlPush("STRUCT"); + xmlStream.xmlPop(); + } + xmlStream.xmlPop(); + } + catch(const EStream &) + { + nlwarning("Cant write %s", sheetName.c_str()); + } + } +}; +//**************************************************************************************************************************** +/** Generate list of spell + */ +static void generateSpellList(CConfigFile &cf, const std::string &sheetName) +{ + CConfigFile::CVar *spellList = cf.getVarPtr("spell_list"); + if (!spellList) + { + nlwarning("Can't read spell list"); + return; + } + COFile f; + if (!f.open(sheetName, false, true)) + { + nlwarning("Can't write %s", sheetName.c_str()); + return; + } + try + { + COXml xmlStreamOut; + xmlStreamOut.init(&f); + xmlStreamOut.xmlPush("FORM"); + IStream &xmlStream = xmlStreamOut; + xmlStream.xmlPush("STRUCT"); + xmlStream.xmlPushBegin("ARRAY"); + xmlStream.xmlSetAttrib("Name"); + std::string name = "List"; + xmlStream.serial(name); + xmlStream.xmlPushEnd(); + for(uint k = 0; k < (uint) spellList->size(); ++k) + { + std::vector result; + NLMISC::splitString(spellList->asString(k), "|", result); + if (result.size() < 2) + { + nlwarning("Should provide at list spell name and id"); + } + xmlStream.xmlPush("STRUCT"); + writeAtom(xmlStream, "ID", result[1]); + writeAtom(xmlStream, "SheetBaseName", result[0]); + xmlStream.xmlPop(); + } + xmlStream.xmlPop(); // STRUCT + xmlStream.xmlPop(); // FORM + } + catch(const EStream &) + { + nlwarning("Cant write %s", sheetName.c_str()); + } +} + +//**************************************************************************************************************************** +int main(int argc, char* argv[]) +{ + if (argc < 2) + { + nlwarning("Usage : %s config_file_name.cfg", argv[0]); + return -1; + } + CConfigFile cf; + try + { + cf.load(argv[1]); + } + catch(const NLMISC::EConfigFile &) + { + nlwarning("Error in config file %s", argv[1]); + return -1; + } + catch(...) + { + nlwarning("Can't read config file %s", argv[1]); + return -1; + } + // output for sheets + std::string outputPath; + CConfigFile::CVar *outputPathVar = cf.getVarPtr("output_path"); + if (outputPathVar) + { + outputPath = outputPathVar->asString() + "/"; + } + // output for 'levels' parents + std::string levelParentsPath; + CConfigFile::CVar *levelParentsPathVar = cf.getVarPtr("level_parents"); + if (levelParentsPathVar) + { + levelParentsPath = levelParentsPathVar->asString() + "/"; + } + // output for projectile parents + std::string projectileParentsPath; + CConfigFile::CVar *projectileParentsPathVar = cf.getVarPtr("projectile_base"); + if (projectileParentsPathVar) + { + projectileParentsPath= projectileParentsPathVar->asString() + "/"; + } + // output for 'projectile by level and mode' parents + std::string projectileByLevelAndModeParentsPath; + CConfigFile::CVar *projectileByLevelAndModeParentsPathVar = cf.getVarPtr("projectile_by_level_and_mode_parents"); + if (projectileByLevelAndModeParentsPathVar) + { + projectileByLevelAndModeParentsPath = projectileByLevelAndModeParentsPathVar->asString() + "/"; + } + // output for 'base spells' parents + std::string baseSpellPath; + CConfigFile::CVar *baseSpellPathVar = cf.getVarPtr("spell_base"); + if (baseSpellPathVar) + { + baseSpellPath = baseSpellPathVar->asString() + "/"; + } + // output for 'spell by levels' parents + std::string spellByLevelParentsPath; + CConfigFile::CVar *spellByLevelParentsPathVar = cf.getVarPtr("spell_by_level_parents"); + if (spellByLevelParentsPathVar) + { + spellByLevelParentsPath = spellByLevelParentsPathVar->asString() + "/"; + } + // output for 'final spell' + std::string finalSpellPath; + CConfigFile::CVar *finalSpellPathVar = cf.getVarPtr("final_spells"); + if (finalSpellPathVar) + { + finalSpellPath = finalSpellPathVar->asString() + "/"; + } + + + + // read number of levels + CConfigFile::CVar *numLevelVar = cf.getVarPtr("num_levels"); + if (!numLevelVar) + { + nlwarning("Can't read number of spell levels"); + return -1; + } + uint numSpellLevels = numLevelVar->asInt(); + + std::vector userParams(numSpellLevels); + + // read user params set for each level + for(uint level = 0; level < numSpellLevels; ++level) + { + std::string varName = toString("user_params_level%d", (int) (level + 1)); + CConfigFile::CVar *up = cf.getVarPtr(varName); + if (!up) + { + nlwarning("Can't read var %s", varName.c_str()); + } + else + { + for(uint k = 0; k < CUserParams::NumUserParams; ++k) + { + userParams[level].UserParam[k] = up->asString(k); + } + } + } + + // read types of spells (offensif, curatif ...) + CConfigFile::CVar *spellTypesList = cf.getVarPtr("spell_types"); + if (!spellTypesList) + { + nlwarning("Can't read types of spells"); + return -1; + } + // read modes of spells + CConfigFile::CVar *spellModesList = cf.getVarPtr("spell_modes"); + + // read name of ps for projectiles + std::vector projPSNames; + projPSNames.resize(spellTypesList->size() * spellModesList->size()); + CConfigFile::CVar *projectileNames = cf.getVarPtr("projectile_fx"); + if (projectileNames) + { + for(uint k = 0; k < (uint) projectileNames->size(); ++k) + { + // entry are expected to have the following form : + // "type|mode|fx_name.ps" + std::vector params; + NLMISC::splitString(projectileNames->asString(k), "|", params); + if (params.size() != 3) + { + nlwarning("Bad param for projectile ps name : %s", projectileNames->asString(k).c_str()); + } + else + { + bool found = false; + // find the mode + for (uint mode = 0; mode < (uint) spellModesList->size(); ++mode) + { + if (spellModesList->asString(mode) == params[1]) + { + for (uint type = 0; type < (uint) spellTypesList->size(); ++type) + { + if (spellTypesList->asString(type) == params[0]) + { + projPSNames[type + mode * spellTypesList->size()] = params[2]; + //nlwarning("%s : found", projectileNames->asString(k).c_str()); + found = true; + break; + } + } + if (found) break; + } + } + //if (!found) nlwarning("%s : not found", projectileNames->asString(k).c_str()); + } + } + } + + nlinfo("Generate projectiles parent sheets..."); + // gen projectiles base sheet + CSpellSheet baseProjectileSheet; + baseProjectileSheet.writeSheet(outputPath + projectileParentsPath + "_projectile_base.spell"); + // gen projectiles parent sheets + for(uint type = 0; type < (uint) spellTypesList->size(); ++type) + { + for(uint mode = 0; mode < (uint) spellModesList->size(); ++mode) + { + std::string sheetName = "_projectile_" + spellTypesList->asString(type) + "_" + spellModesList->asString(mode) + ".spell"; + CSpellSheet ss; + ss.Parents.push_back("_projectile_base.spell"); + // affect ps name if known + ss.Projectile.FX[0].PSName = projPSNames[type + mode * spellTypesList->size()]; + ss.writeSheet(outputPath + projectileParentsPath + sheetName); + } + } + + nlinfo("Generate sheets by level..."); + // generate sheets by level + for(uint level = 0; level < numSpellLevels; ++level) + { + // gen projectiles by level sheets (parent sheets) + std::string sheetName = toString("_projectile_lvl%d.spell", (int) (level + 1)); + CSpellSheet projectileSheet; + projectileSheet.Projectile.setUserParams(userParams[level]); + projectileSheet.writeSheet(outputPath + levelParentsPath + sheetName); + // gen impact level sheets + sheetName = toString("_impact_lvl%d.spell", (int) (level + 1)); + CSpellSheet impactSheet; + impactSheet.Impact.setUserParams(userParams[level]); + impactSheet.writeSheet(outputPath + levelParentsPath + sheetName); + + } + + nlinfo("Generate projectile list (by mode, type and levels)..."); + // generate projectile list (by mode, type and levels) + for(uint type = 0; type < (uint) spellTypesList->size(); ++type) + { + for(uint mode = 0; mode < (uint) spellModesList->size(); ++mode) + { + for(uint level = 0; level < (uint) numSpellLevels; ++level) + { + CSpellSheet ss; + ss.Parents.resize(2); + ss.Parents[0] = toString("_projectile_lvl%d.spell", (int) (level + 1)); // inherit level + ss.Parents[1] = "_projectile_" + spellTypesList->asString(type) + "_" + spellModesList->asString(mode) + ".spell"; // inherit mode and type + std::string sheetName = "_projectile_" + spellTypesList->asString(type) + "_" + spellModesList->asString(mode) + toString("_lvl%d.spell", (int) (level + 1)); + ss.writeSheet(outputPath + projectileByLevelAndModeParentsPath + sheetName); + } + } + } + // + nlinfo("Generate spell list..."); + // read list of spells + // the string format for spells is : "sheet_name|ps_name" + // the name of the particle system is optionnal + CConfigFile::CVar *spellList = cf.getVarPtr("spell_list"); + if (!spellList) + { + nlwarning("Can't read spell list"); + return -1; + } + for(uint k = 0; k < (uint) spellList->size(); ++k) + { + std::string spellName = spellList->asString(k); + std::vector result; + NLMISC::splitString(spellName, "|", result); + if (result.size() < 3) + { + nlwarning("Should provide at least spell name, id and mode"); + } + else + { + // generate parent sheet + CSpellSheet baseSpellSheet; + if (result.size() > 3) + { + baseSpellSheet.Impact.FX[0].PSName = result[3]; + } + baseSpellSheet.writeSheet(outputPath + baseSpellPath + "_" + result[0] + ".spell"); + // generate child sheet + // - by spell level + // - by spell type (chain, bomb, spray ...) + + // save spells by level + for(uint level = 0; level < numSpellLevels; ++level) + { + CSpellSheet leveledSpell; + leveledSpell.Parents.resize(2); + leveledSpell.Parents[0] = "_" + result[0] + ".spell"; + leveledSpell.Parents[1] = toString("_impact_lvl%d.spell", (int) (level + 1)); + leveledSpell.writeSheet(outputPath + spellByLevelParentsPath + "_" + result[0] + toString("_lvl%d.spell", (int) (level + 1))); + } + + // save spell with good projectile and level + for(uint level = 0; level < numSpellLevels; ++level) + { + for(uint mode = 0; mode < (uint) spellModesList->size(); ++mode) + { + CSpellSheet finalSheet; + finalSheet.Parents.resize(2); + finalSheet.Parents[0] = "_" + result[0] + toString("_lvl%d.spell", (int) (level + 1)); + finalSheet.Parents[1] = "_projectile_" + result[2] + "_" + spellModesList->asString(mode) + toString("_lvl%d.spell", (int) (level + 1)); + //finalSheet.writeSheet(outputPath + finalSpellPath + result[0] + toString("_lvl%d_", (int) (level + 1)) + result[2] + "_" + spellModesList->asString(mode) + ".spell"); + finalSheet.writeSheet(outputPath + finalSpellPath + result[0] + "_" + spellModesList->asString(mode) + toString("_lvl%d", (int) (level + 1)) + ".spell"); + } + } + } + } + // generate spell list with their ids + CConfigFile::CVar *spellListFile = cf.getVarPtr("spell_list_file"); + if (spellListFile) + { + generateSpellList(cf, outputPath + spellListFile->asString()); + } + nlinfo("Done"); + return 0; +} + diff --git a/code/ryzom/tools/server/build_world_packed_col/build_world_packed_col.cpp b/code/ryzom/tools/server/build_world_packed_col/build_world_packed_col.cpp index afe6db4cb..e7a1b2a33 100644 --- a/code/ryzom/tools/server/build_world_packed_col/build_world_packed_col.cpp +++ b/code/ryzom/tools/server/build_world_packed_col/build_world_packed_col.cpp @@ -1,435 +1,435 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "std_header.h" -// -#include "packed_world_builder.h" -#include "builder_config.h" -#include "zone_util.h" -// -#include "nel/misc/config_file.h" -#include "nel/misc/path.h" -#include "nel/misc/file.h" -#include "nel/misc/smart_ptr.h" -#include "nel/misc/command.h" -#include "nel/misc/debug.h" -#include "nel/misc/array_2d.h" -// -#include "nel/3d/packed_world.h" -#include "nel/3d/register_3d.h" -// -#include "game_share/scenario_entry_points.h" - - -using namespace NL3D; -using namespace NLMISC; -using namespace R2; - -NLMISC::CLog g_log; - -class CPackedWorldHolder : public NLMISC::CRefCount -{ -public: - CPackedWorld PW; -}; - -typedef NLMISC::CSmartPtr CPackedWorldSmartPtr; - -// get all the islands that are inside the given rect -static void getIslandsInside(sint32 xmin, sint32 xmax, sint32 ymin, sint32 ymax, std::vector &dest) -{ - dest.clear(); - R2::CScenarioEntryPoints &sep = R2::CScenarioEntryPoints::getInstance(); - uint numIslands = (uint)sep.getCompleteIslands().size(); - for(uint l = 0; l < numIslands; ++l) - { - const R2::CScenarioEntryPoints::CCompleteIsland &ci = sep.getCompleteIslands()[l]; - bool outside = (ci.XMin >= xmax || ci.XMax <= xmin || - ci.YMin >= ymax || ci.YMax <= ymin); - if (!outside) - { - dest.push_back(&ci); - } - } -} - -int main(int argc, char* argv[]) -{ - ////////////////// - createDebug(); - registerSerial3d(); - - if (argc != 2) - { - printf("usage : %s config_file_name.cfg\n", CFile::getFilename(argv[0]).c_str()); - return -1; - } - CConfigFile cf; - CBuilderConfig builderConfig; - // - try - { - cf.load(argv[1]); - } - catch(const EStream &) - { - nlwarning("Error while reading config file\n"); - return -1; - } - builderConfig.build(cf); - // build the cache / output directories if needed - if (!CFile::isExists(builderConfig.CWMapCachePath)) - { - CFile::createDirectory(builderConfig.CWMapCachePath); - } - // - if (!CFile::isExists(builderConfig.CachePath)) - { - CFile::createDirectory(builderConfig.CachePath); - } - // - if (!CFile::isExists(builderConfig.OutputPath)) - { - CFile::createDirectory(builderConfig.OutputPath); - } - // - for(uint k = 0; k < builderConfig.SearchPaths.size(); ++k) - { - CPath::addSearchPath(builderConfig.SearchPaths[k], true, false); - } - CPath::remapExtension("dds", "tga", true); - // - R2::CScenarioEntryPoints &sep = R2::CScenarioEntryPoints::getInstance(); - try - { - sep.loadCompleteIslands(); - } - catch(const NLMISC::EStream &) - { - return -1; - } - if (sep.getCompleteIslands().empty()) - { - nlwarning("No entry points found or read error in"); - return -1; - } - // - CPackedWorldBuilder builder; - std::vector islands; - std::vector startPositions; - uint numIslands = (uint)sep.getCompleteIslands().size(); - // - for(uint k = 0; k < numIslands; ++k) - { - std::vector zoneNames; - const R2::CScenarioEntryPoints::CCompleteIsland &ep = sep.getCompleteIslands()[k]; - std::string zoneMin = posToZoneName((float) ep.XMin, (float) ep.YMin); - std::string zoneMax = posToZoneName((float) ep.XMax, (float) ep.YMax); - sint zoneMinX, zoneMinY; - sint zoneMaxX, zoneMaxY; - nlverify(getZonePos(zoneMin, zoneMinX, zoneMinY)); - nlverify(getZonePos(zoneMax, zoneMaxX, zoneMaxY)); - for (sint y = zoneMinY; y <= zoneMaxY; ++y) - { - for (sint x = zoneMinX; x <= zoneMaxX; ++x) - { - zoneNames.push_back(posToZoneName(x * 160.f + 80.f, y * 160.f + 80.f) + ".zonel"); - } - } - // If the packed island already exists, load its header to know from which zones it was built - // This way, if the zones found in an island change it will get rebuilt - bool mustRebuild = true; - std::string islandPath = builderConfig.OutputPath + "/" + ep.Island + ".packed_island"; - CPackedWorld tmpPW; - if (CFile::fileExists(islandPath)) - { - try - { - CIFile f(islandPath); - tmpPW.serialZoneNames(f); - } - catch(const EStream &) - { - tmpPW.ZoneNames.clear(); - } - } - // now, see which zones really should be found in that island - std::vector presentZoneNames; - std::vector presentZonePathes; - for(uint l = 0; l < zoneNames.size(); ++l) - { - std::string zonePath = CPath::lookup(zoneNames[l], false, false); - if (!zonePath.empty()) - { - presentZonePathes.push_back(zonePath); - presentZoneNames.push_back(toLower(zoneNames[l])); - } - } - // - std::sort(tmpPW.ZoneNames.begin(), tmpPW.ZoneNames.end()); - std::sort(presentZoneNames.begin(), presentZoneNames.end()); - // - if (tmpPW.ZoneNames.size() == presentZoneNames.size() && - std::equal(tmpPW.ZoneNames.begin(), tmpPW.ZoneNames.end(), presentZoneNames.begin())) - { - // the same zones were found -> now check their dates against the island one - uint32 packedIslandDate = CFile::getFileModificationDate(islandPath); - mustRebuild = false; - for(uint l = 0; l < presentZonePathes.size(); ++l) - { - if (CFile::getFileModificationDate(presentZonePathes[l]) > packedIslandDate) - { - mustRebuild = true; - } - - } - } - // - CPackedWorldSmartPtr packedIsland = new CPackedWorldHolder; - if (!mustRebuild) - { - try - { - nlinfo("Loading island %s from cache (%d / %d)", ep.Island.c_str(), (int) k, (int) numIslands); - CIFile f(islandPath); - f.serial(packedIsland->PW); - } - catch(const EStream &) - { - mustRebuild = true; // damaged file or bad version ? -> force rebuild - delete packedIsland; // remove whatever was serialized - packedIsland = new CPackedWorldHolder; - } - } - - if (mustRebuild) - { - builder.build(zoneNames, builderConfig.CachePath, false, packedIsland->PW, builderConfig.RefineThreshold); - packedIsland->PW.ZoneNames = presentZoneNames; - // save the result - try - { - COFile f(islandPath); - f.serial(packedIsland->PW); - } - catch(const EStream &) - { - nlwarning("Island %s not saved.", ep.Island.c_str()); - } - } - islands.push_back(packedIsland); - CVector rayStart; - if (!ep.EntryPoints.empty()) - { - rayStart.set((float) ep.EntryPoints[0].X, (float) ep.EntryPoints[0].Y, 10000.f); - } - else - { - rayStart.set(0.5f * (ep.XMin + ep.XMax), 0.5f * (ep.YMin + ep.YMax), 10000.f); - } - //CVector rayEnd((float) ep.X, (float) ep.Y, -10000); - //CVector inter; - //if (packedIsland->PW.raytrace(rayStart, rayEnd, inter)) - //{ - //startPositions.push_back(inter); - //} - //else - //{ - rayStart.z = 300.f; - startPositions.push_back(rayStart); - //} - // TODO: add serialization here ... - // TODO: add a check to see if no zones are more recent -> in this case, do nothing. - // except if fly is wanted, in which case the packed version of the island should be reloaded. - } - - // For all cwmap, keep a file with its coordinates (we need to serialize them because else we must read the whole cwmap - // to retrieve those - for(uint k = 0; k < builderConfig.CWMapList.size(); ++k) - { - // here, the rebuild require that we reload the whole map - std::string cwMapPath = CPath::lookup(builderConfig.CWMapList[k], false, false); - if (cwMapPath.empty()) - { - nlwarning("Can't find %s, island height maps wont be updated"); - continue; - } - uint32 cwMapDate = CFile::getFileModificationDate(cwMapPath); - - std::string shortname = CFile::getFilenameWithoutExtension(builderConfig.CWMapList[k]); - bool mustRebuild = false; - sint32 xmin, xmax; - sint32 ymin, ymax; - try - { - CIFile f(builderConfig.CWMapCachePath + "/" + shortname + ".cw_height"); - f.serialCheck((uint32) 'OBSI'); - f.serial(xmin); - f.serial(xmax); - f.serial(ymin); - f.serial(ymax); - } - catch (const EStream &) - { - mustRebuild = true; - } - // - std::vector completeIslands; - if (!mustRebuild) - { - getIslandsInside(xmin, xmax, ymin, ymax, completeIslands); - for(uint l = 0; l < completeIslands.size(); ++l) - { - uint32 modifDate = CFile::getFileModificationDate(builderConfig.OutputPath + "/" + completeIslands[l]->Island + ".island_hm"); - if (modifDate < cwMapDate) - { - mustRebuild = true; - break; - } - } - } - // - if (mustRebuild) - { - try - { - std::vector args(1); - nlassert(ICommand::LocalCommands); - // set the output path - ICommand::TCommand::iterator commandIt; - commandIt = ICommand::LocalCommands->find("setOutputPath"); - //nlassert(commandIt != ICommand::LocalCommands->end()); - args[0] = builderConfig.CWMapCachePath + "/"; - commandIt->second->execute("", args, g_log, true); - // build the height map - commandIt = ICommand::LocalCommands->find("pacsBuildHeightMap16"); - nlassert(commandIt != ICommand::LocalCommands->end()); - args[0] = cwMapPath; - commandIt->second->execute("", args, g_log, true); - // now extract each island height - // read back coordinates - CIFile f(builderConfig.CWMapCachePath + "/" + shortname + ".cw_height"); - f.serialCheck((uint32) 'OBSI'); - f.serial(xmin); - f.serial(xmax); - f.serial(ymin); - f.serial(ymax); - CArray2D cwHeightMap; - f.serial(cwHeightMap); - // - getIslandsInside(xmin, xmax, ymin, ymax, completeIslands); - for(uint l = 0; l < completeIslands.size(); ++l) - { - nlwarning("Building heightmap for entry point %s", completeIslands[l]->Island.c_str()); - const R2::CScenarioEntryPoints::CCompleteIsland &ep = *completeIslands[l]; - if (ep.XMax == ep.XMin || ep.YMax == ep.YMin) - { - nlwarning("Bad dimensions for island %s, not building heightmap", ep.Island.c_str()); - } - else - { - CArray2D island; - island.init(ep.XMax - ep.XMin, ep.YMax - ep.YMin, 0x7fff); - // get result from global heightmap - island.blit(cwHeightMap, ep.XMin - xmin, ep.YMin - ymin, island.getWidth(), island.getHeight(), 0, 0); - // basic format for now ... - try - { - COFile f(builderConfig.OutputPath + "/" + completeIslands[l]->Island + ".island_hm"); - f.serialCheck((uint32) 'MHSI'); - f.serial(island); - // export tga for check - if (builderConfig.HeightMapsAsTga) - { - CBitmap tgaHM; - tgaHM.resize(island.getWidth(), island.getHeight()); - sint16 hMax = -32768; - sint16 hMin= 32767; - uint numPix = island.getWidth() * island.getHeight(); - for(CArray2D::iterator it = island.begin(); it != island.end(); ++it) - { - if (*it != 32767) - { - hMax = std::max(hMax, *it); - hMin = std::min(hMin, *it); - } - } - float scale = 255.f / favoid0((float) (hMax - hMin)); - float bias = (float) - hMin; - CRGBA *dest = (CRGBA *) &tgaHM.getPixels()[0]; - for(CArray2D::iterator it = island.begin(); it != island.end(); ++it) - { - if (*it == 0x7fff) - { - *dest++ = CRGBA::Magenta; - } - else - { - float height = scale * ((*it) + bias); - clamp(height, 0.f, 255.f); - *dest++ = CRGBA((uint8) height, (uint8) height, (uint8) height); - } - } - // - COFile f(builderConfig.OutputPath + "/" + completeIslands[l]->Island + "_height_map.tga"); - tgaHM.writeTGA(f, 0, true); - } - } - catch(const EStream &e) - { - e; // avoid compile warning - nlwarning(e.what()); - } - } - - } - } - catch (const Exception &e) - { - e; // avoid compile warning - nlwarning(e.what()); - } - } - } - // - if (builderConfig.Fly) - { - std::vector islandInfos; - for(uint k = 0; k < islands.size(); ++k) - { - CPackedWorldBuilder::CIslandInfo islandInfo; - const R2::CScenarioEntryPoints::CCompleteIsland &ci = sep.getCompleteIslands()[k]; - islandInfo.CornerMin.set((float) ci.XMin, (float) ci.YMin, 0.f); - islandInfo.CornerMax.set((float) ci.XMax, (float) ci.YMax, 0.f); - islandInfo.TexName = ci.Island + "_sp.tga"; - islandInfo.StartPosition = startPositions[k]; - islandInfo.PW = &(islands[k]->PW); - // The map is cropped because of power of 2 texture size limitation - // -> change UVScale accordingly - uint texWidth = (uint) ceilf(builderConfig.PixelPerMeter * (ci.XMax - ci.XMin)); - uint texHeight = (uint) ceilf(builderConfig.PixelPerMeter * (ci.YMax - ci.YMin)); - islandInfo.UScale = (float) texWidth / raiseToNextPowerOf2(texWidth); - islandInfo.VScale = (float) texHeight / raiseToNextPowerOf2(texHeight); - // - islandInfos.push_back(islandInfo); - } - builder.fly(islandInfos, builderConfig.CamSpeed); - } - -} - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "std_header.h" +// +#include "packed_world_builder.h" +#include "builder_config.h" +#include "zone_util.h" +// +#include "nel/misc/config_file.h" +#include "nel/misc/path.h" +#include "nel/misc/file.h" +#include "nel/misc/smart_ptr.h" +#include "nel/misc/command.h" +#include "nel/misc/debug.h" +#include "nel/misc/array_2d.h" +// +#include "nel/3d/packed_world.h" +#include "nel/3d/register_3d.h" +// +#include "game_share/scenario_entry_points.h" + + +using namespace NL3D; +using namespace NLMISC; +using namespace R2; + +NLMISC::CLog g_log; + +class CPackedWorldHolder : public NLMISC::CRefCount +{ +public: + CPackedWorld PW; +}; + +typedef NLMISC::CSmartPtr CPackedWorldSmartPtr; + +// get all the islands that are inside the given rect +static void getIslandsInside(sint32 xmin, sint32 xmax, sint32 ymin, sint32 ymax, std::vector &dest) +{ + dest.clear(); + R2::CScenarioEntryPoints &sep = R2::CScenarioEntryPoints::getInstance(); + uint numIslands = (uint)sep.getCompleteIslands().size(); + for(uint l = 0; l < numIslands; ++l) + { + const R2::CScenarioEntryPoints::CCompleteIsland &ci = sep.getCompleteIslands()[l]; + bool outside = (ci.XMin >= xmax || ci.XMax <= xmin || + ci.YMin >= ymax || ci.YMax <= ymin); + if (!outside) + { + dest.push_back(&ci); + } + } +} + +int main(int argc, char* argv[]) +{ + ////////////////// + createDebug(); + registerSerial3d(); + + if (argc != 2) + { + printf("usage : %s config_file_name.cfg\n", CFile::getFilename(argv[0]).c_str()); + return -1; + } + CConfigFile cf; + CBuilderConfig builderConfig; + // + try + { + cf.load(argv[1]); + } + catch(const EStream &) + { + nlwarning("Error while reading config file\n"); + return -1; + } + builderConfig.build(cf); + // build the cache / output directories if needed + if (!CFile::isExists(builderConfig.CWMapCachePath)) + { + CFile::createDirectory(builderConfig.CWMapCachePath); + } + // + if (!CFile::isExists(builderConfig.CachePath)) + { + CFile::createDirectory(builderConfig.CachePath); + } + // + if (!CFile::isExists(builderConfig.OutputPath)) + { + CFile::createDirectory(builderConfig.OutputPath); + } + // + for(uint k = 0; k < builderConfig.SearchPaths.size(); ++k) + { + CPath::addSearchPath(builderConfig.SearchPaths[k], true, false); + } + CPath::remapExtension("dds", "tga", true); + // + R2::CScenarioEntryPoints &sep = R2::CScenarioEntryPoints::getInstance(); + try + { + sep.loadCompleteIslands(); + } + catch(const NLMISC::EStream &) + { + return -1; + } + if (sep.getCompleteIslands().empty()) + { + nlwarning("No entry points found or read error in"); + return -1; + } + // + CPackedWorldBuilder builder; + std::vector islands; + std::vector startPositions; + uint numIslands = (uint)sep.getCompleteIslands().size(); + // + for(uint k = 0; k < numIslands; ++k) + { + std::vector zoneNames; + const R2::CScenarioEntryPoints::CCompleteIsland &ep = sep.getCompleteIslands()[k]; + std::string zoneMin = posToZoneName((float) ep.XMin, (float) ep.YMin); + std::string zoneMax = posToZoneName((float) ep.XMax, (float) ep.YMax); + sint zoneMinX, zoneMinY; + sint zoneMaxX, zoneMaxY; + nlverify(getZonePos(zoneMin, zoneMinX, zoneMinY)); + nlverify(getZonePos(zoneMax, zoneMaxX, zoneMaxY)); + for (sint y = zoneMinY; y <= zoneMaxY; ++y) + { + for (sint x = zoneMinX; x <= zoneMaxX; ++x) + { + zoneNames.push_back(posToZoneName(x * 160.f + 80.f, y * 160.f + 80.f) + ".zonel"); + } + } + // If the packed island already exists, load its header to know from which zones it was built + // This way, if the zones found in an island change it will get rebuilt + bool mustRebuild = true; + std::string islandPath = builderConfig.OutputPath + "/" + ep.Island + ".packed_island"; + CPackedWorld tmpPW; + if (CFile::fileExists(islandPath)) + { + try + { + CIFile f(islandPath); + tmpPW.serialZoneNames(f); + } + catch(const EStream &) + { + tmpPW.ZoneNames.clear(); + } + } + // now, see which zones really should be found in that island + std::vector presentZoneNames; + std::vector presentZonePathes; + for(uint l = 0; l < zoneNames.size(); ++l) + { + std::string zonePath = CPath::lookup(zoneNames[l], false, false); + if (!zonePath.empty()) + { + presentZonePathes.push_back(zonePath); + presentZoneNames.push_back(toLower(zoneNames[l])); + } + } + // + std::sort(tmpPW.ZoneNames.begin(), tmpPW.ZoneNames.end()); + std::sort(presentZoneNames.begin(), presentZoneNames.end()); + // + if (tmpPW.ZoneNames.size() == presentZoneNames.size() && + std::equal(tmpPW.ZoneNames.begin(), tmpPW.ZoneNames.end(), presentZoneNames.begin())) + { + // the same zones were found -> now check their dates against the island one + uint32 packedIslandDate = CFile::getFileModificationDate(islandPath); + mustRebuild = false; + for(uint l = 0; l < presentZonePathes.size(); ++l) + { + if (CFile::getFileModificationDate(presentZonePathes[l]) > packedIslandDate) + { + mustRebuild = true; + } + + } + } + // + CPackedWorldSmartPtr packedIsland = new CPackedWorldHolder; + if (!mustRebuild) + { + try + { + nlinfo("Loading island %s from cache (%d / %d)", ep.Island.c_str(), (int) k, (int) numIslands); + CIFile f(islandPath); + f.serial(packedIsland->PW); + } + catch(const EStream &) + { + mustRebuild = true; // damaged file or bad version ? -> force rebuild + delete packedIsland; // remove whatever was serialized + packedIsland = new CPackedWorldHolder; + } + } + + if (mustRebuild) + { + builder.build(zoneNames, builderConfig.CachePath, false, packedIsland->PW, builderConfig.RefineThreshold); + packedIsland->PW.ZoneNames = presentZoneNames; + // save the result + try + { + COFile f(islandPath); + f.serial(packedIsland->PW); + } + catch(const EStream &) + { + nlwarning("Island %s not saved.", ep.Island.c_str()); + } + } + islands.push_back(packedIsland); + CVector rayStart; + if (!ep.EntryPoints.empty()) + { + rayStart.set((float) ep.EntryPoints[0].X, (float) ep.EntryPoints[0].Y, 10000.f); + } + else + { + rayStart.set(0.5f * (ep.XMin + ep.XMax), 0.5f * (ep.YMin + ep.YMax), 10000.f); + } + //CVector rayEnd((float) ep.X, (float) ep.Y, -10000); + //CVector inter; + //if (packedIsland->PW.raytrace(rayStart, rayEnd, inter)) + //{ + //startPositions.push_back(inter); + //} + //else + //{ + rayStart.z = 300.f; + startPositions.push_back(rayStart); + //} + // TODO: add serialization here ... + // TODO: add a check to see if no zones are more recent -> in this case, do nothing. + // except if fly is wanted, in which case the packed version of the island should be reloaded. + } + + // For all cwmap, keep a file with its coordinates (we need to serialize them because else we must read the whole cwmap + // to retrieve those + for(uint k = 0; k < builderConfig.CWMapList.size(); ++k) + { + // here, the rebuild require that we reload the whole map + std::string cwMapPath = CPath::lookup(builderConfig.CWMapList[k], false, false); + if (cwMapPath.empty()) + { + nlwarning("Can't find %s, island height maps wont be updated"); + continue; + } + uint32 cwMapDate = CFile::getFileModificationDate(cwMapPath); + + std::string shortname = CFile::getFilenameWithoutExtension(builderConfig.CWMapList[k]); + bool mustRebuild = false; + sint32 xmin, xmax; + sint32 ymin, ymax; + try + { + CIFile f(builderConfig.CWMapCachePath + "/" + shortname + ".cw_height"); + f.serialCheck((uint32) 'OBSI'); + f.serial(xmin); + f.serial(xmax); + f.serial(ymin); + f.serial(ymax); + } + catch (const EStream &) + { + mustRebuild = true; + } + // + std::vector completeIslands; + if (!mustRebuild) + { + getIslandsInside(xmin, xmax, ymin, ymax, completeIslands); + for(uint l = 0; l < completeIslands.size(); ++l) + { + uint32 modifDate = CFile::getFileModificationDate(builderConfig.OutputPath + "/" + completeIslands[l]->Island + ".island_hm"); + if (modifDate < cwMapDate) + { + mustRebuild = true; + break; + } + } + } + // + if (mustRebuild) + { + try + { + std::vector args(1); + nlassert(ICommand::LocalCommands); + // set the output path + ICommand::TCommand::iterator commandIt; + commandIt = ICommand::LocalCommands->find("setOutputPath"); + //nlassert(commandIt != ICommand::LocalCommands->end()); + args[0] = builderConfig.CWMapCachePath + "/"; + commandIt->second->execute("", args, g_log, true); + // build the height map + commandIt = ICommand::LocalCommands->find("pacsBuildHeightMap16"); + nlassert(commandIt != ICommand::LocalCommands->end()); + args[0] = cwMapPath; + commandIt->second->execute("", args, g_log, true); + // now extract each island height + // read back coordinates + CIFile f(builderConfig.CWMapCachePath + "/" + shortname + ".cw_height"); + f.serialCheck((uint32) 'OBSI'); + f.serial(xmin); + f.serial(xmax); + f.serial(ymin); + f.serial(ymax); + CArray2D cwHeightMap; + f.serial(cwHeightMap); + // + getIslandsInside(xmin, xmax, ymin, ymax, completeIslands); + for(uint l = 0; l < completeIslands.size(); ++l) + { + nlwarning("Building heightmap for entry point %s", completeIslands[l]->Island.c_str()); + const R2::CScenarioEntryPoints::CCompleteIsland &ep = *completeIslands[l]; + if (ep.XMax == ep.XMin || ep.YMax == ep.YMin) + { + nlwarning("Bad dimensions for island %s, not building heightmap", ep.Island.c_str()); + } + else + { + CArray2D island; + island.init(ep.XMax - ep.XMin, ep.YMax - ep.YMin, 0x7fff); + // get result from global heightmap + island.blit(cwHeightMap, ep.XMin - xmin, ep.YMin - ymin, island.getWidth(), island.getHeight(), 0, 0); + // basic format for now ... + try + { + COFile f(builderConfig.OutputPath + "/" + completeIslands[l]->Island + ".island_hm"); + f.serialCheck((uint32) 'MHSI'); + f.serial(island); + // export tga for check + if (builderConfig.HeightMapsAsTga) + { + CBitmap tgaHM; + tgaHM.resize(island.getWidth(), island.getHeight()); + sint16 hMax = -32768; + sint16 hMin= 32767; + uint numPix = island.getWidth() * island.getHeight(); + for(CArray2D::iterator it = island.begin(); it != island.end(); ++it) + { + if (*it != 32767) + { + hMax = std::max(hMax, *it); + hMin = std::min(hMin, *it); + } + } + float scale = 255.f / favoid0((float) (hMax - hMin)); + float bias = (float) - hMin; + CRGBA *dest = (CRGBA *) &tgaHM.getPixels()[0]; + for(CArray2D::iterator it = island.begin(); it != island.end(); ++it) + { + if (*it == 0x7fff) + { + *dest++ = CRGBA::Magenta; + } + else + { + float height = scale * ((*it) + bias); + clamp(height, 0.f, 255.f); + *dest++ = CRGBA((uint8) height, (uint8) height, (uint8) height); + } + } + // + COFile f(builderConfig.OutputPath + "/" + completeIslands[l]->Island + "_height_map.tga"); + tgaHM.writeTGA(f, 0, true); + } + } + catch(const EStream &e) + { + e; // avoid compile warning + nlwarning(e.what()); + } + } + + } + } + catch (const Exception &e) + { + e; // avoid compile warning + nlwarning(e.what()); + } + } + } + // + if (builderConfig.Fly) + { + std::vector islandInfos; + for(uint k = 0; k < islands.size(); ++k) + { + CPackedWorldBuilder::CIslandInfo islandInfo; + const R2::CScenarioEntryPoints::CCompleteIsland &ci = sep.getCompleteIslands()[k]; + islandInfo.CornerMin.set((float) ci.XMin, (float) ci.YMin, 0.f); + islandInfo.CornerMax.set((float) ci.XMax, (float) ci.YMax, 0.f); + islandInfo.TexName = ci.Island + "_sp.tga"; + islandInfo.StartPosition = startPositions[k]; + islandInfo.PW = &(islands[k]->PW); + // The map is cropped because of power of 2 texture size limitation + // -> change UVScale accordingly + uint texWidth = (uint) ceilf(builderConfig.PixelPerMeter * (ci.XMax - ci.XMin)); + uint texHeight = (uint) ceilf(builderConfig.PixelPerMeter * (ci.YMax - ci.YMin)); + islandInfo.UScale = (float) texWidth / raiseToNextPowerOf2(texWidth); + islandInfo.VScale = (float) texHeight / raiseToNextPowerOf2(texHeight); + // + islandInfos.push_back(islandInfo); + } + builder.fly(islandInfos, builderConfig.CamSpeed); + } + +} + + + diff --git a/code/ryzom/tools/server/build_world_packed_col/builder_config.cpp b/code/ryzom/tools/server/build_world_packed_col/builder_config.cpp index cd33b10c5..32778a8c2 100644 --- a/code/ryzom/tools/server/build_world_packed_col/builder_config.cpp +++ b/code/ryzom/tools/server/build_world_packed_col/builder_config.cpp @@ -1,108 +1,108 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "std_header.h" -// -#include "builder_config.h" -// -#include "nel/misc/config_file.h" - -using namespace NLMISC; - -//************************************************************************* -CBuilderConfig::CBuilderConfig() -{ - CachePath = "island_packed_zones_cache"; - CWMapCachePath = "island_cwmap_cache"; - OutputPath = "islands_col_meshes"; - CamSpeed = 100; - Fly = false; - HeightMapsAsTga = false; - PixelPerMeter = 1.f; - RefineThreshold = 8.f; -} - -//************************************************************************* -void CBuilderConfig::build(NLMISC::CConfigFile &cf) -{ - CConfigFile::CVar *cachePathVar = cf.getVarPtr("CachePath"); - if (cachePathVar) - { - CachePath = cachePathVar->asString(); - } - // - CConfigFile::CVar *cwMapCachePathVar = cf.getVarPtr("CWMapCachePath"); - if (cwMapCachePathVar) - { - CWMapCachePath = cwMapCachePathVar->asString(); - } - // - CConfigFile::CVar *outputPathVar = cf.getVarPtr("OutputPath"); - if (outputPathVar) - { - OutputPath = outputPathVar->asString(); - } - // - CConfigFile::CVar *searchPathsVar = cf.getVarPtr("SearchPaths"); - if (searchPathsVar) - { - SearchPaths.resize(searchPathsVar->size()); - for(sint k = 0; k < (sint)searchPathsVar->size(); ++k) - { - SearchPaths[k] = searchPathsVar->asString(k); - } - } - // - CConfigFile::CVar *cwMapListVar = cf.getVarPtr("CWMapList"); - if (cwMapListVar) - { - CWMapList.resize(cwMapListVar->size()); - for(sint k = 0; k < (sint)cwMapListVar->size(); ++k) - { - CWMapList[k] = cwMapListVar->asString(k); - } - } - // - CConfigFile::CVar *camSpeedVar = cf.getVarPtr("CamSpeed"); - if (camSpeedVar) - { - CamSpeed = camSpeedVar->asFloat(); - } - // - CConfigFile::CVar *flyVar = cf.getVarPtr("Fly"); - if (flyVar) - { - Fly = flyVar->asBool(); - } - // - CConfigFile::CVar *heightMapAsTgaVar = cf.getVarPtr("HeightMapsAsTga"); - if (heightMapAsTgaVar) - { - HeightMapsAsTga = heightMapAsTgaVar->asBool(); - } - // - CConfigFile::CVar *pixelPerMeterVar = cf.getVarPtr("PixelPerMeter"); - if (pixelPerMeterVar) - { - PixelPerMeter = pixelPerMeterVar->asFloat(); - } - // - CConfigFile::CVar *refineThresholdVar = cf.getVarPtr("RefineThreshold"); - if (refineThresholdVar) - { - RefineThreshold = refineThresholdVar->asFloat(); - } -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "std_header.h" +// +#include "builder_config.h" +// +#include "nel/misc/config_file.h" + +using namespace NLMISC; + +//************************************************************************* +CBuilderConfig::CBuilderConfig() +{ + CachePath = "island_packed_zones_cache"; + CWMapCachePath = "island_cwmap_cache"; + OutputPath = "islands_col_meshes"; + CamSpeed = 100; + Fly = false; + HeightMapsAsTga = false; + PixelPerMeter = 1.f; + RefineThreshold = 8.f; +} + +//************************************************************************* +void CBuilderConfig::build(NLMISC::CConfigFile &cf) +{ + CConfigFile::CVar *cachePathVar = cf.getVarPtr("CachePath"); + if (cachePathVar) + { + CachePath = cachePathVar->asString(); + } + // + CConfigFile::CVar *cwMapCachePathVar = cf.getVarPtr("CWMapCachePath"); + if (cwMapCachePathVar) + { + CWMapCachePath = cwMapCachePathVar->asString(); + } + // + CConfigFile::CVar *outputPathVar = cf.getVarPtr("OutputPath"); + if (outputPathVar) + { + OutputPath = outputPathVar->asString(); + } + // + CConfigFile::CVar *searchPathsVar = cf.getVarPtr("SearchPaths"); + if (searchPathsVar) + { + SearchPaths.resize(searchPathsVar->size()); + for(sint k = 0; k < (sint)searchPathsVar->size(); ++k) + { + SearchPaths[k] = searchPathsVar->asString(k); + } + } + // + CConfigFile::CVar *cwMapListVar = cf.getVarPtr("CWMapList"); + if (cwMapListVar) + { + CWMapList.resize(cwMapListVar->size()); + for(sint k = 0; k < (sint)cwMapListVar->size(); ++k) + { + CWMapList[k] = cwMapListVar->asString(k); + } + } + // + CConfigFile::CVar *camSpeedVar = cf.getVarPtr("CamSpeed"); + if (camSpeedVar) + { + CamSpeed = camSpeedVar->asFloat(); + } + // + CConfigFile::CVar *flyVar = cf.getVarPtr("Fly"); + if (flyVar) + { + Fly = flyVar->asBool(); + } + // + CConfigFile::CVar *heightMapAsTgaVar = cf.getVarPtr("HeightMapsAsTga"); + if (heightMapAsTgaVar) + { + HeightMapsAsTga = heightMapAsTgaVar->asBool(); + } + // + CConfigFile::CVar *pixelPerMeterVar = cf.getVarPtr("PixelPerMeter"); + if (pixelPerMeterVar) + { + PixelPerMeter = pixelPerMeterVar->asFloat(); + } + // + CConfigFile::CVar *refineThresholdVar = cf.getVarPtr("RefineThreshold"); + if (refineThresholdVar) + { + RefineThreshold = refineThresholdVar->asFloat(); + } +} diff --git a/code/ryzom/tools/server/build_world_packed_col/builder_config.h b/code/ryzom/tools/server/build_world_packed_col/builder_config.h index 1c2532319..86fa380b0 100644 --- a/code/ryzom/tools/server/build_world_packed_col/builder_config.h +++ b/code/ryzom/tools/server/build_world_packed_col/builder_config.h @@ -1,45 +1,45 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef _BUILDER_CONFIG_H -#define _BUILDER_CONFIG_H - - -namespace NLMISC -{ - class CConfigFile; -} - -class CBuilderConfig -{ -public: - std::string CachePath; - std::string OutputPath; - std::vector SearchPaths; - std::vector CWMapList; - std::string CWMapCachePath; - float CamSpeed; - bool Fly; - bool HeightMapsAsTga; - float PixelPerMeter; - float RefineThreshold; -public: - CBuilderConfig(); - void build(NLMISC::CConfigFile &cf); -}; - - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef _BUILDER_CONFIG_H +#define _BUILDER_CONFIG_H + + +namespace NLMISC +{ + class CConfigFile; +} + +class CBuilderConfig +{ +public: + std::string CachePath; + std::string OutputPath; + std::vector SearchPaths; + std::vector CWMapList; + std::string CWMapCachePath; + float CamSpeed; + bool Fly; + bool HeightMapsAsTga; + float PixelPerMeter; + float RefineThreshold; +public: + CBuilderConfig(); + void build(NLMISC::CConfigFile &cf); +}; + + +#endif diff --git a/code/ryzom/tools/server/build_world_packed_col/packed_world_builder.cpp b/code/ryzom/tools/server/build_world_packed_col/packed_world_builder.cpp index 4d083ea84..d08982ae4 100644 --- a/code/ryzom/tools/server/build_world_packed_col/packed_world_builder.cpp +++ b/code/ryzom/tools/server/build_world_packed_col/packed_world_builder.cpp @@ -1,672 +1,672 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "std_header.h" -// -#include "packed_world_builder.h" -#include "zone_util.h" -// -#include "nel/misc/array_2d.h" -#include "nel/misc/config_file.h" -#include "nel/misc/path.h" -#include "nel/misc/file.h" -#include "nel/misc/vector_2f.h" -#include "nel/misc/triangle.h" -#include "nel/misc/polygon.h" -#include "nel/misc/smart_ptr.h" -#include "nel/misc/quad.h" -// -#include "nel/3d/frustum.h" -#include "nel/3d/viewport.h" -#include "nel/3d/scissor.h" -#include "nel/misc/aabbox.h" -#include "nel/misc/stream.h" -// -#include "nel/3d/landscape.h" -#include "nel/3d/zone.h" -#include "nel/3d/quad_grid.h" -#include "nel/3d/event_mouse_listener.h" -#include "nel/3d/vertex_buffer.h" -#include "nel/3d/material.h" -#include "nel/3d/nelu.h" -#include "nel/3d/scene_group.h" -#include "nel/3d/shape_info.h" -#include "nel/3d/packed_zone.h" -#include "nel/3d/packed_world.h" -#include "nel/3d/texture_file.h" -// -using namespace NL3D; -using namespace NLMISC; - - -static inline void pushVBQuad(NLMISC::CVector *&dest, const NLMISC::CQuad &quad) -{ - *dest++ = quad.V0; - *dest++ = quad.V1; - *dest++ = quad.V2; - *dest++ = quad.V3; -} - - -class CZoneRefCount : public CRefCount -{ -public: - CZone Zone; - bool Loaded; - std::string Path; - std::string IGPath; - sint X; - sint Y; -public: - CZoneRefCount() : Loaded(false) {} -}; - - -static void viewportToScissor(const CViewport &vp, CScissor &scissor) -{ - scissor.X = vp.getX(); - scissor.Y = vp.getY(); - scissor.Width = vp.getWidth(); - scissor.Height = vp.getHeight(); -} - - -class CRemoveBorderLeavePred -{ -public: - CRemoveBorderLeavePred(uint16 zoneId) : ZoneId(zoneId) {} - bool operator()(const CTessFace *tf) const - { - return tf->Patch->getZone()->getZoneId() != ZoneId; - } - uint16 ZoneId; -}; - - -//******************************************************************************************************************** -void CPackedWorldBuilder::build(const std::vector &zoneNames, const std::string &cachePath, bool addLandscapeIG, CPackedWorld &dest, float refineTheshold) -{ - std::vector > zones; - zones.reserve(zoneNames.size()); - sint zoneMinX = 0; - sint zoneMaxX = 0; - sint zoneMinY = 0; - sint zoneMaxY = 0; - bool firstZoneCorner = true; - for(uint k = 0; k < zoneNames.size(); ++k) - { - CSmartPtr zoneRef = new CZoneRefCount; - zoneRef->Path = zoneNames[k]; - if (addLandscapeIG) - { - std::string igFileName = CFile::getFilenameWithoutExtension(zoneRef->Path) + ".ig"; - zoneRef->IGPath = CPath::lookup(igFileName, false, false); - if (zoneRef->IGPath.empty()) - { - nlwarning("Couldn't find ig %s. Maybe there's no ig for that zone.", igFileName.c_str()); - } - } - CVector2f zoneCornerMin, zoneCornerMax; - if (getZonePos(zoneNames[k], zoneRef->X, zoneRef->Y)) - { - if (firstZoneCorner) - { - zoneMinX = zoneMaxX = zoneRef->X; - zoneMinY = zoneMaxY = zoneRef->Y; - firstZoneCorner = false; - } - else - { - zoneMinX = std::min(zoneMinX, zoneRef->X); - zoneMaxX = std::max(zoneMaxX, zoneRef->X); - zoneMinY = std::min(zoneMinY, zoneRef->Y); - zoneMaxY = std::max(zoneMaxY, zoneRef->Y); - } - zones.push_back(zoneRef); - } - } - if (zones.empty()) - { - nlwarning("No zones loaded"); - return; - } - uint gridWidth = zoneMaxX - zoneMinX + 1; - uint gridHeight = zoneMaxY - zoneMinY + 1; - // build a grid of zones - CArray2D zoneGrid; - CArray2D packedZoneGrid; - zoneGrid.init(gridWidth, gridHeight, NULL); - packedZoneGrid.init(gridWidth, gridHeight); - for(uint k = 0; k < zones.size(); ++k) - { - sint x = zones[k]->X - zoneMinX; - sint y = zones[k]->Y - zoneMinY; - zoneGrid(x, y) = zones[k]; - } - // build grid for tris - CVector2f cornerMin, cornerMax; - cornerMin.set(zoneMinX * 160.f, zoneMinY * 160.f); - cornerMax.set((zoneMaxX + 1) * 160.f, (zoneMaxY + 1) * 160.f); - const float CELL_SIZE = 4.f; // resolution of tri grid - - /* - CVillageGrid vg; - vg.init(gridWidth, gridHeight, zoneMinX, zoneMinY); - - - std::vector continentList; - CConfigFile::CVar *worldSheetPtr = cf.getVarPtr("WorldSheet"); - if (!(worldSheetPtr && loadContinentList(worldSheetPtr->asString(), continentList))) - { - CConfigFile::CVar *continentSheetNames = cf.getVarPtr("ContinentSheetNames"); - std::vector > igs; - if (!continentSheetNames) - { - nlwarning("No villages added to collisions"); - } - else - { - for(uint k = 0; k < (uint) continentSheetNames->size(); ++k) - { - continentList.push_back(continentSheetNames->asString(k)); - } - } - } - - bool addVillages = true; - CConfigFile::CVar *addVillagesVar = cf.getVarPtr("AddVillages"); - if (addVillagesVar) - { - addVillages = addVillagesVar->asBool(); - } - if (addVillages) - { - for(uint k = 0; k < (uint) continentList.size(); ++k) - { - vg.addVillagesFromContinent(continentList[k]); - } - } - */ - - TShapeCache shapeCache; - - - - // build each zone separatly - static std::vector leaves; - uint currZoneIndex = 0; - for (sint y = 0; y < (sint) zoneGrid.getHeight(); ++y) - { - for (sint x = 0; x < (sint) zoneGrid.getWidth(); ++x) - { - if (zoneGrid(x, y)) - { - std::string cacheFilename = CPath::standardizePath(cachePath) + CFile::getFilenameWithoutExtension(zoneGrid(x, y)->Path) + ".packed_zone"; - bool mustRebuild = false; - - // if there's any village on this zone that is more recent than the zone, then must rebuild the zone - /* - { - const std::list &villageList = vg.VillageGrid(x, y); - for(std::list::const_iterator it = villageList.begin(); it != villageList.end(); ++it) - { - uint32 modifDate = vg.Villages[*it].FileModificationDate; - uint32 cacheDate = CFile::getFileModificationDate(cacheFilename); - if (modifDate > cacheDate) - { - mustRebuild = true; - break; - } - } - }*/ - - // if landscape ig is reclaimed, see if it is more recent - if (!zoneGrid(x, y)->IGPath.empty()) - { - if (CFile::getFileModificationDate(zoneGrid(x, y)->IGPath) >= CFile::getFileModificationDate(cacheFilename)) - { - mustRebuild = true; - } - } - - if (!mustRebuild) - { - mustRebuild = true; - // see if zone is present in cache and is valid - if (CFile::getFileModificationDate(cacheFilename) >= CFile::getFileModificationDate(zoneGrid(x, y)->Path)) - { - // try to retrieve file from cache - try - { - CIFile f; - if (f.open(cacheFilename)) - { - CPackedZoneBase *pb = NULL; - f.serialPolyPtr(pb); - packedZoneGrid(x, y) = pb; - mustRebuild = false; - nlinfo("Retrieving zone %d / %d from cache\n", (int) currZoneIndex + 1, (int) zones.size()); - } - } - catch(const EStream &) - { - } - } - } - - if (mustRebuild) - { - nlinfo("Rebuilding zone %d / %d \n", (int) currZoneIndex + 1, (int) zones.size()); - CLandscape *landscape = new CLandscape; - landscape->init(); - landscape->setThreshold (refineTheshold / (1000.f * 1000.f)); - //landscape->setThreshold(0); - landscape->setTileMaxSubdivision (0); - // add wanted zones & all zones around for continuity - for (sint ly = y - 1; ly <= y + 1; ++ly) - { - if (ly < 0) continue; - if (ly >= (sint) gridHeight) break; - for (sint lx = x - 1; lx <= x + 1; ++lx) - { - if (lx < 0) continue; - if (lx >= (sint) gridWidth) break; - if (zoneGrid(lx, ly)) - { - if (!zoneGrid(lx, ly)->Loaded) - { - - try - { - CIFile stream(CPath::lookup(zoneGrid(lx, ly)->Path)); - zoneGrid(lx, ly)->Zone.serial(stream); - zoneGrid(lx, ly)->Loaded = true; - } - catch(const Exception &) - { - nlwarning("Error while loading zone %s : zone not loaded \n", zoneGrid(lx, ly)->Path.c_str()); - } - } - if (zoneGrid(lx, ly)->Loaded) - { - landscape->addZone(zoneGrid(lx, ly)->Zone); - } - } - } - } - // - landscape->refineAll(CVector((x + zoneMinX) * 160.f + 80.f, (y + zoneMinY) * 160.f + 80.f, 1000.f)); - // - // Dump tesselated triangles - leaves.clear(); - landscape->getTessellationLeaves(leaves); - leaves.erase(std::remove_if(leaves.begin(), leaves.end(), CRemoveBorderLeavePred(zoneGrid(x, y)->Zone.getZoneId())), leaves.end()); - // gather and load list of villages ig - std::vector igs; - /*if (addVillages) - { - const std::list &villageList = vg.VillageGrid(x, y); - for(std::list::const_iterator it = villageList.begin(); it != villageList.end(); ++it) - { - CVillage &village = vg.Villages[*it]; - village.load(shapeCache); // load if needed - for(uint k = 0; k < village.IG.size(); ++k) - { - if (village.IG[k].IG) - { - igs.push_back(village.IG[k].IG); - } - } - } - }*/ - // - CAABBox baseZoneBBox; - CVector zoneMinCorner((x + zoneMinX) * 160.f, (y + zoneMinY) * 160.f, 0.f); - baseZoneBBox.setMinMax(zoneMinCorner, zoneMinCorner + CVector(160.f, 160.f, 1.f)); - CSmartPtr pz32 = new CPackedZone32; - // - pz32->build(leaves, CELL_SIZE, igs, shapeCache, baseZoneBBox, (sint32) (x + zoneMinX), (sint32) (y + zoneMinY)); - // - // try to convert to 16 bit indices to save some place - CSmartPtr pz16 = pz32->buildPackedZone16(); - if (pz16) - { - packedZoneGrid(x, y) = pz16; - } - else - { - packedZoneGrid(x, y) = pz32; - } - // write result in cache - try - { - if (!CFile::isExists(cachePath)) - { - CFile::createDirectoryTree(cachePath); - } - COFile f; - f.open(cacheFilename); - CPackedZoneBase *pb = packedZoneGrid(x, y); - f.serialPolyPtr(pb); - } - catch(const EStream &e) - { - printf("Error while writing packed zone to cache : \n %s \n", e.what()); - } - // - delete landscape; - } - ++ currZoneIndex; - } - } - } - zoneGrid.clear(); - shapeCache.clear(); - - - std::vector packedZonesArray; - for (sint y = 0; y < (sint) packedZoneGrid.getHeight(); ++y) - { - for (sint x = 0; x < (sint) packedZoneGrid.getWidth(); ++x) - { - if (packedZoneGrid(x, y)) - { - packedZonesArray.push_back(packedZoneGrid(x, y)); - } - } - } - - // build packed world - dest.build(packedZonesArray); -} - - -//******************************************************************************************************************** -void CPackedWorldBuilder::fly(std::vector &islands, float camSpeed) -{ - nlassert(!islands.empty()); - // fly into scene - try - { - CNELU::init(1024, 768, CViewport(), 32, true, NULL, false, true); - } - catch(const Exception &e) - { - nlwarning(e.what()); - return; - } - // - CFrustum frust; - frust.init(-0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 1500.f, 1); - // - - CMatrix camMat; - // - IDriver *driver = CNELU::Driver; - CEvent3dMouseListener mouseListener; - mouseListener.setMouseMode(U3dMouseListener::firstPerson); - mouseListener.setFrustrum(frust); - mouseListener.addToServer(CNELU::EventServer); - mouseListener.setSpeed(camSpeed); - CVertexBuffer vb; - vb.setVertexFormat(CVertexBuffer::PositionFlag); - vb.setPreferredMemory(CVertexBuffer::AGPVolatile, false); - // - CMaterial material; - material.initUnlit(); - material.setDoubleSided(true); - material.setZFunc(CMaterial::lessequal); - CMaterial wiredMaterial; - wiredMaterial.initUnlit(); - wiredMaterial.setDoubleSided(true); - wiredMaterial.setZFunc(CMaterial::lessequal); - wiredMaterial.setColor(CRGBA(255, 255, 255, 250)); - wiredMaterial.texEnvOpAlpha(0, CMaterial::Replace); - wiredMaterial.texEnvArg0Alpha(0, CMaterial::Diffuse, CMaterial::SrcAlpha); - wiredMaterial.setBlend(true); - wiredMaterial.setBlendFunc(CMaterial::srcalpha, CMaterial::invsrcalpha); - CMaterial texturedMaterial; - texturedMaterial.initUnlit(); - texturedMaterial.setDoubleSided(true); - texturedMaterial.setZFunc(CMaterial::lessequal); - // - uint currWorldIndex = ~0; - bool newPosWanted = true; - // - std::vector zones; - // - CMaterial *zoneMat = NULL; - do - { - if (newPosWanted) - { - currWorldIndex = (currWorldIndex + 1) % islands.size(); - const CIslandInfo &island = islands[currWorldIndex]; - camMat.identity(); - camMat.setPos(island.StartPosition); - mouseListener.setMatrix(camMat); - nlassert(island.PW); - islands[currWorldIndex].PW->getZones(zones); - nlwarning("zone = %s \n", posToZoneName(camMat.getPos().x, camMat.getPos().y).c_str()); - newPosWanted = false; - // setup material with projected texture if there's one - if (island.TexName.empty()) - { - zoneMat = &material; - } - else - { - zoneMat = &texturedMaterial; - // just add a projected texture - CTextureFile *newTex = new CTextureFile(island.TexName); - newTex->setWrapS(ITexture::Clamp); - newTex->setWrapT(ITexture::Clamp); - texturedMaterial.setTexture(0, newTex); - texturedMaterial.texEnvOpRGB(0, CMaterial::Replace); - texturedMaterial.texEnvArg0RGB(0, CMaterial::Texture, CMaterial::SrcColor); - texturedMaterial.setTexCoordGen(0, true); - texturedMaterial.setTexCoordGenMode(0, CMaterial::TexCoordGenObjectSpace); - CMatrix mat; - CVector scale = island.CornerMax - island.CornerMin; - scale.x = 1.f / favoid0(scale.x); - scale.y = 1.f / favoid0(scale.y); - scale.z = 0.f; - mat.setScale(scale); - mat.setPos(CVector(- island.CornerMin.x * scale.x, - island.CornerMin.y * scale.y, 0.f)); - // - CMatrix uvScaleMat; - // - uvScaleMat.setScale(CVector(island.UScale, - island.VScale, 0.f)); - uvScaleMat.setPos(CVector(0.f, island.VScale, 0.f)); - // - texturedMaterial.enableUserTexMat(0, true); - texturedMaterial.setUserTexMat(0, uvScaleMat * mat); - } - } - const CRGBA clearColor = CRGBA(0, 0, 127, 0); - driver->enableFog(true); - driver->setupFog(frust.Far * 0.8f, frust.Far, clearColor); - CViewport vp; - vp.init(0.f, 0.f, 1.f, 1.f); - driver->setupViewport(vp); - CScissor scissor; - viewportToScissor(vp, scissor); - driver->setupScissor(scissor); - - CNELU::EventServer.pump(); - camMat = mouseListener.getViewMatrix(); - // - driver->clear2D(clearColor); - driver->clearZBuffer(); - // - driver->setFrustum(frust.Left, frust.Right, frust.Bottom, frust.Top, frust.Near, frust.Far, frust.Perspective); - driver->setupViewMatrix(camMat.inverted()); - driver->setupModelMatrix(CMatrix::Identity); - // - // - const CVector localFrustCorners[8] = - { - CVector(frust.Left, frust.Near, frust.Top), - CVector(frust.Right, frust.Near, frust.Top), - CVector(frust.Right, frust.Near, frust.Bottom), - CVector(frust.Left, frust.Near, frust.Bottom), - CVector(frust.Left * frust.Far / frust.Near, frust.Far, frust.Top * frust.Far / frust.Near), - CVector(frust.Right * frust.Far / frust.Near, frust.Far, frust.Top * frust.Far / frust.Near), - CVector(frust.Right * frust.Far / frust.Near, frust.Far, frust.Bottom * frust.Far / frust.Near), - CVector(frust.Left * frust.Far / frust.Near, frust.Far, frust.Bottom * frust.Far / frust.Near) - }; - // roughly compute covered zones - // - /* - sint frustZoneMinX = INT_MAX; - sint frustZoneMaxX = INT_MIN; - sint frustZoneMinY = INT_MAX; - sint frustZoneMaxY = INT_MIN; - for(uint k = 0; k < sizeofarray(localFrustCorners); ++k) - { - CVector corner = camMat * localFrustCorners[k]; - sint zoneX = (sint) (corner.x / 160.f) - zoneMinX; - sint zoneY = (sint) floorf(corner.y / 160.f) - zoneMinY; - frustZoneMinX = std::min(frustZoneMinX, zoneX); - frustZoneMinY = std::min(frustZoneMinY, zoneY); - frustZoneMaxX = std::max(frustZoneMaxX, zoneX); - frustZoneMaxY = std::max(frustZoneMaxY, zoneY); - } - */ - - const uint TRI_BATCH_SIZE = 10000; // batch size for rendering - - - for(uint k = 0; k < zones.size(); ++k) - { - zones[k]->render(vb, *driver, *zoneMat, wiredMaterial, camMat, TRI_BATCH_SIZE, localFrustCorners); - } - - driver->setPolygonMode(IDriver::Filled); - material.setColor(CRGBA::Green); - // compute intersection with landscape & display a dot at that position - CVector lookAtPos = camMat.getPos() + 1000.f * camMat.getJ(); - CVector inter; - static std::vector triList; - triList.clear(); - bool interFound = islands[currWorldIndex].PW->raytrace(camMat.getPos(), lookAtPos, inter, &triList); - if (!triList.empty()) - { - vb.setNumVertices(3 * (uint32)triList.size()); - CVertexBufferReadWrite vba; - vb.lock(vba); - CVector *dest = vba.getVertexCoordPointer(0); - memcpy(dest, &triList[0], sizeof(CTriangle) * triList.size()); - vba.unlock(); - driver->activeVertexBuffer(vb); - driver->renderRawTriangles(material, 0, (uint32)triList.size()); - } - if (interFound) - { - material.setColor(CRGBA::Magenta); - CQuad q; - q.V0 = inter - camMat.getI() + camMat.getK(); - q.V1 = inter + camMat.getI() + camMat.getK(); - q.V2 = inter + camMat.getI() - camMat.getK(); - q.V3 = inter - camMat.getI() - camMat.getK(); - { - vb.setNumVertices(4); - CVertexBufferReadWrite vba; - vb.lock(vba); - CVector *dest = vba.getVertexCoordPointer(0); - pushVBQuad(dest, q); - vba.unlock(); - } - driver->activeVertexBuffer(vb); - driver->renderRawQuads(material, 0, 1); - } - // - /* - uint NUM_RAYS = 10000; - if (CNELU::AsyncListener.isKeyPushed(KeyT)) - { - printf("Starting raytracing test 1"); - uint numHits = 0; - NLMISC::TTime startTime = CTime::getLocalTime(); - for(uint k = 0; k < NUM_RAYS; ++k) - { - sint zone = rand() % packedZonesArray.size(); - CPackedZoneBase *zonePtr = packedZonesArray[zone]; - CVector cornerMin = zonePtr->Box.getMin(); - CVector cornerMax = zonePtr->Box.getMax(); - CVector start(frand(1.f) * (cornerMax.x - cornerMin.x) + cornerMin.x, - frand(1.f) * (cornerMax.y - cornerMin.y) + cornerMin.y, - frand(1.f) * (cornerMax.z - cornerMin.z) + cornerMin.z); - CVector end(frand(1.f) * (cornerMax.x - cornerMin.x) + cornerMin.x, - frand(1.f) * (cornerMax.y - cornerMin.y) + cornerMin.y, - frand(1.f) * (cornerMax.z - cornerMin.z) + cornerMin.z); - CVector inter; - bool result = pw.raytrace(start, end, inter); - if (result) - { - ++numHits; - } - } - NLMISC::TTime endTime = CTime::getLocalTime(); - - float dt = (float) (endTime - startTime) / 1000.f; - printf("Total time = %.2f s\n", dt); - printf("Num rays = %d\n", (int) NUM_RAYS); - printf("Num hits = %d\n", (int) numHits); - printf("Num test per seconds = %.2f\n", (float) NUM_RAYS / dt); - } - */ - // - /* - if (CNELU::AsyncListener.isKeyPushed(KeyU)) - { - printf("Starting raytracing test 2"); - uint numHits = 0; - NLMISC::TTime startTime = CTime::getLocalTime(); - for(uint k = 0; k < NUM_RAYS; ++k) - { - CVector start = camMat.getPos(); - CVector end(start.x + (frand(200.f) - 100.f), - start.y + (frand(200.f) - 100.f), - start.z + (frand(5.f) - 2.5f)); - CVector inter; - bool result = pw.raytrace(start, end, inter); - if (result) - { - ++numHits; - } - } - NLMISC::TTime endTime = CTime::getLocalTime(); - - float dt = (float) (endTime - startTime) / 1000.f; - printf("Total time = %.2f s\n", dt); - printf("Num rays = %d\n", (int) NUM_RAYS); - printf("Num hits = %d\n", (int) numHits); - printf("Num test per seconds = %.2f\n", (float) NUM_RAYS / dt); - } - */ - if (CNELU::AsyncListener.isKeyPushed(KeyN)) - { - newPosWanted = true; - } - // - driver->setPolygonMode(IDriver::Filled); - // - driver->swapBuffers(); - } - while(!CNELU::AsyncListener.isKeyPushed(KeyESCAPE)); - // -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "std_header.h" +// +#include "packed_world_builder.h" +#include "zone_util.h" +// +#include "nel/misc/array_2d.h" +#include "nel/misc/config_file.h" +#include "nel/misc/path.h" +#include "nel/misc/file.h" +#include "nel/misc/vector_2f.h" +#include "nel/misc/triangle.h" +#include "nel/misc/polygon.h" +#include "nel/misc/smart_ptr.h" +#include "nel/misc/quad.h" +// +#include "nel/3d/frustum.h" +#include "nel/3d/viewport.h" +#include "nel/3d/scissor.h" +#include "nel/misc/aabbox.h" +#include "nel/misc/stream.h" +// +#include "nel/3d/landscape.h" +#include "nel/3d/zone.h" +#include "nel/3d/quad_grid.h" +#include "nel/3d/event_mouse_listener.h" +#include "nel/3d/vertex_buffer.h" +#include "nel/3d/material.h" +#include "nel/3d/nelu.h" +#include "nel/3d/scene_group.h" +#include "nel/3d/shape_info.h" +#include "nel/3d/packed_zone.h" +#include "nel/3d/packed_world.h" +#include "nel/3d/texture_file.h" +// +using namespace NL3D; +using namespace NLMISC; + + +static inline void pushVBQuad(NLMISC::CVector *&dest, const NLMISC::CQuad &quad) +{ + *dest++ = quad.V0; + *dest++ = quad.V1; + *dest++ = quad.V2; + *dest++ = quad.V3; +} + + +class CZoneRefCount : public CRefCount +{ +public: + CZone Zone; + bool Loaded; + std::string Path; + std::string IGPath; + sint X; + sint Y; +public: + CZoneRefCount() : Loaded(false) {} +}; + + +static void viewportToScissor(const CViewport &vp, CScissor &scissor) +{ + scissor.X = vp.getX(); + scissor.Y = vp.getY(); + scissor.Width = vp.getWidth(); + scissor.Height = vp.getHeight(); +} + + +class CRemoveBorderLeavePred +{ +public: + CRemoveBorderLeavePred(uint16 zoneId) : ZoneId(zoneId) {} + bool operator()(const CTessFace *tf) const + { + return tf->Patch->getZone()->getZoneId() != ZoneId; + } + uint16 ZoneId; +}; + + +//******************************************************************************************************************** +void CPackedWorldBuilder::build(const std::vector &zoneNames, const std::string &cachePath, bool addLandscapeIG, CPackedWorld &dest, float refineTheshold) +{ + std::vector > zones; + zones.reserve(zoneNames.size()); + sint zoneMinX = 0; + sint zoneMaxX = 0; + sint zoneMinY = 0; + sint zoneMaxY = 0; + bool firstZoneCorner = true; + for(uint k = 0; k < zoneNames.size(); ++k) + { + CSmartPtr zoneRef = new CZoneRefCount; + zoneRef->Path = zoneNames[k]; + if (addLandscapeIG) + { + std::string igFileName = CFile::getFilenameWithoutExtension(zoneRef->Path) + ".ig"; + zoneRef->IGPath = CPath::lookup(igFileName, false, false); + if (zoneRef->IGPath.empty()) + { + nlwarning("Couldn't find ig %s. Maybe there's no ig for that zone.", igFileName.c_str()); + } + } + CVector2f zoneCornerMin, zoneCornerMax; + if (getZonePos(zoneNames[k], zoneRef->X, zoneRef->Y)) + { + if (firstZoneCorner) + { + zoneMinX = zoneMaxX = zoneRef->X; + zoneMinY = zoneMaxY = zoneRef->Y; + firstZoneCorner = false; + } + else + { + zoneMinX = std::min(zoneMinX, zoneRef->X); + zoneMaxX = std::max(zoneMaxX, zoneRef->X); + zoneMinY = std::min(zoneMinY, zoneRef->Y); + zoneMaxY = std::max(zoneMaxY, zoneRef->Y); + } + zones.push_back(zoneRef); + } + } + if (zones.empty()) + { + nlwarning("No zones loaded"); + return; + } + uint gridWidth = zoneMaxX - zoneMinX + 1; + uint gridHeight = zoneMaxY - zoneMinY + 1; + // build a grid of zones + CArray2D zoneGrid; + CArray2D packedZoneGrid; + zoneGrid.init(gridWidth, gridHeight, NULL); + packedZoneGrid.init(gridWidth, gridHeight); + for(uint k = 0; k < zones.size(); ++k) + { + sint x = zones[k]->X - zoneMinX; + sint y = zones[k]->Y - zoneMinY; + zoneGrid(x, y) = zones[k]; + } + // build grid for tris + CVector2f cornerMin, cornerMax; + cornerMin.set(zoneMinX * 160.f, zoneMinY * 160.f); + cornerMax.set((zoneMaxX + 1) * 160.f, (zoneMaxY + 1) * 160.f); + const float CELL_SIZE = 4.f; // resolution of tri grid + + /* + CVillageGrid vg; + vg.init(gridWidth, gridHeight, zoneMinX, zoneMinY); + + + std::vector continentList; + CConfigFile::CVar *worldSheetPtr = cf.getVarPtr("WorldSheet"); + if (!(worldSheetPtr && loadContinentList(worldSheetPtr->asString(), continentList))) + { + CConfigFile::CVar *continentSheetNames = cf.getVarPtr("ContinentSheetNames"); + std::vector > igs; + if (!continentSheetNames) + { + nlwarning("No villages added to collisions"); + } + else + { + for(uint k = 0; k < (uint) continentSheetNames->size(); ++k) + { + continentList.push_back(continentSheetNames->asString(k)); + } + } + } + + bool addVillages = true; + CConfigFile::CVar *addVillagesVar = cf.getVarPtr("AddVillages"); + if (addVillagesVar) + { + addVillages = addVillagesVar->asBool(); + } + if (addVillages) + { + for(uint k = 0; k < (uint) continentList.size(); ++k) + { + vg.addVillagesFromContinent(continentList[k]); + } + } + */ + + TShapeCache shapeCache; + + + + // build each zone separatly + static std::vector leaves; + uint currZoneIndex = 0; + for (sint y = 0; y < (sint) zoneGrid.getHeight(); ++y) + { + for (sint x = 0; x < (sint) zoneGrid.getWidth(); ++x) + { + if (zoneGrid(x, y)) + { + std::string cacheFilename = CPath::standardizePath(cachePath) + CFile::getFilenameWithoutExtension(zoneGrid(x, y)->Path) + ".packed_zone"; + bool mustRebuild = false; + + // if there's any village on this zone that is more recent than the zone, then must rebuild the zone + /* + { + const std::list &villageList = vg.VillageGrid(x, y); + for(std::list::const_iterator it = villageList.begin(); it != villageList.end(); ++it) + { + uint32 modifDate = vg.Villages[*it].FileModificationDate; + uint32 cacheDate = CFile::getFileModificationDate(cacheFilename); + if (modifDate > cacheDate) + { + mustRebuild = true; + break; + } + } + }*/ + + // if landscape ig is reclaimed, see if it is more recent + if (!zoneGrid(x, y)->IGPath.empty()) + { + if (CFile::getFileModificationDate(zoneGrid(x, y)->IGPath) >= CFile::getFileModificationDate(cacheFilename)) + { + mustRebuild = true; + } + } + + if (!mustRebuild) + { + mustRebuild = true; + // see if zone is present in cache and is valid + if (CFile::getFileModificationDate(cacheFilename) >= CFile::getFileModificationDate(zoneGrid(x, y)->Path)) + { + // try to retrieve file from cache + try + { + CIFile f; + if (f.open(cacheFilename)) + { + CPackedZoneBase *pb = NULL; + f.serialPolyPtr(pb); + packedZoneGrid(x, y) = pb; + mustRebuild = false; + nlinfo("Retrieving zone %d / %d from cache\n", (int) currZoneIndex + 1, (int) zones.size()); + } + } + catch(const EStream &) + { + } + } + } + + if (mustRebuild) + { + nlinfo("Rebuilding zone %d / %d \n", (int) currZoneIndex + 1, (int) zones.size()); + CLandscape *landscape = new CLandscape; + landscape->init(); + landscape->setThreshold (refineTheshold / (1000.f * 1000.f)); + //landscape->setThreshold(0); + landscape->setTileMaxSubdivision (0); + // add wanted zones & all zones around for continuity + for (sint ly = y - 1; ly <= y + 1; ++ly) + { + if (ly < 0) continue; + if (ly >= (sint) gridHeight) break; + for (sint lx = x - 1; lx <= x + 1; ++lx) + { + if (lx < 0) continue; + if (lx >= (sint) gridWidth) break; + if (zoneGrid(lx, ly)) + { + if (!zoneGrid(lx, ly)->Loaded) + { + + try + { + CIFile stream(CPath::lookup(zoneGrid(lx, ly)->Path)); + zoneGrid(lx, ly)->Zone.serial(stream); + zoneGrid(lx, ly)->Loaded = true; + } + catch(const Exception &) + { + nlwarning("Error while loading zone %s : zone not loaded \n", zoneGrid(lx, ly)->Path.c_str()); + } + } + if (zoneGrid(lx, ly)->Loaded) + { + landscape->addZone(zoneGrid(lx, ly)->Zone); + } + } + } + } + // + landscape->refineAll(CVector((x + zoneMinX) * 160.f + 80.f, (y + zoneMinY) * 160.f + 80.f, 1000.f)); + // + // Dump tesselated triangles + leaves.clear(); + landscape->getTessellationLeaves(leaves); + leaves.erase(std::remove_if(leaves.begin(), leaves.end(), CRemoveBorderLeavePred(zoneGrid(x, y)->Zone.getZoneId())), leaves.end()); + // gather and load list of villages ig + std::vector igs; + /*if (addVillages) + { + const std::list &villageList = vg.VillageGrid(x, y); + for(std::list::const_iterator it = villageList.begin(); it != villageList.end(); ++it) + { + CVillage &village = vg.Villages[*it]; + village.load(shapeCache); // load if needed + for(uint k = 0; k < village.IG.size(); ++k) + { + if (village.IG[k].IG) + { + igs.push_back(village.IG[k].IG); + } + } + } + }*/ + // + CAABBox baseZoneBBox; + CVector zoneMinCorner((x + zoneMinX) * 160.f, (y + zoneMinY) * 160.f, 0.f); + baseZoneBBox.setMinMax(zoneMinCorner, zoneMinCorner + CVector(160.f, 160.f, 1.f)); + CSmartPtr pz32 = new CPackedZone32; + // + pz32->build(leaves, CELL_SIZE, igs, shapeCache, baseZoneBBox, (sint32) (x + zoneMinX), (sint32) (y + zoneMinY)); + // + // try to convert to 16 bit indices to save some place + CSmartPtr pz16 = pz32->buildPackedZone16(); + if (pz16) + { + packedZoneGrid(x, y) = pz16; + } + else + { + packedZoneGrid(x, y) = pz32; + } + // write result in cache + try + { + if (!CFile::isExists(cachePath)) + { + CFile::createDirectoryTree(cachePath); + } + COFile f; + f.open(cacheFilename); + CPackedZoneBase *pb = packedZoneGrid(x, y); + f.serialPolyPtr(pb); + } + catch(const EStream &e) + { + printf("Error while writing packed zone to cache : \n %s \n", e.what()); + } + // + delete landscape; + } + ++ currZoneIndex; + } + } + } + zoneGrid.clear(); + shapeCache.clear(); + + + std::vector packedZonesArray; + for (sint y = 0; y < (sint) packedZoneGrid.getHeight(); ++y) + { + for (sint x = 0; x < (sint) packedZoneGrid.getWidth(); ++x) + { + if (packedZoneGrid(x, y)) + { + packedZonesArray.push_back(packedZoneGrid(x, y)); + } + } + } + + // build packed world + dest.build(packedZonesArray); +} + + +//******************************************************************************************************************** +void CPackedWorldBuilder::fly(std::vector &islands, float camSpeed) +{ + nlassert(!islands.empty()); + // fly into scene + try + { + CNELU::init(1024, 768, CViewport(), 32, true, NULL, false, true); + } + catch(const Exception &e) + { + nlwarning(e.what()); + return; + } + // + CFrustum frust; + frust.init(-0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 1500.f, 1); + // + + CMatrix camMat; + // + IDriver *driver = CNELU::Driver; + CEvent3dMouseListener mouseListener; + mouseListener.setMouseMode(U3dMouseListener::firstPerson); + mouseListener.setFrustrum(frust); + mouseListener.addToServer(CNELU::EventServer); + mouseListener.setSpeed(camSpeed); + CVertexBuffer vb; + vb.setVertexFormat(CVertexBuffer::PositionFlag); + vb.setPreferredMemory(CVertexBuffer::AGPVolatile, false); + // + CMaterial material; + material.initUnlit(); + material.setDoubleSided(true); + material.setZFunc(CMaterial::lessequal); + CMaterial wiredMaterial; + wiredMaterial.initUnlit(); + wiredMaterial.setDoubleSided(true); + wiredMaterial.setZFunc(CMaterial::lessequal); + wiredMaterial.setColor(CRGBA(255, 255, 255, 250)); + wiredMaterial.texEnvOpAlpha(0, CMaterial::Replace); + wiredMaterial.texEnvArg0Alpha(0, CMaterial::Diffuse, CMaterial::SrcAlpha); + wiredMaterial.setBlend(true); + wiredMaterial.setBlendFunc(CMaterial::srcalpha, CMaterial::invsrcalpha); + CMaterial texturedMaterial; + texturedMaterial.initUnlit(); + texturedMaterial.setDoubleSided(true); + texturedMaterial.setZFunc(CMaterial::lessequal); + // + uint currWorldIndex = ~0; + bool newPosWanted = true; + // + std::vector zones; + // + CMaterial *zoneMat = NULL; + do + { + if (newPosWanted) + { + currWorldIndex = (currWorldIndex + 1) % islands.size(); + const CIslandInfo &island = islands[currWorldIndex]; + camMat.identity(); + camMat.setPos(island.StartPosition); + mouseListener.setMatrix(camMat); + nlassert(island.PW); + islands[currWorldIndex].PW->getZones(zones); + nlwarning("zone = %s \n", posToZoneName(camMat.getPos().x, camMat.getPos().y).c_str()); + newPosWanted = false; + // setup material with projected texture if there's one + if (island.TexName.empty()) + { + zoneMat = &material; + } + else + { + zoneMat = &texturedMaterial; + // just add a projected texture + CTextureFile *newTex = new CTextureFile(island.TexName); + newTex->setWrapS(ITexture::Clamp); + newTex->setWrapT(ITexture::Clamp); + texturedMaterial.setTexture(0, newTex); + texturedMaterial.texEnvOpRGB(0, CMaterial::Replace); + texturedMaterial.texEnvArg0RGB(0, CMaterial::Texture, CMaterial::SrcColor); + texturedMaterial.setTexCoordGen(0, true); + texturedMaterial.setTexCoordGenMode(0, CMaterial::TexCoordGenObjectSpace); + CMatrix mat; + CVector scale = island.CornerMax - island.CornerMin; + scale.x = 1.f / favoid0(scale.x); + scale.y = 1.f / favoid0(scale.y); + scale.z = 0.f; + mat.setScale(scale); + mat.setPos(CVector(- island.CornerMin.x * scale.x, - island.CornerMin.y * scale.y, 0.f)); + // + CMatrix uvScaleMat; + // + uvScaleMat.setScale(CVector(island.UScale, - island.VScale, 0.f)); + uvScaleMat.setPos(CVector(0.f, island.VScale, 0.f)); + // + texturedMaterial.enableUserTexMat(0, true); + texturedMaterial.setUserTexMat(0, uvScaleMat * mat); + } + } + const CRGBA clearColor = CRGBA(0, 0, 127, 0); + driver->enableFog(true); + driver->setupFog(frust.Far * 0.8f, frust.Far, clearColor); + CViewport vp; + vp.init(0.f, 0.f, 1.f, 1.f); + driver->setupViewport(vp); + CScissor scissor; + viewportToScissor(vp, scissor); + driver->setupScissor(scissor); + + CNELU::EventServer.pump(); + camMat = mouseListener.getViewMatrix(); + // + driver->clear2D(clearColor); + driver->clearZBuffer(); + // + driver->setFrustum(frust.Left, frust.Right, frust.Bottom, frust.Top, frust.Near, frust.Far, frust.Perspective); + driver->setupViewMatrix(camMat.inverted()); + driver->setupModelMatrix(CMatrix::Identity); + // + // + const CVector localFrustCorners[8] = + { + CVector(frust.Left, frust.Near, frust.Top), + CVector(frust.Right, frust.Near, frust.Top), + CVector(frust.Right, frust.Near, frust.Bottom), + CVector(frust.Left, frust.Near, frust.Bottom), + CVector(frust.Left * frust.Far / frust.Near, frust.Far, frust.Top * frust.Far / frust.Near), + CVector(frust.Right * frust.Far / frust.Near, frust.Far, frust.Top * frust.Far / frust.Near), + CVector(frust.Right * frust.Far / frust.Near, frust.Far, frust.Bottom * frust.Far / frust.Near), + CVector(frust.Left * frust.Far / frust.Near, frust.Far, frust.Bottom * frust.Far / frust.Near) + }; + // roughly compute covered zones + // + /* + sint frustZoneMinX = INT_MAX; + sint frustZoneMaxX = INT_MIN; + sint frustZoneMinY = INT_MAX; + sint frustZoneMaxY = INT_MIN; + for(uint k = 0; k < sizeofarray(localFrustCorners); ++k) + { + CVector corner = camMat * localFrustCorners[k]; + sint zoneX = (sint) (corner.x / 160.f) - zoneMinX; + sint zoneY = (sint) floorf(corner.y / 160.f) - zoneMinY; + frustZoneMinX = std::min(frustZoneMinX, zoneX); + frustZoneMinY = std::min(frustZoneMinY, zoneY); + frustZoneMaxX = std::max(frustZoneMaxX, zoneX); + frustZoneMaxY = std::max(frustZoneMaxY, zoneY); + } + */ + + const uint TRI_BATCH_SIZE = 10000; // batch size for rendering + + + for(uint k = 0; k < zones.size(); ++k) + { + zones[k]->render(vb, *driver, *zoneMat, wiredMaterial, camMat, TRI_BATCH_SIZE, localFrustCorners); + } + + driver->setPolygonMode(IDriver::Filled); + material.setColor(CRGBA::Green); + // compute intersection with landscape & display a dot at that position + CVector lookAtPos = camMat.getPos() + 1000.f * camMat.getJ(); + CVector inter; + static std::vector triList; + triList.clear(); + bool interFound = islands[currWorldIndex].PW->raytrace(camMat.getPos(), lookAtPos, inter, &triList); + if (!triList.empty()) + { + vb.setNumVertices(3 * (uint32)triList.size()); + CVertexBufferReadWrite vba; + vb.lock(vba); + CVector *dest = vba.getVertexCoordPointer(0); + memcpy(dest, &triList[0], sizeof(CTriangle) * triList.size()); + vba.unlock(); + driver->activeVertexBuffer(vb); + driver->renderRawTriangles(material, 0, (uint32)triList.size()); + } + if (interFound) + { + material.setColor(CRGBA::Magenta); + CQuad q; + q.V0 = inter - camMat.getI() + camMat.getK(); + q.V1 = inter + camMat.getI() + camMat.getK(); + q.V2 = inter + camMat.getI() - camMat.getK(); + q.V3 = inter - camMat.getI() - camMat.getK(); + { + vb.setNumVertices(4); + CVertexBufferReadWrite vba; + vb.lock(vba); + CVector *dest = vba.getVertexCoordPointer(0); + pushVBQuad(dest, q); + vba.unlock(); + } + driver->activeVertexBuffer(vb); + driver->renderRawQuads(material, 0, 1); + } + // + /* + uint NUM_RAYS = 10000; + if (CNELU::AsyncListener.isKeyPushed(KeyT)) + { + printf("Starting raytracing test 1"); + uint numHits = 0; + NLMISC::TTime startTime = CTime::getLocalTime(); + for(uint k = 0; k < NUM_RAYS; ++k) + { + sint zone = rand() % packedZonesArray.size(); + CPackedZoneBase *zonePtr = packedZonesArray[zone]; + CVector cornerMin = zonePtr->Box.getMin(); + CVector cornerMax = zonePtr->Box.getMax(); + CVector start(frand(1.f) * (cornerMax.x - cornerMin.x) + cornerMin.x, + frand(1.f) * (cornerMax.y - cornerMin.y) + cornerMin.y, + frand(1.f) * (cornerMax.z - cornerMin.z) + cornerMin.z); + CVector end(frand(1.f) * (cornerMax.x - cornerMin.x) + cornerMin.x, + frand(1.f) * (cornerMax.y - cornerMin.y) + cornerMin.y, + frand(1.f) * (cornerMax.z - cornerMin.z) + cornerMin.z); + CVector inter; + bool result = pw.raytrace(start, end, inter); + if (result) + { + ++numHits; + } + } + NLMISC::TTime endTime = CTime::getLocalTime(); + + float dt = (float) (endTime - startTime) / 1000.f; + printf("Total time = %.2f s\n", dt); + printf("Num rays = %d\n", (int) NUM_RAYS); + printf("Num hits = %d\n", (int) numHits); + printf("Num test per seconds = %.2f\n", (float) NUM_RAYS / dt); + } + */ + // + /* + if (CNELU::AsyncListener.isKeyPushed(KeyU)) + { + printf("Starting raytracing test 2"); + uint numHits = 0; + NLMISC::TTime startTime = CTime::getLocalTime(); + for(uint k = 0; k < NUM_RAYS; ++k) + { + CVector start = camMat.getPos(); + CVector end(start.x + (frand(200.f) - 100.f), + start.y + (frand(200.f) - 100.f), + start.z + (frand(5.f) - 2.5f)); + CVector inter; + bool result = pw.raytrace(start, end, inter); + if (result) + { + ++numHits; + } + } + NLMISC::TTime endTime = CTime::getLocalTime(); + + float dt = (float) (endTime - startTime) / 1000.f; + printf("Total time = %.2f s\n", dt); + printf("Num rays = %d\n", (int) NUM_RAYS); + printf("Num hits = %d\n", (int) numHits); + printf("Num test per seconds = %.2f\n", (float) NUM_RAYS / dt); + } + */ + if (CNELU::AsyncListener.isKeyPushed(KeyN)) + { + newPosWanted = true; + } + // + driver->setPolygonMode(IDriver::Filled); + // + driver->swapBuffers(); + } + while(!CNELU::AsyncListener.isKeyPushed(KeyESCAPE)); + // +} diff --git a/code/ryzom/tools/server/build_world_packed_col/packed_world_builder.h b/code/ryzom/tools/server/build_world_packed_col/packed_world_builder.h index b773ba589..8b6926b47 100644 --- a/code/ryzom/tools/server/build_world_packed_col/packed_world_builder.h +++ b/code/ryzom/tools/server/build_world_packed_col/packed_world_builder.h @@ -1,49 +1,49 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef _PACKED_WORLD_BUILDER_H -#define _PACKED_WORLD_BUILDER_H - - -#include "nel/misc/vector_2f.h" - -namespace NL3D -{ - class CPackedWorld; -} - -class CPackedWorldBuilder -{ -public: - // merge a set of zones into a packed world - void build(const std::vector &zoneNames, const std::string &cachePath, bool addLandscapeIG, NL3D::CPackedWorld &dest, float refineTheshold); - // create a window & fly through a list of packed worlds - class CIslandInfo - { - public: - NL3D::CPackedWorld *PW; - NLMISC::CVector StartPosition; - std::string TexName; // projected texture - NLMISC::CVector CornerMin, CornerMax; - float UScale, VScale; - CIslandInfo() : PW(NULL), UScale(1.f), VScale(1.f) {} - }; - // - void fly(std::vector &islands, float camSpeed); -}; - - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef _PACKED_WORLD_BUILDER_H +#define _PACKED_WORLD_BUILDER_H + + +#include "nel/misc/vector_2f.h" + +namespace NL3D +{ + class CPackedWorld; +} + +class CPackedWorldBuilder +{ +public: + // merge a set of zones into a packed world + void build(const std::vector &zoneNames, const std::string &cachePath, bool addLandscapeIG, NL3D::CPackedWorld &dest, float refineTheshold); + // create a window & fly through a list of packed worlds + class CIslandInfo + { + public: + NL3D::CPackedWorld *PW; + NLMISC::CVector StartPosition; + std::string TexName; // projected texture + NLMISC::CVector CornerMin, CornerMax; + float UScale, VScale; + CIslandInfo() : PW(NULL), UScale(1.f), VScale(1.f) {} + }; + // + void fly(std::vector &islands, float camSpeed); +}; + + +#endif diff --git a/code/ryzom/tools/server/build_world_packed_col/std_header.cpp b/code/ryzom/tools/server/build_world_packed_col/std_header.cpp index 89957ac91..bde789b64 100644 --- a/code/ryzom/tools/server/build_world_packed_col/std_header.cpp +++ b/code/ryzom/tools/server/build_world_packed_col/std_header.cpp @@ -1,17 +1,17 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + #include "std_header.h" \ No newline at end of file diff --git a/code/ryzom/tools/server/build_world_packed_col/std_header.h b/code/ryzom/tools/server/build_world_packed_col/std_header.h index 4584d4937..fbed11d81 100644 --- a/code/ryzom/tools/server/build_world_packed_col/std_header.h +++ b/code/ryzom/tools/server/build_world_packed_col/std_header.h @@ -1,25 +1,25 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/misc/types_nl.h" -#include "nel/misc/stream.h" -#include "nel/misc/vector.h" -#include "nel/misc/matrix.h" -// -#include -#include -#include +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/misc/types_nl.h" +#include "nel/misc/stream.h" +#include "nel/misc/vector.h" +#include "nel/misc/matrix.h" +// +#include +#include +#include #include \ No newline at end of file diff --git a/code/ryzom/tools/server/build_world_packed_col/test_col_world.cpp b/code/ryzom/tools/server/build_world_packed_col/test_col_world.cpp index a9a7506b5..21f85b760 100644 --- a/code/ryzom/tools/server/build_world_packed_col/test_col_world.cpp +++ b/code/ryzom/tools/server/build_world_packed_col/test_col_world.cpp @@ -1,1100 +1,1100 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -/*#include "std_header.h" -// -// test_col_world.cpp : Defines the entry point for the console application. -// -#include "zone_util.h" -#include "village.h" -// -#include "nel/misc/array_2d.h" -#include "nel/misc/config_file.h" -#include "nel/misc/path.h" -#include "nel/misc/file.h" -#include "nel/misc/vector_2f.h" -#include "nel/misc/triangle.h" -#include "nel/misc/polygon.h" -#include "nel/misc/smart_ptr.h" -#include "nel/misc/quad.h" -// -#include "nel/3d/frustum.h" -#include "nel/3d/viewport.h" -#include "nel/3d/scissor.h" -#include "nel/misc/aabbox.h" -#include "nel/misc/stream.h" -// -#include "3d/landscape.h" -#include "3d/zone.h" -#include "3d/quad_grid.h" -#include "3d/event_mouse_listener.h" -#include "3d/vertex_buffer.h" -#include "3d/material.h" -#include "3d/register_3d.h" -#include "3d/nelu.h" -#include "3d/scene_group.h" -#include "3d/shape_info.h" -#include "3d/packed_zone.h" -#include "3d/packed_world.h" -// -#include -// - -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" -#include "nel/georges/u_form_loader.h" - - -using namespace NLMISC; -using namespace NL3D; - - - -static inline void pushVBQuad(NLMISC::CVector *&dest, const NLMISC::CQuad &quad) -{ - *dest++ = quad.V0; - *dest++ = quad.V1; - *dest++ = quad.V2; - *dest++ = quad.V3; -} - - -class CZoneRefCount : public CRefCount -{ -public: - CZone Zone; - bool Loaded; - std::string Path; - std::string IGPath; - sint X; - sint Y; -public: - CZoneRefCount() : Loaded(false) {} -}; - - -static void viewportToScissor(const CViewport &vp, CScissor &scissor) -{ - scissor.X = vp.getX(); - scissor.Y = vp.getY(); - scissor.Width = vp.getWidth(); - scissor.Height = vp.getHeight(); -} - - - - -// load list of continent from the .world sheet -static bool loadContinentList(const std::string &worldSheet, std::vector &continentList) -{ - NLGEORGES::UFormLoader *loader = NLGEORGES::UFormLoader::createLoader(); - // - std::string path = CPath::lookup(worldSheet, false, false); - if (path.empty()) - { - NLGEORGES::UFormLoader::releaseLoader(loader); - nlwarning("Path not found for %s.", worldSheet.c_str()); - return false; - } - NLGEORGES::UForm *worldForm; - worldForm = loader->loadForm(path.c_str()); - if (worldForm == NULL) - { - NLGEORGES::UFormLoader::releaseLoader(loader); - return false; - } - - uint size; - NLGEORGES::UFormElm *pElt; - nlverify (worldForm->getRootNode().getNodeByName (&pElt, "continents list")); - if(!pElt) - { - nlwarning("node 'continents list' not found in a .world"); - NLGEORGES::UFormLoader::releaseLoader(loader); - return false; - } - else - { - nlverify (pElt->getArraySize (size)); - for (uint32 i = 0; i getArrayNode (&pEltOfList, i) && pEltOfList) - { - std::string continentName; - pEltOfList->getValueByName (continentName, "continent_name"); - if (CFile::getExtension(continentName).empty()) - { - continentName += ".continent"; - } - continentList.push_back(continentName); - } - } - } - NLGEORGES::UFormLoader::releaseLoader(loader); - return true; -} - - -class CRemoveBorderLeavePred -{ -public: - CRemoveBorderLeavePred(uint16 zoneId) : ZoneId(zoneId) {} - bool operator()(const CTessFace *tf) const - { - return tf->Patch->getZone()->getZoneId() != ZoneId; - } - uint16 ZoneId; -}; - - -static bool parseCamPos(CConfigFile &cf, CVector &camPos) -{ - CConfigFile::CVar *camPosVar = cf.getVarPtr("CamPos"); - if (camPosVar) - { - if (camPosVar->size() == 3) - { - camPos.x = camPosVar->asFloat(0); - camPos.y = camPosVar->asFloat(1); - camPos.z = camPosVar->asFloat(2); - return true; - } - else - { - // it is a zone name - sint zoneX, zoneY; - if (getZonePos(camPosVar->asString(), zoneX, zoneY)) - { - camPos.x = 160.f * zoneX + 80.f; - camPos.y = 160.f * zoneY + 80.f; - camPos.z = 0.f; - return true; - } - } - } - return false; -} - -static bool parseCamSpeed(CConfigFile &cf, float &camSpeed) -{ - CConfigFile::CVar *camSpeedVar = cf.getVarPtr("CamSpeed"); - if (camSpeedVar) - { - camSpeed = camSpeedVar->asFloat(); - return true; - } - return false; -} - -static bool newCamSpeedWanted = false; -static float newCamSpeed = FLT_MIN; -static bool newCamPosWanted = false; - -static CVector newCamPos(FLT_MAX, FLT_MAX, FLT_MAX); - -static void configFileChanged(const std::string &filename) -{ - CConfigFile cf; - try - { - cf.load(filename); - CVector camPos; - if (parseCamPos(cf, camPos)) - { - if (camPos!= newCamPos) - { - newCamPos = camPos; - newCamPosWanted = true; - } - } - float camSpeed; - if (parseCamSpeed(cf, camSpeed)) - { - if (camSpeed != newCamSpeed) - { - newCamSpeed= camSpeed; - newCamSpeedWanted = true; - } - } - } - catch(const EStream &) - { - printf("Error while reading config file\n"); - } -} - -int main(int argc, char* argv[]) -{ - registerSerial3d(); - - if (argc != 2) - { - printf("usage : %s config_file_name.cfg\n", CFile::getFilename(argv[0]).c_str()); - return -1; - } - // - std::string worldSheetName; - // - std::string cachePath; - // load all landscape zones - std::vector zoneNames; - CConfigFile cf; - CVector camPos(18927.f, -24382.f, 0.f); - - bool addLandscapeIG = false; - - float camSpeed = 35.f; - try - { - cf.load(argv[1]); - parseCamPos(cf, camPos); - newCamPos = camPos; - parseCamSpeed(cf, camSpeed); - newCamSpeed = camSpeed; - CConfigFile::CVar &paths = cf.getVar("ZonesPaths"); - for(uint k = 0; k < (uint) paths.size(); ++k) - { - std::vector files; - CPath::getPathContent(paths.asString(k), true, false, true, files); - for(uint l = 0; l < files.size(); ++l) - { - std::string ext = CFile::getExtension(files[l]); - if (nlstricmp(ext, "zonel") == 0) - { - zoneNames.push_back(files[l]); - } - } - } - cachePath = cf.getVar("CachePath").asString(); - CConfigFile::CVar *searchPaths = cf.getVarPtr("SearchPaths"); - for(uint k = 0; k < (uint) searchPaths->size(); ++k) - { - CPath::addSearchPath(searchPaths->asString(k), true, false); - } - CConfigFile::CVar *addLandscapeIGVarPtr = cf.getVarPtr("AddLandscapeIG"); - if (addLandscapeIGVarPtr) - { - addLandscapeIG = addLandscapeIGVarPtr->asInt() != 0; - } - } - catch(const EStream &) - { - printf("Error while reading config file\n"); - return -1; - } - catch(const EConfigFile &e) - { - printf(e.what()); - return -1; - } - // - CFile::addFileChangeCallback(argv[1], configFileChanged); - // - std::vector > zones; - zones.reserve(zoneNames.size()); - sint zoneMinX, zoneMaxX; - sint zoneMinY, zoneMaxY; - bool firstZoneCorner = true; - for(uint k = 0; k < zoneNames.size(); ++k) - { - CSmartPtr zoneRef = new CZoneRefCount; - zoneRef->Path = zoneNames[k]; - if (addLandscapeIG) - { - std::string igFileName = CFile::getFilenameWithoutExtension(zoneRef->Path) + ".ig"; - zoneRef->IGPath = CPath::lookup(igFileName, false, false); - if (zoneRef->IGPath.empty()) - { - nlwarning("Couldn't find ig %s. Maybe there's no ig for that zone.", igFileName.c_str()); - } - } - //printf("Loading zone %d / %d \n", (int) k + 1, (int) zoneNames.size()); - CVector2f zoneCornerMin, zoneCornerMax; - if (getZonePos(zoneNames[k], zoneRef->X, zoneRef->Y)) - { - if (firstZoneCorner) - { - zoneMinX = zoneMaxX = zoneRef->X; - zoneMinY = zoneMaxY = zoneRef->Y; - firstZoneCorner = false; - } - else - { - zoneMinX = std::min(zoneMinX, zoneRef->X); - zoneMaxX = std::max(zoneMaxX, zoneRef->X); - zoneMinY = std::min(zoneMinY, zoneRef->Y); - zoneMaxY = std::max(zoneMaxY, zoneRef->Y); - } - zones.push_back(zoneRef); - } - } - if (zones.empty()) - { - printf("No zones loaded \n"); - return -1; - } - uint gridWidth = zoneMaxX - zoneMinX + 1; - uint gridHeight = zoneMaxY - zoneMinY + 1; - // build a grid of zones - CArray2D zoneGrid; - CArray2D packedZoneGrid; - zoneGrid.init(gridWidth, gridHeight, NULL); - packedZoneGrid.init(gridWidth, gridHeight); - for(uint k = 0; k < zones.size(); ++k) - { - sint x = zones[k]->X - zoneMinX; - sint y = zones[k]->Y - zoneMinY; - zoneGrid(x, y) = zones[k]; - } - // build grid for tris - CVector2f cornerMin, cornerMax; - cornerMin.set(zoneMinX * 160.f, zoneMinY * 160.f); - cornerMax.set((zoneMaxX + 1) * 160.f, (zoneMaxY + 1) * 160.f); - const float CELL_SIZE = 4.f; // resolution of tri grid - - CVillageGrid vg; - vg.init(gridWidth, gridHeight, zoneMinX, zoneMinY); - - - std::vector continentList; - CConfigFile::CVar *worldSheetPtr = cf.getVarPtr("WorldSheet"); - if (!(worldSheetPtr && loadContinentList(worldSheetPtr->asString(), continentList))) - { - CConfigFile::CVar *continentSheetNames = cf.getVarPtr("ContinentSheetNames"); - std::vector > igs; - if (!continentSheetNames) - { - nlwarning("No villages added to collisions"); - } - else - { - for(uint k = 0; k < (uint) continentSheetNames->size(); ++k) - { - continentList.push_back(continentSheetNames->asString(k)); - } - } - } - - bool addVillages = true; - CConfigFile::CVar *addVillagesVar = cf.getVarPtr("AddVillages"); - if (addVillagesVar) - { - addVillages = addVillagesVar->asBool(); - } - if (addVillages) - { - for(uint k = 0; k < (uint) continentList.size(); ++k) - { - vg.addVillagesFromContinent(continentList[k]); - } - } - - TShapeCache shapeCache; - - - - // build each zone separatly - static std::vector leaves; - uint currZoneIndex = 0; - for (sint y = 0; y < (sint) zoneGrid.getHeight(); ++y) - { - for (sint x = 0; x < (sint) zoneGrid.getWidth(); ++x) - { - if (zoneGrid(x, y)) - { - std::string cacheFilename = CPath::standardizePath(cachePath) + CFile::getFilenameWithoutExtension(zoneGrid(x, y)->Path) + ".packed_zone"; - bool mustRebuild = false; - - // if there's any village on this zone that is more recent than the zone, then must rebuild the zone - { - const std::list &villageList = vg.VillageGrid(x, y); - for(std::list::const_iterator it = villageList.begin(); it != villageList.end(); ++it) - { - uint32 modifDate = vg.Villages[*it].FileModificationDate; - uint32 cacheDate = CFile::getFileModificationDate(cacheFilename); - if (modifDate > cacheDate) - { - mustRebuild = true; - break; - } - } - } - - // if landscape ig is reclaimed, see if it is more recent - if (!zoneGrid(x, y)->IGPath.empty()) - { - if (CFile::getFileModificationDate(zoneGrid(x, y)->IGPath) >= CFile::getFileModificationDate(cacheFilename)) - { - mustRebuild = true; - } - } - - if (!mustRebuild) - { - mustRebuild = true; - // see if zone is present in cache and is valid - if (CFile::getFileModificationDate(cacheFilename) >= CFile::getFileModificationDate(zoneGrid(x, y)->Path)) - { - // try to retrieve file from cache - try - { - CIFile f; - f.open(cacheFilename); - CPackedZoneBase *pb; - f.serialPolyPtr(pb); - packedZoneGrid(x, y) = pb; - mustRebuild = false; - printf("Retrieving zone %d / %d from cache\n", (int) currZoneIndex + 1, (int) zones.size()); - } - catch(const EStream &) - { - } - } - } - - if (mustRebuild) - { - printf("Rebuilding zone %d / %d \n", (int) currZoneIndex + 1, (int) zones.size()); - CLandscape *landscape = new CLandscape; - landscape->init(); - landscape->setThreshold (8.f / (1000.f * 1000.f)); - //landscape->setThreshold(0); - landscape->setTileMaxSubdivision (0); - // add wanted zone & all zones around for continuity - for (sint ly = y - 1; ly <= y + 1; ++ly) - { - if (ly < 0) continue; - if (ly >= (sint) gridHeight) break; - for (sint lx = x - 1; lx <= x + 1; ++lx) - { - if (lx < 0) continue; - if (lx >= (sint) gridWidth) break; - if (zoneGrid(lx, ly)) - { - if (!zoneGrid(lx, ly)->Loaded) - { - CIFile stream; - try - { - stream.open(zoneGrid(lx, ly)->Path); - zoneGrid(lx, ly)->Zone.serial(stream); - zoneGrid(lx, ly)->Loaded = true; - } - catch(const EStream &) - { - printf("Error while loading zone %s : zone not loaded \n"); - } - } - if (zoneGrid(lx, ly)->Loaded) - { - landscape->addZone(zoneGrid(lx, ly)->Zone); - } - } - } - } - // - landscape->refineAll(CVector((x + zoneMinX) * 160.f + 80.f, (y + zoneMinY) * 160.f + 80.f, 1000.f)); - // - // Dump tesselated triangles - leaves.clear(); - landscape->getTessellationLeaves(leaves); - leaves.erase(std::remove_if(leaves.begin(), leaves.end(), CRemoveBorderLeavePred(zoneGrid(x, y)->Zone.getZoneId())), leaves.end()); - // gather and load list of villages ig - std::vector igs; - if (addVillages) - { - const std::list &villageList = vg.VillageGrid(x, y); - for(std::list::const_iterator it = villageList.begin(); it != villageList.end(); ++it) - { - CVillage &village = vg.Villages[*it]; - village.load(shapeCache); // load if needed - for(uint k = 0; k < village.IG.size(); ++k) - { - if (village.IG[k].IG) - { - igs.push_back(village.IG[k].IG); - } - } - } - } - // - CAABBox baseZoneBBox; - CVector zoneMinCorner((x + zoneMinX) * 160.f, (y + zoneMinY) * 160.f, 0.f); - baseZoneBBox.setMinMax(zoneMinCorner, zoneMinCorner + CVector(160.f, 160.f, 1.f)); - CSmartPtr pz32 = new CPackedZone32; - // - pz32->build(leaves, CELL_SIZE, igs, shapeCache, baseZoneBBox, (sint32) (x + zoneMinX), (sint32) (y + zoneMinY)); - // - // try to convert to 16 bit indices to save some place - CSmartPtr pz16 = pz32->buildPackedZone16(); - if (pz16) - { - packedZoneGrid(x, y) = pz16; - } - else - { - packedZoneGrid(x, y) = pz32; - } - // write result in cache - try - { - if (!CFile::isExists(cachePath)) - { - CFile::createDirectoryTree(cachePath); - } - COFile f; - f.open(cacheFilename); - CPackedZoneBase *pb = packedZoneGrid(x, y); - f.serialPolyPtr(pb); - } - catch(const EStream &e) - { - printf("Error while writing packed zone to cache : \n %s \n", e.what()); - } - // - delete landscape; - } - ++ currZoneIndex; - } - } - } - zoneGrid.clear(); - shapeCache.clear(); - - - std::vector packedZonesArray; - for (sint y = 0; y < (sint) packedZoneGrid.getHeight(); ++y) - { - for (sint x = 0; x < (sint) packedZoneGrid.getWidth(); ++x) - { - if (packedZoneGrid(x, y)) - { - packedZonesArray.push_back(packedZoneGrid(x, y)); - } - } - } - - // build packed world - CPackedWorld pw; - pw.build(packedZonesArray); - - - bool fly = true; - CConfigFile::CVar *flyVar = cf.getVarPtr("Fly"); - if (flyVar) - { - fly = flyVar->asBool(); - } - - if (!fly) return 0; - - // fly into scene - try - { - CNELU::init(1024, 768, CViewport(), 32, true, NULL, false, true); - } - catch(const Exception &e) - { - puts(e.what()); - getchar(); - return -1; - } - // - CFrustum frust; - frust.init(-0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 150.f, 1); - // - - CMatrix camMat; - camMat.identity(); - camMat.setPos(camPos); - // - IDriver *driver = CNELU::Driver; - CEvent3dMouseListener mouseListener; - mouseListener.setMatrix(camMat); - mouseListener.setMouseMode(U3dMouseListener::firstPerson); - mouseListener.setFrustrum(frust); - mouseListener.addToServer(CNELU::EventServer); - mouseListener.setSpeed(camSpeed); - CVertexBuffer vb; - vb.setVertexFormat(CVertexBuffer::PositionFlag); - vb.setPreferredMemory(CVertexBuffer::AGPVolatile, false); - // - CMaterial material; - material.initUnlit(); - material.setDoubleSided(true); - material.setZFunc(CMaterial::lessequal); - // - do - { - printf("zone = %s \n", posToZoneName(camMat.getPos().x, camMat.getPos().y).c_str()); - // - CFile::checkFileChange(); - if (newCamPosWanted) - { - camMat.setPos(newCamPos); - mouseListener.setMatrix(camMat); - newCamPosWanted = false; - } - if (newCamSpeedWanted) - { - mouseListener.setSpeed(newCamSpeed); - newCamSpeedWanted = false; - } - const CRGBA clearColor = CRGBA(0, 0, 127, 0); - driver->enableFog(true); - driver->setupFog(frust.Far * 0.8f, frust.Far, clearColor); - CViewport vp; - vp.init(0.f, 0.f, 1.f, 1.f); - driver->setupViewport(vp); - CScissor scissor; - viewportToScissor(vp, scissor); - driver->setupScissor(scissor); - - CNELU::EventServer.pump(); - camMat = mouseListener.getViewMatrix(); - // - driver->clear2D(clearColor); - driver->clearZBuffer(); - // - driver->setFrustum(frust.Left, frust.Right, frust.Bottom, frust.Top, frust.Near, frust.Far, frust.Perspective); - driver->setupViewMatrix(camMat.inverted()); - driver->setupModelMatrix(CMatrix::Identity); - // - // - const CVector localFrustCorners[8] = - { - CVector(frust.Left, frust.Near, frust.Top), - CVector(frust.Right, frust.Near, frust.Top), - CVector(frust.Right, frust.Near, frust.Bottom), - CVector(frust.Left, frust.Near, frust.Bottom), - CVector(frust.Left * frust.Far / frust.Near, frust.Far, frust.Top * frust.Far / frust.Near), - CVector(frust.Right * frust.Far / frust.Near, frust.Far, frust.Top * frust.Far / frust.Near), - CVector(frust.Right * frust.Far / frust.Near, frust.Far, frust.Bottom * frust.Far / frust.Near), - CVector(frust.Left * frust.Far / frust.Near, frust.Far, frust.Bottom * frust.Far / frust.Near) - }; - // roughly compute covered zones - // - sint frustZoneMinX = INT_MAX; - sint frustZoneMaxX = INT_MIN; - sint frustZoneMinY = INT_MAX; - sint frustZoneMaxY = INT_MIN; - for(uint k = 0; k < sizeofarray(localFrustCorners); ++k) - { - CVector corner = camMat * localFrustCorners[k]; - sint zoneX = (sint) (corner.x / 160.f) - zoneMinX; - sint zoneY = (sint) floorf(corner.y / 160.f) - zoneMinY; - frustZoneMinX = std::min(frustZoneMinX, zoneX); - frustZoneMinY = std::min(frustZoneMinY, zoneY); - frustZoneMaxX = std::max(frustZoneMaxX, zoneX); - frustZoneMaxY = std::max(frustZoneMaxY, zoneY); - } - - const uint TRI_BATCH_SIZE = 10000; // batch size for rendering - - - //for (sint y = frustZoneMinY; y <= frustZoneMaxY; ++y) - //{ - //if (y < 0) continue; - //if (y >= (sint) gridHeight) break; - //for (sint x = frustZoneMinX; x <= frustZoneMaxX; ++x) - //{ - //if (x < 0) continue; - //if (x >= (sint) gridWidth) break; - //if (packedZoneGrid(x, y)) - //{ - //packedZoneGrid(x, y)->render(vb, *driver, material, camMat, TRI_BATCH_SIZE, localFrustCorners); - //} - //} - //} - - - for (sint y = 0; y <= (sint) gridHeight; ++y) - { - if (y < 0) continue; - if (y >= (sint) gridHeight) break; - for (sint x = 0; x <= (sint) gridWidth; ++x) - { - if (x < 0) continue; - if (x >= (sint) gridWidth) break; - if (packedZoneGrid(x, y)) - { - packedZoneGrid(x, y)->render(vb, *driver, material, camMat, TRI_BATCH_SIZE, localFrustCorners); - } - } - } - - driver->setPolygonMode(IDriver::Filled); - material.setColor(CRGBA::Green); - // compute intersection with landscape & display a dot at that position - CVector lookAtPos = camMat.getPos() + 1000.f * camMat.getJ(); - CVector inter; - static std::vector triList; - triList.clear(); - bool interFound = pw.raytrace(camMat.getPos(), lookAtPos, inter, &triList); - if (!triList.empty()) - { - vb.setNumVertices(3 * triList.size()); - CVertexBufferReadWrite vba; - vb.lock(vba); - CVector *dest = vba.getVertexCoordPointer(0); - memcpy(dest, &triList[0], sizeof(CTriangle) * triList.size()); - vba.unlock(); - driver->activeVertexBuffer(vb); - driver->renderRawTriangles(material, 0, triList.size()); - } - if (interFound) - { - material.setColor(CRGBA::Magenta); - CQuad q; - q.V0 = inter - camMat.getI() + camMat.getK(); - q.V1 = inter + camMat.getI() + camMat.getK(); - q.V2 = inter + camMat.getI() - camMat.getK(); - q.V3 = inter - camMat.getI() - camMat.getK(); - { - vb.setNumVertices(4); - CVertexBufferReadWrite vba; - vb.lock(vba); - CVector *dest = vba.getVertexCoordPointer(0); - pushVBQuad(dest, q); - vba.unlock(); - } - driver->activeVertexBuffer(vb); - driver->renderRawQuads(material, 0, 1); - } - // -// for(uint k = 0; k < sizeofarray(frustCorners); ++k) -// { -// frustCorners[k] = camMat * frustCorners[k]; -// frustCorners[k].x -= cornerMin.x; -// frustCorners[k].y -= cornerMin.y; -// } -// // project frustum on x/y plane to see where to test polys -// sint minY = INT_MAX; -// CPolygon2D::TRasterVect silhouette; -// addQuadToSilhouette(frustCorners[0], frustCorners[1], frustCorners[2], frustCorners[3], silhouette, minY, CELL_SIZE); -// addQuadToSilhouette(frustCorners[1], frustCorners[5], frustCorners[6], frustCorners[2], silhouette, minY, CELL_SIZE); -// addQuadToSilhouette(frustCorners[4], frustCorners[5], frustCorners[6], frustCorners[7], silhouette, minY, CELL_SIZE); -// addQuadToSilhouette(frustCorners[0], frustCorners[4], frustCorners[7], frustCorners[3], silhouette, minY, CELL_SIZE); -// addQuadToSilhouette(frustCorners[0], frustCorners[1], frustCorners[5], frustCorners[4], silhouette, minY, CELL_SIZE); -// addQuadToSilhouette(frustCorners[3], frustCorners[7], frustCorners[6], frustCorners[2], silhouette, minY, CELL_SIZE); -// // -// driver->setPolygonMode(IDriver::Line); -// // -// material.setColor(CRGBA::White); -// // -// vb.setNumVertices(TRI_BATCH_SIZE * 3); -// { -// CVertexBufferReadWrite vba; -// vb.lock(vba); -// CVector *dest = vba.getVertexCoordPointer(0); -// const CVector *endDest = dest + TRI_BATCH_SIZE * 3; -// for(sint y = 0; y < (sint) silhouette.size(); ++y) -// { -// sint gridY = y + minY; -// if (gridY < 0) continue; -// if (gridY >= triGridHeight) continue; -// sint minX = silhouette[y].first; -// sint maxX = silhouette[y].second; -// for (sint x = minX; x <= maxX; ++x) -// { -// if (x < 0) continue; -// if (x >= triGridWidth) break; -// sint triRefIndex = triGrid(x, gridY); -// while (triRefIndex != -1) -// { -// CTriangle tri = tris[triRefs[triRefIndex].TriIndex]; -// triRefIndex = triRefs[triRefIndex].NextTriRef; -// tri.V0.x += cornerMin.x; -// tri.V0.y += cornerMin.y; -// tri.V1.x += cornerMin.x; -// tri.V1.y += cornerMin.y; -// tri.V2.x += cornerMin.x; -// tri.V2.y += cornerMin.y; -// *dest++ = tri.V0; -// *dest++ = tri.V1; -// *dest++ = tri.V2; -// if (dest == endDest) -// { -// // flush batch -// vba.unlock(); -// material.setColor(CRGBA(100, 100, 100)); -// driver->setPolygonMode(IDriver::Filled); -// driver->renderRawTriangles(material, 0, TRI_BATCH_SIZE); -// material.setColor(CRGBA::White); -// driver->setPolygonMode(IDriver::Line); -// driver->renderRawTriangles(material, 0, TRI_BATCH_SIZE); -// // reclaim a new batch -// vb.lock(vba); -// dest = vba.getVertexCoordPointer(0); -// endDest = dest + TRI_BATCH_SIZE * 3; -// } -// } -// } -// } -// vba.unlock(); -// uint numRemainingTris = TRI_BATCH_SIZE - ((endDest - dest) / 3); -// if (numRemainingTris) -// { -// material.setColor(CRGBA(100, 100, 100)); -// driver->setPolygonMode(IDriver::Filled); -// driver->activeVertexBuffer(vb); -// driver->renderRawTriangles(material, 0, numRemainingTris); -// material.setColor(CRGBA::White); -// driver->setPolygonMode(IDriver::Line); -// driver->renderRawTriangles(material, 0, numRemainingTris); -// } -// } - - // prepare 2D view - -// const uint GRID_EXTENT = 20; -// sint currPosX = (sint) (camMat.getPos().x / CELL_SIZE); -// sint currPosY = (sint) (camMat.getPos().y / CELL_SIZE); -// driver->setFrustum( - (float) (GRID_EXTENT - 1) * CELL_SIZE, (float) (GRID_EXTENT - 1) * CELL_SIZE, -// - (float) (GRID_EXTENT - 1) * CELL_SIZE, (float) (GRID_EXTENT - 1) * CELL_SIZE, 0.f, 1.f, false); -// vp.init(0.1f, 0.1f, 0.4f ,0.4f); -// driver->setupViewport(vp); -// viewportToScissor(vp, scissor); -// driver->setupScissor(scissor); -// // -// driver->clear2D(CRGBA(0, 127, 0, 0)); -// driver->clearZBuffer(); -// CMatrix viewMatrix; -// viewMatrix.setRot(CVector::I, -CVector::K, CVector::J); -// viewMatrix.setPos(CVector(camMat.getPos().x, camMat.getPos().y, 0.f)); -// viewMatrix.invert(); -// driver->setupViewMatrix(viewMatrix); -// driver->setupModelMatrix(CMatrix::Identity); -// -// driver->setPolygonMode(IDriver::Filled); - -// // draw covered portion of the grid -// material.setColor(CRGBA(127, 0, 0)); -// { -// CVertexBufferReadWrite vba; -// vb.lock(vba); -// CVector *dest = vba.getVertexCoordPointer(0); -// sint numQuads = 0; -// for(sint y = 0; y < (sint) silhouette.size(); ++y) -// { -// if (silhouette[y].first > silhouette[y].second) continue; -// CQuad q; -// q.V0.x = silhouette[y].first * CELL_SIZE + cornerMin.x; -// q.V0.y = (y + minY) * CELL_SIZE + cornerMin.y; -// q.V1.x = (silhouette[y].second + 1) * CELL_SIZE + cornerMin.x; -// ++ numQuads; -// q.V1.y = q.V0.y; -// q.V2.x = q.V1.x; -// q.V2.y = q.V1.y + CELL_SIZE; -// q.V3.x = q.V0.x; -// q.V3.y = q.V2.y; -// pushVBQuad2D(dest, q); -// } -// nlassert(numQuads * 4 < TRI_BATCH_SIZE * 3); -// vba.unlock(); -// driver->renderRawQuads(material, 0, numQuads); -// } -// */ - // - /* -// driver->setPolygonMode(IDriver::Line); -// // draw grid around & frustum -// { -// // -// material.setColor(CRGBA(127, 127, 127)); -// { -// CVertexBufferReadWrite vba; -// vb.lock(vba); -// CVector *dest = vba.getVertexCoordPointer(0); -// for(sint x = currPosX - GRID_EXTENT; x <= currPosX + (sint) GRID_EXTENT; ++x) -// { -// pushVBLine2D(dest, CVector(x * CELL_SIZE, (currPosY + (sint) GRID_EXTENT) * CELL_SIZE, 0.f), -// CVector(x * CELL_SIZE, (currPosY - (sint) GRID_EXTENT) * CELL_SIZE, 0.f)); -// } -// for(sint y = currPosY - GRID_EXTENT; y <= currPosY + (sint) GRID_EXTENT; ++y) -// { -// pushVBLine2D(dest, CVector((currPosX - (sint) GRID_EXTENT) * CELL_SIZE, y * CELL_SIZE, 0.f), -// CVector((currPosX + (sint) GRID_EXTENT) * CELL_SIZE, y * CELL_SIZE, 0.f)); -// } -// vba.unlock(); -// uint numTri = 2 * (2 * GRID_EXTENT + 1); -// nlassert(numTri <= TRI_BATCH_SIZE); -// driver->renderRawTriangles(material, 0, numTri); -// } -// material.setColor(CRGBA::Red); -// { -// CVertexBufferReadWrite vba; -// vb.lock(vba); -// CVector *dest = vba.getVertexCoordPointer(0); -// for(uint k = 0; k < sizeofarray(localFrustCorners); ++k) -// { -// frustCorners[k].x += cornerMin.x; -// frustCorners[k].y += cornerMin.y; -// } -// pushVBLine2D(dest, frustCorners[1], frustCorners[5]); -// pushVBLine2D(dest, frustCorners[5], frustCorners[6]); -// pushVBLine2D(dest, frustCorners[6], frustCorners[2]); -// pushVBLine2D(dest, frustCorners[2], frustCorners[1]); -// // -// pushVBLine2D(dest, frustCorners[5], frustCorners[4]); -// pushVBLine2D(dest, frustCorners[4], frustCorners[7]); -// pushVBLine2D(dest, frustCorners[7], frustCorners[6]); -// // -// pushVBLine2D(dest, frustCorners[4], frustCorners[0]); -// pushVBLine2D(dest, frustCorners[0], frustCorners[3]); -// pushVBLine2D(dest, frustCorners[3], frustCorners[7]); -// // -// pushVBLine2D(dest, frustCorners[0], frustCorners[1]); -// pushVBLine2D(dest, frustCorners[3], frustCorners[2]); -// // -// nlassert(12 <= TRI_BATCH_SIZE); -// vba.unlock(); -// material.setColor(CRGBA::Red); -// driver->renderRawTriangles(material, 0, 12); -// } -// } -// - -// // draw underlying geometry -// material.setColor(CRGBA::White); -// { -// CVertexBufferReadWrite vba; -// vb.lock(vba); -// CVector *dest = vba.getVertexCoordPointer(0); -// const CVector *endDest = dest + TRI_BATCH_SIZE * 3; -// // compute cam pos in tri grid -// currPosX = (sint) ((camMat.getPos().x - cornerMin.x) / CELL_SIZE); -// currPosY = (sint) ((camMat.getPos().y - cornerMin.y) / CELL_SIZE); -// for(sint y = currPosY - GRID_EXTENT; y < currPosY + (sint) GRID_EXTENT; ++y) -// { -// for(sint x = currPosX - GRID_EXTENT; x < currPosX + (sint) GRID_EXTENT; ++x) -// { -// if (y < 0) continue; -// if (y >= triGridHeight) break; -// if (x < 0) continue; -// if (x >= triGridWidth) break; -// sint triRefIndex = triGrid(x, y); -// while (triRefIndex != -1) -// { -// CTriangle tri = tris[triRefs[triRefIndex].TriIndex]; -// tri.V0.x += cornerMin.x; -// tri.V0.y += cornerMin.y; -// tri.V1.x += cornerMin.x; -// tri.V1.y += cornerMin.y; -// tri.V2.x += cornerMin.x; -// tri.V2.y += cornerMin.y; -// -// triRefIndex = triRefs[triRefIndex].NextTriRef; -// pushVBTri2D(dest, tri); -// if (dest == endDest) -// { -// // flush batch -// vba.unlock(); -// driver->renderRawTriangles(material, 0, TRI_BATCH_SIZE); -// // reclaim a new batch -// vb.lock(vba); -// dest = vba.getVertexCoordPointer(0); -// endDest = dest + TRI_BATCH_SIZE * 3; -// } -// } -// } -// } -// vba.unlock(); -// uint numRemainingTris = TRI_BATCH_SIZE - ((endDest - dest) / 3); -// if (numRemainingTris) -// { -// driver->renderRawTriangles(material, 0, numRemainingTris); -// } -// } - - uint NUM_RAYS = 10000; - if (CNELU::AsyncListener.isKeyPushed(KeyT)) - { - printf("Starting raytracing test 1"); - uint numHits = 0; - NLMISC::TTime startTime = CTime::getLocalTime(); - for(uint k = 0; k < NUM_RAYS; ++k) - { - sint zone = rand() % packedZonesArray.size(); - CPackedZoneBase *zonePtr = packedZonesArray[zone]; - CVector cornerMin = zonePtr->Box.getMin(); - CVector cornerMax = zonePtr->Box.getMax(); - CVector start(frand(1.f) * (cornerMax.x - cornerMin.x) + cornerMin.x, - frand(1.f) * (cornerMax.y - cornerMin.y) + cornerMin.y, - frand(1.f) * (cornerMax.z - cornerMin.z) + cornerMin.z); - CVector end(frand(1.f) * (cornerMax.x - cornerMin.x) + cornerMin.x, - frand(1.f) * (cornerMax.y - cornerMin.y) + cornerMin.y, - frand(1.f) * (cornerMax.z - cornerMin.z) + cornerMin.z); - CVector inter; - bool result = pw.raytrace(start, end, inter); - if (result) - { - ++numHits; - } - } - NLMISC::TTime endTime = CTime::getLocalTime(); - - float dt = (float) (endTime - startTime) / 1000.f; - printf("Total time = %.2f s\n", dt); - printf("Num rays = %d\n", (int) NUM_RAYS); - printf("Num hits = %d\n", (int) numHits); - printf("Num test per seconds = %.2f\n", (float) NUM_RAYS / dt); - } - // - if (CNELU::AsyncListener.isKeyPushed(KeyU)) - { - printf("Starting raytracing test 2"); - uint numHits = 0; - NLMISC::TTime startTime = CTime::getLocalTime(); - for(uint k = 0; k < NUM_RAYS; ++k) - { - CVector start = camMat.getPos(); - CVector end(start.x + (frand(200.f) - 100.f), - start.y + (frand(200.f) - 100.f), - start.z + (frand(5.f) - 2.5f)); - CVector inter; - bool result = pw.raytrace(start, end, inter); - if (result) - { - ++numHits; - } - } - NLMISC::TTime endTime = CTime::getLocalTime(); - - float dt = (float) (endTime - startTime) / 1000.f; - printf("Total time = %.2f s\n", dt); - printf("Num rays = %d\n", (int) NUM_RAYS); - printf("Num hits = %d\n", (int) numHits); - printf("Num test per seconds = %.2f\n", (float) NUM_RAYS / dt); - } - // - driver->setPolygonMode(IDriver::Filled); - // - driver->swapBuffers(); - } - while(!CNELU::AsyncListener.isKeyPushed(KeyESCAPE)); - - - - return 0; -} - -*/ - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +/*#include "std_header.h" +// +// test_col_world.cpp : Defines the entry point for the console application. +// +#include "zone_util.h" +#include "village.h" +// +#include "nel/misc/array_2d.h" +#include "nel/misc/config_file.h" +#include "nel/misc/path.h" +#include "nel/misc/file.h" +#include "nel/misc/vector_2f.h" +#include "nel/misc/triangle.h" +#include "nel/misc/polygon.h" +#include "nel/misc/smart_ptr.h" +#include "nel/misc/quad.h" +// +#include "nel/3d/frustum.h" +#include "nel/3d/viewport.h" +#include "nel/3d/scissor.h" +#include "nel/misc/aabbox.h" +#include "nel/misc/stream.h" +// +#include "3d/landscape.h" +#include "3d/zone.h" +#include "3d/quad_grid.h" +#include "3d/event_mouse_listener.h" +#include "3d/vertex_buffer.h" +#include "3d/material.h" +#include "3d/register_3d.h" +#include "3d/nelu.h" +#include "3d/scene_group.h" +#include "3d/shape_info.h" +#include "3d/packed_zone.h" +#include "3d/packed_world.h" +// +#include +// + +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" +#include "nel/georges/u_form_loader.h" + + +using namespace NLMISC; +using namespace NL3D; + + + +static inline void pushVBQuad(NLMISC::CVector *&dest, const NLMISC::CQuad &quad) +{ + *dest++ = quad.V0; + *dest++ = quad.V1; + *dest++ = quad.V2; + *dest++ = quad.V3; +} + + +class CZoneRefCount : public CRefCount +{ +public: + CZone Zone; + bool Loaded; + std::string Path; + std::string IGPath; + sint X; + sint Y; +public: + CZoneRefCount() : Loaded(false) {} +}; + + +static void viewportToScissor(const CViewport &vp, CScissor &scissor) +{ + scissor.X = vp.getX(); + scissor.Y = vp.getY(); + scissor.Width = vp.getWidth(); + scissor.Height = vp.getHeight(); +} + + + + +// load list of continent from the .world sheet +static bool loadContinentList(const std::string &worldSheet, std::vector &continentList) +{ + NLGEORGES::UFormLoader *loader = NLGEORGES::UFormLoader::createLoader(); + // + std::string path = CPath::lookup(worldSheet, false, false); + if (path.empty()) + { + NLGEORGES::UFormLoader::releaseLoader(loader); + nlwarning("Path not found for %s.", worldSheet.c_str()); + return false; + } + NLGEORGES::UForm *worldForm; + worldForm = loader->loadForm(path.c_str()); + if (worldForm == NULL) + { + NLGEORGES::UFormLoader::releaseLoader(loader); + return false; + } + + uint size; + NLGEORGES::UFormElm *pElt; + nlverify (worldForm->getRootNode().getNodeByName (&pElt, "continents list")); + if(!pElt) + { + nlwarning("node 'continents list' not found in a .world"); + NLGEORGES::UFormLoader::releaseLoader(loader); + return false; + } + else + { + nlverify (pElt->getArraySize (size)); + for (uint32 i = 0; i getArrayNode (&pEltOfList, i) && pEltOfList) + { + std::string continentName; + pEltOfList->getValueByName (continentName, "continent_name"); + if (CFile::getExtension(continentName).empty()) + { + continentName += ".continent"; + } + continentList.push_back(continentName); + } + } + } + NLGEORGES::UFormLoader::releaseLoader(loader); + return true; +} + + +class CRemoveBorderLeavePred +{ +public: + CRemoveBorderLeavePred(uint16 zoneId) : ZoneId(zoneId) {} + bool operator()(const CTessFace *tf) const + { + return tf->Patch->getZone()->getZoneId() != ZoneId; + } + uint16 ZoneId; +}; + + +static bool parseCamPos(CConfigFile &cf, CVector &camPos) +{ + CConfigFile::CVar *camPosVar = cf.getVarPtr("CamPos"); + if (camPosVar) + { + if (camPosVar->size() == 3) + { + camPos.x = camPosVar->asFloat(0); + camPos.y = camPosVar->asFloat(1); + camPos.z = camPosVar->asFloat(2); + return true; + } + else + { + // it is a zone name + sint zoneX, zoneY; + if (getZonePos(camPosVar->asString(), zoneX, zoneY)) + { + camPos.x = 160.f * zoneX + 80.f; + camPos.y = 160.f * zoneY + 80.f; + camPos.z = 0.f; + return true; + } + } + } + return false; +} + +static bool parseCamSpeed(CConfigFile &cf, float &camSpeed) +{ + CConfigFile::CVar *camSpeedVar = cf.getVarPtr("CamSpeed"); + if (camSpeedVar) + { + camSpeed = camSpeedVar->asFloat(); + return true; + } + return false; +} + +static bool newCamSpeedWanted = false; +static float newCamSpeed = FLT_MIN; +static bool newCamPosWanted = false; + +static CVector newCamPos(FLT_MAX, FLT_MAX, FLT_MAX); + +static void configFileChanged(const std::string &filename) +{ + CConfigFile cf; + try + { + cf.load(filename); + CVector camPos; + if (parseCamPos(cf, camPos)) + { + if (camPos!= newCamPos) + { + newCamPos = camPos; + newCamPosWanted = true; + } + } + float camSpeed; + if (parseCamSpeed(cf, camSpeed)) + { + if (camSpeed != newCamSpeed) + { + newCamSpeed= camSpeed; + newCamSpeedWanted = true; + } + } + } + catch(const EStream &) + { + printf("Error while reading config file\n"); + } +} + +int main(int argc, char* argv[]) +{ + registerSerial3d(); + + if (argc != 2) + { + printf("usage : %s config_file_name.cfg\n", CFile::getFilename(argv[0]).c_str()); + return -1; + } + // + std::string worldSheetName; + // + std::string cachePath; + // load all landscape zones + std::vector zoneNames; + CConfigFile cf; + CVector camPos(18927.f, -24382.f, 0.f); + + bool addLandscapeIG = false; + + float camSpeed = 35.f; + try + { + cf.load(argv[1]); + parseCamPos(cf, camPos); + newCamPos = camPos; + parseCamSpeed(cf, camSpeed); + newCamSpeed = camSpeed; + CConfigFile::CVar &paths = cf.getVar("ZonesPaths"); + for(uint k = 0; k < (uint) paths.size(); ++k) + { + std::vector files; + CPath::getPathContent(paths.asString(k), true, false, true, files); + for(uint l = 0; l < files.size(); ++l) + { + std::string ext = CFile::getExtension(files[l]); + if (nlstricmp(ext, "zonel") == 0) + { + zoneNames.push_back(files[l]); + } + } + } + cachePath = cf.getVar("CachePath").asString(); + CConfigFile::CVar *searchPaths = cf.getVarPtr("SearchPaths"); + for(uint k = 0; k < (uint) searchPaths->size(); ++k) + { + CPath::addSearchPath(searchPaths->asString(k), true, false); + } + CConfigFile::CVar *addLandscapeIGVarPtr = cf.getVarPtr("AddLandscapeIG"); + if (addLandscapeIGVarPtr) + { + addLandscapeIG = addLandscapeIGVarPtr->asInt() != 0; + } + } + catch(const EStream &) + { + printf("Error while reading config file\n"); + return -1; + } + catch(const EConfigFile &e) + { + printf(e.what()); + return -1; + } + // + CFile::addFileChangeCallback(argv[1], configFileChanged); + // + std::vector > zones; + zones.reserve(zoneNames.size()); + sint zoneMinX, zoneMaxX; + sint zoneMinY, zoneMaxY; + bool firstZoneCorner = true; + for(uint k = 0; k < zoneNames.size(); ++k) + { + CSmartPtr zoneRef = new CZoneRefCount; + zoneRef->Path = zoneNames[k]; + if (addLandscapeIG) + { + std::string igFileName = CFile::getFilenameWithoutExtension(zoneRef->Path) + ".ig"; + zoneRef->IGPath = CPath::lookup(igFileName, false, false); + if (zoneRef->IGPath.empty()) + { + nlwarning("Couldn't find ig %s. Maybe there's no ig for that zone.", igFileName.c_str()); + } + } + //printf("Loading zone %d / %d \n", (int) k + 1, (int) zoneNames.size()); + CVector2f zoneCornerMin, zoneCornerMax; + if (getZonePos(zoneNames[k], zoneRef->X, zoneRef->Y)) + { + if (firstZoneCorner) + { + zoneMinX = zoneMaxX = zoneRef->X; + zoneMinY = zoneMaxY = zoneRef->Y; + firstZoneCorner = false; + } + else + { + zoneMinX = std::min(zoneMinX, zoneRef->X); + zoneMaxX = std::max(zoneMaxX, zoneRef->X); + zoneMinY = std::min(zoneMinY, zoneRef->Y); + zoneMaxY = std::max(zoneMaxY, zoneRef->Y); + } + zones.push_back(zoneRef); + } + } + if (zones.empty()) + { + printf("No zones loaded \n"); + return -1; + } + uint gridWidth = zoneMaxX - zoneMinX + 1; + uint gridHeight = zoneMaxY - zoneMinY + 1; + // build a grid of zones + CArray2D zoneGrid; + CArray2D packedZoneGrid; + zoneGrid.init(gridWidth, gridHeight, NULL); + packedZoneGrid.init(gridWidth, gridHeight); + for(uint k = 0; k < zones.size(); ++k) + { + sint x = zones[k]->X - zoneMinX; + sint y = zones[k]->Y - zoneMinY; + zoneGrid(x, y) = zones[k]; + } + // build grid for tris + CVector2f cornerMin, cornerMax; + cornerMin.set(zoneMinX * 160.f, zoneMinY * 160.f); + cornerMax.set((zoneMaxX + 1) * 160.f, (zoneMaxY + 1) * 160.f); + const float CELL_SIZE = 4.f; // resolution of tri grid + + CVillageGrid vg; + vg.init(gridWidth, gridHeight, zoneMinX, zoneMinY); + + + std::vector continentList; + CConfigFile::CVar *worldSheetPtr = cf.getVarPtr("WorldSheet"); + if (!(worldSheetPtr && loadContinentList(worldSheetPtr->asString(), continentList))) + { + CConfigFile::CVar *continentSheetNames = cf.getVarPtr("ContinentSheetNames"); + std::vector > igs; + if (!continentSheetNames) + { + nlwarning("No villages added to collisions"); + } + else + { + for(uint k = 0; k < (uint) continentSheetNames->size(); ++k) + { + continentList.push_back(continentSheetNames->asString(k)); + } + } + } + + bool addVillages = true; + CConfigFile::CVar *addVillagesVar = cf.getVarPtr("AddVillages"); + if (addVillagesVar) + { + addVillages = addVillagesVar->asBool(); + } + if (addVillages) + { + for(uint k = 0; k < (uint) continentList.size(); ++k) + { + vg.addVillagesFromContinent(continentList[k]); + } + } + + TShapeCache shapeCache; + + + + // build each zone separatly + static std::vector leaves; + uint currZoneIndex = 0; + for (sint y = 0; y < (sint) zoneGrid.getHeight(); ++y) + { + for (sint x = 0; x < (sint) zoneGrid.getWidth(); ++x) + { + if (zoneGrid(x, y)) + { + std::string cacheFilename = CPath::standardizePath(cachePath) + CFile::getFilenameWithoutExtension(zoneGrid(x, y)->Path) + ".packed_zone"; + bool mustRebuild = false; + + // if there's any village on this zone that is more recent than the zone, then must rebuild the zone + { + const std::list &villageList = vg.VillageGrid(x, y); + for(std::list::const_iterator it = villageList.begin(); it != villageList.end(); ++it) + { + uint32 modifDate = vg.Villages[*it].FileModificationDate; + uint32 cacheDate = CFile::getFileModificationDate(cacheFilename); + if (modifDate > cacheDate) + { + mustRebuild = true; + break; + } + } + } + + // if landscape ig is reclaimed, see if it is more recent + if (!zoneGrid(x, y)->IGPath.empty()) + { + if (CFile::getFileModificationDate(zoneGrid(x, y)->IGPath) >= CFile::getFileModificationDate(cacheFilename)) + { + mustRebuild = true; + } + } + + if (!mustRebuild) + { + mustRebuild = true; + // see if zone is present in cache and is valid + if (CFile::getFileModificationDate(cacheFilename) >= CFile::getFileModificationDate(zoneGrid(x, y)->Path)) + { + // try to retrieve file from cache + try + { + CIFile f; + f.open(cacheFilename); + CPackedZoneBase *pb; + f.serialPolyPtr(pb); + packedZoneGrid(x, y) = pb; + mustRebuild = false; + printf("Retrieving zone %d / %d from cache\n", (int) currZoneIndex + 1, (int) zones.size()); + } + catch(const EStream &) + { + } + } + } + + if (mustRebuild) + { + printf("Rebuilding zone %d / %d \n", (int) currZoneIndex + 1, (int) zones.size()); + CLandscape *landscape = new CLandscape; + landscape->init(); + landscape->setThreshold (8.f / (1000.f * 1000.f)); + //landscape->setThreshold(0); + landscape->setTileMaxSubdivision (0); + // add wanted zone & all zones around for continuity + for (sint ly = y - 1; ly <= y + 1; ++ly) + { + if (ly < 0) continue; + if (ly >= (sint) gridHeight) break; + for (sint lx = x - 1; lx <= x + 1; ++lx) + { + if (lx < 0) continue; + if (lx >= (sint) gridWidth) break; + if (zoneGrid(lx, ly)) + { + if (!zoneGrid(lx, ly)->Loaded) + { + CIFile stream; + try + { + stream.open(zoneGrid(lx, ly)->Path); + zoneGrid(lx, ly)->Zone.serial(stream); + zoneGrid(lx, ly)->Loaded = true; + } + catch(const EStream &) + { + printf("Error while loading zone %s : zone not loaded \n"); + } + } + if (zoneGrid(lx, ly)->Loaded) + { + landscape->addZone(zoneGrid(lx, ly)->Zone); + } + } + } + } + // + landscape->refineAll(CVector((x + zoneMinX) * 160.f + 80.f, (y + zoneMinY) * 160.f + 80.f, 1000.f)); + // + // Dump tesselated triangles + leaves.clear(); + landscape->getTessellationLeaves(leaves); + leaves.erase(std::remove_if(leaves.begin(), leaves.end(), CRemoveBorderLeavePred(zoneGrid(x, y)->Zone.getZoneId())), leaves.end()); + // gather and load list of villages ig + std::vector igs; + if (addVillages) + { + const std::list &villageList = vg.VillageGrid(x, y); + for(std::list::const_iterator it = villageList.begin(); it != villageList.end(); ++it) + { + CVillage &village = vg.Villages[*it]; + village.load(shapeCache); // load if needed + for(uint k = 0; k < village.IG.size(); ++k) + { + if (village.IG[k].IG) + { + igs.push_back(village.IG[k].IG); + } + } + } + } + // + CAABBox baseZoneBBox; + CVector zoneMinCorner((x + zoneMinX) * 160.f, (y + zoneMinY) * 160.f, 0.f); + baseZoneBBox.setMinMax(zoneMinCorner, zoneMinCorner + CVector(160.f, 160.f, 1.f)); + CSmartPtr pz32 = new CPackedZone32; + // + pz32->build(leaves, CELL_SIZE, igs, shapeCache, baseZoneBBox, (sint32) (x + zoneMinX), (sint32) (y + zoneMinY)); + // + // try to convert to 16 bit indices to save some place + CSmartPtr pz16 = pz32->buildPackedZone16(); + if (pz16) + { + packedZoneGrid(x, y) = pz16; + } + else + { + packedZoneGrid(x, y) = pz32; + } + // write result in cache + try + { + if (!CFile::isExists(cachePath)) + { + CFile::createDirectoryTree(cachePath); + } + COFile f; + f.open(cacheFilename); + CPackedZoneBase *pb = packedZoneGrid(x, y); + f.serialPolyPtr(pb); + } + catch(const EStream &e) + { + printf("Error while writing packed zone to cache : \n %s \n", e.what()); + } + // + delete landscape; + } + ++ currZoneIndex; + } + } + } + zoneGrid.clear(); + shapeCache.clear(); + + + std::vector packedZonesArray; + for (sint y = 0; y < (sint) packedZoneGrid.getHeight(); ++y) + { + for (sint x = 0; x < (sint) packedZoneGrid.getWidth(); ++x) + { + if (packedZoneGrid(x, y)) + { + packedZonesArray.push_back(packedZoneGrid(x, y)); + } + } + } + + // build packed world + CPackedWorld pw; + pw.build(packedZonesArray); + + + bool fly = true; + CConfigFile::CVar *flyVar = cf.getVarPtr("Fly"); + if (flyVar) + { + fly = flyVar->asBool(); + } + + if (!fly) return 0; + + // fly into scene + try + { + CNELU::init(1024, 768, CViewport(), 32, true, NULL, false, true); + } + catch(const Exception &e) + { + puts(e.what()); + getchar(); + return -1; + } + // + CFrustum frust; + frust.init(-0.1f, 0.1f, -0.1f, 0.1f, 0.1f, 150.f, 1); + // + + CMatrix camMat; + camMat.identity(); + camMat.setPos(camPos); + // + IDriver *driver = CNELU::Driver; + CEvent3dMouseListener mouseListener; + mouseListener.setMatrix(camMat); + mouseListener.setMouseMode(U3dMouseListener::firstPerson); + mouseListener.setFrustrum(frust); + mouseListener.addToServer(CNELU::EventServer); + mouseListener.setSpeed(camSpeed); + CVertexBuffer vb; + vb.setVertexFormat(CVertexBuffer::PositionFlag); + vb.setPreferredMemory(CVertexBuffer::AGPVolatile, false); + // + CMaterial material; + material.initUnlit(); + material.setDoubleSided(true); + material.setZFunc(CMaterial::lessequal); + // + do + { + printf("zone = %s \n", posToZoneName(camMat.getPos().x, camMat.getPos().y).c_str()); + // + CFile::checkFileChange(); + if (newCamPosWanted) + { + camMat.setPos(newCamPos); + mouseListener.setMatrix(camMat); + newCamPosWanted = false; + } + if (newCamSpeedWanted) + { + mouseListener.setSpeed(newCamSpeed); + newCamSpeedWanted = false; + } + const CRGBA clearColor = CRGBA(0, 0, 127, 0); + driver->enableFog(true); + driver->setupFog(frust.Far * 0.8f, frust.Far, clearColor); + CViewport vp; + vp.init(0.f, 0.f, 1.f, 1.f); + driver->setupViewport(vp); + CScissor scissor; + viewportToScissor(vp, scissor); + driver->setupScissor(scissor); + + CNELU::EventServer.pump(); + camMat = mouseListener.getViewMatrix(); + // + driver->clear2D(clearColor); + driver->clearZBuffer(); + // + driver->setFrustum(frust.Left, frust.Right, frust.Bottom, frust.Top, frust.Near, frust.Far, frust.Perspective); + driver->setupViewMatrix(camMat.inverted()); + driver->setupModelMatrix(CMatrix::Identity); + // + // + const CVector localFrustCorners[8] = + { + CVector(frust.Left, frust.Near, frust.Top), + CVector(frust.Right, frust.Near, frust.Top), + CVector(frust.Right, frust.Near, frust.Bottom), + CVector(frust.Left, frust.Near, frust.Bottom), + CVector(frust.Left * frust.Far / frust.Near, frust.Far, frust.Top * frust.Far / frust.Near), + CVector(frust.Right * frust.Far / frust.Near, frust.Far, frust.Top * frust.Far / frust.Near), + CVector(frust.Right * frust.Far / frust.Near, frust.Far, frust.Bottom * frust.Far / frust.Near), + CVector(frust.Left * frust.Far / frust.Near, frust.Far, frust.Bottom * frust.Far / frust.Near) + }; + // roughly compute covered zones + // + sint frustZoneMinX = INT_MAX; + sint frustZoneMaxX = INT_MIN; + sint frustZoneMinY = INT_MAX; + sint frustZoneMaxY = INT_MIN; + for(uint k = 0; k < sizeofarray(localFrustCorners); ++k) + { + CVector corner = camMat * localFrustCorners[k]; + sint zoneX = (sint) (corner.x / 160.f) - zoneMinX; + sint zoneY = (sint) floorf(corner.y / 160.f) - zoneMinY; + frustZoneMinX = std::min(frustZoneMinX, zoneX); + frustZoneMinY = std::min(frustZoneMinY, zoneY); + frustZoneMaxX = std::max(frustZoneMaxX, zoneX); + frustZoneMaxY = std::max(frustZoneMaxY, zoneY); + } + + const uint TRI_BATCH_SIZE = 10000; // batch size for rendering + + + //for (sint y = frustZoneMinY; y <= frustZoneMaxY; ++y) + //{ + //if (y < 0) continue; + //if (y >= (sint) gridHeight) break; + //for (sint x = frustZoneMinX; x <= frustZoneMaxX; ++x) + //{ + //if (x < 0) continue; + //if (x >= (sint) gridWidth) break; + //if (packedZoneGrid(x, y)) + //{ + //packedZoneGrid(x, y)->render(vb, *driver, material, camMat, TRI_BATCH_SIZE, localFrustCorners); + //} + //} + //} + + + for (sint y = 0; y <= (sint) gridHeight; ++y) + { + if (y < 0) continue; + if (y >= (sint) gridHeight) break; + for (sint x = 0; x <= (sint) gridWidth; ++x) + { + if (x < 0) continue; + if (x >= (sint) gridWidth) break; + if (packedZoneGrid(x, y)) + { + packedZoneGrid(x, y)->render(vb, *driver, material, camMat, TRI_BATCH_SIZE, localFrustCorners); + } + } + } + + driver->setPolygonMode(IDriver::Filled); + material.setColor(CRGBA::Green); + // compute intersection with landscape & display a dot at that position + CVector lookAtPos = camMat.getPos() + 1000.f * camMat.getJ(); + CVector inter; + static std::vector triList; + triList.clear(); + bool interFound = pw.raytrace(camMat.getPos(), lookAtPos, inter, &triList); + if (!triList.empty()) + { + vb.setNumVertices(3 * triList.size()); + CVertexBufferReadWrite vba; + vb.lock(vba); + CVector *dest = vba.getVertexCoordPointer(0); + memcpy(dest, &triList[0], sizeof(CTriangle) * triList.size()); + vba.unlock(); + driver->activeVertexBuffer(vb); + driver->renderRawTriangles(material, 0, triList.size()); + } + if (interFound) + { + material.setColor(CRGBA::Magenta); + CQuad q; + q.V0 = inter - camMat.getI() + camMat.getK(); + q.V1 = inter + camMat.getI() + camMat.getK(); + q.V2 = inter + camMat.getI() - camMat.getK(); + q.V3 = inter - camMat.getI() - camMat.getK(); + { + vb.setNumVertices(4); + CVertexBufferReadWrite vba; + vb.lock(vba); + CVector *dest = vba.getVertexCoordPointer(0); + pushVBQuad(dest, q); + vba.unlock(); + } + driver->activeVertexBuffer(vb); + driver->renderRawQuads(material, 0, 1); + } + // +// for(uint k = 0; k < sizeofarray(frustCorners); ++k) +// { +// frustCorners[k] = camMat * frustCorners[k]; +// frustCorners[k].x -= cornerMin.x; +// frustCorners[k].y -= cornerMin.y; +// } +// // project frustum on x/y plane to see where to test polys +// sint minY = INT_MAX; +// CPolygon2D::TRasterVect silhouette; +// addQuadToSilhouette(frustCorners[0], frustCorners[1], frustCorners[2], frustCorners[3], silhouette, minY, CELL_SIZE); +// addQuadToSilhouette(frustCorners[1], frustCorners[5], frustCorners[6], frustCorners[2], silhouette, minY, CELL_SIZE); +// addQuadToSilhouette(frustCorners[4], frustCorners[5], frustCorners[6], frustCorners[7], silhouette, minY, CELL_SIZE); +// addQuadToSilhouette(frustCorners[0], frustCorners[4], frustCorners[7], frustCorners[3], silhouette, minY, CELL_SIZE); +// addQuadToSilhouette(frustCorners[0], frustCorners[1], frustCorners[5], frustCorners[4], silhouette, minY, CELL_SIZE); +// addQuadToSilhouette(frustCorners[3], frustCorners[7], frustCorners[6], frustCorners[2], silhouette, minY, CELL_SIZE); +// // +// driver->setPolygonMode(IDriver::Line); +// // +// material.setColor(CRGBA::White); +// // +// vb.setNumVertices(TRI_BATCH_SIZE * 3); +// { +// CVertexBufferReadWrite vba; +// vb.lock(vba); +// CVector *dest = vba.getVertexCoordPointer(0); +// const CVector *endDest = dest + TRI_BATCH_SIZE * 3; +// for(sint y = 0; y < (sint) silhouette.size(); ++y) +// { +// sint gridY = y + minY; +// if (gridY < 0) continue; +// if (gridY >= triGridHeight) continue; +// sint minX = silhouette[y].first; +// sint maxX = silhouette[y].second; +// for (sint x = minX; x <= maxX; ++x) +// { +// if (x < 0) continue; +// if (x >= triGridWidth) break; +// sint triRefIndex = triGrid(x, gridY); +// while (triRefIndex != -1) +// { +// CTriangle tri = tris[triRefs[triRefIndex].TriIndex]; +// triRefIndex = triRefs[triRefIndex].NextTriRef; +// tri.V0.x += cornerMin.x; +// tri.V0.y += cornerMin.y; +// tri.V1.x += cornerMin.x; +// tri.V1.y += cornerMin.y; +// tri.V2.x += cornerMin.x; +// tri.V2.y += cornerMin.y; +// *dest++ = tri.V0; +// *dest++ = tri.V1; +// *dest++ = tri.V2; +// if (dest == endDest) +// { +// // flush batch +// vba.unlock(); +// material.setColor(CRGBA(100, 100, 100)); +// driver->setPolygonMode(IDriver::Filled); +// driver->renderRawTriangles(material, 0, TRI_BATCH_SIZE); +// material.setColor(CRGBA::White); +// driver->setPolygonMode(IDriver::Line); +// driver->renderRawTriangles(material, 0, TRI_BATCH_SIZE); +// // reclaim a new batch +// vb.lock(vba); +// dest = vba.getVertexCoordPointer(0); +// endDest = dest + TRI_BATCH_SIZE * 3; +// } +// } +// } +// } +// vba.unlock(); +// uint numRemainingTris = TRI_BATCH_SIZE - ((endDest - dest) / 3); +// if (numRemainingTris) +// { +// material.setColor(CRGBA(100, 100, 100)); +// driver->setPolygonMode(IDriver::Filled); +// driver->activeVertexBuffer(vb); +// driver->renderRawTriangles(material, 0, numRemainingTris); +// material.setColor(CRGBA::White); +// driver->setPolygonMode(IDriver::Line); +// driver->renderRawTriangles(material, 0, numRemainingTris); +// } +// } + + // prepare 2D view + +// const uint GRID_EXTENT = 20; +// sint currPosX = (sint) (camMat.getPos().x / CELL_SIZE); +// sint currPosY = (sint) (camMat.getPos().y / CELL_SIZE); +// driver->setFrustum( - (float) (GRID_EXTENT - 1) * CELL_SIZE, (float) (GRID_EXTENT - 1) * CELL_SIZE, +// - (float) (GRID_EXTENT - 1) * CELL_SIZE, (float) (GRID_EXTENT - 1) * CELL_SIZE, 0.f, 1.f, false); +// vp.init(0.1f, 0.1f, 0.4f ,0.4f); +// driver->setupViewport(vp); +// viewportToScissor(vp, scissor); +// driver->setupScissor(scissor); +// // +// driver->clear2D(CRGBA(0, 127, 0, 0)); +// driver->clearZBuffer(); +// CMatrix viewMatrix; +// viewMatrix.setRot(CVector::I, -CVector::K, CVector::J); +// viewMatrix.setPos(CVector(camMat.getPos().x, camMat.getPos().y, 0.f)); +// viewMatrix.invert(); +// driver->setupViewMatrix(viewMatrix); +// driver->setupModelMatrix(CMatrix::Identity); +// +// driver->setPolygonMode(IDriver::Filled); + +// // draw covered portion of the grid +// material.setColor(CRGBA(127, 0, 0)); +// { +// CVertexBufferReadWrite vba; +// vb.lock(vba); +// CVector *dest = vba.getVertexCoordPointer(0); +// sint numQuads = 0; +// for(sint y = 0; y < (sint) silhouette.size(); ++y) +// { +// if (silhouette[y].first > silhouette[y].second) continue; +// CQuad q; +// q.V0.x = silhouette[y].first * CELL_SIZE + cornerMin.x; +// q.V0.y = (y + minY) * CELL_SIZE + cornerMin.y; +// q.V1.x = (silhouette[y].second + 1) * CELL_SIZE + cornerMin.x; +// ++ numQuads; +// q.V1.y = q.V0.y; +// q.V2.x = q.V1.x; +// q.V2.y = q.V1.y + CELL_SIZE; +// q.V3.x = q.V0.x; +// q.V3.y = q.V2.y; +// pushVBQuad2D(dest, q); +// } +// nlassert(numQuads * 4 < TRI_BATCH_SIZE * 3); +// vba.unlock(); +// driver->renderRawQuads(material, 0, numQuads); +// } +// */ + // + /* +// driver->setPolygonMode(IDriver::Line); +// // draw grid around & frustum +// { +// // +// material.setColor(CRGBA(127, 127, 127)); +// { +// CVertexBufferReadWrite vba; +// vb.lock(vba); +// CVector *dest = vba.getVertexCoordPointer(0); +// for(sint x = currPosX - GRID_EXTENT; x <= currPosX + (sint) GRID_EXTENT; ++x) +// { +// pushVBLine2D(dest, CVector(x * CELL_SIZE, (currPosY + (sint) GRID_EXTENT) * CELL_SIZE, 0.f), +// CVector(x * CELL_SIZE, (currPosY - (sint) GRID_EXTENT) * CELL_SIZE, 0.f)); +// } +// for(sint y = currPosY - GRID_EXTENT; y <= currPosY + (sint) GRID_EXTENT; ++y) +// { +// pushVBLine2D(dest, CVector((currPosX - (sint) GRID_EXTENT) * CELL_SIZE, y * CELL_SIZE, 0.f), +// CVector((currPosX + (sint) GRID_EXTENT) * CELL_SIZE, y * CELL_SIZE, 0.f)); +// } +// vba.unlock(); +// uint numTri = 2 * (2 * GRID_EXTENT + 1); +// nlassert(numTri <= TRI_BATCH_SIZE); +// driver->renderRawTriangles(material, 0, numTri); +// } +// material.setColor(CRGBA::Red); +// { +// CVertexBufferReadWrite vba; +// vb.lock(vba); +// CVector *dest = vba.getVertexCoordPointer(0); +// for(uint k = 0; k < sizeofarray(localFrustCorners); ++k) +// { +// frustCorners[k].x += cornerMin.x; +// frustCorners[k].y += cornerMin.y; +// } +// pushVBLine2D(dest, frustCorners[1], frustCorners[5]); +// pushVBLine2D(dest, frustCorners[5], frustCorners[6]); +// pushVBLine2D(dest, frustCorners[6], frustCorners[2]); +// pushVBLine2D(dest, frustCorners[2], frustCorners[1]); +// // +// pushVBLine2D(dest, frustCorners[5], frustCorners[4]); +// pushVBLine2D(dest, frustCorners[4], frustCorners[7]); +// pushVBLine2D(dest, frustCorners[7], frustCorners[6]); +// // +// pushVBLine2D(dest, frustCorners[4], frustCorners[0]); +// pushVBLine2D(dest, frustCorners[0], frustCorners[3]); +// pushVBLine2D(dest, frustCorners[3], frustCorners[7]); +// // +// pushVBLine2D(dest, frustCorners[0], frustCorners[1]); +// pushVBLine2D(dest, frustCorners[3], frustCorners[2]); +// // +// nlassert(12 <= TRI_BATCH_SIZE); +// vba.unlock(); +// material.setColor(CRGBA::Red); +// driver->renderRawTriangles(material, 0, 12); +// } +// } +// + +// // draw underlying geometry +// material.setColor(CRGBA::White); +// { +// CVertexBufferReadWrite vba; +// vb.lock(vba); +// CVector *dest = vba.getVertexCoordPointer(0); +// const CVector *endDest = dest + TRI_BATCH_SIZE * 3; +// // compute cam pos in tri grid +// currPosX = (sint) ((camMat.getPos().x - cornerMin.x) / CELL_SIZE); +// currPosY = (sint) ((camMat.getPos().y - cornerMin.y) / CELL_SIZE); +// for(sint y = currPosY - GRID_EXTENT; y < currPosY + (sint) GRID_EXTENT; ++y) +// { +// for(sint x = currPosX - GRID_EXTENT; x < currPosX + (sint) GRID_EXTENT; ++x) +// { +// if (y < 0) continue; +// if (y >= triGridHeight) break; +// if (x < 0) continue; +// if (x >= triGridWidth) break; +// sint triRefIndex = triGrid(x, y); +// while (triRefIndex != -1) +// { +// CTriangle tri = tris[triRefs[triRefIndex].TriIndex]; +// tri.V0.x += cornerMin.x; +// tri.V0.y += cornerMin.y; +// tri.V1.x += cornerMin.x; +// tri.V1.y += cornerMin.y; +// tri.V2.x += cornerMin.x; +// tri.V2.y += cornerMin.y; +// +// triRefIndex = triRefs[triRefIndex].NextTriRef; +// pushVBTri2D(dest, tri); +// if (dest == endDest) +// { +// // flush batch +// vba.unlock(); +// driver->renderRawTriangles(material, 0, TRI_BATCH_SIZE); +// // reclaim a new batch +// vb.lock(vba); +// dest = vba.getVertexCoordPointer(0); +// endDest = dest + TRI_BATCH_SIZE * 3; +// } +// } +// } +// } +// vba.unlock(); +// uint numRemainingTris = TRI_BATCH_SIZE - ((endDest - dest) / 3); +// if (numRemainingTris) +// { +// driver->renderRawTriangles(material, 0, numRemainingTris); +// } +// } + + uint NUM_RAYS = 10000; + if (CNELU::AsyncListener.isKeyPushed(KeyT)) + { + printf("Starting raytracing test 1"); + uint numHits = 0; + NLMISC::TTime startTime = CTime::getLocalTime(); + for(uint k = 0; k < NUM_RAYS; ++k) + { + sint zone = rand() % packedZonesArray.size(); + CPackedZoneBase *zonePtr = packedZonesArray[zone]; + CVector cornerMin = zonePtr->Box.getMin(); + CVector cornerMax = zonePtr->Box.getMax(); + CVector start(frand(1.f) * (cornerMax.x - cornerMin.x) + cornerMin.x, + frand(1.f) * (cornerMax.y - cornerMin.y) + cornerMin.y, + frand(1.f) * (cornerMax.z - cornerMin.z) + cornerMin.z); + CVector end(frand(1.f) * (cornerMax.x - cornerMin.x) + cornerMin.x, + frand(1.f) * (cornerMax.y - cornerMin.y) + cornerMin.y, + frand(1.f) * (cornerMax.z - cornerMin.z) + cornerMin.z); + CVector inter; + bool result = pw.raytrace(start, end, inter); + if (result) + { + ++numHits; + } + } + NLMISC::TTime endTime = CTime::getLocalTime(); + + float dt = (float) (endTime - startTime) / 1000.f; + printf("Total time = %.2f s\n", dt); + printf("Num rays = %d\n", (int) NUM_RAYS); + printf("Num hits = %d\n", (int) numHits); + printf("Num test per seconds = %.2f\n", (float) NUM_RAYS / dt); + } + // + if (CNELU::AsyncListener.isKeyPushed(KeyU)) + { + printf("Starting raytracing test 2"); + uint numHits = 0; + NLMISC::TTime startTime = CTime::getLocalTime(); + for(uint k = 0; k < NUM_RAYS; ++k) + { + CVector start = camMat.getPos(); + CVector end(start.x + (frand(200.f) - 100.f), + start.y + (frand(200.f) - 100.f), + start.z + (frand(5.f) - 2.5f)); + CVector inter; + bool result = pw.raytrace(start, end, inter); + if (result) + { + ++numHits; + } + } + NLMISC::TTime endTime = CTime::getLocalTime(); + + float dt = (float) (endTime - startTime) / 1000.f; + printf("Total time = %.2f s\n", dt); + printf("Num rays = %d\n", (int) NUM_RAYS); + printf("Num hits = %d\n", (int) numHits); + printf("Num test per seconds = %.2f\n", (float) NUM_RAYS / dt); + } + // + driver->setPolygonMode(IDriver::Filled); + // + driver->swapBuffers(); + } + while(!CNELU::AsyncListener.isKeyPushed(KeyESCAPE)); + + + + return 0; +} + +*/ + + diff --git a/code/ryzom/tools/server/build_world_packed_col/village.cpp b/code/ryzom/tools/server/build_world_packed_col/village.cpp index 8d3681878..f29486c61 100644 --- a/code/ryzom/tools/server/build_world_packed_col/village.cpp +++ b/code/ryzom/tools/server/build_world_packed_col/village.cpp @@ -1,304 +1,304 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#if 0 -#include "std_header.h" -// -#include "village.h" -#include "zone_util.h" -// -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" -#include "nel/georges/u_form_loader.h" -// -#include "nel/misc/path.h" -#include "nel/misc/file.h" -// -#include "3d/shape.h" - - -using namespace NLMISC; -using namespace NL3D; - -//********************************************************************************************** -CVillageGrid::CVillageGrid() -{ - _ZoneMinX = 0; - _ZoneMinY = 0; - -} - -//********************************************************************************************** -void CVillageGrid::init(uint gridWidth, uint gridHeight, sint zoneMinX, sint zoneMinY) -{ - reset(); - nlassert(gridWidth > 0); - nlassert(gridHeight > 0); - _ZoneMinX = zoneMinX; - _ZoneMinY = zoneMinY; - VillageGrid.init(gridWidth, gridHeight); -} - -//********************************************************************************************** -void CVillageGrid::reset() -{ - NLMISC::contReset(*this); -} - -//********************************************************************************************** -void CVillageGrid::addVillagesFromContinent(const std::string &continentSheetName) -{ - // Load the form - NLGEORGES::UFormLoader *loader = NLGEORGES::UFormLoader::createLoader(); - // - std::string path = CPath::lookup(continentSheetName, false, false); - if (path.empty()) - { - nlwarning("Path not found for %s.", continentSheetName.c_str()); - return; - } - NLGEORGES::UForm *villageForm; - villageForm = loader->loadForm(path.c_str()); - if(villageForm != NULL) - { - NLGEORGES::UFormElm &rootItem = villageForm->getRootNode(); - // try to get the village list - // Load the village list - NLGEORGES::UFormElm *villagesItem; - if(!(rootItem.getNodeByName (&villagesItem, "Villages") && villagesItem)) - { - nlwarning("No villages where found in %s", continentSheetName.c_str()); - return; - } - - // Get number of village - uint numVillage; - nlverify (villagesItem->getArraySize (numVillage)); - - // For each village - for(uint k = 0; k < numVillage; ++k) - { - NLGEORGES::UFormElm *currVillage; - if (!(villagesItem->getArrayNode (&currVillage, k) && currVillage)) - { - nlwarning("Couldn't get village %d in continent %s", continentSheetName.c_str(), k); - continue; - } - // check that this village is in the dependency zones - NLGEORGES::UFormElm *zoneNameItem; - if (!currVillage->getNodeByName (&zoneNameItem, "Zone") && zoneNameItem) - { - nlwarning("Couldn't get zone item of village %d in continent %s", continentSheetName.c_str(), k); - continue; - } - std::string zoneName; - if (!zoneNameItem->getValue(zoneName)) - { - nlwarning("Couldn't get zone name of village %d in continent %s", continentSheetName.c_str(), k); - continue; - } - sint zoneX, zoneY; - if (!getZonePos(zoneName, zoneX, zoneY)) - { - nlwarning("Zone name of village %d in continent %s is invalid", continentSheetName.c_str(), k); - continue; - } - sint villageMinX, villageMinY; - sint villageMaxX, villageMaxY; - - - // retrieve width & height of covered region - uint32 regionWidth; - uint32 regionHeight; - float centerX, centerY; - if (!currVillage->getValueByName(regionWidth, "Width") || - !currVillage->getValueByName(regionHeight, "Height") || - !currVillage->getValueByName(centerX, "CenterX") || - !currVillage->getValueByName(centerY, "CenterY")) - { - nlwarning("Can't retrieve region covered by village %d in continent %s", continentSheetName.c_str(), k); - continue; - } - // - villageMinX = villageMaxX = zoneX; - villageMinY = villageMaxY = zoneY; - // extends with bbox from center to min corner if leveldesigner forgot to enter good width & height - villageMaxX = std::max(villageMaxX, (sint) ((zoneX * 160.f + 2.f * centerX) / 160.f)); - villageMaxY = std::max(villageMaxY, (sint) ((zoneY * 160.f + 2.f * centerY) / 160.f)); - // - villageMinX -= _ZoneMinX; - villageMaxX -= _ZoneMinX; - villageMinY -= _ZoneMinY; - villageMaxY -= _ZoneMinY; - // - CVillage village; - if (loadVillageSheet(currVillage, continentSheetName, k, village)) - { - // - village.FileModificationDate = std::max(village.FileModificationDate, CFile::getFileModificationDate(path)); - // - Villages.push_back(CVillage()); - Villages.back().swap(village); - // - for (sint y = villageMinY; y <= (sint) villageMaxY; ++y) - { - if (y < 0) continue; - if (y >= (sint) VillageGrid.getHeight()) continue; - for (sint x = villageMinX; x <= (sint) villageMaxX; ++x) - { - if (x < 0) continue; - if (x >= (sint) VillageGrid.getWidth()) continue; - VillageGrid(x, y).push_back(Villages.size() - 1); - } - } - } - } - } - else - { - nlwarning("Can't load continent form : %s", continentSheetName.c_str()); - } -} - -//********************************************************************************************** -bool CVillageGrid::loadVillageSheet(const NLGEORGES::UFormElm *villageItem, const std::string &continentSheetName, uint villageIndex, CVillage &dest) -{ - dest.IG.clear(); - const NLGEORGES::UFormElm *igNamesItem; - if (! (villageItem->getNodeByName (&igNamesItem, "IgList") && igNamesItem) ) - { - nlwarning("No list of IGs was found in the continent form %s, village #%d", continentSheetName.c_str(), (int) villageIndex); - return false; - } - - // Get number of village - uint numIgs; - nlverify (igNamesItem->getArraySize (numIgs)); - const NLGEORGES::UFormElm *currIg; - uint32 mostRecentIGDate = 0; - for(uint l = 0; l < numIgs; ++l) - { - if (!(igNamesItem->getArrayNode (&currIg, l) && currIg)) - { - nlwarning("Couldn't get ig #%d in the continent form %s, in village #%d", l, continentSheetName.c_str(), (int) villageIndex); - continue; - } - const NLGEORGES::UFormElm *igNameItem; - currIg->getNodeByName (&igNameItem, "IgName"); - std::string igName; - if (!igNameItem->getValue (igName)) - { - nlwarning("Couldn't get ig name of ig #%d in the continent form %s, in village #%d", l, continentSheetName.c_str(), (int) villageIndex); - continue; - } - if (igName.empty()) - { - nlwarning("Ig name of ig #%d in the continent form %s, in village #%d is an empty string", l, continentSheetName.c_str(), (int) villageIndex); - continue; - } - // ensure .ig - igName = CFile::getFilenameWithoutExtension(igName) + ".ig"; - - - CIGInfo igInfo; - - // add this ig - std::string nameLookup = CPath::lookup (igName, false, true); - if (!nameLookup.empty()) - { - igInfo.Path = nameLookup; - dest.IG.push_back(igInfo); - mostRecentIGDate = std::max(mostRecentIGDate, CFile::getFileModificationDate(nameLookup)); - } - else - { - nlwarning("Couldn't find ig %s in continent form %s, in village %d", igName.c_str(), continentSheetName.c_str(), (int) villageIndex); - } - } - dest.FileModificationDate = mostRecentIGDate; - return true; -} - - -//********************************************************************************************** -void CVillage::load(TShapeCache &shapeCache) -{ - for(std::vector::iterator it = IG.begin(); it != IG.end(); ++it) - { - it->load(shapeCache); - } -} - -//********************************************************************************************** -void CIGInfo::load(TShapeCache &shapeCache) -{ - if (Loaded) return; - Loaded = true; // even if loading fails, don't try twice to load it - try - { - CIFile stream; - stream.open(Path); - printf(Path.c_str()); - CSmartPtr ig = new CInstanceGroup; - ig->serial(stream); - IG = ig; // commit - } - catch(const EStream &e) - { - nlwarning(e.what()); - } - if (IG) - { - // complete cache - for(uint k = 0; k < IG->getNumInstance(); ++k) - { - std::string shapeName = standardizeShapeName(IG->getShapeName(k)); - if (NLMISC::toLower(CFile::getExtension(shapeName)) == "pacs_prim") - { - continue; - } - TShapeCache::iterator it = shapeCache.find(shapeName); - CShapeInfo si; - bool buildOK = false; - if (it == shapeCache.end()) - { - CShapeStream ss; - try - { - - CIFile stream; - std::string path = CPath::lookup(shapeName, false, false); - if (!path.empty()) - { - stream.open(path); - ss.serial(stream); - CShapeInfo si; - si.build(*ss.getShapePointer()); - delete ss.getShapePointer(); - shapeCache[shapeName].swap(si); - } - } - catch (const EStream &e) - { - // shape not loaded - nlwarning(e.what()); - } - } - } - } -} - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#if 0 +#include "std_header.h" +// +#include "village.h" +#include "zone_util.h" +// +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" +#include "nel/georges/u_form_loader.h" +// +#include "nel/misc/path.h" +#include "nel/misc/file.h" +// +#include "3d/shape.h" + + +using namespace NLMISC; +using namespace NL3D; + +//********************************************************************************************** +CVillageGrid::CVillageGrid() +{ + _ZoneMinX = 0; + _ZoneMinY = 0; + +} + +//********************************************************************************************** +void CVillageGrid::init(uint gridWidth, uint gridHeight, sint zoneMinX, sint zoneMinY) +{ + reset(); + nlassert(gridWidth > 0); + nlassert(gridHeight > 0); + _ZoneMinX = zoneMinX; + _ZoneMinY = zoneMinY; + VillageGrid.init(gridWidth, gridHeight); +} + +//********************************************************************************************** +void CVillageGrid::reset() +{ + NLMISC::contReset(*this); +} + +//********************************************************************************************** +void CVillageGrid::addVillagesFromContinent(const std::string &continentSheetName) +{ + // Load the form + NLGEORGES::UFormLoader *loader = NLGEORGES::UFormLoader::createLoader(); + // + std::string path = CPath::lookup(continentSheetName, false, false); + if (path.empty()) + { + nlwarning("Path not found for %s.", continentSheetName.c_str()); + return; + } + NLGEORGES::UForm *villageForm; + villageForm = loader->loadForm(path.c_str()); + if(villageForm != NULL) + { + NLGEORGES::UFormElm &rootItem = villageForm->getRootNode(); + // try to get the village list + // Load the village list + NLGEORGES::UFormElm *villagesItem; + if(!(rootItem.getNodeByName (&villagesItem, "Villages") && villagesItem)) + { + nlwarning("No villages where found in %s", continentSheetName.c_str()); + return; + } + + // Get number of village + uint numVillage; + nlverify (villagesItem->getArraySize (numVillage)); + + // For each village + for(uint k = 0; k < numVillage; ++k) + { + NLGEORGES::UFormElm *currVillage; + if (!(villagesItem->getArrayNode (&currVillage, k) && currVillage)) + { + nlwarning("Couldn't get village %d in continent %s", continentSheetName.c_str(), k); + continue; + } + // check that this village is in the dependency zones + NLGEORGES::UFormElm *zoneNameItem; + if (!currVillage->getNodeByName (&zoneNameItem, "Zone") && zoneNameItem) + { + nlwarning("Couldn't get zone item of village %d in continent %s", continentSheetName.c_str(), k); + continue; + } + std::string zoneName; + if (!zoneNameItem->getValue(zoneName)) + { + nlwarning("Couldn't get zone name of village %d in continent %s", continentSheetName.c_str(), k); + continue; + } + sint zoneX, zoneY; + if (!getZonePos(zoneName, zoneX, zoneY)) + { + nlwarning("Zone name of village %d in continent %s is invalid", continentSheetName.c_str(), k); + continue; + } + sint villageMinX, villageMinY; + sint villageMaxX, villageMaxY; + + + // retrieve width & height of covered region + uint32 regionWidth; + uint32 regionHeight; + float centerX, centerY; + if (!currVillage->getValueByName(regionWidth, "Width") || + !currVillage->getValueByName(regionHeight, "Height") || + !currVillage->getValueByName(centerX, "CenterX") || + !currVillage->getValueByName(centerY, "CenterY")) + { + nlwarning("Can't retrieve region covered by village %d in continent %s", continentSheetName.c_str(), k); + continue; + } + // + villageMinX = villageMaxX = zoneX; + villageMinY = villageMaxY = zoneY; + // extends with bbox from center to min corner if leveldesigner forgot to enter good width & height + villageMaxX = std::max(villageMaxX, (sint) ((zoneX * 160.f + 2.f * centerX) / 160.f)); + villageMaxY = std::max(villageMaxY, (sint) ((zoneY * 160.f + 2.f * centerY) / 160.f)); + // + villageMinX -= _ZoneMinX; + villageMaxX -= _ZoneMinX; + villageMinY -= _ZoneMinY; + villageMaxY -= _ZoneMinY; + // + CVillage village; + if (loadVillageSheet(currVillage, continentSheetName, k, village)) + { + // + village.FileModificationDate = std::max(village.FileModificationDate, CFile::getFileModificationDate(path)); + // + Villages.push_back(CVillage()); + Villages.back().swap(village); + // + for (sint y = villageMinY; y <= (sint) villageMaxY; ++y) + { + if (y < 0) continue; + if (y >= (sint) VillageGrid.getHeight()) continue; + for (sint x = villageMinX; x <= (sint) villageMaxX; ++x) + { + if (x < 0) continue; + if (x >= (sint) VillageGrid.getWidth()) continue; + VillageGrid(x, y).push_back(Villages.size() - 1); + } + } + } + } + } + else + { + nlwarning("Can't load continent form : %s", continentSheetName.c_str()); + } +} + +//********************************************************************************************** +bool CVillageGrid::loadVillageSheet(const NLGEORGES::UFormElm *villageItem, const std::string &continentSheetName, uint villageIndex, CVillage &dest) +{ + dest.IG.clear(); + const NLGEORGES::UFormElm *igNamesItem; + if (! (villageItem->getNodeByName (&igNamesItem, "IgList") && igNamesItem) ) + { + nlwarning("No list of IGs was found in the continent form %s, village #%d", continentSheetName.c_str(), (int) villageIndex); + return false; + } + + // Get number of village + uint numIgs; + nlverify (igNamesItem->getArraySize (numIgs)); + const NLGEORGES::UFormElm *currIg; + uint32 mostRecentIGDate = 0; + for(uint l = 0; l < numIgs; ++l) + { + if (!(igNamesItem->getArrayNode (&currIg, l) && currIg)) + { + nlwarning("Couldn't get ig #%d in the continent form %s, in village #%d", l, continentSheetName.c_str(), (int) villageIndex); + continue; + } + const NLGEORGES::UFormElm *igNameItem; + currIg->getNodeByName (&igNameItem, "IgName"); + std::string igName; + if (!igNameItem->getValue (igName)) + { + nlwarning("Couldn't get ig name of ig #%d in the continent form %s, in village #%d", l, continentSheetName.c_str(), (int) villageIndex); + continue; + } + if (igName.empty()) + { + nlwarning("Ig name of ig #%d in the continent form %s, in village #%d is an empty string", l, continentSheetName.c_str(), (int) villageIndex); + continue; + } + // ensure .ig + igName = CFile::getFilenameWithoutExtension(igName) + ".ig"; + + + CIGInfo igInfo; + + // add this ig + std::string nameLookup = CPath::lookup (igName, false, true); + if (!nameLookup.empty()) + { + igInfo.Path = nameLookup; + dest.IG.push_back(igInfo); + mostRecentIGDate = std::max(mostRecentIGDate, CFile::getFileModificationDate(nameLookup)); + } + else + { + nlwarning("Couldn't find ig %s in continent form %s, in village %d", igName.c_str(), continentSheetName.c_str(), (int) villageIndex); + } + } + dest.FileModificationDate = mostRecentIGDate; + return true; +} + + +//********************************************************************************************** +void CVillage::load(TShapeCache &shapeCache) +{ + for(std::vector::iterator it = IG.begin(); it != IG.end(); ++it) + { + it->load(shapeCache); + } +} + +//********************************************************************************************** +void CIGInfo::load(TShapeCache &shapeCache) +{ + if (Loaded) return; + Loaded = true; // even if loading fails, don't try twice to load it + try + { + CIFile stream; + stream.open(Path); + printf(Path.c_str()); + CSmartPtr ig = new CInstanceGroup; + ig->serial(stream); + IG = ig; // commit + } + catch(const EStream &e) + { + nlwarning(e.what()); + } + if (IG) + { + // complete cache + for(uint k = 0; k < IG->getNumInstance(); ++k) + { + std::string shapeName = standardizeShapeName(IG->getShapeName(k)); + if (NLMISC::toLower(CFile::getExtension(shapeName)) == "pacs_prim") + { + continue; + } + TShapeCache::iterator it = shapeCache.find(shapeName); + CShapeInfo si; + bool buildOK = false; + if (it == shapeCache.end()) + { + CShapeStream ss; + try + { + + CIFile stream; + std::string path = CPath::lookup(shapeName, false, false); + if (!path.empty()) + { + stream.open(path); + ss.serial(stream); + CShapeInfo si; + si.build(*ss.getShapePointer()); + delete ss.getShapePointer(); + shapeCache[shapeName].swap(si); + } + } + catch (const EStream &e) + { + // shape not loaded + nlwarning(e.what()); + } + } + } + } +} + +#endif diff --git a/code/ryzom/tools/server/build_world_packed_col/village.h b/code/ryzom/tools/server/build_world_packed_col/village.h index 8a8b3be55..2d1c85591 100644 --- a/code/ryzom/tools/server/build_world_packed_col/village.h +++ b/code/ryzom/tools/server/build_world_packed_col/village.h @@ -1,88 +1,88 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -/*#ifndef _VILLAGE_H -#define _VILLAGE_H - -#include "nel/misc/array_2d.h" -#include "3d/shape_info.h" -// -#include "3d/scene_group.h" -// -#include "nel/misc/smart_ptr.h" -// -#include - - -namespace NLGEORGES -{ - class UFormElm; -} - -class CIGInfo -{ -public: - std::string Path; - NLMISC::CSmartPtr IG; // NULL if not loaded yet - bool Loaded; -public: - CIGInfo() : Loaded(false) {} - // load data & complete shape cache. no-op if datas where already loaded - void load(NL3D::TShapeCache &shapeCache); -}; - - -class CVillage -{ -public: - std::vector IG; - uint32 FileModificationDate; -public: - void swap(CVillage &other) - { - IG.swap(other.IG); - std::swap(other.FileModificationDate, FileModificationDate); - } - // load data & complete shape cache. no-op if datas where already loaded - void load(NL3D::TShapeCache &shapeCache); -}; - - - - -class CVillageGrid -{ -public: - std::vector Villages; - NLMISC::CArray2D > VillageGrid; // each grid cells gives the list of villages that overlap that cell (identified by their indices into 'Villages') -public: - CVillageGrid(); - // - void init(uint gridWidth, uint gridHright, sint zoneMinX, sint zoneMinY); - void reset(); - // Load & add all villages of a continent to the map - void addVillagesFromContinent(const std::string &continentSheetName); -private: - sint _ZoneMinX; - sint _ZoneMinY; -private: - bool loadVillageSheet(const NLGEORGES::UFormElm *villageItem, const std::string &continentSheetName, uint villageIndex, CVillage &dest); -}; - - - -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +/*#ifndef _VILLAGE_H +#define _VILLAGE_H + +#include "nel/misc/array_2d.h" +#include "3d/shape_info.h" +// +#include "3d/scene_group.h" +// +#include "nel/misc/smart_ptr.h" +// +#include + + +namespace NLGEORGES +{ + class UFormElm; +} + +class CIGInfo +{ +public: + std::string Path; + NLMISC::CSmartPtr IG; // NULL if not loaded yet + bool Loaded; +public: + CIGInfo() : Loaded(false) {} + // load data & complete shape cache. no-op if datas where already loaded + void load(NL3D::TShapeCache &shapeCache); +}; + + +class CVillage +{ +public: + std::vector IG; + uint32 FileModificationDate; +public: + void swap(CVillage &other) + { + IG.swap(other.IG); + std::swap(other.FileModificationDate, FileModificationDate); + } + // load data & complete shape cache. no-op if datas where already loaded + void load(NL3D::TShapeCache &shapeCache); +}; + + + + +class CVillageGrid +{ +public: + std::vector Villages; + NLMISC::CArray2D > VillageGrid; // each grid cells gives the list of villages that overlap that cell (identified by their indices into 'Villages') +public: + CVillageGrid(); + // + void init(uint gridWidth, uint gridHright, sint zoneMinX, sint zoneMinY); + void reset(); + // Load & add all villages of a continent to the map + void addVillagesFromContinent(const std::string &continentSheetName); +private: + sint _ZoneMinX; + sint _ZoneMinY; +private: + bool loadVillageSheet(const NLGEORGES::UFormElm *villageItem, const std::string &continentSheetName, uint villageIndex, CVillage &dest); +}; + + + +#endif */ \ No newline at end of file diff --git a/code/ryzom/tools/server/build_world_packed_col/zone_util.cpp b/code/ryzom/tools/server/build_world_packed_col/zone_util.cpp index d63e3caf5..998e5e67f 100644 --- a/code/ryzom/tools/server/build_world_packed_col/zone_util.cpp +++ b/code/ryzom/tools/server/build_world_packed_col/zone_util.cpp @@ -1,70 +1,70 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "std_header.h" -// -#include "zone_util.h" -// -#include "nel/misc/path.h" - -//********************************************************************************************** -bool getZonePos(const std::string &name, sint &destX, sint &destY) -{ - if (name.empty()) - { - printf ("empty name\n"); - return false; - } - - static std::string zoneName; - static std::string xStr, yStr; - xStr.clear(); - yStr.clear(); - zoneName = NLMISC::CFile::getFilenameWithoutExtension(name); - uint32 i = 0; - while (zoneName[i] != '_') - { - if (!::isdigit(zoneName[i])) return false; - yStr += zoneName[i]; ++i; - if (i == zoneName.size()) - return false; - } - ++i; - while (i < zoneName.size()) - { - if (!::isalpha(zoneName[i])) return false; - xStr += (char) ::toupper(zoneName[i]); ++i; - } - if (xStr.size() != 2) return false; - // compute min corner - destX = ((xStr[0] - 'A') * 26 + (xStr[1] - 'A')); - NLMISC::fromString(yStr, destY); - destY = -destY; - return true; -} - -//********************************************************************************************** -std::string posToZoneName(float x, float y) -{ - std::string zoneName; - sint zoneX = (sint) floorf(x / 160.f); - sint zoneY = (sint) floorf(y / 160.f); - zoneName += NLMISC::toString(- zoneY) + "_"; - zoneName += (char) ('A' + zoneX / 26); - zoneName += (char) ('A' + zoneX % 26); - return zoneName; -} - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "std_header.h" +// +#include "zone_util.h" +// +#include "nel/misc/path.h" + +//********************************************************************************************** +bool getZonePos(const std::string &name, sint &destX, sint &destY) +{ + if (name.empty()) + { + printf ("empty name\n"); + return false; + } + + static std::string zoneName; + static std::string xStr, yStr; + xStr.clear(); + yStr.clear(); + zoneName = NLMISC::CFile::getFilenameWithoutExtension(name); + uint32 i = 0; + while (zoneName[i] != '_') + { + if (!::isdigit(zoneName[i])) return false; + yStr += zoneName[i]; ++i; + if (i == zoneName.size()) + return false; + } + ++i; + while (i < zoneName.size()) + { + if (!::isalpha(zoneName[i])) return false; + xStr += (char) ::toupper(zoneName[i]); ++i; + } + if (xStr.size() != 2) return false; + // compute min corner + destX = ((xStr[0] - 'A') * 26 + (xStr[1] - 'A')); + NLMISC::fromString(yStr, destY); + destY = -destY; + return true; +} + +//********************************************************************************************** +std::string posToZoneName(float x, float y) +{ + std::string zoneName; + sint zoneX = (sint) floorf(x / 160.f); + sint zoneY = (sint) floorf(y / 160.f); + zoneName += NLMISC::toString(- zoneY) + "_"; + zoneName += (char) ('A' + zoneX / 26); + zoneName += (char) ('A' + zoneX % 26); + return zoneName; +} + diff --git a/code/ryzom/tools/server/build_world_packed_col/zone_util.h b/code/ryzom/tools/server/build_world_packed_col/zone_util.h index 29e276ede..b87d629dd 100644 --- a/code/ryzom/tools/server/build_world_packed_col/zone_util.h +++ b/code/ryzom/tools/server/build_world_packed_col/zone_util.h @@ -1,34 +1,34 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef _ZONE_UTIL_H -#define _ZONE_UTIL_H - - -#include - - -// compute pos of a zone from its name -bool getZonePos(const std::string &name, sint &destX, sint &destY); - -std::string posToZoneName(float x, float y); - - - - - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef _ZONE_UTIL_H +#define _ZONE_UTIL_H + + +#include + + +// compute pos of a zone from its name +bool getZonePos(const std::string &name, sint &destX, sint &destY); + +std::string posToZoneName(float x, float y); + + + + + + #endif \ No newline at end of file diff --git a/code/ryzom/tools/sheet_random_generator/StdAfx.cpp b/code/ryzom/tools/sheet_random_generator/StdAfx.cpp index 9831595d4..2f6983355 100644 --- a/code/ryzom/tools/sheet_random_generator/StdAfx.cpp +++ b/code/ryzom/tools/sheet_random_generator/StdAfx.cpp @@ -1,24 +1,24 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.cpp : source file that includes just the standard includes -// sheet_random_generator.pch will be the pre-compiled header -// stdafx.obj will contain the pre-compiled type information - -#include "stdafx.h" - -// TODO: reference any additional headers you need in STDAFX.H -// and not in this file +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.cpp : source file that includes just the standard includes +// sheet_random_generator.pch will be the pre-compiled header +// stdafx.obj will contain the pre-compiled type information + +#include "stdafx.h" + +// TODO: reference any additional headers you need in STDAFX.H +// and not in this file diff --git a/code/ryzom/tools/sheet_random_generator/StdAfx.h b/code/ryzom/tools/sheet_random_generator/StdAfx.h index 6547b7537..86ce37592 100644 --- a/code/ryzom/tools/sheet_random_generator/StdAfx.h +++ b/code/ryzom/tools/sheet_random_generator/StdAfx.h @@ -1,35 +1,35 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// stdafx.h : include file for standard system include files, -// or project specific include files that are used frequently, but -// are changed infrequently -// - -#if !defined(AFX_STDAFX_H__902B2BCD_4B48_45C5_8DAD_69C53472BD0C__INCLUDED_) -#define AFX_STDAFX_H__902B2BCD_4B48_45C5_8DAD_69C53472BD0C__INCLUDED_ - -#if _MSC_VER > 1000 -#pragma once -#endif // _MSC_VER > 1000 - - -// TODO: reference additional headers your program requires here - -//{{AFX_INSERT_LOCATION}} -// Microsoft Visual C++ will insert additional declarations immediately before the previous line. - -#endif // !defined(AFX_STDAFX_H__902B2BCD_4B48_45C5_8DAD_69C53472BD0C__INCLUDED_) +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#if !defined(AFX_STDAFX_H__902B2BCD_4B48_45C5_8DAD_69C53472BD0C__INCLUDED_) +#define AFX_STDAFX_H__902B2BCD_4B48_45C5_8DAD_69C53472BD0C__INCLUDED_ + +#if _MSC_VER > 1000 +#pragma once +#endif // _MSC_VER > 1000 + + +// TODO: reference additional headers your program requires here + +//{{AFX_INSERT_LOCATION}} +// Microsoft Visual C++ will insert additional declarations immediately before the previous line. + +#endif // !defined(AFX_STDAFX_H__902B2BCD_4B48_45C5_8DAD_69C53472BD0C__INCLUDED_) diff --git a/code/ryzom/tools/sheet_random_generator/sheet_random_generator.cpp b/code/ryzom/tools/sheet_random_generator/sheet_random_generator.cpp index a3d56f40d..fd139a55a 100644 --- a/code/ryzom/tools/sheet_random_generator/sheet_random_generator.cpp +++ b/code/ryzom/tools/sheet_random_generator/sheet_random_generator.cpp @@ -1,3907 +1,3907 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - -#include "StdAfx.h" -#include "srg_utilities.h" -#include "game_share/protection_type.h" -#include "nel/misc/string_conversion.h" - -/* - * V3 - */ - -// Flags: overridden by the config file values - -/// Generate only new materials sheets, don't modify existing -bool GenOnlyNewRawMaterials = true; - -/// Allow to modify existing material sheets -enum TExistingRMAction { BrowseRM, ModifyRM, SkipRM } ExistingRMAction = BrowseRM; - -/// Skip RM for creatures -bool SkipRawMaterialsForCreatures = false; - -/// Browse creature sheets and set their raw material properties using raw materials generated or loaded -bool AssignRawMaterialsHarvestToCreatureSheets = true; - -/// Prevent from overwriting raw material assignment to creatures when already done -bool AssignOnlyToUnassignedCreatures = true; - -/// Skip RM for deposits -bool SkipRawMaterialsForDeposits = false; - -/// Skip non-mission raw materials -bool GenOnlyMissionRawMaterials = false; - -/// Generate deposit sheets using raw materials generated or loaded -bool AssignRawMaterialsHarvestToDepositSheets = true; - -/// Browse all deposits found (to produce doc), including not generated ones -bool BrowseOtherDeposits = false; - -/// Substitute invalid raw materials assignments in deposits with valid similar assignments -bool FixDeposits = false; - -/// Write even blank properties (to erase old assignments) -bool EraseOldCreatureAssignments = false; - -/// Test (for creatures: test previous assignment only, on deposit: test current assignment) -bool TestExistingAssigments = true; - -/// Print the names of raw materials in a file -bool OutputNameList = false; - -/// Display families and properties -bool DisplayFamAndProp = false; - -/// Produce html documentation -bool ProduceDoc = true; - -/// If not ~0, print all RMs of zone level -uint32 GetSelectionUntilLevel = ~0; - -/// Max number of MP by family (by ecosystem and levelzone) -uint32 MaxNbRMByFamilyEZ = 10; - -/// If true, sort by decreasing originality -bool SortByOriginality = false; - -/// Max number of MP useful for one craft slot -uint32 MaxNbRMByCraftSlotE = 100; - -/// Check if sheets (when loading them in browse mode) have valid durability -bool CheckDurability = false; - -/// Generate files for WorldEditor listbox for families -bool GenerateDepositSystemMpFiles = true; - -// Discard rm with originality lower than this value -//uint32 OriginalityMinThreshold = 0; - -// Number of combinations to randomize per raw material (obsolete) -//uint32 NbFaberCombinations = 10; - - -const uint32 NB_RAW_MATERIAL_FAMILIES_PER_CREATURE = 9; -const uint32 NB_RAW_MATERIALS_PER_DEPOSIT = 30; - -const string CommonCreatureCode = "zz"; - -CRulesFilter propertySetFilter, familyFaberFilter, familyCreatureFilter, creatureFamilyFilter, familyColorsFilter; - -vector< CRulesFilter > ecosystemDepositFilters; - -const char * locationNames [NB_LOCATIONS] = { "InDeposits", "InCreatures" }; - - -FILE *GraphFile; -CFileDisplayer ListDisplayer( "families_output.txt", true ); -CLog ListLog; - -uint32 nbMaterialSheetsProcessed = 0, nbRejectedProperties = 0, nbExistingSheetsLoaded = 0, nbExistingSheetsModified = 0, nbSheetsProcessed = 0, nbNewSheetsGenerated = 0; - - -typedef map< string, PROTECTION_TYPE::TProtectionType > CProtectionTypeMap; -CProtectionTypeMap JewelProtectionTypeByFamilyEcosystem; -//bool HasSpecializedJewelProtectionTypeByCiv [NbCiv] = { false, false, false, false, false }; -//set< PROTECTION_TYPE::TProtectionType > midProtectionTypesUsed; - - -CRMData SortableData; - -CTitles Titles; - -CMainStat MainStat; - -CRulesStr2Filter CustomizedPropertiesSheetName; - -//vector< CGenRawMaterial > Repository; - -/* - * - */ -CSString makeAbbrevName( CSString name, const CSkeletonMap& alreadyDone ) -{ - CSString abbrevName = name.left( 6 ).toUpper(); - if ( (name.size() == abbrevName.size() + 1) && - (abbrevName[abbrevName.size()-1] == 'E') && (tolower(name[name.size()-1]) == 'r') ) - abbrevName[abbrevName.size()-1] = 'R'; - - CSkeletonMap::const_iterator isk; - for ( isk=alreadyDone.begin(); isk!=alreadyDone.end(); ++isk ) - { - if ( (abbrevName == (*isk).second.AbbrevName) && (name != (*isk).second.Name) ) - nlerror( "Duplicate abbrevName %s for %s and %s", abbrevName.c_str(), (*isk).second.Name.c_str(), name.c_str() ); - } - return abbrevName; -} - - -/* - * No duplicate check (multiple families have the same prefix name, ex: Abhaya) - */ -CSString makeAbbrevName( CSString name ) -{ - CSString abbrevName = name.left( 6 ).toUpper(); - if ( (name.size() == abbrevName.size() + 1) && - (abbrevName[abbrevName.size()-1] == 'E') && (tolower(name[name.size()-1]) == 'r') ) - abbrevName[abbrevName.size()-1] = 'R'; - string::size_type p = abbrevName.find( " " ); - if ( p != string::npos ) - abbrevName = abbrevName.left( p ); - - return abbrevName; -} - - -/// DISABLED -#if 0 -/* - * Returns false if the RM must NOT be generated. - */ -bool CFaberCharacteristics::randomizeValues( TFaberInterestLevel interestLevel, TFaberInterestLevel nbInterestLevels, uint iVariant, float widthRatio, float peakOccurRatio, float baseBoost, TEcosystem iEcosystem, uint iFreq, uint iFamily ) -{ - if ( FaberElement == ~0 ) - return true; - if ( interestLevel == NAInterestLevel ) // no random values - return true; - - uint32 rPeak = ~0; - uint32 rCharac; - - // Boost 0, 1 or 2 characs, depending on iVariant and interestLevel - uint rBoostedCharac [2] = { ~0, ~0 }; - if ( iVariant == 2 ) // A-E:1>=90%; F:5>=90% - { - do - { - rBoostedCharac[0] = getRandomValue( NbCharacs-1 ); - } - while ( ! CharacSlotFilter[rBoostedCharac[0]][FaberElement] ); - /*if ( interestLevel == nbInterestLevels-1 ) // TODO - { - do - { - rBoostedCharac[1] = getRandomValue( NbCharacs-1 ); // currently, can loop infinitely if there is only one matching CharactSlotFilter - } - while ( (rBoostedCharac[1] == rBoostedCharac[0]) || (! CharacSlotFilter[rBoostedCharac[1]][FaberElement]) ); - }*/ - } - - // Browse characs - for ( rCharac=0; rCharac!=NbCharacs; ++rCharac ) - { - if ( ! CharacSlotFilter[rCharac][FaberElement] ) - continue; - - // Special cases - if ( (FaberElement == ITEM_PART_JEWEL_GEM) && (rCharac == JewelProtection) ) - { - if ( ! randomizeJewelProtection( (TStatQuality)interestLevel, iEcosystem, iFreq, iFamily ) ) - return false; - } - else // general case - { - // Randomize variation of interest level (different for each characteristic) - /*TFaberInterestLevel deltaLevel = (sint)getRandomValue( nbInterestLevels ) - ((sint)(nbInterestLevels) / 2);*/ - TFaberInterestLevel actualLevel = interestLevel; /*max( (sint)0, min( (sint)nbInterestLevels-1, ((sint)interestLevel) + deltaLevel ) );*/ - sint factor; - - // Boosted charac? - if ( (rCharac == rBoostedCharac[0]) ) - { - Values[rCharac] = 90.0f + frand( 10.0f ); - } - else - { - // Handle reversed interest - if ( PositiveCharacs[rCharac] ) - factor = actualLevel; - else - factor = (nbInterestLevels - 1) - actualLevel; - - // Get a peak value? - bool isPeak = false; - if ( peakOccurRatio != 0.0f) - { - float peakDice = frand( 1.0f / peakOccurRatio ); - isPeak = (peakDice < 1.0f); - if ( isPeak ) - rPeak = rCharac; - } - - // Force a value higher than min? (if higher_or_eq than average, or if reversed interest) - bool greaterThanMin = (actualLevel > nbInterestLevels/2) || (!PositiveCharacs[rCharac]); - - // Calculate min and max - float minValue; - float maxValue = isPeak ? PeakCharacValues[rCharac] : MaxCharacValues[rCharac]; - if ( greaterThanMin ) - { - minValue = MinCharacValues[rCharac]; - maxValue -= minValue; - } - - // Calculate value - float normalSlice = maxValue / (float)nbInterestLevels; - float enlargedSlice = normalSlice * widthRatio; - float baseOfSlice = max( 0.0f, (((float)factor) * normalSlice) + (normalSlice-enlargedSlice)/2.0f ) + baseBoost; - float value = min( baseOfSlice + frand( enlargedSlice ), maxValue ); - //nldebug( "%d/%d range=%.1f slice=%.1f enlarged=%.1f base=%.1f value=%.1f", factor, nbInterestLevels, maxValue, normalSlice, enlargedSlice, baseOfSlice, value ); - if ( greaterThanMin ) - { - value += minValue; - } - - // Prevent to get a null durability - if ( rCharac == Durability ) - if ( value < 1.0f ) - value = 1.0f; - - Values[rCharac] = value; - //nldebug( "%s: %s (level %s)", sCharacs[rCharac], isPeak?"PEAK":"normal", - // PositiveCharacs[rCharac] ? sInterestLevels[level] : sInterestLevels[(NbFaberInterestLevels - 1) - level] ); - } - } - } - - calcQualitativeValues(); - //nldebug( "%s (IL=%u)", CraftParts[FaberElement].Name.c_str(), interestLevel ); - - /*// Display only "best" - if ( interestLevel == nbInterestLevels-1 ) - nldebug( " %s %s Durability=%g Weight=%g, DMG=%g, Speed=%g, SapLoad=%g, Range=%g%s", - faberElems[FaberElement].c_str(), sNomenclaturedInterestLevels[getNomenclaturedInterestLevel( interestLevel, nbInterestLevels )], - Values[Durability], Values[Weight], Values[DMG], Values[Speed], Values[SapLoad], Values[Range], - (rPeak!=~0) ? toString( " (PEAK for %s)", sCharacs[rPeak] ).c_str() : "" );*/ - - return true; -} -#endif - - -/* - * Returns false if the RM must NOT be generated. - */ -sint32 CFaberCharacteristics::computeValues( TStatQuality statQuality, const TFamInfo& famInfo, sint remarkableIndicesSetBaseIndex, - TEcosystem iEcosystem, uint iFreq, uint iFamily ) -{ - nlassert( FaberElement != ~0 ); - nlassert( statQuality != NAInterestLevel ); - - // Special case (jewels) - if ( FaberElement == ITEM_PART_JEWEL_GEM ) - { - computeJewelProtection( statQuality, iEcosystem, iFamily ); - } - - // First set all stats to the medium value for the required quality - static float MediumStatsByStatQuality [NbStatQualities] = { 20.0f, 35.0f, 50.0f, 65.0f, 80.0f }; - float statEnergyAvg = MediumStatsByStatQuality[statQuality]; - for ( uint rCharac=0; rCharac!=NbCharacs; ++rCharac ) - { - if ( CharacSlotFilter[rCharac][FaberElement] ) - Values[rCharac] = statEnergyAvg; - } - - // Special case for RM with no boost or lowering - if ( remarkableIndicesSetBaseIndex == -1 ) - return (sint32)statEnergyAvg; - - // Calculate the number of characs in filtered list - /*uint nbFilteredCharacs = 0; - for ( uint rCharac=0; rCharac!=NbCharacs; ++rCharac ) - { - if ( CharacSlotFilter[rCharac][FaberElement] ) - ++nbFilteredCharacs; - }*/ - - vector RemarkableByCharac( NbCharacs, false ); - - // Boost one stat up (+40) - float remaining = 0; - /*Obsolete: remarkable indices were relative marked characs, not to the whole charac set - uint rBestCharac = ~0; - uint indexOfRemarkableCharacInFiltered = famInfo.RemarkableStatIndex[remarkableIndicesSetBaseIndex+RBest] % nbFilteredCharacs; - sint indexOfCharacInFiltered = -1; - for ( uint rCharac=0; rCharac!=NbCharacs; ++rCharac ) - { - if ( CharacSlotFilter[rCharac][FaberElement] ) - ++indexOfCharacInFiltered; - if ( indexOfCharacInFiltered = indexOfRemarkableCharacInFiltered ) - { - RemarkableByCharac[rCharac] = true; - rBestCharac = rCharac; - Values[rCharac] += 40.0f; - if ( Values[rCharac] > 100.0f ) - remaining = Values[rCharac] - 100.0f; - } - } - nlassert( rBestCharac != ~0 ); // we should have found the best index - */ - uint rBestCharac = famInfo.RemarkableStatIndex[remarkableIndicesSetBaseIndex+RBest]; - RemarkableByCharac[rBestCharac] = true; - Values[rBestCharac] += 40.0f; - - // Lower two stats (-20, -20) - for ( uint i=RWorst1; i<=RWorst2; ++i ) - { - if ( famInfo.RemarkableStatIndex[remarkableIndicesSetBaseIndex+i] == -1 ) - { - // Case (+20, -20) instead of (+40, -20, -20) because only two characs in filtered list - nlassert( i==RWorst2 ); - Values[rBestCharac] -= 20.0f; // +40 already applied - break; // -20 already applied when i==Worst1 - } - - /*indexOfRemarkableCharacInFiltered = famInfo.RemarkableStatIndex[remarkableIndicesSetBaseIndex+i] % nbFilteredCharacs; - indexOfCharacInFiltered = -1; - for ( uint rCharac=0; rCharac!=NbCharacs; ++rCharac ) - { - if ( CharacSlotFilter[rCharac][FaberElement] ) - ++indexOfCharacInFiltered; - if ( indexOfCharacInFiltered = indexOfRemarkableCharacInFiltered ) - { - if ( RemarkableByCharac[rCharac] ) - nlerror( "Twice the same remarkable charac" ); - RemarkableByCharac[rCharac] = true; - Values[rCharac] -= 20.0f; - nlassert( ! (Values[rCharac] < 0) ); - } - }*/ - uint rCharac = famInfo.RemarkableStatIndex[remarkableIndicesSetBaseIndex+i]; - if ( RemarkableByCharac[rCharac] ) - nlerror( "Twice the same remarkable charac" ); - RemarkableByCharac[rCharac] = true; - Values[rCharac] -= 20.0f; - if ( (Values[rCharac] < 1.0f) && (rCharac == Durability) ) - Values[rCharac] = 1.0f; // prevent from having a null durability (= no item part) - nlassert( ! (Values[rCharac] < 0) ); - } - - // Clamp max of Best charac (after lowering, because it can modify the Best charac) - if ( Values[rBestCharac] > 100.0f ) - { - remaining = Values[rBestCharac] - 100.0f; - Values[rBestCharac] = 100.0f; - } - - // Raise other with optional remaining (divided by the number to raise) - if ( remaining > 0 ) - { - float nbToRaise = 0; - for ( uint rCharac=0; rCharac!=NbCharacs; ++rCharac ) - { - if ( CharacSlotFilter[rCharac][FaberElement] && (!RemarkableByCharac[rCharac]) ) - ++nbToRaise; - } - nlassert( nbToRaise != 0 ); - float remainingSlice = remaining / nbToRaise; - for ( uint rCharac=0; rCharac!=NbCharacs; ++rCharac ) - { - if ( CharacSlotFilter[rCharac][FaberElement] && (!RemarkableByCharac[rCharac]) ) - { - Values[rCharac] += remainingSlice; - } - } - } - - return (sint32)statEnergyAvg; -} - - -//// DISABLED -#if 0 -/* - * Returns false if the RM must NOT be generated. - */ -bool CFaberCharacteristics::randomizeJewelProtection( TStatQuality statQuality, TEcosystem iEcosystem, uint iFreq, uint iFamily ) -{ - PROTECTION_TYPE::TProtectionType protectionType; - - // Test if the family-ecosystem already has a jewel protection type - string feKey = familyCodes[iFamily] + ecosystemCodes[iEcosystem]; - CProtectionTypeMap::iterator it = JewelProtectionTypeByFamilyEcosystem.find( feKey ); - if ( it != JewelProtectionTypeByFamilyEcosystem.end() ) - { - protectionType = (*it).second; - } - else - { - /*if ( iFreq > 2 ) // 100% of "freq>=3" RM - { - protectionType = PROTECTION_TYPE::None; - } - else if ( iFreq > 1 ) - { - uint iRandomPercent = getRandomValue( 100 ); - if ( iRandomPercent < 50 ) // 50% of "freq 2" RM - { - protectionType = PROTECTION_TYPE::None; - } - else // 50% of "freq 2" RM - { - uint iProType = getRandomValue( 3 ); - protectionType = (PROTECTION_TYPE::TProtectionType)(PROTECTION_TYPE::Cold + iProType); - } - }*/ - if ( iEcosystem == CommonEcosystem ) - { - uint iRandomPercent = getRandomValue( 100 ); - if ( iRandomPercent < 50 ) // 50% of "freq 2" RM - { - protectionType = PROTECTION_TYPE::None; - } - else // 50% of "freq 2" RM - { - uint iProType = getRandomValue( 3 ); - protectionType = (PROTECTION_TYPE::TProtectionType)(PROTECTION_TYPE::Cold + iProType); - } - } - else - { - // Get the civ speciality corresponding to the rm family (if any) - /*const TFamInfo& rmFamily = FamSet[families[iFamily]]; - TCiv civ = AllCiv; //nlinfo( "%s %u", rmFamily.CompatibleCraftParts.c_str(), rmFamily.Properties.size() ); - uint iP = rmFamily.getPropIndexByCraftPart( 'A' + (char)ITEM_PART_JEWEL_GEM ); - if ( iP != ~0 ) - civ = rmFamily.Civs[iP];*/ - - // Ensure there is one speciality protection type per civ - TCiv civ = EcosystemToCiv[iEcosystem]; - if ( /*(civ != AllCiv)*/ (iEcosystem >= Desert) && (iEcosystem <= Jungle) && (!HasSpecializedJewelProtectionTypeByCiv[civ]) ) - { - switch ( /*civ*/iEcosystem ) - { - case /*Fyros*/Desert: protectionType = PROTECTION_TYPE::Fire; break; - case /*Matis*/Forest: protectionType = PROTECTION_TYPE::Poison; break; - case /*Tryker*/Lacustre: protectionType = PROTECTION_TYPE::Shockwave; break; - case /*Zorai*/Jungle: protectionType = PROTECTION_TYPE::Electricity; break; - } - HasSpecializedJewelProtectionTypeByCiv[civ] = true; - } - else - { - uint iProType; - // Ensure all values are used - do - { - iProType = getRandomValue( PROTECTION_TYPE::None-PROTECTION_TYPE::Madness ); - protectionType = (PROTECTION_TYPE::TProtectionType)(PROTECTION_TYPE::Madness + iProType); - } - while ( (midProtectionTypesUsed.size() < PROTECTION_TYPE::None-PROTECTION_TYPE::Madness) - && midProtectionTypesUsed.find( protectionType ) != midProtectionTypesUsed.end() ); - midProtectionTypesUsed.insert( protectionType ); - } - } - JewelProtectionTypeByFamilyEcosystem.insert( make_pair( feKey, protectionType ) ); - } - - // Disable the protection if the interest level does not match the protection type (cold-rot always, madness-mm from C, fire-electric from E) - /*if ( protectionType >= PROTECTION_TYPE::Madness ) - { - if ( statQuality == Basic ) // reject Basic - { - protectionType = PROTECTION_TYPE::None; - //return false; // do not suppress the RM as it can be used for another item part - } - } - else if ( protectionType >= PROTECTION_TYPE::Fire ) - { - if ( statQuality < Choice ) // reject Basic, Fine - { - protectionType = PROTECTION_TYPE::None; - //return false; - } - }*/ - - Values[JewelProtection] = (float)(uint)protectionType; - return true; -} -#endif - - -/* - * - */ -void CFaberCharacteristics::computeJewelProtection( TStatQuality statQuality, TEcosystem iEcosystem, uint iFamily ) -{ - TFamInfo& famInfo = FamSet[families[iFamily]]; - if ( famInfo.JewelProtIndex == -1 ) - { - Values[JewelProtection] = (float)PROTECTION_TYPE::None; - } - else - { - uint protIndex = (uint)famInfo.JewelProtIndex; - if ( protIndex < PROTECTION_TYPE::Fire ) - { - Values[JewelProtection] = (statQuality >= Fine) ? (float)(PROTECTION_TYPE::TProtectionType)protIndex : (float)PROTECTION_TYPE::None; - } - else if ( protIndex == PROTECTION_TYPE::Fire ) - { - static const PROTECTION_TYPE::TProtectionType EcosystemToProtectionType[NbEcosystems] = { - PROTECTION_TYPE::None, // Common - PROTECTION_TYPE::Fire, // Desert (Fyros) - PROTECTION_TYPE::Poison, // Forest (Matis) - PROTECTION_TYPE::Shockwave, // Lacustre (Tryker) - PROTECTION_TYPE::Electricity, // Jungle (Zorai) - PROTECTION_TYPE::Fear // Primeroot - }; - Values[JewelProtection] = (statQuality >= Choice) ? (float)EcosystemToProtectionType[iEcosystem] : (float)PROTECTION_TYPE::None; - } - else if ( protIndex >= PROTECTION_TYPE::Madness ) - { - Values[JewelProtection] = (statQuality >= Choice) ? (float)(PROTECTION_TYPE::TProtectionType)protIndex : (float)PROTECTION_TYPE::None; - } - } -} - - -/* - * Reject a prop if any of the previous props are in its incompatibility list - * (assumes the incompatibity lists are filled for every property) - */ -bool passPropSetFilter( const vector& iPropertyRelatedProperties, uint32 *iProperties, sint rCurrentProp, uint32 iProp ) -{ - for ( sint r=0; r!=rCurrentProp; ++r ) - { - if ( ! passNegativeFilter( iPropertyRelatedProperties, iProperties[r] ) ) - return false; - } - return true; -} - - -/* - * Reject a faber element if it is NOT in the compatibility list - */ -bool passFaberElementFilter( const vector& iCompatibleFaberElements, uint32 rFaberElement ) -{ - return passPositiveFilter( iCompatibleFaberElements, rFaberElement ); -} - -/* - * Reject a color if it is in the incompatibility list of a family - */ -/*bool passColorFilter( const vector& iFamilyRelatedColors, uint32 iColor ) -{ - return passPositiveFilter( iFamilyRelatedColors, iColor ); -}*/ - - -/* - * - */ -void setCustomizedPropertyValues( UFormElm& node, const CSString& sheetFilename ) -{ - CRulesStr2Filter::const_iterator icp = CustomizedPropertiesSheetName.find( sheetFilename ); - if ( icp != CustomizedPropertiesSheetName.end() ) - { - uint nbCustomProps = 0; - for ( vs::const_iterator ip=(*icp).second.begin(); ip!=(*icp).second.end(); ++ip ) - { - CSString propName = *ip; - ++ip; - if ( ip == (*icp).second.end() ) - { - nlwarning( "Malformed CustomizedProperties line" ); - break; - } - CSString value = *ip; - node.setValueByName( value.c_str(), propName.c_str() ); - ++nbCustomProps; - } - nldebug( "%s has %u customized properties", sheetFilename.c_str(), nbCustomProps ); - } -} - - -/* - * - */ -void randomizeProperties( uint32 *iProperties, uint32 iFamily, uint32 iEcosystem, uint32 &nbRejectedProperties ) -{ - nlerror( "TODO" ); -#if 0 - sint rProperty; // property rank - // Randomize properties - for ( rProperty=0; rProperty!=NbPropertySlots; ++rProperty ) - { - uint32 iProp, nbTries = 0; - - // Get random value and apply property rules filters - do - { - if ( nbTries != 0 ) // debug display - { - //nldebug( "Rejected property %s in family %s with", properties[iProp].c_str(), families[iFamily].c_str() ); - //for ( sint r=0; r!=rProperty; ++r ) - // DebugLog->displayRaw( "%s ", properties[iProperties[r]].c_str() ); - //DebugLog->displayRawNL( "" ); - } - iProp = getRandomValue( properties.size() ); - ++nbTries; - } - while ( ! (passPropFamilyFilter( familyPropertyFilter[iFamily], iProp ) && - passPropSetFilter( propertySetFilter[iProp], iProperties, rProperty, iProp )) ); - nbRejectedProperties += nbTries - 1; - - // Remove redundancy (undefine if already set) - for ( sint r=0; r!=rProperty; ++r ) - { - if ( iProp == iProperties[r] ) - { - iProp = UndefinedProperty; - break; - } - } - - iProperties[rProperty] = iProp; - } - - // Move undefined properties at the back - sint lastPropertySlot = NbPropertySlots-1; - for ( rProperty=lastPropertySlot-1; rProperty>=0; --rProperty ) - { - if ( iProperties[rProperty] == UndefinedProperty ) - { - sint lastUsedPropertySlot = getLastUsedPropertySlot( iProperties, lastPropertySlot, UndefinedProperty ); - if ( lastUsedPropertySlot == -1 ) - { - nlwarning( "No matching properties for %s %s", ecosystems[iEcosystem].c_str(), families[iFamily].c_str() ); - } - if ( lastUsedPropertySlot > rProperty ) - { - uint32 itmp = iProperties[lastUsedPropertySlot]; - iProperties[lastUsedPropertySlot] = iProperties[rProperty]; - iProperties[rProperty] = itmp; - } - } - } -#endif -} - - - - -/* - * Returns name in capitals, or an empty string if no match - */ -//string findRawMaterialFromCriteria( uint32 iEcosystem, uint32 iFamily, uint32 iCreature, TFaberInterestLevel actualLevel, char **errorReport ) -//{ -// vector *codes = NULL; -// bool found = false; -// -// if ( iCreature != ~0 ) -// { -// // 1. Match ecosystem and creature specialization -// RawMaterialRepository.getFaberCombinationCodes( iEcosystem, iFamily, iCreature, &codes ); -// if ( codes && (! codes->empty()) ) -// found = true; -// else -// { -// // 2. Match creature specialization in common ecosystem -// RawMaterialRepository.getFaberCombinationCodes( CommonEcosystem, iFamily, iCreature, &codes ); -// if ( codes && (! codes->empty()) ) -// found = true; -// } -// } -// if ( ! found ) -// { -// iCreature = ~0; -// -// // 3. Match ecosystem and common creature -// RawMaterialRepository.getFaberCombinationCodes( iEcosystem, iFamily, iCreature, &codes ); -// if ( codes && (! codes->empty()) ) -// found = true; -// else -// { -// // 4. Match common creature in common ecosystem -// RawMaterialRepository.getFaberCombinationCodes( CommonEcosystem, iFamily, iCreature, &codes ); -// if ( codes && (! codes->empty()) ) -// found = true; -// } -// } -// if ( ! found ) -// { -// *errorReport = "no compatible family"; -// return ""; -// } -// else -// { -// // Remap requested interest level if the material found is from common type -// if ( iCreature == ~0 ) -// { -// actualLevel = actualLevel * NbFaberInterestLevelsByEcosystem[CommonEcosystem] / NbFaberInterestLevelsByEcosystem[iEcosystem]; -// } -// -// // Discard faber codes that are higher than the requested level -// //nldebug( "Codes 1: %u", codes->size() ); -// vector matchingCodes; -// vector::iterator ic; -// for ( ic=codes->begin(); ic!=codes->end(); ++ic ) -// { -// if ( hasMatchingFaberLevel( (*ic).FirstLevel, actualLevel ) ) -// matchingCodes.push_back( &(*ic) ); -// } -// if ( matchingCodes.empty() ) -// { -// *errorReport = "no compatible level"; -// return ""; -// } -// //nldebug( "Codes 2: %u", matchingCodes.size() ); -// -// // Select best level matches -// keepOnlyHighestLevel( matchingCodes ); -// nldebug( "%s has %u matches", families[iFamily].c_str(), matchingCodes.size() ); -// -// // Choose one faber combination -// uint32 iComb = getRandomValue( matchingCodes.size() ); -// -// // Build string -// string crStr = (iCreature == ~0) ? CommonCreatureCode : creatureCodes[iCreature]; -// string ilStr = toString( "%02d", matchingCodes[iComb]->FirstLevel + 1 ); // 00 is NAInterestLevel; -// string faberStr( NB_FABERELEMS_CODE_CHARS, ' ' ); -// memcpy( &faberStr[0], matchingCodes[iComb]->Code.Ch, NB_FABERELEMS_CODE_CHARS ); -// string name = "m" + familyCodes[iFamily] + crStr + ecosystemCodes[iEcosystem] + ilStr + faberStr; -// strlwr( name ); -// //nlinfo( "%s", name.c_str() ); -// return name; -// } -//} - - -/* - * 1st arg: whichArray - * 2nd arg: col - * 3rd arg: iFamily - */ -typedef void (*TDispatchFunc) ( uint32, uint32, uint32 ); - - -/* - * Build SkgroupToModels and CreatureModels - */ -void deliverCreatureModels( vs& srcRow ) -{ - if ( ! srcRow[0].empty() ) - { - bool isModelRow = (srcRow.size()>2) && (srcRow[1]=="M"); - bool isNameRow = (srcRow.size()>2) && (srcRow[1]=="N"); - for ( uint32 c=2; c!=srcRow.size(); ++c ) - { - if ( ! srcRow[c].empty() ) - { - if ( isModelRow && (!srcRow[c].empty()) ) - { - // Models (ex: HD) - SkgroupToModels[srcRow[0]].push_back( srcRow[c] ); - nldebug( "Model: '%s' for %s (%u)", srcRow[c].c_str(), srcRow[0].c_str(), SkgroupToModels[srcRow[0]].size()-1 ); - } - else if ( isNameRow ) - { - // Creature names (by model) (assumes names are below filenames) - vs& modelsOfGroup = SkgroupToModels[srcRow[0]]; - uint32 skIndex = c - 3; // warning: beginning at column D - if ( skIndex < modelsOfGroup.size() ) - { - CreatureModels[modelsOfGroup[skIndex]].Name = srcRow[c]; - CSString abbrevName = makeAbbrevName( srcRow[c], CreatureModels ); - CreatureModels[modelsOfGroup[skIndex]].AbbrevName = abbrevName; - nldebug( "Name: %s '%s' %s", modelsOfGroup[skIndex].c_str(), srcRow[c].c_str(), abbrevName.c_str() ); - - } - else - nlwarning( "Can't set name %s for %s (%u)", srcRow[c].c_str(), srcRow[0].c_str(), skIndex ); - } - } - } - } -} - - -/* - * - */ -/*void deliverSkgroups( vs& srcRow ) -{ - if ( ! srcRow[0].empty() ) - { - for ( uint32 c=1; c!=srcRow.size(); ++c ) - { - if ( ! srcRow[c].empty() ) - { - if ( srcRow[c].findNS( ".skel" ) != string::npos ) - { - // Skeleton filenames - SkgroupToModels[srcRow[0]].push_back( srcRow[c] ); - nldebug( "Skeleton: '%s' for %s (%u)", srcRow[c].c_str(), srcRow[0].c_str(), SkgroupToModels[srcRow[0]].size()-1 ); - } - else - { - // Creature names (by skeleton) (assumes names are below filenames) - vs& skeletonsOfGroup = SkgroupToModels[srcRow[0]]; - uint32 skIndex = c - 3; // warning: beginning at column D - if ( skIndex < skeletonsOfGroup.size() ) - { - CreatureModels[skeletonsOfGroup[skIndex]].Name = srcRow[c]; - CSString abbrevName = makeAbbrevName( srcRow[c], CreatureModels ); - CreatureModels[skeletonsOfGroup[skIndex]].AbbrevName = abbrevName; - nldebug( "Name: %s '%s' %s", skeletonsOfGroup[skIndex].c_str(), srcRow[c].c_str(), abbrevName.c_str() ); - - } - else - nlwarning( "Can't set name %s for %s (%u)", srcRow[c].c_str(), srcRow[0].c_str(), skIndex ); - } - } - } - } -}*/ - -/* - * Build CreatureToModel (obsolete, used creature_skeletons.csv) - */ -/*void deliverSkeletons( vs& srcRow ) -{ - if ( (srcRow[0] != "FILE") && (srcRow.size()>1) && (!srcRow[1].empty()) ) - { - // Remove quotes - string::size_type p = 0; - while ( p < srcRow[1].size() ) - { - if ( srcRow[1][p] == '"' ) - srcRow[1].erase( p, 1 ); - else - ++p; - } - if ( ! srcRow[1].empty() ) - { - // Read mapping creature -> skeleton - CSkeletonMap::iterator ism = CreatureModels.find( srcRow[1] ); - if ( ism == CreatureModels.end() ) - nldebug( "%s", srcRow[1].c_str() ); - - if ( (srcRow[0].size() == 6) && (srcRow[0][0] == 'c') ) - { - TSkeletonInfo& skeInfo = CreatureModels[srcRow[1]]; - CSString creaModel = srcRow[0].left( 5 ); - CreatureFamilyIndices[creaModel] = vu(); - skeInfo.IsUsed = true; - skeInfo.CreaturesOfSke.push_back( srcRow[0] ); - CreatureToModel[creaModel] = srcRow[1]; - //nlinfo( "Selecting %s (%s)", srcRow[1].c_str(), creaModel.c_str() ); - } - else - { - //nlinfo( "Discarding %s", srcRow[1].c_str() ); - CreatureModels.insert( make_pair( srcRow[1], TSkeletonInfo() ) ); - } - } - } -}*/ - - -/* - * - */ -/*void dispatchToCreatures( uint32, uint32 col, uint32 iFamily ) -{ - nlassert( ! skeletonGroupColumns.empty() ); // missing SkeletonGroup line? - CSString& skegrp = skeletonGroupColumns[col]; - vs& skeletons = SkgroupToModels[skegrp]; - if ( skeletons.empty() ) - nlwarning( "No skeleton found for group '%s'", skegrp.c_str() ); - for ( vs::const_iterator isk=skeletons.begin(); isk!=skeletons.end(); ++isk ) - { - const CSString& ske = *isk; - CreatureModels[ske].SkGroup = skegrp; - nldebug( "%u: %s -> %s", col, skegrp.c_str(), ske.c_str() ); - - vs& creatures = CreatureModels[ske].CreaturesOfSke; - for ( vs::const_iterator ic=creatures.begin(); ic!=creatures.end(); ++ic ) - { - const CSString& creaCode = *ic; - if ( (creaCode.size() == 6) && (creaCode[0] == 'c') && (creaCode[5]>='0') && (creaCode[5]<='5') ) - { - CSString creaModel = creaCode.rightCrop( 1 ); // don't use local level - vu& familiesForCreature = CreatureFamilyIndices[creaModel]; - if ( find( familiesForCreature.begin(), familiesForCreature.end(), iFamily ) == familiesForCreature.end() ) - { - familiesForCreature.push_back( iFamily ); - if ( ! CreatureModels[ske].IsUsed ) - nldebug( "Now %s used", ske.c_str() ); - CreatureModels[ske].IsUsed = true; - CreatureToModel[creaModel] = ske; - //nldebug( "%s -> %s %s %s", creaModel.left( 3 ).c_str(), CreatureModels[ske].Name.c_str(), CreatureModels[ske].AbbrevName.c_str(), ske.c_str() ); - } - } - } - } -}*/ - - -/* - * - */ -/*void deliverCreatures( vs& srcRow ) -{ - if ( srcRow[0] == "SkeletonGroup" ) - { - srcRow[0] = srcRow[0].strip(); - skeletonGroupColumns.push_back( "" ); // column 0 - for ( uint32 c=1; c!=srcRow.size(); ++c ) - { - if ( ! srcRow[c].empty() ) - { - // Set new value in column list - skeletonGroupColumns.push_back( srcRow[c] ); - } - else - { - // Copy last value in column list - if ( ! skeletonGroupColumns.empty() ) - skeletonGroupColumns.push_back( skeletonGroupColumns.back() ); - } - } - nldebug( "%u skeleton group columns", skeletonGroupColumns.size() ); - } -}*/ - - -/* - * - */ -void deliverItemPartParams( vs& srcRow ) -{ - const uint itemPartCol = 0; // 1 from base 1 - const uint legendCol = 6; - const uint firstCharacCol = 7; // 8 from base 1 - - if ( srcRow.size() < legendCol+1 ) - return; - - // Read item part index - uint rItemPart = ~0; - if ( ! srcRow[itemPartCol].empty() ) - rItemPart = (uint)(srcRow[itemPartCol][0] - 'A'); - - // Select item part compatibility or charac bound - uint characParam = ~0; - if ( srcRow[legendCol].empty() ) - { - if ( rItemPart != ~0 ) - { - if ( srcRow.size() < firstCharacCol+1 ) - { - nlwarning( "Can't find compatibility for craft characs of item parts %s", srcRow[itemPartCol].c_str() ); - return; - } - - characParam = 0; - nldebug( "Loading compability for craft characs of item part %s", srcRow[itemPartCol].c_str() ); - if ( ! CraftParts.isEnabled( rItemPart ) ) - nlinfo( "Item part %s was absent from rm_fam_prop.csv (disabled)", srcRow[itemPartCol].c_str() ); - } - else - { - return; - } - } - else if ( srcRow[legendCol] == "Positive" ) - { - characParam = 1; - nldebug( "Loading calc way for craft characs" ); - } - else if ( srcRow[legendCol] == "Min" ) - { - characParam = 2; - nldebug( "Loading min bounds for craft characs" ); - } - else if ( srcRow[legendCol] == "Max" ) - { - characParam = 3; - nldebug( "Loading max bounds for craft characs" ); - } - else if ( srcRow[legendCol] == "Peak" ) - { - characParam = 4; - nldebug( "Loading peak bounds for craft characs" ); - } - else - { - nlwarning( "Unknown legend for item part charac: %s", srcRow[legendCol].c_str() ); - return; - } - - // Read item part compatibility or charac bounds - for ( uint c=firstCharacCol; cgetRootNode() ); - form->getRootNode().setValueByName( ecosystems[iEcosystem].c_str(), "mp.Ecosystem" ); - form->getRootNode().setValueByName( "raw material (mp)", "basics.family" ); - form->getRootNode().setValueByName( (sint32)99, "basics.stackable" ); - form->getRootNode().setValueByName( "Faber", "mp.Category" ); - CIconInfo& iconInfo = Icons[ecosystems[iEcosystem]]; - if ( ! iconInfo.IconBackground.empty() ) - form->getRootNode().setValueByName( iconInfo.IconBackground.c_str(), "3d.icon background" ); - else - nlwarning( "Can't find icon background for ecosystem %s", ecosystems[iEcosystem].c_str() ); - - CSString ecoParentName = getEcoParentName( iEcosystem ); - - setCustomizedPropertyValues( form->getRootNode(), ecoParentName ); - - // Don't save in ecosystem directory but in parent dir - flushSheetToDisk( rawMaterialPath + "_parent/" + ecoParentName, form ); -} - - -// _m + 2 chars -CSString getFamParentName( uint32 iFamily ) -{ - return CSString("_m") + familyCodes[iFamily] + "." + rmSheetType; -} - -/* - * - */ -void writeParentSheetFam( CForm *form, uint32 iFamily ) -{ - const TFamInfo& famInfo = FamSet[families[iFamily]]; - if ( ! famInfo.IsActive ) - return; - - // Family - clearSheet( form, &form->getRootNode() ); - form->getRootNode().setValueByName( families[iFamily].c_str(), "mp.Family" ); - - // Group - if ( famInfo.Group != ~0 ) - form->getRootNode().setValueByName( groups[famInfo.Group].c_str(), "mp.Group" ); - - // Icons - CIconInfo& iconInfo = Icons[families[iFamily]]; - if ( ! iconInfo.Icon.empty() ) - form->getRootNode().setValueByName( iconInfo.Icon.c_str(), "3d.icon" ); - else - { - nlwarning( "Can't find icon for family %s", families[iFamily].c_str() ); - /*CIconInfo& iconInfo2 = Icons["Unknown"]; - if ( ! iconInfo2.Icon.empty() ) - form->getRootNode().setValueByName( iconInfo2.Icon.c_str(), "3d.icon" ); - else - nlwarning( "Can't find ricon for default background (Unknown)" );*/ - } - - //form->getRootNode().setValueByName( "TODO", "mp.HarvestSkill" ); - CSString famParentName = getFamParentName( iFamily ); - - // New: abrevname even for raw materials from deposits - if ( ! famInfo.IsInCreatures ) - { - CSString& abbrevName = makeAbbrevName( families[iFamily] ); - if ( ! abbrevName.empty() ) - form->getRootNode().setValueByName( abbrevName.c_str(), "3d.text overlay" ); - } - - // Bulk - form->getRootNode().setValueByName( "0.5", "basics.Bulk" ); - - // Sellable? - form->getRootNode().setValueByName( (!famInfo.IsForMission) ? "true" : "false", "basics.Drop or Sell" ); - /*bool tmpTest; // check bool read/write - form->getRootNode().getValueByName( tmpTest, "basics.Drop or Sell" ); - nlassert( tmpTest == (!famInfo.IsForMission) );*/ - - setCustomizedPropertyValues( form->getRootNode(), famParentName ); - - // Don't save in ecosystem directory but in parent dir - flushSheetToDisk( rawMaterialPath + "_parent/" + famParentName, form ); -} - - -// _m + 3 chars -CSString getCreaParentName( const CSString& creaMainModel ) -{ - return CSString("_m") + creaMainModel + "." + rmSheetType; -} - -/* - * - */ -void writeParentSheetCreature( CForm *form, const CSString& creaModel ) -{ - // Write abbrev name - //nldebug( "%s %s %s %u", creaModel.c_str(), CreatureToModel[creaModel].c_str(), CreatureModels[CreatureToModel[creaModel]].SkGroup.c_str(), CreatureModels[CreatureToModel[creaModel]].CreaturesOfSke.size() ); - CSString& abbrevName = CreatureModels[creaModel].AbbrevName; - if ( ! abbrevName.empty() ) - form->getRootNode().setValueByName( abbrevName.c_str(), "3d.text overlay" ); - else - nlwarning( "Can't find abbrev name for %s", creaModel.c_str() ); - - CSString creaParentName = "_mc" + creaModel.toLower() + "." + rmSheetType; - - setCustomizedPropertyValues( form->getRootNode(), creaParentName ); - - // Save in base dir - flushSheetToDisk( rawMaterialPath + "_parent/" + creaParentName, form ); -} - - -/* - * - */ -bool CMainStat::updateCraftStatistics( uint32 rFaberElem, uint32 iEcosystem, uint32 iFam, TCiv civ ) -{ - ++NbRMByFaberElem[rFaberElem]; - ++NbRMByFaberElemByEcosystem[iEcosystem][rFaberElem]; - ++NbRMByFaberElemByFamilyAndCiv[iFam][civ][rFaberElem]; - return true; -} - - -/* - * Returns false if the RM must NOT be generated. - */ -bool CGenRawMaterial::computeCraftCharacs( uint iVariant, const CSString& sheetName ) -{ - /*CSString props; - for ( uint32 p=0; p!=RMProperties.size(); ++ p ) - props += " " + properties[RMProperties[p]]; - nldebug( "%s %s %s", locFam.c_str(), props.c_str(), (familyGroups[iFam]==~0) ? "-" : groups[familyGroups[iFam]].c_str() );*/ - - vector actualEnergies( NbFaberElements, 0.0f ); - vector sapLoads( NbFaberElements, 0.0f ); - TFamInfo& famInfo = FamSet[familyStr()]; - sint masterSumFreq = 0; - - // Compute craft scores - sint nbFaberElemsFilled = 0; - for ( uint32 rFaberElem=0; rFaberElem!=NbFaberElements; ++rFaberElem ) - { - // Exclude if in exclusion list - if ( hasCraftPart( rFaberElem ) ) - { - /*sint rarityModifier = 0; - float baseBoost = 0.0f; - - // For the PrimeRoots ecosystem, increase the stats and rarity - if ( IEcosystem == PrimeRoots ) - { - ++rarityModifier; - baseBoost = 10.0f; - }*/ - - /*// For raw materials specialized by civ matching the ecosystem, increase their craft stats - TCiv civ = getCivSpec( rFaberElem, famInfo ); - if ( civ != AllCiv ) - { - uint iCivEcosystem = getIndexFromString( string(CivEcosystemCodes[civ]), ecosystemCodes ); - if ( iCivEcosystem == IEcosystem ) - { - ++rarityModifier; - } - }*/ - - // For rare raw materials, increase their craft stats - sint sumFreq = 0; - for ( vu::iterator ivf=famInfo.Freqs.begin(); ivf!=famInfo.Freqs.end(); ++ivf ) - sumFreq += (sint)(*ivf); - sint avgFreq = sumFreq / (sint)famInfo.Freqs.size(); - /*avgFreq = max( avgFreq - rarityModifier, 0 ); - masterSumFreq += avgFreq; - float peakOccurRatio; - switch ( avgFreq ) - { - case 0: peakOccurRatio = 0.60f; break; // 60% - case 1: peakOccurRatio = 0.40f; break; // 40% - case 2: peakOccurRatio = 0.20f; break; // 20% - default: peakOccurRatio = 0.01f / (float)(avgFreq-2); // 3=1%, 4=0.5%, 5=0.33%... - }*/ - //float peakOccurRatio = 0.01f; - - // Compute scores (5 levels, width ratio=2 i.e. enlargedSlice=40%) - CFaberCharacteristics craftSlot; - craftSlot.initFaberElement( rFaberElem ); - // Now, the stat values are no more random (except special things such as jewels) - /*if ( ! craftSlot.randomizeValues( (TFaberInterestLevel)(StatQuality), 5, iVariant, 2.0f, peakOccurRatio, baseBoost, (TEcosystem)IEcosystem, avgFreq, IFamily ) ) - return false;*/ - sint remarkableIndicesSetBaseIndex = nbFaberElemsFilled * 3; - if ( avgFreq == 0 ) - remarkableIndicesSetBaseIndex = -1; // "Kitin Larva" : all at 80 - else - nlassert( nbFaberElemsFilled < 2 ); - sint32 newStatEnergy = craftSlot.computeValues( StatQuality, famInfo, remarkableIndicesSetBaseIndex, (TEcosystem)IEcosystem, avgFreq, IFamily ); - nlassert( (StatEnergyAvg == 0) || (newStatEnergy == StatEnergyAvg) || (newStatEnergy == -1) ); - if ( newStatEnergy == -1 ) - return false; - StatEnergyAvg = newStatEnergy; - RMCraftCharacs.push_back( craftSlot ); - actualEnergies[rFaberElem] = craftSlot.ActualEnergy; - sapLoads[rFaberElem] = craftSlot.Values[SapLoad]; - - ++nbFaberElemsFilled; - } - } - // For mission RMs, set statenergy as class - if ( nbFaberElemsFilled == 0 ) - { - uint zoneLevel = (uint)(sheetName[RM_INDEX_LEVELZONE_CODE]-'a'); - if ( zoneLevel == 0 ) - StatEnergyAvg = 20; - else - StatEnergyAvg = 20 + (zoneLevel-1)*15; - } - - // Compute rarity - sint masterAvgFreq; - if ( nbFaberElemsFilled == 0 ) - { - // TODO: When the RM is not craftable, the rarity (=> price) depends on the level - sint sumFreq = 0; - for ( vu::iterator ivf=famInfo.Freqs.begin(); ivf!=famInfo.Freqs.end(); ++ivf ) - sumFreq += (sint)(*ivf); - masterAvgFreq = sumFreq / (sint)famInfo.Freqs.size(); - } - else - { - // TODO: depend not only on freq but on ILevelZone or craft characteristics - masterAvgFreq = masterSumFreq / nbFaberElemsFilled; - } - /*switch ( masterAvgFreq ) - { - case 1 : Rarity = (IEcosystem==PrimeRoots? 80 : 67); break; // only PrimeRoots and one other ecosystem - case 2 : Rarity = 33; break; // Common - case 3 : Rarity = 67; break; // only one ecosystem - case 4 : Rarity = 1; break; // Goo - default: Rarity = 100; - }*/ - - // Compute property depths - IPropertyDepths.resize( famInfo.Properties.size() ); - for ( uint p=0; p!=famInfo.CraftPartsByProp.size(); ++p ) - { - // Calculate a single property depth using the actual energies of faber elements that use the property - uint32 nbFaberElemsThatUseTheProps = 0; - float sumActualEnergy = 0.0f; - for ( uint iCompatibleCP=famInfo.getBeginCraftPartForProp(p); iCompatibleCP!=famInfo.getEndCraftPartForProp(p); ++iCompatibleCP ) - { - uint rFaberElem = famInfo.getCompatibleCraftPart( iCompatibleCP ); - sumActualEnergy += actualEnergies[rFaberElem]; - ++nbFaberElemsThatUseTheProps; - } - float avgActualIEnergy = 0.0f; - if ( nbFaberElemsThatUseTheProps != 0 ) - avgActualIEnergy = sumActualEnergy / (float)nbFaberElemsThatUseTheProps; - if ( avgActualIEnergy < 0 ) - avgActualIEnergy = 0.0f; - uint32 iPropertyDepth = (uint32)(avgActualIEnergy*((float)(NbPropertyDepths - 1))) + 1; - if ( iPropertyDepth >= NbPropertyDepths ) - iPropertyDepth = NbPropertyDepths-1; - //nldebug( "Depth %s %s-%u: %s (%.2f)", properties[iProperty].c_str(), locFam.c_str(), iLevelZone, PropertyDepths[iPropertyDepth], avgActualInterest ); - nlassert( iPropertyDepth != 0 ); - IPropertyDepths[p] = iPropertyDepth; - } - - // Compute sap load estimation - /*float sumSapLoad = 0.0f; - uint32 nbSapLoads = 0; - for ( uint32 rFaberElem=0; rFaberElem!=NbFaberElements; ++rFaberElem ) - { - if ( hasCraftPart( rFaberElem ) ) - { - if ( sapLoads[rFaberElem] != 0.0f ) - { - sumSapLoad += sapLoads[rFaberElem]; - ++nbSapLoads; - } - } - } - if ( nbSapLoads != 0 ) - { - float avgSapLoad = sumSapLoad / nbSapLoads; - if ( avgSapLoad < 0 ) - avgSapLoad = 0.0f; - uint32 iSapLoadEst = (uint32)(avgSapLoad * 3.0f / MaxCharacValues[SapLoad]); - if ( iSapLoadEst > 2 ) - iSapLoadEst = 3; // peak - //nldebug( "Sap load est: %u", iSapLoadEst ); - SapLoadLevel = iSapLoadEst; - }*/ - - // Compute color - TColor CommonColors [4] = { Beige, Green, Turquoise, Violet }; - TColor RareColors [2] = { Red, Blue }; - TColor PrimerootColors [2] = { White, Black }; - if ( famInfo.IsForMission ) - { - Color = Beige; - } - else if ( famInfo.ColorIndex == -1 ) - { - nlwarning( "No color provided for family %s", familyStr().c_str() ); - Color = InvalidColor; - } - else - { - uint colorIndex = (uint)famInfo.ColorIndex; - if ( IEcosystem == PrimeRoots ) - Color = PrimerootColors[colorIndex % 2]; - else if ( StatQuality >= Choice ) - Color = RareColors[colorIndex % 2]; - else - Color = CommonColors[colorIndex % 4]; - } - - return true; -} - - -/* - * - */ -void CGenRawMaterial::collectStats( TRMItem& item, CMainStat& mainStats ) -{ - // Name & title - item.push( DtName, SheetName ); - item.push( DtTitle, Titles[SheetName] ); - - // Properties - for ( uint32 p=0; p!=/*min( NbPropertySlots,*/ (uint32)RMProperties.size()/*)*/; ++p ) - { - if ( RMProperties[p] != UndefinedProperty ) - { - ++mainStats.NbRMHavingProperty[ILocation][IEcosystem][RMProperties[p]]; - item.push( DtProp, propertyStr( p ) ); - } - } - - // Family - item.push( DtRMFamily, familyStr() ); - - // Group - item.push( DtGroup, groups[Group] ); - - // Ecosystem - item.push( DtEcosystem, ecosystemStr() ); - - TFamInfo& famInfo = FamSet[familyStr()]; - - // LevelZone (for creatures) - item.push( DtLevelZone, famInfo.IsForMission ? - toString( "%c", 'A' + (char)ILevelZone ) : - "-" ); - - // StatQuality - item.push( DtStatQuality, string( StatQualityStr[StatQuality] ) ); - - // Craft stats - vector actualInterests( NbFaberElements, 0.0f ); - vector sapLoads( NbFaberElements, 0.0f ); - for ( uint p=0; p!=famInfo.CraftPartsByProp.size(); ++p ) - { - for ( uint iCompatibleCP=famInfo.getBeginCraftPartForProp(p); iCompatibleCP!=famInfo.getEndCraftPartForProp(p); ++iCompatibleCP ) - { - uint rFaberElem = famInfo.getCompatibleCraftPart( iCompatibleCP ); - CFaberCharacteristics *craftSlot = getCraftSlot( rFaberElem ); - nlassert( craftSlot ); - - TCiv civ = getCivSpec( IEcosystem, StatQuality ); ////getCivSpec( rFaberElem, FamSet[familyStr()] ); - CSString civS = CivNames[civ]; - - item.push( DtCraftSlotName, getShortFaberElemString( rFaberElem ) ); - item.push( DtCraftCivSpec, civS ); - /*item.push( DtCraftSlotEnergy, toString( "%02u", (uint)(craftSlot->ActualEnergy*100.0f) ), true ); - item.push( DtCraftSlotOriginality, toString( "%03u", (uint)(craftSlot->ActualOriginality*100.0f) ), true );*/ - - mainStats.updateCraftStatistics( rFaberElem, IEcosystem, IFamily, famInfo.Civs[p] ); - } - } - - item.push( DtColor, colors[Color] ); - item.push( DtAverageEnergy, toString( "%d", StatEnergyAvg ) ); - - // Rarity - //item.push( DtRarity, toString( "%2u", Rarity ) ); - - // Max Quality - item.push( DtMaxLevel, toString( "%u", MaxLevel ) ); - - // Protection - CFaberCharacteristics *itemPart = getCraftSlot( ITEM_PART_JEWEL_GEM ); - if ( itemPart ) - item.push( DtJewelProtectionType, PROTECTION_TYPE::toString( (PROTECTION_TYPE::TProtectionType)(uint)itemPart->Values[JewelProtection] ) ); - - // Customized properties - CRulesStr2Filter::const_iterator icp = CustomizedPropertiesSheetName.find( SheetName + "." + rmSheetType ); - if ( icp != CustomizedPropertiesSheetName.end() ) - { - CSString line; - for ( vs::const_iterator ip=(*icp).second.begin(); ip!=(*icp).second.end(); ++ip ) - { - if ( ip != (*icp).second.begin() ) - line += "; "; - CSString propName = *ip; - ++ip; - if ( ip == (*icp).second.end() ) - break; - CSString value = *ip; - line += propName + "=" + value; - } - item.push( DtCustomizedProperties, line ); - } - - if ( GraphFile ) - { - fprintf( GraphFile, "%s;%s%u;%u;%u;%u;\n", SheetName.c_str(), ecosystems[IEcosystem].c_str(), StatQuality, StatEnergyAvg, (uint)(getOriginalityAvg()*100.0f), (uint)/*(getMainCivSpec( famInfo ))*/getCivSpec( IEcosystem, StatQuality )*4+100 ); - } - - mainStats.updateMainStats( RMCraftCharacs.size() ); -} - - -/* - * - */ -void CGenRawMaterial::writeSheet( CForm *form ) -{ - // Write properties (obsolete) - /*if ( RMProperties.size() > NbPropertySlots ) - nlwarning( "More properties than property slots (%s)", familyStr().c_str() ); - for ( uint32 p=0; p!=min( NbPropertySlots, (uint32)RMProperties.size()); ++p ) - { - if ( RMProperties[p] != UndefinedProperty ) - { - form->getRootNode().setValueByName( propertyStr( p ).c_str(), toString( "mp.Material property %d", p+1 ).c_str() ); - } - }*/ - - // Write color - /*vu& famColors = familyColorsFilter[iFam]; - if ( famColors.empty() ) - nlwarning( "No matching color for family %s", families[iFam].c_str() ); - else - { - uint32 iiColor = getRandomValue( famColors.size() ); - form->getRootNode().setValueByName( colors[famColors[iiColor]].c_str(), "mp.MpColor" ); - }*/ - if ( Color != InvalidColor ) - form->getRootNode().setValueByName( colors[Color].c_str(), "mp.MpColor" ); - - // Write icon overlay (TODO) - /*CSString& iconTextOver = Icons[locFam.splitTo('.')]; - if ( ! iconTextOver.empty() ) - form->getRootNode().setValueByName( iconTextOver.c_str(), "3d.icon text over" );*/ - - /*CSString props; - for ( uint32 p=0; p!=iProperties.size(); ++ p ) - props += " " + properties[iProperties[p]]; - nldebug( "%s %s %s", locFam.c_str(), props.c_str(), (familyGroups[iFam]==~0) ? "-" : groups[familyGroups[iFam]].c_str() );*/ - - vector actualInterests( NbFaberElements, 0.0f ); - vector sapLoads( NbFaberElements, 0.0f ); - - // Write craft stats - list::const_iterator ics; - for ( ics=RMCraftCharacs.begin(); ics!=RMCraftCharacs.end(); ++ics ) - { - const CFaberCharacteristics& craftSlot = (*ics); - const uint32& rFaberElem = craftSlot.FaberElement; - - for ( uint r=0; r!=NbCharacs; ++r ) - { - switch ( r ) - { - case JewelProtection: // see below - break; - case CraftCivSpec: - { - CSString civS; - TCiv civ = getCivSpec( IEcosystem, StatQuality ); //getCivSpec( rFaberElem, FamSet[familyStr()] ); - if ( civ == AllCiv ) - civS = "common"; //"Common_Species"; - else - civS = CivNames[civ]; - form->getRootNode().setValueByName( civS.toLower().c_str(), (CraftParts[rFaberElem].Path + ".CraftCivSpec").c_str() ); - } - break; - default: - { - //if ( craftSlot.Values[r] != 0.0f ) - if ( CharacSlotFilter[r][rFaberElem] ) - form->getRootNode().setValueByName( (sint32)(craftSlot.Values[r]), (CraftParts[rFaberElem].Path + "." + string(sCharacs[r])).c_str() ); - } - } - } - - // Write CraftEstimatedQuality (formerly known as property depths, I still use old property vector) - /*for ( uint32 p=0; p!=IPropertyDepths.size(); ++p ) - { - CSString itemPartAsPropS = propertyStr( p ); - if ( itemPartAsPropS.empty() ) - continue; - uint itemPartAsProp = itemPartAsPropS[0] - 'A'; - if ( itemPartAsProp == rFaberElem ) - { - form->getRootNode().setValueByName( propertyDepthStr( p ).c_str(), (CraftParts[rFaberElem].Path + ".CraftEstimatedQuality").c_str() ); - break; - } - }*/ - } - - // Jewel protection - CFaberCharacteristics *itemPart = getCraftSlot( ITEM_PART_JEWEL_GEM ); - if ( itemPart ) - form->getRootNode().setValueByName( PROTECTION_TYPE::toString( (PROTECTION_TYPE::TProtectionType)(uint)itemPart->Values[JewelProtection] ).c_str(), (CraftParts[ITEM_PART_JEWEL_GEM].Path + "." + string(sCharacs[JewelProtection])).c_str() ); - - // Write sap load estimation - /*if ( SapLoadLevel != ~0 ) - form->getRootNode().setValueByName( (uint32)SapLoadLevel, "mp.Sap load est" );*/ - - // Write rarity - //form->getRootNode().setValueByName( (uint32)Rarity, "mp.Rarity" ); - - // Write max quality - form->getRootNode().setValueByName( (uint32)MaxLevel, "mp.MaxQuality" ); - - // Write energy - form->getRootNode().setValueByName( StatEnergyAvg, "mp.StatEnergy" ); - - // Write customized properties - setCustomizedPropertyValues( form->getRootNode(), SheetName + "." + rmSheetType ); -} - - -/* - * - */ -/*string getPossibleAdjectivesFromSheetNameForDeposit( const CSString& sheetName ) -{ - uint iFamily = getIndexFromString( sheetName.substr( RM_INDEX_FAMILY_CODE, NB_FAMILY_CODE_CHARS ), familyCodes ); - - string locFam = packLocFamily( depositTypeLetters[iLoc], IFamily ); - //nlinfo( "%s", locFam.c_str() ); - RAdj = LocFamilyToAdjectives[locFam].find( adj.toUpper().c_str() ); -}*/ - - -/* - * - */ -void CGenRawMaterial::loadSheet( CForm *form, const std::string& sheetName, bool full ) -{ - SheetName = sheetName; - string value; - - if ( full ) - { - // Location - uint32 iLoc; - if ( SheetName[0] == 'c' ) - iLoc = InCreatures; - else - { - /*switch ( SheetName[2] ) - { - case 'u': iLoc = Under; break; - case 'o': iLoc = Over; break; - case 'f': iLoc = Flora; break; - default: nlstop; - }*/ - iLoc = InDeposits; - } - ILocation = iLoc; - - // Ecosystem - form->getRootNode().getValueByName( value, "mp.Ecosystem" ); - if ( ! value.empty() ) - IEcosystem = (TEcosystem)getIndexFromString( SheetName.substr( RM_INDEX_ECOSYSTEM_CODE, NB_ECOSYSTEM_CODE_CHARS ), ecosystemCodes ); // not using value because != label - - // Family - form->getRootNode().getValueByName( value, "mp.Family" ); - if ( ! value.empty() ) - IFamily = getIndexFromString( SheetName.substr( RM_INDEX_FAMILY_CODE, NB_FAMILY_CODE_CHARS ), familyCodes ); // not using value because != label - - fillPropertiesFromFamily(); - - // StatQuality - setStatQuality( SheetName[RM_INDEX_LEVELZONE_CODE] ); - } - - // Color - uint32 v; - form->getRootNode().getValueByName( v, "mp.MpColor" ); - Color = (TColor)v; - - // Craft stats - uint32 nbFaberElemsFilled = 0; - for ( uint32 rFaberElem=0; rFaberElem!=NbFaberElements; ++rFaberElem ) - { - sint32 val; - form->getRootNode().getValueByName( val, (CraftParts[rFaberElem].Path + ".Durability").c_str() ); - if ( val != 0 ) - { - CFaberCharacteristics craftSlot; - craftSlot.initFaberElement( rFaberElem ); - - for ( uint r=0; r!=NbCharacs; ++r ) - { - switch ( r ) - { - case JewelProtection: - { - if ( CharacSlotFilter[r][rFaberElem] ) - { - string proTypeS; - form->getRootNode().getValueByName( proTypeS, (CraftParts[rFaberElem].Path + "." + string(sCharacs[r])).c_str() ); - craftSlot.Values[r] = (float)(uint)PROTECTION_TYPE::fromString( proTypeS ); - } - else - craftSlot.Values[r] = 0.0f; - } - break; - case CraftCivSpec: - { - if ( CharacSlotFilter[r][rFaberElem] ) - { - string civS; - form->getRootNode().getValueByName( civS, (CraftParts[rFaberElem].Path + "." + string(sCharacs[r])).c_str() ); - TCiv civ = AllCiv; - if ( civS != "Common_Species" ) - for ( uint c=0; c!=NbCiv; ++c ) - if ( string(CivNames[c]) == civS ) - civ = (TCiv)c; - craftSlot.Values[r] = (float)(uint)civ; - } - } - break; - default: - { - form->getRootNode().getValueByName( val, (CraftParts[rFaberElem].Path + "." + string(sCharacs[r])).c_str() ); - craftSlot.Values[r] = (float)val; - } - } - } - - craftSlot.calcQualitativeValues(); - - RMCraftCharacs.push_back( craftSlot ); - - //nlinfo( "%s %s %s %s", item.Fields[DtName][0].c_str(), faberElems[rFaberElem].c_str(), families[iFam].c_str(), familyGroups[iFam]==~0?"":groups[familyGroups[iFam]].c_str() ); - } - else - { - if ( CheckDurability ) - { - // Check if Durability==0 is not a mistake - for ( uint r=0; r!=NbCharacs; ++r ) - { - if ( r != JewelProtection && r!=CraftCivSpec ) - { - form->getRootNode().getValueByName( val, (CraftParts[rFaberElem].Path + "." + string(sCharacs[r])).c_str() ); - if ( val != 0 ) - { - nlwarning( "%s has a null durability for item part %c", sheetName.c_str(), (char)('A' + (char)rFaberElem) ); - break; - } - } - } - } - } - } - - /*// These properties are currently useless when reading (not used for doc) - // Write property depths - uint p = 0; - bool res = true; - while ( res ) - { - string valueStr; - res = form->getRootNode().getValueByName( valueStr, toString( "mp.Prop %u depth", p+1 ).c_str() ); - if ( res ) - IPropertyDepths.push_back( propertyDepthFromString( valueStr ) ); - ++p; - } - - // Sap load est - form->getRootNode().getValueByName( SapLoadLevel, "mp.Sap load est" ); - */ - - // Rarity - //form->getRootNode().getValueByName( Rarity, "mp.Rarity" ); - - // Max Quality - form->getRootNode().getValueByName( MaxLevel, "mp.MaxQuality" ); - - // Energy - form->getRootNode().getValueByName( StatEnergyAvg, "mp.StatEnergy" ); - - ++nbSheetsProcessed; -} - - -/* - * - */ -void writeRMSheetToDisk( CForm *form, const string& sheetName ) -{ - if ( ! EraseOldCreatureAssignments ) - { - flushSheetToDisk( rawMaterialPath + dirbase + sheetName + "." + rmSheetType, form ); - ++nbSheetsProcessed; - if ( inputSheetPathContent.find( sheetName ) == inputSheetPathContent.end() ) - ++nbNewSheetsGenerated; - } - if ( GetSelectionUntilLevel != ~0 ) - { - if ( (sheetName[5] - 'a') <= (sint)GetSelectionUntilLevel ) - InfoLog->displayRawNL( "SELECTION: %s", sheetName.c_str() ); - } -} - - -/* - * Write sheet, write stat - */ -void selectRawMaterial( CForm *form, CForm *ecoParentForm, CForm *famParentForm, CGenRawMaterial *rm ) -{ - // Clear sheet (otherwise the previous values would remain) - clearSheet( form, &form->getRootNode() ); - - // Link to the parent sheets (the form arguments are always the last parent forms but there aren't used by the func anyway) - form->insertParent( 0, getEcoParentName( rm->IEcosystem ).c_str(), ecoParentForm ); - form->insertParent( 1, getFamParentName( rm->IFamily ).c_str(), famParentForm ); - - // Write stats - TRMItem item; - rm->collectStats( item, MainStat ); - SortableData.addItem( item ); - - // Write to disk - rm->writeSheet( form ); - writeRMSheetToDisk( form, rm->SheetName ); -} - - -/* - * - */ -/*string findSubstitutionForDepositRM( const string& srcName, char adjCode ) -{ - //nldebug( "SRC: %s", srcName.c_str() ); - string substitution = srcName; - CRMData::CLookup::const_iterator ilk; - char decl; - for ( decl='a'; decl!='h'; ++decl ) // up to 7 declinaisons - { - substitution[3] = decl; - substitution[2] = srcName[2]; - substitution[8] = adjCode; - //nldebug( "TRYING %s", substitution.c_str() ); - ilk = SortableData.lookup( DtName ).find( substitution ); - if ( ilk != SortableData.lookup( DtName ).end() ) - return substitution; - - uint iLoc; - for ( iLoc=0; iLoc!=NB_DEPOSITS; ++iLoc ) - { - char locChar = tolower( depositTypeLetters[iLoc][0] ); - if ( locChar == srcName[2] ) - continue; - - substitution[2] = locChar; - //nldebug( "TRYING %s", substitution.c_str() ); - ilk = SortableData.lookup( DtName ).find( substitution ); - if ( ilk != SortableData.lookup( DtName ).end() ) - return substitution; - } - } - return string(); -}*/ - - -/* - * Result has at least one character - */ -inline CSString getCreatureEcosystemCode( uint itEcosystem ) -{ - switch ( itEcosystem ) - { - case Goo: return "g"; - case Invasion: return "i"; - case Raid: return "r"; - case Event: return "e"; - case N: return "n"; - case S: return "s"; - case T: return "t"; - case U: return "u"; - case V: return "v"; - case W: return "w"; - case X: return "x"; - case Y: return "y"; - case Z: return "z"; - default: return ecosystemCodes[itEcosystem]; - } -} - - -/* - * - */ -inline CSString getCreatureLZCode( const CSString& creaModel, uint itEcosystem, uint iZone ) -{ - nlassert( iZone < 10 ); - return string("c") + creaModel.toLower() + getCreatureEcosystemCode( itEcosystem ) + toString( "%c", (char)('a' + (char)iZone) ); -} - - -/* - * - */ -void loadConfigFile() -{ - // Load config file - try - { - CConfigFile configFile; - configFile.load( "raw_material_generation.cfg" ); - CConfigFile::CVar *var = configFile.getVarPtr( "RawMaterialPath" ); - if ( var ) rawMaterialPath = var->asString(); - var = configFile.getVarPtr( "CreatureSubPath" ); - if ( var ) - { - creaturePath = var->asString(); - if ( creaturePath[creaturePath.size()-1] != '/' ) - creaturePath += "/"; - } - var = configFile.getVarPtr( "CreatureAssignmentPath" ); - if ( var ) - { - creatureAssignmentPath = var->asString(); - if ( creatureAssignmentPath[creatureAssignmentPath.size()-1] != '/' ) - creatureAssignmentPath += "/"; - } - var = configFile.getVarPtr( "DepositSubPath" ); - if ( var ) - { - depositPath = var->asString(); - if ( depositPath[depositPath.size()-1] != '/' ) - depositPath += "/"; - } - - loadConfigFlag( configFile, "WriteSheetsToDisk", WriteSheetsToDisk ); - loadConfigFlag( configFile, "GenOnlyNewRawMaterials", GenOnlyNewRawMaterials ); - loadConfigFlag( configFile, "SkipRawMaterialsForCreatures", SkipRawMaterialsForCreatures ); - loadConfigFlag( configFile, "AssignRawMaterialsHarvestToCreatureSheets", AssignRawMaterialsHarvestToCreatureSheets ); - loadConfigFlag( configFile, "AssignOnlyToUnassignedCreatures", AssignOnlyToUnassignedCreatures ); - loadConfigFlag( configFile, "SkipRawMaterialsForDeposits", SkipRawMaterialsForDeposits ); - loadConfigFlag( configFile, "GenOnlyMissionRawMaterials", GenOnlyMissionRawMaterials ); - loadConfigFlag( configFile, "AssignRawMaterialsHarvestToDepositSheets", AssignRawMaterialsHarvestToDepositSheets ); - loadConfigFlag( configFile, "BrowseOtherDeposits", BrowseOtherDeposits ); - loadConfigFlag( configFile, "FixDeposits", FixDeposits ); - loadConfigFlag( configFile, "EraseOldCreatureAssignments", EraseOldCreatureAssignments ); - loadConfigFlag( configFile, "TestExistingAssigments", TestExistingAssigments ); - loadConfigFlag( configFile, "OutputNameList", OutputNameList ); - loadConfigFlag( configFile, "DisplayFamAndProp", DisplayFamAndProp ); - loadConfigFlag( configFile, "ProduceDoc", ProduceDoc ); - loadConfigFlag( configFile, "CheckDurability", CheckDurability ); - loadConfigFlag( configFile, "GenerateDepositSystemMpFiles", GenerateDepositSystemMpFiles ); - - var = configFile.getVarPtr( "ExistingRMAction" ); - if ( var ) ExistingRMAction = (TExistingRMAction)var->asInt(); - - var = configFile.getVarPtr( "GetSelectionUntilLevel" ); - if ( var ) GetSelectionUntilLevel = (uint32)var->asInt(); - - var = configFile.getVarPtr( "SortByOriginality" ); - if ( var ) SortByOriginality = ((uint32)var->asInt() == 1); - - var = configFile.getVarPtr( "MaxNbRMByFamilyEZ" ); - if ( var ) MaxNbRMByFamilyEZ = (uint32)var->asInt(); - - var = configFile.getVarPtr( "MaxNbRMByCraftSlotE" ); - if ( var ) MaxNbRMByCraftSlotE = (uint32)var->asInt(); - - //var = configFile.getVarPtr( "OriginalityMinThreshold" ); - //if ( var ) OriginalityMinThreshold = (uint32)var->asInt(); - - /*var = configFile.getVarPtr( "NbFaberCombinations" ); - if ( var ) NbFaberCombinations = var->asInt();*/ - - var = configFile.getVarPtr( "TranslationPath" ); - if ( var ) TranslationPath = var->asString(); - - var = configFile.getVarPtr( "SystemMPPath" ); - if ( var ) SystemMPPath = var->asString(); - - var = configFile.getVarPtr( "CustomizedProperties" ); - if ( var ) - { - for ( sint i=0; i!= var->size(); ++i ) - { - CSString sheetFilename = var->asString( i ); - ++i; - if ( i < var->size() ) - { - CSString propName = var->asString( i ); - ++i; - if ( i < var->size() ) - { - CSString value = var->asString( i ); - CustomizedPropertiesSheetName[sheetFilename].push_back( propName ); - CustomizedPropertiesSheetName[sheetFilename].push_back( value ); - } - } - } - } - } - catch ( EConfigFile& e ) - { - nlwarning( "%s - Press a key", e.what() ); - getch(); - } -} - - -/* - * - */ -void displayFamNames() -{ - ListLog.displayRawNL( "Family names for en.uxt:" ); - for ( uint i=0; i!=families.size(); ++i ) - { - if ( ! families[i].empty() ) - { - uint num = atoi( familyCodes[i].c_str() ); - ListLog.displayRawNL( "mpfam%u\t\t\t[%s]", num, families[i].c_str() ); - } - } - ListLog.displayRawNL( "Groups names for en.uxt:" ); - for ( uint i=0; i!=groups.size(); ++i ) - { - if ( ! groups[i].empty() ) - ListLog.displayRawNL( "mpgroup%u\t\t\t[%s]", i, groups[i].c_str() ); - } - ListLog.displayRawNL( "Groups by family:" ); - for ( uint i=0; i!=families.size(); ++i ) - { - if ( ! families[i].empty() ) - { - TFamInfo& famInfo = FamSet[families[i]]; - ListLog.displayRawNL( "%u\t%s", i, (famInfo.Group!=~0) ? groups[famInfo.Group].c_str() : "" ); - } - } - ListLog.displayRawNL( "Families by group:" ); - for ( uint i=0; i!=groups.size(); ++i ) - { - if ( ! groups[i].empty() ) - { - ListLog.displayRawNL( "Group:\t\t\t%s", groups[i].c_str() ); - for ( uint j=0; j!=families.size(); ++j ) - { - if ( FamSet[families[j]].Group == i ) - ListLog.displayRawNL( "Group:\t%u\t%u\t\t%s", i, j, families[j].c_str() ); - } - } - } - ListLog.displayRawNL( "Group icons for _ic_groups.forage_source" ); - ListLog.displayRawNL( " " ); - for ( uint i=0; i!=groups.size(); ++i ) - { - //if ( ! groups[i].empty() ) - ListLog.displayRawNL( " ", Icons[groups[i]].Icon.c_str() ); - } - ListLog.displayRawNL( " "); - ListLog.displayRawNL( "Family icons for _ic_families.forage_source" ); - ListLog.displayRawNL( " " ); - for ( uint i=0; i!=families.size(); ++i ) - { - //if ( ! families[i].empty() ) - ListLog.displayRawNL( " ", Icons[families[i]].Icon.c_str() ); - } - ListLog.displayRawNL( " "); -} - - -/* - * For deposit families only - */ -void generateSytemMpFiles() -{ - if ( ! GenerateDepositSystemMpFiles ) - return; - - string dir = SystemMPPath; - nlinfo( "Processing 'system mp' files for WorldEditor in %s...", dir.c_str() ); - - // Build the right list of files - vector systemMpFilenames; - systemMpFilenames.resize( families.size() ); - for ( uint i=0; i!=families.size(); ++i ) - { - if ( ! families[i].empty() ) - { - if ( FamSet[families[i]].IsInDeposits ) - systemMpFilenames[i] = conventionalDirectory( families[i] ) + toString( "_%u.mp", i ); - } - } - - // List and delete obsolete files - vector currentFiles; - CPath::getPathContent( dir, false, false, true, currentFiles ); - for ( uint i=0; i!=currentFiles.size(); ++i ) - { - string currentFile = CFile::getFilename( currentFiles[i] ); - if ( currentFile.find( ".mp" ) != string::npos ) - { - if ( find( systemMpFilenames.begin(), systemMpFilenames.end(), currentFile ) == systemMpFilenames.end() ) - { - nlinfo( "Deleting obsolete %s (PLEASE COMMIT)", currentFile.c_str() ); - if ( WriteSheetsToDisk ) - CFile::deleteFile( currentFiles[i] ); - } - } - } - - // Create new files - for ( uint i=0; i!=families.size(); ++i ) - { - if ( (! families[i].empty()) && (! systemMpFilenames[i].empty()) ) - { - // Check if file present ; if not, create it - if ( ! CFile::fileExists( dir + systemMpFilenames[i] ) ) - { - nlinfo( "Creating %s (PLEASE COMMIT)", systemMpFilenames[i].c_str() ); - if ( WriteSheetsToDisk ) - { - COFile f; - f.open( dir + systemMpFilenames[i], false, true ); - f.close(); - } - } - } - } -} - - -/* - * generateRawMaterials - */ -void generateRawMaterials() -{ - // Load config file - loadConfigFile(); - - // Load lists from DFNs - loadSheetPath(); - UFormLoader *formLoader = UFormLoader::createLoader (); - loadDFNs( formLoader ); - - // TEMP: remove all raw materials for creatures! - /*string dp = "r:/code/ryzom/data_leveldesign/leveldesign/game_element/sitem/raw_material/"; - string ecos [5] = { "desert", "forest", "jungle", "lacustre", "prime_roots" }; - vector thefiles [5]; - for ( uint i=0; i!=5; ++i ) - { - CPath::getPathContent( dp + ecos[i], false, false, true, thefiles[i] ); - nlinfo( "%u files in %s", thefiles[i].size(), (dp + ecos[i]).c_str() ); - } - map::iterator it; - for ( it=inputSheetPathContent.begin(); it!=inputSheetPathContent.end(); ++it ) - { - const string& s1 = (*it).first, s2 = (*it).second; - string::size_type p; - if ( (p = s2.find( "raw_material/_parent/_mc" )) != string::npos ) - { - string cc = s1.substr( 3, 2 ); - for ( uint i=0; i!=5; ++i ) - { - for ( vector::iterator its=thefiles[i].begin(); its!=thefiles[i].end(); ++its ) - { - string& fl = (*its); - string::size_type q; - if ( (q = fl.find( string( "c") + cc )) != string::npos ) - { - if ( (fl[q-1] >= '0') && (fl[q-1] <= '9') ) - { - nlinfo( "Deleting %s", fl.c_str() ); - CFile::deleteFile( fl ); - } - } - } - } - } - } - - return;*/ - - // Load families from CSV file - loadFamAndProp( "rm_fam_prop.csv", DisplayFamAndProp ); - if ( TFamInfo::UseGenerateOnly != 0 ) - nlinfo( "Requested to generate only %u marked RM families", TFamInfo::UseGenerateOnly ); - else - nlinfo( "Requested to generate all RM families" ); - - // Load template sheet for final and parent forms - NLMISC::CSmartPtr form = loadTemplateForm( formLoader, rmSheetType ); - NLMISC::CSmartPtr ecoParentForm = loadTemplateForm( formLoader, rmSheetType ); - NLMISC::CSmartPtr famParentForm = loadTemplateForm( formLoader, rmSheetType ); - - for ( uint r=0; r!=NbCharacs; ++r ) - CharacSlotFilter[r].resize( NbFaberElements ); - - // Load other CSV files - loadCSVFile( "rm_item_parts.csv", deliverItemPartParams ); - loadCSVFile( "creature_models.csv", deliverCreatureModels ); - //nlinfo( "Loaded %u creature categories", SkgroupToModels.size() ); - dispatchFamiliesToLocations(); - nlinfo( "%u creatures models selected", RMFamilyIndicesByCreatureModel.size() ); - nlinfo( "%u creature models used", checkSkeletons() ); - nlinfo( "%u icon lines loaded", Icons.size() ); - - // Summary - nlinfo( "%u families, %u ecosystems, %u properties, %u craft parts, %u colors", families.size(), ecosystems.size(), properties.size(), CraftParts.CraftParts.size(), colors.size() ); - - // Generate names(with nomenclature) - ListLog.addDisplayer( &ListDisplayer ); - familyCodes.resize( families.size() ); - ecosystemCodes.resize( ecosystems.size() ); - for_each( familyCodes.begin(), familyCodes.end(), normalizeFamilyCode ); - displayFamNames(); - generateSytemMpFiles(); - //buildNomenclatureCodes( "New families:", families, familyCodes, NB_FAMILY_CODE_CHARS ); // useless currently - buildNomenclatureCodes( NULL, ecosystems, ecosystemCodes, NB_ECOSYSTEM_CODE_CHARS ); - - // Load Unicode titles (can share the same hash map because codes are distinct) - loadTitles( "item", "work", "wk", Titles ); - loadTitles( "creature", "translated", "en", Titles ); - - createDirectoryStructure(); - MainStat.init(); - FILE *nameOutputFile; - if ( OutputNameList ) - nameOutputFile = fopen( "rm_names_output.csv", "wt" ); - GraphFile = fopen( "rm_output_graph.csv", "wt" ); - fprintf( GraphFile, "Graph type: Line with markers displayed at each data value, columns B to E. For deposits, sort by column B\n" ); - fprintf( GraphFile, "Ecosystem specialization: 100=Desert, 104=Forest, 108=Lake, 112=Jungle, 116=All\n" ); - fprintf( GraphFile, "RM code;Zone;Energy;Originality;Eco. spec.;\n\n" ); - SortableData.init( ProduceDoc ); - - // Generate random values - //RawMaterialRepository.resize( ecosystems.size(), families.size() ); - RandomGenerator.srand( (unsigned)time( NULL ) ); - - /* - * New raw materials - */ - if ( GenOnlyNewRawMaterials || AssignRawMaterialsHarvestToCreatureSheets || AssignRawMaterialsHarvestToDepositSheets || FixDeposits ) - { - // Parents - if ( ExistingRMAction == ModifyRM ) - { - for ( uint32 iEcosystem=0; iEcosystem!=ecosystems.size(); ++iEcosystem ) - { - // Parent item for ecosystem - clearSheet( ecoParentForm, &form->getRootNode() ); - writeParentSheetEco( ecoParentForm, iEcosystem ); - } - - for ( uint32 iFamily=0; iFamily!=families.size(); ++iFamily ) - { - if ( TFamInfo::mustGenerateFamily( iFamily ) ) - { - // Parent item for family - clearSheet( famParentForm, &form->getRootNode() ); - writeParentSheetFam( famParentForm, iFamily ); - } - } - } - - uint32 nbAssignedMaterials = 0, nbCreatureSheetsSkipped = 0, nbErasedCreatureAssignments = 0; - uint32 maxLastAssignedRMSlot = 0; - NLMISC::CSmartPtr creaParentForm; - NLMISC::CSmartPtr creaForm; - set creatureSheets; - - if ( SkipRawMaterialsForCreatures ) - goto processRawMaterialsForDeposits; - - // - // Iterate on creatures raw materials - // - for ( CRulesStrFilter::iterator icr=RMFamilyIndicesByCreatureModel.begin(); icr!=RMFamilyIndicesByCreatureModel.end(); ++icr ) - { - // HD - const CSString& creaModel = (*icr).first; - vu& familiesForCreatureModel = (*icr).second; - - // Parent item for creature (one per model) - CSString creaCMainModelCode = string("c") + creaModel.toLower(); // CHD - static float progress = 0.0f; - if ( familiesForCreatureModel.empty() ) - { - nlinfo( "No RM has been defined for non-goo %s (%s)", creaCMainModelCode.c_str(), CreatureModels[creaModel].Name.c_str() ); - CreatureMainModelsWithoutRM.insert( creaCMainModelCode ); - } - else - nlinfo( "%u RM for each variant of non-goo %s (%.1f%%)", familiesForCreatureModel.size(), creaModel.c_str(), 100.0f*progress/(float)RMFamilyIndicesByCreatureModel.size() ); - ++progress; - - // Write parent item sheet - if ( ExistingRMAction == ModifyRM ) - { - creaParentForm = loadTemplateForm( formLoader, rmSheetType ); - clearSheet( creaParentForm, &form->getRootNode() ); - writeParentSheetCreature( creaParentForm, creaModel ); - } - - // Iterate on ecosystems - for ( uint itEcosystemOfCreature=CommonEcosystem+1; itEcosystemOfCreature!=NbEcosystemsPlusExtensions; ++itEcosystemOfCreature ) - { - // CHDF - - for ( uint iZone=0; iZone!=10; ++iZone ) - { - uint iLevelZone = (iZone<=1) ? 0 : iZone-1; - - // CHDFA-CHDFJ - CSString creaLZCode = getCreatureLZCode( creaModel, itEcosystemOfCreature, iZone ); - - for ( uint32 iLocalLevel=1; iLocalLevel!=MAX_NB_LOCAL_LEVELS+1; ++iLocalLevel ) // warning: base 1 - { - // CHDFA1-CHDFA9 (only if creature sheet exists on disk) - TStatQuality statQuality = CreatureLocalLevelToStatQuality[iLocalLevel-1]; - - CSString creaSheetName = creaLZCode + toString("%u", iLocalLevel); - map::const_iterator ipc = inputSheetPathContent.find( creaSheetName ); - if ( ipc == inputSheetPathContent.end() ) - continue; - - if ( ((itEcosystemOfCreature != Goo) && familiesForCreatureModel.empty()) || - (statQuality == InvalidStatQuality) ) // mission creatures (*6.creature) have invalid StatQuality => no RMs (bugged: no parent created) - { - // Generate empty parent creature sheets if not existing yet - const CSString& creaPathAndFilename = creatureAssignmentPath + string("_") + creaSheetName + "_mp." + crSheetType; - map::const_iterator ipcp = inputSheetPathContent.find( creaSheetName + "_mp" /*+"." + crSheetType*/ ); - if ( ipc == inputSheetPathContent.end() ) - { - UForm *creaForm = formLoader->loadForm( (string("_empty.") + crSheetType).c_str() ); - flushSheetToDisk( creaPathAndFilename, creaForm ); - } - } - else - { - // Get the list of RM families for the current processed creature - vu familiesForThisCreature; - uint nbInvasionFamilies = 0; - switch ( itEcosystemOfCreature ) - { - case Goo: - familiesForThisCreature = GooCreatureFamilyIndices; - break; - case Invasion: - case Raid: - case Event: - case N: - case S: - case T: - case U: - case V: - case W: - case X: - case Y: - case Z: - { - // Special RMs for all invasion/raid creatures - vu& familiesForAllIRCreatures = InvasionRaidCreatureFamilyIndices['*']; - familiesForThisCreature.insert( familiesForThisCreature.end(), familiesForAllIRCreatures.begin(), familiesForAllIRCreatures.end() ); - nbInvasionFamilies += familiesForAllIRCreatures.size(); - - // Special RMs for this type of invasion/raid creature - char cd [2]; - cd[0] = creaLZCode[1]; - cd[1] = '\0'; - ::strlwr( cd ); - vu& familiesForThisTypeOfIRCreature = InvasionRaidCreatureFamilyIndices[cd[0]]; - familiesForThisCreature.insert( familiesForThisCreature.end(), familiesForThisTypeOfIRCreature.begin(), familiesForThisTypeOfIRCreature.end() ); - nbInvasionFamilies += familiesForThisTypeOfIRCreature.size(); - - // Normal craft RMs if sufficient level or event - if ( (iLocalLevel >= 5) || - ((itEcosystemOfCreature >= Event) && (itEcosystemOfCreature <= Z)) ) - { - familiesForThisCreature.insert( familiesForThisCreature.end(), familiesForCreatureModel.begin(), familiesForCreatureModel.end() ); - } - break; - } - default: - familiesForThisCreature = familiesForCreatureModel; - } - - // Iterate on corresponding families - for ( vu::iterator ifc=familiesForThisCreature.begin(); ifc!=familiesForThisCreature.end(); ++ifc ) - { - uint32 iFam = (*ifc); - if ( ! TFamInfo::mustGenerateFamily( iFam ) ) - continue; - - //nldebug( "%s - %u adj: %s", families[iFam].c_str(), adjsForFamily.size(), adjsForFamily.c_str() ); - // For creature, the ecosystems are already limited by which creature sheets exist - - bool isMissionRawMaterial = FamSet[families[iFam]].IsForMission; - if ( GenOnlyMissionRawMaterials && (! isMissionRawMaterial) ) - continue; - - bool isInvasionFamily = ((uint)(ifc-familiesForThisCreature.begin()) < nbInvasionFamilies); - CSString rmCodeMid; - uint iEcosystem = ~0; - switch ( itEcosystemOfCreature ) - { - case Goo: - rmCodeMid = toString( "cxxc%c", (char)('a' + (char)iZone) ); - iEcosystem = CommonEcosystem; - break; - case Invasion: - case Raid: - case Event: - case N: - case S: - case T: - case U: - case V: - case W: - case X: - case Y: - case Z: - if ( isInvasionFamily || // the special RMs for invasion creature (possibly with several variants) - ((iLocalLevel <= 4) && ((itEcosystemOfCreature == Invasion) || (itEcosystemOfCreature == Raid))) ) // invasion/raid creatures have normal RMs only for bosses (all event creatures have normal RMs) - { - // Special invasion RM - rmCodeMid = toString( "ixxcc" ); - iEcosystem = CommonEcosystem; - } - else - { - // No mission RM for named/bosses/mini-bosses - if ( isMissionRawMaterial ) - continue; - - // Ecosystem is always Common, because the ecosystem of the creature is Invasion or Raid - iEcosystem = CommonEcosystem; - CSString creaLZCodeCommon = getCreatureLZCode( creaModel, iEcosystem, iZone ); - rmCodeMid = creaLZCodeCommon.substr( 0, creaLZCode.size() - 1 ) + toString( "%c", (char)((char)'a'+(char)statQuality) ); - } - break; - default: - if ( isMissionRawMaterial ) - { - // No mission RM for named/bosses/mini-bosses - if ( iLocalLevel > 4 ) - continue; - - // Ecosystem is always specialized - iEcosystem = itEcosystemOfCreature; - - // Mission RMs range from quality a (plain, in newbieland only) to f (magnificient) - rmCodeMid = creaLZCode; - } - else - { - // Ecosystem-specialized from Choice quality - if ( (statQuality <= Fine) ) - iEcosystem = CommonEcosystem; - else - iEcosystem = itEcosystemOfCreature; - - // Now: for craft RMs, statquality is bound on local level instead of level zone - CSString creaLZCodeCommon = getCreatureLZCode( creaModel, iEcosystem, iZone ); - rmCodeMid = creaLZCodeCommon.substr( 0, creaLZCode.size() - 1 ) + toString( "%c", (char)((char)'a'+(char)statQuality) ); - } - } - dirbase = conventionalDirectory( ecosystems[iEcosystem] ) + "/"; - - // Iterate on variants (now: only one variant) - uint32 nbVariants = 1; - if ( (itEcosystemOfCreature == Invasion) || (itEcosystemOfCreature == Raid) ) - { - if ( (iLocalLevel == 6) || (iLocalLevel == 8) ) - nbVariants = 0; - else if ( iLocalLevel <= 4 ) - nbVariants = 1; - // for 5 & 7, two variants only for the boss kitin invasion RM (trophy) - else if ( isInvasionFamily && (creaLZCode[1] == 'k') ) - nbVariants = 2; - } - for ( uint32 iVariant=1; iVariant<=nbVariants; ++iVariant ) - { - CSString sheetName = CSString( "m" ) - + familyCodes[iFam] - + rmCodeMid - + toString( "%02u", iVariant ); - - if ( GenOnlyNewRawMaterials ) - { - map::const_iterator iprm = inputSheetPathContent.find( sheetName ); - if ( iprm != inputSheetPathContent.end() ) - continue; - } - - if ( (! IsRMSheetGenerated[sheetName].Done) ) - { - IsRMSheetGenerated[sheetName].Done = true; - - //DebugLog->displayRawNL( "%s %s", sheetName.c_str(), getRMName( sheetName ).c_str() ); - if ( OutputNameList ) - { - CSString fullName; - if ( isInvasionFamily && (creaLZCode[1] == 'k') ) - { - switch ( iVariant ) - { - case 1: fullName = "Fragment of Kitin Claw;a;the;Fragments of Kitin Claw;;the;;"; break; - case 2: fullName = "Kitin Trophy;a;the;Kitin Trophies;;the;;"; break; - default:; - } - } - else - { - fullName = getRMShortName( sheetName, statQuality, isMissionRawMaterial ); - } - fprintf( nameOutputFile, "%s;%s\n", sheetName.c_str(), fullName.c_str() ); - } - - CGenRawMaterial rawMaterial( sheetName ); - - rawMaterial.ILocation = InCreatures; - rawMaterial.IFamily = iFam; - rawMaterial.Group = FamSet[families[iFam]].Group; - rawMaterial.IEcosystem = (TEcosystem)iEcosystem; - rawMaterial.StatQuality = statQuality; - if ( isMissionRawMaterial ) - rawMaterial.ILevelZone = iZone; - else - rawMaterial.ILevelZone = iLevelZone; - rawMaterial.fillPropertiesFromFamily(); - - if ( ExistingRMAction == ModifyRM ) - { - // Clear sheet (otherwise the previous values would remain) - clearSheet( form, &form->getRootNode() ); - - // Link to the parent sheets (the form arguments are always the last parent forms but there aren't used by the func anyway) - form->insertParent( 0, getEcoParentName( iEcosystem ).c_str(), ecoParentForm ); - form->insertParent( 1, getFamParentName( iFam ).c_str(), famParentForm ); - if ( ! ((itEcosystemOfCreature == Goo) || - (isInvasionFamily)) ) - form->insertParent( 2, getCreaParentName( creaCMainModelCode ).c_str(), creaParentForm ); - - rawMaterial.MaxLevel = 250; - if ( ! rawMaterial.computeCraftCharacs( iVariant, sheetName ) ) - continue; - - // Write to disk - rawMaterial.writeSheet( form ); - writeRMSheetToDisk( form, sheetName ); - } - else - { - form = (CForm*)formLoader->loadForm( (rawMaterialPath + dirbase + sheetName + "." + rmSheetType).c_str() ); - if ( ! form ) - { - nlwarning( "Can't load %s", (rawMaterialPath + dirbase + sheetName + "." + rmSheetType).c_str() ); - continue; - } - - rawMaterial.loadSheet( form, sheetName, false ); - } - - TRMItem item; - rawMaterial.collectStats( item, MainStat ); - SortableData.addItem( item ); - //Repository.push_back( rawMaterial ); - } - - // Assignment to existing creature sheets (TODO: for Common ecosystem, search Goo creature as well) - if ( AssignRawMaterialsHarvestToCreatureSheets ) // TEMP - { - // For RM of Common ecosystem, add creatures from Goo pseudo-ecosystem - /*CSString creaModel2 = creaModel; - if ( iEcosystem == CommonEcosystem ) - { - creaModel2[3] = 'g'; // replace CommonEcosystem by Goo for creatures - }*/ - - // We don't write into the real creature sheet, but we want it's _*_mp.creature parent sheet - const CSString& creaPathAndFilename = creatureAssignmentPath + string("_") + creaSheetName + "_mp." + crSheetType; - - // Find free and used slots (when not overwriting) - WarningLog->addNegativeFilter( "Can't open" ); // because loadForm() will emit a warning if not existing yet (but passing the filter is very slow) :( - creaForm = formLoader->loadForm( creaPathAndFilename.c_str() ); - WarningLog->removeFilter( "Can't open" ); - if ( ! creaForm ) - creaForm = formLoader->loadForm( (string("_empty.") + crSheetType).c_str() ); - if ( creaForm ) - { - CSString rmSheetFilename = sheetName + "." + rmSheetType; - bool alreadyAssigned = false; - uint32 firstFreeRMSlot = 0, lastAssignedRMSlot = 0; - for ( uint32 rMP=1; rMP<=NB_RAW_MATERIAL_FAMILIES_PER_CREATURE; ++rMP ) - { - string value; - creaForm->getRootNode().getValueByName( value, toString( "Harvest.MP%u.AssociatedItem", rMP ).c_str() ); - - if ( (value.size() == SIZE_RAW_MATERIAL_SHEET_FILENAME) && (value[0] == 'm') ) - { - // Erase all (old & new!) (needs a pass before assignment) - if ( EraseOldCreatureAssignments ) - { - creaForm->getRootNode().setValueByName( "", toString( "Harvest.MP%u.AssociatedItem", rMP ).c_str() ); - //nldebug( "Erasing old assignment %s in %s.creature", value.c_str(), sheetName.c_str() ); - } - else - { - if ( value == rmSheetFilename ) - { - alreadyAssigned = true; - TRMItem item; - item.push( DtName, sheetName ); - item.push( DtCreature, creaSheetName ); - item.push( DtCreaTitle, Titles[creaSheetName] ); - SortableData.updateItemAppend( item, DtCreature ); - SortableData.updateItemAppend( item, DtCreaTitle ); - } - lastAssignedRMSlot = rMP; - if ( lastAssignedRMSlot > maxLastAssignedRMSlot ) - maxLastAssignedRMSlot = lastAssignedRMSlot; - } - - // Test validity of existing assignments (in TestExistingAssigments mode) - if ( TestExistingAssigments ) - { - string sn = value.substr( 0, 11 ); - if ( inputSheetPathContent.find( sn ) == inputSheetPathContent.end() ) - { - nlwarning( "RM %s (assigned to %s.creature) not found", sn.c_str(), creaSheetName.c_str() ); - } - } - } - else if ( firstFreeRMSlot == 0 ) - firstFreeRMSlot = rMP; - } - - if ( EraseOldCreatureAssignments ) - { - if ( creatureSheets.find( creaSheetName ) == creatureSheets.end() ) - { - flushSheetToDisk( creaPathAndFilename, creaForm ); - ++nbErasedCreatureAssignments; - } - } - else if ( AssignOnlyToUnassignedCreatures && (lastAssignedRMSlot != 0) ) - { - // Skip assignment if already done (in AssignOnlyToUnassignedCreatures mode) - if ( creatureSheets.find( creaSheetName ) == creatureSheets.end() ) - { - ++nbCreatureSheetsSkipped; - nldebug( "Skipped %s.creature", creaSheetName.c_str() ); - } - } - else - { - // Assign current RM to first free slot - if ( firstFreeRMSlot != 0 ) - { - if ( ! alreadyAssigned ) - { - creaForm->getRootNode().setValueByName( rmSheetFilename.c_str(), toString( "Harvest.MP%u.AssociatedItem", firstFreeRMSlot ).c_str() ); - //nlinfo( "%s %s got %s %s", CreatureModels[CreatureToModel[creaModel2]].Name.c_str(), creaSheetName.c_str(), families[iFam].c_str(), sheetName.c_str() ); - flushSheetToDisk( creaPathAndFilename, creaForm ); - ++nbAssignedMaterials; - - // These stats won't be correct if WriteSheetsToDisk is disabled && ExistingAction is ModifyRM (infinite slots) - TRMItem item; - item.push( DtName, sheetName ); - item.push( DtCreature, creaSheetName ); - item.push( DtCreaTitle, Titles[creaSheetName] ); - SortableData.updateItemAppend( item, DtCreature ); - SortableData.updateItemAppend( item, DtCreaTitle ); - } - } - else if ( (ExistingRMAction == ModifyRM) && (! alreadyAssigned) ) - { - nlwarning( "No free slot to assign %s %s %s to %s", CreatureModels[CreatureToModel[creaModel/*2*/]].Name.c_str(), families[iFam].c_str(), sheetName.c_str(), creaSheetName.c_str() ); - } - } - creatureSheets.insert( creaSheetName ); - } - else - { - nlwarning( "Can't open %s", creaPathAndFilename.c_str() ); - } - } - } - } - } - } - } - } - } - if ( AssignRawMaterialsHarvestToCreatureSheets ) - { - // Find creature sheets that were not processed (missing model for example) - for ( map::const_iterator ipc = inputSheetPathContent.begin(); ipc!=inputSheetPathContent.end(); ++ipc ) - { - const CSString& creaSheetName = (*ipc).first; - const CSString& creaPathAndFilename = (*ipc).second; - - if ( ! ((creaSheetName[0] == 'c') && (creaSheetName.size() == 6)) ) - continue; - - if ( creatureSheets.find( creaSheetName ) == creatureSheets.end() ) - { - if ( CreatureMainModelsWithoutRM.find( creaSheetName.substr( 0, 3 ) ) != CreatureMainModelsWithoutRM.end() ) - { - nldebug( "Creature %s (%s) has no MP", creaSheetName.c_str(), CreatureModels[CreatureToModel[creaSheetName.substr( 0, 5 )]].Name.c_str() ); - } - else if ( TFamInfo::UseGenerateOnly == 0 ) // avoid warnings when generating only a subset of the RM families - { - if ( creaSheetName[CR_INDEX_LOCAL_LEVEL_CODE] == '6' ) - nldebug( "Mission creature '6' %s (%s) not processed", creaSheetName.c_str(), CreatureModels[CreatureToModel[creaSheetName.substr( 0, 5 )]].Name.c_str() ); - else if ( creaSheetName[1] == 'd' ) - nldebug( "Degenerated creature 'cd' %s (%s) not processed", creaSheetName.c_str(), CreatureModels[CreatureToModel[creaSheetName.substr( 0, 5 )]].Name.c_str() ); - else - { - string reason; - uint i; - for ( i=0; i!=NbEcosystemsPlusExtensions; ++i ) - { - if ( creaSheetName[CR_INDEX_ECOSYSTEM_CODE] == getCreatureEcosystemCode( i )[0] ) - break; - } - if ( i == NbEcosystemsPlusExtensions ) - reason = toString( " (invalid ecosystem %c)", creaSheetName[CR_INDEX_ECOSYSTEM_CODE] ); - nlwarning( "Creature %s (%s) not processed%s", creaSheetName.c_str(), CreatureModels[CreatureToModel[creaSheetName.substr( 0, 5 )]].Name.c_str(), reason.c_str() ); - } - } - - if ( EraseOldCreatureAssignments ) - { - CSmartPtr creaForm = formLoader->loadForm( (creaSheetName + "." + crSheetType).c_str() ); - if ( creaForm ) - { - for ( uint32 rMP=1; rMP<=4; ++rMP ) // only to 4 (TODO: use the proper number) - { - creaForm->getRootNode().setValueByName( "", toString( "Harvest.MP%u.AssociatedItem", rMP ).c_str() ); - //nldebug( "Erasing old assignment %s in %s.creature", value.c_str(), sheetName.c_str() ); - } - flushSheetToDisk( creaPathAndFilename, creaForm ); - ++nbErasedCreatureAssignments; - } - else - nlwarning( "Can't open %s", creaPathAndFilename.c_str() ); - } - } - } - - nlinfo( "%u raw materials assigned to %u creature sheets (%u skipped, already assigned; %u erased; biggest last slot: %u)", nbAssignedMaterials, creatureSheets.size(), nbCreatureSheetsSkipped, nbErasedCreatureAssignments, maxLastAssignedRMSlot ); - } - -processRawMaterialsForDeposits: - // - // Iterate on deposit location - // - - fprintf( GraphFile, "\n" ); - nlassert( ! DepositFamilyIndices.empty() ); - map< uint32, vs > materialsByZoneForDeposits; - NLMISC::CSmartPtr depParentForm, depForm; - float avgSumOriginalityAvg = 0.0f; - uint32 nbDepositsGenerated = 0; - - if ( SkipRawMaterialsForDeposits ) - goto endDeposits; - - if ( AssignRawMaterialsHarvestToDepositSheets || FixDeposits ) - { - /*uint32*/ nbAssignedMaterials = 0; - - if ( ExistingRMAction == ModifyRM ) - { - // Write deposit parent sheet - depParentForm = loadTemplateForm( formLoader, dpSheetType ); - clearSheet( depParentForm, &form->getRootNode() ); - //parentForm->getRootNode().setValueByName( "Harvest", "Skill" ); - for ( uint32 rMP=0; rMP!=NB_RAW_MATERIALS_PER_DEPOSIT; ++rMP ) - { - string rm = toString( "MP%02u.", rMP+1 ); - uint32 rSeason; - for ( rSeason=0; rSeason!=seasons.size(); ++rSeason ) - { - depParentForm->getRootNode().setValueByName( (uint32)0, (rm + seasons[rSeason] + ".MinQuantity").c_str() ); - depParentForm->getRootNode().setValueByName( (uint32)100, (rm + seasons[rSeason] + ".MaxQuantity").c_str() ); - depParentForm->getRootNode().setValueByName( (uint32)10, (rm + seasons[rSeason] + ".RegenRate").c_str() ); - depParentForm->getRootNode().setValueByName( (uint32)50, (rm + seasons[rSeason] + ".AngryLevel").c_str() ); - depParentForm->getRootNode().setValueByName( (uint32)30, (rm + seasons[rSeason] + ".FuryLevel").c_str() ); - depParentForm->getRootNode().setValueByName( (uint32)10, (rm + seasons[rSeason] + ".BlackKamiLevel").c_str() ); - } - depParentForm->getRootNode().setValueByName( (uint32)1, (rm + "MinGetQuantity").c_str() ); - depParentForm->getRootNode().setValueByName( (uint32)20, (rm + "MaxGetQuantity").c_str() ); - depParentForm->getRootNode().setValueByName( (uint32)1, (rm + "MinGetQuality").c_str() ); - depParentForm->getRootNode().setValueByName( (uint32)25, (rm + "MaxGetQuality").c_str() ); - depParentForm->getRootNode().setValueByName( (uint32)80, (rm + "PresenceProbabilities").c_str() ); - } - flushSheetToDisk( "_parent.deposit", depParentForm ); - - // Setup deposit sheet - depForm = loadTemplateForm( formLoader, dpSheetType ); - clearSheet( depForm, &form->getRootNode() ); - } - } - - // Iterate on ecosystem - for ( uint32 iEcosystem=0; iEcosystem!=NbEcosystems; ++iEcosystem ) - { - COriginalitySorter OriginalitySorter; - - uint32 nbPerEcosystem = min( (uint32)((ecosystemCodes[iEcosystem][0] == 'c') ? 7 : 3), MaxNbRMByFamilyEZ ); - nlinfo( "Generating/browsing %u sets for %s...", nbPerEcosystem, ecosystems[iEcosystem].c_str() ); - materialsByZoneForDeposits.clear(); - - vu& familiesForDeposit = DepositFamilyIndices; - - // Iterate on variations in ecosystem - for ( uint32 iv=0; iv!=nbPerEcosystem; ++iv ) - { - string variationInEcosystem = string( 1, (char)('a' + iv) ); - - // Iterate on level zone - for ( uint32 iZone=0; iZone<6; ++iZone ) - { - TStatQuality statQuality = (iZone == 0) ? Basic : (TStatQuality)(iZone - 1); - - // Iterate on families - for ( vu::iterator ifc=familiesForDeposit.begin(); ifc!=familiesForDeposit.end(); ++ifc ) - { - uint32 iFam = (*ifc); - if ( ! TFamInfo::mustGenerateFamily( iFam ) ) - continue; - - // Test if the raw material family must be generated for this ecosystem - const TFamInfo& rmfamily = FamSet[families[iFam]]; - bool isMissionRawMaterial = rmfamily.IsForMission; - if ( isMissionRawMaterial ) - { - // All foraged mission RMs are Common (unlike creature RMs) - if ( iEcosystem != CommonEcosystem ) - continue; - - // Mission quality ranges from A=B to F - } - else - { - if ( GenOnlyMissionRawMaterials ) - continue; - - // Basic & Fine in Common, better RMs specialized by ecosystem - if ( ! rmfamily.existsInEcosystem( (TEcosystem)iEcosystem, statQuality ) ) - continue; - - // Craft quality ranges from B (#0) to F (#4) (deposits of newbielands have B) - if ( iZone == 0 ) - continue; - } - - // Iterate on variants - for ( uint32 iVariant=1; iVariant<=1; ++iVariant ) - { - CSString sheetName = CSString( "m" ) - + familyCodes[iFam] - + CSString( "dx" ) + variationInEcosystem + ecosystemCodes[iEcosystem] + string( 1, (char)('a' + iZone) ) - + toString( "%02u", iVariant ); - - if ( GenOnlyNewRawMaterials ) - { - map::const_iterator iprm = inputSheetPathContent.find( sheetName ); - if ( iprm != inputSheetPathContent.end() ) - continue; - } - - //DebugLog->displayRawNL( "%s %s", sheetName.c_str(), getRMName( sheetName ).c_str() ); - if ( OutputNameList ) - fprintf( nameOutputFile, "%s;%s\n", sheetName.c_str(), getRMShortName( sheetName, statQuality, isMissionRawMaterial ).c_str() ); - - // Set output directory - dirbase = conventionalDirectory( ecosystems[iEcosystem] ) + "/"; - - CGenRawMaterial *rm = new CGenRawMaterial( sheetName ); - CGenRawMaterial& rawMaterial = *rm; - rawMaterial.ILocation = InDeposits; - rawMaterial.IFamily = iFam; - rawMaterial.Group = FamSet[families[iFam]].Group; - rawMaterial.IEcosystem = (TEcosystem)iEcosystem; - rawMaterial.StatQuality = statQuality; - if ( isMissionRawMaterial ) - rawMaterial.ILevelZone = iZone; - else - rawMaterial.ILevelZone = ~0; - rawMaterial.fillPropertiesFromFamily(); - - if ( ExistingRMAction == ModifyRM ) - { - rawMaterial.MaxLevel = (rawMaterial.StatQuality+1) * 250 / (NB_UNIQUE_LEVELZONES_PER_CONTINENT); - if ( ! rawMaterial.computeCraftCharacs( iVariant, sheetName ) ) - { - delete rm; - continue; - } - - /*if ( (uint)(rawMaterial.getOriginalityMax()*100.0f) >= OriginalityMinThreshold ) - { - // Write to disk - rawMaterial.writeSheet( form ); - writeRMSheetToDisk( form, sheetName ); - }*/ - - if ( SortByOriginality ) - OriginalitySorter.pushRM( &rawMaterial ); - else - { - selectRawMaterial( form, ecoParentForm, famParentForm, &rawMaterial ); - delete rm; - } - } - else - { - if ( inputSheetPathContent.find( sheetName ) != inputSheetPathContent.end() ) - { - form = (CForm*)formLoader->loadForm( (rawMaterialPath + dirbase + sheetName + "." + rmSheetType).c_str() ); - if ( ! form ) - { - nlwarning( "Can't load %s", (rawMaterialPath + dirbase + sheetName + "." + rmSheetType).c_str() ); - } - else - { - rawMaterial.loadSheet( form, sheetName, false ); - - // Write stats - TRMItem item; - rm->collectStats( item, MainStat ); - SortableData.addItem( item ); - } - } - delete rm; - } - - } - } - } - } - - if ( ExistingRMAction == ModifyRM ) - { - if ( SortByOriginality ) - { - nlerror( "Deprecated" ); - /*set usedRMFamilies [5]; - uint sumNBRMCraftBySlot = 0, sumOriginalityAvg = 0; - for ( uint r=0; r!=NbFaberElements; ++r ) - { - uint iNBRMCraftBySlot = 0, iUniqueNBRMCraftBySlot = 0; - nlinfo( "%s: Popping at most %u RM from %u (%ux5) compatible", getShortFaberElemString(r).c_str(), MaxNbRMByCraftSlotE, OriginalitySorter.RMByOriginalityByCraftSlot[r].size(), OriginalitySorter.RMByOriginalityByCraftSlot[r].size()/5 ); - COriginalitySorter::CMultiMapByOriginality::const_iterator imo; - for ( imo= OriginalitySorter.RMByOriginalityByCraftSlot[r].begin(); - imo!=OriginalitySorter.RMByOriginalityByCraftSlot[r].end(); - ++imo ) - { - if ( iNBRMCraftBySlot >= MaxNbRMByCraftSlotE ) - break; - - const uint32& originality = (*imo).first; - CGenRawMaterial *rm = (*imo).second; - - if ( ! OriginalitySorter.alreadyPopped( rm ) ) - { - //InfoLog->displayRawNL( "NewOne: %p: %s %s %u", rm, rm->SheetName.c_str(), faberElems[r].c_str(), (*imo).first ); - selectRawMaterial( form, ecoParentForm, famParentForm, rm ); - - // Memorize for deposit assignment - materialsByZoneForDeposits[rm->ILevelZone+1].push_back( rm->SheetName ); - usedRMFamilies[rm->ILevelZone].insert( rm->IFamily ); - - sumOriginalityAvg += (uint)(rm->getOriginalityAvg()*100.0f); - ++iUniqueNBRMCraftBySlot; - - OriginalitySorter.popAndDeleteRM( rm ); - } - else - { - //InfoLog->displayRawNL( "Already: %p: %s %u", rm, faberElems[r].c_str(), (*imo).first ); - } - ++iNBRMCraftBySlot; // when already popped, consider as counting for the rms for current craft slot - } - nldebug( "%s: %u rm generated (for deposits)", CraftParts[r].Name.c_str(), iNBRMCraftBySlot ); - sumNBRMCraftBySlot += iUniqueNBRMCraftBySlot; - } - nlinfo( "Total selected for deposits in %s: %u", ecosystems[iEcosystem].c_str(), sumNBRMCraftBySlot ); - - // Force at least one rm of each (family, levelzone) - uint iRM = 0; - for ( uint32 iLevelZone=0; iLevelZone!=5; ++iLevelZone ) - { - COriginalitySorter::CRMSet::const_iterator itRm = OriginalitySorter.getRMSetBegin(); - while ( (itRm = OriginalitySorter.getFirstRMNotInFamilyListFromPos( usedRMFamilies[iLevelZone], iLevelZone, itRm )) != OriginalitySorter.getRMSetEnd() ) - { - CGenRawMaterial *rm = (*itRm); - selectRawMaterial( form, ecoParentForm, famParentForm, rm ); - - // Memorize for deposit assignment - materialsByZoneForDeposits[rm->ILevelZone+1].push_back( rm->SheetName ); - usedRMFamilies[iLevelZone].insert( rm->IFamily ); - nldebug( "Adding %s (family %s zone %c)", rm->SheetName.c_str(), rm->familyStr().c_str(), 'A' + (char)(rm->ILevelZone+1) ); - ++iRM; - sumOriginalityAvg += (uint)(rm->getOriginalityAvg()*100.0f); - } - } - nlinfo( "Added %u RM (one per family per levelzone)", iRM ); - sumNBRMCraftBySlot += iRM; - avgSumOriginalityAvg += (float)sumOriginalityAvg / (float)sumNBRMCraftBySlot; - - // Delete rm objects - OriginalitySorter.deleteAllRemainingRM(); - */ - } - } - - if ( AssignRawMaterialsHarvestToDepositSheets || FixDeposits ) - { - nlinfo( "Generating/browsing deposits for %s...", ecosystems[iEcosystem].c_str() ); - - // Iterate on level zone - for ( uint32 iZone=0; iZone<=5; ++iZone ) - { - string depSheetName = string("d") + ecosystemCodes[iEcosystem].c_str() + toString( "%caa", (char)('a' + iZone) ); - - if ( ExistingRMAction == ModifyRM ) - { - clearSheet( depForm, &depForm->getRootNode() ); - depForm->insertParent( 0, "_parent.deposit", depParentForm ); - - // Get the list of raw material families and make a random selection of raw material sheets - set usedFamilies; - uint32 iz = (iZone==0) ? 1 : iZone; // 'A' gets raw materials of zone 'B' - vs& compatibleMaterials = materialsByZoneForDeposits[iz]; - for ( uint32 rMP=0; rMP!=NB_RAW_MATERIALS_PER_DEPOSIT; ++rMP ) - { - bool famOk = false; - uint32 escapeCounter = 0; - do - { - CSString rmName; - - // Particular cases (forced for LD missions) - if ( iz == 1 ) - { - /*switch ( rMP ) - { - case 0: - rmName = "mdubcbwof01"; - break; - case 1: - rmName = "mduacbwoo01"; - break; - case 2: - rmName = "mduacbref01"; - break; - }*/ - } - if ( rmName.empty() ) - { - // Generic case, get a random value - if ( ! compatibleMaterials.empty() ) - { - uint32 iMaterial = getRandomValue( compatibleMaterials.size() ); - rmName = compatibleMaterials[iMaterial]; - } - } - - // No compatible material? - if ( rmName.empty() ) - { - escapeCounter = 16; - break; - } - - // Prevent from having the same family more than once - CSString extFamily = rmName.substr( RM_INDEX_FAMILY_CODE, NB_FAMILY_CODE_CHARS ); - if ( usedFamilies.find( extFamily ) == usedFamilies.end() ) - { - usedFamilies.insert( extFamily ); - - // Assign RM to current deposit slot - depForm->getRootNode().setValueByName( (rmName+"."+rmSheetType).c_str(), toString( "MP%02u.AssociatedItem", rMP+1 ).c_str() ); - nldebug( "%s got %s %s", depSheetName.c_str(), families[getIndexFromString( rmName.substr( 6, 2 ), familyCodes )].c_str(), rmName.c_str() ); - ++nbAssignedMaterials; - - // Test validity of existing assignments (in TestExistingAssigments mode) - if ( TestExistingAssigments ) - { - if ( inputSheetPathContent.find( rmName ) == inputSheetPathContent.end() ) - { - nlwarning( "RM %s (assigned to %s.deposit) not found", rmName.c_str(), depSheetName.c_str() ); - } - } - - TRMItem depItem; - depItem.push( DtName, rmName ); - //depItem.push( DtDeposit, depSheetName ); - //SortableData.updateItemAppend( depItem, DtDeposit ); - - famOk = true; - } - else - ++escapeCounter; - } - while ( (! famOk) && (escapeCounter < 16) ); - if ( ! famOk ) - { - nlwarning( "Deposit %s got only %u RM", depSheetName.c_str(), rMP ); - break; - } - } - - flushSheetToDisk( depositPath + depSheetName + "." + dpSheetType, depForm ); - ++nbDepositsGenerated; - } - else if ( ! FixDeposits ) - { - const string& filename = inputSheetPathContent[depSheetName]; - if ( filename.empty() ) - nlwarning( "%s not found", (depSheetName + "." + dpSheetType).c_str() ); - else - depForm = (CForm*)formLoader->loadForm( filename.c_str() ); - - uint32 nbRMinDep = 0; - //string rms = depSheetName + ": "; - for ( uint32 rMP=0; rMP!=NB_RAW_MATERIALS_PER_DEPOSIT; ++rMP ) - { - CSString value; - depForm->getRootNode().getValueByName( value, toString( "MP%02u.AssociatedItem", rMP+1 ).c_str() ); - if ( ! value.empty() ) - { - CSString rmName = value.rightCrop( rmSheetType.size() + 1 ); - TRMItem depItem; - depItem.push( DtName, rmName ); - //depItem.push( DtDeposit, depSheetName ); - //rms += rmName + ","; - //SortableData.updateItemAppend( depItem, DtDeposit ); - ++nbRMinDep; - } - } - //nlinfo( "%u RM in deposit %s: %s", nbRMinDep, depSheetName.c_str(), rms.c_str() ); - } - } - } - } - if ( AssignRawMaterialsHarvestToDepositSheets ) - { - nlinfo( "%u raw materials assigned to %u deposit sheets", nbAssignedMaterials, nbDepositsGenerated ); - } - nlinfo( "Average originality: %.2f", (float)avgSumOriginalityAvg / (float)ecosystems.size() ); -endDeposits: - nldebug( "End of generation" ); - } - - if ( BrowseOtherDeposits || FixDeposits ) - { - // Access deposits - vector depositFiles; - CPath::getPathContent( depositPath, true, false, true, depositFiles ); - for ( vector::const_iterator idf=depositFiles.begin(); idf!=depositFiles.end(); ++idf ) - { - const string& filename = (*idf); - const CSString& depSheetName = CFile::getFilenameWithoutExtension( filename ); - - if ( (filename.find( ".deposit" ) != string::npos) && (depSheetName[0] == 'd') && (depSheetName.size() == 5) ) - { - bool isGenerated = (depSheetName.right( 2 ) == "aa"); - - // If not fixing deposits (just browsing), discard generated ones (already browsed) - if ( (! FixDeposits) && isGenerated ) - continue; - - CSmartPtr depForm = (CForm*)formLoader->loadForm( filename.c_str() ); - bool modified = false; - - // Browse or check/substitute all RM assigned to deposit - for ( uint32 rMP=0; rMP!=NB_RAW_MATERIALS_PER_DEPOSIT; ++rMP ) - { - CSString value, substitution; - depForm->getRootNode().getValueByName( value, toString( "MP%02u.AssociatedItem", rMP+1 ).c_str() ); - if ( value.empty() ) - continue; - - if ( ! isGenerated ) - { - TRMItem depItem; - depItem.push( DtName, value ); - //depItem.push( DtDeposit, depSheetName ); - //SortableData.updateItemAppend( depItem, DtDeposit ); - } - - if ( FixDeposits ) - { - nlerror( "TODO" ); // this code is for V2, not suitable for V3 - /*value = value.rightCrop( 6 ); // remove .sitem - CRMData::CLookup::const_iterator ilk = SortableData.lookup( DtName ).find( value ); - if ( ilk == SortableData.lookup( DtName ).end() ) - { - // Find a substitution by declinaison/location - char adjCode = value[8]; - string substitution = findSubstitutionForDepositRM( value, adjCode ); - if ( substitution.empty() ) - { - // Find a substitution by adjective (emit a warning) - for ( mss::const_iterator ita=adjectives.begin(); ita!=adjectives.end(); ++ita ) - { - adjCode = tolower( (*ita).first[0] ); - if ( adjCode == value[8] ) - continue; - - substitution = findSubstitutionForDepositRM( value, adjCode ); - if ( ! substitution.empty() ) - { - nlinfo( "Replacing adj %s by %s for %s", adjectives[string(1,(char)toupper(value[8]))].c_str(), (*ita).second.c_str(), value.c_str() ); - break; - } - } - } - if ( substitution.empty() ) - { - nlwarning( "Could not find a substitution for %s in %s", value.c_str(), depSheetName.c_str() ); - } - else - { - depForm->getRootNode().setValueByName( (substitution+".sitem").c_str(), toString( "MP%02u.AssociatedItem", rMP+1 ).c_str() ); - nlinfo( "%s replaced by %s", value.c_str(), substitution.c_str() ); - modified = true; - } - - } - if ( modified ) - { - flushSheetToDisk( filename, depForm ); - }*/ - } - } - } - } - } - - if ( OutputNameList ) - fclose( nameOutputFile ); - fclose( GraphFile ); - - //nlinfo( "%u RM in repository", Repository.size() ); - - // Produce main doc - CProducedDocHtml MainDoc; - CProducedDocCSV MainCSV; - MainDoc.open( "rm.html", "Raw materials by generation order", ProduceDoc ); - MainCSV.open( "output_rm_for_craft.csv", ProduceDoc ); - MainDoc.write( "
    \n" ); - MainDoc.write( "" ); - for ( uint32 c=0; c!=DtNbCols; ++c ) - { - MainDoc.write( "" ); - MainCSV.write( string(DataColStr[c]) + "," ); - } - MainDoc.write( "" ); - MainCSV.write( "\n" ); - for ( CRMData::CItems::const_iterator isd=SortableData.items().begin(); isd!=SortableData.items().end(); ++isd ) - { - MainDoc.write( (*isd).toHTMLRow() ); - } - MainDoc.write( "
    " + string(DataColStr[c]) + "
    \n" ); - - // Produce alt docs - CProducedDocHtml AltDocs[DtNbCols]; - for ( uint32 c=0; c!=DtNbCols; ++c ) - { - AltDocs[c].open( "rm_" + string(DataColStr[c]) + ".html", "Raw materials by " + string(DataColStr[c]), ProduceDoc ); - AltDocs[c].write( "
    \n" ); - AltDocs[c].write( "" ); - for ( uint32 cc=0; cc!=DtNbCols; ++cc ) - if ( cc == c ) - AltDocs[c].write( "" ); - else - AltDocs[c].write( "" ); - AltDocs[c].write( "" ); - string previousKey = "[NO PREVIOUS]"; // not a blank string, because it may be a valid value - string previousName = ""; - for ( CRMData::CLookup::const_iterator isd=SortableData.lookup( c ).begin(); isd!=SortableData.lookup( c ).end(); ++isd ) - { - const TRMItem& item = SortableData.getRow( (*isd).second ); - AltDocs[c].write( item.toHTMLRow( c, (*isd).first, previousKey, DtName, previousName ) ); - - if ( c == DtCraftSlotName ) - MainCSV.write( item.toCSVLine( ',', "", c, (*isd).first, previousKey, DtName, previousName ) ); - - previousKey = (*isd).first; - previousName = item.Fields[DtName][0]; - } - AltDocs[c].write( "
    " + string(DataColStr[cc]) + "" + string(DataColStr[cc]) + "
    \n" ); - AltDocs[c].save(); - } - - // Stats - if ( (nbSheetsProcessed != 0) ) - { - CProducedDocHtml StatFile; - StatFile.open( "rm_stats.html", "Raw material statistics", ProduceDoc ); - StatFile.writepln( toString( "Total: %u raw materials (%u new)", nbSheetsProcessed, nbNewSheetsGenerated ) ); - StatFile.writepln( toString( "Faber elements filled: avg %u, min %u, max %u", MainStat.SumNbFaberElemsFilled / nbSheetsProcessed, MainStat.MinNbFaberElemsFilled, MainStat.MaxNbFaberElemsFilled ) ); - - // What can be crafted from each raw material family - StatFile.writeln( "What can be crafted from each raw material family:
    " ); - StatFile.writeln( "
      " ); - for ( uint32 iFam=0; iFam!=families.size(); ++iFam ) - { - if ( ! FamSet[families[iFam]].IsActive ) - continue; - - string propStr; - vs& props = FamSet[families[iFam]].Properties; - for ( vs::const_iterator ip = props.begin(); ip!=props.end(); ++ip ) - { - if ( ip != props.begin() ) - propStr += ", "; - propStr += (*ip); - } - uint nbLines = 0; - StatFile.writeln( "
    • " + families[iFam] + ": " + propStr + "

      " ); - StatFile.writeln( "
        " ); - for ( uint32 c=0; c!=NbCiv; ++c ) - { - bool civHasAPlan = false; - for ( uint32 rFaberElem=0; rFaberElem!=NbFaberElements; ++rFaberElem ) - { - if ( MainStat.NbRMByFaberElemByFamilyAndCiv[iFam][c][rFaberElem] != 0 ) - { - civHasAPlan = true; - break; - } - } - if ( civHasAPlan ) - { - StatFile.writeln( "
      • " + string(CivNames[c]) + " plans

        " ); - StatFile.writeln( "
          " ); - for ( uint32 rFaberElem=0; rFaberElem!=NbFaberElements; ++rFaberElem ) - { - if ( MainStat.NbRMByFaberElemByFamilyAndCiv[iFam][c][rFaberElem] != 0 ) - { - StatFile.writebln( CraftParts[rFaberElem].Name + toString(": %u different", MainStat.NbRMByFaberElemByFamilyAndCiv[iFam][c][rFaberElem] ) ); - ++nbLines; - } - } - StatFile.writeln( "
        " ); - } - } - StatFile.writeln( "
      " ); - if ( nbLines == 0 ) - { - if ( ! FamSet[families[iFam]].IsForMission ) - { - if ( ! ( (SkipRawMaterialsForCreatures && FamSet[families[iFam]].IsInCreatures) || - (SkipRawMaterialsForDeposits && FamSet[families[iFam]].IsInDeposits) ) ) - nlwarning( "%s is not used by any craft plan!", families[iFam].c_str() ); - } - StatFile.writebln( "No use for this family" ); - // Tip: if RM of a creature, check if the creature exists - } - } - StatFile.writeln( "
    " ); - - // Number of compatible RM by ecosystem, by craft slot - vector nbFabs( NbEcosystems, 0 ); - for ( uint32 rFaberElem=0; rFaberElem!=NbFaberElements; ++rFaberElem ) - { - StatFile.writebln( toString( "%s: %u compatible RM", CraftParts[rFaberElem].Name.c_str(), MainStat.NbRMByFaberElem[rFaberElem] ) ); - if ( CraftParts[rFaberElem].Name.c_str(), MainStat.NbRMByFaberElem[rFaberElem] != 0 ) - { - for ( uint32 iEcosystem=0; iEcosystem!=ecosystems.size(); ++iEcosystem ) - { - StatFile.writebln( toString( "(%u in %s)", MainStat.NbRMByFaberElemByEcosystem[iEcosystem][rFaberElem], ecosystems[iEcosystem].c_str() ) ); - nbFabs[iEcosystem] += MainStat.NbRMByFaberElemByEcosystem[iEcosystem][rFaberElem]; - } - } - } - for ( uint32 iEcosystem=0; iEcosystem!=ecosystems.size(); ++iEcosystem ) - { - StatFile.writebln( toString( "(Total %u in %s)", nbFabs[iEcosystem], ecosystems[iEcosystem].c_str() ) ); - } - - // Number of properties by ecosystem - for ( uint32 iProp=0; iProp!=properties.size(); ++iProp ) - { - uint32 nbTotal = 0; - /*for ( uint32 iLoc=0; iLoc!=NB_LOCATIONS; ++iLoc ) - { - uint32 nbInLoc = 0; - for ( uint32 iEcosystem=0; iEcosystem!=ecosystems.size(); ++iEcosystem ) - { - uint32 nb = NbRMHavingProperty[iLoc][iEcosystem][iProp]; - StatFile.writeln( toString( "\t\t%s %s %s: %u RM", locationNames[iLoc], ecosystems[iEcosystem].c_str(), properties[iProp].c_str(), nb ) ); - nbInLoc += nb; - } - StatFile.writeln( toString( "\t%s %s: %u RM", locationNames[iLoc], properties[iProp].c_str(), nbInLoc ) ); - }*/ - StatFile.writeln( "
      " ); - for ( uint32 iEcosystem=0; iEcosystem!=ecosystems.size(); ++iEcosystem ) - { - uint32 nbInEco = 0; - for ( uint32 iLoc=0; iLoc!=NB_LOCATIONS; ++iLoc ) - { - uint32 nb = MainStat.NbRMHavingProperty[iLoc][iEcosystem][iProp]; - //StatFile.writebln( toString( "\t\t%s %s %s: %u RM", locationNames[iLoc], ecosystems[iEcosystem].c_str(), properties[iProp].c_str(), nb ) ); - nbInEco += nb; - } - StatFile.writebln( toString( "%s %s: %u", ecosystems[iEcosystem].c_str(), properties[iProp].c_str(), nbInEco ) ); - nbTotal += nbInEco; - } - StatFile.writeln( "
    " ); - StatFile.writebln( toString( "%s: %u RM", properties[iProp].c_str(), nbTotal ) ); - } - StatFile.save(); - MainDoc.writepln( "Go to statistics" ); - } - - MainDoc.save(); - MainCSV.save(); - -#if 0 - // - // O L D - V 1 - // - // Randomize color (POSITIVE filter) - CRulesFilter& familyColorFilter = familyColorFilters[iEcosystem][iFamily].empty() ? familyColorFilters[CommonEcosystem] : familyColorFilters[iEcosystem]; - if ( familyColorFilter[iFamily].empty() ) - { - nlwarning( "%s not generated: no possible color in any ecosystem", families[iFamily].c_str() ); - continue; - } - else - { - iColor = familyColorFilter[iFamily][getRandomValue( familyColorFilter[iFamily].size() )]; - } - - if ( isCrSpecialization ) - form->getRootNode().setValueByName( (creatures[iCreature] + " " + strlwr( static_cast(families[iFamily]) )).c_str(), "basics.name" ); - - /* - * Creatures - */ - if ( AssignRawMaterialsHarvestToCreatureSheets ) - { - uint32 nbCreatures = 0, nbCreaturesInSubPath = 0; - nlinfo( "Generating assignments to creature sheets..." ); - getTransposedMap( creatureFamilyFilter, familyCreatureFilter ); - for ( CRulesFilter::const_iterator ir=creatureFamilyFilter.begin(); ir!=creatureFamilyFilter.end(); ++ir ) - { - const char *sCreature = ((*ir).first == ~0) ? "COMMON" : creatures[(*ir).first].c_str(); - nlinfo( "Creature %s -> %u compatible raw materials families", sCreature, (*ir).second.size() ); - } - - // Browse creature sheet repository - map::const_iterator ipc; - for ( ipc=inputSheetPathContent.begin(); ipc!=inputSheetPathContent.end(); ++ipc ) - { - const string& sheetName = (*ipc).first; - const string& filename = (*ipc).second; - if (CFile::getExtension( filename ) == crSheetType) - { - nldebug( "%s", filename.c_str() ); - ++nbCreatures; - } - if ( (CFile::getExtension( filename ) == crSheetType) && - (strlwr(filename).find( creaturePath ) != string::npos) ) - { - ++nbCreaturesInSubPath; - nldebug( "OK" ); - // Load creature sheet - form = (CForm*)formLoader->loadForm( filename.c_str() ); - if ( ! form ) - { - nlwarning( "Can't load sheet %s", filename.c_str() ); - continue; - } - - string eco = string(1, sheetName[1+NB_CREATURE_CODE_CHARS]); - uint32 iEcosystem = getIndexFromString( eco, ecosystemCodes ); - if ( iEcosystem == ~0 ) - { - nlwarning( "Ecosystem code %s in %s unknown", eco.c_str(), sheetName.c_str() ); - continue; - } - - string cr = sheetName.substr( 1, NB_CREATURE_CODE_CHARS ); - uint32 iCreature = getIndexFromString( cr, creatureCodes ); - if ( iCreature == ~0 ) - { - nlwarning( "Creature code %s in %s unknown", cr.c_str(), sheetName.c_str() ); - continue; - } - - // Transform creature level to faber interest level ((ZL, lastLL) = (ZL+1, FirstLL)) - TFaberInterestLevel mainLevel; // mainLevel in [0.. NbFaberInterestLevelsByEcosystem[iEcosystem][ - sint localLevel = (sint)(sheetName[1+NB_CREATURE_CODE_CHARS+2] - '1'); - uint32 zoneLevel = (sint)(sheetName[1+NB_CREATURE_CODE_CHARS+1] - 'a'); - mainLevel = zoneLevel*NB_UNIQUE_LEVELS_PER_ZONE + localLevel; - nlassertex( mainLevel >= 0, ("%s ZL=%d LL=%d FL=%d", sheetName.c_str(), zoneLevel, localLevel, mainLevel) ); - if ( mainLevel >= NbFaberInterestLevelsByEcosystem[iEcosystem] ) - { - nlwarning( "Wrong level %s ZL=%d maxLL=%u LL=%d maxFL=%d FL=%d", sheetName.c_str(), zoneLevel, NB_UNIQUE_LEVELS_PER_ZONE+1, localLevel, NbFaberInterestLevelsByEcosystem[iEcosystem], mainLevel ); - mainLevel = NbFaberInterestLevelsByEcosystem[iEcosystem] - 1; - } - - for ( uint32 rFamily=0; rFamily!=creatureFamilyFilter[iCreature].size(); ++rFamily ) - { - if ( rFamily > NB_RAW_MATERIAL_FAMILIES_PER_CREATURE ) - { - nlwarning( "Too many compatible materials found (%u) for %s (%s, %s)", creatureFamilyFilter[iCreature].size(), - sheetName.c_str(), (iCreature==~0) ? cr.c_str() : creatures[iCreature].c_str(), families[creatureFamilyFilter[iCreature][rFamily]].c_str() ); - continue; - } - - sint levelModifier = ((sint)getRandomValue( 3 )) - 1; // {-1, 0, 1} - TFaberInterestLevel actualLevel = max( 0, min( NbFaberInterestLevelsByEcosystem[iEcosystem]-1, mainLevel + levelModifier ) ); - char *errorReport; - string rmName = findRawMaterialFromCriteria( iEcosystem, creatureFamilyFilter[iCreature][rFamily], iCreature, actualLevel, &errorReport ); - if ( rmName.empty() ) - { - nlwarning( "%s %s (%s) has no match (%s)", - (iCreature==~0) ? cr.c_str() : creatures[iCreature].c_str(), families[creatureFamilyFilter[iCreature][rFamily]].c_str(), sheetName.c_str(), errorReport ); - } - } - - /* - * Deposits - */ - - // For each ecosystem - for ( iEcosystem=0; iEcosystem!=ecosystemDepositFilters.size(); ++iEcosystem ) - { - // For each deposit level - uint32 rLevel; - for ( rLevel=0; rLevel!=5; ++rLevel ) - { - - } - } - } - - // Test deposit validity - /*if ( TestExistingAssigments ) - { - map::const_iterator ipc; - for ( ipc=inputSheetPathContent.begin(); ipc!=inputSheetPathContent.end(); ++ipc ) - { - const string& sheetName = (*ipc).first; - const string& filename = (*ipc).second; - if ( (CFile::getExtension( filename ) == dpSheetType) ) - { - // Load deposit sheet - form = (CForm*)formLoader->loadForm( filename.c_str() ); - if ( ! form ) - { - nlwarning( "Can't load sheet %s", filename.c_str() ); - continue; - } - - for ( uint32 iRM=0; iRM!=30; ++iRM ) - { - string value; - form->getRootNode().getValueByName( value, toString( "MP%02u.AssociatedItem", iRM+1 ).c_str() ); - if ( (value.size() == 19) && (value[0] == 'm') ) - { - string sn = value.substr( 0, 14 ); - if ( inputSheetPathContent.find( sn ) == inputSheetPathContent.end() ) - { - nlwarning( "RM %s (assigned to %s.deposit) not found", sn.c_str(), sheetName.c_str() ); - } - } - } - } - } - }*/ -#endif -} - - - -/* - * - */ -void usage(char *argv0, FILE *out) -{ - fprintf(out, "\n"); - fprintf(out, "Syntax: %s [-p ]", argv0); - fprintf(out, "\n"); -} - - -/* - * - */ -int main(int argc, char* argv[]) -{ - // parse command line - uint32 i; - for (i=1; (sint)i after -p option\n"); - usage(argv[0], stderr); - exit(0); - } - inputSheetPath = argv[i]; - break; - case 'n': - ++i; - if ((sint)i == argc) - { - fprintf(stderr, "Missing after -n option\n"); - usage(argv[0], stderr); - exit(0); - } - ExtractNamesCsv = argv[i]; - break; - } - } - } - - if ( ! ExtractNamesCsv.empty() ) - extractRawMaterialNames(); - else - generateRawMaterials(); - - return 0; -} - - -// Impossible to insert game_share/protection_type.h into project because of #@&$£ precompiled headers -namespace PROTECTION_TYPE -{ - NL_BEGIN_STRING_CONVERSION_TABLE (TProtectionType) - NL_STRING_CONVERSION_TABLE_ENTRY(Cold) - NL_STRING_CONVERSION_TABLE_ENTRY(Acid) - NL_STRING_CONVERSION_TABLE_ENTRY(Rot) - NL_STRING_CONVERSION_TABLE_ENTRY(Fire) - NL_STRING_CONVERSION_TABLE_ENTRY(Shockwave) - NL_STRING_CONVERSION_TABLE_ENTRY(Poison) - NL_STRING_CONVERSION_TABLE_ENTRY(Electricity) - NL_STRING_CONVERSION_TABLE_ENTRY(Madness) - NL_STRING_CONVERSION_TABLE_ENTRY(Slow) - NL_STRING_CONVERSION_TABLE_ENTRY(Snare) - NL_STRING_CONVERSION_TABLE_ENTRY(Sleep) - NL_STRING_CONVERSION_TABLE_ENTRY(Stun) - NL_STRING_CONVERSION_TABLE_ENTRY(Root) - NL_STRING_CONVERSION_TABLE_ENTRY(Blind) - NL_STRING_CONVERSION_TABLE_ENTRY(Fear) - NL_STRING_CONVERSION_TABLE_ENTRY(None) - NL_END_STRING_CONVERSION_TABLE(TProtectionType, ProtectionTypeConversion, None) - - - //----------------------------------------------- - // fromString: - //----------------------------------------------- - TProtectionType fromString(const std::string &str) - { - return ProtectionTypeConversion.fromString(str); - } - - - //----------------------------------------------- - // toString : - //----------------------------------------------- - const std::string& toString(TProtectionType protection_type) - { - return ProtectionTypeConversion.toString(protection_type); - } -}; // PROTECTION_TYPE +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#include "StdAfx.h" +#include "srg_utilities.h" +#include "game_share/protection_type.h" +#include "nel/misc/string_conversion.h" + +/* + * V3 + */ + +// Flags: overridden by the config file values + +/// Generate only new materials sheets, don't modify existing +bool GenOnlyNewRawMaterials = true; + +/// Allow to modify existing material sheets +enum TExistingRMAction { BrowseRM, ModifyRM, SkipRM } ExistingRMAction = BrowseRM; + +/// Skip RM for creatures +bool SkipRawMaterialsForCreatures = false; + +/// Browse creature sheets and set their raw material properties using raw materials generated or loaded +bool AssignRawMaterialsHarvestToCreatureSheets = true; + +/// Prevent from overwriting raw material assignment to creatures when already done +bool AssignOnlyToUnassignedCreatures = true; + +/// Skip RM for deposits +bool SkipRawMaterialsForDeposits = false; + +/// Skip non-mission raw materials +bool GenOnlyMissionRawMaterials = false; + +/// Generate deposit sheets using raw materials generated or loaded +bool AssignRawMaterialsHarvestToDepositSheets = true; + +/// Browse all deposits found (to produce doc), including not generated ones +bool BrowseOtherDeposits = false; + +/// Substitute invalid raw materials assignments in deposits with valid similar assignments +bool FixDeposits = false; + +/// Write even blank properties (to erase old assignments) +bool EraseOldCreatureAssignments = false; + +/// Test (for creatures: test previous assignment only, on deposit: test current assignment) +bool TestExistingAssigments = true; + +/// Print the names of raw materials in a file +bool OutputNameList = false; + +/// Display families and properties +bool DisplayFamAndProp = false; + +/// Produce html documentation +bool ProduceDoc = true; + +/// If not ~0, print all RMs of zone level +uint32 GetSelectionUntilLevel = ~0; + +/// Max number of MP by family (by ecosystem and levelzone) +uint32 MaxNbRMByFamilyEZ = 10; + +/// If true, sort by decreasing originality +bool SortByOriginality = false; + +/// Max number of MP useful for one craft slot +uint32 MaxNbRMByCraftSlotE = 100; + +/// Check if sheets (when loading them in browse mode) have valid durability +bool CheckDurability = false; + +/// Generate files for WorldEditor listbox for families +bool GenerateDepositSystemMpFiles = true; + +// Discard rm with originality lower than this value +//uint32 OriginalityMinThreshold = 0; + +// Number of combinations to randomize per raw material (obsolete) +//uint32 NbFaberCombinations = 10; + + +const uint32 NB_RAW_MATERIAL_FAMILIES_PER_CREATURE = 9; +const uint32 NB_RAW_MATERIALS_PER_DEPOSIT = 30; + +const string CommonCreatureCode = "zz"; + +CRulesFilter propertySetFilter, familyFaberFilter, familyCreatureFilter, creatureFamilyFilter, familyColorsFilter; + +vector< CRulesFilter > ecosystemDepositFilters; + +const char * locationNames [NB_LOCATIONS] = { "InDeposits", "InCreatures" }; + + +FILE *GraphFile; +CFileDisplayer ListDisplayer( "families_output.txt", true ); +CLog ListLog; + +uint32 nbMaterialSheetsProcessed = 0, nbRejectedProperties = 0, nbExistingSheetsLoaded = 0, nbExistingSheetsModified = 0, nbSheetsProcessed = 0, nbNewSheetsGenerated = 0; + + +typedef map< string, PROTECTION_TYPE::TProtectionType > CProtectionTypeMap; +CProtectionTypeMap JewelProtectionTypeByFamilyEcosystem; +//bool HasSpecializedJewelProtectionTypeByCiv [NbCiv] = { false, false, false, false, false }; +//set< PROTECTION_TYPE::TProtectionType > midProtectionTypesUsed; + + +CRMData SortableData; + +CTitles Titles; + +CMainStat MainStat; + +CRulesStr2Filter CustomizedPropertiesSheetName; + +//vector< CGenRawMaterial > Repository; + +/* + * + */ +CSString makeAbbrevName( CSString name, const CSkeletonMap& alreadyDone ) +{ + CSString abbrevName = name.left( 6 ).toUpper(); + if ( (name.size() == abbrevName.size() + 1) && + (abbrevName[abbrevName.size()-1] == 'E') && (tolower(name[name.size()-1]) == 'r') ) + abbrevName[abbrevName.size()-1] = 'R'; + + CSkeletonMap::const_iterator isk; + for ( isk=alreadyDone.begin(); isk!=alreadyDone.end(); ++isk ) + { + if ( (abbrevName == (*isk).second.AbbrevName) && (name != (*isk).second.Name) ) + nlerror( "Duplicate abbrevName %s for %s and %s", abbrevName.c_str(), (*isk).second.Name.c_str(), name.c_str() ); + } + return abbrevName; +} + + +/* + * No duplicate check (multiple families have the same prefix name, ex: Abhaya) + */ +CSString makeAbbrevName( CSString name ) +{ + CSString abbrevName = name.left( 6 ).toUpper(); + if ( (name.size() == abbrevName.size() + 1) && + (abbrevName[abbrevName.size()-1] == 'E') && (tolower(name[name.size()-1]) == 'r') ) + abbrevName[abbrevName.size()-1] = 'R'; + string::size_type p = abbrevName.find( " " ); + if ( p != string::npos ) + abbrevName = abbrevName.left( p ); + + return abbrevName; +} + + +/// DISABLED +#if 0 +/* + * Returns false if the RM must NOT be generated. + */ +bool CFaberCharacteristics::randomizeValues( TFaberInterestLevel interestLevel, TFaberInterestLevel nbInterestLevels, uint iVariant, float widthRatio, float peakOccurRatio, float baseBoost, TEcosystem iEcosystem, uint iFreq, uint iFamily ) +{ + if ( FaberElement == ~0 ) + return true; + if ( interestLevel == NAInterestLevel ) // no random values + return true; + + uint32 rPeak = ~0; + uint32 rCharac; + + // Boost 0, 1 or 2 characs, depending on iVariant and interestLevel + uint rBoostedCharac [2] = { ~0, ~0 }; + if ( iVariant == 2 ) // A-E:1>=90%; F:5>=90% + { + do + { + rBoostedCharac[0] = getRandomValue( NbCharacs-1 ); + } + while ( ! CharacSlotFilter[rBoostedCharac[0]][FaberElement] ); + /*if ( interestLevel == nbInterestLevels-1 ) // TODO + { + do + { + rBoostedCharac[1] = getRandomValue( NbCharacs-1 ); // currently, can loop infinitely if there is only one matching CharactSlotFilter + } + while ( (rBoostedCharac[1] == rBoostedCharac[0]) || (! CharacSlotFilter[rBoostedCharac[1]][FaberElement]) ); + }*/ + } + + // Browse characs + for ( rCharac=0; rCharac!=NbCharacs; ++rCharac ) + { + if ( ! CharacSlotFilter[rCharac][FaberElement] ) + continue; + + // Special cases + if ( (FaberElement == ITEM_PART_JEWEL_GEM) && (rCharac == JewelProtection) ) + { + if ( ! randomizeJewelProtection( (TStatQuality)interestLevel, iEcosystem, iFreq, iFamily ) ) + return false; + } + else // general case + { + // Randomize variation of interest level (different for each characteristic) + /*TFaberInterestLevel deltaLevel = (sint)getRandomValue( nbInterestLevels ) - ((sint)(nbInterestLevels) / 2);*/ + TFaberInterestLevel actualLevel = interestLevel; /*max( (sint)0, min( (sint)nbInterestLevels-1, ((sint)interestLevel) + deltaLevel ) );*/ + sint factor; + + // Boosted charac? + if ( (rCharac == rBoostedCharac[0]) ) + { + Values[rCharac] = 90.0f + frand( 10.0f ); + } + else + { + // Handle reversed interest + if ( PositiveCharacs[rCharac] ) + factor = actualLevel; + else + factor = (nbInterestLevels - 1) - actualLevel; + + // Get a peak value? + bool isPeak = false; + if ( peakOccurRatio != 0.0f) + { + float peakDice = frand( 1.0f / peakOccurRatio ); + isPeak = (peakDice < 1.0f); + if ( isPeak ) + rPeak = rCharac; + } + + // Force a value higher than min? (if higher_or_eq than average, or if reversed interest) + bool greaterThanMin = (actualLevel > nbInterestLevels/2) || (!PositiveCharacs[rCharac]); + + // Calculate min and max + float minValue; + float maxValue = isPeak ? PeakCharacValues[rCharac] : MaxCharacValues[rCharac]; + if ( greaterThanMin ) + { + minValue = MinCharacValues[rCharac]; + maxValue -= minValue; + } + + // Calculate value + float normalSlice = maxValue / (float)nbInterestLevels; + float enlargedSlice = normalSlice * widthRatio; + float baseOfSlice = max( 0.0f, (((float)factor) * normalSlice) + (normalSlice-enlargedSlice)/2.0f ) + baseBoost; + float value = min( baseOfSlice + frand( enlargedSlice ), maxValue ); + //nldebug( "%d/%d range=%.1f slice=%.1f enlarged=%.1f base=%.1f value=%.1f", factor, nbInterestLevels, maxValue, normalSlice, enlargedSlice, baseOfSlice, value ); + if ( greaterThanMin ) + { + value += minValue; + } + + // Prevent to get a null durability + if ( rCharac == Durability ) + if ( value < 1.0f ) + value = 1.0f; + + Values[rCharac] = value; + //nldebug( "%s: %s (level %s)", sCharacs[rCharac], isPeak?"PEAK":"normal", + // PositiveCharacs[rCharac] ? sInterestLevels[level] : sInterestLevels[(NbFaberInterestLevels - 1) - level] ); + } + } + } + + calcQualitativeValues(); + //nldebug( "%s (IL=%u)", CraftParts[FaberElement].Name.c_str(), interestLevel ); + + /*// Display only "best" + if ( interestLevel == nbInterestLevels-1 ) + nldebug( " %s %s Durability=%g Weight=%g, DMG=%g, Speed=%g, SapLoad=%g, Range=%g%s", + faberElems[FaberElement].c_str(), sNomenclaturedInterestLevels[getNomenclaturedInterestLevel( interestLevel, nbInterestLevels )], + Values[Durability], Values[Weight], Values[DMG], Values[Speed], Values[SapLoad], Values[Range], + (rPeak!=~0) ? toString( " (PEAK for %s)", sCharacs[rPeak] ).c_str() : "" );*/ + + return true; +} +#endif + + +/* + * Returns false if the RM must NOT be generated. + */ +sint32 CFaberCharacteristics::computeValues( TStatQuality statQuality, const TFamInfo& famInfo, sint remarkableIndicesSetBaseIndex, + TEcosystem iEcosystem, uint iFreq, uint iFamily ) +{ + nlassert( FaberElement != ~0 ); + nlassert( statQuality != NAInterestLevel ); + + // Special case (jewels) + if ( FaberElement == ITEM_PART_JEWEL_GEM ) + { + computeJewelProtection( statQuality, iEcosystem, iFamily ); + } + + // First set all stats to the medium value for the required quality + static float MediumStatsByStatQuality [NbStatQualities] = { 20.0f, 35.0f, 50.0f, 65.0f, 80.0f }; + float statEnergyAvg = MediumStatsByStatQuality[statQuality]; + for ( uint rCharac=0; rCharac!=NbCharacs; ++rCharac ) + { + if ( CharacSlotFilter[rCharac][FaberElement] ) + Values[rCharac] = statEnergyAvg; + } + + // Special case for RM with no boost or lowering + if ( remarkableIndicesSetBaseIndex == -1 ) + return (sint32)statEnergyAvg; + + // Calculate the number of characs in filtered list + /*uint nbFilteredCharacs = 0; + for ( uint rCharac=0; rCharac!=NbCharacs; ++rCharac ) + { + if ( CharacSlotFilter[rCharac][FaberElement] ) + ++nbFilteredCharacs; + }*/ + + vector RemarkableByCharac( NbCharacs, false ); + + // Boost one stat up (+40) + float remaining = 0; + /*Obsolete: remarkable indices were relative marked characs, not to the whole charac set + uint rBestCharac = ~0; + uint indexOfRemarkableCharacInFiltered = famInfo.RemarkableStatIndex[remarkableIndicesSetBaseIndex+RBest] % nbFilteredCharacs; + sint indexOfCharacInFiltered = -1; + for ( uint rCharac=0; rCharac!=NbCharacs; ++rCharac ) + { + if ( CharacSlotFilter[rCharac][FaberElement] ) + ++indexOfCharacInFiltered; + if ( indexOfCharacInFiltered = indexOfRemarkableCharacInFiltered ) + { + RemarkableByCharac[rCharac] = true; + rBestCharac = rCharac; + Values[rCharac] += 40.0f; + if ( Values[rCharac] > 100.0f ) + remaining = Values[rCharac] - 100.0f; + } + } + nlassert( rBestCharac != ~0 ); // we should have found the best index + */ + uint rBestCharac = famInfo.RemarkableStatIndex[remarkableIndicesSetBaseIndex+RBest]; + RemarkableByCharac[rBestCharac] = true; + Values[rBestCharac] += 40.0f; + + // Lower two stats (-20, -20) + for ( uint i=RWorst1; i<=RWorst2; ++i ) + { + if ( famInfo.RemarkableStatIndex[remarkableIndicesSetBaseIndex+i] == -1 ) + { + // Case (+20, -20) instead of (+40, -20, -20) because only two characs in filtered list + nlassert( i==RWorst2 ); + Values[rBestCharac] -= 20.0f; // +40 already applied + break; // -20 already applied when i==Worst1 + } + + /*indexOfRemarkableCharacInFiltered = famInfo.RemarkableStatIndex[remarkableIndicesSetBaseIndex+i] % nbFilteredCharacs; + indexOfCharacInFiltered = -1; + for ( uint rCharac=0; rCharac!=NbCharacs; ++rCharac ) + { + if ( CharacSlotFilter[rCharac][FaberElement] ) + ++indexOfCharacInFiltered; + if ( indexOfCharacInFiltered = indexOfRemarkableCharacInFiltered ) + { + if ( RemarkableByCharac[rCharac] ) + nlerror( "Twice the same remarkable charac" ); + RemarkableByCharac[rCharac] = true; + Values[rCharac] -= 20.0f; + nlassert( ! (Values[rCharac] < 0) ); + } + }*/ + uint rCharac = famInfo.RemarkableStatIndex[remarkableIndicesSetBaseIndex+i]; + if ( RemarkableByCharac[rCharac] ) + nlerror( "Twice the same remarkable charac" ); + RemarkableByCharac[rCharac] = true; + Values[rCharac] -= 20.0f; + if ( (Values[rCharac] < 1.0f) && (rCharac == Durability) ) + Values[rCharac] = 1.0f; // prevent from having a null durability (= no item part) + nlassert( ! (Values[rCharac] < 0) ); + } + + // Clamp max of Best charac (after lowering, because it can modify the Best charac) + if ( Values[rBestCharac] > 100.0f ) + { + remaining = Values[rBestCharac] - 100.0f; + Values[rBestCharac] = 100.0f; + } + + // Raise other with optional remaining (divided by the number to raise) + if ( remaining > 0 ) + { + float nbToRaise = 0; + for ( uint rCharac=0; rCharac!=NbCharacs; ++rCharac ) + { + if ( CharacSlotFilter[rCharac][FaberElement] && (!RemarkableByCharac[rCharac]) ) + ++nbToRaise; + } + nlassert( nbToRaise != 0 ); + float remainingSlice = remaining / nbToRaise; + for ( uint rCharac=0; rCharac!=NbCharacs; ++rCharac ) + { + if ( CharacSlotFilter[rCharac][FaberElement] && (!RemarkableByCharac[rCharac]) ) + { + Values[rCharac] += remainingSlice; + } + } + } + + return (sint32)statEnergyAvg; +} + + +//// DISABLED +#if 0 +/* + * Returns false if the RM must NOT be generated. + */ +bool CFaberCharacteristics::randomizeJewelProtection( TStatQuality statQuality, TEcosystem iEcosystem, uint iFreq, uint iFamily ) +{ + PROTECTION_TYPE::TProtectionType protectionType; + + // Test if the family-ecosystem already has a jewel protection type + string feKey = familyCodes[iFamily] + ecosystemCodes[iEcosystem]; + CProtectionTypeMap::iterator it = JewelProtectionTypeByFamilyEcosystem.find( feKey ); + if ( it != JewelProtectionTypeByFamilyEcosystem.end() ) + { + protectionType = (*it).second; + } + else + { + /*if ( iFreq > 2 ) // 100% of "freq>=3" RM + { + protectionType = PROTECTION_TYPE::None; + } + else if ( iFreq > 1 ) + { + uint iRandomPercent = getRandomValue( 100 ); + if ( iRandomPercent < 50 ) // 50% of "freq 2" RM + { + protectionType = PROTECTION_TYPE::None; + } + else // 50% of "freq 2" RM + { + uint iProType = getRandomValue( 3 ); + protectionType = (PROTECTION_TYPE::TProtectionType)(PROTECTION_TYPE::Cold + iProType); + } + }*/ + if ( iEcosystem == CommonEcosystem ) + { + uint iRandomPercent = getRandomValue( 100 ); + if ( iRandomPercent < 50 ) // 50% of "freq 2" RM + { + protectionType = PROTECTION_TYPE::None; + } + else // 50% of "freq 2" RM + { + uint iProType = getRandomValue( 3 ); + protectionType = (PROTECTION_TYPE::TProtectionType)(PROTECTION_TYPE::Cold + iProType); + } + } + else + { + // Get the civ speciality corresponding to the rm family (if any) + /*const TFamInfo& rmFamily = FamSet[families[iFamily]]; + TCiv civ = AllCiv; //nlinfo( "%s %u", rmFamily.CompatibleCraftParts.c_str(), rmFamily.Properties.size() ); + uint iP = rmFamily.getPropIndexByCraftPart( 'A' + (char)ITEM_PART_JEWEL_GEM ); + if ( iP != ~0 ) + civ = rmFamily.Civs[iP];*/ + + // Ensure there is one speciality protection type per civ + TCiv civ = EcosystemToCiv[iEcosystem]; + if ( /*(civ != AllCiv)*/ (iEcosystem >= Desert) && (iEcosystem <= Jungle) && (!HasSpecializedJewelProtectionTypeByCiv[civ]) ) + { + switch ( /*civ*/iEcosystem ) + { + case /*Fyros*/Desert: protectionType = PROTECTION_TYPE::Fire; break; + case /*Matis*/Forest: protectionType = PROTECTION_TYPE::Poison; break; + case /*Tryker*/Lacustre: protectionType = PROTECTION_TYPE::Shockwave; break; + case /*Zorai*/Jungle: protectionType = PROTECTION_TYPE::Electricity; break; + } + HasSpecializedJewelProtectionTypeByCiv[civ] = true; + } + else + { + uint iProType; + // Ensure all values are used + do + { + iProType = getRandomValue( PROTECTION_TYPE::None-PROTECTION_TYPE::Madness ); + protectionType = (PROTECTION_TYPE::TProtectionType)(PROTECTION_TYPE::Madness + iProType); + } + while ( (midProtectionTypesUsed.size() < PROTECTION_TYPE::None-PROTECTION_TYPE::Madness) + && midProtectionTypesUsed.find( protectionType ) != midProtectionTypesUsed.end() ); + midProtectionTypesUsed.insert( protectionType ); + } + } + JewelProtectionTypeByFamilyEcosystem.insert( make_pair( feKey, protectionType ) ); + } + + // Disable the protection if the interest level does not match the protection type (cold-rot always, madness-mm from C, fire-electric from E) + /*if ( protectionType >= PROTECTION_TYPE::Madness ) + { + if ( statQuality == Basic ) // reject Basic + { + protectionType = PROTECTION_TYPE::None; + //return false; // do not suppress the RM as it can be used for another item part + } + } + else if ( protectionType >= PROTECTION_TYPE::Fire ) + { + if ( statQuality < Choice ) // reject Basic, Fine + { + protectionType = PROTECTION_TYPE::None; + //return false; + } + }*/ + + Values[JewelProtection] = (float)(uint)protectionType; + return true; +} +#endif + + +/* + * + */ +void CFaberCharacteristics::computeJewelProtection( TStatQuality statQuality, TEcosystem iEcosystem, uint iFamily ) +{ + TFamInfo& famInfo = FamSet[families[iFamily]]; + if ( famInfo.JewelProtIndex == -1 ) + { + Values[JewelProtection] = (float)PROTECTION_TYPE::None; + } + else + { + uint protIndex = (uint)famInfo.JewelProtIndex; + if ( protIndex < PROTECTION_TYPE::Fire ) + { + Values[JewelProtection] = (statQuality >= Fine) ? (float)(PROTECTION_TYPE::TProtectionType)protIndex : (float)PROTECTION_TYPE::None; + } + else if ( protIndex == PROTECTION_TYPE::Fire ) + { + static const PROTECTION_TYPE::TProtectionType EcosystemToProtectionType[NbEcosystems] = { + PROTECTION_TYPE::None, // Common + PROTECTION_TYPE::Fire, // Desert (Fyros) + PROTECTION_TYPE::Poison, // Forest (Matis) + PROTECTION_TYPE::Shockwave, // Lacustre (Tryker) + PROTECTION_TYPE::Electricity, // Jungle (Zorai) + PROTECTION_TYPE::Fear // Primeroot + }; + Values[JewelProtection] = (statQuality >= Choice) ? (float)EcosystemToProtectionType[iEcosystem] : (float)PROTECTION_TYPE::None; + } + else if ( protIndex >= PROTECTION_TYPE::Madness ) + { + Values[JewelProtection] = (statQuality >= Choice) ? (float)(PROTECTION_TYPE::TProtectionType)protIndex : (float)PROTECTION_TYPE::None; + } + } +} + + +/* + * Reject a prop if any of the previous props are in its incompatibility list + * (assumes the incompatibity lists are filled for every property) + */ +bool passPropSetFilter( const vector& iPropertyRelatedProperties, uint32 *iProperties, sint rCurrentProp, uint32 iProp ) +{ + for ( sint r=0; r!=rCurrentProp; ++r ) + { + if ( ! passNegativeFilter( iPropertyRelatedProperties, iProperties[r] ) ) + return false; + } + return true; +} + + +/* + * Reject a faber element if it is NOT in the compatibility list + */ +bool passFaberElementFilter( const vector& iCompatibleFaberElements, uint32 rFaberElement ) +{ + return passPositiveFilter( iCompatibleFaberElements, rFaberElement ); +} + +/* + * Reject a color if it is in the incompatibility list of a family + */ +/*bool passColorFilter( const vector& iFamilyRelatedColors, uint32 iColor ) +{ + return passPositiveFilter( iFamilyRelatedColors, iColor ); +}*/ + + +/* + * + */ +void setCustomizedPropertyValues( UFormElm& node, const CSString& sheetFilename ) +{ + CRulesStr2Filter::const_iterator icp = CustomizedPropertiesSheetName.find( sheetFilename ); + if ( icp != CustomizedPropertiesSheetName.end() ) + { + uint nbCustomProps = 0; + for ( vs::const_iterator ip=(*icp).second.begin(); ip!=(*icp).second.end(); ++ip ) + { + CSString propName = *ip; + ++ip; + if ( ip == (*icp).second.end() ) + { + nlwarning( "Malformed CustomizedProperties line" ); + break; + } + CSString value = *ip; + node.setValueByName( value.c_str(), propName.c_str() ); + ++nbCustomProps; + } + nldebug( "%s has %u customized properties", sheetFilename.c_str(), nbCustomProps ); + } +} + + +/* + * + */ +void randomizeProperties( uint32 *iProperties, uint32 iFamily, uint32 iEcosystem, uint32 &nbRejectedProperties ) +{ + nlerror( "TODO" ); +#if 0 + sint rProperty; // property rank + // Randomize properties + for ( rProperty=0; rProperty!=NbPropertySlots; ++rProperty ) + { + uint32 iProp, nbTries = 0; + + // Get random value and apply property rules filters + do + { + if ( nbTries != 0 ) // debug display + { + //nldebug( "Rejected property %s in family %s with", properties[iProp].c_str(), families[iFamily].c_str() ); + //for ( sint r=0; r!=rProperty; ++r ) + // DebugLog->displayRaw( "%s ", properties[iProperties[r]].c_str() ); + //DebugLog->displayRawNL( "" ); + } + iProp = getRandomValue( properties.size() ); + ++nbTries; + } + while ( ! (passPropFamilyFilter( familyPropertyFilter[iFamily], iProp ) && + passPropSetFilter( propertySetFilter[iProp], iProperties, rProperty, iProp )) ); + nbRejectedProperties += nbTries - 1; + + // Remove redundancy (undefine if already set) + for ( sint r=0; r!=rProperty; ++r ) + { + if ( iProp == iProperties[r] ) + { + iProp = UndefinedProperty; + break; + } + } + + iProperties[rProperty] = iProp; + } + + // Move undefined properties at the back + sint lastPropertySlot = NbPropertySlots-1; + for ( rProperty=lastPropertySlot-1; rProperty>=0; --rProperty ) + { + if ( iProperties[rProperty] == UndefinedProperty ) + { + sint lastUsedPropertySlot = getLastUsedPropertySlot( iProperties, lastPropertySlot, UndefinedProperty ); + if ( lastUsedPropertySlot == -1 ) + { + nlwarning( "No matching properties for %s %s", ecosystems[iEcosystem].c_str(), families[iFamily].c_str() ); + } + if ( lastUsedPropertySlot > rProperty ) + { + uint32 itmp = iProperties[lastUsedPropertySlot]; + iProperties[lastUsedPropertySlot] = iProperties[rProperty]; + iProperties[rProperty] = itmp; + } + } + } +#endif +} + + + + +/* + * Returns name in capitals, or an empty string if no match + */ +//string findRawMaterialFromCriteria( uint32 iEcosystem, uint32 iFamily, uint32 iCreature, TFaberInterestLevel actualLevel, char **errorReport ) +//{ +// vector *codes = NULL; +// bool found = false; +// +// if ( iCreature != ~0 ) +// { +// // 1. Match ecosystem and creature specialization +// RawMaterialRepository.getFaberCombinationCodes( iEcosystem, iFamily, iCreature, &codes ); +// if ( codes && (! codes->empty()) ) +// found = true; +// else +// { +// // 2. Match creature specialization in common ecosystem +// RawMaterialRepository.getFaberCombinationCodes( CommonEcosystem, iFamily, iCreature, &codes ); +// if ( codes && (! codes->empty()) ) +// found = true; +// } +// } +// if ( ! found ) +// { +// iCreature = ~0; +// +// // 3. Match ecosystem and common creature +// RawMaterialRepository.getFaberCombinationCodes( iEcosystem, iFamily, iCreature, &codes ); +// if ( codes && (! codes->empty()) ) +// found = true; +// else +// { +// // 4. Match common creature in common ecosystem +// RawMaterialRepository.getFaberCombinationCodes( CommonEcosystem, iFamily, iCreature, &codes ); +// if ( codes && (! codes->empty()) ) +// found = true; +// } +// } +// if ( ! found ) +// { +// *errorReport = "no compatible family"; +// return ""; +// } +// else +// { +// // Remap requested interest level if the material found is from common type +// if ( iCreature == ~0 ) +// { +// actualLevel = actualLevel * NbFaberInterestLevelsByEcosystem[CommonEcosystem] / NbFaberInterestLevelsByEcosystem[iEcosystem]; +// } +// +// // Discard faber codes that are higher than the requested level +// //nldebug( "Codes 1: %u", codes->size() ); +// vector matchingCodes; +// vector::iterator ic; +// for ( ic=codes->begin(); ic!=codes->end(); ++ic ) +// { +// if ( hasMatchingFaberLevel( (*ic).FirstLevel, actualLevel ) ) +// matchingCodes.push_back( &(*ic) ); +// } +// if ( matchingCodes.empty() ) +// { +// *errorReport = "no compatible level"; +// return ""; +// } +// //nldebug( "Codes 2: %u", matchingCodes.size() ); +// +// // Select best level matches +// keepOnlyHighestLevel( matchingCodes ); +// nldebug( "%s has %u matches", families[iFamily].c_str(), matchingCodes.size() ); +// +// // Choose one faber combination +// uint32 iComb = getRandomValue( matchingCodes.size() ); +// +// // Build string +// string crStr = (iCreature == ~0) ? CommonCreatureCode : creatureCodes[iCreature]; +// string ilStr = toString( "%02d", matchingCodes[iComb]->FirstLevel + 1 ); // 00 is NAInterestLevel; +// string faberStr( NB_FABERELEMS_CODE_CHARS, ' ' ); +// memcpy( &faberStr[0], matchingCodes[iComb]->Code.Ch, NB_FABERELEMS_CODE_CHARS ); +// string name = "m" + familyCodes[iFamily] + crStr + ecosystemCodes[iEcosystem] + ilStr + faberStr; +// strlwr( name ); +// //nlinfo( "%s", name.c_str() ); +// return name; +// } +//} + + +/* + * 1st arg: whichArray + * 2nd arg: col + * 3rd arg: iFamily + */ +typedef void (*TDispatchFunc) ( uint32, uint32, uint32 ); + + +/* + * Build SkgroupToModels and CreatureModels + */ +void deliverCreatureModels( vs& srcRow ) +{ + if ( ! srcRow[0].empty() ) + { + bool isModelRow = (srcRow.size()>2) && (srcRow[1]=="M"); + bool isNameRow = (srcRow.size()>2) && (srcRow[1]=="N"); + for ( uint32 c=2; c!=srcRow.size(); ++c ) + { + if ( ! srcRow[c].empty() ) + { + if ( isModelRow && (!srcRow[c].empty()) ) + { + // Models (ex: HD) + SkgroupToModels[srcRow[0]].push_back( srcRow[c] ); + nldebug( "Model: '%s' for %s (%u)", srcRow[c].c_str(), srcRow[0].c_str(), SkgroupToModels[srcRow[0]].size()-1 ); + } + else if ( isNameRow ) + { + // Creature names (by model) (assumes names are below filenames) + vs& modelsOfGroup = SkgroupToModels[srcRow[0]]; + uint32 skIndex = c - 3; // warning: beginning at column D + if ( skIndex < modelsOfGroup.size() ) + { + CreatureModels[modelsOfGroup[skIndex]].Name = srcRow[c]; + CSString abbrevName = makeAbbrevName( srcRow[c], CreatureModels ); + CreatureModels[modelsOfGroup[skIndex]].AbbrevName = abbrevName; + nldebug( "Name: %s '%s' %s", modelsOfGroup[skIndex].c_str(), srcRow[c].c_str(), abbrevName.c_str() ); + + } + else + nlwarning( "Can't set name %s for %s (%u)", srcRow[c].c_str(), srcRow[0].c_str(), skIndex ); + } + } + } + } +} + + +/* + * + */ +/*void deliverSkgroups( vs& srcRow ) +{ + if ( ! srcRow[0].empty() ) + { + for ( uint32 c=1; c!=srcRow.size(); ++c ) + { + if ( ! srcRow[c].empty() ) + { + if ( srcRow[c].findNS( ".skel" ) != string::npos ) + { + // Skeleton filenames + SkgroupToModels[srcRow[0]].push_back( srcRow[c] ); + nldebug( "Skeleton: '%s' for %s (%u)", srcRow[c].c_str(), srcRow[0].c_str(), SkgroupToModels[srcRow[0]].size()-1 ); + } + else + { + // Creature names (by skeleton) (assumes names are below filenames) + vs& skeletonsOfGroup = SkgroupToModels[srcRow[0]]; + uint32 skIndex = c - 3; // warning: beginning at column D + if ( skIndex < skeletonsOfGroup.size() ) + { + CreatureModels[skeletonsOfGroup[skIndex]].Name = srcRow[c]; + CSString abbrevName = makeAbbrevName( srcRow[c], CreatureModels ); + CreatureModels[skeletonsOfGroup[skIndex]].AbbrevName = abbrevName; + nldebug( "Name: %s '%s' %s", skeletonsOfGroup[skIndex].c_str(), srcRow[c].c_str(), abbrevName.c_str() ); + + } + else + nlwarning( "Can't set name %s for %s (%u)", srcRow[c].c_str(), srcRow[0].c_str(), skIndex ); + } + } + } + } +}*/ + +/* + * Build CreatureToModel (obsolete, used creature_skeletons.csv) + */ +/*void deliverSkeletons( vs& srcRow ) +{ + if ( (srcRow[0] != "FILE") && (srcRow.size()>1) && (!srcRow[1].empty()) ) + { + // Remove quotes + string::size_type p = 0; + while ( p < srcRow[1].size() ) + { + if ( srcRow[1][p] == '"' ) + srcRow[1].erase( p, 1 ); + else + ++p; + } + if ( ! srcRow[1].empty() ) + { + // Read mapping creature -> skeleton + CSkeletonMap::iterator ism = CreatureModels.find( srcRow[1] ); + if ( ism == CreatureModels.end() ) + nldebug( "%s", srcRow[1].c_str() ); + + if ( (srcRow[0].size() == 6) && (srcRow[0][0] == 'c') ) + { + TSkeletonInfo& skeInfo = CreatureModels[srcRow[1]]; + CSString creaModel = srcRow[0].left( 5 ); + CreatureFamilyIndices[creaModel] = vu(); + skeInfo.IsUsed = true; + skeInfo.CreaturesOfSke.push_back( srcRow[0] ); + CreatureToModel[creaModel] = srcRow[1]; + //nlinfo( "Selecting %s (%s)", srcRow[1].c_str(), creaModel.c_str() ); + } + else + { + //nlinfo( "Discarding %s", srcRow[1].c_str() ); + CreatureModels.insert( make_pair( srcRow[1], TSkeletonInfo() ) ); + } + } + } +}*/ + + +/* + * + */ +/*void dispatchToCreatures( uint32, uint32 col, uint32 iFamily ) +{ + nlassert( ! skeletonGroupColumns.empty() ); // missing SkeletonGroup line? + CSString& skegrp = skeletonGroupColumns[col]; + vs& skeletons = SkgroupToModels[skegrp]; + if ( skeletons.empty() ) + nlwarning( "No skeleton found for group '%s'", skegrp.c_str() ); + for ( vs::const_iterator isk=skeletons.begin(); isk!=skeletons.end(); ++isk ) + { + const CSString& ske = *isk; + CreatureModels[ske].SkGroup = skegrp; + nldebug( "%u: %s -> %s", col, skegrp.c_str(), ske.c_str() ); + + vs& creatures = CreatureModels[ske].CreaturesOfSke; + for ( vs::const_iterator ic=creatures.begin(); ic!=creatures.end(); ++ic ) + { + const CSString& creaCode = *ic; + if ( (creaCode.size() == 6) && (creaCode[0] == 'c') && (creaCode[5]>='0') && (creaCode[5]<='5') ) + { + CSString creaModel = creaCode.rightCrop( 1 ); // don't use local level + vu& familiesForCreature = CreatureFamilyIndices[creaModel]; + if ( find( familiesForCreature.begin(), familiesForCreature.end(), iFamily ) == familiesForCreature.end() ) + { + familiesForCreature.push_back( iFamily ); + if ( ! CreatureModels[ske].IsUsed ) + nldebug( "Now %s used", ske.c_str() ); + CreatureModels[ske].IsUsed = true; + CreatureToModel[creaModel] = ske; + //nldebug( "%s -> %s %s %s", creaModel.left( 3 ).c_str(), CreatureModels[ske].Name.c_str(), CreatureModels[ske].AbbrevName.c_str(), ske.c_str() ); + } + } + } + } +}*/ + + +/* + * + */ +/*void deliverCreatures( vs& srcRow ) +{ + if ( srcRow[0] == "SkeletonGroup" ) + { + srcRow[0] = srcRow[0].strip(); + skeletonGroupColumns.push_back( "" ); // column 0 + for ( uint32 c=1; c!=srcRow.size(); ++c ) + { + if ( ! srcRow[c].empty() ) + { + // Set new value in column list + skeletonGroupColumns.push_back( srcRow[c] ); + } + else + { + // Copy last value in column list + if ( ! skeletonGroupColumns.empty() ) + skeletonGroupColumns.push_back( skeletonGroupColumns.back() ); + } + } + nldebug( "%u skeleton group columns", skeletonGroupColumns.size() ); + } +}*/ + + +/* + * + */ +void deliverItemPartParams( vs& srcRow ) +{ + const uint itemPartCol = 0; // 1 from base 1 + const uint legendCol = 6; + const uint firstCharacCol = 7; // 8 from base 1 + + if ( srcRow.size() < legendCol+1 ) + return; + + // Read item part index + uint rItemPart = ~0; + if ( ! srcRow[itemPartCol].empty() ) + rItemPart = (uint)(srcRow[itemPartCol][0] - 'A'); + + // Select item part compatibility or charac bound + uint characParam = ~0; + if ( srcRow[legendCol].empty() ) + { + if ( rItemPart != ~0 ) + { + if ( srcRow.size() < firstCharacCol+1 ) + { + nlwarning( "Can't find compatibility for craft characs of item parts %s", srcRow[itemPartCol].c_str() ); + return; + } + + characParam = 0; + nldebug( "Loading compability for craft characs of item part %s", srcRow[itemPartCol].c_str() ); + if ( ! CraftParts.isEnabled( rItemPart ) ) + nlinfo( "Item part %s was absent from rm_fam_prop.csv (disabled)", srcRow[itemPartCol].c_str() ); + } + else + { + return; + } + } + else if ( srcRow[legendCol] == "Positive" ) + { + characParam = 1; + nldebug( "Loading calc way for craft characs" ); + } + else if ( srcRow[legendCol] == "Min" ) + { + characParam = 2; + nldebug( "Loading min bounds for craft characs" ); + } + else if ( srcRow[legendCol] == "Max" ) + { + characParam = 3; + nldebug( "Loading max bounds for craft characs" ); + } + else if ( srcRow[legendCol] == "Peak" ) + { + characParam = 4; + nldebug( "Loading peak bounds for craft characs" ); + } + else + { + nlwarning( "Unknown legend for item part charac: %s", srcRow[legendCol].c_str() ); + return; + } + + // Read item part compatibility or charac bounds + for ( uint c=firstCharacCol; cgetRootNode() ); + form->getRootNode().setValueByName( ecosystems[iEcosystem].c_str(), "mp.Ecosystem" ); + form->getRootNode().setValueByName( "raw material (mp)", "basics.family" ); + form->getRootNode().setValueByName( (sint32)99, "basics.stackable" ); + form->getRootNode().setValueByName( "Faber", "mp.Category" ); + CIconInfo& iconInfo = Icons[ecosystems[iEcosystem]]; + if ( ! iconInfo.IconBackground.empty() ) + form->getRootNode().setValueByName( iconInfo.IconBackground.c_str(), "3d.icon background" ); + else + nlwarning( "Can't find icon background for ecosystem %s", ecosystems[iEcosystem].c_str() ); + + CSString ecoParentName = getEcoParentName( iEcosystem ); + + setCustomizedPropertyValues( form->getRootNode(), ecoParentName ); + + // Don't save in ecosystem directory but in parent dir + flushSheetToDisk( rawMaterialPath + "_parent/" + ecoParentName, form ); +} + + +// _m + 2 chars +CSString getFamParentName( uint32 iFamily ) +{ + return CSString("_m") + familyCodes[iFamily] + "." + rmSheetType; +} + +/* + * + */ +void writeParentSheetFam( CForm *form, uint32 iFamily ) +{ + const TFamInfo& famInfo = FamSet[families[iFamily]]; + if ( ! famInfo.IsActive ) + return; + + // Family + clearSheet( form, &form->getRootNode() ); + form->getRootNode().setValueByName( families[iFamily].c_str(), "mp.Family" ); + + // Group + if ( famInfo.Group != ~0 ) + form->getRootNode().setValueByName( groups[famInfo.Group].c_str(), "mp.Group" ); + + // Icons + CIconInfo& iconInfo = Icons[families[iFamily]]; + if ( ! iconInfo.Icon.empty() ) + form->getRootNode().setValueByName( iconInfo.Icon.c_str(), "3d.icon" ); + else + { + nlwarning( "Can't find icon for family %s", families[iFamily].c_str() ); + /*CIconInfo& iconInfo2 = Icons["Unknown"]; + if ( ! iconInfo2.Icon.empty() ) + form->getRootNode().setValueByName( iconInfo2.Icon.c_str(), "3d.icon" ); + else + nlwarning( "Can't find ricon for default background (Unknown)" );*/ + } + + //form->getRootNode().setValueByName( "TODO", "mp.HarvestSkill" ); + CSString famParentName = getFamParentName( iFamily ); + + // New: abrevname even for raw materials from deposits + if ( ! famInfo.IsInCreatures ) + { + CSString& abbrevName = makeAbbrevName( families[iFamily] ); + if ( ! abbrevName.empty() ) + form->getRootNode().setValueByName( abbrevName.c_str(), "3d.text overlay" ); + } + + // Bulk + form->getRootNode().setValueByName( "0.5", "basics.Bulk" ); + + // Sellable? + form->getRootNode().setValueByName( (!famInfo.IsForMission) ? "true" : "false", "basics.Drop or Sell" ); + /*bool tmpTest; // check bool read/write + form->getRootNode().getValueByName( tmpTest, "basics.Drop or Sell" ); + nlassert( tmpTest == (!famInfo.IsForMission) );*/ + + setCustomizedPropertyValues( form->getRootNode(), famParentName ); + + // Don't save in ecosystem directory but in parent dir + flushSheetToDisk( rawMaterialPath + "_parent/" + famParentName, form ); +} + + +// _m + 3 chars +CSString getCreaParentName( const CSString& creaMainModel ) +{ + return CSString("_m") + creaMainModel + "." + rmSheetType; +} + +/* + * + */ +void writeParentSheetCreature( CForm *form, const CSString& creaModel ) +{ + // Write abbrev name + //nldebug( "%s %s %s %u", creaModel.c_str(), CreatureToModel[creaModel].c_str(), CreatureModels[CreatureToModel[creaModel]].SkGroup.c_str(), CreatureModels[CreatureToModel[creaModel]].CreaturesOfSke.size() ); + CSString& abbrevName = CreatureModels[creaModel].AbbrevName; + if ( ! abbrevName.empty() ) + form->getRootNode().setValueByName( abbrevName.c_str(), "3d.text overlay" ); + else + nlwarning( "Can't find abbrev name for %s", creaModel.c_str() ); + + CSString creaParentName = "_mc" + creaModel.toLower() + "." + rmSheetType; + + setCustomizedPropertyValues( form->getRootNode(), creaParentName ); + + // Save in base dir + flushSheetToDisk( rawMaterialPath + "_parent/" + creaParentName, form ); +} + + +/* + * + */ +bool CMainStat::updateCraftStatistics( uint32 rFaberElem, uint32 iEcosystem, uint32 iFam, TCiv civ ) +{ + ++NbRMByFaberElem[rFaberElem]; + ++NbRMByFaberElemByEcosystem[iEcosystem][rFaberElem]; + ++NbRMByFaberElemByFamilyAndCiv[iFam][civ][rFaberElem]; + return true; +} + + +/* + * Returns false if the RM must NOT be generated. + */ +bool CGenRawMaterial::computeCraftCharacs( uint iVariant, const CSString& sheetName ) +{ + /*CSString props; + for ( uint32 p=0; p!=RMProperties.size(); ++ p ) + props += " " + properties[RMProperties[p]]; + nldebug( "%s %s %s", locFam.c_str(), props.c_str(), (familyGroups[iFam]==~0) ? "-" : groups[familyGroups[iFam]].c_str() );*/ + + vector actualEnergies( NbFaberElements, 0.0f ); + vector sapLoads( NbFaberElements, 0.0f ); + TFamInfo& famInfo = FamSet[familyStr()]; + sint masterSumFreq = 0; + + // Compute craft scores + sint nbFaberElemsFilled = 0; + for ( uint32 rFaberElem=0; rFaberElem!=NbFaberElements; ++rFaberElem ) + { + // Exclude if in exclusion list + if ( hasCraftPart( rFaberElem ) ) + { + /*sint rarityModifier = 0; + float baseBoost = 0.0f; + + // For the PrimeRoots ecosystem, increase the stats and rarity + if ( IEcosystem == PrimeRoots ) + { + ++rarityModifier; + baseBoost = 10.0f; + }*/ + + /*// For raw materials specialized by civ matching the ecosystem, increase their craft stats + TCiv civ = getCivSpec( rFaberElem, famInfo ); + if ( civ != AllCiv ) + { + uint iCivEcosystem = getIndexFromString( string(CivEcosystemCodes[civ]), ecosystemCodes ); + if ( iCivEcosystem == IEcosystem ) + { + ++rarityModifier; + } + }*/ + + // For rare raw materials, increase their craft stats + sint sumFreq = 0; + for ( vu::iterator ivf=famInfo.Freqs.begin(); ivf!=famInfo.Freqs.end(); ++ivf ) + sumFreq += (sint)(*ivf); + sint avgFreq = sumFreq / (sint)famInfo.Freqs.size(); + /*avgFreq = max( avgFreq - rarityModifier, 0 ); + masterSumFreq += avgFreq; + float peakOccurRatio; + switch ( avgFreq ) + { + case 0: peakOccurRatio = 0.60f; break; // 60% + case 1: peakOccurRatio = 0.40f; break; // 40% + case 2: peakOccurRatio = 0.20f; break; // 20% + default: peakOccurRatio = 0.01f / (float)(avgFreq-2); // 3=1%, 4=0.5%, 5=0.33%... + }*/ + //float peakOccurRatio = 0.01f; + + // Compute scores (5 levels, width ratio=2 i.e. enlargedSlice=40%) + CFaberCharacteristics craftSlot; + craftSlot.initFaberElement( rFaberElem ); + // Now, the stat values are no more random (except special things such as jewels) + /*if ( ! craftSlot.randomizeValues( (TFaberInterestLevel)(StatQuality), 5, iVariant, 2.0f, peakOccurRatio, baseBoost, (TEcosystem)IEcosystem, avgFreq, IFamily ) ) + return false;*/ + sint remarkableIndicesSetBaseIndex = nbFaberElemsFilled * 3; + if ( avgFreq == 0 ) + remarkableIndicesSetBaseIndex = -1; // "Kitin Larva" : all at 80 + else + nlassert( nbFaberElemsFilled < 2 ); + sint32 newStatEnergy = craftSlot.computeValues( StatQuality, famInfo, remarkableIndicesSetBaseIndex, (TEcosystem)IEcosystem, avgFreq, IFamily ); + nlassert( (StatEnergyAvg == 0) || (newStatEnergy == StatEnergyAvg) || (newStatEnergy == -1) ); + if ( newStatEnergy == -1 ) + return false; + StatEnergyAvg = newStatEnergy; + RMCraftCharacs.push_back( craftSlot ); + actualEnergies[rFaberElem] = craftSlot.ActualEnergy; + sapLoads[rFaberElem] = craftSlot.Values[SapLoad]; + + ++nbFaberElemsFilled; + } + } + // For mission RMs, set statenergy as class + if ( nbFaberElemsFilled == 0 ) + { + uint zoneLevel = (uint)(sheetName[RM_INDEX_LEVELZONE_CODE]-'a'); + if ( zoneLevel == 0 ) + StatEnergyAvg = 20; + else + StatEnergyAvg = 20 + (zoneLevel-1)*15; + } + + // Compute rarity + sint masterAvgFreq; + if ( nbFaberElemsFilled == 0 ) + { + // TODO: When the RM is not craftable, the rarity (=> price) depends on the level + sint sumFreq = 0; + for ( vu::iterator ivf=famInfo.Freqs.begin(); ivf!=famInfo.Freqs.end(); ++ivf ) + sumFreq += (sint)(*ivf); + masterAvgFreq = sumFreq / (sint)famInfo.Freqs.size(); + } + else + { + // TODO: depend not only on freq but on ILevelZone or craft characteristics + masterAvgFreq = masterSumFreq / nbFaberElemsFilled; + } + /*switch ( masterAvgFreq ) + { + case 1 : Rarity = (IEcosystem==PrimeRoots? 80 : 67); break; // only PrimeRoots and one other ecosystem + case 2 : Rarity = 33; break; // Common + case 3 : Rarity = 67; break; // only one ecosystem + case 4 : Rarity = 1; break; // Goo + default: Rarity = 100; + }*/ + + // Compute property depths + IPropertyDepths.resize( famInfo.Properties.size() ); + for ( uint p=0; p!=famInfo.CraftPartsByProp.size(); ++p ) + { + // Calculate a single property depth using the actual energies of faber elements that use the property + uint32 nbFaberElemsThatUseTheProps = 0; + float sumActualEnergy = 0.0f; + for ( uint iCompatibleCP=famInfo.getBeginCraftPartForProp(p); iCompatibleCP!=famInfo.getEndCraftPartForProp(p); ++iCompatibleCP ) + { + uint rFaberElem = famInfo.getCompatibleCraftPart( iCompatibleCP ); + sumActualEnergy += actualEnergies[rFaberElem]; + ++nbFaberElemsThatUseTheProps; + } + float avgActualIEnergy = 0.0f; + if ( nbFaberElemsThatUseTheProps != 0 ) + avgActualIEnergy = sumActualEnergy / (float)nbFaberElemsThatUseTheProps; + if ( avgActualIEnergy < 0 ) + avgActualIEnergy = 0.0f; + uint32 iPropertyDepth = (uint32)(avgActualIEnergy*((float)(NbPropertyDepths - 1))) + 1; + if ( iPropertyDepth >= NbPropertyDepths ) + iPropertyDepth = NbPropertyDepths-1; + //nldebug( "Depth %s %s-%u: %s (%.2f)", properties[iProperty].c_str(), locFam.c_str(), iLevelZone, PropertyDepths[iPropertyDepth], avgActualInterest ); + nlassert( iPropertyDepth != 0 ); + IPropertyDepths[p] = iPropertyDepth; + } + + // Compute sap load estimation + /*float sumSapLoad = 0.0f; + uint32 nbSapLoads = 0; + for ( uint32 rFaberElem=0; rFaberElem!=NbFaberElements; ++rFaberElem ) + { + if ( hasCraftPart( rFaberElem ) ) + { + if ( sapLoads[rFaberElem] != 0.0f ) + { + sumSapLoad += sapLoads[rFaberElem]; + ++nbSapLoads; + } + } + } + if ( nbSapLoads != 0 ) + { + float avgSapLoad = sumSapLoad / nbSapLoads; + if ( avgSapLoad < 0 ) + avgSapLoad = 0.0f; + uint32 iSapLoadEst = (uint32)(avgSapLoad * 3.0f / MaxCharacValues[SapLoad]); + if ( iSapLoadEst > 2 ) + iSapLoadEst = 3; // peak + //nldebug( "Sap load est: %u", iSapLoadEst ); + SapLoadLevel = iSapLoadEst; + }*/ + + // Compute color + TColor CommonColors [4] = { Beige, Green, Turquoise, Violet }; + TColor RareColors [2] = { Red, Blue }; + TColor PrimerootColors [2] = { White, Black }; + if ( famInfo.IsForMission ) + { + Color = Beige; + } + else if ( famInfo.ColorIndex == -1 ) + { + nlwarning( "No color provided for family %s", familyStr().c_str() ); + Color = InvalidColor; + } + else + { + uint colorIndex = (uint)famInfo.ColorIndex; + if ( IEcosystem == PrimeRoots ) + Color = PrimerootColors[colorIndex % 2]; + else if ( StatQuality >= Choice ) + Color = RareColors[colorIndex % 2]; + else + Color = CommonColors[colorIndex % 4]; + } + + return true; +} + + +/* + * + */ +void CGenRawMaterial::collectStats( TRMItem& item, CMainStat& mainStats ) +{ + // Name & title + item.push( DtName, SheetName ); + item.push( DtTitle, Titles[SheetName] ); + + // Properties + for ( uint32 p=0; p!=/*min( NbPropertySlots,*/ (uint32)RMProperties.size()/*)*/; ++p ) + { + if ( RMProperties[p] != UndefinedProperty ) + { + ++mainStats.NbRMHavingProperty[ILocation][IEcosystem][RMProperties[p]]; + item.push( DtProp, propertyStr( p ) ); + } + } + + // Family + item.push( DtRMFamily, familyStr() ); + + // Group + item.push( DtGroup, groups[Group] ); + + // Ecosystem + item.push( DtEcosystem, ecosystemStr() ); + + TFamInfo& famInfo = FamSet[familyStr()]; + + // LevelZone (for creatures) + item.push( DtLevelZone, famInfo.IsForMission ? + toString( "%c", 'A' + (char)ILevelZone ) : + "-" ); + + // StatQuality + item.push( DtStatQuality, string( StatQualityStr[StatQuality] ) ); + + // Craft stats + vector actualInterests( NbFaberElements, 0.0f ); + vector sapLoads( NbFaberElements, 0.0f ); + for ( uint p=0; p!=famInfo.CraftPartsByProp.size(); ++p ) + { + for ( uint iCompatibleCP=famInfo.getBeginCraftPartForProp(p); iCompatibleCP!=famInfo.getEndCraftPartForProp(p); ++iCompatibleCP ) + { + uint rFaberElem = famInfo.getCompatibleCraftPart( iCompatibleCP ); + CFaberCharacteristics *craftSlot = getCraftSlot( rFaberElem ); + nlassert( craftSlot ); + + TCiv civ = getCivSpec( IEcosystem, StatQuality ); ////getCivSpec( rFaberElem, FamSet[familyStr()] ); + CSString civS = CivNames[civ]; + + item.push( DtCraftSlotName, getShortFaberElemString( rFaberElem ) ); + item.push( DtCraftCivSpec, civS ); + /*item.push( DtCraftSlotEnergy, toString( "%02u", (uint)(craftSlot->ActualEnergy*100.0f) ), true ); + item.push( DtCraftSlotOriginality, toString( "%03u", (uint)(craftSlot->ActualOriginality*100.0f) ), true );*/ + + mainStats.updateCraftStatistics( rFaberElem, IEcosystem, IFamily, famInfo.Civs[p] ); + } + } + + item.push( DtColor, colors[Color] ); + item.push( DtAverageEnergy, toString( "%d", StatEnergyAvg ) ); + + // Rarity + //item.push( DtRarity, toString( "%2u", Rarity ) ); + + // Max Quality + item.push( DtMaxLevel, toString( "%u", MaxLevel ) ); + + // Protection + CFaberCharacteristics *itemPart = getCraftSlot( ITEM_PART_JEWEL_GEM ); + if ( itemPart ) + item.push( DtJewelProtectionType, PROTECTION_TYPE::toString( (PROTECTION_TYPE::TProtectionType)(uint)itemPart->Values[JewelProtection] ) ); + + // Customized properties + CRulesStr2Filter::const_iterator icp = CustomizedPropertiesSheetName.find( SheetName + "." + rmSheetType ); + if ( icp != CustomizedPropertiesSheetName.end() ) + { + CSString line; + for ( vs::const_iterator ip=(*icp).second.begin(); ip!=(*icp).second.end(); ++ip ) + { + if ( ip != (*icp).second.begin() ) + line += "; "; + CSString propName = *ip; + ++ip; + if ( ip == (*icp).second.end() ) + break; + CSString value = *ip; + line += propName + "=" + value; + } + item.push( DtCustomizedProperties, line ); + } + + if ( GraphFile ) + { + fprintf( GraphFile, "%s;%s%u;%u;%u;%u;\n", SheetName.c_str(), ecosystems[IEcosystem].c_str(), StatQuality, StatEnergyAvg, (uint)(getOriginalityAvg()*100.0f), (uint)/*(getMainCivSpec( famInfo ))*/getCivSpec( IEcosystem, StatQuality )*4+100 ); + } + + mainStats.updateMainStats( RMCraftCharacs.size() ); +} + + +/* + * + */ +void CGenRawMaterial::writeSheet( CForm *form ) +{ + // Write properties (obsolete) + /*if ( RMProperties.size() > NbPropertySlots ) + nlwarning( "More properties than property slots (%s)", familyStr().c_str() ); + for ( uint32 p=0; p!=min( NbPropertySlots, (uint32)RMProperties.size()); ++p ) + { + if ( RMProperties[p] != UndefinedProperty ) + { + form->getRootNode().setValueByName( propertyStr( p ).c_str(), toString( "mp.Material property %d", p+1 ).c_str() ); + } + }*/ + + // Write color + /*vu& famColors = familyColorsFilter[iFam]; + if ( famColors.empty() ) + nlwarning( "No matching color for family %s", families[iFam].c_str() ); + else + { + uint32 iiColor = getRandomValue( famColors.size() ); + form->getRootNode().setValueByName( colors[famColors[iiColor]].c_str(), "mp.MpColor" ); + }*/ + if ( Color != InvalidColor ) + form->getRootNode().setValueByName( colors[Color].c_str(), "mp.MpColor" ); + + // Write icon overlay (TODO) + /*CSString& iconTextOver = Icons[locFam.splitTo('.')]; + if ( ! iconTextOver.empty() ) + form->getRootNode().setValueByName( iconTextOver.c_str(), "3d.icon text over" );*/ + + /*CSString props; + for ( uint32 p=0; p!=iProperties.size(); ++ p ) + props += " " + properties[iProperties[p]]; + nldebug( "%s %s %s", locFam.c_str(), props.c_str(), (familyGroups[iFam]==~0) ? "-" : groups[familyGroups[iFam]].c_str() );*/ + + vector actualInterests( NbFaberElements, 0.0f ); + vector sapLoads( NbFaberElements, 0.0f ); + + // Write craft stats + list::const_iterator ics; + for ( ics=RMCraftCharacs.begin(); ics!=RMCraftCharacs.end(); ++ics ) + { + const CFaberCharacteristics& craftSlot = (*ics); + const uint32& rFaberElem = craftSlot.FaberElement; + + for ( uint r=0; r!=NbCharacs; ++r ) + { + switch ( r ) + { + case JewelProtection: // see below + break; + case CraftCivSpec: + { + CSString civS; + TCiv civ = getCivSpec( IEcosystem, StatQuality ); //getCivSpec( rFaberElem, FamSet[familyStr()] ); + if ( civ == AllCiv ) + civS = "common"; //"Common_Species"; + else + civS = CivNames[civ]; + form->getRootNode().setValueByName( civS.toLower().c_str(), (CraftParts[rFaberElem].Path + ".CraftCivSpec").c_str() ); + } + break; + default: + { + //if ( craftSlot.Values[r] != 0.0f ) + if ( CharacSlotFilter[r][rFaberElem] ) + form->getRootNode().setValueByName( (sint32)(craftSlot.Values[r]), (CraftParts[rFaberElem].Path + "." + string(sCharacs[r])).c_str() ); + } + } + } + + // Write CraftEstimatedQuality (formerly known as property depths, I still use old property vector) + /*for ( uint32 p=0; p!=IPropertyDepths.size(); ++p ) + { + CSString itemPartAsPropS = propertyStr( p ); + if ( itemPartAsPropS.empty() ) + continue; + uint itemPartAsProp = itemPartAsPropS[0] - 'A'; + if ( itemPartAsProp == rFaberElem ) + { + form->getRootNode().setValueByName( propertyDepthStr( p ).c_str(), (CraftParts[rFaberElem].Path + ".CraftEstimatedQuality").c_str() ); + break; + } + }*/ + } + + // Jewel protection + CFaberCharacteristics *itemPart = getCraftSlot( ITEM_PART_JEWEL_GEM ); + if ( itemPart ) + form->getRootNode().setValueByName( PROTECTION_TYPE::toString( (PROTECTION_TYPE::TProtectionType)(uint)itemPart->Values[JewelProtection] ).c_str(), (CraftParts[ITEM_PART_JEWEL_GEM].Path + "." + string(sCharacs[JewelProtection])).c_str() ); + + // Write sap load estimation + /*if ( SapLoadLevel != ~0 ) + form->getRootNode().setValueByName( (uint32)SapLoadLevel, "mp.Sap load est" );*/ + + // Write rarity + //form->getRootNode().setValueByName( (uint32)Rarity, "mp.Rarity" ); + + // Write max quality + form->getRootNode().setValueByName( (uint32)MaxLevel, "mp.MaxQuality" ); + + // Write energy + form->getRootNode().setValueByName( StatEnergyAvg, "mp.StatEnergy" ); + + // Write customized properties + setCustomizedPropertyValues( form->getRootNode(), SheetName + "." + rmSheetType ); +} + + +/* + * + */ +/*string getPossibleAdjectivesFromSheetNameForDeposit( const CSString& sheetName ) +{ + uint iFamily = getIndexFromString( sheetName.substr( RM_INDEX_FAMILY_CODE, NB_FAMILY_CODE_CHARS ), familyCodes ); + + string locFam = packLocFamily( depositTypeLetters[iLoc], IFamily ); + //nlinfo( "%s", locFam.c_str() ); + RAdj = LocFamilyToAdjectives[locFam].find( adj.toUpper().c_str() ); +}*/ + + +/* + * + */ +void CGenRawMaterial::loadSheet( CForm *form, const std::string& sheetName, bool full ) +{ + SheetName = sheetName; + string value; + + if ( full ) + { + // Location + uint32 iLoc; + if ( SheetName[0] == 'c' ) + iLoc = InCreatures; + else + { + /*switch ( SheetName[2] ) + { + case 'u': iLoc = Under; break; + case 'o': iLoc = Over; break; + case 'f': iLoc = Flora; break; + default: nlstop; + }*/ + iLoc = InDeposits; + } + ILocation = iLoc; + + // Ecosystem + form->getRootNode().getValueByName( value, "mp.Ecosystem" ); + if ( ! value.empty() ) + IEcosystem = (TEcosystem)getIndexFromString( SheetName.substr( RM_INDEX_ECOSYSTEM_CODE, NB_ECOSYSTEM_CODE_CHARS ), ecosystemCodes ); // not using value because != label + + // Family + form->getRootNode().getValueByName( value, "mp.Family" ); + if ( ! value.empty() ) + IFamily = getIndexFromString( SheetName.substr( RM_INDEX_FAMILY_CODE, NB_FAMILY_CODE_CHARS ), familyCodes ); // not using value because != label + + fillPropertiesFromFamily(); + + // StatQuality + setStatQuality( SheetName[RM_INDEX_LEVELZONE_CODE] ); + } + + // Color + uint32 v; + form->getRootNode().getValueByName( v, "mp.MpColor" ); + Color = (TColor)v; + + // Craft stats + uint32 nbFaberElemsFilled = 0; + for ( uint32 rFaberElem=0; rFaberElem!=NbFaberElements; ++rFaberElem ) + { + sint32 val; + form->getRootNode().getValueByName( val, (CraftParts[rFaberElem].Path + ".Durability").c_str() ); + if ( val != 0 ) + { + CFaberCharacteristics craftSlot; + craftSlot.initFaberElement( rFaberElem ); + + for ( uint r=0; r!=NbCharacs; ++r ) + { + switch ( r ) + { + case JewelProtection: + { + if ( CharacSlotFilter[r][rFaberElem] ) + { + string proTypeS; + form->getRootNode().getValueByName( proTypeS, (CraftParts[rFaberElem].Path + "." + string(sCharacs[r])).c_str() ); + craftSlot.Values[r] = (float)(uint)PROTECTION_TYPE::fromString( proTypeS ); + } + else + craftSlot.Values[r] = 0.0f; + } + break; + case CraftCivSpec: + { + if ( CharacSlotFilter[r][rFaberElem] ) + { + string civS; + form->getRootNode().getValueByName( civS, (CraftParts[rFaberElem].Path + "." + string(sCharacs[r])).c_str() ); + TCiv civ = AllCiv; + if ( civS != "Common_Species" ) + for ( uint c=0; c!=NbCiv; ++c ) + if ( string(CivNames[c]) == civS ) + civ = (TCiv)c; + craftSlot.Values[r] = (float)(uint)civ; + } + } + break; + default: + { + form->getRootNode().getValueByName( val, (CraftParts[rFaberElem].Path + "." + string(sCharacs[r])).c_str() ); + craftSlot.Values[r] = (float)val; + } + } + } + + craftSlot.calcQualitativeValues(); + + RMCraftCharacs.push_back( craftSlot ); + + //nlinfo( "%s %s %s %s", item.Fields[DtName][0].c_str(), faberElems[rFaberElem].c_str(), families[iFam].c_str(), familyGroups[iFam]==~0?"":groups[familyGroups[iFam]].c_str() ); + } + else + { + if ( CheckDurability ) + { + // Check if Durability==0 is not a mistake + for ( uint r=0; r!=NbCharacs; ++r ) + { + if ( r != JewelProtection && r!=CraftCivSpec ) + { + form->getRootNode().getValueByName( val, (CraftParts[rFaberElem].Path + "." + string(sCharacs[r])).c_str() ); + if ( val != 0 ) + { + nlwarning( "%s has a null durability for item part %c", sheetName.c_str(), (char)('A' + (char)rFaberElem) ); + break; + } + } + } + } + } + } + + /*// These properties are currently useless when reading (not used for doc) + // Write property depths + uint p = 0; + bool res = true; + while ( res ) + { + string valueStr; + res = form->getRootNode().getValueByName( valueStr, toString( "mp.Prop %u depth", p+1 ).c_str() ); + if ( res ) + IPropertyDepths.push_back( propertyDepthFromString( valueStr ) ); + ++p; + } + + // Sap load est + form->getRootNode().getValueByName( SapLoadLevel, "mp.Sap load est" ); + */ + + // Rarity + //form->getRootNode().getValueByName( Rarity, "mp.Rarity" ); + + // Max Quality + form->getRootNode().getValueByName( MaxLevel, "mp.MaxQuality" ); + + // Energy + form->getRootNode().getValueByName( StatEnergyAvg, "mp.StatEnergy" ); + + ++nbSheetsProcessed; +} + + +/* + * + */ +void writeRMSheetToDisk( CForm *form, const string& sheetName ) +{ + if ( ! EraseOldCreatureAssignments ) + { + flushSheetToDisk( rawMaterialPath + dirbase + sheetName + "." + rmSheetType, form ); + ++nbSheetsProcessed; + if ( inputSheetPathContent.find( sheetName ) == inputSheetPathContent.end() ) + ++nbNewSheetsGenerated; + } + if ( GetSelectionUntilLevel != ~0 ) + { + if ( (sheetName[5] - 'a') <= (sint)GetSelectionUntilLevel ) + InfoLog->displayRawNL( "SELECTION: %s", sheetName.c_str() ); + } +} + + +/* + * Write sheet, write stat + */ +void selectRawMaterial( CForm *form, CForm *ecoParentForm, CForm *famParentForm, CGenRawMaterial *rm ) +{ + // Clear sheet (otherwise the previous values would remain) + clearSheet( form, &form->getRootNode() ); + + // Link to the parent sheets (the form arguments are always the last parent forms but there aren't used by the func anyway) + form->insertParent( 0, getEcoParentName( rm->IEcosystem ).c_str(), ecoParentForm ); + form->insertParent( 1, getFamParentName( rm->IFamily ).c_str(), famParentForm ); + + // Write stats + TRMItem item; + rm->collectStats( item, MainStat ); + SortableData.addItem( item ); + + // Write to disk + rm->writeSheet( form ); + writeRMSheetToDisk( form, rm->SheetName ); +} + + +/* + * + */ +/*string findSubstitutionForDepositRM( const string& srcName, char adjCode ) +{ + //nldebug( "SRC: %s", srcName.c_str() ); + string substitution = srcName; + CRMData::CLookup::const_iterator ilk; + char decl; + for ( decl='a'; decl!='h'; ++decl ) // up to 7 declinaisons + { + substitution[3] = decl; + substitution[2] = srcName[2]; + substitution[8] = adjCode; + //nldebug( "TRYING %s", substitution.c_str() ); + ilk = SortableData.lookup( DtName ).find( substitution ); + if ( ilk != SortableData.lookup( DtName ).end() ) + return substitution; + + uint iLoc; + for ( iLoc=0; iLoc!=NB_DEPOSITS; ++iLoc ) + { + char locChar = tolower( depositTypeLetters[iLoc][0] ); + if ( locChar == srcName[2] ) + continue; + + substitution[2] = locChar; + //nldebug( "TRYING %s", substitution.c_str() ); + ilk = SortableData.lookup( DtName ).find( substitution ); + if ( ilk != SortableData.lookup( DtName ).end() ) + return substitution; + } + } + return string(); +}*/ + + +/* + * Result has at least one character + */ +inline CSString getCreatureEcosystemCode( uint itEcosystem ) +{ + switch ( itEcosystem ) + { + case Goo: return "g"; + case Invasion: return "i"; + case Raid: return "r"; + case Event: return "e"; + case N: return "n"; + case S: return "s"; + case T: return "t"; + case U: return "u"; + case V: return "v"; + case W: return "w"; + case X: return "x"; + case Y: return "y"; + case Z: return "z"; + default: return ecosystemCodes[itEcosystem]; + } +} + + +/* + * + */ +inline CSString getCreatureLZCode( const CSString& creaModel, uint itEcosystem, uint iZone ) +{ + nlassert( iZone < 10 ); + return string("c") + creaModel.toLower() + getCreatureEcosystemCode( itEcosystem ) + toString( "%c", (char)('a' + (char)iZone) ); +} + + +/* + * + */ +void loadConfigFile() +{ + // Load config file + try + { + CConfigFile configFile; + configFile.load( "raw_material_generation.cfg" ); + CConfigFile::CVar *var = configFile.getVarPtr( "RawMaterialPath" ); + if ( var ) rawMaterialPath = var->asString(); + var = configFile.getVarPtr( "CreatureSubPath" ); + if ( var ) + { + creaturePath = var->asString(); + if ( creaturePath[creaturePath.size()-1] != '/' ) + creaturePath += "/"; + } + var = configFile.getVarPtr( "CreatureAssignmentPath" ); + if ( var ) + { + creatureAssignmentPath = var->asString(); + if ( creatureAssignmentPath[creatureAssignmentPath.size()-1] != '/' ) + creatureAssignmentPath += "/"; + } + var = configFile.getVarPtr( "DepositSubPath" ); + if ( var ) + { + depositPath = var->asString(); + if ( depositPath[depositPath.size()-1] != '/' ) + depositPath += "/"; + } + + loadConfigFlag( configFile, "WriteSheetsToDisk", WriteSheetsToDisk ); + loadConfigFlag( configFile, "GenOnlyNewRawMaterials", GenOnlyNewRawMaterials ); + loadConfigFlag( configFile, "SkipRawMaterialsForCreatures", SkipRawMaterialsForCreatures ); + loadConfigFlag( configFile, "AssignRawMaterialsHarvestToCreatureSheets", AssignRawMaterialsHarvestToCreatureSheets ); + loadConfigFlag( configFile, "AssignOnlyToUnassignedCreatures", AssignOnlyToUnassignedCreatures ); + loadConfigFlag( configFile, "SkipRawMaterialsForDeposits", SkipRawMaterialsForDeposits ); + loadConfigFlag( configFile, "GenOnlyMissionRawMaterials", GenOnlyMissionRawMaterials ); + loadConfigFlag( configFile, "AssignRawMaterialsHarvestToDepositSheets", AssignRawMaterialsHarvestToDepositSheets ); + loadConfigFlag( configFile, "BrowseOtherDeposits", BrowseOtherDeposits ); + loadConfigFlag( configFile, "FixDeposits", FixDeposits ); + loadConfigFlag( configFile, "EraseOldCreatureAssignments", EraseOldCreatureAssignments ); + loadConfigFlag( configFile, "TestExistingAssigments", TestExistingAssigments ); + loadConfigFlag( configFile, "OutputNameList", OutputNameList ); + loadConfigFlag( configFile, "DisplayFamAndProp", DisplayFamAndProp ); + loadConfigFlag( configFile, "ProduceDoc", ProduceDoc ); + loadConfigFlag( configFile, "CheckDurability", CheckDurability ); + loadConfigFlag( configFile, "GenerateDepositSystemMpFiles", GenerateDepositSystemMpFiles ); + + var = configFile.getVarPtr( "ExistingRMAction" ); + if ( var ) ExistingRMAction = (TExistingRMAction)var->asInt(); + + var = configFile.getVarPtr( "GetSelectionUntilLevel" ); + if ( var ) GetSelectionUntilLevel = (uint32)var->asInt(); + + var = configFile.getVarPtr( "SortByOriginality" ); + if ( var ) SortByOriginality = ((uint32)var->asInt() == 1); + + var = configFile.getVarPtr( "MaxNbRMByFamilyEZ" ); + if ( var ) MaxNbRMByFamilyEZ = (uint32)var->asInt(); + + var = configFile.getVarPtr( "MaxNbRMByCraftSlotE" ); + if ( var ) MaxNbRMByCraftSlotE = (uint32)var->asInt(); + + //var = configFile.getVarPtr( "OriginalityMinThreshold" ); + //if ( var ) OriginalityMinThreshold = (uint32)var->asInt(); + + /*var = configFile.getVarPtr( "NbFaberCombinations" ); + if ( var ) NbFaberCombinations = var->asInt();*/ + + var = configFile.getVarPtr( "TranslationPath" ); + if ( var ) TranslationPath = var->asString(); + + var = configFile.getVarPtr( "SystemMPPath" ); + if ( var ) SystemMPPath = var->asString(); + + var = configFile.getVarPtr( "CustomizedProperties" ); + if ( var ) + { + for ( sint i=0; i!= var->size(); ++i ) + { + CSString sheetFilename = var->asString( i ); + ++i; + if ( i < var->size() ) + { + CSString propName = var->asString( i ); + ++i; + if ( i < var->size() ) + { + CSString value = var->asString( i ); + CustomizedPropertiesSheetName[sheetFilename].push_back( propName ); + CustomizedPropertiesSheetName[sheetFilename].push_back( value ); + } + } + } + } + } + catch ( EConfigFile& e ) + { + nlwarning( "%s - Press a key", e.what() ); + getch(); + } +} + + +/* + * + */ +void displayFamNames() +{ + ListLog.displayRawNL( "Family names for en.uxt:" ); + for ( uint i=0; i!=families.size(); ++i ) + { + if ( ! families[i].empty() ) + { + uint num = atoi( familyCodes[i].c_str() ); + ListLog.displayRawNL( "mpfam%u\t\t\t[%s]", num, families[i].c_str() ); + } + } + ListLog.displayRawNL( "Groups names for en.uxt:" ); + for ( uint i=0; i!=groups.size(); ++i ) + { + if ( ! groups[i].empty() ) + ListLog.displayRawNL( "mpgroup%u\t\t\t[%s]", i, groups[i].c_str() ); + } + ListLog.displayRawNL( "Groups by family:" ); + for ( uint i=0; i!=families.size(); ++i ) + { + if ( ! families[i].empty() ) + { + TFamInfo& famInfo = FamSet[families[i]]; + ListLog.displayRawNL( "%u\t%s", i, (famInfo.Group!=~0) ? groups[famInfo.Group].c_str() : "" ); + } + } + ListLog.displayRawNL( "Families by group:" ); + for ( uint i=0; i!=groups.size(); ++i ) + { + if ( ! groups[i].empty() ) + { + ListLog.displayRawNL( "Group:\t\t\t%s", groups[i].c_str() ); + for ( uint j=0; j!=families.size(); ++j ) + { + if ( FamSet[families[j]].Group == i ) + ListLog.displayRawNL( "Group:\t%u\t%u\t\t%s", i, j, families[j].c_str() ); + } + } + } + ListLog.displayRawNL( "Group icons for _ic_groups.forage_source" ); + ListLog.displayRawNL( " " ); + for ( uint i=0; i!=groups.size(); ++i ) + { + //if ( ! groups[i].empty() ) + ListLog.displayRawNL( " ", Icons[groups[i]].Icon.c_str() ); + } + ListLog.displayRawNL( " "); + ListLog.displayRawNL( "Family icons for _ic_families.forage_source" ); + ListLog.displayRawNL( " " ); + for ( uint i=0; i!=families.size(); ++i ) + { + //if ( ! families[i].empty() ) + ListLog.displayRawNL( " ", Icons[families[i]].Icon.c_str() ); + } + ListLog.displayRawNL( " "); +} + + +/* + * For deposit families only + */ +void generateSytemMpFiles() +{ + if ( ! GenerateDepositSystemMpFiles ) + return; + + string dir = SystemMPPath; + nlinfo( "Processing 'system mp' files for WorldEditor in %s...", dir.c_str() ); + + // Build the right list of files + vector systemMpFilenames; + systemMpFilenames.resize( families.size() ); + for ( uint i=0; i!=families.size(); ++i ) + { + if ( ! families[i].empty() ) + { + if ( FamSet[families[i]].IsInDeposits ) + systemMpFilenames[i] = conventionalDirectory( families[i] ) + toString( "_%u.mp", i ); + } + } + + // List and delete obsolete files + vector currentFiles; + CPath::getPathContent( dir, false, false, true, currentFiles ); + for ( uint i=0; i!=currentFiles.size(); ++i ) + { + string currentFile = CFile::getFilename( currentFiles[i] ); + if ( currentFile.find( ".mp" ) != string::npos ) + { + if ( find( systemMpFilenames.begin(), systemMpFilenames.end(), currentFile ) == systemMpFilenames.end() ) + { + nlinfo( "Deleting obsolete %s (PLEASE COMMIT)", currentFile.c_str() ); + if ( WriteSheetsToDisk ) + CFile::deleteFile( currentFiles[i] ); + } + } + } + + // Create new files + for ( uint i=0; i!=families.size(); ++i ) + { + if ( (! families[i].empty()) && (! systemMpFilenames[i].empty()) ) + { + // Check if file present ; if not, create it + if ( ! CFile::fileExists( dir + systemMpFilenames[i] ) ) + { + nlinfo( "Creating %s (PLEASE COMMIT)", systemMpFilenames[i].c_str() ); + if ( WriteSheetsToDisk ) + { + COFile f; + f.open( dir + systemMpFilenames[i], false, true ); + f.close(); + } + } + } + } +} + + +/* + * generateRawMaterials + */ +void generateRawMaterials() +{ + // Load config file + loadConfigFile(); + + // Load lists from DFNs + loadSheetPath(); + UFormLoader *formLoader = UFormLoader::createLoader (); + loadDFNs( formLoader ); + + // TEMP: remove all raw materials for creatures! + /*string dp = "r:/code/ryzom/data_leveldesign/leveldesign/game_element/sitem/raw_material/"; + string ecos [5] = { "desert", "forest", "jungle", "lacustre", "prime_roots" }; + vector thefiles [5]; + for ( uint i=0; i!=5; ++i ) + { + CPath::getPathContent( dp + ecos[i], false, false, true, thefiles[i] ); + nlinfo( "%u files in %s", thefiles[i].size(), (dp + ecos[i]).c_str() ); + } + map::iterator it; + for ( it=inputSheetPathContent.begin(); it!=inputSheetPathContent.end(); ++it ) + { + const string& s1 = (*it).first, s2 = (*it).second; + string::size_type p; + if ( (p = s2.find( "raw_material/_parent/_mc" )) != string::npos ) + { + string cc = s1.substr( 3, 2 ); + for ( uint i=0; i!=5; ++i ) + { + for ( vector::iterator its=thefiles[i].begin(); its!=thefiles[i].end(); ++its ) + { + string& fl = (*its); + string::size_type q; + if ( (q = fl.find( string( "c") + cc )) != string::npos ) + { + if ( (fl[q-1] >= '0') && (fl[q-1] <= '9') ) + { + nlinfo( "Deleting %s", fl.c_str() ); + CFile::deleteFile( fl ); + } + } + } + } + } + } + + return;*/ + + // Load families from CSV file + loadFamAndProp( "rm_fam_prop.csv", DisplayFamAndProp ); + if ( TFamInfo::UseGenerateOnly != 0 ) + nlinfo( "Requested to generate only %u marked RM families", TFamInfo::UseGenerateOnly ); + else + nlinfo( "Requested to generate all RM families" ); + + // Load template sheet for final and parent forms + NLMISC::CSmartPtr form = loadTemplateForm( formLoader, rmSheetType ); + NLMISC::CSmartPtr ecoParentForm = loadTemplateForm( formLoader, rmSheetType ); + NLMISC::CSmartPtr famParentForm = loadTemplateForm( formLoader, rmSheetType ); + + for ( uint r=0; r!=NbCharacs; ++r ) + CharacSlotFilter[r].resize( NbFaberElements ); + + // Load other CSV files + loadCSVFile( "rm_item_parts.csv", deliverItemPartParams ); + loadCSVFile( "creature_models.csv", deliverCreatureModels ); + //nlinfo( "Loaded %u creature categories", SkgroupToModels.size() ); + dispatchFamiliesToLocations(); + nlinfo( "%u creatures models selected", RMFamilyIndicesByCreatureModel.size() ); + nlinfo( "%u creature models used", checkSkeletons() ); + nlinfo( "%u icon lines loaded", Icons.size() ); + + // Summary + nlinfo( "%u families, %u ecosystems, %u properties, %u craft parts, %u colors", families.size(), ecosystems.size(), properties.size(), CraftParts.CraftParts.size(), colors.size() ); + + // Generate names(with nomenclature) + ListLog.addDisplayer( &ListDisplayer ); + familyCodes.resize( families.size() ); + ecosystemCodes.resize( ecosystems.size() ); + for_each( familyCodes.begin(), familyCodes.end(), normalizeFamilyCode ); + displayFamNames(); + generateSytemMpFiles(); + //buildNomenclatureCodes( "New families:", families, familyCodes, NB_FAMILY_CODE_CHARS ); // useless currently + buildNomenclatureCodes( NULL, ecosystems, ecosystemCodes, NB_ECOSYSTEM_CODE_CHARS ); + + // Load Unicode titles (can share the same hash map because codes are distinct) + loadTitles( "item", "work", "wk", Titles ); + loadTitles( "creature", "translated", "en", Titles ); + + createDirectoryStructure(); + MainStat.init(); + FILE *nameOutputFile; + if ( OutputNameList ) + nameOutputFile = fopen( "rm_names_output.csv", "wt" ); + GraphFile = fopen( "rm_output_graph.csv", "wt" ); + fprintf( GraphFile, "Graph type: Line with markers displayed at each data value, columns B to E. For deposits, sort by column B\n" ); + fprintf( GraphFile, "Ecosystem specialization: 100=Desert, 104=Forest, 108=Lake, 112=Jungle, 116=All\n" ); + fprintf( GraphFile, "RM code;Zone;Energy;Originality;Eco. spec.;\n\n" ); + SortableData.init( ProduceDoc ); + + // Generate random values + //RawMaterialRepository.resize( ecosystems.size(), families.size() ); + RandomGenerator.srand( (unsigned)time( NULL ) ); + + /* + * New raw materials + */ + if ( GenOnlyNewRawMaterials || AssignRawMaterialsHarvestToCreatureSheets || AssignRawMaterialsHarvestToDepositSheets || FixDeposits ) + { + // Parents + if ( ExistingRMAction == ModifyRM ) + { + for ( uint32 iEcosystem=0; iEcosystem!=ecosystems.size(); ++iEcosystem ) + { + // Parent item for ecosystem + clearSheet( ecoParentForm, &form->getRootNode() ); + writeParentSheetEco( ecoParentForm, iEcosystem ); + } + + for ( uint32 iFamily=0; iFamily!=families.size(); ++iFamily ) + { + if ( TFamInfo::mustGenerateFamily( iFamily ) ) + { + // Parent item for family + clearSheet( famParentForm, &form->getRootNode() ); + writeParentSheetFam( famParentForm, iFamily ); + } + } + } + + uint32 nbAssignedMaterials = 0, nbCreatureSheetsSkipped = 0, nbErasedCreatureAssignments = 0; + uint32 maxLastAssignedRMSlot = 0; + NLMISC::CSmartPtr creaParentForm; + NLMISC::CSmartPtr creaForm; + set creatureSheets; + + if ( SkipRawMaterialsForCreatures ) + goto processRawMaterialsForDeposits; + + // + // Iterate on creatures raw materials + // + for ( CRulesStrFilter::iterator icr=RMFamilyIndicesByCreatureModel.begin(); icr!=RMFamilyIndicesByCreatureModel.end(); ++icr ) + { + // HD + const CSString& creaModel = (*icr).first; + vu& familiesForCreatureModel = (*icr).second; + + // Parent item for creature (one per model) + CSString creaCMainModelCode = string("c") + creaModel.toLower(); // CHD + static float progress = 0.0f; + if ( familiesForCreatureModel.empty() ) + { + nlinfo( "No RM has been defined for non-goo %s (%s)", creaCMainModelCode.c_str(), CreatureModels[creaModel].Name.c_str() ); + CreatureMainModelsWithoutRM.insert( creaCMainModelCode ); + } + else + nlinfo( "%u RM for each variant of non-goo %s (%.1f%%)", familiesForCreatureModel.size(), creaModel.c_str(), 100.0f*progress/(float)RMFamilyIndicesByCreatureModel.size() ); + ++progress; + + // Write parent item sheet + if ( ExistingRMAction == ModifyRM ) + { + creaParentForm = loadTemplateForm( formLoader, rmSheetType ); + clearSheet( creaParentForm, &form->getRootNode() ); + writeParentSheetCreature( creaParentForm, creaModel ); + } + + // Iterate on ecosystems + for ( uint itEcosystemOfCreature=CommonEcosystem+1; itEcosystemOfCreature!=NbEcosystemsPlusExtensions; ++itEcosystemOfCreature ) + { + // CHDF + + for ( uint iZone=0; iZone!=10; ++iZone ) + { + uint iLevelZone = (iZone<=1) ? 0 : iZone-1; + + // CHDFA-CHDFJ + CSString creaLZCode = getCreatureLZCode( creaModel, itEcosystemOfCreature, iZone ); + + for ( uint32 iLocalLevel=1; iLocalLevel!=MAX_NB_LOCAL_LEVELS+1; ++iLocalLevel ) // warning: base 1 + { + // CHDFA1-CHDFA9 (only if creature sheet exists on disk) + TStatQuality statQuality = CreatureLocalLevelToStatQuality[iLocalLevel-1]; + + CSString creaSheetName = creaLZCode + toString("%u", iLocalLevel); + map::const_iterator ipc = inputSheetPathContent.find( creaSheetName ); + if ( ipc == inputSheetPathContent.end() ) + continue; + + if ( ((itEcosystemOfCreature != Goo) && familiesForCreatureModel.empty()) || + (statQuality == InvalidStatQuality) ) // mission creatures (*6.creature) have invalid StatQuality => no RMs (bugged: no parent created) + { + // Generate empty parent creature sheets if not existing yet + const CSString& creaPathAndFilename = creatureAssignmentPath + string("_") + creaSheetName + "_mp." + crSheetType; + map::const_iterator ipcp = inputSheetPathContent.find( creaSheetName + "_mp" /*+"." + crSheetType*/ ); + if ( ipc == inputSheetPathContent.end() ) + { + UForm *creaForm = formLoader->loadForm( (string("_empty.") + crSheetType).c_str() ); + flushSheetToDisk( creaPathAndFilename, creaForm ); + } + } + else + { + // Get the list of RM families for the current processed creature + vu familiesForThisCreature; + uint nbInvasionFamilies = 0; + switch ( itEcosystemOfCreature ) + { + case Goo: + familiesForThisCreature = GooCreatureFamilyIndices; + break; + case Invasion: + case Raid: + case Event: + case N: + case S: + case T: + case U: + case V: + case W: + case X: + case Y: + case Z: + { + // Special RMs for all invasion/raid creatures + vu& familiesForAllIRCreatures = InvasionRaidCreatureFamilyIndices['*']; + familiesForThisCreature.insert( familiesForThisCreature.end(), familiesForAllIRCreatures.begin(), familiesForAllIRCreatures.end() ); + nbInvasionFamilies += familiesForAllIRCreatures.size(); + + // Special RMs for this type of invasion/raid creature + char cd [2]; + cd[0] = creaLZCode[1]; + cd[1] = '\0'; + ::strlwr( cd ); + vu& familiesForThisTypeOfIRCreature = InvasionRaidCreatureFamilyIndices[cd[0]]; + familiesForThisCreature.insert( familiesForThisCreature.end(), familiesForThisTypeOfIRCreature.begin(), familiesForThisTypeOfIRCreature.end() ); + nbInvasionFamilies += familiesForThisTypeOfIRCreature.size(); + + // Normal craft RMs if sufficient level or event + if ( (iLocalLevel >= 5) || + ((itEcosystemOfCreature >= Event) && (itEcosystemOfCreature <= Z)) ) + { + familiesForThisCreature.insert( familiesForThisCreature.end(), familiesForCreatureModel.begin(), familiesForCreatureModel.end() ); + } + break; + } + default: + familiesForThisCreature = familiesForCreatureModel; + } + + // Iterate on corresponding families + for ( vu::iterator ifc=familiesForThisCreature.begin(); ifc!=familiesForThisCreature.end(); ++ifc ) + { + uint32 iFam = (*ifc); + if ( ! TFamInfo::mustGenerateFamily( iFam ) ) + continue; + + //nldebug( "%s - %u adj: %s", families[iFam].c_str(), adjsForFamily.size(), adjsForFamily.c_str() ); + // For creature, the ecosystems are already limited by which creature sheets exist + + bool isMissionRawMaterial = FamSet[families[iFam]].IsForMission; + if ( GenOnlyMissionRawMaterials && (! isMissionRawMaterial) ) + continue; + + bool isInvasionFamily = ((uint)(ifc-familiesForThisCreature.begin()) < nbInvasionFamilies); + CSString rmCodeMid; + uint iEcosystem = ~0; + switch ( itEcosystemOfCreature ) + { + case Goo: + rmCodeMid = toString( "cxxc%c", (char)('a' + (char)iZone) ); + iEcosystem = CommonEcosystem; + break; + case Invasion: + case Raid: + case Event: + case N: + case S: + case T: + case U: + case V: + case W: + case X: + case Y: + case Z: + if ( isInvasionFamily || // the special RMs for invasion creature (possibly with several variants) + ((iLocalLevel <= 4) && ((itEcosystemOfCreature == Invasion) || (itEcosystemOfCreature == Raid))) ) // invasion/raid creatures have normal RMs only for bosses (all event creatures have normal RMs) + { + // Special invasion RM + rmCodeMid = toString( "ixxcc" ); + iEcosystem = CommonEcosystem; + } + else + { + // No mission RM for named/bosses/mini-bosses + if ( isMissionRawMaterial ) + continue; + + // Ecosystem is always Common, because the ecosystem of the creature is Invasion or Raid + iEcosystem = CommonEcosystem; + CSString creaLZCodeCommon = getCreatureLZCode( creaModel, iEcosystem, iZone ); + rmCodeMid = creaLZCodeCommon.substr( 0, creaLZCode.size() - 1 ) + toString( "%c", (char)((char)'a'+(char)statQuality) ); + } + break; + default: + if ( isMissionRawMaterial ) + { + // No mission RM for named/bosses/mini-bosses + if ( iLocalLevel > 4 ) + continue; + + // Ecosystem is always specialized + iEcosystem = itEcosystemOfCreature; + + // Mission RMs range from quality a (plain, in newbieland only) to f (magnificient) + rmCodeMid = creaLZCode; + } + else + { + // Ecosystem-specialized from Choice quality + if ( (statQuality <= Fine) ) + iEcosystem = CommonEcosystem; + else + iEcosystem = itEcosystemOfCreature; + + // Now: for craft RMs, statquality is bound on local level instead of level zone + CSString creaLZCodeCommon = getCreatureLZCode( creaModel, iEcosystem, iZone ); + rmCodeMid = creaLZCodeCommon.substr( 0, creaLZCode.size() - 1 ) + toString( "%c", (char)((char)'a'+(char)statQuality) ); + } + } + dirbase = conventionalDirectory( ecosystems[iEcosystem] ) + "/"; + + // Iterate on variants (now: only one variant) + uint32 nbVariants = 1; + if ( (itEcosystemOfCreature == Invasion) || (itEcosystemOfCreature == Raid) ) + { + if ( (iLocalLevel == 6) || (iLocalLevel == 8) ) + nbVariants = 0; + else if ( iLocalLevel <= 4 ) + nbVariants = 1; + // for 5 & 7, two variants only for the boss kitin invasion RM (trophy) + else if ( isInvasionFamily && (creaLZCode[1] == 'k') ) + nbVariants = 2; + } + for ( uint32 iVariant=1; iVariant<=nbVariants; ++iVariant ) + { + CSString sheetName = CSString( "m" ) + + familyCodes[iFam] + + rmCodeMid + + toString( "%02u", iVariant ); + + if ( GenOnlyNewRawMaterials ) + { + map::const_iterator iprm = inputSheetPathContent.find( sheetName ); + if ( iprm != inputSheetPathContent.end() ) + continue; + } + + if ( (! IsRMSheetGenerated[sheetName].Done) ) + { + IsRMSheetGenerated[sheetName].Done = true; + + //DebugLog->displayRawNL( "%s %s", sheetName.c_str(), getRMName( sheetName ).c_str() ); + if ( OutputNameList ) + { + CSString fullName; + if ( isInvasionFamily && (creaLZCode[1] == 'k') ) + { + switch ( iVariant ) + { + case 1: fullName = "Fragment of Kitin Claw;a;the;Fragments of Kitin Claw;;the;;"; break; + case 2: fullName = "Kitin Trophy;a;the;Kitin Trophies;;the;;"; break; + default:; + } + } + else + { + fullName = getRMShortName( sheetName, statQuality, isMissionRawMaterial ); + } + fprintf( nameOutputFile, "%s;%s\n", sheetName.c_str(), fullName.c_str() ); + } + + CGenRawMaterial rawMaterial( sheetName ); + + rawMaterial.ILocation = InCreatures; + rawMaterial.IFamily = iFam; + rawMaterial.Group = FamSet[families[iFam]].Group; + rawMaterial.IEcosystem = (TEcosystem)iEcosystem; + rawMaterial.StatQuality = statQuality; + if ( isMissionRawMaterial ) + rawMaterial.ILevelZone = iZone; + else + rawMaterial.ILevelZone = iLevelZone; + rawMaterial.fillPropertiesFromFamily(); + + if ( ExistingRMAction == ModifyRM ) + { + // Clear sheet (otherwise the previous values would remain) + clearSheet( form, &form->getRootNode() ); + + // Link to the parent sheets (the form arguments are always the last parent forms but there aren't used by the func anyway) + form->insertParent( 0, getEcoParentName( iEcosystem ).c_str(), ecoParentForm ); + form->insertParent( 1, getFamParentName( iFam ).c_str(), famParentForm ); + if ( ! ((itEcosystemOfCreature == Goo) || + (isInvasionFamily)) ) + form->insertParent( 2, getCreaParentName( creaCMainModelCode ).c_str(), creaParentForm ); + + rawMaterial.MaxLevel = 250; + if ( ! rawMaterial.computeCraftCharacs( iVariant, sheetName ) ) + continue; + + // Write to disk + rawMaterial.writeSheet( form ); + writeRMSheetToDisk( form, sheetName ); + } + else + { + form = (CForm*)formLoader->loadForm( (rawMaterialPath + dirbase + sheetName + "." + rmSheetType).c_str() ); + if ( ! form ) + { + nlwarning( "Can't load %s", (rawMaterialPath + dirbase + sheetName + "." + rmSheetType).c_str() ); + continue; + } + + rawMaterial.loadSheet( form, sheetName, false ); + } + + TRMItem item; + rawMaterial.collectStats( item, MainStat ); + SortableData.addItem( item ); + //Repository.push_back( rawMaterial ); + } + + // Assignment to existing creature sheets (TODO: for Common ecosystem, search Goo creature as well) + if ( AssignRawMaterialsHarvestToCreatureSheets ) // TEMP + { + // For RM of Common ecosystem, add creatures from Goo pseudo-ecosystem + /*CSString creaModel2 = creaModel; + if ( iEcosystem == CommonEcosystem ) + { + creaModel2[3] = 'g'; // replace CommonEcosystem by Goo for creatures + }*/ + + // We don't write into the real creature sheet, but we want it's _*_mp.creature parent sheet + const CSString& creaPathAndFilename = creatureAssignmentPath + string("_") + creaSheetName + "_mp." + crSheetType; + + // Find free and used slots (when not overwriting) + WarningLog->addNegativeFilter( "Can't open" ); // because loadForm() will emit a warning if not existing yet (but passing the filter is very slow) :( + creaForm = formLoader->loadForm( creaPathAndFilename.c_str() ); + WarningLog->removeFilter( "Can't open" ); + if ( ! creaForm ) + creaForm = formLoader->loadForm( (string("_empty.") + crSheetType).c_str() ); + if ( creaForm ) + { + CSString rmSheetFilename = sheetName + "." + rmSheetType; + bool alreadyAssigned = false; + uint32 firstFreeRMSlot = 0, lastAssignedRMSlot = 0; + for ( uint32 rMP=1; rMP<=NB_RAW_MATERIAL_FAMILIES_PER_CREATURE; ++rMP ) + { + string value; + creaForm->getRootNode().getValueByName( value, toString( "Harvest.MP%u.AssociatedItem", rMP ).c_str() ); + + if ( (value.size() == SIZE_RAW_MATERIAL_SHEET_FILENAME) && (value[0] == 'm') ) + { + // Erase all (old & new!) (needs a pass before assignment) + if ( EraseOldCreatureAssignments ) + { + creaForm->getRootNode().setValueByName( "", toString( "Harvest.MP%u.AssociatedItem", rMP ).c_str() ); + //nldebug( "Erasing old assignment %s in %s.creature", value.c_str(), sheetName.c_str() ); + } + else + { + if ( value == rmSheetFilename ) + { + alreadyAssigned = true; + TRMItem item; + item.push( DtName, sheetName ); + item.push( DtCreature, creaSheetName ); + item.push( DtCreaTitle, Titles[creaSheetName] ); + SortableData.updateItemAppend( item, DtCreature ); + SortableData.updateItemAppend( item, DtCreaTitle ); + } + lastAssignedRMSlot = rMP; + if ( lastAssignedRMSlot > maxLastAssignedRMSlot ) + maxLastAssignedRMSlot = lastAssignedRMSlot; + } + + // Test validity of existing assignments (in TestExistingAssigments mode) + if ( TestExistingAssigments ) + { + string sn = value.substr( 0, 11 ); + if ( inputSheetPathContent.find( sn ) == inputSheetPathContent.end() ) + { + nlwarning( "RM %s (assigned to %s.creature) not found", sn.c_str(), creaSheetName.c_str() ); + } + } + } + else if ( firstFreeRMSlot == 0 ) + firstFreeRMSlot = rMP; + } + + if ( EraseOldCreatureAssignments ) + { + if ( creatureSheets.find( creaSheetName ) == creatureSheets.end() ) + { + flushSheetToDisk( creaPathAndFilename, creaForm ); + ++nbErasedCreatureAssignments; + } + } + else if ( AssignOnlyToUnassignedCreatures && (lastAssignedRMSlot != 0) ) + { + // Skip assignment if already done (in AssignOnlyToUnassignedCreatures mode) + if ( creatureSheets.find( creaSheetName ) == creatureSheets.end() ) + { + ++nbCreatureSheetsSkipped; + nldebug( "Skipped %s.creature", creaSheetName.c_str() ); + } + } + else + { + // Assign current RM to first free slot + if ( firstFreeRMSlot != 0 ) + { + if ( ! alreadyAssigned ) + { + creaForm->getRootNode().setValueByName( rmSheetFilename.c_str(), toString( "Harvest.MP%u.AssociatedItem", firstFreeRMSlot ).c_str() ); + //nlinfo( "%s %s got %s %s", CreatureModels[CreatureToModel[creaModel2]].Name.c_str(), creaSheetName.c_str(), families[iFam].c_str(), sheetName.c_str() ); + flushSheetToDisk( creaPathAndFilename, creaForm ); + ++nbAssignedMaterials; + + // These stats won't be correct if WriteSheetsToDisk is disabled && ExistingAction is ModifyRM (infinite slots) + TRMItem item; + item.push( DtName, sheetName ); + item.push( DtCreature, creaSheetName ); + item.push( DtCreaTitle, Titles[creaSheetName] ); + SortableData.updateItemAppend( item, DtCreature ); + SortableData.updateItemAppend( item, DtCreaTitle ); + } + } + else if ( (ExistingRMAction == ModifyRM) && (! alreadyAssigned) ) + { + nlwarning( "No free slot to assign %s %s %s to %s", CreatureModels[CreatureToModel[creaModel/*2*/]].Name.c_str(), families[iFam].c_str(), sheetName.c_str(), creaSheetName.c_str() ); + } + } + creatureSheets.insert( creaSheetName ); + } + else + { + nlwarning( "Can't open %s", creaPathAndFilename.c_str() ); + } + } + } + } + } + } + } + } + } + if ( AssignRawMaterialsHarvestToCreatureSheets ) + { + // Find creature sheets that were not processed (missing model for example) + for ( map::const_iterator ipc = inputSheetPathContent.begin(); ipc!=inputSheetPathContent.end(); ++ipc ) + { + const CSString& creaSheetName = (*ipc).first; + const CSString& creaPathAndFilename = (*ipc).second; + + if ( ! ((creaSheetName[0] == 'c') && (creaSheetName.size() == 6)) ) + continue; + + if ( creatureSheets.find( creaSheetName ) == creatureSheets.end() ) + { + if ( CreatureMainModelsWithoutRM.find( creaSheetName.substr( 0, 3 ) ) != CreatureMainModelsWithoutRM.end() ) + { + nldebug( "Creature %s (%s) has no MP", creaSheetName.c_str(), CreatureModels[CreatureToModel[creaSheetName.substr( 0, 5 )]].Name.c_str() ); + } + else if ( TFamInfo::UseGenerateOnly == 0 ) // avoid warnings when generating only a subset of the RM families + { + if ( creaSheetName[CR_INDEX_LOCAL_LEVEL_CODE] == '6' ) + nldebug( "Mission creature '6' %s (%s) not processed", creaSheetName.c_str(), CreatureModels[CreatureToModel[creaSheetName.substr( 0, 5 )]].Name.c_str() ); + else if ( creaSheetName[1] == 'd' ) + nldebug( "Degenerated creature 'cd' %s (%s) not processed", creaSheetName.c_str(), CreatureModels[CreatureToModel[creaSheetName.substr( 0, 5 )]].Name.c_str() ); + else + { + string reason; + uint i; + for ( i=0; i!=NbEcosystemsPlusExtensions; ++i ) + { + if ( creaSheetName[CR_INDEX_ECOSYSTEM_CODE] == getCreatureEcosystemCode( i )[0] ) + break; + } + if ( i == NbEcosystemsPlusExtensions ) + reason = toString( " (invalid ecosystem %c)", creaSheetName[CR_INDEX_ECOSYSTEM_CODE] ); + nlwarning( "Creature %s (%s) not processed%s", creaSheetName.c_str(), CreatureModels[CreatureToModel[creaSheetName.substr( 0, 5 )]].Name.c_str(), reason.c_str() ); + } + } + + if ( EraseOldCreatureAssignments ) + { + CSmartPtr creaForm = formLoader->loadForm( (creaSheetName + "." + crSheetType).c_str() ); + if ( creaForm ) + { + for ( uint32 rMP=1; rMP<=4; ++rMP ) // only to 4 (TODO: use the proper number) + { + creaForm->getRootNode().setValueByName( "", toString( "Harvest.MP%u.AssociatedItem", rMP ).c_str() ); + //nldebug( "Erasing old assignment %s in %s.creature", value.c_str(), sheetName.c_str() ); + } + flushSheetToDisk( creaPathAndFilename, creaForm ); + ++nbErasedCreatureAssignments; + } + else + nlwarning( "Can't open %s", creaPathAndFilename.c_str() ); + } + } + } + + nlinfo( "%u raw materials assigned to %u creature sheets (%u skipped, already assigned; %u erased; biggest last slot: %u)", nbAssignedMaterials, creatureSheets.size(), nbCreatureSheetsSkipped, nbErasedCreatureAssignments, maxLastAssignedRMSlot ); + } + +processRawMaterialsForDeposits: + // + // Iterate on deposit location + // + + fprintf( GraphFile, "\n" ); + nlassert( ! DepositFamilyIndices.empty() ); + map< uint32, vs > materialsByZoneForDeposits; + NLMISC::CSmartPtr depParentForm, depForm; + float avgSumOriginalityAvg = 0.0f; + uint32 nbDepositsGenerated = 0; + + if ( SkipRawMaterialsForDeposits ) + goto endDeposits; + + if ( AssignRawMaterialsHarvestToDepositSheets || FixDeposits ) + { + /*uint32*/ nbAssignedMaterials = 0; + + if ( ExistingRMAction == ModifyRM ) + { + // Write deposit parent sheet + depParentForm = loadTemplateForm( formLoader, dpSheetType ); + clearSheet( depParentForm, &form->getRootNode() ); + //parentForm->getRootNode().setValueByName( "Harvest", "Skill" ); + for ( uint32 rMP=0; rMP!=NB_RAW_MATERIALS_PER_DEPOSIT; ++rMP ) + { + string rm = toString( "MP%02u.", rMP+1 ); + uint32 rSeason; + for ( rSeason=0; rSeason!=seasons.size(); ++rSeason ) + { + depParentForm->getRootNode().setValueByName( (uint32)0, (rm + seasons[rSeason] + ".MinQuantity").c_str() ); + depParentForm->getRootNode().setValueByName( (uint32)100, (rm + seasons[rSeason] + ".MaxQuantity").c_str() ); + depParentForm->getRootNode().setValueByName( (uint32)10, (rm + seasons[rSeason] + ".RegenRate").c_str() ); + depParentForm->getRootNode().setValueByName( (uint32)50, (rm + seasons[rSeason] + ".AngryLevel").c_str() ); + depParentForm->getRootNode().setValueByName( (uint32)30, (rm + seasons[rSeason] + ".FuryLevel").c_str() ); + depParentForm->getRootNode().setValueByName( (uint32)10, (rm + seasons[rSeason] + ".BlackKamiLevel").c_str() ); + } + depParentForm->getRootNode().setValueByName( (uint32)1, (rm + "MinGetQuantity").c_str() ); + depParentForm->getRootNode().setValueByName( (uint32)20, (rm + "MaxGetQuantity").c_str() ); + depParentForm->getRootNode().setValueByName( (uint32)1, (rm + "MinGetQuality").c_str() ); + depParentForm->getRootNode().setValueByName( (uint32)25, (rm + "MaxGetQuality").c_str() ); + depParentForm->getRootNode().setValueByName( (uint32)80, (rm + "PresenceProbabilities").c_str() ); + } + flushSheetToDisk( "_parent.deposit", depParentForm ); + + // Setup deposit sheet + depForm = loadTemplateForm( formLoader, dpSheetType ); + clearSheet( depForm, &form->getRootNode() ); + } + } + + // Iterate on ecosystem + for ( uint32 iEcosystem=0; iEcosystem!=NbEcosystems; ++iEcosystem ) + { + COriginalitySorter OriginalitySorter; + + uint32 nbPerEcosystem = min( (uint32)((ecosystemCodes[iEcosystem][0] == 'c') ? 7 : 3), MaxNbRMByFamilyEZ ); + nlinfo( "Generating/browsing %u sets for %s...", nbPerEcosystem, ecosystems[iEcosystem].c_str() ); + materialsByZoneForDeposits.clear(); + + vu& familiesForDeposit = DepositFamilyIndices; + + // Iterate on variations in ecosystem + for ( uint32 iv=0; iv!=nbPerEcosystem; ++iv ) + { + string variationInEcosystem = string( 1, (char)('a' + iv) ); + + // Iterate on level zone + for ( uint32 iZone=0; iZone<6; ++iZone ) + { + TStatQuality statQuality = (iZone == 0) ? Basic : (TStatQuality)(iZone - 1); + + // Iterate on families + for ( vu::iterator ifc=familiesForDeposit.begin(); ifc!=familiesForDeposit.end(); ++ifc ) + { + uint32 iFam = (*ifc); + if ( ! TFamInfo::mustGenerateFamily( iFam ) ) + continue; + + // Test if the raw material family must be generated for this ecosystem + const TFamInfo& rmfamily = FamSet[families[iFam]]; + bool isMissionRawMaterial = rmfamily.IsForMission; + if ( isMissionRawMaterial ) + { + // All foraged mission RMs are Common (unlike creature RMs) + if ( iEcosystem != CommonEcosystem ) + continue; + + // Mission quality ranges from A=B to F + } + else + { + if ( GenOnlyMissionRawMaterials ) + continue; + + // Basic & Fine in Common, better RMs specialized by ecosystem + if ( ! rmfamily.existsInEcosystem( (TEcosystem)iEcosystem, statQuality ) ) + continue; + + // Craft quality ranges from B (#0) to F (#4) (deposits of newbielands have B) + if ( iZone == 0 ) + continue; + } + + // Iterate on variants + for ( uint32 iVariant=1; iVariant<=1; ++iVariant ) + { + CSString sheetName = CSString( "m" ) + + familyCodes[iFam] + + CSString( "dx" ) + variationInEcosystem + ecosystemCodes[iEcosystem] + string( 1, (char)('a' + iZone) ) + + toString( "%02u", iVariant ); + + if ( GenOnlyNewRawMaterials ) + { + map::const_iterator iprm = inputSheetPathContent.find( sheetName ); + if ( iprm != inputSheetPathContent.end() ) + continue; + } + + //DebugLog->displayRawNL( "%s %s", sheetName.c_str(), getRMName( sheetName ).c_str() ); + if ( OutputNameList ) + fprintf( nameOutputFile, "%s;%s\n", sheetName.c_str(), getRMShortName( sheetName, statQuality, isMissionRawMaterial ).c_str() ); + + // Set output directory + dirbase = conventionalDirectory( ecosystems[iEcosystem] ) + "/"; + + CGenRawMaterial *rm = new CGenRawMaterial( sheetName ); + CGenRawMaterial& rawMaterial = *rm; + rawMaterial.ILocation = InDeposits; + rawMaterial.IFamily = iFam; + rawMaterial.Group = FamSet[families[iFam]].Group; + rawMaterial.IEcosystem = (TEcosystem)iEcosystem; + rawMaterial.StatQuality = statQuality; + if ( isMissionRawMaterial ) + rawMaterial.ILevelZone = iZone; + else + rawMaterial.ILevelZone = ~0; + rawMaterial.fillPropertiesFromFamily(); + + if ( ExistingRMAction == ModifyRM ) + { + rawMaterial.MaxLevel = (rawMaterial.StatQuality+1) * 250 / (NB_UNIQUE_LEVELZONES_PER_CONTINENT); + if ( ! rawMaterial.computeCraftCharacs( iVariant, sheetName ) ) + { + delete rm; + continue; + } + + /*if ( (uint)(rawMaterial.getOriginalityMax()*100.0f) >= OriginalityMinThreshold ) + { + // Write to disk + rawMaterial.writeSheet( form ); + writeRMSheetToDisk( form, sheetName ); + }*/ + + if ( SortByOriginality ) + OriginalitySorter.pushRM( &rawMaterial ); + else + { + selectRawMaterial( form, ecoParentForm, famParentForm, &rawMaterial ); + delete rm; + } + } + else + { + if ( inputSheetPathContent.find( sheetName ) != inputSheetPathContent.end() ) + { + form = (CForm*)formLoader->loadForm( (rawMaterialPath + dirbase + sheetName + "." + rmSheetType).c_str() ); + if ( ! form ) + { + nlwarning( "Can't load %s", (rawMaterialPath + dirbase + sheetName + "." + rmSheetType).c_str() ); + } + else + { + rawMaterial.loadSheet( form, sheetName, false ); + + // Write stats + TRMItem item; + rm->collectStats( item, MainStat ); + SortableData.addItem( item ); + } + } + delete rm; + } + + } + } + } + } + + if ( ExistingRMAction == ModifyRM ) + { + if ( SortByOriginality ) + { + nlerror( "Deprecated" ); + /*set usedRMFamilies [5]; + uint sumNBRMCraftBySlot = 0, sumOriginalityAvg = 0; + for ( uint r=0; r!=NbFaberElements; ++r ) + { + uint iNBRMCraftBySlot = 0, iUniqueNBRMCraftBySlot = 0; + nlinfo( "%s: Popping at most %u RM from %u (%ux5) compatible", getShortFaberElemString(r).c_str(), MaxNbRMByCraftSlotE, OriginalitySorter.RMByOriginalityByCraftSlot[r].size(), OriginalitySorter.RMByOriginalityByCraftSlot[r].size()/5 ); + COriginalitySorter::CMultiMapByOriginality::const_iterator imo; + for ( imo= OriginalitySorter.RMByOriginalityByCraftSlot[r].begin(); + imo!=OriginalitySorter.RMByOriginalityByCraftSlot[r].end(); + ++imo ) + { + if ( iNBRMCraftBySlot >= MaxNbRMByCraftSlotE ) + break; + + const uint32& originality = (*imo).first; + CGenRawMaterial *rm = (*imo).second; + + if ( ! OriginalitySorter.alreadyPopped( rm ) ) + { + //InfoLog->displayRawNL( "NewOne: %p: %s %s %u", rm, rm->SheetName.c_str(), faberElems[r].c_str(), (*imo).first ); + selectRawMaterial( form, ecoParentForm, famParentForm, rm ); + + // Memorize for deposit assignment + materialsByZoneForDeposits[rm->ILevelZone+1].push_back( rm->SheetName ); + usedRMFamilies[rm->ILevelZone].insert( rm->IFamily ); + + sumOriginalityAvg += (uint)(rm->getOriginalityAvg()*100.0f); + ++iUniqueNBRMCraftBySlot; + + OriginalitySorter.popAndDeleteRM( rm ); + } + else + { + //InfoLog->displayRawNL( "Already: %p: %s %u", rm, faberElems[r].c_str(), (*imo).first ); + } + ++iNBRMCraftBySlot; // when already popped, consider as counting for the rms for current craft slot + } + nldebug( "%s: %u rm generated (for deposits)", CraftParts[r].Name.c_str(), iNBRMCraftBySlot ); + sumNBRMCraftBySlot += iUniqueNBRMCraftBySlot; + } + nlinfo( "Total selected for deposits in %s: %u", ecosystems[iEcosystem].c_str(), sumNBRMCraftBySlot ); + + // Force at least one rm of each (family, levelzone) + uint iRM = 0; + for ( uint32 iLevelZone=0; iLevelZone!=5; ++iLevelZone ) + { + COriginalitySorter::CRMSet::const_iterator itRm = OriginalitySorter.getRMSetBegin(); + while ( (itRm = OriginalitySorter.getFirstRMNotInFamilyListFromPos( usedRMFamilies[iLevelZone], iLevelZone, itRm )) != OriginalitySorter.getRMSetEnd() ) + { + CGenRawMaterial *rm = (*itRm); + selectRawMaterial( form, ecoParentForm, famParentForm, rm ); + + // Memorize for deposit assignment + materialsByZoneForDeposits[rm->ILevelZone+1].push_back( rm->SheetName ); + usedRMFamilies[iLevelZone].insert( rm->IFamily ); + nldebug( "Adding %s (family %s zone %c)", rm->SheetName.c_str(), rm->familyStr().c_str(), 'A' + (char)(rm->ILevelZone+1) ); + ++iRM; + sumOriginalityAvg += (uint)(rm->getOriginalityAvg()*100.0f); + } + } + nlinfo( "Added %u RM (one per family per levelzone)", iRM ); + sumNBRMCraftBySlot += iRM; + avgSumOriginalityAvg += (float)sumOriginalityAvg / (float)sumNBRMCraftBySlot; + + // Delete rm objects + OriginalitySorter.deleteAllRemainingRM(); + */ + } + } + + if ( AssignRawMaterialsHarvestToDepositSheets || FixDeposits ) + { + nlinfo( "Generating/browsing deposits for %s...", ecosystems[iEcosystem].c_str() ); + + // Iterate on level zone + for ( uint32 iZone=0; iZone<=5; ++iZone ) + { + string depSheetName = string("d") + ecosystemCodes[iEcosystem].c_str() + toString( "%caa", (char)('a' + iZone) ); + + if ( ExistingRMAction == ModifyRM ) + { + clearSheet( depForm, &depForm->getRootNode() ); + depForm->insertParent( 0, "_parent.deposit", depParentForm ); + + // Get the list of raw material families and make a random selection of raw material sheets + set usedFamilies; + uint32 iz = (iZone==0) ? 1 : iZone; // 'A' gets raw materials of zone 'B' + vs& compatibleMaterials = materialsByZoneForDeposits[iz]; + for ( uint32 rMP=0; rMP!=NB_RAW_MATERIALS_PER_DEPOSIT; ++rMP ) + { + bool famOk = false; + uint32 escapeCounter = 0; + do + { + CSString rmName; + + // Particular cases (forced for LD missions) + if ( iz == 1 ) + { + /*switch ( rMP ) + { + case 0: + rmName = "mdubcbwof01"; + break; + case 1: + rmName = "mduacbwoo01"; + break; + case 2: + rmName = "mduacbref01"; + break; + }*/ + } + if ( rmName.empty() ) + { + // Generic case, get a random value + if ( ! compatibleMaterials.empty() ) + { + uint32 iMaterial = getRandomValue( compatibleMaterials.size() ); + rmName = compatibleMaterials[iMaterial]; + } + } + + // No compatible material? + if ( rmName.empty() ) + { + escapeCounter = 16; + break; + } + + // Prevent from having the same family more than once + CSString extFamily = rmName.substr( RM_INDEX_FAMILY_CODE, NB_FAMILY_CODE_CHARS ); + if ( usedFamilies.find( extFamily ) == usedFamilies.end() ) + { + usedFamilies.insert( extFamily ); + + // Assign RM to current deposit slot + depForm->getRootNode().setValueByName( (rmName+"."+rmSheetType).c_str(), toString( "MP%02u.AssociatedItem", rMP+1 ).c_str() ); + nldebug( "%s got %s %s", depSheetName.c_str(), families[getIndexFromString( rmName.substr( 6, 2 ), familyCodes )].c_str(), rmName.c_str() ); + ++nbAssignedMaterials; + + // Test validity of existing assignments (in TestExistingAssigments mode) + if ( TestExistingAssigments ) + { + if ( inputSheetPathContent.find( rmName ) == inputSheetPathContent.end() ) + { + nlwarning( "RM %s (assigned to %s.deposit) not found", rmName.c_str(), depSheetName.c_str() ); + } + } + + TRMItem depItem; + depItem.push( DtName, rmName ); + //depItem.push( DtDeposit, depSheetName ); + //SortableData.updateItemAppend( depItem, DtDeposit ); + + famOk = true; + } + else + ++escapeCounter; + } + while ( (! famOk) && (escapeCounter < 16) ); + if ( ! famOk ) + { + nlwarning( "Deposit %s got only %u RM", depSheetName.c_str(), rMP ); + break; + } + } + + flushSheetToDisk( depositPath + depSheetName + "." + dpSheetType, depForm ); + ++nbDepositsGenerated; + } + else if ( ! FixDeposits ) + { + const string& filename = inputSheetPathContent[depSheetName]; + if ( filename.empty() ) + nlwarning( "%s not found", (depSheetName + "." + dpSheetType).c_str() ); + else + depForm = (CForm*)formLoader->loadForm( filename.c_str() ); + + uint32 nbRMinDep = 0; + //string rms = depSheetName + ": "; + for ( uint32 rMP=0; rMP!=NB_RAW_MATERIALS_PER_DEPOSIT; ++rMP ) + { + CSString value; + depForm->getRootNode().getValueByName( value, toString( "MP%02u.AssociatedItem", rMP+1 ).c_str() ); + if ( ! value.empty() ) + { + CSString rmName = value.rightCrop( rmSheetType.size() + 1 ); + TRMItem depItem; + depItem.push( DtName, rmName ); + //depItem.push( DtDeposit, depSheetName ); + //rms += rmName + ","; + //SortableData.updateItemAppend( depItem, DtDeposit ); + ++nbRMinDep; + } + } + //nlinfo( "%u RM in deposit %s: %s", nbRMinDep, depSheetName.c_str(), rms.c_str() ); + } + } + } + } + if ( AssignRawMaterialsHarvestToDepositSheets ) + { + nlinfo( "%u raw materials assigned to %u deposit sheets", nbAssignedMaterials, nbDepositsGenerated ); + } + nlinfo( "Average originality: %.2f", (float)avgSumOriginalityAvg / (float)ecosystems.size() ); +endDeposits: + nldebug( "End of generation" ); + } + + if ( BrowseOtherDeposits || FixDeposits ) + { + // Access deposits + vector depositFiles; + CPath::getPathContent( depositPath, true, false, true, depositFiles ); + for ( vector::const_iterator idf=depositFiles.begin(); idf!=depositFiles.end(); ++idf ) + { + const string& filename = (*idf); + const CSString& depSheetName = CFile::getFilenameWithoutExtension( filename ); + + if ( (filename.find( ".deposit" ) != string::npos) && (depSheetName[0] == 'd') && (depSheetName.size() == 5) ) + { + bool isGenerated = (depSheetName.right( 2 ) == "aa"); + + // If not fixing deposits (just browsing), discard generated ones (already browsed) + if ( (! FixDeposits) && isGenerated ) + continue; + + CSmartPtr depForm = (CForm*)formLoader->loadForm( filename.c_str() ); + bool modified = false; + + // Browse or check/substitute all RM assigned to deposit + for ( uint32 rMP=0; rMP!=NB_RAW_MATERIALS_PER_DEPOSIT; ++rMP ) + { + CSString value, substitution; + depForm->getRootNode().getValueByName( value, toString( "MP%02u.AssociatedItem", rMP+1 ).c_str() ); + if ( value.empty() ) + continue; + + if ( ! isGenerated ) + { + TRMItem depItem; + depItem.push( DtName, value ); + //depItem.push( DtDeposit, depSheetName ); + //SortableData.updateItemAppend( depItem, DtDeposit ); + } + + if ( FixDeposits ) + { + nlerror( "TODO" ); // this code is for V2, not suitable for V3 + /*value = value.rightCrop( 6 ); // remove .sitem + CRMData::CLookup::const_iterator ilk = SortableData.lookup( DtName ).find( value ); + if ( ilk == SortableData.lookup( DtName ).end() ) + { + // Find a substitution by declinaison/location + char adjCode = value[8]; + string substitution = findSubstitutionForDepositRM( value, adjCode ); + if ( substitution.empty() ) + { + // Find a substitution by adjective (emit a warning) + for ( mss::const_iterator ita=adjectives.begin(); ita!=adjectives.end(); ++ita ) + { + adjCode = tolower( (*ita).first[0] ); + if ( adjCode == value[8] ) + continue; + + substitution = findSubstitutionForDepositRM( value, adjCode ); + if ( ! substitution.empty() ) + { + nlinfo( "Replacing adj %s by %s for %s", adjectives[string(1,(char)toupper(value[8]))].c_str(), (*ita).second.c_str(), value.c_str() ); + break; + } + } + } + if ( substitution.empty() ) + { + nlwarning( "Could not find a substitution for %s in %s", value.c_str(), depSheetName.c_str() ); + } + else + { + depForm->getRootNode().setValueByName( (substitution+".sitem").c_str(), toString( "MP%02u.AssociatedItem", rMP+1 ).c_str() ); + nlinfo( "%s replaced by %s", value.c_str(), substitution.c_str() ); + modified = true; + } + + } + if ( modified ) + { + flushSheetToDisk( filename, depForm ); + }*/ + } + } + } + } + } + + if ( OutputNameList ) + fclose( nameOutputFile ); + fclose( GraphFile ); + + //nlinfo( "%u RM in repository", Repository.size() ); + + // Produce main doc + CProducedDocHtml MainDoc; + CProducedDocCSV MainCSV; + MainDoc.open( "rm.html", "Raw materials by generation order", ProduceDoc ); + MainCSV.open( "output_rm_for_craft.csv", ProduceDoc ); + MainDoc.write( "
    \n" ); + MainDoc.write( "" ); + for ( uint32 c=0; c!=DtNbCols; ++c ) + { + MainDoc.write( "" ); + MainCSV.write( string(DataColStr[c]) + "," ); + } + MainDoc.write( "" ); + MainCSV.write( "\n" ); + for ( CRMData::CItems::const_iterator isd=SortableData.items().begin(); isd!=SortableData.items().end(); ++isd ) + { + MainDoc.write( (*isd).toHTMLRow() ); + } + MainDoc.write( "
    " + string(DataColStr[c]) + "
    \n" ); + + // Produce alt docs + CProducedDocHtml AltDocs[DtNbCols]; + for ( uint32 c=0; c!=DtNbCols; ++c ) + { + AltDocs[c].open( "rm_" + string(DataColStr[c]) + ".html", "Raw materials by " + string(DataColStr[c]), ProduceDoc ); + AltDocs[c].write( "
    \n" ); + AltDocs[c].write( "" ); + for ( uint32 cc=0; cc!=DtNbCols; ++cc ) + if ( cc == c ) + AltDocs[c].write( "" ); + else + AltDocs[c].write( "" ); + AltDocs[c].write( "" ); + string previousKey = "[NO PREVIOUS]"; // not a blank string, because it may be a valid value + string previousName = ""; + for ( CRMData::CLookup::const_iterator isd=SortableData.lookup( c ).begin(); isd!=SortableData.lookup( c ).end(); ++isd ) + { + const TRMItem& item = SortableData.getRow( (*isd).second ); + AltDocs[c].write( item.toHTMLRow( c, (*isd).first, previousKey, DtName, previousName ) ); + + if ( c == DtCraftSlotName ) + MainCSV.write( item.toCSVLine( ',', "", c, (*isd).first, previousKey, DtName, previousName ) ); + + previousKey = (*isd).first; + previousName = item.Fields[DtName][0]; + } + AltDocs[c].write( "
    " + string(DataColStr[cc]) + "" + string(DataColStr[cc]) + "
    \n" ); + AltDocs[c].save(); + } + + // Stats + if ( (nbSheetsProcessed != 0) ) + { + CProducedDocHtml StatFile; + StatFile.open( "rm_stats.html", "Raw material statistics", ProduceDoc ); + StatFile.writepln( toString( "Total: %u raw materials (%u new)", nbSheetsProcessed, nbNewSheetsGenerated ) ); + StatFile.writepln( toString( "Faber elements filled: avg %u, min %u, max %u", MainStat.SumNbFaberElemsFilled / nbSheetsProcessed, MainStat.MinNbFaberElemsFilled, MainStat.MaxNbFaberElemsFilled ) ); + + // What can be crafted from each raw material family + StatFile.writeln( "What can be crafted from each raw material family:
    " ); + StatFile.writeln( "
      " ); + for ( uint32 iFam=0; iFam!=families.size(); ++iFam ) + { + if ( ! FamSet[families[iFam]].IsActive ) + continue; + + string propStr; + vs& props = FamSet[families[iFam]].Properties; + for ( vs::const_iterator ip = props.begin(); ip!=props.end(); ++ip ) + { + if ( ip != props.begin() ) + propStr += ", "; + propStr += (*ip); + } + uint nbLines = 0; + StatFile.writeln( "
    • " + families[iFam] + ": " + propStr + "

      " ); + StatFile.writeln( "
        " ); + for ( uint32 c=0; c!=NbCiv; ++c ) + { + bool civHasAPlan = false; + for ( uint32 rFaberElem=0; rFaberElem!=NbFaberElements; ++rFaberElem ) + { + if ( MainStat.NbRMByFaberElemByFamilyAndCiv[iFam][c][rFaberElem] != 0 ) + { + civHasAPlan = true; + break; + } + } + if ( civHasAPlan ) + { + StatFile.writeln( "
      • " + string(CivNames[c]) + " plans

        " ); + StatFile.writeln( "
          " ); + for ( uint32 rFaberElem=0; rFaberElem!=NbFaberElements; ++rFaberElem ) + { + if ( MainStat.NbRMByFaberElemByFamilyAndCiv[iFam][c][rFaberElem] != 0 ) + { + StatFile.writebln( CraftParts[rFaberElem].Name + toString(": %u different", MainStat.NbRMByFaberElemByFamilyAndCiv[iFam][c][rFaberElem] ) ); + ++nbLines; + } + } + StatFile.writeln( "
        " ); + } + } + StatFile.writeln( "
      " ); + if ( nbLines == 0 ) + { + if ( ! FamSet[families[iFam]].IsForMission ) + { + if ( ! ( (SkipRawMaterialsForCreatures && FamSet[families[iFam]].IsInCreatures) || + (SkipRawMaterialsForDeposits && FamSet[families[iFam]].IsInDeposits) ) ) + nlwarning( "%s is not used by any craft plan!", families[iFam].c_str() ); + } + StatFile.writebln( "No use for this family" ); + // Tip: if RM of a creature, check if the creature exists + } + } + StatFile.writeln( "
    " ); + + // Number of compatible RM by ecosystem, by craft slot + vector nbFabs( NbEcosystems, 0 ); + for ( uint32 rFaberElem=0; rFaberElem!=NbFaberElements; ++rFaberElem ) + { + StatFile.writebln( toString( "%s: %u compatible RM", CraftParts[rFaberElem].Name.c_str(), MainStat.NbRMByFaberElem[rFaberElem] ) ); + if ( CraftParts[rFaberElem].Name.c_str(), MainStat.NbRMByFaberElem[rFaberElem] != 0 ) + { + for ( uint32 iEcosystem=0; iEcosystem!=ecosystems.size(); ++iEcosystem ) + { + StatFile.writebln( toString( "(%u in %s)", MainStat.NbRMByFaberElemByEcosystem[iEcosystem][rFaberElem], ecosystems[iEcosystem].c_str() ) ); + nbFabs[iEcosystem] += MainStat.NbRMByFaberElemByEcosystem[iEcosystem][rFaberElem]; + } + } + } + for ( uint32 iEcosystem=0; iEcosystem!=ecosystems.size(); ++iEcosystem ) + { + StatFile.writebln( toString( "(Total %u in %s)", nbFabs[iEcosystem], ecosystems[iEcosystem].c_str() ) ); + } + + // Number of properties by ecosystem + for ( uint32 iProp=0; iProp!=properties.size(); ++iProp ) + { + uint32 nbTotal = 0; + /*for ( uint32 iLoc=0; iLoc!=NB_LOCATIONS; ++iLoc ) + { + uint32 nbInLoc = 0; + for ( uint32 iEcosystem=0; iEcosystem!=ecosystems.size(); ++iEcosystem ) + { + uint32 nb = NbRMHavingProperty[iLoc][iEcosystem][iProp]; + StatFile.writeln( toString( "\t\t%s %s %s: %u RM", locationNames[iLoc], ecosystems[iEcosystem].c_str(), properties[iProp].c_str(), nb ) ); + nbInLoc += nb; + } + StatFile.writeln( toString( "\t%s %s: %u RM", locationNames[iLoc], properties[iProp].c_str(), nbInLoc ) ); + }*/ + StatFile.writeln( "
      " ); + for ( uint32 iEcosystem=0; iEcosystem!=ecosystems.size(); ++iEcosystem ) + { + uint32 nbInEco = 0; + for ( uint32 iLoc=0; iLoc!=NB_LOCATIONS; ++iLoc ) + { + uint32 nb = MainStat.NbRMHavingProperty[iLoc][iEcosystem][iProp]; + //StatFile.writebln( toString( "\t\t%s %s %s: %u RM", locationNames[iLoc], ecosystems[iEcosystem].c_str(), properties[iProp].c_str(), nb ) ); + nbInEco += nb; + } + StatFile.writebln( toString( "%s %s: %u", ecosystems[iEcosystem].c_str(), properties[iProp].c_str(), nbInEco ) ); + nbTotal += nbInEco; + } + StatFile.writeln( "
    " ); + StatFile.writebln( toString( "%s: %u RM", properties[iProp].c_str(), nbTotal ) ); + } + StatFile.save(); + MainDoc.writepln( "Go to statistics" ); + } + + MainDoc.save(); + MainCSV.save(); + +#if 0 + // + // O L D - V 1 + // + // Randomize color (POSITIVE filter) + CRulesFilter& familyColorFilter = familyColorFilters[iEcosystem][iFamily].empty() ? familyColorFilters[CommonEcosystem] : familyColorFilters[iEcosystem]; + if ( familyColorFilter[iFamily].empty() ) + { + nlwarning( "%s not generated: no possible color in any ecosystem", families[iFamily].c_str() ); + continue; + } + else + { + iColor = familyColorFilter[iFamily][getRandomValue( familyColorFilter[iFamily].size() )]; + } + + if ( isCrSpecialization ) + form->getRootNode().setValueByName( (creatures[iCreature] + " " + strlwr( static_cast(families[iFamily]) )).c_str(), "basics.name" ); + + /* + * Creatures + */ + if ( AssignRawMaterialsHarvestToCreatureSheets ) + { + uint32 nbCreatures = 0, nbCreaturesInSubPath = 0; + nlinfo( "Generating assignments to creature sheets..." ); + getTransposedMap( creatureFamilyFilter, familyCreatureFilter ); + for ( CRulesFilter::const_iterator ir=creatureFamilyFilter.begin(); ir!=creatureFamilyFilter.end(); ++ir ) + { + const char *sCreature = ((*ir).first == ~0) ? "COMMON" : creatures[(*ir).first].c_str(); + nlinfo( "Creature %s -> %u compatible raw materials families", sCreature, (*ir).second.size() ); + } + + // Browse creature sheet repository + map::const_iterator ipc; + for ( ipc=inputSheetPathContent.begin(); ipc!=inputSheetPathContent.end(); ++ipc ) + { + const string& sheetName = (*ipc).first; + const string& filename = (*ipc).second; + if (CFile::getExtension( filename ) == crSheetType) + { + nldebug( "%s", filename.c_str() ); + ++nbCreatures; + } + if ( (CFile::getExtension( filename ) == crSheetType) && + (strlwr(filename).find( creaturePath ) != string::npos) ) + { + ++nbCreaturesInSubPath; + nldebug( "OK" ); + // Load creature sheet + form = (CForm*)formLoader->loadForm( filename.c_str() ); + if ( ! form ) + { + nlwarning( "Can't load sheet %s", filename.c_str() ); + continue; + } + + string eco = string(1, sheetName[1+NB_CREATURE_CODE_CHARS]); + uint32 iEcosystem = getIndexFromString( eco, ecosystemCodes ); + if ( iEcosystem == ~0 ) + { + nlwarning( "Ecosystem code %s in %s unknown", eco.c_str(), sheetName.c_str() ); + continue; + } + + string cr = sheetName.substr( 1, NB_CREATURE_CODE_CHARS ); + uint32 iCreature = getIndexFromString( cr, creatureCodes ); + if ( iCreature == ~0 ) + { + nlwarning( "Creature code %s in %s unknown", cr.c_str(), sheetName.c_str() ); + continue; + } + + // Transform creature level to faber interest level ((ZL, lastLL) = (ZL+1, FirstLL)) + TFaberInterestLevel mainLevel; // mainLevel in [0.. NbFaberInterestLevelsByEcosystem[iEcosystem][ + sint localLevel = (sint)(sheetName[1+NB_CREATURE_CODE_CHARS+2] - '1'); + uint32 zoneLevel = (sint)(sheetName[1+NB_CREATURE_CODE_CHARS+1] - 'a'); + mainLevel = zoneLevel*NB_UNIQUE_LEVELS_PER_ZONE + localLevel; + nlassertex( mainLevel >= 0, ("%s ZL=%d LL=%d FL=%d", sheetName.c_str(), zoneLevel, localLevel, mainLevel) ); + if ( mainLevel >= NbFaberInterestLevelsByEcosystem[iEcosystem] ) + { + nlwarning( "Wrong level %s ZL=%d maxLL=%u LL=%d maxFL=%d FL=%d", sheetName.c_str(), zoneLevel, NB_UNIQUE_LEVELS_PER_ZONE+1, localLevel, NbFaberInterestLevelsByEcosystem[iEcosystem], mainLevel ); + mainLevel = NbFaberInterestLevelsByEcosystem[iEcosystem] - 1; + } + + for ( uint32 rFamily=0; rFamily!=creatureFamilyFilter[iCreature].size(); ++rFamily ) + { + if ( rFamily > NB_RAW_MATERIAL_FAMILIES_PER_CREATURE ) + { + nlwarning( "Too many compatible materials found (%u) for %s (%s, %s)", creatureFamilyFilter[iCreature].size(), + sheetName.c_str(), (iCreature==~0) ? cr.c_str() : creatures[iCreature].c_str(), families[creatureFamilyFilter[iCreature][rFamily]].c_str() ); + continue; + } + + sint levelModifier = ((sint)getRandomValue( 3 )) - 1; // {-1, 0, 1} + TFaberInterestLevel actualLevel = max( 0, min( NbFaberInterestLevelsByEcosystem[iEcosystem]-1, mainLevel + levelModifier ) ); + char *errorReport; + string rmName = findRawMaterialFromCriteria( iEcosystem, creatureFamilyFilter[iCreature][rFamily], iCreature, actualLevel, &errorReport ); + if ( rmName.empty() ) + { + nlwarning( "%s %s (%s) has no match (%s)", + (iCreature==~0) ? cr.c_str() : creatures[iCreature].c_str(), families[creatureFamilyFilter[iCreature][rFamily]].c_str(), sheetName.c_str(), errorReport ); + } + } + + /* + * Deposits + */ + + // For each ecosystem + for ( iEcosystem=0; iEcosystem!=ecosystemDepositFilters.size(); ++iEcosystem ) + { + // For each deposit level + uint32 rLevel; + for ( rLevel=0; rLevel!=5; ++rLevel ) + { + + } + } + } + + // Test deposit validity + /*if ( TestExistingAssigments ) + { + map::const_iterator ipc; + for ( ipc=inputSheetPathContent.begin(); ipc!=inputSheetPathContent.end(); ++ipc ) + { + const string& sheetName = (*ipc).first; + const string& filename = (*ipc).second; + if ( (CFile::getExtension( filename ) == dpSheetType) ) + { + // Load deposit sheet + form = (CForm*)formLoader->loadForm( filename.c_str() ); + if ( ! form ) + { + nlwarning( "Can't load sheet %s", filename.c_str() ); + continue; + } + + for ( uint32 iRM=0; iRM!=30; ++iRM ) + { + string value; + form->getRootNode().getValueByName( value, toString( "MP%02u.AssociatedItem", iRM+1 ).c_str() ); + if ( (value.size() == 19) && (value[0] == 'm') ) + { + string sn = value.substr( 0, 14 ); + if ( inputSheetPathContent.find( sn ) == inputSheetPathContent.end() ) + { + nlwarning( "RM %s (assigned to %s.deposit) not found", sn.c_str(), sheetName.c_str() ); + } + } + } + } + } + }*/ +#endif +} + + + +/* + * + */ +void usage(char *argv0, FILE *out) +{ + fprintf(out, "\n"); + fprintf(out, "Syntax: %s [-p ]", argv0); + fprintf(out, "\n"); +} + + +/* + * + */ +int main(int argc, char* argv[]) +{ + // parse command line + uint32 i; + for (i=1; (sint)i after -p option\n"); + usage(argv[0], stderr); + exit(0); + } + inputSheetPath = argv[i]; + break; + case 'n': + ++i; + if ((sint)i == argc) + { + fprintf(stderr, "Missing after -n option\n"); + usage(argv[0], stderr); + exit(0); + } + ExtractNamesCsv = argv[i]; + break; + } + } + } + + if ( ! ExtractNamesCsv.empty() ) + extractRawMaterialNames(); + else + generateRawMaterials(); + + return 0; +} + + +// Impossible to insert game_share/protection_type.h into project because of #@&$£ precompiled headers +namespace PROTECTION_TYPE +{ + NL_BEGIN_STRING_CONVERSION_TABLE (TProtectionType) + NL_STRING_CONVERSION_TABLE_ENTRY(Cold) + NL_STRING_CONVERSION_TABLE_ENTRY(Acid) + NL_STRING_CONVERSION_TABLE_ENTRY(Rot) + NL_STRING_CONVERSION_TABLE_ENTRY(Fire) + NL_STRING_CONVERSION_TABLE_ENTRY(Shockwave) + NL_STRING_CONVERSION_TABLE_ENTRY(Poison) + NL_STRING_CONVERSION_TABLE_ENTRY(Electricity) + NL_STRING_CONVERSION_TABLE_ENTRY(Madness) + NL_STRING_CONVERSION_TABLE_ENTRY(Slow) + NL_STRING_CONVERSION_TABLE_ENTRY(Snare) + NL_STRING_CONVERSION_TABLE_ENTRY(Sleep) + NL_STRING_CONVERSION_TABLE_ENTRY(Stun) + NL_STRING_CONVERSION_TABLE_ENTRY(Root) + NL_STRING_CONVERSION_TABLE_ENTRY(Blind) + NL_STRING_CONVERSION_TABLE_ENTRY(Fear) + NL_STRING_CONVERSION_TABLE_ENTRY(None) + NL_END_STRING_CONVERSION_TABLE(TProtectionType, ProtectionTypeConversion, None) + + + //----------------------------------------------- + // fromString: + //----------------------------------------------- + TProtectionType fromString(const std::string &str) + { + return ProtectionTypeConversion.fromString(str); + } + + + //----------------------------------------------- + // toString : + //----------------------------------------------- + const std::string& toString(TProtectionType protection_type) + { + return ProtectionTypeConversion.toString(protection_type); + } +}; // PROTECTION_TYPE diff --git a/code/ryzom/tools/sheet_random_generator/srg_utilities.cpp b/code/ryzom/tools/sheet_random_generator/srg_utilities.cpp index a66d42498..4643117eb 100644 --- a/code/ryzom/tools/sheet_random_generator/srg_utilities.cpp +++ b/code/ryzom/tools/sheet_random_generator/srg_utilities.cpp @@ -1,19 +1,19 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - -#include "StdAfx.h" +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#include "StdAfx.h" diff --git a/code/ryzom/tools/sheet_random_generator/srg_utilities.h b/code/ryzom/tools/sheet_random_generator/srg_utilities.h index 1e90bd868..9aabc645a 100644 --- a/code/ryzom/tools/sheet_random_generator/srg_utilities.h +++ b/code/ryzom/tools/sheet_random_generator/srg_utilities.h @@ -1,2964 +1,2964 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - -#ifndef NL_SRG_UTILITIES_H -#define NL_SRG_UTILITIES_H - - -// Misc -#include -#include -#include "nel/misc/path.h" -#include "nel/misc/file.h" -#include "nel/misc/smart_ptr.h" -#include "nel/misc/command.h" -#include "nel/misc/path.h" -#include -#include -// Georges -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" -#include "nel/georges/u_form_dfn.h" -#include "nel/georges/u_form_loader.h" -#include "nel/georges/u_type.h" -// Georges, bypassing interface -#include "georges/stdgeorges.h" -#include "georges/form.h" -// C -#include -#include -// stl -#include -#include -#include - -using namespace NLMISC; -using namespace NLGEORGES; -using namespace std; - - -typedef sint TFaberInterestLevel; -const TFaberInterestLevel NAInterestLevel = -1; -const uint32 NbNomenclaturedFaberLevel = 5; // excluding N/A -const char *sNomenclaturedInterestLevels [NbNomenclaturedFaberLevel+1] = { "N/A", "Worst", "Bad", "Average", "Good", "Best" }; // from -1 to 5 -CRandom RandomGenerator; - -typedef CVectorSString vs; - -typedef map > CRulesFilter; -typedef map , CUnsensitiveSStringLessPred > CRulesStrFilter; -typedef map CRulesStr2Filter; -typedef map< CSString, CSString, CUnsensitiveSStringLessPred > mss; -typedef vector vu; -typedef hash_map< string, string, hash > CTitles; // code -> utf8 title - -// Write sheet files, or display to screen only -bool WriteSheetsToDisk = true; - -// Overriden by command-line argument after -n -string ExtractNamesCsv; - - -const uint32 NbFaberElements = 26; - -const uint32 RM_INDEX_FAMILY_CODE = 1; -const uint32 NB_FAMILY_CODE_CHARS = 4; - -const uint32 RM_INDEX_CREATURE_CODE = 5; -const uint32 NB_CREATURE_CODE_CHARS = 5; - -const uint32 RM_INDEX_ECOSYSTEM_CODE = 8; -const uint32 NB_ECOSYSTEM_CODE_CHARS = 1; - -const uint32 RM_INDEX_LEVELZONE_CODE = 9; - -const uint32 SIZE_RAW_MATERIAL_SHEET_FILENAME = 18; - -/*const uint32 RM_INDEX_INTEREST_LEVEL = 6; -const uint32 NB_INTEREST_LEVEL_CHARS = 2; - -const uint32 RM_INDEX_FABERELEMS_CODE = 8; -const uint32 NB_FABERELEMS_CODE_CHARS = 6;*/ - -const uint32 CR_INDEX_ECOSYSTEM_CODE = 3; // in creature code -const uint32 CR_INDEX_LEVELZONE_CODE = 4; -const uint32 CR_INDEX_LOCAL_LEVEL_CODE = 5; - -//const uint32 NB_UNIQUE_LEVELS_PER_ZONE = 4; // not counting the bosses, the fifth equals the first one of next -const uint32 NB_UNIQUE_LEVELZONES_PER_CONTINENT = 5; -const uint32 MAX_NB_LOCAL_LEVELS = 8; -//const uint32 NB_ZONE_LEVELS = 5; // TEMP for forest ecosystem -//const uint32 NbFaberInterestLevels = (NB_ZONE_LEVELS * NB_UNIQUE_LEVELS_PER_ZONE) + 1; // excluding N/A - -string inputSheetPath; -bool inputSheetPathLoaded = false; -map inputSheetPathContent; // short filename without ext, full filename with path -string TranslationPath; -string SystemMPPath; - - -// These vectors have the same indices : by family -vs families; -vs familyCodes, ecosystemCodes, propertyCodes, creatureCodes; - -sint MaxFamilyNum = -1; - -enum TColor { Red, Beige, Green, Turquoise, Blue, Violet, White, Black, NbColors, InvalidColor=NbColors }; - -// By ecosystem, color, property, rm group, creature, season -vs ecosystems, colors, properties, groups, creatures, seasons; -mss adjectives; - -// DtName must be the 1st one -enum TDataCol { DtName, DtTitle, DtRMFamily, DtGroup, DtEcosystem, DtLevelZone, DtStatQuality, DtProp, DtCreature, DtCreaTitle, DtCraftSlotName, DtCraftCivSpec, DtColor, DtAverageEnergy, DtMaxLevel, DtJewelProtectionType, DtCustomizedProperties, DtNbCols }; -const char *DataColStr [DtNbCols] = { "Code", "Name", "Family", "Group", "Ecosystem", "LevelZone", "Stat Quality", "Properties", "Creature sheets", "Creatures", "Item parts", "Craft civ spec", "Color", "Average energy", "Max level", "Jewel protection type", "Customized" }; - -const uint32 NbPropertyDepths = 5; -const char *PropertyDepths [NbPropertyDepths] = { "Unknown", "Slightly", "Moderately", "Quite", "Extremely" }; - -typedef uint32 TGroup; // index in groups, and value in groups .typ - -//enum TLocation { Under, Over, Flora, Creatures, NB_LOCATIONS, NB_DEPOSITS=Flora+1 }; -enum TLocation { InDeposits, InCreatures, NB_LOCATIONS }; -vu DepositFamilyIndices; - -enum TCiv { Fyros, Matis, Tryker, Zorai, AllCiv, NbCiv }; -const char *CivNames [NbCiv] = { "Fyros", "Matis", "Tryker", "Zorai", "All" }; -const char *CivEcosystemCodes [NbCiv] = { "D", "F", "L", "J", "X" }; - -enum TEcosystem { CommonEcosystem, Desert, Forest, Lacustre, Jungle, PrimeRoots, NbEcosystems, Goo=NbEcosystems, Invasion, Raid, Event, N, S, T, U, V, W, X, Y, Z, NbEcosystemsPlusExtensions }; - -TCiv EcosystemToCiv[NbEcosystems] = { AllCiv, Fyros, Matis, Tryker, Zorai, AllCiv }; - -enum TStatQuality { Basic, Fine, Choice, Excellent, Supreme, NbStatQualities, InvalidStatQuality=NbStatQualities }; -char *StatQualityStr [NbStatQualities+1] = { "Basic", "Fine", "Choice", "Excellent", "Supreme", "N/A" }; - -TStatQuality CreatureLocalLevelToStatQuality [MAX_NB_LOCAL_LEVELS] = -{ - Basic, // 1 (index 0) - Fine, // 2 - Basic, // 3 - Fine, // 4 - Excellent, // 5 (named creatures) - InvalidStatQuality, // 6 (mission creatures, their RMs have no craft stats) - Supreme, // 7 (bosses) - Choice // 8 (mini-bosses) -}; - - -enum TIndexOfRemarkableStatIndex { RBestA, RBest=RBestA, RWorstA1, RWorst1=RWorstA1, RWorstA2, RWorst2=RWorstA2, RBestB, RWorstB1, RWorstB2, NB_REMARKABLE_STAT_INDICES }; - -struct TSkeletonInfo -{ - TSkeletonInfo() : IsUsed(false) {} - - //vs CreaturesOfSke; - CSString Name; - CSString AbbrevName; - //CSString SkGroup; - bool IsUsed; // true if has RM -}; - -typedef map CSkeletonMap; - -// By skeleton group, by skeleton, bu creature model -CRulesStr2Filter SkgroupToModels; -CSkeletonMap CreatureModels; -mss CreatureToModel; -//vs skeletonGroupColumns; -set CreatureMainModelsWithoutRM; - -// By creature model -CRulesStrFilter RMFamilyIndicesByCreatureModel; -vu GooCreatureFamilyIndices; - -typedef map CCreatureTypeToFamilyIndices; // the key is the 2nd char of the creature code (h for herbivore, k for kitin...) -CCreatureTypeToFamilyIndices InvasionRaidCreatureFamilyIndices; - -struct TBool -{ - TBool() : Done(false) {} - bool Done; -}; - -typedef map< uint, TBool > CDoneMap; // indexed by levelzone -map< string, TBool > IsRMSheetGenerated; // indexed by sheetname - -string rawMaterialPath, creaturePath, creatureAssignmentPath, depositPath; -string dirbase; - - -const string oldRmSheetType = "item"; -const string rmSheetType = "sitem"; -const string crSheetType = "creature"; -const string dpSheetType = "deposit"; - - -//const uint32 NbPropertySlots = 10; // obsolete -uint32 UndefinedProperty = ~0; - - - -/* - * - */ -struct CIconInfo -{ - CSString IconBackground, Icon, IconOver, IconOver2; -}; - -map< CSString, CIconInfo, CUnsensitiveSStringLessPred > Icons; - - -/* - * - */ -class CMainStat -{ -public: - - /// - CMainStat() : SumNbFaberElemsFilled(0), MaxNbFaberElemsFilled(0), MinNbFaberElemsFilled(~0), - NbRMByFaberElem( NbFaberElements, 0 ) {} - - /// Call it when families etc. are ready - void init() - { - NbRMByFaberElemByFamilyAndCiv.resize( families.size() ); - for ( uint32 i=0; i!=families.size(); ++i ) - { - NbRMByFaberElemByFamilyAndCiv[i].resize( NbCiv ); - for ( uint32 c=0; c!=NbCiv; ++c ) - NbRMByFaberElemByFamilyAndCiv[i][c].resize( NbFaberElements ); - } - - for ( uint32 iEcosystem=0; iEcosystem!=ecosystems.size(); ++iEcosystem ) - { - for ( uint32 iLoc=0; iLoc!=NB_LOCATIONS; ++iLoc ) - { - NbRMHavingProperty[iLoc][iEcosystem].resize( properties.size() ); - NbRMByFaberElemByEcosystem[iEcosystem].resize( NbFaberElements ); - } - } - } - - /// - bool updateCraftStatistics( uint32 rFaberElem, uint32 iEcosystem, uint32 iFam, TCiv civ ); - - /// - void updateMainStats( uint32 nbFaberElemsFilled ) - { - SumNbFaberElemsFilled += nbFaberElemsFilled; - if ( nbFaberElemsFilled < MinNbFaberElemsFilled ) - MinNbFaberElemsFilled = nbFaberElemsFilled; - if ( nbFaberElemsFilled> MaxNbFaberElemsFilled ) - MaxNbFaberElemsFilled = nbFaberElemsFilled; - } - - // By property and by ecosystem and location - vu NbRMHavingProperty [NB_LOCATIONS][NbEcosystems]; - - uint32 SumNbFaberElemsFilled; - uint32 MaxNbFaberElemsFilled; - uint32 MinNbFaberElemsFilled; - - vector NbRMByFaberElem;; - vector NbRMByFaberElemByEcosystem [NbEcosystems]; - vector< vector < vector< uint32 > > > NbRMByFaberElemByFamilyAndCiv; - -}; - - -/* - * From georges2csv - */ -void loadSheetPath() -{ - if (inputSheetPathLoaded) - return; - - NLMISC::createDebug(); - NLMISC::WarningLog->addNegativeFilter( "CPath::insertFileInMap" ); - - CPath::addSearchPath(inputSheetPath, true, false); // for Georges to work properly - - vector files; - CPath::getPathContent (inputSheetPath, true, false, true, files); - - uint32 i; - for (i=0; i& values, const vector& labels ) : TypePredefinedValues(values), TypePredefinedLabels(labels) {} - - vector TypePredefinedValues; - vector TypePredefinedLabels; -}; - - -/* - * - */ -struct TIconMapping -{ - const char *FamilyName; - const char *IconFilename; -}; - - -/* - * - */ -sint getNomenclaturedInterestLevel( TFaberInterestLevel level, TFaberInterestLevel nbInterestLevels ) -{ - return (level == NAInterestLevel) ? 0 : (level * NbNomenclaturedFaberLevel / nbInterestLevels) + 1; -} - - -/* - * - */ -//struct CFaberCode -//{ -// char Ch[NB_FABERELEMS_CODE_CHARS]; -//}; - - -/* - * - */ -//struct CFaberCombination -//{ -// CFaberCombination( TFaberInterestLevel firstLevel, const string& code ) : FirstLevel(firstLevel) -// { -// memcpy( Code.Ch, &code[0], NB_FABERELEMS_CODE_CHARS ); -// } -// -// TFaberInterestLevel FirstLevel; -// CFaberCode Code; -//}; - - -/* - * - */ -//class CSheetNameRepository -//{ -//public: -// -// /// -// void resize( uint32 nbEcosystems, uint32 nbFamilies ) -// { -// _Container.resize( nbEcosystems ); -// for ( uint32 i=0; i!=nbEcosystems; ++i ) -// { -// _Container[i].resize( nbFamilies ); -// } -// } -// -// /// -// void insert( uint32 iEcosystem, uint32 iFamily, uint32 iCreature, TFaberInterestLevel level, const string& faberCombinationCode ) -// { -// // nlassert( faberCombinationCode.size() == NB_FABERELEMS_CODE_CHARS ); -// _Container[iEcosystem][iFamily][iCreature].push_back( CFaberCombination( level, faberCombinationCode ) ); -// } -// -// /// -// void getFaberCombinationCodes( uint32 iEcosystem, uint32 iFamily, uint32 iCreature, vector **codes ) -// { -// map < uint32, vector< CFaberCombination > >::iterator im; -// /*nldebug( "%u %u -> %u cr (searching for %u)", iEcosystem, iFamily, _Container[iEcosystem][iFamily].size(), iCreature ); -// for ( im=_Container[iEcosystem][iFamily].begin(); im!=_Container[iEcosystem][iFamily].end(); ++im ) -// nldebug( "cr %u -- %u combinations", (*im).first, (*im).second.size() );*/ -// im = _Container[iEcosystem][iFamily].find( iCreature ); -// if ( im == _Container[iEcosystem][iFamily].end() ) -// *codes = NULL; -// else -// *codes = &((im)->second); -// } -// -//private: -// -// /// Indexs: iEcosystem, iFamily, rCreatureSpecialization, rFaberCombination -// vector< vector < map < uint32, vector< CFaberCombination > > > > _Container; -//}; - - -//void CSheetNameRepository::getFaberCombinationCodes( uint32 iEcosystem, uint32 iFamily, uint32 iCreature, vector **codes ) - - -//CSheetNameRepository RawMaterialRepository; - -/** - * Characteristics. - * When adding a new characteristic, ADD IT INTO "v3_source_tables.xls!Item Parts v3"/"rm_item_parts.csv" and mark compatible item parts - */ -enum TFaberCharacteristic { - Durability, Weight, SapLoad, DMG, Speed, Range, - DodgeModifier, ParryModifier, AdversaryDodgeModifier, AdversaryParryModifier, - ProtectionFactor, MaxSlashProtect, MaxBluntProtect, MaxPierceProtect, - ECTF, EPF, - OACTF, OAPF, - HCTP, HPF, - DACTF, DAPF, - JewelProtection, - CraftCivSpec, - NbCharacs }; - -const char *sCharacs [NbCharacs] = { - "Durability", "Weight", "SapLoad", "DMG", "Speed", "Range", - "DodgeModifier", "ParryModifier", "AdversaryDodgeModifier", "AdversaryParryModifier", - "ProtectionFactor", "MaxSlashingProtection", "MaxBluntProtection", "MaxPiercingProtection", - "ElementalCastingTimeFactor", "ElementalPowerFactor", - "OffensiveAfflictionCastingTimeFactor", "OffensiveAfflictionPowerFactor", - "HealCastingTimeFactor", "HealPowerFactor", - "DefensiveAfflictionCastingTimeFactor", "DefensiveAfflictionPowerFactor", - "JewelProtectionType", - "CraftCivSpec" }; - -//const bool PositiveCharacs [NbCharacs] = { true, false, true, false, true, true }; -//const float MinCharacValues [NbCharacs] = { 100, 0.1f, 10, 0.2f, 100, 0 }; -//const float MaxCharacValues [NbCharacs] = { 500, 1.5f, 400, 2.0f, 500, 60 }; -//const float PeakCharacValues [NbCharacs] = { 2000, 2.5f, 800, 5.0f, 2000, 80 }; -bool PositiveCharacs [NbCharacs]; -float MinCharacValues [NbCharacs]; -float MaxCharacValues [NbCharacs]; -float PeakCharacValues [NbCharacs]; -vector CharacSlotFilter [NbCharacs]; // it's a positive filter - - - -/* - * - */ -struct TFamInfo -{ - vs Properties; // ex: propForA, propForB, propForC - CSString CompatibleCraftParts; // ex: ABC - vu CraftPartsByProp; // ex: 0, 1, 2 (indices in ompatibleCraftParts) - vector Civs; // ex: Fyros, All, All - vu Freqs; // ex: 1, 2, 2 - TGroup Group; - bool IsActive; // False if not in rm_fam_prop.csv - bool IsInDeposits; - bool IsInCreatures; - CSString SpecialCreatureTag; - bool GenerateOnly; - bool IsForMission; - sint8 RemarkableStatIndex [NB_REMARKABLE_STAT_INDICES]; - sint8 ColorIndex; - sint8 JewelProtIndex; - - static uint UseGenerateOnly; // if 0, generate all; otherwise, generate only families that have GenerateOnly set to true - - /// - TFamInfo() : Group(~0), IsInDeposits(false), IsActive(false), IsInCreatures(false), SpecialCreatureTag(), GenerateOnly(false), IsForMission(false), ColorIndex(-1), JewelProtIndex(-1) {} - - /// - uint getCompatibleCraftPart( uint iCompatibleCP ) const - { - return (uint)(CompatibleCraftParts[iCompatibleCP] - 'A'); - } - - /// whichProp: index in Properties - uint getBeginCraftPartForProp( uint whichProp ) const - { - return CraftPartsByProp[whichProp]; - } - - /// whichProp: index in Properties - uint getEndCraftPartForProp( uint whichProp ) const - { - if ( whichProp == Properties.size()-1 ) - return CompatibleCraftParts.size(); - else - return CraftPartsByProp[whichProp+1]; - } - - /// whichProp: index in Properties - CSString getCraftPartForProp( uint whichProp ) const - { - uint start = getBeginCraftPartForProp( whichProp ); - return CompatibleCraftParts.substr( start, getEndCraftPartForProp( whichProp ) - start ); - } - - /** With the returned index, you can get elt in Property, CraftPartsByProp, Civs and Freqs. - * Returns ~0 if not found. - */ - uint getPropIndexByCraftPart( char itemPart ) const - { - for ( uint i=0; i!=CraftPartsByProp.size(); ++i ) - { - char itemPartCode [2]; - itemPartCode[0] = itemPart; - itemPartCode[1] = '\0'; - if ( getCraftPartForProp( i ).find( itemPartCode ) != string::npos ) - return i; - } - return ~0; - } - - /// - bool existsInEcosystem( TEcosystem iEcosystem, TStatQuality statQuality ) const; - - /// - static bool mustGenerateFamily( uint iFamily ); -}; - - -const uint ITEM_PART_JEWEL_GEM = 17; // R - - -/* - * - */ -struct CFaberCharacteristics -{ - /// Default constructor (for reading) - CFaberCharacteristics() - : FaberElement(~0), ActualEnergy(0.0f), ActualOriginality(0.0f) - { - for ( uint32 i=0; i!=NbCharacs; ++i ) - Values[i] = 0.0f; - } - - /// - void serial( NLMISC::IStream& s ) - { - s.serial( FaberElement ); - s.serial( ActualEnergy ); - s.serial( ActualOriginality ); - for ( uint32 c=0; c!=NbCharacs; ++c ) - s.serial( Values[c] ); - } - - /// - void initFaberElement( uint32 rFaberElement ) { FaberElement = rFaberElement; } - - /// Returns false if the RM must NOT be generated. - bool randomizeValues( TFaberInterestLevel interestLevel, TFaberInterestLevel nbInterestLevels, uint iVariant, float widthRatio, float peakOccurRatio, float baseBoost, TEcosystem iEcosystem, uint iFreq, uint iFamily ); - - /// Returns -1 if the RM must NOT be generated, otherwise return the stat average - sint32 computeValues( TStatQuality statQuality, const TFamInfo& famInfo, sint remarkableIndicesSetBaseIndex, - TEcosystem iEcosystem, uint iFreq, uint iFamily ); - - /// - void calcQualitativeValues(); - - /// Index of faber element in "MpParam" - uint32 FaberElement; - - /// Values - float Values [NbCharacs]; - - /// Average of the actual interest of the random values between 0 and 1 - float ActualEnergy; - - /// - float ActualOriginality; - -protected: - - // Returns false if the RM must NOT be generated. - //bool randomizeJewelProtection( TStatQuality statQuality, TEcosystem iEcosystem, uint iFreq, uint iFamily ); - - void computeJewelProtection( TStatQuality statQuality, TEcosystem iEcosystem, uint iFamily ); -}; - - -// -void CFaberCharacteristics::calcQualitativeValues() -{ - float actualInterests [NbCharacs]; - - // Calculate the average of ratio between [0,1] - float sumActualInterest = 0.0f; - uint nbCharacsUsed = 0; - for ( uint r=0; r!=NbCharacs; ++r ) - { - if ( MaxCharacValues[r] == 0 ) - continue; - if ( ! CharacSlotFilter[r][FaberElement] ) - continue; - - float interestRatio = (Values[r] / PeakCharacValues[r]); // new: Peak is taken as the max => the Energy is in [0..100] - if ( ! PositiveCharacs[r] ) - interestRatio = 1.0f - interestRatio; // thus, can be negative - - actualInterests[r] = interestRatio; - sumActualInterest += interestRatio; - ++nbCharacsUsed; - } - - if ( nbCharacsUsed == 0 ) - return; - - ActualEnergy = (sumActualInterest / (float)nbCharacsUsed); - if ( ActualEnergy > 1.0f ) - ActualEnergy = 1.0f; - - // Calculate the standard deviation (SQRT(SUM((Ai-Aavg)²)/N)) - float varianceSum = 0.0f; - for ( uint r=0; r!=NbCharacs; ++r ) - { - if ( MaxCharacValues[r] == 0 ) - continue; - if ( ! CharacSlotFilter[r][FaberElement] ) - continue; - - varianceSum += sqr( actualInterests[r] - ActualEnergy ); - } - - // Don't normalize standard deviation, otherwise low energy materials will be considered more - // original (by average) than high energy materials. They wouldn't be comparable. - - //if ( ActualEnergy != 0.0f ) - ActualOriginality = (float)sqrt( (double)(varianceSum / (float)nbCharacsUsed) ); // / ActualEnergy; - //else - // nlinfo( "Null energy for craft slot %u", FaberElement ); -} - - -/* - * Fill childrenToGet if rootNameForGetChildren is not null - */ -void fillFromDFN( UFormLoader *formLoader, map& dfnFields, UFormDfn *formDfn, const string& rootName, const string& dfnFilename, - const char *rootNameForGetChildren=NULL, vector& childrenToGet=vector() ) -{ - uint32 i; - for ( i=0; i!=formDfn->getNumEntry(); ++i ) - { - string entryName, rootBase; - formDfn->getEntryName( i, entryName ); - rootBase = rootName.empty() ? "" : (rootName+"."); - - UFormDfn::TEntryType entryType; - bool array; - formDfn->getEntryType( i, entryType, array ); - switch ( entryType ) - { - case UFormDfn::EntryVirtualDfn: - { - CSmartPtr subFormDfn = formLoader->loadFormDfn( (entryName + ".dfn").c_str() ); - if ( ! subFormDfn ) - nlwarning( "Can't load virtual DFN %s", entryName.c_str() ); - else - fillFromDFN( formLoader, dfnFields, subFormDfn, rootBase + entryName, entryName + ".dfn", rootNameForGetChildren, childrenToGet ); // recurse - break; - } - case UFormDfn::EntryDfn: // .dfn - { - UFormDfn *subFormDfn; - if ( formDfn->getEntryDfn( i, &subFormDfn) ) - { - string filename; - formDfn->getEntryFilename( i, filename ); - fillFromDFN( formLoader, dfnFields, subFormDfn, rootBase + entryName, filename, rootNameForGetChildren, childrenToGet ); // recurse - } - if ( rootNameForGetChildren && (rootName == rootNameForGetChildren) ) - { - childrenToGet.push_back( rootBase + entryName ); - } - break; - } - case UFormDfn::EntryType: // .typ - { - vector values, labels; - UType *subType; - if ( formDfn->getEntryType( i, &subType ) ) - { - uint32 listSize = subType->getNumDefinition(); - if ( listSize > 0 ) - { - string label, value; - for ( uint32 j=0; j!=listSize; ++j ) - { - subType->getDefinition( j, label, value ); - if ( (subType->getIncrement() == "1") && (subType->getType() == UType::UnsignedInt || subType->getType() == UType::SignedInt) ) - { - // Fill blank entry for skipped identifier values (to allow indexing by identifier value) - sint num = atoi( value.c_str() ); - while ( num - (sint)values.size() > 0 ) - { - values.push_back( "" ); - labels.push_back( "" ); - } - } - values.push_back( value ); - labels.push_back( label ); - } - } - } - dfnFields.insert( make_pair( rootBase + entryName, CDfnFieldInfo(values, labels) ) ); - //nlinfo( "DFN entry: %s (in %s)", (rootBase + entryName).c_str(), dfnFilename.c_str() ); - break; - } - } - } -} - - -/* - * - */ -CForm *loadTemplateForm( UFormLoader *formLoader, const string& sheetType ) -{ - CForm *form = (CForm*)formLoader->loadForm( (string("_empty.")+sheetType).c_str() ); - if ( ! form ) - nlerror( "Can't load sheet _empty.%s", sheetType.c_str() ); - return form; -} - - -/* - * - */ -void eraseCarriageReturns( string& s ) -{ - const char CR = '\n'; - string::size_type p = s.find( CR ); - while ( (p=s.find( CR )) != string::npos ) - s.erase( p, 1 ); -} - - -/* - * - */ -string getNomenclatureCode( const string& longName, set& usedCodes, uint32 nbLetters ) -{ - if ( nbLetters > longName.size() ) - nlerror( "Wrong nbLetters for %s", longName.c_str() ); - - // Start with beginning of name - string code = strlwr(longName.substr( 0, nbLetters )); - uint32 i = nbLetters-1; - while ( usedCodes.find( code ) != usedCodes.end() ) - { - ++i; - if ( i < longName.size() ) - { - // Substitute last code char by a char from the name (except ' ') - if ( longName[i] != ' ' ) - code[nbLetters-1] = tolower(longName[i]); - else - continue; - } - else - { - // If no char from the name is suitable, increment the last char of the code until suitable - char c=1; - while ( usedCodes.find( code ) != usedCodes.end() ) - { - code[nbLetters-1] = tolower(longName[nbLetters-1]) + c; - ++c; - if ( code[1] > 'z' ) - nlerror( "Impossible to make code for %s", longName.c_str() ); - } - } - } - strlwr( code ); - usedCodes.insert( code ); - return code; -} - - -/* - * Displays mapping if title not null. - */ -void buildNomenclatureCodes( const char *title, const vector& longNames, vector& codes, uint32 nbLetters ) -{ - set usedCodeSet; - uint32 i; - for ( i=0; i!=longNames.size(); ++i ) - { - codes[i] = getNomenclatureCode( longNames[i], usedCodeSet, nbLetters ); - if ( title ) - nlinfo( "%s %s -> %s", title, longNames[i].c_str(), codes[i].c_str() ); - //DebugLog->displayRawNL( "%s", longNames[i].c_str() ); - } -} - - -/* - * Set the size of a family code to NB_FAMILY_CODE_CHARS - */ -void normalizeFamilyCode( std::string& s ) -{ - if ( s.size() > NB_FAMILY_CODE_CHARS ) - { - nlerror( "Family codes limited to %u chars (%s)", NB_FAMILY_CODE_CHARS, s.c_str() ); - } - else - { - uint p = s.size(); - while ( p < NB_FAMILY_CODE_CHARS ) - { - s = "0" + s; - ++p; - } - } -} - - -/* - * - */ -void loadNomenclatureCodes( const char *title, const vector& longNames, vector& codes, const char *filename ) -{ - if ( longNames.empty() ) - { - nlwarning( "No nomenclature codes to load. %s", title ? title : "" ); - return; - } - codes.resize( longNames.size() ); - - char lineBuffer[2048]; - FILE *rulesFile; - const char *SEPARATOR = ";"; - vector args; - vector::iterator iarg; - vector::const_iterator ivs; - - if ( (rulesFile = fopen( filename, "r" )) == NULL ) - { - nlwarning( "Can't find file %s", filename ); - } - else - { - while ( ! feof(rulesFile) ) - { - // Get from file - fgets( lineBuffer, 2048, rulesFile ); - explode( lineBuffer, SEPARATOR, args ); - - // Get rid of carriage returns! - for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) - { - eraseCarriageReturns( *iarg ); - } - - // Read - const uint32 MIN_COLS = 6; - const uint32 NAME_COL = 4; - const uint32 C_COL = 2; - const uint32 R_COL = 3; - const uint32 NB_CODE_CHARS = 2; - if ( (args.size()>=MIN_COLS) && (! args[0].empty()) && (args[0].find( "name" )==string::npos) ) // skip blank lines, and lines with blank header or "name" in the first column - { - if ( args[NAME_COL].empty() ) - continue; - - ivs = find( longNames.begin(), longNames.end(), args[NAME_COL] ); - if ( ivs == longNames.end() ) - nlwarning( "Name %s is not in the names array", args[NAME_COL].c_str() ); - else - { - string code = args[C_COL] + args[R_COL]; - if ( code.size() < NB_CODE_CHARS ) - { - nlwarning( "Invalid partial code for %s: %s", (*ivs).c_str(), code.c_str() ); - continue; - } - else if ( code.size() > NB_CODE_CHARS ) - { - nlinfo( "Compacting code '%s' for %s", code.c_str(), (*ivs).c_str() ); - string::size_type p; - while ( (p = code.find( ' ' )) != string::npos ) - { - code.erase( p, 1 ); - } - } - - if ( codes[ivs-longNames.begin()].empty() ) - { - if ( title ) - nlinfo( "%s %s -> %s", title, (*ivs).c_str(), code.c_str() ); - codes[ivs-longNames.begin()] = code; - } - else - { - if ( code != codes[ivs-longNames.begin()] ) - nlwarning( "Invalid nomenclature: (%s and %s for %s: ", codes[ivs-longNames.begin()].c_str(), code.c_str(), (*ivs).c_str() ); - } - } - } - } - - for ( ivs=codes.begin(); ivs!=codes.end(); ++ivs ) - { - if ( (*ivs).empty() ) - nlwarning( "No code found for %s", (*(longNames.begin() + (ivs - codes.begin()))).c_str() ); - } - } -} - - -/* - * - */ -inline sint getLastUsedPropertySlot( uint32 *iProperties, sint lastPropertySlot, uint32 undefinedProperty ) -{ - for ( sint r=lastPropertySlot; r>=0; --r ) - { - if ( iProperties[r] != undefinedProperty ) - return r; - } - return -1; -} - - -/* - * - */ -inline bool passNegativeFilter( const vector& incompatibilityList, uint32 iValue ) -{ - vector::const_iterator ip = find( incompatibilityList.begin(), incompatibilityList.end(), iValue ); - return (ip == incompatibilityList.end()); -} - - -/* - * - */ -inline bool passPositiveFilter( const vector& compatibilityList, uint32 iValue ) -{ - vector::const_iterator ip = find( compatibilityList.begin(), compatibilityList.end(), iValue ); - return (ip != compatibilityList.end()); -} - - -/* - * Reject a prop if it is in the incompatibility list of a family - */ -bool passPropFamilyFilter( const vector& iFamilyRelatedProperties, uint32 iProp ) -{ - return passNegativeFilter( iFamilyRelatedProperties, iProp ); -} - - -/* - * Reject a creature if NOT in the creature list of a family - */ -/*bool passCreatureFilter( const vector& iFamilyRelatedCreatures, uint32 iCreature ) -{ - //nldebug( "%u related creatures, %s", iFamilyRelatedCreatures.size(), passPositiveFilter( iFamilyRelatedCreatures, iCreature ) ? "TRUE": "FALSE" ); - return passPositiveFilter( iFamilyRelatedCreatures, iCreature ); -}*/ - - -/* - * - */ -class CStrIComparator : public binary_function -{ -public: - bool operator() ( const string& s1, const string& s2 ) const - { - return (nlstricmp( s1, s2 ) == 0); - } -}; - - -/* - * - */ -void displayList( const vector& v, CLog *log=DebugLog ) -{ - vector::const_iterator ist; - for ( ist=v.begin(); ist!=v.end(); ++ist ) - log->displayRaw( "%s ", (*ist).c_str() ); - log->displayRawNL( "" ); -} - - -/* - * - */ -uint32 getIndexFromString( const string& s, const vector& v, bool displayWarning=true ) -{ - if ( v.empty() ) - { - if ( displayWarning ) - nlwarning( "Can't find '%s' in empty array", s.c_str() ); - return ~0; - } - else - { - vector::const_iterator ist = find_if( v.begin(), v.end(), bind2nd(CStrIComparator(), s) ); - if ( ist == v.end() ) - { - if ( displayWarning ) - { - nlwarning( "Can't find '%s' in:", s.c_str() ); - displayList( v, WarningLog ); - } - return ~0; - } - else - return ist - v.begin(); - } -} - - -/* - * - */ -uint32 getIndexFromString( const string& s, const char **array, uint arraySize, bool displayWarning=true ) -{ - if ( arraySize == 0 ) - { - if ( displayWarning ) - nlwarning( "Can't find '%s' in empty array", s.c_str() ); - return ~0; - } - else - { - for ( uint i=0; i!=arraySize; ++i ) - { - if ( strlwr(string(array[i])) == strlwr(s) ) - return i; - } - - if ( displayWarning ) - { - nlwarning( "Can't find '%s' in:", s.c_str() ); - //displayList( v, WarningLog ); - } - return ~0; - } -} - - -/* - * Returns the index of the erased element, ~0 if not found - */ -uint32 removeEntryFromList( vector& v, const string& entry ) -{ - vector::iterator ivs; - ivs = find( v.begin(), v.end(), entry ); - uint32 index; - if ( ivs != v.end() ) - { - index = ivs - v.begin(); - v.erase( ivs ); - return index; - } - else - return ~0; -} - - -/* - * - */ -bool removeEntryFromListByIndex( vector& v, uint32 index ) -{ - if ( index < v.size() ) - { - v.erase( v.begin() + index ); - return true; - } - else - return false; -} - - -typedef void (*TMapDeliveryCallback) ( mss& ); -typedef void (*TVectorDeliveryCallback) ( vs& ); - - -/* - * - */ -void loadCSVFile( const char *filename, TMapDeliveryCallback deliveryCallback, bool firstColWithoutName=false ) -{ - char lineBuffer[2048]; - FILE *file; - const char *SEPARATOR = ";"; - vector args; - vector::iterator iarg; - - if ( (file = fopen( filename, "r" )) == NULL ) - { - nlwarning( "Can't find file %s", filename ); - } - else - { - // Read first line as header with column names - lineBuffer[0] = '\0'; - fgets( lineBuffer, 2048, file ); - explode( lineBuffer, SEPARATOR, args ); - - // Store column names (and get rid of carriage returns!) - vector < string > columnNames; - mss valuesByName; - for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) - { - if ( firstColWithoutName && (iarg == args.begin()) ) - { - *iarg = "<>"; // override column name for the 1st column - } - eraseCarriageReturns( *iarg ); - columnNames.push_back( *iarg ); - valuesByName.insert( make_pair( *iarg, string("") ) ); - } - - while ( ! feof(file) ) - { - // Get from file - lineBuffer[0] = '\0'; - fgets( lineBuffer, 2048, file ); - explode( lineBuffer, SEPARATOR, args ); - - // Set values (and get rid of carriage returns!) - for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) - { - eraseCarriageReturns( *iarg ); - valuesByName[columnNames[iarg-args.begin()]] = *iarg; - } - - // Deliver the wanted fields - deliveryCallback( valuesByName ); - } - } -} - - -/* - * - */ -void loadCSVFile( const char *filename, TVectorDeliveryCallback deliveryCallback ) -{ - char lineBuffer[2048]; - FILE *file; - const char *SEPARATOR = ";"; - vs args; - vs::iterator iarg; - - if ( (file = fopen( filename, "r" )) == NULL ) - { - nlwarning( "Can't find file %s", filename ); - } - else - { - while ( ! feof(file) ) - { - // Get from file - lineBuffer[0] = '\0'; - fgets( lineBuffer, 2048, file ); - explode( lineBuffer, SEPARATOR, args ); - - // Get rid of carriage returns! - for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) - { - eraseCarriageReturns( *iarg ); - } - - // Deliver the wanted fields - deliveryCallback( args ); - } - } -} - - -/* - * - */ -void loadValueFile( const char *filename, const vector& keyStrings, - vector& contents, sint defaultValue ) -{ - nlassert( keyStrings.size() == contents.size() ); - char lineBuffer[2048]; - FILE *rulesFile; - const char *SEPARATOR = ";"; - vector args; - vector::iterator iarg; - - if ( (rulesFile = fopen( filename, "r" )) == NULL ) - { - nlwarning( "Can't find file %s", filename ); - } - else - { - while ( ! feof(rulesFile) ) - { - // Get from file - lineBuffer[0] = '\0'; - fgets( lineBuffer, 2048, rulesFile ); - explode( lineBuffer, SEPARATOR, args ); - - // Get rid of carriage returns! - for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) - { - eraseCarriageReturns( *iarg ); - } - - // Read - if ( (! args.empty()) && (! args[0].empty()) ) // skip blank lines, and lines with blank header - { - sint value = defaultValue; - for ( uint32 a=0; a!=args.size()-1; ++a ) - { - if ( ! args[a+1].empty() ) // skip blank entries - value = atoi( args[a+1].c_str() ); - } - uint32 index = getIndexFromString( args[0], keyStrings ); - if ( index != ~0 ) - { - contents[index] = value; - } - } - } - fclose( rulesFile ); - } -} - - -/* - * - */ -void loadRulesFile( const char *filename, const vector& keyStrings, - const vector& contentStrings, CRulesFilter& filter, - const string& matchExtKeyAtFirstColumn=string() ) -{ - char lineBuffer[2048]; - FILE *rulesFile; - const char *SEPARATOR = ";"; - uint32 firstColumn = matchExtKeyAtFirstColumn.empty() ? 0 : 1; - vector args; - vector::iterator iarg; - - if ( (rulesFile = fopen( filename, "r" )) == NULL ) - { - nlwarning( "Can't find file %s", filename ); - } - else - { - while ( ! feof(rulesFile) ) - { - // Get from file - lineBuffer[0] = '\0'; - fgets( lineBuffer, 2048, rulesFile ); - explode( lineBuffer, SEPARATOR, args ); - - // Get rid of carriage returns! - for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) - { - eraseCarriageReturns( *iarg ); - } - - // Match with ext key string if set - if ( (! matchExtKeyAtFirstColumn.empty()) && (args[0]!=matchExtKeyAtFirstColumn) ) - continue; - - // Read - if ( (! args.empty()) && (! args[firstColumn].empty()) ) // skip blank lines, and lines with blank header - { - vector contents; - for ( uint32 a=firstColumn; a!=args.size()-1; ++a ) - { - if ( ! args[a+1].empty() ) // skip blank entries - contents.push_back( getIndexFromString( args[a+1], contentStrings ) ); - } - filter.insert( make_pair( getIndexFromString( args[firstColumn], keyStrings ), contents ) ); - } - } - fclose( rulesFile ); - } -} - - -/* - * 1st column: extKeyStrings (corresponding to the filters 'vector'); 2nd: keyStrings - */ -void loadRulesFileMulti( const char *filename, const vector& extKeyStrings, const vector& keyStrings, const vector& contentStrings, vector& filters ) -{ - filters.resize( extKeyStrings.size() ); - for ( uint32 i=0; i!=filters.size(); ++i ) - { - loadRulesFile( filename, keyStrings, contentStrings, filters[i], extKeyStrings[i] ); - /*CRulesFilter::const_iterator irf; - nldebug( "%s", extKeyStrings[i].c_str() ); - for ( irf=filters[i].begin(); irf!=filters[i].end(); ++irf ) - { - nldebug( "%s", keyStrings[(*irf).first].c_str() ); - vector::const_iterator ivi; - for ( ivi=(*irf).second.begin(); ivi!=(*irf).second.end(); ++ivi ) - { - nldebug( "%u", *ivi ); - } - }*/ - } -} - - -/* - * Clear the form to reuse it (and all contents below node) - */ -void clearSheet( CForm *form, UFormElm* node ) -{ - ((CFormElm*)node)->clean(); - form->clean(); -} - - -/* - * Saves to disk if bool WriteSheetsToDisk is true - */ -void flushSheetToDisk( const string& fullFilename, UForm *form ) -{ - if ( WriteSheetsToDisk ) - { - COFile output( fullFilename ); - form->write( output, false ); - } -} - - -/* - * - */ -string::size_type findCapital( const string& s, string::size_type startPos ) -{ - string::size_type p; - for ( p=startPos; p!=s.size(); ++p ) - { - if ( (s[p] >= 'A') && (s[p] <= 'Z') ) - return p; - } - return string::npos; -} - - -/* - * Transform "MyString " into "My string" - */ -void detachValue( string& s ) -{ - if ( s.size() < 2 ) - return; - - string::size_type p; - while ( (p = findCapital( s, 1 )) != string::npos ) - { - s.insert( p, " " ); - s[p+1] = tolower( s[p+1] ); - } - - // Rip off any blank at the end - if ( s[s.size()-1] == ' ' ) - { - s.resize( s.size()-1 ); - } -} - - -/* - * - */ -void getTransposedMap( CRulesFilter& dest, const CRulesFilter& src ) -{ - CRulesFilter::const_iterator im; - for ( im=src.begin(); im!=src.end(); ++im ) - { - vector::const_iterator iv; - for ( iv=(*im).second.begin(); iv!=(*im).second.end(); ++iv ) - { - dest[*iv].push_back( (*im).first ); - } - } -} - - -/* - * - */ -string makeFaberElementCode( uint32 iFaberElement, TFaberInterestLevel level, TFaberInterestLevel nbInterestLevels ) -{ - return toString( "%c%d", 'a' + iFaberElement, getNomenclaturedInterestLevel( level, nbInterestLevels ) ); -} - - -/* - * - */ -inline bool hasMatchingFaberLevel( TFaberInterestLevel storedLevel, TFaberInterestLevel submittedLevel ) -{ - return storedLevel <= submittedLevel; -} - - -/* - * - */ -//void keepOnlyHighestLevel( vector& codes ) -//{ -// nlassert( ! codes.empty() ); -// sint maxLevel = -1; -// uint32 i; -// for ( i=0; i!=codes.size(); ++i ) -// { -// if ( codes[i]->FirstLevel > maxLevel ) -// { -// maxLevel = codes[i]->FirstLevel; -// } -// } -// vector remainingCodes; -// for ( i=0; i!=codes.size(); ++i ) -// { -// if ( codes[i]->FirstLevel == maxLevel ) -// remainingCodes.push_back( codes[i] ); -// } -// -// //nldebug( "%u codes, highest level = %u with %u occurences", codes.size(), maxLevel, remainingCodes.size() ); -// //nlassert( remainingCodes.size() <= codes.size() ); -// codes = remainingCodes; -// nlassert( ! codes.empty() ); -//} - - -/* - * - */ -bool allIncludedIn( const vu& subset, const vu& bigset ) -{ - vu::const_iterator iv; - for ( iv=subset.begin(); iv!=subset.end(); ++iv ) - { - if ( find( bigset.begin(), bigset.end(), *iv ) == bigset.end() ) - return false; - } - return true; -} - - -/* - * - */ -void loadConfigFlag( CConfigFile& configFile, const char *varTitle, bool &flag ) -{ - CConfigFile::CVar *var = configFile.getVarPtr( varTitle ); - if ( var ) - flag = (var->asInt() == 1); -} - - -/* - * - */ -string::size_type getCapitalFromPos( const string& s, string::size_type startPos ) -{ - //nldebug( "%s %u", s.c_str(), startPos ); - string::size_type p; - for ( p=startPos; p= 'A') && (s[p] <= 'Z') ) - return p; - } - return string::npos; -} - - -/* - * Also used to make system_mp filenames. - * Converts "My Identifier" or "MyIdentifier" to "my_identifier" ("My identifier" to "Myidentifier") - */ -string conventionalDirectory( const string& dirname ) -{ - if ( dirname.empty() ) - return ""; - - string result = dirname; - - // Remove blanks - string::size_type p = 0; - while ( (p = result.find( ' ' )) != string::npos ) - { - result.erase( p, 1 ); - } - - // Convert capitals to underscores - result[0] = tolower( result[0] ); - p = 1; - while ( (p = getCapitalFromPos( result, p )) != string::npos ) - { - result.insert( p, "_" ); - ++p; - result[p] = tolower( result[p] ); - } - return result; -} - - -mss UniqueRMNamesAndSheetCodeHead; - - -/* - * - */ -void readRMNames( mss& values ) -{ - string& name = values["basics.name"]; - if ( ! name.empty() ) - { - string radix = values["FILE"].substr( 0, 5 ); - UniqueRMNamesAndSheetCodeHead.insert( make_pair( name, radix ) ); - } -} - - -/* - * - */ -void loadTitles( const string& sourceWords, const string& sourceBase, const string& languageCode, CTitles& dest ) -{ - STRING_MANAGER::TWorksheet worksheet; - STRING_MANAGER::loadExcelSheet( TranslationPath + sourceBase + "/" + sourceWords + "_words_" + languageCode + ".txt", worksheet ); - uint cp, cn, nbTitles = 0; - if ( worksheet.findCol( ucstring(sourceWords + " ID"), cp ) && worksheet.findCol( ucstring("name"), cn ) ) - { - for ( std::vector::iterator ip = worksheet.begin(); ip!=worksheet.end(); ++ip ) - { - if ( ip == worksheet.begin() ) // skip first row - continue; - STRING_MANAGER::TWorksheet::TRow& row = *ip; - dest.insert( make_pair( row[cp].toString(), row[cn].toUtf8() ) ); - ++nbTitles; - } - } - else - nlwarning( "%s ID or name not found", sourceWords.c_str() ); - - nlinfo( "Loaded %u %s titles", nbTitles, sourceWords.c_str() ); -} - - -/* - * - */ -void extractRawMaterialNames() -{ - loadCSVFile( ExtractNamesCsv.c_str(), readRMNames ); - FILE *output = fopen( (CFile::getFilenameWithoutExtension( ExtractNamesCsv ) + "_output.csv").c_str(), "wt" ); - fprintf( output, "Code;Name\n" ); - for ( mss::const_iterator iun=UniqueRMNamesAndSheetCodeHead.begin(); iun!=UniqueRMNamesAndSheetCodeHead.end(); ++iun ) - { - const string& codeRadix = (*iun).second; - const string& name = (*iun).first; - fprintf( output, "%s;%s\n", codeRadix.c_str(), name.c_str() ); - } -} - - -/* - * - */ -void cleanExteriorWhitespace( vs& line ) -{ - for ( vs::iterator it=line.begin(); it!=line.end(); ++it ) - { - CSString& s = (*it); - string::size_type p; - for ( p=0; p!=s.size(); ++p ) - { - if ( s[p] != ' ' ) - break; - } - if ( (p != 0) && (p != s.size()) ) - s = s.substr( p ); - - for ( p=0; p!=s.size(); ++p ) - { - if ( s[s.size()-1-p] != ' ' ) - break; - } - if ( (p != 0) && (p != s.size()) ) - s = s.rightCrop( p ); - } -} - - -uint TFamInfo::UseGenerateOnly = 0; - -// Only used for deposits; for creature, works with the creature sheets found -/*bool TFamInfo::existsInEcosystem( TEcosystem iEcosystem, TStatQuality statQuality ) const -{ - switch ( iEcosystem ) - { - case CommonEcosystem: // The Common rm exists if the rm family has a freq=2 (or 0 but only in Supreme) - return ( (find( Freqs.begin(), Freqs.end(), 2 ) != Freqs.end()) - || ((find( Freqs.begin(), Freqs.end(), 0 ) != Freqs.end()) && (statQuality == Supreme)) ); - // was: find_if ... bind2nd( equals(), 1 ) - break; - case PrimeRoots: // Only freq 1 families exist if the PrimeRoots - return find( Freqs.begin(), Freqs.end(), 1 ) != Freqs.end(); - break; - default: // A rm family exists in the ecosystem matching a civ if the corresponding freq is 1 or 3 - { - uint iCiv = getIndexFromString( ecosystemCodes[iEcosystem], CivEcosystemCodes, NbCiv, false ); - vector::const_iterator it = find( Civs.begin(), Civs.end(), (TCiv)iCiv ); - if ( it != Civs.end() ) - return (Freqs[it-Civs.begin()] == 1) || (Freqs[it-Civs.begin()] == 3); - else - return false; - } - } -}*/ - -// Only used for deposits; -bool TFamInfo::existsInEcosystem( TEcosystem iEcosystem, TStatQuality statQuality ) const -{ - if ( find( Freqs.begin(), Freqs.end(), 0 ) != Freqs.end() ) - { - // Freq 0 => only Common/Supreme - return (statQuality == Supreme) && (iEcosystem == CommonEcosystem); - } - else if ( statQuality <= Fine ) - { - // Basic, Fine => Common - return (iEcosystem == CommonEcosystem); - } - else - { - // Choice to Supreme => One per ecosystem - return (iEcosystem != CommonEcosystem) && (iEcosystem < NbEcosystems); - } -} - - -/* - * - */ -struct TCraftPartInfo -{ - CSString Name; - CSString Path; - uint8 PartIndex; - bool Enabled; -}; - - -/* - * - */ -class CCraftParts -{ -public: - - /// - CCraftParts() : CraftParts( NbFaberElements ) - { - for ( uint i=0; i!=NbFaberElements; ++i ) - { - CraftParts[i].PartIndex = i; - CraftParts[i].Enabled = false; - } - } - - /// - void registerPartChars( const CSString& parts ) - { - for ( string::size_type p=0; p!=parts.size(); ++p ) - { - uint index = (uint)(parts[p] - 'A'); - CraftParts[index].Enabled = true; - } - } - - /// - bool isEnabled( uint index ) const - { - return CraftParts[index].Enabled; - } - - /// - void getNamesAndPaths( const vector& paths ) - { - uint i = 0; - vector::const_iterator ip; - for ( ip=paths.begin(); ip!=paths.end(); ++ip ) - { - if ( i >= CraftParts.size() ) - nlerror( "Mismatch between sitem DFN and constant (nb of craft parts)" ); - - CraftParts[i].Path = (*ip); - string::size_type p = (*ip).rfind( '.' ) + 1; // string::npos+1 gives 0 - CraftParts[i].Name = (*ip).substr( p ); - nldebug( "%u: %s", ip-paths.begin(), CraftParts[i].Name.c_str() ); - ++i; - } - } - - /// - TCraftPartInfo& operator[] ( uint index ) { return CraftParts[index]; } - - vector< TCraftPartInfo > CraftParts; - -}; - -typedef map CFamMap; -CFamMap FamSet; -CCraftParts CraftParts; - -enum TFamAndPropLine { - LFam, LGroup, LCraftParts, LCiv, LFreq, LLoc, - LIconMain, LIconBk, LIconOv1, LIconOv2, LIconSpecial, - LCraftPlans, LGenerateOnly, - LBaseOfRemarkableStatIndices, - LColorIndex = LBaseOfRemarkableStatIndices + NB_REMARKABLE_STAT_INDICES, - LJewelProtIndex, - NbFamAndPropCols }; - - -// static -bool TFamInfo::mustGenerateFamily( uint iFamily ) -{ - if ( families[iFamily].empty() ) - return false; - else if ( ! TFamInfo::UseGenerateOnly ) - return true; - else - { - TFamInfo& famInfo = FamSet[families[iFamily]]; - return ( famInfo.GenerateOnly ); - } -} - - -/* - * - */ -CSString getShortFaberElemString( uint rFaberElem ) -{ - string& longString = CraftParts[rFaberElem].Name; - return reinterpret_cast(longString.substr( longString.find( "(" ) + 1 )).rightCrop( 1 ); -} - - -/* - * - */ -TCiv getCivFromStr( const CSString& civStr ) -{ - if ( civStr.empty() ) - return AllCiv; - else - { - for ( uint i=0; i!=NbCiv; ++i ) - { - if ( civStr == CSString(CivNames[i]) ) - return (TCiv)i; - } - nlwarning( "Unknown civ '%s'", civStr.c_str() ); - return AllCiv; - } -} - - -/* - * - */ -uint getFreqFromStr( const CSString& freqStr ) -{ - uint f = atoi( freqStr.c_str() ); - if ( (f < 1) && (f > 5) ) - nlwarning( "Unknown freq '%s'", freqStr.c_str() ); - return f; -} - - -/* - * Returns ~0 if s is empty - */ -TGroup getNewOrExistingGroupFromStr( const CSString& s ) -{ - uint i = getIndexFromString( s, groups, false ); - if ( i == ~0 ) - { - if ( s.empty() ) - return ~0; - else - { - i = groups.size(); - groups.push_back( s ); - nlinfo( "New group: %s (%u)", s.c_str(), i ); - } - } - return i; -} - - -/* - * - */ -void deliverFamAndProp( vs& line ) -{ - if ( line.size() < NbFamAndPropCols ) - line.resize( NbFamAndPropCols ); - - cleanExteriorWhitespace( line ); - - if ( line[LFam].empty() ) - { - // Load special icons - if ( (line.size() >= LIconSpecial+1) && (! line[LIconSpecial].empty()) && (line[LIconMain].empty()) ) - { - /*if ( line.size() >= LIconMain+1 ) - Icons[line[LIconSpecial]].Icon = line[LIconMain];*/ - if ( line.size() >= LIconBk+1 ) - Icons[line[LIconSpecial]].IconBackground = line[LIconBk]; - if ( line.size() >= LIconOv1+1 ) - Icons[line[LIconSpecial]].IconOver = line[LIconOv1]; - } - return; - } - - // Load icons of families - if ( line.size() >= LIconMain+1 ) - { - Icons[line[LFam]].Icon = line[LIconMain]; - if ( ! line[LGroup].empty() ) - { - // For group, set icon of first family of group found! (for forage source knowledge) - if ( Icons.find( line[LGroup] ) == Icons.end() ) - { - Icons[line[LGroup]].Icon = line[LIconMain]; - } - } - } - if ( line.size() >= LIconBk+1 ) - Icons[line[LFam]].IconBackground = line[LIconBk]; - if ( line.size() >= LIconOv1+1 ) - Icons[line[LFam]].IconOver = line[LIconOv1]; - - TFamInfo& famInfo = FamSet[line[LFam]]; - famInfo.IsActive = true; - /*if ( ! line[LCraftParts].empty() ) - { - // Store by property (line[LProp]) - famInfo.Properties.push_back( line[LProp] ); - famInfo.CraftPartsByProp.push_back( famInfo.CompatibleCraftParts.size() ); // beginning of craft parts chars - famInfo.CompatibleCraftParts += line[LCraftParts]; - CraftParts.registerPartChars( line[LCraftParts] ); - famInfo.Civs.push_back( getCivFromStr( line[LCiv] ) ); - famInfo.Freqs.push_back( getFreqFromStr( line[LFreq] ) ); - famInfo.IsInDeposits = line[LLoc].contains( "D" ); - famInfo.IsInCreatures = line[LLoc].contains( "C" ); - if ( ! (famInfo.IsInDeposits || famInfo.IsInCreatures) ) - nlwarning( "Unknown loc for %s", line[LFam].c_str() ); - }*/ - - for ( string::size_type p=0; p!=line[LCraftParts].size(); ++p ) - { - // Store by property = craft part (each char of line[LCraftParts]) - CSString craftPart = string( 1, line[LCraftParts][p]); - famInfo.Properties.push_back( craftPart ); - famInfo.CraftPartsByProp.push_back( famInfo.CompatibleCraftParts.size() ); - famInfo.CompatibleCraftParts += craftPart; - CraftParts.registerPartChars( craftPart ); - famInfo.Civs.push_back( getCivFromStr( line[LCiv] ) ); - famInfo.Freqs.push_back( getFreqFromStr( line[LFreq] ) ); - } - if ( line[LCraftParts].empty() ) - { - famInfo.Freqs.push_back( getFreqFromStr( line[LFreq] ) ); // freq needed for Rarity computation - } - famInfo.Group = getNewOrExistingGroupFromStr( line[LGroup] ); - famInfo.IsInDeposits = line[LLoc].contains( "D" ); - famInfo.IsInCreatures = line[LLoc].contains( "C" ); - if ( ! (famInfo.IsInDeposits || famInfo.IsInCreatures) ) - { - famInfo.SpecialCreatureTag = line[LLoc]; - if ( (famInfo.SpecialCreatureTag[0] != 'G') && (famInfo.SpecialCreatureTag[0] != 'I') ) - nlwarning( "Unknown loc %s for %s", line[LLoc].c_str(), line[LFam].c_str() ); - } - famInfo.IsForMission = line[LCraftParts].empty(); - for ( uint i=0; i!=NB_REMARKABLE_STAT_INDICES; ++i ) - { - if ( line[LBaseOfRemarkableStatIndices+i].empty() && (! line[LCraftParts].empty()) && (line[LFreq] != "0") ) - nlerror( "%s has empty stat index %u", line[LFam].c_str(), i ); - famInfo.RemarkableStatIndex[i] = atoi( line[LBaseOfRemarkableStatIndices+i].c_str() ); - } - if ( ! line[LColorIndex].empty() ) - famInfo.ColorIndex = atoi( line[LColorIndex].c_str() ); - if ( ! line[LJewelProtIndex].empty() ) - famInfo.JewelProtIndex = atoi( line[LJewelProtIndex].c_str() ); - bool markedForGeneration = (line[LGenerateOnly] == "X"); - if ( (!markedForGeneration) && famInfo.GenerateOnly ) - { - nlwarning( "Found duplicate family line with different GenerateOnly setting" ); - } - else - { - famInfo.GenerateOnly = markedForGeneration; - } - if ( famInfo.GenerateOnly ) - ++TFamInfo::UseGenerateOnly; -} - - -typedef map< TGroup, set > CGroupMap; - - -/* - * - */ -void loadFamAndProp( const string& filename, bool displayAll ) -{ - loadCSVFile( filename.c_str(), deliverFamAndProp ); - - if ( displayAll ) - { - set propSet; - CGroupMap groupMap; - - /// Generate contents of item_mp_family.typ (and fill group map) - nlinfo( "item_mp_family.typ:" ); - InfoLog->displayRawNL( "" ); - uint i = 1; - for ( CFamMap::iterator iss=FamSet.begin(); iss!=FamSet.end(); ++iss ) - { - const CSString& famStr = (*iss).first; - TFamInfo& famInfo = (*iss).second; - InfoLog->displayRawNL( "", famStr.c_str(), i ); - - // Get info about props and group - for ( vs::iterator ip=famInfo.Properties.begin(); ip!=famInfo.Properties.end(); ++ip ) - { - propSet.insert( *ip ); - } - groupMap[ famInfo.Group ].insert( i ); // ~0 is for "no group" (creature's RMs only) - ++i; - } - - /* - /// Generate family-specialized forage search bricks (TODO) - nlinfo( "Family-specialized forage search bricks:"); - i = 1; - for ( CGroupMap::iterator igm=groupMap.begin(); igm!=groupMap.end(); ++igm ) - { - CSString skill = toString( "SHFM%u", i ); - CSString rmgrpBrickCode = toString( "BHFPMB%02u", i ); - CSString rmfamBrickFamCode = "BHFPMI" + string( 1, (char)'A' + ((char)(i-1)) ); - uint j = 1; - for ( set:::iterator ifs=(*igm).begin(); ifs!=(*igm).end(); ++ifs ) - { - // TODO: modifier of modifier - CSString brickCode = rmfamBrickFamCode + toString( "%02u", j ); - InfoLog->displayRawNL( "%s\t80\t%s\t%u\t\t%s\t\tFG_RMFAM_FILT: %u\t", brickCode.c_str(), rmgrpBrickCode.c_str(), j, skill.c_str(), (*ifs) ); - ++j; - } - } - - /// Generate family-specialized forage search phrases (TODO) - nlinfo( "Family-specialized forage search phrases:"); - i = 1; - for ( CFamMap::iterator iss=FamSet.begin(); iss!=FamSet.end(); ++iss ) - { - const CSString& famStr = (*iss).first; - TFamInfo& famInfo = (*iss).second; - InfoLog->displayRawNL( "", famStr.c_str(), i ); - } - - /// Generate family-specialized forage extraction bricks (TODO) - nlinfo( "Family-specialized forage extraction bricks:"); - i = 1; - for ( CFamMap::iterator iss=FamSet.begin(); iss!=FamSet.end(); ++iss ) - { - const CSString& famStr = (*iss).first; - TFamInfo& famInfo = (*iss).second; - InfoLog->displayRawNL( "", famStr.c_str(), i ); - ++i; - } - - /// Generate family-specialized forage extraction phrases (TODO) - nlinfo( "Family-specialized forage extraction phrases:"); - i = 1; - for ( CFamMap::iterator iss=FamSet.begin(); iss!=FamSet.end(); ++iss ) - { - const CSString& famStr = (*iss).first; - TFamInfo& famInfo = (*iss).second; - InfoLog->displayRawNL( "", famStr.c_str(), i ); - ++i; - }*/ - - /// Generate item_mp_property.typ - nlinfo( "Item parts as props:" ); - InfoLog->displayRawNL( "" ); - i = 1; - for ( set::iterator iss=propSet.begin(); iss!=propSet.end(); ++iss ) - { - InfoLog->displayRawNL( "", (*iss).c_str(), i ); - ++i; - } - - /// Generate item_mp_group.typ - nlinfo( "Groups:" ); - InfoLog->displayRawNL( "" ); - i = 1; - for ( CGroupMap::iterator igm=groupMap.begin(); igm!=groupMap.end(); ++igm ) - { - if ( (*igm).first != ~0 ) - { - InfoLog->displayRawNL( "", (groups[(*igm).first]).c_str(), i ); - ++i; - } - } - - /* - /// Generate group-specialized forage search bricks (TODO) - nlinfo( "Group-specialized forage search bricks:"); - i = 1; - for ( CGroupMap::iterator igm=groupMap.begin(); igm!=groupMap.end(); ++igm ) - { - CSString skill = toString( "SHFM%u", i ); - CSString rmgrpBrickCode = toString( "BHFPMB%02u", i ); - ++i; - } - - /// Generate group-specialized forage search phrases - nlinfo( "Group-specialized forage search phrases:"); - i = 1; - for ( set::iterator iss=groupSet.begin(); iss!=groupSet.end(); ++iss ) - { - if ( (*iss).empty() ) - continue; - InfoLog->displayRawNL( "", (*iss).c_str(), i ); - ++i; - } - - /// Generate group-specialized forage extraction bricks - nlinfo( "Group-specialized forage extraction bricks:"); - i = 1; - for ( set::iterator iss=groupSet.begin(); iss!=groupSet.end(); ++iss ) - { - if ( (*iss).empty() ) - continue; - InfoLog->displayRawNL( "", (*iss).c_str(), i ); - ++i; - } - - /// Generate group-specialized forage extraction phrases - nlinfo( "Group-specialized forage extraction phrases:"); - i = 1; - for ( set::iterator iss=groupSet.begin(); iss!=groupSet.end(); ++iss ) - { - if ( (*iss).empty() ) - continue; - InfoLog->displayRawNL( "", (*iss).c_str(), i ); - ++i; - }*/ - - nlinfo( "TODO: Keep old values when adding new entries" ); - nlinfo( "Don't forget to regen craft plans and to map localized texts" ); - } -} - - -/* - * Multi-indexed array. - * NC is the number of columns. - */ -template -class CSortableData -{ -public: - - /// A row is made of fields, usually 1 per column but there may be more than one (each one is a key) - struct TSortableItem - { - std::vector Fields [NC]; - - /// - void push( uint32 column, const std::string& f, bool allowDuplicates=false ) - { - if ( (allowDuplicates) || (find( Fields[column].begin(), Fields[column].end(), f ) == Fields[column].end()) ) - Fields[column].push_back( f ); - } - - /** - * Display the item as a row of a HTML table. - * If (key!=previousKey) and (name==previousName), the row will not be displayed entirely to save space - * - * \param keyColumn If not ~0, column used for sorting => this column displays only the field matching the key - * \param key The key used for sorting (see keyColumn) - * \param previousKey Previous key - * \param nameColumn If not ~0, column used for the unique name (column must have exaclty one element) - * \param previousName Previous name - */ - std::string toHTMLRow( uint32 keyColumn=~0, const string& key=string(), const string& previousKey=string(), - uint32 nameColumn=~0, const string& previousName=string() ) const - { - std::string s = "
    "; - bool lightMode = (nameColumn == ~0) ? false : ((key != previousKey) && (Fields[nameColumn][0] == previousName)); - for ( uint32 c=0; c!=NC; ++c ) - { - s += ""; - } - s += "\n"; - return s; - } - - - /// - std::string toCSVLine( char columnSeparator=',', string internalSeparator=" - ", uint32 keyColumn=~0, const string& key=string(), const string& previousKey=string(), - uint32 nameColumn=~0, const string& previousName=string() ) const - { - std::string s; - bool lightMode = (nameColumn == ~0) ? false : ((key != previousKey) && (Fields[nameColumn][0] == previousName)); - for ( uint32 c=0; c!=NC; ++c ) - { - if ( c == keyColumn ) - s += key; // key should be a substr of columnToString( c ) - else - { - if ( lightMode ) - s += "\""; - else - s += columnToString( c, internalSeparator ); - } - s += columnSeparator; - } - s += "\n"; - return s; - } - - /// - std::string columnToString( uint32 column, const std::string& internalSeparator=", " ) const - { - std::string s; - std::vector::const_iterator ivs; - for ( ivs=Fields[column].begin(); ivs!=Fields[column].end(); ++ivs ) - { - if ( ivs!=Fields[column].begin() ) - s += internalSeparator; - s += (*ivs); - } - return s; - } - }; - - typedef std::multimap< std::string, uint32 > CLookup; // key to index (not pt because reallocation invalidates pointers) - typedef std::vector< TSortableItem > CItems; - - /// Init - void init( bool enabled ) - { - _Enabled = enabled; - } - - /// Add a row - void addItem( const TSortableItem& item ) - { - if ( ! _Enabled ) - return; - - _Items.push_back( item ); - for ( uint32 c=0; c!=NC; ++c ) - { - for ( std::vector::const_iterator ik=item.Fields[c].begin(); ik!=item.Fields[c].end(); ++ik ) - { - _Indices[c].insert( make_pair( *ik, _Items.size()-1 ) ); - } - } - } - - /** - * Update a row (found by the first column, which must have exactly one element). - * Returns true if it existed before, false if it's being created. - * If it existed before: - * - Does not remove elements that already exist and are not in the new item - * - Adds the new elements found in the new item at the specified columns, and updates lookup map - */ - bool updateItemAppend( const TSortableItem& item, uint32 column ) - { - if ( ! _Enabled ) - return true; // quiet - - uint32 nameColumn = 0; - CLookup::iterator ilk = _Indices[nameColumn].find( item.Fields[nameColumn][0] ); - if ( ilk != _Indices[nameColumn].end() ) - { - uint32& index = (*ilk).second; - - // Update map for the specified column - // and update item column - for ( std::vector::const_iterator ivs=item.Fields[column].begin(); ivs!=item.Fields[column].end(); ++ivs ) - { - ilk = _Indices[column].find( *ivs ); - if ( (ilk == _Indices[column].end()) || ( getRow( (*ilk).second ).Fields[nameColumn][0] != item.Fields[nameColumn][0]) ) - { - _Indices[column].insert( make_pair( *ivs, index ) ); - _Items[index].Fields[column].push_back( *ivs ); - } - } - - return true; - } - else - { - addItem( item ); - return false; - } - } - - /** - * Update a row (found by the first column, which must have exactly one element). - * Returns true if it existed before, false if it's being created. - * If it existed before: - * - Does not update lookup maps or item for columns that were already present. - * - Adds entries in lookup maps and updates item for new columns (fields that were empty). - */ - /*bool updateItemAppend( const TSortableItem& item ) - { - if ( ! _Enabled ) - return true; // quiet - - CLookup::iterator ilk = _Indices[0].find( item.Fields[0][0] ); - if ( ilk != _Indices[0].end() ) - { - uint32& index = (*ilk).second; - - for ( uint32 c=1; c!=NC; ++c ) - { - // Update maps for previously empty columns - if ( _Items[index].Fields[c].empty() ) - { - for ( std::vector::iterator ivs=item.Fields[c].begin(); ivs!=item.Fields[c].end(); ++ivs ) - _Indices[c].insert( make_pair( *ivs, index ) ); - } - - // Update item column - _Items[index].Fields[c] = item.Fields[c]; - } - - return true; - } - else - { - addItem( item ); - return false; - } - }*/ - - /// Find or browse by key - CLookup& lookup( uint32 column ) - { - return _Indices[column]; - } - - /// Browse by adding order - CItems& items() - { - return _Items; - } - - /// Get a row by index - TSortableItem& getRow( uint32 index ) - { - return _Items[index]; - } - -private: - - CLookup _Indices [NC]; - - CItems _Items; - - bool _Enabled; -}; - - -typedef CSortableData CRMData; -typedef CRMData::TSortableItem TRMItem; - - -/** - * - */ -class CProducedDocHtml -{ -public: - - /// - CProducedDocHtml() : _File(NULL), _Enabled(false) {} - - /// - void open( const std::string& filename, const std::string& title, bool enableFlag ) - { - _Enabled = enableFlag; - if ( ! _Enabled ) - return; - - _File = fopen( filename.c_str(), "wt" ); - fprintf( _File, ("\n\n" + title + "\n\n").c_str() ); - } - - /// - void write( const std::string& htmlCode ) - { - if ( ! _Enabled ) - return; - - fprintf( _File, htmlCode.c_str() ); - } - - /// - void writeln( const std::string& htmlCode ) - { - write( htmlCode + "\n" ); - } - - /// - void writebln( const std::string& htmlCode ) - { - write( htmlCode + "
    \n" ); - } - - /// - void writepln( const std::string& htmlCode ) - { - write( "

    " + htmlCode + "

    \n" ); - } - - /// - void save() - { - if ( ! _Enabled ) - return; - - fprintf( _File, "\n" ); - fclose( _File ); - } - -private: - - FILE *_File; - bool _Enabled; -}; - - -/** - * - */ -class CProducedDocCSV -{ -public: - - /// - CProducedDocCSV() : _File(NULL), _Enabled(false) {} - - /// - void open( const std::string& filename, bool enableFlag ) - { - _Enabled = enableFlag; - if ( ! _Enabled ) - return; - - _File = fopen( filename.c_str(), "wt" ); - } - - /// - void write( const std::string& data ) - { - if ( ! _Enabled ) - return; - - fprintf( _File, data.c_str() ); - } - - /// - void writeln( const std::string& data ) - { - write( data + "\n" ); - } - - /// - void save() - { - if ( ! _Enabled ) - return; - - fclose( _File ); - } - -private: - - FILE *_File; - bool _Enabled; -}; - - - -/** - * - */ -class CGenRawMaterial -{ -public: - - /// Constructor - CGenRawMaterial( const std::string& sheetName = std::string() ) : SheetName(sheetName), ILocation(~0), IFamily(~0), IEcosystem(NbEcosystems), StatQuality(InvalidStatQuality), Color(InvalidColor), StatEnergyAvg(0) - {} - - /// Serial - void serial( NLMISC::IStream& s ) - { - s.serial( SheetName ); - s.serial( (uint32&)ILocation ); - s.serial( (uint32&)IFamily ); - s.serial( (uint32&)Group ); - s.serial( (uint32&)IEcosystem ); - s.serial( (uint32&)StatQuality ); - s.serial( (sint32&)Color ); - //s.serial( (uint32&)SapLoadLevel ); - //s.serial( (uint32&)Rarity ); - s.serial( (sint32&)StatEnergyAvg ); - s.serial( (uint32&)MaxLevel ); - s.serialCont( RMProperties ); - s.serialCont( IPropertyDepths ); - s.serialCont( RMCraftCharacs ); - } - - /// Computes randomly RMCraftCharacs, IPropertyDepths... Returns false if the RM must NOT be generated. - bool computeCraftCharacs( uint iVariant, const CSString& sheetName ); - - /// - void writeSheet( CForm *form ); - - /// - void loadSheet( CForm *form, const std::string& sheetName, bool full ); - - /// - void collectStats( TRMItem& item, CMainStat& mainStats ); - - /// Return average of energies (including max quality as half of the balance) - /*float getEnergyAvg() const - { - if ( RMCraftCharacs.empty() ) - return 0.0f; - else - { - float sum = 0.0f; - for ( list::const_iterator ics=RMCraftCharacs.begin(); ics!=RMCraftCharacs.end(); ++ics ) - { - sum += (*ics).ActualEnergy; - } - //return (sum + (float)MaxQuality / 250.0f) / ((float)RMCraftCharacs.size() + 1); - return (sum / (float)RMCraftCharacs.size()); // now, MaxQuality is not part of the average - } - }*/ - - /// - float getOriginalityAvg() const - { - float sum = 0.0f; - for ( list::const_iterator ics=RMCraftCharacs.begin(); ics!=RMCraftCharacs.end(); ++ics ) - { - sum += (*ics).ActualOriginality; - } - return sum / (float)RMCraftCharacs.size(); - } - - /// - float getOriginalityMax() const - { - float maxOriginality = 0.0f; - for ( list::const_iterator ics=RMCraftCharacs.begin(); ics!=RMCraftCharacs.end(); ++ics ) - { - if ( (*ics).ActualOriginality > maxOriginality ) - maxOriginality = (*ics).ActualOriginality; - } - return maxOriginality; - } - - /// - void fillPropertiesFromFamily() - { - vs& props = FamSet[familyStr()].Properties; - RMProperties.resize( props.size() ); - for ( vs::iterator ip=props.begin(); ip!=props.end(); ++ip ) - { - RMProperties[ip-props.begin()] = getIndexFromString( *ip, properties ); - } - } - - /// - bool hasCraftPart( uint craftPartIndex ) - { - return CraftParts.isEnabled( craftPartIndex ) && (FamSet[familyStr()].CompatibleCraftParts.find( string( 1, (char)'A' + craftPartIndex ).c_str() ) != string::npos); - } - - /// - /*TCiv getCivSpec( uint craftPartIndex, const TFamInfo& famInfo ) - { - TCiv civ = NbCiv; - for ( vector::const_iterator ivc=famInfo.Civs.begin(); ivc!=famInfo.Civs.end(); ++ivc ) - { - // Skip those not matching the current rFaberElem - if ( famInfo.getCraftPartForProp( ivc-famInfo.Civs.begin() ).find( string( 1, (char)('A' + craftPartIndex) ).c_str() ) != string::npos ) - { - if ( (civ != NbCiv) && ((*ivc) != civ) ) - { - nlwarning( "Different civ specializations for %s, %s (%s and %s)", familyStr().c_str(), getShortFaberElemString( craftPartIndex ).c_str(), CivNames[civ], CivNames[*ivc] ); - return AllCiv; - } - civ = (*ivc); - } - } - if ( civ == NbCiv ) - return AllCiv; - else if ( civ = - return civ; - }*/ - - /// - TCiv getCivSpec( TEcosystem iEcosystem, TStatQuality statQuality ) - { - if ( (statQuality <= Fine) || (iEcosystem >= NbEcosystems) ) - return AllCiv; - else - return EcosystemToCiv[iEcosystem]; - } - - /// - /*TCiv getMainCivSpec( const TFamInfo& famInfo ) - { - TCiv civ = NbCiv; - for ( list::const_iterator ics=RMCraftCharacs.begin(); ics!=RMCraftCharacs.end(); ++ics ) - { - TCiv civOfCraftPart = getCivSpec( (*ics).FaberElement, famInfo ); - if ( (civ != NbCiv) && (civOfCraftPart != civ) ) - { - return AllCiv; - } - civ = civOfCraftPart; - } - if ( civ == NbCiv ) - return AllCiv; - else - return civ; - }*/ - - /// - /*const char * getMainEcosystemSpec( const TFamInfo& famInfo ) - { - return CivEcosystemCodes[getMainCivSpec( famInfo )]; - }*/ - - /// Code - CSString SheetName; - - /// Index in locations - uint32 ILocation; - - /// Index in families - uint32 IFamily; - - /// - CSString familyStr() const { return families[IFamily]; } - - /// Group number - TGroup Group; - - /// - CSString groupStr() const { return Group==~0 ? "" : groups[Group]; } - - /// Index in ecosystems - TEcosystem IEcosystem; - - /// - CSString ecosystemStr() const { return ecosystems[IEcosystem]; } - - /// From Basic) to Supreme) - TStatQuality StatQuality; - - /// From 'b' (Basic) to 'f' (Supreme) - char levelZoneLChar() const { return 'b' + (char)StatQuality; } - - /// Same - void setStatQuality( char levelZoneChar ) { StatQuality = (TStatQuality)(levelZoneChar - 'b'); } - - /// For creatures - uint32 ILevelZone; - - /// Index in colors - TColor Color; - - /// - CSString colorStr() const { return colors[Color]; } - - /// Sap load level - //uint32 SapLoadLevel; - - /// Rarity - //uint32 Rarity; - - sint32 StatEnergyAvg; - - /// Max quality - uint32 MaxLevel; - - /// Indices in properties - vu RMProperties; - - /// - CSString propertyStr( uint32 p ) const { return properties[RMProperties[p]]; } - - /// - vu IPropertyDepths; - - /// - CSString propertyDepthStr( uint32 p ) const { return PropertyDepths[IPropertyDepths[p]]; } - - /// - CFaberCharacteristics *getCraftSlot( uint rFaberElem ) - { - std::list< CFaberCharacteristics >::iterator icl; - for ( icl=RMCraftCharacs.begin(); icl!=RMCraftCharacs.end(); ++icl ) - { - if ( (*icl).FaberElement == rFaberElem ) - return &(*icl); - } - return NULL; - } - - /// Randomly generated characs - std::list< CFaberCharacteristics > RMCraftCharacs; -}; - - -/** - * - */ -class COriginalitySorter -{ -public: - - typedef std::set< CGenRawMaterial* > CRMSet; - typedef std::multimap< uint32, CGenRawMaterial*, std::greater > CMultiMapByOriginality; - - /// - COriginalitySorter() : RMByOriginalityByCraftSlot( NbFaberElements ) {} - - /// - void pushRM( CGenRawMaterial *rawMaterial ) - { - RawMaterials.insert( rawMaterial ); - - //InfoLog->displayRawNL( "Inserting RM" ); - std::list< CFaberCharacteristics >::const_iterator ilc; - for ( ilc=rawMaterial->RMCraftCharacs.begin(); ilc!=rawMaterial->RMCraftCharacs.end(); ++ilc ) - { - //InfoLog->displayRawNL( " %u: %s orig=%u", (*ilc).FaberElement, rawMaterial->SheetName.c_str(), (uint32)((*ilc).ActualOriginality*100.0f) ); - RMByOriginalityByCraftSlot[(*ilc).FaberElement].insert( make_pair( (uint32)((*ilc).ActualOriginality*100.0f), rawMaterial ) ); - } - } - - /// - void popAndDeleteRM( CGenRawMaterial *rawMaterial ) - { - delete rawMaterial; - RawMaterials.erase( rawMaterial ); - } - - /// - bool alreadyPopped( CGenRawMaterial *rawMaterial ) const - { - return RawMaterials.find( rawMaterial ) == RawMaterials.end(); - } - - /// fromPos and the returned iterator are the pos internal to the COriginalitySorter RM set - /*CRMSet::const_iterator getFirstRMNotInFamilyListFromPos( const set& familyList, TStatQuality statQuality, CRMSet::const_iterator fromPos ) const - { - CRMSet::const_iterator irm; - for ( irm=fromPos; irm!=RawMaterials.end(); ++irm ) - { - if ( ((*irm)->StatQuality == statQuality) && - (familyList.find( (*irm)->IFamily ) == familyList.end()) ) - return irm; - } - return RawMaterials.end(); - }*/ - - /// - CRMSet::iterator getRMSetBegin() const { return RawMaterials.begin(); } - - /// - CRMSet::iterator getRMSetEnd() const { return RawMaterials.end(); } - - /// - void deleteAllRemainingRM() - { - CRMSet::iterator irm; - for ( irm=RawMaterials.begin(); irm!=RawMaterials.end(); ++irm ) - { - delete (*irm); - } - RawMaterials.clear(); - // Does not clear the maps by originality - } - - std::vector< CMultiMapByOriginality > RMByOriginalityByCraftSlot; - -private: - - CRMSet RawMaterials; -}; - - -#define checkColor( c ) nlassert( colors[c] == #c ); - - -/* - * - */ -void loadDFNs( UFormLoader *formLoader ) -{ - map dfnFields; - NLMISC::CSmartPtr formDfn; - formDfn = formLoader->loadFormDfn( (rmSheetType + ".dfn").c_str() ); - if ( ! formDfn ) - nlerror( "Can't find DFN for %s", rmSheetType.c_str() ); - vector craftPartsPaths; - fillFromDFN( formLoader, dfnFields, formDfn, "", rmSheetType, "mp.MpParam", craftPartsPaths ); - - // Get craft parts - CraftParts.getNamesAndPaths( craftPartsPaths ); - - formDfn = formLoader->loadFormDfn( (crSheetType + ".dfn").c_str() ); - if ( ! formDfn ) - nlerror( "Can't find DFN for %s", crSheetType.c_str() ); - fillFromDFN( formLoader, dfnFields, formDfn, "", crSheetType ); - - // Get lists of predefined values from sitem and creature DFN - families = dfnFields["mp.Family"].TypePredefinedLabels; - familyCodes = dfnFields["mp.Family"].TypePredefinedValues; - groups = dfnFields["mp.Group"].TypePredefinedLabels; - - //properties = dfnFields["mp.Material property 1"].TypePredefinedLabels; - //nlverify( removeEntryFromList( properties, "Undefined" ) != ~0 ); - properties.resize( craftPartsPaths.size() ); - for ( uint i=0; i!=properties.size(); ++i ) // now, use properties as item part list - properties[i] = string( 1, (char)('A' + i) ); - - ecosystems = dfnFields["mp.Ecosystem"].TypePredefinedLabels, - colors = dfnFields["mp.MpColor"].TypePredefinedLabels, - creatures = dfnFields["Basics.Race"].TypePredefinedLabels; - seasons.push_back( "Winter" ); - seasons.push_back( "Spring" ); - seasons.push_back( "Summer" ); - seasons.push_back( "Autumn" ); - //removeEntryFromList( families, "Undefined" ); - //removeEntryFromList( familyCodes, "0" ); - nlverify( removeEntryFromList( ecosystems, "unknown" ) != ~0 ); - nlverify( removeEntryFromList( ecosystems, "Goo" ) != ~0 ); - nlassert( ecosystems[0] == "Common" ); - nlassert( ecosystems[1] == "Desert" ); // ensure we match with enum TEcosystem! - nlassert( ecosystems[2] == "Forest" ); - nlassert( ecosystems[3] == "Lacustre" ); - nlassert( ecosystems[4] == "Jungle" ); - nlassert( ecosystems[5] == "PrimeRoots" ); - //removeEntryFromList( ecosystems, "Common" ); // TODO - nlassert( NbEcosystems == ecosystems.size() ); - nlverify( removeEntryFromList( colors, "None" ) != ~0 ); - nlverify( removeEntryFromList( colors, "UserColor") != ~0 ); - nlassert( colors.size() == NbColors ); - checkColor( Red ); - checkColor( Beige ); - checkColor( Green ); - checkColor( Turquoise ); - checkColor( Blue ); - checkColor( Violet ); - checkColor( White ); - checkColor( Black ); - - /*UndefinedProperty = getIndexFromString( "Undefined", properties ); - nlassert( UndefinedProperty != ~0 );*/ -} - - -/* - * Build RMFamilyIndicesByCreatureModel and DepositFamilyIndices - */ -void dispatchFamiliesToLocations() -{ - for ( CFamMap::iterator iss=FamSet.begin(); iss!=FamSet.end(); ++iss ) - { - const CSString& famStr = (*iss).first; - TFamInfo& famInfo = (*iss).second; - uint iFam = getIndexFromString( famStr, families ); - if ( famInfo.IsInDeposits ) - { - // Deposits - nlassert( iFam != ~0 ); - DepositFamilyIndices.push_back( iFam ); - } - if ( famInfo.IsInCreatures ) - { - // Extract creature name from left of family name (ASSUMES there's no blank in creature name) - CSString creaNameForRMFamily = famStr.splitTo( ' ' ); - - // Dispatch - for ( CSkeletonMap::iterator icm=CreatureModels.begin(); icm!=CreatureModels.end(); ++icm ) - { - const CSString& creaModel = (*icm).first; - TSkeletonInfo& modelInfo = (*icm).second; - - if ( modelInfo.Name == creaNameForRMFamily ) - { - RMFamilyIndicesByCreatureModel[creaModel].push_back( iFam ); - //nlinfo( "+ %s for %s (now %u models registered)", famStr.c_str(), creaModel.c_str(), RMFamilyIndicesByCreatureModel.size() ); - modelInfo.IsUsed = true; // Name and AbbrevName are set by deliverCreatureModels() - } - } - } - else switch ( famInfo.SpecialCreatureTag[0] ) - { - // Goo & invasion/raid creatures - case 'G': - { - GooCreatureFamilyIndices.push_back( iFam ); - nldebug( "Family %s selected for goo creatures", famStr.c_str() ); - break; - } - case 'I': - { - if ( famInfo.SpecialCreatureTag.size() == 1 ) - { - InvasionRaidCreatureFamilyIndices['*'].push_back( iFam ); - nldebug( "Family %s selected for all invasion creatures", famStr.c_str() ); - } - else - { - for ( uint c=1; c!=famInfo.SpecialCreatureTag.size(); ++c ) - { - InvasionRaidCreatureFamilyIndices[famInfo.SpecialCreatureTag[c]].push_back( iFam ); - nldebug( "Family %s selected for invasion creature of type %c", famStr.c_str(), famInfo.SpecialCreatureTag[c] ); - } - } - break; - } - } - } -} - - -/* - * Returns the number of models used - */ -uint checkSkeletons() -{ - uint32 nbSkeUsed = 0; - for ( CSkeletonMap::const_iterator isc=CreatureModels.begin(); isc!=CreatureModels.end(); ++isc ) - { - const string& skeFilename = (*isc).first; - const TSkeletonInfo& ske = (*isc).second; - const bool& used = (*isc).second.IsUsed; - if ( used ) - { - nldebug( "Model %s (%s) %s", skeFilename.c_str(), ske.AbbrevName.c_str(), used?"used":"NOT USED" ); - ++nbSkeUsed; - } - else - nlwarning( "Model %s %s", skeFilename.c_str(), used?"":"NOT USED" ); - } - return nbSkeUsed; -} - - -/* - * - */ -void createDirectoryStructure() -{ - // Create the directory structure - if ( WriteSheetsToDisk ) - { - for ( uint32 i=0; i!=ecosystems.size(); ++i ) - { - string dirname = conventionalDirectory( ecosystems[i] ); - if ( ! CFile::isExists( rawMaterialPath + dirname ) ) - { - CFile::createDirectory( rawMaterialPath + dirname ); - } - else - { - if ( ! CFile::isDirectory( rawMaterialPath + dirname ) ) - { - nlwarning( "%s already existing but not a directory!", (rawMaterialPath + dirname).c_str() ); - } - } - } - string dirname = "_parent"; - if ( ! CFile::isExists( rawMaterialPath + dirname ) ) - { - CFile::createDirectory( rawMaterialPath + dirname ); - } - else - { - if ( ! CFile::isDirectory( rawMaterialPath + dirname ) ) - { - nlwarning( "%s already existing but not a directory!", (rawMaterialPath + dirname).c_str() ); - } - } - } -} - - -#endif // NL_SRG_UTILITIES_H - -/* End of srg_utilities.h */ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef NL_SRG_UTILITIES_H +#define NL_SRG_UTILITIES_H + + +// Misc +#include +#include +#include "nel/misc/path.h" +#include "nel/misc/file.h" +#include "nel/misc/smart_ptr.h" +#include "nel/misc/command.h" +#include "nel/misc/path.h" +#include +#include +// Georges +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" +#include "nel/georges/u_form_dfn.h" +#include "nel/georges/u_form_loader.h" +#include "nel/georges/u_type.h" +// Georges, bypassing interface +#include "georges/stdgeorges.h" +#include "georges/form.h" +// C +#include +#include +// stl +#include +#include +#include + +using namespace NLMISC; +using namespace NLGEORGES; +using namespace std; + + +typedef sint TFaberInterestLevel; +const TFaberInterestLevel NAInterestLevel = -1; +const uint32 NbNomenclaturedFaberLevel = 5; // excluding N/A +const char *sNomenclaturedInterestLevels [NbNomenclaturedFaberLevel+1] = { "N/A", "Worst", "Bad", "Average", "Good", "Best" }; // from -1 to 5 +CRandom RandomGenerator; + +typedef CVectorSString vs; + +typedef map > CRulesFilter; +typedef map , CUnsensitiveSStringLessPred > CRulesStrFilter; +typedef map CRulesStr2Filter; +typedef map< CSString, CSString, CUnsensitiveSStringLessPred > mss; +typedef vector vu; +typedef hash_map< string, string, hash > CTitles; // code -> utf8 title + +// Write sheet files, or display to screen only +bool WriteSheetsToDisk = true; + +// Overriden by command-line argument after -n +string ExtractNamesCsv; + + +const uint32 NbFaberElements = 26; + +const uint32 RM_INDEX_FAMILY_CODE = 1; +const uint32 NB_FAMILY_CODE_CHARS = 4; + +const uint32 RM_INDEX_CREATURE_CODE = 5; +const uint32 NB_CREATURE_CODE_CHARS = 5; + +const uint32 RM_INDEX_ECOSYSTEM_CODE = 8; +const uint32 NB_ECOSYSTEM_CODE_CHARS = 1; + +const uint32 RM_INDEX_LEVELZONE_CODE = 9; + +const uint32 SIZE_RAW_MATERIAL_SHEET_FILENAME = 18; + +/*const uint32 RM_INDEX_INTEREST_LEVEL = 6; +const uint32 NB_INTEREST_LEVEL_CHARS = 2; + +const uint32 RM_INDEX_FABERELEMS_CODE = 8; +const uint32 NB_FABERELEMS_CODE_CHARS = 6;*/ + +const uint32 CR_INDEX_ECOSYSTEM_CODE = 3; // in creature code +const uint32 CR_INDEX_LEVELZONE_CODE = 4; +const uint32 CR_INDEX_LOCAL_LEVEL_CODE = 5; + +//const uint32 NB_UNIQUE_LEVELS_PER_ZONE = 4; // not counting the bosses, the fifth equals the first one of next +const uint32 NB_UNIQUE_LEVELZONES_PER_CONTINENT = 5; +const uint32 MAX_NB_LOCAL_LEVELS = 8; +//const uint32 NB_ZONE_LEVELS = 5; // TEMP for forest ecosystem +//const uint32 NbFaberInterestLevels = (NB_ZONE_LEVELS * NB_UNIQUE_LEVELS_PER_ZONE) + 1; // excluding N/A + +string inputSheetPath; +bool inputSheetPathLoaded = false; +map inputSheetPathContent; // short filename without ext, full filename with path +string TranslationPath; +string SystemMPPath; + + +// These vectors have the same indices : by family +vs families; +vs familyCodes, ecosystemCodes, propertyCodes, creatureCodes; + +sint MaxFamilyNum = -1; + +enum TColor { Red, Beige, Green, Turquoise, Blue, Violet, White, Black, NbColors, InvalidColor=NbColors }; + +// By ecosystem, color, property, rm group, creature, season +vs ecosystems, colors, properties, groups, creatures, seasons; +mss adjectives; + +// DtName must be the 1st one +enum TDataCol { DtName, DtTitle, DtRMFamily, DtGroup, DtEcosystem, DtLevelZone, DtStatQuality, DtProp, DtCreature, DtCreaTitle, DtCraftSlotName, DtCraftCivSpec, DtColor, DtAverageEnergy, DtMaxLevel, DtJewelProtectionType, DtCustomizedProperties, DtNbCols }; +const char *DataColStr [DtNbCols] = { "Code", "Name", "Family", "Group", "Ecosystem", "LevelZone", "Stat Quality", "Properties", "Creature sheets", "Creatures", "Item parts", "Craft civ spec", "Color", "Average energy", "Max level", "Jewel protection type", "Customized" }; + +const uint32 NbPropertyDepths = 5; +const char *PropertyDepths [NbPropertyDepths] = { "Unknown", "Slightly", "Moderately", "Quite", "Extremely" }; + +typedef uint32 TGroup; // index in groups, and value in groups .typ + +//enum TLocation { Under, Over, Flora, Creatures, NB_LOCATIONS, NB_DEPOSITS=Flora+1 }; +enum TLocation { InDeposits, InCreatures, NB_LOCATIONS }; +vu DepositFamilyIndices; + +enum TCiv { Fyros, Matis, Tryker, Zorai, AllCiv, NbCiv }; +const char *CivNames [NbCiv] = { "Fyros", "Matis", "Tryker", "Zorai", "All" }; +const char *CivEcosystemCodes [NbCiv] = { "D", "F", "L", "J", "X" }; + +enum TEcosystem { CommonEcosystem, Desert, Forest, Lacustre, Jungle, PrimeRoots, NbEcosystems, Goo=NbEcosystems, Invasion, Raid, Event, N, S, T, U, V, W, X, Y, Z, NbEcosystemsPlusExtensions }; + +TCiv EcosystemToCiv[NbEcosystems] = { AllCiv, Fyros, Matis, Tryker, Zorai, AllCiv }; + +enum TStatQuality { Basic, Fine, Choice, Excellent, Supreme, NbStatQualities, InvalidStatQuality=NbStatQualities }; +char *StatQualityStr [NbStatQualities+1] = { "Basic", "Fine", "Choice", "Excellent", "Supreme", "N/A" }; + +TStatQuality CreatureLocalLevelToStatQuality [MAX_NB_LOCAL_LEVELS] = +{ + Basic, // 1 (index 0) + Fine, // 2 + Basic, // 3 + Fine, // 4 + Excellent, // 5 (named creatures) + InvalidStatQuality, // 6 (mission creatures, their RMs have no craft stats) + Supreme, // 7 (bosses) + Choice // 8 (mini-bosses) +}; + + +enum TIndexOfRemarkableStatIndex { RBestA, RBest=RBestA, RWorstA1, RWorst1=RWorstA1, RWorstA2, RWorst2=RWorstA2, RBestB, RWorstB1, RWorstB2, NB_REMARKABLE_STAT_INDICES }; + +struct TSkeletonInfo +{ + TSkeletonInfo() : IsUsed(false) {} + + //vs CreaturesOfSke; + CSString Name; + CSString AbbrevName; + //CSString SkGroup; + bool IsUsed; // true if has RM +}; + +typedef map CSkeletonMap; + +// By skeleton group, by skeleton, bu creature model +CRulesStr2Filter SkgroupToModels; +CSkeletonMap CreatureModels; +mss CreatureToModel; +//vs skeletonGroupColumns; +set CreatureMainModelsWithoutRM; + +// By creature model +CRulesStrFilter RMFamilyIndicesByCreatureModel; +vu GooCreatureFamilyIndices; + +typedef map CCreatureTypeToFamilyIndices; // the key is the 2nd char of the creature code (h for herbivore, k for kitin...) +CCreatureTypeToFamilyIndices InvasionRaidCreatureFamilyIndices; + +struct TBool +{ + TBool() : Done(false) {} + bool Done; +}; + +typedef map< uint, TBool > CDoneMap; // indexed by levelzone +map< string, TBool > IsRMSheetGenerated; // indexed by sheetname + +string rawMaterialPath, creaturePath, creatureAssignmentPath, depositPath; +string dirbase; + + +const string oldRmSheetType = "item"; +const string rmSheetType = "sitem"; +const string crSheetType = "creature"; +const string dpSheetType = "deposit"; + + +//const uint32 NbPropertySlots = 10; // obsolete +uint32 UndefinedProperty = ~0; + + + +/* + * + */ +struct CIconInfo +{ + CSString IconBackground, Icon, IconOver, IconOver2; +}; + +map< CSString, CIconInfo, CUnsensitiveSStringLessPred > Icons; + + +/* + * + */ +class CMainStat +{ +public: + + /// + CMainStat() : SumNbFaberElemsFilled(0), MaxNbFaberElemsFilled(0), MinNbFaberElemsFilled(~0), + NbRMByFaberElem( NbFaberElements, 0 ) {} + + /// Call it when families etc. are ready + void init() + { + NbRMByFaberElemByFamilyAndCiv.resize( families.size() ); + for ( uint32 i=0; i!=families.size(); ++i ) + { + NbRMByFaberElemByFamilyAndCiv[i].resize( NbCiv ); + for ( uint32 c=0; c!=NbCiv; ++c ) + NbRMByFaberElemByFamilyAndCiv[i][c].resize( NbFaberElements ); + } + + for ( uint32 iEcosystem=0; iEcosystem!=ecosystems.size(); ++iEcosystem ) + { + for ( uint32 iLoc=0; iLoc!=NB_LOCATIONS; ++iLoc ) + { + NbRMHavingProperty[iLoc][iEcosystem].resize( properties.size() ); + NbRMByFaberElemByEcosystem[iEcosystem].resize( NbFaberElements ); + } + } + } + + /// + bool updateCraftStatistics( uint32 rFaberElem, uint32 iEcosystem, uint32 iFam, TCiv civ ); + + /// + void updateMainStats( uint32 nbFaberElemsFilled ) + { + SumNbFaberElemsFilled += nbFaberElemsFilled; + if ( nbFaberElemsFilled < MinNbFaberElemsFilled ) + MinNbFaberElemsFilled = nbFaberElemsFilled; + if ( nbFaberElemsFilled> MaxNbFaberElemsFilled ) + MaxNbFaberElemsFilled = nbFaberElemsFilled; + } + + // By property and by ecosystem and location + vu NbRMHavingProperty [NB_LOCATIONS][NbEcosystems]; + + uint32 SumNbFaberElemsFilled; + uint32 MaxNbFaberElemsFilled; + uint32 MinNbFaberElemsFilled; + + vector NbRMByFaberElem;; + vector NbRMByFaberElemByEcosystem [NbEcosystems]; + vector< vector < vector< uint32 > > > NbRMByFaberElemByFamilyAndCiv; + +}; + + +/* + * From georges2csv + */ +void loadSheetPath() +{ + if (inputSheetPathLoaded) + return; + + NLMISC::createDebug(); + NLMISC::WarningLog->addNegativeFilter( "CPath::insertFileInMap" ); + + CPath::addSearchPath(inputSheetPath, true, false); // for Georges to work properly + + vector files; + CPath::getPathContent (inputSheetPath, true, false, true, files); + + uint32 i; + for (i=0; i& values, const vector& labels ) : TypePredefinedValues(values), TypePredefinedLabels(labels) {} + + vector TypePredefinedValues; + vector TypePredefinedLabels; +}; + + +/* + * + */ +struct TIconMapping +{ + const char *FamilyName; + const char *IconFilename; +}; + + +/* + * + */ +sint getNomenclaturedInterestLevel( TFaberInterestLevel level, TFaberInterestLevel nbInterestLevels ) +{ + return (level == NAInterestLevel) ? 0 : (level * NbNomenclaturedFaberLevel / nbInterestLevels) + 1; +} + + +/* + * + */ +//struct CFaberCode +//{ +// char Ch[NB_FABERELEMS_CODE_CHARS]; +//}; + + +/* + * + */ +//struct CFaberCombination +//{ +// CFaberCombination( TFaberInterestLevel firstLevel, const string& code ) : FirstLevel(firstLevel) +// { +// memcpy( Code.Ch, &code[0], NB_FABERELEMS_CODE_CHARS ); +// } +// +// TFaberInterestLevel FirstLevel; +// CFaberCode Code; +//}; + + +/* + * + */ +//class CSheetNameRepository +//{ +//public: +// +// /// +// void resize( uint32 nbEcosystems, uint32 nbFamilies ) +// { +// _Container.resize( nbEcosystems ); +// for ( uint32 i=0; i!=nbEcosystems; ++i ) +// { +// _Container[i].resize( nbFamilies ); +// } +// } +// +// /// +// void insert( uint32 iEcosystem, uint32 iFamily, uint32 iCreature, TFaberInterestLevel level, const string& faberCombinationCode ) +// { +// // nlassert( faberCombinationCode.size() == NB_FABERELEMS_CODE_CHARS ); +// _Container[iEcosystem][iFamily][iCreature].push_back( CFaberCombination( level, faberCombinationCode ) ); +// } +// +// /// +// void getFaberCombinationCodes( uint32 iEcosystem, uint32 iFamily, uint32 iCreature, vector **codes ) +// { +// map < uint32, vector< CFaberCombination > >::iterator im; +// /*nldebug( "%u %u -> %u cr (searching for %u)", iEcosystem, iFamily, _Container[iEcosystem][iFamily].size(), iCreature ); +// for ( im=_Container[iEcosystem][iFamily].begin(); im!=_Container[iEcosystem][iFamily].end(); ++im ) +// nldebug( "cr %u -- %u combinations", (*im).first, (*im).second.size() );*/ +// im = _Container[iEcosystem][iFamily].find( iCreature ); +// if ( im == _Container[iEcosystem][iFamily].end() ) +// *codes = NULL; +// else +// *codes = &((im)->second); +// } +// +//private: +// +// /// Indexs: iEcosystem, iFamily, rCreatureSpecialization, rFaberCombination +// vector< vector < map < uint32, vector< CFaberCombination > > > > _Container; +//}; + + +//void CSheetNameRepository::getFaberCombinationCodes( uint32 iEcosystem, uint32 iFamily, uint32 iCreature, vector **codes ) + + +//CSheetNameRepository RawMaterialRepository; + +/** + * Characteristics. + * When adding a new characteristic, ADD IT INTO "v3_source_tables.xls!Item Parts v3"/"rm_item_parts.csv" and mark compatible item parts + */ +enum TFaberCharacteristic { + Durability, Weight, SapLoad, DMG, Speed, Range, + DodgeModifier, ParryModifier, AdversaryDodgeModifier, AdversaryParryModifier, + ProtectionFactor, MaxSlashProtect, MaxBluntProtect, MaxPierceProtect, + ECTF, EPF, + OACTF, OAPF, + HCTP, HPF, + DACTF, DAPF, + JewelProtection, + CraftCivSpec, + NbCharacs }; + +const char *sCharacs [NbCharacs] = { + "Durability", "Weight", "SapLoad", "DMG", "Speed", "Range", + "DodgeModifier", "ParryModifier", "AdversaryDodgeModifier", "AdversaryParryModifier", + "ProtectionFactor", "MaxSlashingProtection", "MaxBluntProtection", "MaxPiercingProtection", + "ElementalCastingTimeFactor", "ElementalPowerFactor", + "OffensiveAfflictionCastingTimeFactor", "OffensiveAfflictionPowerFactor", + "HealCastingTimeFactor", "HealPowerFactor", + "DefensiveAfflictionCastingTimeFactor", "DefensiveAfflictionPowerFactor", + "JewelProtectionType", + "CraftCivSpec" }; + +//const bool PositiveCharacs [NbCharacs] = { true, false, true, false, true, true }; +//const float MinCharacValues [NbCharacs] = { 100, 0.1f, 10, 0.2f, 100, 0 }; +//const float MaxCharacValues [NbCharacs] = { 500, 1.5f, 400, 2.0f, 500, 60 }; +//const float PeakCharacValues [NbCharacs] = { 2000, 2.5f, 800, 5.0f, 2000, 80 }; +bool PositiveCharacs [NbCharacs]; +float MinCharacValues [NbCharacs]; +float MaxCharacValues [NbCharacs]; +float PeakCharacValues [NbCharacs]; +vector CharacSlotFilter [NbCharacs]; // it's a positive filter + + + +/* + * + */ +struct TFamInfo +{ + vs Properties; // ex: propForA, propForB, propForC + CSString CompatibleCraftParts; // ex: ABC + vu CraftPartsByProp; // ex: 0, 1, 2 (indices in ompatibleCraftParts) + vector Civs; // ex: Fyros, All, All + vu Freqs; // ex: 1, 2, 2 + TGroup Group; + bool IsActive; // False if not in rm_fam_prop.csv + bool IsInDeposits; + bool IsInCreatures; + CSString SpecialCreatureTag; + bool GenerateOnly; + bool IsForMission; + sint8 RemarkableStatIndex [NB_REMARKABLE_STAT_INDICES]; + sint8 ColorIndex; + sint8 JewelProtIndex; + + static uint UseGenerateOnly; // if 0, generate all; otherwise, generate only families that have GenerateOnly set to true + + /// + TFamInfo() : Group(~0), IsInDeposits(false), IsActive(false), IsInCreatures(false), SpecialCreatureTag(), GenerateOnly(false), IsForMission(false), ColorIndex(-1), JewelProtIndex(-1) {} + + /// + uint getCompatibleCraftPart( uint iCompatibleCP ) const + { + return (uint)(CompatibleCraftParts[iCompatibleCP] - 'A'); + } + + /// whichProp: index in Properties + uint getBeginCraftPartForProp( uint whichProp ) const + { + return CraftPartsByProp[whichProp]; + } + + /// whichProp: index in Properties + uint getEndCraftPartForProp( uint whichProp ) const + { + if ( whichProp == Properties.size()-1 ) + return CompatibleCraftParts.size(); + else + return CraftPartsByProp[whichProp+1]; + } + + /// whichProp: index in Properties + CSString getCraftPartForProp( uint whichProp ) const + { + uint start = getBeginCraftPartForProp( whichProp ); + return CompatibleCraftParts.substr( start, getEndCraftPartForProp( whichProp ) - start ); + } + + /** With the returned index, you can get elt in Property, CraftPartsByProp, Civs and Freqs. + * Returns ~0 if not found. + */ + uint getPropIndexByCraftPart( char itemPart ) const + { + for ( uint i=0; i!=CraftPartsByProp.size(); ++i ) + { + char itemPartCode [2]; + itemPartCode[0] = itemPart; + itemPartCode[1] = '\0'; + if ( getCraftPartForProp( i ).find( itemPartCode ) != string::npos ) + return i; + } + return ~0; + } + + /// + bool existsInEcosystem( TEcosystem iEcosystem, TStatQuality statQuality ) const; + + /// + static bool mustGenerateFamily( uint iFamily ); +}; + + +const uint ITEM_PART_JEWEL_GEM = 17; // R + + +/* + * + */ +struct CFaberCharacteristics +{ + /// Default constructor (for reading) + CFaberCharacteristics() + : FaberElement(~0), ActualEnergy(0.0f), ActualOriginality(0.0f) + { + for ( uint32 i=0; i!=NbCharacs; ++i ) + Values[i] = 0.0f; + } + + /// + void serial( NLMISC::IStream& s ) + { + s.serial( FaberElement ); + s.serial( ActualEnergy ); + s.serial( ActualOriginality ); + for ( uint32 c=0; c!=NbCharacs; ++c ) + s.serial( Values[c] ); + } + + /// + void initFaberElement( uint32 rFaberElement ) { FaberElement = rFaberElement; } + + /// Returns false if the RM must NOT be generated. + bool randomizeValues( TFaberInterestLevel interestLevel, TFaberInterestLevel nbInterestLevels, uint iVariant, float widthRatio, float peakOccurRatio, float baseBoost, TEcosystem iEcosystem, uint iFreq, uint iFamily ); + + /// Returns -1 if the RM must NOT be generated, otherwise return the stat average + sint32 computeValues( TStatQuality statQuality, const TFamInfo& famInfo, sint remarkableIndicesSetBaseIndex, + TEcosystem iEcosystem, uint iFreq, uint iFamily ); + + /// + void calcQualitativeValues(); + + /// Index of faber element in "MpParam" + uint32 FaberElement; + + /// Values + float Values [NbCharacs]; + + /// Average of the actual interest of the random values between 0 and 1 + float ActualEnergy; + + /// + float ActualOriginality; + +protected: + + // Returns false if the RM must NOT be generated. + //bool randomizeJewelProtection( TStatQuality statQuality, TEcosystem iEcosystem, uint iFreq, uint iFamily ); + + void computeJewelProtection( TStatQuality statQuality, TEcosystem iEcosystem, uint iFamily ); +}; + + +// +void CFaberCharacteristics::calcQualitativeValues() +{ + float actualInterests [NbCharacs]; + + // Calculate the average of ratio between [0,1] + float sumActualInterest = 0.0f; + uint nbCharacsUsed = 0; + for ( uint r=0; r!=NbCharacs; ++r ) + { + if ( MaxCharacValues[r] == 0 ) + continue; + if ( ! CharacSlotFilter[r][FaberElement] ) + continue; + + float interestRatio = (Values[r] / PeakCharacValues[r]); // new: Peak is taken as the max => the Energy is in [0..100] + if ( ! PositiveCharacs[r] ) + interestRatio = 1.0f - interestRatio; // thus, can be negative + + actualInterests[r] = interestRatio; + sumActualInterest += interestRatio; + ++nbCharacsUsed; + } + + if ( nbCharacsUsed == 0 ) + return; + + ActualEnergy = (sumActualInterest / (float)nbCharacsUsed); + if ( ActualEnergy > 1.0f ) + ActualEnergy = 1.0f; + + // Calculate the standard deviation (SQRT(SUM((Ai-Aavg)²)/N)) + float varianceSum = 0.0f; + for ( uint r=0; r!=NbCharacs; ++r ) + { + if ( MaxCharacValues[r] == 0 ) + continue; + if ( ! CharacSlotFilter[r][FaberElement] ) + continue; + + varianceSum += sqr( actualInterests[r] - ActualEnergy ); + } + + // Don't normalize standard deviation, otherwise low energy materials will be considered more + // original (by average) than high energy materials. They wouldn't be comparable. + + //if ( ActualEnergy != 0.0f ) + ActualOriginality = (float)sqrt( (double)(varianceSum / (float)nbCharacsUsed) ); // / ActualEnergy; + //else + // nlinfo( "Null energy for craft slot %u", FaberElement ); +} + + +/* + * Fill childrenToGet if rootNameForGetChildren is not null + */ +void fillFromDFN( UFormLoader *formLoader, map& dfnFields, UFormDfn *formDfn, const string& rootName, const string& dfnFilename, + const char *rootNameForGetChildren=NULL, vector& childrenToGet=vector() ) +{ + uint32 i; + for ( i=0; i!=formDfn->getNumEntry(); ++i ) + { + string entryName, rootBase; + formDfn->getEntryName( i, entryName ); + rootBase = rootName.empty() ? "" : (rootName+"."); + + UFormDfn::TEntryType entryType; + bool array; + formDfn->getEntryType( i, entryType, array ); + switch ( entryType ) + { + case UFormDfn::EntryVirtualDfn: + { + CSmartPtr subFormDfn = formLoader->loadFormDfn( (entryName + ".dfn").c_str() ); + if ( ! subFormDfn ) + nlwarning( "Can't load virtual DFN %s", entryName.c_str() ); + else + fillFromDFN( formLoader, dfnFields, subFormDfn, rootBase + entryName, entryName + ".dfn", rootNameForGetChildren, childrenToGet ); // recurse + break; + } + case UFormDfn::EntryDfn: // .dfn + { + UFormDfn *subFormDfn; + if ( formDfn->getEntryDfn( i, &subFormDfn) ) + { + string filename; + formDfn->getEntryFilename( i, filename ); + fillFromDFN( formLoader, dfnFields, subFormDfn, rootBase + entryName, filename, rootNameForGetChildren, childrenToGet ); // recurse + } + if ( rootNameForGetChildren && (rootName == rootNameForGetChildren) ) + { + childrenToGet.push_back( rootBase + entryName ); + } + break; + } + case UFormDfn::EntryType: // .typ + { + vector values, labels; + UType *subType; + if ( formDfn->getEntryType( i, &subType ) ) + { + uint32 listSize = subType->getNumDefinition(); + if ( listSize > 0 ) + { + string label, value; + for ( uint32 j=0; j!=listSize; ++j ) + { + subType->getDefinition( j, label, value ); + if ( (subType->getIncrement() == "1") && (subType->getType() == UType::UnsignedInt || subType->getType() == UType::SignedInt) ) + { + // Fill blank entry for skipped identifier values (to allow indexing by identifier value) + sint num = atoi( value.c_str() ); + while ( num - (sint)values.size() > 0 ) + { + values.push_back( "" ); + labels.push_back( "" ); + } + } + values.push_back( value ); + labels.push_back( label ); + } + } + } + dfnFields.insert( make_pair( rootBase + entryName, CDfnFieldInfo(values, labels) ) ); + //nlinfo( "DFN entry: %s (in %s)", (rootBase + entryName).c_str(), dfnFilename.c_str() ); + break; + } + } + } +} + + +/* + * + */ +CForm *loadTemplateForm( UFormLoader *formLoader, const string& sheetType ) +{ + CForm *form = (CForm*)formLoader->loadForm( (string("_empty.")+sheetType).c_str() ); + if ( ! form ) + nlerror( "Can't load sheet _empty.%s", sheetType.c_str() ); + return form; +} + + +/* + * + */ +void eraseCarriageReturns( string& s ) +{ + const char CR = '\n'; + string::size_type p = s.find( CR ); + while ( (p=s.find( CR )) != string::npos ) + s.erase( p, 1 ); +} + + +/* + * + */ +string getNomenclatureCode( const string& longName, set& usedCodes, uint32 nbLetters ) +{ + if ( nbLetters > longName.size() ) + nlerror( "Wrong nbLetters for %s", longName.c_str() ); + + // Start with beginning of name + string code = strlwr(longName.substr( 0, nbLetters )); + uint32 i = nbLetters-1; + while ( usedCodes.find( code ) != usedCodes.end() ) + { + ++i; + if ( i < longName.size() ) + { + // Substitute last code char by a char from the name (except ' ') + if ( longName[i] != ' ' ) + code[nbLetters-1] = tolower(longName[i]); + else + continue; + } + else + { + // If no char from the name is suitable, increment the last char of the code until suitable + char c=1; + while ( usedCodes.find( code ) != usedCodes.end() ) + { + code[nbLetters-1] = tolower(longName[nbLetters-1]) + c; + ++c; + if ( code[1] > 'z' ) + nlerror( "Impossible to make code for %s", longName.c_str() ); + } + } + } + strlwr( code ); + usedCodes.insert( code ); + return code; +} + + +/* + * Displays mapping if title not null. + */ +void buildNomenclatureCodes( const char *title, const vector& longNames, vector& codes, uint32 nbLetters ) +{ + set usedCodeSet; + uint32 i; + for ( i=0; i!=longNames.size(); ++i ) + { + codes[i] = getNomenclatureCode( longNames[i], usedCodeSet, nbLetters ); + if ( title ) + nlinfo( "%s %s -> %s", title, longNames[i].c_str(), codes[i].c_str() ); + //DebugLog->displayRawNL( "%s", longNames[i].c_str() ); + } +} + + +/* + * Set the size of a family code to NB_FAMILY_CODE_CHARS + */ +void normalizeFamilyCode( std::string& s ) +{ + if ( s.size() > NB_FAMILY_CODE_CHARS ) + { + nlerror( "Family codes limited to %u chars (%s)", NB_FAMILY_CODE_CHARS, s.c_str() ); + } + else + { + uint p = s.size(); + while ( p < NB_FAMILY_CODE_CHARS ) + { + s = "0" + s; + ++p; + } + } +} + + +/* + * + */ +void loadNomenclatureCodes( const char *title, const vector& longNames, vector& codes, const char *filename ) +{ + if ( longNames.empty() ) + { + nlwarning( "No nomenclature codes to load. %s", title ? title : "" ); + return; + } + codes.resize( longNames.size() ); + + char lineBuffer[2048]; + FILE *rulesFile; + const char *SEPARATOR = ";"; + vector args; + vector::iterator iarg; + vector::const_iterator ivs; + + if ( (rulesFile = fopen( filename, "r" )) == NULL ) + { + nlwarning( "Can't find file %s", filename ); + } + else + { + while ( ! feof(rulesFile) ) + { + // Get from file + fgets( lineBuffer, 2048, rulesFile ); + explode( lineBuffer, SEPARATOR, args ); + + // Get rid of carriage returns! + for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) + { + eraseCarriageReturns( *iarg ); + } + + // Read + const uint32 MIN_COLS = 6; + const uint32 NAME_COL = 4; + const uint32 C_COL = 2; + const uint32 R_COL = 3; + const uint32 NB_CODE_CHARS = 2; + if ( (args.size()>=MIN_COLS) && (! args[0].empty()) && (args[0].find( "name" )==string::npos) ) // skip blank lines, and lines with blank header or "name" in the first column + { + if ( args[NAME_COL].empty() ) + continue; + + ivs = find( longNames.begin(), longNames.end(), args[NAME_COL] ); + if ( ivs == longNames.end() ) + nlwarning( "Name %s is not in the names array", args[NAME_COL].c_str() ); + else + { + string code = args[C_COL] + args[R_COL]; + if ( code.size() < NB_CODE_CHARS ) + { + nlwarning( "Invalid partial code for %s: %s", (*ivs).c_str(), code.c_str() ); + continue; + } + else if ( code.size() > NB_CODE_CHARS ) + { + nlinfo( "Compacting code '%s' for %s", code.c_str(), (*ivs).c_str() ); + string::size_type p; + while ( (p = code.find( ' ' )) != string::npos ) + { + code.erase( p, 1 ); + } + } + + if ( codes[ivs-longNames.begin()].empty() ) + { + if ( title ) + nlinfo( "%s %s -> %s", title, (*ivs).c_str(), code.c_str() ); + codes[ivs-longNames.begin()] = code; + } + else + { + if ( code != codes[ivs-longNames.begin()] ) + nlwarning( "Invalid nomenclature: (%s and %s for %s: ", codes[ivs-longNames.begin()].c_str(), code.c_str(), (*ivs).c_str() ); + } + } + } + } + + for ( ivs=codes.begin(); ivs!=codes.end(); ++ivs ) + { + if ( (*ivs).empty() ) + nlwarning( "No code found for %s", (*(longNames.begin() + (ivs - codes.begin()))).c_str() ); + } + } +} + + +/* + * + */ +inline sint getLastUsedPropertySlot( uint32 *iProperties, sint lastPropertySlot, uint32 undefinedProperty ) +{ + for ( sint r=lastPropertySlot; r>=0; --r ) + { + if ( iProperties[r] != undefinedProperty ) + return r; + } + return -1; +} + + +/* + * + */ +inline bool passNegativeFilter( const vector& incompatibilityList, uint32 iValue ) +{ + vector::const_iterator ip = find( incompatibilityList.begin(), incompatibilityList.end(), iValue ); + return (ip == incompatibilityList.end()); +} + + +/* + * + */ +inline bool passPositiveFilter( const vector& compatibilityList, uint32 iValue ) +{ + vector::const_iterator ip = find( compatibilityList.begin(), compatibilityList.end(), iValue ); + return (ip != compatibilityList.end()); +} + + +/* + * Reject a prop if it is in the incompatibility list of a family + */ +bool passPropFamilyFilter( const vector& iFamilyRelatedProperties, uint32 iProp ) +{ + return passNegativeFilter( iFamilyRelatedProperties, iProp ); +} + + +/* + * Reject a creature if NOT in the creature list of a family + */ +/*bool passCreatureFilter( const vector& iFamilyRelatedCreatures, uint32 iCreature ) +{ + //nldebug( "%u related creatures, %s", iFamilyRelatedCreatures.size(), passPositiveFilter( iFamilyRelatedCreatures, iCreature ) ? "TRUE": "FALSE" ); + return passPositiveFilter( iFamilyRelatedCreatures, iCreature ); +}*/ + + +/* + * + */ +class CStrIComparator : public binary_function +{ +public: + bool operator() ( const string& s1, const string& s2 ) const + { + return (nlstricmp( s1, s2 ) == 0); + } +}; + + +/* + * + */ +void displayList( const vector& v, CLog *log=DebugLog ) +{ + vector::const_iterator ist; + for ( ist=v.begin(); ist!=v.end(); ++ist ) + log->displayRaw( "%s ", (*ist).c_str() ); + log->displayRawNL( "" ); +} + + +/* + * + */ +uint32 getIndexFromString( const string& s, const vector& v, bool displayWarning=true ) +{ + if ( v.empty() ) + { + if ( displayWarning ) + nlwarning( "Can't find '%s' in empty array", s.c_str() ); + return ~0; + } + else + { + vector::const_iterator ist = find_if( v.begin(), v.end(), bind2nd(CStrIComparator(), s) ); + if ( ist == v.end() ) + { + if ( displayWarning ) + { + nlwarning( "Can't find '%s' in:", s.c_str() ); + displayList( v, WarningLog ); + } + return ~0; + } + else + return ist - v.begin(); + } +} + + +/* + * + */ +uint32 getIndexFromString( const string& s, const char **array, uint arraySize, bool displayWarning=true ) +{ + if ( arraySize == 0 ) + { + if ( displayWarning ) + nlwarning( "Can't find '%s' in empty array", s.c_str() ); + return ~0; + } + else + { + for ( uint i=0; i!=arraySize; ++i ) + { + if ( strlwr(string(array[i])) == strlwr(s) ) + return i; + } + + if ( displayWarning ) + { + nlwarning( "Can't find '%s' in:", s.c_str() ); + //displayList( v, WarningLog ); + } + return ~0; + } +} + + +/* + * Returns the index of the erased element, ~0 if not found + */ +uint32 removeEntryFromList( vector& v, const string& entry ) +{ + vector::iterator ivs; + ivs = find( v.begin(), v.end(), entry ); + uint32 index; + if ( ivs != v.end() ) + { + index = ivs - v.begin(); + v.erase( ivs ); + return index; + } + else + return ~0; +} + + +/* + * + */ +bool removeEntryFromListByIndex( vector& v, uint32 index ) +{ + if ( index < v.size() ) + { + v.erase( v.begin() + index ); + return true; + } + else + return false; +} + + +typedef void (*TMapDeliveryCallback) ( mss& ); +typedef void (*TVectorDeliveryCallback) ( vs& ); + + +/* + * + */ +void loadCSVFile( const char *filename, TMapDeliveryCallback deliveryCallback, bool firstColWithoutName=false ) +{ + char lineBuffer[2048]; + FILE *file; + const char *SEPARATOR = ";"; + vector args; + vector::iterator iarg; + + if ( (file = fopen( filename, "r" )) == NULL ) + { + nlwarning( "Can't find file %s", filename ); + } + else + { + // Read first line as header with column names + lineBuffer[0] = '\0'; + fgets( lineBuffer, 2048, file ); + explode( lineBuffer, SEPARATOR, args ); + + // Store column names (and get rid of carriage returns!) + vector < string > columnNames; + mss valuesByName; + for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) + { + if ( firstColWithoutName && (iarg == args.begin()) ) + { + *iarg = "<>"; // override column name for the 1st column + } + eraseCarriageReturns( *iarg ); + columnNames.push_back( *iarg ); + valuesByName.insert( make_pair( *iarg, string("") ) ); + } + + while ( ! feof(file) ) + { + // Get from file + lineBuffer[0] = '\0'; + fgets( lineBuffer, 2048, file ); + explode( lineBuffer, SEPARATOR, args ); + + // Set values (and get rid of carriage returns!) + for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) + { + eraseCarriageReturns( *iarg ); + valuesByName[columnNames[iarg-args.begin()]] = *iarg; + } + + // Deliver the wanted fields + deliveryCallback( valuesByName ); + } + } +} + + +/* + * + */ +void loadCSVFile( const char *filename, TVectorDeliveryCallback deliveryCallback ) +{ + char lineBuffer[2048]; + FILE *file; + const char *SEPARATOR = ";"; + vs args; + vs::iterator iarg; + + if ( (file = fopen( filename, "r" )) == NULL ) + { + nlwarning( "Can't find file %s", filename ); + } + else + { + while ( ! feof(file) ) + { + // Get from file + lineBuffer[0] = '\0'; + fgets( lineBuffer, 2048, file ); + explode( lineBuffer, SEPARATOR, args ); + + // Get rid of carriage returns! + for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) + { + eraseCarriageReturns( *iarg ); + } + + // Deliver the wanted fields + deliveryCallback( args ); + } + } +} + + +/* + * + */ +void loadValueFile( const char *filename, const vector& keyStrings, + vector& contents, sint defaultValue ) +{ + nlassert( keyStrings.size() == contents.size() ); + char lineBuffer[2048]; + FILE *rulesFile; + const char *SEPARATOR = ";"; + vector args; + vector::iterator iarg; + + if ( (rulesFile = fopen( filename, "r" )) == NULL ) + { + nlwarning( "Can't find file %s", filename ); + } + else + { + while ( ! feof(rulesFile) ) + { + // Get from file + lineBuffer[0] = '\0'; + fgets( lineBuffer, 2048, rulesFile ); + explode( lineBuffer, SEPARATOR, args ); + + // Get rid of carriage returns! + for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) + { + eraseCarriageReturns( *iarg ); + } + + // Read + if ( (! args.empty()) && (! args[0].empty()) ) // skip blank lines, and lines with blank header + { + sint value = defaultValue; + for ( uint32 a=0; a!=args.size()-1; ++a ) + { + if ( ! args[a+1].empty() ) // skip blank entries + value = atoi( args[a+1].c_str() ); + } + uint32 index = getIndexFromString( args[0], keyStrings ); + if ( index != ~0 ) + { + contents[index] = value; + } + } + } + fclose( rulesFile ); + } +} + + +/* + * + */ +void loadRulesFile( const char *filename, const vector& keyStrings, + const vector& contentStrings, CRulesFilter& filter, + const string& matchExtKeyAtFirstColumn=string() ) +{ + char lineBuffer[2048]; + FILE *rulesFile; + const char *SEPARATOR = ";"; + uint32 firstColumn = matchExtKeyAtFirstColumn.empty() ? 0 : 1; + vector args; + vector::iterator iarg; + + if ( (rulesFile = fopen( filename, "r" )) == NULL ) + { + nlwarning( "Can't find file %s", filename ); + } + else + { + while ( ! feof(rulesFile) ) + { + // Get from file + lineBuffer[0] = '\0'; + fgets( lineBuffer, 2048, rulesFile ); + explode( lineBuffer, SEPARATOR, args ); + + // Get rid of carriage returns! + for ( iarg=args.begin(); iarg!=args.end(); ++iarg ) + { + eraseCarriageReturns( *iarg ); + } + + // Match with ext key string if set + if ( (! matchExtKeyAtFirstColumn.empty()) && (args[0]!=matchExtKeyAtFirstColumn) ) + continue; + + // Read + if ( (! args.empty()) && (! args[firstColumn].empty()) ) // skip blank lines, and lines with blank header + { + vector contents; + for ( uint32 a=firstColumn; a!=args.size()-1; ++a ) + { + if ( ! args[a+1].empty() ) // skip blank entries + contents.push_back( getIndexFromString( args[a+1], contentStrings ) ); + } + filter.insert( make_pair( getIndexFromString( args[firstColumn], keyStrings ), contents ) ); + } + } + fclose( rulesFile ); + } +} + + +/* + * 1st column: extKeyStrings (corresponding to the filters 'vector'); 2nd: keyStrings + */ +void loadRulesFileMulti( const char *filename, const vector& extKeyStrings, const vector& keyStrings, const vector& contentStrings, vector& filters ) +{ + filters.resize( extKeyStrings.size() ); + for ( uint32 i=0; i!=filters.size(); ++i ) + { + loadRulesFile( filename, keyStrings, contentStrings, filters[i], extKeyStrings[i] ); + /*CRulesFilter::const_iterator irf; + nldebug( "%s", extKeyStrings[i].c_str() ); + for ( irf=filters[i].begin(); irf!=filters[i].end(); ++irf ) + { + nldebug( "%s", keyStrings[(*irf).first].c_str() ); + vector::const_iterator ivi; + for ( ivi=(*irf).second.begin(); ivi!=(*irf).second.end(); ++ivi ) + { + nldebug( "%u", *ivi ); + } + }*/ + } +} + + +/* + * Clear the form to reuse it (and all contents below node) + */ +void clearSheet( CForm *form, UFormElm* node ) +{ + ((CFormElm*)node)->clean(); + form->clean(); +} + + +/* + * Saves to disk if bool WriteSheetsToDisk is true + */ +void flushSheetToDisk( const string& fullFilename, UForm *form ) +{ + if ( WriteSheetsToDisk ) + { + COFile output( fullFilename ); + form->write( output, false ); + } +} + + +/* + * + */ +string::size_type findCapital( const string& s, string::size_type startPos ) +{ + string::size_type p; + for ( p=startPos; p!=s.size(); ++p ) + { + if ( (s[p] >= 'A') && (s[p] <= 'Z') ) + return p; + } + return string::npos; +} + + +/* + * Transform "MyString " into "My string" + */ +void detachValue( string& s ) +{ + if ( s.size() < 2 ) + return; + + string::size_type p; + while ( (p = findCapital( s, 1 )) != string::npos ) + { + s.insert( p, " " ); + s[p+1] = tolower( s[p+1] ); + } + + // Rip off any blank at the end + if ( s[s.size()-1] == ' ' ) + { + s.resize( s.size()-1 ); + } +} + + +/* + * + */ +void getTransposedMap( CRulesFilter& dest, const CRulesFilter& src ) +{ + CRulesFilter::const_iterator im; + for ( im=src.begin(); im!=src.end(); ++im ) + { + vector::const_iterator iv; + for ( iv=(*im).second.begin(); iv!=(*im).second.end(); ++iv ) + { + dest[*iv].push_back( (*im).first ); + } + } +} + + +/* + * + */ +string makeFaberElementCode( uint32 iFaberElement, TFaberInterestLevel level, TFaberInterestLevel nbInterestLevels ) +{ + return toString( "%c%d", 'a' + iFaberElement, getNomenclaturedInterestLevel( level, nbInterestLevels ) ); +} + + +/* + * + */ +inline bool hasMatchingFaberLevel( TFaberInterestLevel storedLevel, TFaberInterestLevel submittedLevel ) +{ + return storedLevel <= submittedLevel; +} + + +/* + * + */ +//void keepOnlyHighestLevel( vector& codes ) +//{ +// nlassert( ! codes.empty() ); +// sint maxLevel = -1; +// uint32 i; +// for ( i=0; i!=codes.size(); ++i ) +// { +// if ( codes[i]->FirstLevel > maxLevel ) +// { +// maxLevel = codes[i]->FirstLevel; +// } +// } +// vector remainingCodes; +// for ( i=0; i!=codes.size(); ++i ) +// { +// if ( codes[i]->FirstLevel == maxLevel ) +// remainingCodes.push_back( codes[i] ); +// } +// +// //nldebug( "%u codes, highest level = %u with %u occurences", codes.size(), maxLevel, remainingCodes.size() ); +// //nlassert( remainingCodes.size() <= codes.size() ); +// codes = remainingCodes; +// nlassert( ! codes.empty() ); +//} + + +/* + * + */ +bool allIncludedIn( const vu& subset, const vu& bigset ) +{ + vu::const_iterator iv; + for ( iv=subset.begin(); iv!=subset.end(); ++iv ) + { + if ( find( bigset.begin(), bigset.end(), *iv ) == bigset.end() ) + return false; + } + return true; +} + + +/* + * + */ +void loadConfigFlag( CConfigFile& configFile, const char *varTitle, bool &flag ) +{ + CConfigFile::CVar *var = configFile.getVarPtr( varTitle ); + if ( var ) + flag = (var->asInt() == 1); +} + + +/* + * + */ +string::size_type getCapitalFromPos( const string& s, string::size_type startPos ) +{ + //nldebug( "%s %u", s.c_str(), startPos ); + string::size_type p; + for ( p=startPos; p= 'A') && (s[p] <= 'Z') ) + return p; + } + return string::npos; +} + + +/* + * Also used to make system_mp filenames. + * Converts "My Identifier" or "MyIdentifier" to "my_identifier" ("My identifier" to "Myidentifier") + */ +string conventionalDirectory( const string& dirname ) +{ + if ( dirname.empty() ) + return ""; + + string result = dirname; + + // Remove blanks + string::size_type p = 0; + while ( (p = result.find( ' ' )) != string::npos ) + { + result.erase( p, 1 ); + } + + // Convert capitals to underscores + result[0] = tolower( result[0] ); + p = 1; + while ( (p = getCapitalFromPos( result, p )) != string::npos ) + { + result.insert( p, "_" ); + ++p; + result[p] = tolower( result[p] ); + } + return result; +} + + +mss UniqueRMNamesAndSheetCodeHead; + + +/* + * + */ +void readRMNames( mss& values ) +{ + string& name = values["basics.name"]; + if ( ! name.empty() ) + { + string radix = values["FILE"].substr( 0, 5 ); + UniqueRMNamesAndSheetCodeHead.insert( make_pair( name, radix ) ); + } +} + + +/* + * + */ +void loadTitles( const string& sourceWords, const string& sourceBase, const string& languageCode, CTitles& dest ) +{ + STRING_MANAGER::TWorksheet worksheet; + STRING_MANAGER::loadExcelSheet( TranslationPath + sourceBase + "/" + sourceWords + "_words_" + languageCode + ".txt", worksheet ); + uint cp, cn, nbTitles = 0; + if ( worksheet.findCol( ucstring(sourceWords + " ID"), cp ) && worksheet.findCol( ucstring("name"), cn ) ) + { + for ( std::vector::iterator ip = worksheet.begin(); ip!=worksheet.end(); ++ip ) + { + if ( ip == worksheet.begin() ) // skip first row + continue; + STRING_MANAGER::TWorksheet::TRow& row = *ip; + dest.insert( make_pair( row[cp].toString(), row[cn].toUtf8() ) ); + ++nbTitles; + } + } + else + nlwarning( "%s ID or name not found", sourceWords.c_str() ); + + nlinfo( "Loaded %u %s titles", nbTitles, sourceWords.c_str() ); +} + + +/* + * + */ +void extractRawMaterialNames() +{ + loadCSVFile( ExtractNamesCsv.c_str(), readRMNames ); + FILE *output = fopen( (CFile::getFilenameWithoutExtension( ExtractNamesCsv ) + "_output.csv").c_str(), "wt" ); + fprintf( output, "Code;Name\n" ); + for ( mss::const_iterator iun=UniqueRMNamesAndSheetCodeHead.begin(); iun!=UniqueRMNamesAndSheetCodeHead.end(); ++iun ) + { + const string& codeRadix = (*iun).second; + const string& name = (*iun).first; + fprintf( output, "%s;%s\n", codeRadix.c_str(), name.c_str() ); + } +} + + +/* + * + */ +void cleanExteriorWhitespace( vs& line ) +{ + for ( vs::iterator it=line.begin(); it!=line.end(); ++it ) + { + CSString& s = (*it); + string::size_type p; + for ( p=0; p!=s.size(); ++p ) + { + if ( s[p] != ' ' ) + break; + } + if ( (p != 0) && (p != s.size()) ) + s = s.substr( p ); + + for ( p=0; p!=s.size(); ++p ) + { + if ( s[s.size()-1-p] != ' ' ) + break; + } + if ( (p != 0) && (p != s.size()) ) + s = s.rightCrop( p ); + } +} + + +uint TFamInfo::UseGenerateOnly = 0; + +// Only used for deposits; for creature, works with the creature sheets found +/*bool TFamInfo::existsInEcosystem( TEcosystem iEcosystem, TStatQuality statQuality ) const +{ + switch ( iEcosystem ) + { + case CommonEcosystem: // The Common rm exists if the rm family has a freq=2 (or 0 but only in Supreme) + return ( (find( Freqs.begin(), Freqs.end(), 2 ) != Freqs.end()) + || ((find( Freqs.begin(), Freqs.end(), 0 ) != Freqs.end()) && (statQuality == Supreme)) ); + // was: find_if ... bind2nd( equals(), 1 ) + break; + case PrimeRoots: // Only freq 1 families exist if the PrimeRoots + return find( Freqs.begin(), Freqs.end(), 1 ) != Freqs.end(); + break; + default: // A rm family exists in the ecosystem matching a civ if the corresponding freq is 1 or 3 + { + uint iCiv = getIndexFromString( ecosystemCodes[iEcosystem], CivEcosystemCodes, NbCiv, false ); + vector::const_iterator it = find( Civs.begin(), Civs.end(), (TCiv)iCiv ); + if ( it != Civs.end() ) + return (Freqs[it-Civs.begin()] == 1) || (Freqs[it-Civs.begin()] == 3); + else + return false; + } + } +}*/ + +// Only used for deposits; +bool TFamInfo::existsInEcosystem( TEcosystem iEcosystem, TStatQuality statQuality ) const +{ + if ( find( Freqs.begin(), Freqs.end(), 0 ) != Freqs.end() ) + { + // Freq 0 => only Common/Supreme + return (statQuality == Supreme) && (iEcosystem == CommonEcosystem); + } + else if ( statQuality <= Fine ) + { + // Basic, Fine => Common + return (iEcosystem == CommonEcosystem); + } + else + { + // Choice to Supreme => One per ecosystem + return (iEcosystem != CommonEcosystem) && (iEcosystem < NbEcosystems); + } +} + + +/* + * + */ +struct TCraftPartInfo +{ + CSString Name; + CSString Path; + uint8 PartIndex; + bool Enabled; +}; + + +/* + * + */ +class CCraftParts +{ +public: + + /// + CCraftParts() : CraftParts( NbFaberElements ) + { + for ( uint i=0; i!=NbFaberElements; ++i ) + { + CraftParts[i].PartIndex = i; + CraftParts[i].Enabled = false; + } + } + + /// + void registerPartChars( const CSString& parts ) + { + for ( string::size_type p=0; p!=parts.size(); ++p ) + { + uint index = (uint)(parts[p] - 'A'); + CraftParts[index].Enabled = true; + } + } + + /// + bool isEnabled( uint index ) const + { + return CraftParts[index].Enabled; + } + + /// + void getNamesAndPaths( const vector& paths ) + { + uint i = 0; + vector::const_iterator ip; + for ( ip=paths.begin(); ip!=paths.end(); ++ip ) + { + if ( i >= CraftParts.size() ) + nlerror( "Mismatch between sitem DFN and constant (nb of craft parts)" ); + + CraftParts[i].Path = (*ip); + string::size_type p = (*ip).rfind( '.' ) + 1; // string::npos+1 gives 0 + CraftParts[i].Name = (*ip).substr( p ); + nldebug( "%u: %s", ip-paths.begin(), CraftParts[i].Name.c_str() ); + ++i; + } + } + + /// + TCraftPartInfo& operator[] ( uint index ) { return CraftParts[index]; } + + vector< TCraftPartInfo > CraftParts; + +}; + +typedef map CFamMap; +CFamMap FamSet; +CCraftParts CraftParts; + +enum TFamAndPropLine { + LFam, LGroup, LCraftParts, LCiv, LFreq, LLoc, + LIconMain, LIconBk, LIconOv1, LIconOv2, LIconSpecial, + LCraftPlans, LGenerateOnly, + LBaseOfRemarkableStatIndices, + LColorIndex = LBaseOfRemarkableStatIndices + NB_REMARKABLE_STAT_INDICES, + LJewelProtIndex, + NbFamAndPropCols }; + + +// static +bool TFamInfo::mustGenerateFamily( uint iFamily ) +{ + if ( families[iFamily].empty() ) + return false; + else if ( ! TFamInfo::UseGenerateOnly ) + return true; + else + { + TFamInfo& famInfo = FamSet[families[iFamily]]; + return ( famInfo.GenerateOnly ); + } +} + + +/* + * + */ +CSString getShortFaberElemString( uint rFaberElem ) +{ + string& longString = CraftParts[rFaberElem].Name; + return reinterpret_cast(longString.substr( longString.find( "(" ) + 1 )).rightCrop( 1 ); +} + + +/* + * + */ +TCiv getCivFromStr( const CSString& civStr ) +{ + if ( civStr.empty() ) + return AllCiv; + else + { + for ( uint i=0; i!=NbCiv; ++i ) + { + if ( civStr == CSString(CivNames[i]) ) + return (TCiv)i; + } + nlwarning( "Unknown civ '%s'", civStr.c_str() ); + return AllCiv; + } +} + + +/* + * + */ +uint getFreqFromStr( const CSString& freqStr ) +{ + uint f = atoi( freqStr.c_str() ); + if ( (f < 1) && (f > 5) ) + nlwarning( "Unknown freq '%s'", freqStr.c_str() ); + return f; +} + + +/* + * Returns ~0 if s is empty + */ +TGroup getNewOrExistingGroupFromStr( const CSString& s ) +{ + uint i = getIndexFromString( s, groups, false ); + if ( i == ~0 ) + { + if ( s.empty() ) + return ~0; + else + { + i = groups.size(); + groups.push_back( s ); + nlinfo( "New group: %s (%u)", s.c_str(), i ); + } + } + return i; +} + + +/* + * + */ +void deliverFamAndProp( vs& line ) +{ + if ( line.size() < NbFamAndPropCols ) + line.resize( NbFamAndPropCols ); + + cleanExteriorWhitespace( line ); + + if ( line[LFam].empty() ) + { + // Load special icons + if ( (line.size() >= LIconSpecial+1) && (! line[LIconSpecial].empty()) && (line[LIconMain].empty()) ) + { + /*if ( line.size() >= LIconMain+1 ) + Icons[line[LIconSpecial]].Icon = line[LIconMain];*/ + if ( line.size() >= LIconBk+1 ) + Icons[line[LIconSpecial]].IconBackground = line[LIconBk]; + if ( line.size() >= LIconOv1+1 ) + Icons[line[LIconSpecial]].IconOver = line[LIconOv1]; + } + return; + } + + // Load icons of families + if ( line.size() >= LIconMain+1 ) + { + Icons[line[LFam]].Icon = line[LIconMain]; + if ( ! line[LGroup].empty() ) + { + // For group, set icon of first family of group found! (for forage source knowledge) + if ( Icons.find( line[LGroup] ) == Icons.end() ) + { + Icons[line[LGroup]].Icon = line[LIconMain]; + } + } + } + if ( line.size() >= LIconBk+1 ) + Icons[line[LFam]].IconBackground = line[LIconBk]; + if ( line.size() >= LIconOv1+1 ) + Icons[line[LFam]].IconOver = line[LIconOv1]; + + TFamInfo& famInfo = FamSet[line[LFam]]; + famInfo.IsActive = true; + /*if ( ! line[LCraftParts].empty() ) + { + // Store by property (line[LProp]) + famInfo.Properties.push_back( line[LProp] ); + famInfo.CraftPartsByProp.push_back( famInfo.CompatibleCraftParts.size() ); // beginning of craft parts chars + famInfo.CompatibleCraftParts += line[LCraftParts]; + CraftParts.registerPartChars( line[LCraftParts] ); + famInfo.Civs.push_back( getCivFromStr( line[LCiv] ) ); + famInfo.Freqs.push_back( getFreqFromStr( line[LFreq] ) ); + famInfo.IsInDeposits = line[LLoc].contains( "D" ); + famInfo.IsInCreatures = line[LLoc].contains( "C" ); + if ( ! (famInfo.IsInDeposits || famInfo.IsInCreatures) ) + nlwarning( "Unknown loc for %s", line[LFam].c_str() ); + }*/ + + for ( string::size_type p=0; p!=line[LCraftParts].size(); ++p ) + { + // Store by property = craft part (each char of line[LCraftParts]) + CSString craftPart = string( 1, line[LCraftParts][p]); + famInfo.Properties.push_back( craftPart ); + famInfo.CraftPartsByProp.push_back( famInfo.CompatibleCraftParts.size() ); + famInfo.CompatibleCraftParts += craftPart; + CraftParts.registerPartChars( craftPart ); + famInfo.Civs.push_back( getCivFromStr( line[LCiv] ) ); + famInfo.Freqs.push_back( getFreqFromStr( line[LFreq] ) ); + } + if ( line[LCraftParts].empty() ) + { + famInfo.Freqs.push_back( getFreqFromStr( line[LFreq] ) ); // freq needed for Rarity computation + } + famInfo.Group = getNewOrExistingGroupFromStr( line[LGroup] ); + famInfo.IsInDeposits = line[LLoc].contains( "D" ); + famInfo.IsInCreatures = line[LLoc].contains( "C" ); + if ( ! (famInfo.IsInDeposits || famInfo.IsInCreatures) ) + { + famInfo.SpecialCreatureTag = line[LLoc]; + if ( (famInfo.SpecialCreatureTag[0] != 'G') && (famInfo.SpecialCreatureTag[0] != 'I') ) + nlwarning( "Unknown loc %s for %s", line[LLoc].c_str(), line[LFam].c_str() ); + } + famInfo.IsForMission = line[LCraftParts].empty(); + for ( uint i=0; i!=NB_REMARKABLE_STAT_INDICES; ++i ) + { + if ( line[LBaseOfRemarkableStatIndices+i].empty() && (! line[LCraftParts].empty()) && (line[LFreq] != "0") ) + nlerror( "%s has empty stat index %u", line[LFam].c_str(), i ); + famInfo.RemarkableStatIndex[i] = atoi( line[LBaseOfRemarkableStatIndices+i].c_str() ); + } + if ( ! line[LColorIndex].empty() ) + famInfo.ColorIndex = atoi( line[LColorIndex].c_str() ); + if ( ! line[LJewelProtIndex].empty() ) + famInfo.JewelProtIndex = atoi( line[LJewelProtIndex].c_str() ); + bool markedForGeneration = (line[LGenerateOnly] == "X"); + if ( (!markedForGeneration) && famInfo.GenerateOnly ) + { + nlwarning( "Found duplicate family line with different GenerateOnly setting" ); + } + else + { + famInfo.GenerateOnly = markedForGeneration; + } + if ( famInfo.GenerateOnly ) + ++TFamInfo::UseGenerateOnly; +} + + +typedef map< TGroup, set > CGroupMap; + + +/* + * + */ +void loadFamAndProp( const string& filename, bool displayAll ) +{ + loadCSVFile( filename.c_str(), deliverFamAndProp ); + + if ( displayAll ) + { + set propSet; + CGroupMap groupMap; + + /// Generate contents of item_mp_family.typ (and fill group map) + nlinfo( "item_mp_family.typ:" ); + InfoLog->displayRawNL( "" ); + uint i = 1; + for ( CFamMap::iterator iss=FamSet.begin(); iss!=FamSet.end(); ++iss ) + { + const CSString& famStr = (*iss).first; + TFamInfo& famInfo = (*iss).second; + InfoLog->displayRawNL( "", famStr.c_str(), i ); + + // Get info about props and group + for ( vs::iterator ip=famInfo.Properties.begin(); ip!=famInfo.Properties.end(); ++ip ) + { + propSet.insert( *ip ); + } + groupMap[ famInfo.Group ].insert( i ); // ~0 is for "no group" (creature's RMs only) + ++i; + } + + /* + /// Generate family-specialized forage search bricks (TODO) + nlinfo( "Family-specialized forage search bricks:"); + i = 1; + for ( CGroupMap::iterator igm=groupMap.begin(); igm!=groupMap.end(); ++igm ) + { + CSString skill = toString( "SHFM%u", i ); + CSString rmgrpBrickCode = toString( "BHFPMB%02u", i ); + CSString rmfamBrickFamCode = "BHFPMI" + string( 1, (char)'A' + ((char)(i-1)) ); + uint j = 1; + for ( set:::iterator ifs=(*igm).begin(); ifs!=(*igm).end(); ++ifs ) + { + // TODO: modifier of modifier + CSString brickCode = rmfamBrickFamCode + toString( "%02u", j ); + InfoLog->displayRawNL( "%s\t80\t%s\t%u\t\t%s\t\tFG_RMFAM_FILT: %u\t", brickCode.c_str(), rmgrpBrickCode.c_str(), j, skill.c_str(), (*ifs) ); + ++j; + } + } + + /// Generate family-specialized forage search phrases (TODO) + nlinfo( "Family-specialized forage search phrases:"); + i = 1; + for ( CFamMap::iterator iss=FamSet.begin(); iss!=FamSet.end(); ++iss ) + { + const CSString& famStr = (*iss).first; + TFamInfo& famInfo = (*iss).second; + InfoLog->displayRawNL( "", famStr.c_str(), i ); + } + + /// Generate family-specialized forage extraction bricks (TODO) + nlinfo( "Family-specialized forage extraction bricks:"); + i = 1; + for ( CFamMap::iterator iss=FamSet.begin(); iss!=FamSet.end(); ++iss ) + { + const CSString& famStr = (*iss).first; + TFamInfo& famInfo = (*iss).second; + InfoLog->displayRawNL( "", famStr.c_str(), i ); + ++i; + } + + /// Generate family-specialized forage extraction phrases (TODO) + nlinfo( "Family-specialized forage extraction phrases:"); + i = 1; + for ( CFamMap::iterator iss=FamSet.begin(); iss!=FamSet.end(); ++iss ) + { + const CSString& famStr = (*iss).first; + TFamInfo& famInfo = (*iss).second; + InfoLog->displayRawNL( "", famStr.c_str(), i ); + ++i; + }*/ + + /// Generate item_mp_property.typ + nlinfo( "Item parts as props:" ); + InfoLog->displayRawNL( "" ); + i = 1; + for ( set::iterator iss=propSet.begin(); iss!=propSet.end(); ++iss ) + { + InfoLog->displayRawNL( "", (*iss).c_str(), i ); + ++i; + } + + /// Generate item_mp_group.typ + nlinfo( "Groups:" ); + InfoLog->displayRawNL( "" ); + i = 1; + for ( CGroupMap::iterator igm=groupMap.begin(); igm!=groupMap.end(); ++igm ) + { + if ( (*igm).first != ~0 ) + { + InfoLog->displayRawNL( "", (groups[(*igm).first]).c_str(), i ); + ++i; + } + } + + /* + /// Generate group-specialized forage search bricks (TODO) + nlinfo( "Group-specialized forage search bricks:"); + i = 1; + for ( CGroupMap::iterator igm=groupMap.begin(); igm!=groupMap.end(); ++igm ) + { + CSString skill = toString( "SHFM%u", i ); + CSString rmgrpBrickCode = toString( "BHFPMB%02u", i ); + ++i; + } + + /// Generate group-specialized forage search phrases + nlinfo( "Group-specialized forage search phrases:"); + i = 1; + for ( set::iterator iss=groupSet.begin(); iss!=groupSet.end(); ++iss ) + { + if ( (*iss).empty() ) + continue; + InfoLog->displayRawNL( "", (*iss).c_str(), i ); + ++i; + } + + /// Generate group-specialized forage extraction bricks + nlinfo( "Group-specialized forage extraction bricks:"); + i = 1; + for ( set::iterator iss=groupSet.begin(); iss!=groupSet.end(); ++iss ) + { + if ( (*iss).empty() ) + continue; + InfoLog->displayRawNL( "", (*iss).c_str(), i ); + ++i; + } + + /// Generate group-specialized forage extraction phrases + nlinfo( "Group-specialized forage extraction phrases:"); + i = 1; + for ( set::iterator iss=groupSet.begin(); iss!=groupSet.end(); ++iss ) + { + if ( (*iss).empty() ) + continue; + InfoLog->displayRawNL( "", (*iss).c_str(), i ); + ++i; + }*/ + + nlinfo( "TODO: Keep old values when adding new entries" ); + nlinfo( "Don't forget to regen craft plans and to map localized texts" ); + } +} + + +/* + * Multi-indexed array. + * NC is the number of columns. + */ +template +class CSortableData +{ +public: + + /// A row is made of fields, usually 1 per column but there may be more than one (each one is a key) + struct TSortableItem + { + std::vector Fields [NC]; + + /// + void push( uint32 column, const std::string& f, bool allowDuplicates=false ) + { + if ( (allowDuplicates) || (find( Fields[column].begin(), Fields[column].end(), f ) == Fields[column].end()) ) + Fields[column].push_back( f ); + } + + /** + * Display the item as a row of a HTML table. + * If (key!=previousKey) and (name==previousName), the row will not be displayed entirely to save space + * + * \param keyColumn If not ~0, column used for sorting => this column displays only the field matching the key + * \param key The key used for sorting (see keyColumn) + * \param previousKey Previous key + * \param nameColumn If not ~0, column used for the unique name (column must have exaclty one element) + * \param previousName Previous name + */ + std::string toHTMLRow( uint32 keyColumn=~0, const string& key=string(), const string& previousKey=string(), + uint32 nameColumn=~0, const string& previousName=string() ) const + { + std::string s = "
    "; + bool lightMode = (nameColumn == ~0) ? false : ((key != previousKey) && (Fields[nameColumn][0] == previousName)); + for ( uint32 c=0; c!=NC; ++c ) + { + s += ""; + } + s += "\n"; + return s; + } + + + /// + std::string toCSVLine( char columnSeparator=',', string internalSeparator=" - ", uint32 keyColumn=~0, const string& key=string(), const string& previousKey=string(), + uint32 nameColumn=~0, const string& previousName=string() ) const + { + std::string s; + bool lightMode = (nameColumn == ~0) ? false : ((key != previousKey) && (Fields[nameColumn][0] == previousName)); + for ( uint32 c=0; c!=NC; ++c ) + { + if ( c == keyColumn ) + s += key; // key should be a substr of columnToString( c ) + else + { + if ( lightMode ) + s += "\""; + else + s += columnToString( c, internalSeparator ); + } + s += columnSeparator; + } + s += "\n"; + return s; + } + + /// + std::string columnToString( uint32 column, const std::string& internalSeparator=", " ) const + { + std::string s; + std::vector::const_iterator ivs; + for ( ivs=Fields[column].begin(); ivs!=Fields[column].end(); ++ivs ) + { + if ( ivs!=Fields[column].begin() ) + s += internalSeparator; + s += (*ivs); + } + return s; + } + }; + + typedef std::multimap< std::string, uint32 > CLookup; // key to index (not pt because reallocation invalidates pointers) + typedef std::vector< TSortableItem > CItems; + + /// Init + void init( bool enabled ) + { + _Enabled = enabled; + } + + /// Add a row + void addItem( const TSortableItem& item ) + { + if ( ! _Enabled ) + return; + + _Items.push_back( item ); + for ( uint32 c=0; c!=NC; ++c ) + { + for ( std::vector::const_iterator ik=item.Fields[c].begin(); ik!=item.Fields[c].end(); ++ik ) + { + _Indices[c].insert( make_pair( *ik, _Items.size()-1 ) ); + } + } + } + + /** + * Update a row (found by the first column, which must have exactly one element). + * Returns true if it existed before, false if it's being created. + * If it existed before: + * - Does not remove elements that already exist and are not in the new item + * - Adds the new elements found in the new item at the specified columns, and updates lookup map + */ + bool updateItemAppend( const TSortableItem& item, uint32 column ) + { + if ( ! _Enabled ) + return true; // quiet + + uint32 nameColumn = 0; + CLookup::iterator ilk = _Indices[nameColumn].find( item.Fields[nameColumn][0] ); + if ( ilk != _Indices[nameColumn].end() ) + { + uint32& index = (*ilk).second; + + // Update map for the specified column + // and update item column + for ( std::vector::const_iterator ivs=item.Fields[column].begin(); ivs!=item.Fields[column].end(); ++ivs ) + { + ilk = _Indices[column].find( *ivs ); + if ( (ilk == _Indices[column].end()) || ( getRow( (*ilk).second ).Fields[nameColumn][0] != item.Fields[nameColumn][0]) ) + { + _Indices[column].insert( make_pair( *ivs, index ) ); + _Items[index].Fields[column].push_back( *ivs ); + } + } + + return true; + } + else + { + addItem( item ); + return false; + } + } + + /** + * Update a row (found by the first column, which must have exactly one element). + * Returns true if it existed before, false if it's being created. + * If it existed before: + * - Does not update lookup maps or item for columns that were already present. + * - Adds entries in lookup maps and updates item for new columns (fields that were empty). + */ + /*bool updateItemAppend( const TSortableItem& item ) + { + if ( ! _Enabled ) + return true; // quiet + + CLookup::iterator ilk = _Indices[0].find( item.Fields[0][0] ); + if ( ilk != _Indices[0].end() ) + { + uint32& index = (*ilk).second; + + for ( uint32 c=1; c!=NC; ++c ) + { + // Update maps for previously empty columns + if ( _Items[index].Fields[c].empty() ) + { + for ( std::vector::iterator ivs=item.Fields[c].begin(); ivs!=item.Fields[c].end(); ++ivs ) + _Indices[c].insert( make_pair( *ivs, index ) ); + } + + // Update item column + _Items[index].Fields[c] = item.Fields[c]; + } + + return true; + } + else + { + addItem( item ); + return false; + } + }*/ + + /// Find or browse by key + CLookup& lookup( uint32 column ) + { + return _Indices[column]; + } + + /// Browse by adding order + CItems& items() + { + return _Items; + } + + /// Get a row by index + TSortableItem& getRow( uint32 index ) + { + return _Items[index]; + } + +private: + + CLookup _Indices [NC]; + + CItems _Items; + + bool _Enabled; +}; + + +typedef CSortableData CRMData; +typedef CRMData::TSortableItem TRMItem; + + +/** + * + */ +class CProducedDocHtml +{ +public: + + /// + CProducedDocHtml() : _File(NULL), _Enabled(false) {} + + /// + void open( const std::string& filename, const std::string& title, bool enableFlag ) + { + _Enabled = enableFlag; + if ( ! _Enabled ) + return; + + _File = fopen( filename.c_str(), "wt" ); + fprintf( _File, ("\n\n" + title + "\n\n").c_str() ); + } + + /// + void write( const std::string& htmlCode ) + { + if ( ! _Enabled ) + return; + + fprintf( _File, htmlCode.c_str() ); + } + + /// + void writeln( const std::string& htmlCode ) + { + write( htmlCode + "\n" ); + } + + /// + void writebln( const std::string& htmlCode ) + { + write( htmlCode + "
    \n" ); + } + + /// + void writepln( const std::string& htmlCode ) + { + write( "

    " + htmlCode + "

    \n" ); + } + + /// + void save() + { + if ( ! _Enabled ) + return; + + fprintf( _File, "\n" ); + fclose( _File ); + } + +private: + + FILE *_File; + bool _Enabled; +}; + + +/** + * + */ +class CProducedDocCSV +{ +public: + + /// + CProducedDocCSV() : _File(NULL), _Enabled(false) {} + + /// + void open( const std::string& filename, bool enableFlag ) + { + _Enabled = enableFlag; + if ( ! _Enabled ) + return; + + _File = fopen( filename.c_str(), "wt" ); + } + + /// + void write( const std::string& data ) + { + if ( ! _Enabled ) + return; + + fprintf( _File, data.c_str() ); + } + + /// + void writeln( const std::string& data ) + { + write( data + "\n" ); + } + + /// + void save() + { + if ( ! _Enabled ) + return; + + fclose( _File ); + } + +private: + + FILE *_File; + bool _Enabled; +}; + + + +/** + * + */ +class CGenRawMaterial +{ +public: + + /// Constructor + CGenRawMaterial( const std::string& sheetName = std::string() ) : SheetName(sheetName), ILocation(~0), IFamily(~0), IEcosystem(NbEcosystems), StatQuality(InvalidStatQuality), Color(InvalidColor), StatEnergyAvg(0) + {} + + /// Serial + void serial( NLMISC::IStream& s ) + { + s.serial( SheetName ); + s.serial( (uint32&)ILocation ); + s.serial( (uint32&)IFamily ); + s.serial( (uint32&)Group ); + s.serial( (uint32&)IEcosystem ); + s.serial( (uint32&)StatQuality ); + s.serial( (sint32&)Color ); + //s.serial( (uint32&)SapLoadLevel ); + //s.serial( (uint32&)Rarity ); + s.serial( (sint32&)StatEnergyAvg ); + s.serial( (uint32&)MaxLevel ); + s.serialCont( RMProperties ); + s.serialCont( IPropertyDepths ); + s.serialCont( RMCraftCharacs ); + } + + /// Computes randomly RMCraftCharacs, IPropertyDepths... Returns false if the RM must NOT be generated. + bool computeCraftCharacs( uint iVariant, const CSString& sheetName ); + + /// + void writeSheet( CForm *form ); + + /// + void loadSheet( CForm *form, const std::string& sheetName, bool full ); + + /// + void collectStats( TRMItem& item, CMainStat& mainStats ); + + /// Return average of energies (including max quality as half of the balance) + /*float getEnergyAvg() const + { + if ( RMCraftCharacs.empty() ) + return 0.0f; + else + { + float sum = 0.0f; + for ( list::const_iterator ics=RMCraftCharacs.begin(); ics!=RMCraftCharacs.end(); ++ics ) + { + sum += (*ics).ActualEnergy; + } + //return (sum + (float)MaxQuality / 250.0f) / ((float)RMCraftCharacs.size() + 1); + return (sum / (float)RMCraftCharacs.size()); // now, MaxQuality is not part of the average + } + }*/ + + /// + float getOriginalityAvg() const + { + float sum = 0.0f; + for ( list::const_iterator ics=RMCraftCharacs.begin(); ics!=RMCraftCharacs.end(); ++ics ) + { + sum += (*ics).ActualOriginality; + } + return sum / (float)RMCraftCharacs.size(); + } + + /// + float getOriginalityMax() const + { + float maxOriginality = 0.0f; + for ( list::const_iterator ics=RMCraftCharacs.begin(); ics!=RMCraftCharacs.end(); ++ics ) + { + if ( (*ics).ActualOriginality > maxOriginality ) + maxOriginality = (*ics).ActualOriginality; + } + return maxOriginality; + } + + /// + void fillPropertiesFromFamily() + { + vs& props = FamSet[familyStr()].Properties; + RMProperties.resize( props.size() ); + for ( vs::iterator ip=props.begin(); ip!=props.end(); ++ip ) + { + RMProperties[ip-props.begin()] = getIndexFromString( *ip, properties ); + } + } + + /// + bool hasCraftPart( uint craftPartIndex ) + { + return CraftParts.isEnabled( craftPartIndex ) && (FamSet[familyStr()].CompatibleCraftParts.find( string( 1, (char)'A' + craftPartIndex ).c_str() ) != string::npos); + } + + /// + /*TCiv getCivSpec( uint craftPartIndex, const TFamInfo& famInfo ) + { + TCiv civ = NbCiv; + for ( vector::const_iterator ivc=famInfo.Civs.begin(); ivc!=famInfo.Civs.end(); ++ivc ) + { + // Skip those not matching the current rFaberElem + if ( famInfo.getCraftPartForProp( ivc-famInfo.Civs.begin() ).find( string( 1, (char)('A' + craftPartIndex) ).c_str() ) != string::npos ) + { + if ( (civ != NbCiv) && ((*ivc) != civ) ) + { + nlwarning( "Different civ specializations for %s, %s (%s and %s)", familyStr().c_str(), getShortFaberElemString( craftPartIndex ).c_str(), CivNames[civ], CivNames[*ivc] ); + return AllCiv; + } + civ = (*ivc); + } + } + if ( civ == NbCiv ) + return AllCiv; + else if ( civ = + return civ; + }*/ + + /// + TCiv getCivSpec( TEcosystem iEcosystem, TStatQuality statQuality ) + { + if ( (statQuality <= Fine) || (iEcosystem >= NbEcosystems) ) + return AllCiv; + else + return EcosystemToCiv[iEcosystem]; + } + + /// + /*TCiv getMainCivSpec( const TFamInfo& famInfo ) + { + TCiv civ = NbCiv; + for ( list::const_iterator ics=RMCraftCharacs.begin(); ics!=RMCraftCharacs.end(); ++ics ) + { + TCiv civOfCraftPart = getCivSpec( (*ics).FaberElement, famInfo ); + if ( (civ != NbCiv) && (civOfCraftPart != civ) ) + { + return AllCiv; + } + civ = civOfCraftPart; + } + if ( civ == NbCiv ) + return AllCiv; + else + return civ; + }*/ + + /// + /*const char * getMainEcosystemSpec( const TFamInfo& famInfo ) + { + return CivEcosystemCodes[getMainCivSpec( famInfo )]; + }*/ + + /// Code + CSString SheetName; + + /// Index in locations + uint32 ILocation; + + /// Index in families + uint32 IFamily; + + /// + CSString familyStr() const { return families[IFamily]; } + + /// Group number + TGroup Group; + + /// + CSString groupStr() const { return Group==~0 ? "" : groups[Group]; } + + /// Index in ecosystems + TEcosystem IEcosystem; + + /// + CSString ecosystemStr() const { return ecosystems[IEcosystem]; } + + /// From Basic) to Supreme) + TStatQuality StatQuality; + + /// From 'b' (Basic) to 'f' (Supreme) + char levelZoneLChar() const { return 'b' + (char)StatQuality; } + + /// Same + void setStatQuality( char levelZoneChar ) { StatQuality = (TStatQuality)(levelZoneChar - 'b'); } + + /// For creatures + uint32 ILevelZone; + + /// Index in colors + TColor Color; + + /// + CSString colorStr() const { return colors[Color]; } + + /// Sap load level + //uint32 SapLoadLevel; + + /// Rarity + //uint32 Rarity; + + sint32 StatEnergyAvg; + + /// Max quality + uint32 MaxLevel; + + /// Indices in properties + vu RMProperties; + + /// + CSString propertyStr( uint32 p ) const { return properties[RMProperties[p]]; } + + /// + vu IPropertyDepths; + + /// + CSString propertyDepthStr( uint32 p ) const { return PropertyDepths[IPropertyDepths[p]]; } + + /// + CFaberCharacteristics *getCraftSlot( uint rFaberElem ) + { + std::list< CFaberCharacteristics >::iterator icl; + for ( icl=RMCraftCharacs.begin(); icl!=RMCraftCharacs.end(); ++icl ) + { + if ( (*icl).FaberElement == rFaberElem ) + return &(*icl); + } + return NULL; + } + + /// Randomly generated characs + std::list< CFaberCharacteristics > RMCraftCharacs; +}; + + +/** + * + */ +class COriginalitySorter +{ +public: + + typedef std::set< CGenRawMaterial* > CRMSet; + typedef std::multimap< uint32, CGenRawMaterial*, std::greater > CMultiMapByOriginality; + + /// + COriginalitySorter() : RMByOriginalityByCraftSlot( NbFaberElements ) {} + + /// + void pushRM( CGenRawMaterial *rawMaterial ) + { + RawMaterials.insert( rawMaterial ); + + //InfoLog->displayRawNL( "Inserting RM" ); + std::list< CFaberCharacteristics >::const_iterator ilc; + for ( ilc=rawMaterial->RMCraftCharacs.begin(); ilc!=rawMaterial->RMCraftCharacs.end(); ++ilc ) + { + //InfoLog->displayRawNL( " %u: %s orig=%u", (*ilc).FaberElement, rawMaterial->SheetName.c_str(), (uint32)((*ilc).ActualOriginality*100.0f) ); + RMByOriginalityByCraftSlot[(*ilc).FaberElement].insert( make_pair( (uint32)((*ilc).ActualOriginality*100.0f), rawMaterial ) ); + } + } + + /// + void popAndDeleteRM( CGenRawMaterial *rawMaterial ) + { + delete rawMaterial; + RawMaterials.erase( rawMaterial ); + } + + /// + bool alreadyPopped( CGenRawMaterial *rawMaterial ) const + { + return RawMaterials.find( rawMaterial ) == RawMaterials.end(); + } + + /// fromPos and the returned iterator are the pos internal to the COriginalitySorter RM set + /*CRMSet::const_iterator getFirstRMNotInFamilyListFromPos( const set& familyList, TStatQuality statQuality, CRMSet::const_iterator fromPos ) const + { + CRMSet::const_iterator irm; + for ( irm=fromPos; irm!=RawMaterials.end(); ++irm ) + { + if ( ((*irm)->StatQuality == statQuality) && + (familyList.find( (*irm)->IFamily ) == familyList.end()) ) + return irm; + } + return RawMaterials.end(); + }*/ + + /// + CRMSet::iterator getRMSetBegin() const { return RawMaterials.begin(); } + + /// + CRMSet::iterator getRMSetEnd() const { return RawMaterials.end(); } + + /// + void deleteAllRemainingRM() + { + CRMSet::iterator irm; + for ( irm=RawMaterials.begin(); irm!=RawMaterials.end(); ++irm ) + { + delete (*irm); + } + RawMaterials.clear(); + // Does not clear the maps by originality + } + + std::vector< CMultiMapByOriginality > RMByOriginalityByCraftSlot; + +private: + + CRMSet RawMaterials; +}; + + +#define checkColor( c ) nlassert( colors[c] == #c ); + + +/* + * + */ +void loadDFNs( UFormLoader *formLoader ) +{ + map dfnFields; + NLMISC::CSmartPtr formDfn; + formDfn = formLoader->loadFormDfn( (rmSheetType + ".dfn").c_str() ); + if ( ! formDfn ) + nlerror( "Can't find DFN for %s", rmSheetType.c_str() ); + vector craftPartsPaths; + fillFromDFN( formLoader, dfnFields, formDfn, "", rmSheetType, "mp.MpParam", craftPartsPaths ); + + // Get craft parts + CraftParts.getNamesAndPaths( craftPartsPaths ); + + formDfn = formLoader->loadFormDfn( (crSheetType + ".dfn").c_str() ); + if ( ! formDfn ) + nlerror( "Can't find DFN for %s", crSheetType.c_str() ); + fillFromDFN( formLoader, dfnFields, formDfn, "", crSheetType ); + + // Get lists of predefined values from sitem and creature DFN + families = dfnFields["mp.Family"].TypePredefinedLabels; + familyCodes = dfnFields["mp.Family"].TypePredefinedValues; + groups = dfnFields["mp.Group"].TypePredefinedLabels; + + //properties = dfnFields["mp.Material property 1"].TypePredefinedLabels; + //nlverify( removeEntryFromList( properties, "Undefined" ) != ~0 ); + properties.resize( craftPartsPaths.size() ); + for ( uint i=0; i!=properties.size(); ++i ) // now, use properties as item part list + properties[i] = string( 1, (char)('A' + i) ); + + ecosystems = dfnFields["mp.Ecosystem"].TypePredefinedLabels, + colors = dfnFields["mp.MpColor"].TypePredefinedLabels, + creatures = dfnFields["Basics.Race"].TypePredefinedLabels; + seasons.push_back( "Winter" ); + seasons.push_back( "Spring" ); + seasons.push_back( "Summer" ); + seasons.push_back( "Autumn" ); + //removeEntryFromList( families, "Undefined" ); + //removeEntryFromList( familyCodes, "0" ); + nlverify( removeEntryFromList( ecosystems, "unknown" ) != ~0 ); + nlverify( removeEntryFromList( ecosystems, "Goo" ) != ~0 ); + nlassert( ecosystems[0] == "Common" ); + nlassert( ecosystems[1] == "Desert" ); // ensure we match with enum TEcosystem! + nlassert( ecosystems[2] == "Forest" ); + nlassert( ecosystems[3] == "Lacustre" ); + nlassert( ecosystems[4] == "Jungle" ); + nlassert( ecosystems[5] == "PrimeRoots" ); + //removeEntryFromList( ecosystems, "Common" ); // TODO + nlassert( NbEcosystems == ecosystems.size() ); + nlverify( removeEntryFromList( colors, "None" ) != ~0 ); + nlverify( removeEntryFromList( colors, "UserColor") != ~0 ); + nlassert( colors.size() == NbColors ); + checkColor( Red ); + checkColor( Beige ); + checkColor( Green ); + checkColor( Turquoise ); + checkColor( Blue ); + checkColor( Violet ); + checkColor( White ); + checkColor( Black ); + + /*UndefinedProperty = getIndexFromString( "Undefined", properties ); + nlassert( UndefinedProperty != ~0 );*/ +} + + +/* + * Build RMFamilyIndicesByCreatureModel and DepositFamilyIndices + */ +void dispatchFamiliesToLocations() +{ + for ( CFamMap::iterator iss=FamSet.begin(); iss!=FamSet.end(); ++iss ) + { + const CSString& famStr = (*iss).first; + TFamInfo& famInfo = (*iss).second; + uint iFam = getIndexFromString( famStr, families ); + if ( famInfo.IsInDeposits ) + { + // Deposits + nlassert( iFam != ~0 ); + DepositFamilyIndices.push_back( iFam ); + } + if ( famInfo.IsInCreatures ) + { + // Extract creature name from left of family name (ASSUMES there's no blank in creature name) + CSString creaNameForRMFamily = famStr.splitTo( ' ' ); + + // Dispatch + for ( CSkeletonMap::iterator icm=CreatureModels.begin(); icm!=CreatureModels.end(); ++icm ) + { + const CSString& creaModel = (*icm).first; + TSkeletonInfo& modelInfo = (*icm).second; + + if ( modelInfo.Name == creaNameForRMFamily ) + { + RMFamilyIndicesByCreatureModel[creaModel].push_back( iFam ); + //nlinfo( "+ %s for %s (now %u models registered)", famStr.c_str(), creaModel.c_str(), RMFamilyIndicesByCreatureModel.size() ); + modelInfo.IsUsed = true; // Name and AbbrevName are set by deliverCreatureModels() + } + } + } + else switch ( famInfo.SpecialCreatureTag[0] ) + { + // Goo & invasion/raid creatures + case 'G': + { + GooCreatureFamilyIndices.push_back( iFam ); + nldebug( "Family %s selected for goo creatures", famStr.c_str() ); + break; + } + case 'I': + { + if ( famInfo.SpecialCreatureTag.size() == 1 ) + { + InvasionRaidCreatureFamilyIndices['*'].push_back( iFam ); + nldebug( "Family %s selected for all invasion creatures", famStr.c_str() ); + } + else + { + for ( uint c=1; c!=famInfo.SpecialCreatureTag.size(); ++c ) + { + InvasionRaidCreatureFamilyIndices[famInfo.SpecialCreatureTag[c]].push_back( iFam ); + nldebug( "Family %s selected for invasion creature of type %c", famStr.c_str(), famInfo.SpecialCreatureTag[c] ); + } + } + break; + } + } + } +} + + +/* + * Returns the number of models used + */ +uint checkSkeletons() +{ + uint32 nbSkeUsed = 0; + for ( CSkeletonMap::const_iterator isc=CreatureModels.begin(); isc!=CreatureModels.end(); ++isc ) + { + const string& skeFilename = (*isc).first; + const TSkeletonInfo& ske = (*isc).second; + const bool& used = (*isc).second.IsUsed; + if ( used ) + { + nldebug( "Model %s (%s) %s", skeFilename.c_str(), ske.AbbrevName.c_str(), used?"used":"NOT USED" ); + ++nbSkeUsed; + } + else + nlwarning( "Model %s %s", skeFilename.c_str(), used?"":"NOT USED" ); + } + return nbSkeUsed; +} + + +/* + * + */ +void createDirectoryStructure() +{ + // Create the directory structure + if ( WriteSheetsToDisk ) + { + for ( uint32 i=0; i!=ecosystems.size(); ++i ) + { + string dirname = conventionalDirectory( ecosystems[i] ); + if ( ! CFile::isExists( rawMaterialPath + dirname ) ) + { + CFile::createDirectory( rawMaterialPath + dirname ); + } + else + { + if ( ! CFile::isDirectory( rawMaterialPath + dirname ) ) + { + nlwarning( "%s already existing but not a directory!", (rawMaterialPath + dirname).c_str() ); + } + } + } + string dirname = "_parent"; + if ( ! CFile::isExists( rawMaterialPath + dirname ) ) + { + CFile::createDirectory( rawMaterialPath + dirname ); + } + else + { + if ( ! CFile::isDirectory( rawMaterialPath + dirname ) ) + { + nlwarning( "%s already existing but not a directory!", (rawMaterialPath + dirname).c_str() ); + } + } + } +} + + +#endif // NL_SRG_UTILITIES_H + +/* End of srg_utilities.h */ diff --git a/code/ryzom/tools/sheets_packer/sheets_packer.cpp b/code/ryzom/tools/sheets_packer/sheets_packer.cpp index ae64497eb..b5dc5e951 100644 --- a/code/ryzom/tools/sheets_packer/sheets_packer.cpp +++ b/code/ryzom/tools/sheets_packer/sheets_packer.cpp @@ -1,112 +1,112 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - - -////////////// -// INCLUDES // -////////////// -#include "stdpch.h" -// Misc. -#include "nel/misc/types_nl.h" -#include "nel/misc/debug.h" - -#if defined(NL_OS_WINDOWS) -#include -#include -#endif - -// game share -#include "game_share/ryzom_version.h" - -// Client -#include "sheets_packer_init.h" - - -/////////// -// USING // -/////////// -using namespace NLMISC; - - -///////////// -// GLOBALS // -///////////// -static uint32 Version = 1; // Client Version. - - -/////////////// -// FUNCTIONS // -/////////////// - - -//--------------------------------------------------- -// MAIN : -// Entry for the Apllication. -//--------------------------------------------------- -int main(int argc, char **argv) -{ - ///////////////////////////////// - // Initialize the application. // - try - { - // If the init fail -> return Failure. - if(!init()) - return EXIT_FAILURE; - } - catch(const EFatalError &) { return EXIT_FAILURE; /* nothing to do */ } - catch(const Exception &e) - { - try - { - nlerror ("Initialization of the application failed : %s", e.what()); - } - catch(const EFatalError &) - { - // nothing to do - } - - // Failure -> Exit. - return EXIT_FAILURE; - } - - ///////////////////////////// - // Release all the memory. // - try - { - release(); - } - catch(const EFatalError &) { return EXIT_FAILURE; /* nothing to do */ } - catch(const Exception &e) - { - try - { - nlerror ("Release of the application failed: %s", e.what()); - } - catch(const EFatalError &) - { - // nothing to do - } - - // Failure -> Exit. - return EXIT_FAILURE; - } - - - // EXIT of the Application. - return EXIT_SUCCESS; -}// main // +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + + +////////////// +// INCLUDES // +////////////// +#include "stdpch.h" +// Misc. +#include "nel/misc/types_nl.h" +#include "nel/misc/debug.h" + +#if defined(NL_OS_WINDOWS) +#include +#include +#endif + +// game share +#include "game_share/ryzom_version.h" + +// Client +#include "sheets_packer_init.h" + + +/////////// +// USING // +/////////// +using namespace NLMISC; + + +///////////// +// GLOBALS // +///////////// +static uint32 Version = 1; // Client Version. + + +/////////////// +// FUNCTIONS // +/////////////// + + +//--------------------------------------------------- +// MAIN : +// Entry for the Apllication. +//--------------------------------------------------- +int main(int argc, char **argv) +{ + ///////////////////////////////// + // Initialize the application. // + try + { + // If the init fail -> return Failure. + if(!init()) + return EXIT_FAILURE; + } + catch(const EFatalError &) { return EXIT_FAILURE; /* nothing to do */ } + catch(const Exception &e) + { + try + { + nlerror ("Initialization of the application failed : %s", e.what()); + } + catch(const EFatalError &) + { + // nothing to do + } + + // Failure -> Exit. + return EXIT_FAILURE; + } + + ///////////////////////////// + // Release all the memory. // + try + { + release(); + } + catch(const EFatalError &) { return EXIT_FAILURE; /* nothing to do */ } + catch(const Exception &e) + { + try + { + nlerror ("Release of the application failed: %s", e.what()); + } + catch(const EFatalError &) + { + // nothing to do + } + + // Failure -> Exit. + return EXIT_FAILURE; + } + + + // EXIT of the Application. + return EXIT_SUCCESS; +}// main // diff --git a/code/ryzom/tools/sheets_packer/sheets_packer_cfg.cpp b/code/ryzom/tools/sheets_packer/sheets_packer_cfg.cpp index 760a61869..d44f6f1c0 100644 --- a/code/ryzom/tools/sheets_packer/sheets_packer_cfg.cpp +++ b/code/ryzom/tools/sheets_packer/sheets_packer_cfg.cpp @@ -1,252 +1,252 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - - -///////////// -// INCLUDE // -///////////// -#include "stdpch.h" - -// Misc. -#include "nel/misc/config_file.h" -#include "nel/misc/bit_mem_stream.h" -// Client. -#include "sheets_packer_cfg.h" - - -/////////// -// MACRO // -/////////// -//----------------------------------------------- -/// Macro to read a Bool from the CFG. -/// variableName : Variable Name to Read and Set. -//----------------------------------------------- -#define READ_BOOL(variableName) \ - /* Read the Variable Value From Script */ \ - varPtr = AppCfg.ConfigFile.getVarPtr(#variableName); \ - /* Value found, set the Variable */ \ - if(varPtr) \ - AppCfg.variableName = varPtr->asInt() ? true : false; \ - /* Use the Default Value */ \ - else \ - nlwarning("CFG: Default value used for '"#variableName"' !!!"); \ - -//----------------------------------------------- -/// Macro to read an Int from the CFG. -/// variableName : Variable Name to Read and Set. -//----------------------------------------------- -#define READ_INT(variableName) \ - /* Read the Variable Value From Script */ \ - varPtr = AppCfg.ConfigFile.getVarPtr(#variableName); \ - /* Value found, set the Variable */ \ - if(varPtr) \ - AppCfg.variableName = varPtr->asInt(); \ - /* Use the Default Value */ \ - else \ - nlwarning("CFG: Default value used for '"#variableName"' !!!"); \ - -//----------------------------------------------- -/// Macro to read a Float from the CFG. -/// variableName : Variable Name to Read and Set. -//----------------------------------------------- -#define READ_FLOAT(variableName) \ - /* Read the Variable Value From Script */ \ - varPtr = AppCfg.ConfigFile.getVarPtr(#variableName); \ - /* Value found, set the Variable */ \ - if(varPtr) \ - AppCfg.variableName = varPtr->asFloat(); \ - /* Use the Default Value */ \ - else \ - nlwarning("CFG: Default value used for '"#variableName"' !!!"); \ - -//----------------------------------------------- -/// Macro to read a Double from the CFG. -/// variableName : Variable Name to Read and Set. -//----------------------------------------------- -#define READ_DOUBLE(variableName) \ - /* Read the Variable Value From Script */ \ - varPtr = AppCfg.ConfigFile.getVarPtr(#variableName); \ - /* Value found, set the Variable */ \ - if(varPtr) \ - AppCfg.variableName = varPtr->asDouble(); \ - /* Use the Default Value */ \ - else \ - nlwarning("CFG: Default value used for '"#variableName"' !!!"); \ - -//----------------------------------------------- -/// Macro to read a String from the CFG. -/// variableName : Variable Name to Read and Set. -//----------------------------------------------- -#define READ_STRING(variableName) \ - /* Read the Variable Value From Script */ \ - varPtr = AppCfg.ConfigFile.getVarPtr(#variableName); \ - /* Value found, set the Variable */ \ - if(varPtr) \ - AppCfg.variableName = varPtr->asString(); \ - /* Use the Default Value */ \ - else \ - nlwarning("CFG: Default value used for '"#variableName"' !!!"); \ - -//----------------------------------------------- -/// Macro to read a CVector from the CFG. -/// variableName : Variable Name to Read and Set. -//----------------------------------------------- -#define READ_CVECTOR(variableName) \ - /* Read the Variable Value From Script */ \ - varPtr = AppCfg.ConfigFile.getVarPtr(#variableName); \ - if(varPtr) \ - { \ - /* Check params */ \ - if(varPtr->size()==3) \ - { \ - AppCfg.variableName.x = varPtr->asFloat(0); \ - AppCfg.variableName.y = varPtr->asFloat(1); \ - AppCfg.variableName.z = varPtr->asFloat(2); \ - } \ - else \ - nlwarning("CFG: Bad params for '"#variableName"' !!!"); \ - } \ - else \ - nlwarning("CFG: Default value used for '"#variableName"' !!!"); \ - - -/////////// -// USING // -/////////// -using namespace NLMISC; - - -//////////// -// GLOBAL // -//////////// -CClientConfig AppCfg; -const std::string ConfigFileName = "sheets_packer.cfg"; - - -///////////// -// METHODS // -///////////// -//--------------------------------------------------- -// CClientConfig : -// Constructor. -//--------------------------------------------------- -CClientConfig::CClientConfig() -{ -}// CClientConfig // - - -//--------------------------------------------------- -// load : -// Load the client config file. -//--------------------------------------------------- -void setValues() -{ - nlinfo ("reloading the config file!"); - - CConfigFile::CVar *varPtr = 0; - - ////////// - // MISC // - // Data Path. - try - { - AppCfg.DataPath.clear (); - CConfigFile::CVar &cvDataPath = AppCfg.ConfigFile.getVar("DataPath"); - for (uint i = 0; i < cvDataPath.size(); i++) - AppCfg.DataPath.push_back(cvDataPath.asString(i)); - } - catch(const EUnknownVar &) {nlwarning("Default value used for 'DataPath' !!!");} - - // World sheet name - READ_STRING(WorldSheet) - // Primitives path - READ_STRING(PrimitivesPath) - // Output data path - READ_STRING(OutputDataPath) - // Ligo primitive class - READ_STRING(LigoPrimitiveClass) - - ///////////// - // FILTERS // - createDebug (); - try - { - CConfigFile::CVar &cvTmp = AppCfg.ConfigFile.getVar("NegFiltersDebug"); - for(uint k = 0; k < (uint)cvTmp.size(); ++k) - { - DebugLog->addNegativeFilter (cvTmp.asString(k).c_str()); - } - } - catch(const EUnknownVar &) {} - try - { - CConfigFile::CVar &cvTmp = AppCfg.ConfigFile.getVar("NegFiltersInfo"); - for(uint k = 0; k < (uint)cvTmp.size(); ++k) - { - InfoLog->addNegativeFilter (cvTmp.asString(k).c_str()); - } - } - catch(const EUnknownVar &) {} - try - { - CConfigFile::CVar &cvTmp = AppCfg.ConfigFile.getVar("NegFiltersWarning"); - for(uint k = 0; k < (uint)cvTmp.size(); ++k) - { - WarningLog->addNegativeFilter (cvTmp.asString(k).c_str()); - } - } - catch(const EUnknownVar &) {} -}// load // - - -//----------------------------------------------- -// serial : -// Serialize CFG. -//----------------------------------------------- -void CClientConfig::serial(class NLMISC::IStream &f) throw(NLMISC::EStream) -{ - // Start the opening of a new node named ClientCFG. - f.xmlPush("ClientCFG"); - - // Close the serial for hte Client CFG. - f.xmlPop(); -}// serial // - - -//----------------------------------------------- -// init : -//----------------------------------------------- -void CClientConfig::init(const std::string &configFileName) -{ - if(!CFile::fileExists(configFileName)) - nlwarning("CFG::init: '%s' Not Found !!!", configFileName.c_str ()); - - // if the config file will be modified, it calls automatically the function setValues() - AppCfg.ConfigFile.setCallback (setValues); - - // load the config files - AppCfg.ConfigFile.load (configFileName); -}// init // - - -//----------------------------------------------- -// release : -//----------------------------------------------- -void CClientConfig::release () -{ -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + + +///////////// +// INCLUDE // +///////////// +#include "stdpch.h" + +// Misc. +#include "nel/misc/config_file.h" +#include "nel/misc/bit_mem_stream.h" +// Client. +#include "sheets_packer_cfg.h" + + +/////////// +// MACRO // +/////////// +//----------------------------------------------- +/// Macro to read a Bool from the CFG. +/// variableName : Variable Name to Read and Set. +//----------------------------------------------- +#define READ_BOOL(variableName) \ + /* Read the Variable Value From Script */ \ + varPtr = AppCfg.ConfigFile.getVarPtr(#variableName); \ + /* Value found, set the Variable */ \ + if(varPtr) \ + AppCfg.variableName = varPtr->asInt() ? true : false; \ + /* Use the Default Value */ \ + else \ + nlwarning("CFG: Default value used for '"#variableName"' !!!"); \ + +//----------------------------------------------- +/// Macro to read an Int from the CFG. +/// variableName : Variable Name to Read and Set. +//----------------------------------------------- +#define READ_INT(variableName) \ + /* Read the Variable Value From Script */ \ + varPtr = AppCfg.ConfigFile.getVarPtr(#variableName); \ + /* Value found, set the Variable */ \ + if(varPtr) \ + AppCfg.variableName = varPtr->asInt(); \ + /* Use the Default Value */ \ + else \ + nlwarning("CFG: Default value used for '"#variableName"' !!!"); \ + +//----------------------------------------------- +/// Macro to read a Float from the CFG. +/// variableName : Variable Name to Read and Set. +//----------------------------------------------- +#define READ_FLOAT(variableName) \ + /* Read the Variable Value From Script */ \ + varPtr = AppCfg.ConfigFile.getVarPtr(#variableName); \ + /* Value found, set the Variable */ \ + if(varPtr) \ + AppCfg.variableName = varPtr->asFloat(); \ + /* Use the Default Value */ \ + else \ + nlwarning("CFG: Default value used for '"#variableName"' !!!"); \ + +//----------------------------------------------- +/// Macro to read a Double from the CFG. +/// variableName : Variable Name to Read and Set. +//----------------------------------------------- +#define READ_DOUBLE(variableName) \ + /* Read the Variable Value From Script */ \ + varPtr = AppCfg.ConfigFile.getVarPtr(#variableName); \ + /* Value found, set the Variable */ \ + if(varPtr) \ + AppCfg.variableName = varPtr->asDouble(); \ + /* Use the Default Value */ \ + else \ + nlwarning("CFG: Default value used for '"#variableName"' !!!"); \ + +//----------------------------------------------- +/// Macro to read a String from the CFG. +/// variableName : Variable Name to Read and Set. +//----------------------------------------------- +#define READ_STRING(variableName) \ + /* Read the Variable Value From Script */ \ + varPtr = AppCfg.ConfigFile.getVarPtr(#variableName); \ + /* Value found, set the Variable */ \ + if(varPtr) \ + AppCfg.variableName = varPtr->asString(); \ + /* Use the Default Value */ \ + else \ + nlwarning("CFG: Default value used for '"#variableName"' !!!"); \ + +//----------------------------------------------- +/// Macro to read a CVector from the CFG. +/// variableName : Variable Name to Read and Set. +//----------------------------------------------- +#define READ_CVECTOR(variableName) \ + /* Read the Variable Value From Script */ \ + varPtr = AppCfg.ConfigFile.getVarPtr(#variableName); \ + if(varPtr) \ + { \ + /* Check params */ \ + if(varPtr->size()==3) \ + { \ + AppCfg.variableName.x = varPtr->asFloat(0); \ + AppCfg.variableName.y = varPtr->asFloat(1); \ + AppCfg.variableName.z = varPtr->asFloat(2); \ + } \ + else \ + nlwarning("CFG: Bad params for '"#variableName"' !!!"); \ + } \ + else \ + nlwarning("CFG: Default value used for '"#variableName"' !!!"); \ + + +/////////// +// USING // +/////////// +using namespace NLMISC; + + +//////////// +// GLOBAL // +//////////// +CClientConfig AppCfg; +const std::string ConfigFileName = "sheets_packer.cfg"; + + +///////////// +// METHODS // +///////////// +//--------------------------------------------------- +// CClientConfig : +// Constructor. +//--------------------------------------------------- +CClientConfig::CClientConfig() +{ +}// CClientConfig // + + +//--------------------------------------------------- +// load : +// Load the client config file. +//--------------------------------------------------- +void setValues() +{ + nlinfo ("reloading the config file!"); + + CConfigFile::CVar *varPtr = 0; + + ////////// + // MISC // + // Data Path. + try + { + AppCfg.DataPath.clear (); + CConfigFile::CVar &cvDataPath = AppCfg.ConfigFile.getVar("DataPath"); + for (uint i = 0; i < cvDataPath.size(); i++) + AppCfg.DataPath.push_back(cvDataPath.asString(i)); + } + catch(const EUnknownVar &) {nlwarning("Default value used for 'DataPath' !!!");} + + // World sheet name + READ_STRING(WorldSheet) + // Primitives path + READ_STRING(PrimitivesPath) + // Output data path + READ_STRING(OutputDataPath) + // Ligo primitive class + READ_STRING(LigoPrimitiveClass) + + ///////////// + // FILTERS // + createDebug (); + try + { + CConfigFile::CVar &cvTmp = AppCfg.ConfigFile.getVar("NegFiltersDebug"); + for(uint k = 0; k < (uint)cvTmp.size(); ++k) + { + DebugLog->addNegativeFilter (cvTmp.asString(k).c_str()); + } + } + catch(const EUnknownVar &) {} + try + { + CConfigFile::CVar &cvTmp = AppCfg.ConfigFile.getVar("NegFiltersInfo"); + for(uint k = 0; k < (uint)cvTmp.size(); ++k) + { + InfoLog->addNegativeFilter (cvTmp.asString(k).c_str()); + } + } + catch(const EUnknownVar &) {} + try + { + CConfigFile::CVar &cvTmp = AppCfg.ConfigFile.getVar("NegFiltersWarning"); + for(uint k = 0; k < (uint)cvTmp.size(); ++k) + { + WarningLog->addNegativeFilter (cvTmp.asString(k).c_str()); + } + } + catch(const EUnknownVar &) {} +}// load // + + +//----------------------------------------------- +// serial : +// Serialize CFG. +//----------------------------------------------- +void CClientConfig::serial(class NLMISC::IStream &f) throw(NLMISC::EStream) +{ + // Start the opening of a new node named ClientCFG. + f.xmlPush("ClientCFG"); + + // Close the serial for hte Client CFG. + f.xmlPop(); +}// serial // + + +//----------------------------------------------- +// init : +//----------------------------------------------- +void CClientConfig::init(const std::string &configFileName) +{ + if(!CFile::fileExists(configFileName)) + nlwarning("CFG::init: '%s' Not Found !!!", configFileName.c_str ()); + + // if the config file will be modified, it calls automatically the function setValues() + AppCfg.ConfigFile.setCallback (setValues); + + // load the config files + AppCfg.ConfigFile.load (configFileName); +}// init // + + +//----------------------------------------------- +// release : +//----------------------------------------------- +void CClientConfig::release () +{ +} diff --git a/code/ryzom/tools/sheets_packer/sheets_packer_cfg.h b/code/ryzom/tools/sheets_packer/sheets_packer_cfg.h index 6c1f2e12a..feeade016 100644 --- a/code/ryzom/tools/sheets_packer/sheets_packer_cfg.h +++ b/code/ryzom/tools/sheets_packer/sheets_packer_cfg.h @@ -1,79 +1,79 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - -#ifndef TL_SHEETS_PACKER_CFG_H -#define TL_SHEETS_PACKER_CFG_H - - -////////////// -// Includes // -////////////// -// Misc. -#include "nel/misc/types_nl.h" -#include "nel/misc/config_file.h" -// std. -#include - - -//--------------------------------------------------- -// CClientConfig : -// Struct to manage a config file for the client. -//--------------------------------------------------- -struct CClientConfig -{ - // the config file must be always be available - NLMISC::CConfigFile ConfigFile; - - void init (const std::string &configFileName); - - /// Data Path. - std::vector DataPath; - - /// World sheet name - std::string WorldSheet; - /// Path where to find .primitive files - std::string PrimitivesPath; - /// Path where to create lmconts.packed - std::string OutputDataPath; - - - std::string LigoPrimitiveClass; - -public: - /// Constructor. - CClientConfig(); - - friend void setValues (); - - /// Serialize CFG. - virtual void serial(class NLMISC::IStream &f) throw(NLMISC::EStream); - - /// End process - void release (); -};// CClientConfig // - - -//////////// -// GLOBAL // -//////////// -extern CClientConfig AppCfg; -extern const std::string ConfigFileName; - -#endif // TL_SHEETS_PACKER_CFG_H - -/* End of sheets_packer_cfg.h */ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + +#ifndef TL_SHEETS_PACKER_CFG_H +#define TL_SHEETS_PACKER_CFG_H + + +////////////// +// Includes // +////////////// +// Misc. +#include "nel/misc/types_nl.h" +#include "nel/misc/config_file.h" +// std. +#include + + +//--------------------------------------------------- +// CClientConfig : +// Struct to manage a config file for the client. +//--------------------------------------------------- +struct CClientConfig +{ + // the config file must be always be available + NLMISC::CConfigFile ConfigFile; + + void init (const std::string &configFileName); + + /// Data Path. + std::vector DataPath; + + /// World sheet name + std::string WorldSheet; + /// Path where to find .primitive files + std::string PrimitivesPath; + /// Path where to create lmconts.packed + std::string OutputDataPath; + + + std::string LigoPrimitiveClass; + +public: + /// Constructor. + CClientConfig(); + + friend void setValues (); + + /// Serialize CFG. + virtual void serial(class NLMISC::IStream &f) throw(NLMISC::EStream); + + /// End process + void release (); +};// CClientConfig // + + +//////////// +// GLOBAL // +//////////// +extern CClientConfig AppCfg; +extern const std::string ConfigFileName; + +#endif // TL_SHEETS_PACKER_CFG_H + +/* End of sheets_packer_cfg.h */ diff --git a/code/ryzom/tools/sheets_packer/sheets_packer_init.cpp b/code/ryzom/tools/sheets_packer/sheets_packer_init.cpp index 02f115d03..0415a01bc 100644 --- a/code/ryzom/tools/sheets_packer/sheets_packer_init.cpp +++ b/code/ryzom/tools/sheets_packer/sheets_packer_init.cpp @@ -1,126 +1,126 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - - -////////////// -// INCLUDES // -////////////// -#include "stdpch.h" -// Misc. -#include "nel/misc/debug.h" -#include "nel/misc/displayer.h" -#include "nel/misc/path.h" -#include "nel/misc/log.h" -#include "nel/misc/sheet_id.h" - -#include "nel/ligo/ligo_config.h" -#include "nel/ligo/primitive.h" -// Application -#include "sheets_packer_init.h" -#include "sheets_packer_cfg.h" -#include "sheet_manager.h" - -#include "continent_manager_build.h" - -/////////// -// USING // -/////////// -using namespace NLMISC; -//using namespace NL3D; -using namespace std; - - -///////////// -// GLOBALS // -///////////// -CFileDisplayer *fd = NULL; - -NLLIGO::CLigoConfig LigoConfig; - -/////////////// -// FUNCTIONS // -/////////////// -//--------------------------------------------------- -// init : -// Initialize the application. -// Return false if the init fails. -//--------------------------------------------------- -bool init() -{ - // Add a displayer for Debug Infos. - createDebug(); - - fd = new CFileDisplayer(getLogDirectory() + "sheets_packer.log", true, "SHEETS_PACKER.LOG"); - - // register ligo 'standard' class - NLLIGO::Register(); - - DebugLog->addDisplayer (fd); - InfoLog->addDisplayer (fd); - WarningLog->addDisplayer (fd); - ErrorLog->addDisplayer (fd); - AssertLog->addDisplayer (fd); - - // Load the application configuration. - nlinfo("Loading config file..."); - AppCfg.init(ConfigFileName); - - // Define the root path that contains all data needed for the application. - nlinfo("Adding search paths..."); - for(uint i = 0; i < AppCfg.DataPath.size(); i++) - CPath::addSearchPath(AppCfg.DataPath[i], true, false); - - // Initialize Sheet IDs. - nlinfo("Init SheetId..."); - CSheetId::init(true); - - // load packed sheets - nlinfo("Loading sheets..."); - IProgressCallback callback; - SheetMngr.setOutputDataPath(AppCfg.OutputDataPath); - SheetMngr.load (callback, true, true); - - // Make the lmconts.packed file - if (!LigoConfig.readPrimitiveClass (AppCfg.LigoPrimitiveClass.c_str(), false)) - nlwarning ("Can't load primitive class file %s", AppCfg.LigoPrimitiveClass.c_str()); - NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig; - buildLMConts(AppCfg.WorldSheet, AppCfg.PrimitivesPath, AppCfg.OutputDataPath); - - // The init is a success. - return true; -}// init // - -//--------------------------------------------------- -// release : -// Release all the memory. -//--------------------------------------------------- -void release() -{ - DebugLog->removeDisplayer ("SHEETS_PACKER.LOG"); - InfoLog->removeDisplayer ("SHEETS_PACKER.LOG"); - WarningLog->removeDisplayer ("SHEETS_PACKER.LOG"); - ErrorLog->removeDisplayer ("SHEETS_PACKER.LOG"); - AssertLog->removeDisplayer ("SHEETS_PACKER.LOG"); - - delete fd; - fd = NULL; -}// release // - -void outputSomeDebugInfoForPackedSheetCrash() -{ -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + + +////////////// +// INCLUDES // +////////////// +#include "stdpch.h" +// Misc. +#include "nel/misc/debug.h" +#include "nel/misc/displayer.h" +#include "nel/misc/path.h" +#include "nel/misc/log.h" +#include "nel/misc/sheet_id.h" + +#include "nel/ligo/ligo_config.h" +#include "nel/ligo/primitive.h" +// Application +#include "sheets_packer_init.h" +#include "sheets_packer_cfg.h" +#include "sheet_manager.h" + +#include "continent_manager_build.h" + +/////////// +// USING // +/////////// +using namespace NLMISC; +//using namespace NL3D; +using namespace std; + + +///////////// +// GLOBALS // +///////////// +CFileDisplayer *fd = NULL; + +NLLIGO::CLigoConfig LigoConfig; + +/////////////// +// FUNCTIONS // +/////////////// +//--------------------------------------------------- +// init : +// Initialize the application. +// Return false if the init fails. +//--------------------------------------------------- +bool init() +{ + // Add a displayer for Debug Infos. + createDebug(); + + fd = new CFileDisplayer(getLogDirectory() + "sheets_packer.log", true, "SHEETS_PACKER.LOG"); + + // register ligo 'standard' class + NLLIGO::Register(); + + DebugLog->addDisplayer (fd); + InfoLog->addDisplayer (fd); + WarningLog->addDisplayer (fd); + ErrorLog->addDisplayer (fd); + AssertLog->addDisplayer (fd); + + // Load the application configuration. + nlinfo("Loading config file..."); + AppCfg.init(ConfigFileName); + + // Define the root path that contains all data needed for the application. + nlinfo("Adding search paths..."); + for(uint i = 0; i < AppCfg.DataPath.size(); i++) + CPath::addSearchPath(AppCfg.DataPath[i], true, false); + + // Initialize Sheet IDs. + nlinfo("Init SheetId..."); + CSheetId::init(true); + + // load packed sheets + nlinfo("Loading sheets..."); + IProgressCallback callback; + SheetMngr.setOutputDataPath(AppCfg.OutputDataPath); + SheetMngr.load (callback, true, true); + + // Make the lmconts.packed file + if (!LigoConfig.readPrimitiveClass (AppCfg.LigoPrimitiveClass.c_str(), false)) + nlwarning ("Can't load primitive class file %s", AppCfg.LigoPrimitiveClass.c_str()); + NLLIGO::CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig; + buildLMConts(AppCfg.WorldSheet, AppCfg.PrimitivesPath, AppCfg.OutputDataPath); + + // The init is a success. + return true; +}// init // + +//--------------------------------------------------- +// release : +// Release all the memory. +//--------------------------------------------------- +void release() +{ + DebugLog->removeDisplayer ("SHEETS_PACKER.LOG"); + InfoLog->removeDisplayer ("SHEETS_PACKER.LOG"); + WarningLog->removeDisplayer ("SHEETS_PACKER.LOG"); + ErrorLog->removeDisplayer ("SHEETS_PACKER.LOG"); + AssertLog->removeDisplayer ("SHEETS_PACKER.LOG"); + + delete fd; + fd = NULL; +}// release // + +void outputSomeDebugInfoForPackedSheetCrash() +{ +} diff --git a/code/ryzom/tools/sheets_packer/sheets_packer_init.h b/code/ryzom/tools/sheets_packer/sheets_packer_init.h index 26c476a7c..4015679ea 100644 --- a/code/ryzom/tools/sheets_packer/sheets_packer_init.h +++ b/code/ryzom/tools/sheets_packer/sheets_packer_init.h @@ -1,35 +1,35 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - - -#ifndef TL_SHEETS_PACKER_INIT_H -#define TL_SHEETS_PACKER_INIT_H - - - -#include "nel/misc/types_nl.h" - -// Initialize the application. -bool init(); - -// Release all. -void release(); - -#endif // TL_SHEETS_PACKER_INIT_H - -/* End of sheets_packer_init.h */ +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + + +#ifndef TL_SHEETS_PACKER_INIT_H +#define TL_SHEETS_PACKER_INIT_H + + + +#include "nel/misc/types_nl.h" + +// Initialize the application. +bool init(); + +// Release all. +void release(); + +#endif // TL_SHEETS_PACKER_INIT_H + +/* End of sheets_packer_init.h */ diff --git a/code/ryzom/tools/sheets_packer/stdpch.cpp b/code/ryzom/tools/sheets_packer/stdpch.cpp index 143fb51cd..99215b203 100644 --- a/code/ryzom/tools/sheets_packer/stdpch.cpp +++ b/code/ryzom/tools/sheets_packer/stdpch.cpp @@ -1,2 +1,2 @@ - -#include "stdpch.h" + +#include "stdpch.h" diff --git a/code/ryzom/tools/sheets_packer/stdpch.h b/code/ryzom/tools/sheets_packer/stdpch.h index afa7d2137..dae35b8a8 100644 --- a/code/ryzom/tools/sheets_packer/stdpch.h +++ b/code/ryzom/tools/sheets_packer/stdpch.h @@ -1,40 +1,40 @@ -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -//#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -//#include - -#ifdef NL_OS_WINDOWS -#define NOMINMAX -#include -#endif // NL_OS_WINDOWS +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//#include + +#ifdef NL_OS_WINDOWS +#define NOMINMAX +#include +#endif // NL_OS_WINDOWS diff --git a/code/ryzom/tools/skill_extractor/skill_extractor.cpp b/code/ryzom/tools/skill_extractor/skill_extractor.cpp index 532f72556..a37d22ba8 100644 --- a/code/ryzom/tools/skill_extractor/skill_extractor.cpp +++ b/code/ryzom/tools/skill_extractor/skill_extractor.cpp @@ -1,748 +1,748 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - - -#include "nel/misc/types_nl.h" -#include "nel/misc/file.h" -#include "nel/misc/config_file.h" - -#include "string.h" - -#include -#include - -using namespace std; -using namespace NLMISC; - -// define macro for outputone code line -#define outLine( s )\ -{\ - out = string(s);\ - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() );\ -}\ - - -// set of code -static set Codes; - -struct CSkill -{ - string SkillName; - string NormalizedSkillName; - CSkill *ParentSkillPtr; - string ParentSkill; - uint16 MaxValue; - string Code; - uint8 StageType; - string MainCategory; - string SecondaryCategory; - vector Children; - - CSkill() : ParentSkillPtr(NULL),MaxValue(0),StageType(0) - {} - - CSkill(const CSkill &skill) - { - *this = skill; - } - - CSkill &operator=(const CSkill &skill) - { - SkillName = skill.SkillName; - NormalizedSkillName = skill.NormalizedSkillName; - ParentSkillPtr = skill.ParentSkillPtr; - ParentSkill = skill.ParentSkill; - MaxValue = skill.MaxValue; - Code = skill.Code; - StageType = skill.StageType; - MainCategory = skill.MainCategory; - SecondaryCategory = skill.SecondaryCategory; - Children = skill.Children; - - return *this; - } - - void skillName(string name) - { - SkillName = name; -/* // fast correction to avoid strange cases when names end with a ' ' - sint i = SkillName.size(); - for ( ; i > 0; i-- ) - { - if ( SkillName[i-1] != ' ' ) - break; - } - SkillName.resize( i ); - - uint idxSpace; - char c[2]; - c[0] = SkillName.substr( 0, 1).c_str()[0] - 32; - c[1] = 0; - NormalizedSkillName = string( c ) + SkillName.substr( 1 ); - while( ( idxSpace = NormalizedSkillName.find(" ") ) != string::npos ) - { - string skillNameTmp = NormalizedSkillName.substr( 0, idxSpace ); - if( idxSpace < ( SkillName.size() - 1 ) ) - { - c[0] = (*NormalizedSkillName.substr( idxSpace + 1, 1 ).c_str()); - if( c[0] >= 'a' ) c[0] -= 32; - skillNameTmp = skillNameTmp + string( c ) + NormalizedSkillName.substr( idxSpace + 2 ); - } - NormalizedSkillName = skillNameTmp; - } -*/ - NormalizedSkillName = SkillName; - } - - void buildCode() - { - if (ParentSkillPtr != NULL) - Code = ParentSkillPtr->Code + Code; - - Codes.insert( Code ); - - for (uint i = 0 ; i < Children.size() ; ++i) - Children[i]->buildCode(); - } - - void writeInSheet(COFile &fo) - { - /* - - - - - - - - - - */ - string out; - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - - if (ParentSkillPtr != NULL) - { - out = string(" \n"); - } - else - { - out = string(" \n"); - } - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - - if( !Children.empty()) - { - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - for (uint i = 0 ; i < Children.size() ; ++i) - { - out = string(" NormalizedSkillName + string("\" Value=\"")+ Children[i]->SkillName + string("\"/>\n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - } - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - } - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - - for (uint i = 0 ; i < Children.size() ; ++i) - Children[i]->writeInSheet(fo); - } -}; - -struct CSkillTree -{ - void buildCode() - { - for (uint i = 0 ; i < RootSkills.size() ; ++i) - RootSkills[i]->buildCode(); - } - - vector RootSkills; -}; - -static CSkillTree SkillTree; -static map< string, CSkill> SkillNameToStruct; -char separators[] = ";,"; - - -//----------------------------------------------- -// main -// -//----------------------------------------------- -sint main( sint argc, char ** argv ) -{ - ///////////////////////////////////////////////////////////////////////////////////// - // Somes working variables - char buffer[4096]; - - // vector contained selector category - vector< string > selector; - - ///////////////////////////////////////////////////////////////////////////////////// - // Check number of arguments - if( argc < 4 ) - { - printf("Create a file .typ for george contained a subset of skills\n\n"); - printf("SKILL_EXTRACTOR <[ ...]\n"); - printf(" param 1 : create tree (yes) or no (no)\n"); - printf(" if output file have .typ extension, generate .typ george file format\n"); - printf(" if output file have .dfn extension, generate .dfn george file format\n"); - printf(" param 3 is sheet2 of SkillCategory.xls exported in csv format\n"); - printf(" Selector is category present in input file, selectors begins by '+' for or operation and by '.' for and operation\n"); - printf(" the first selector must be or operation (begin by '+' character)\n"); - return 1; - } - - // parse the config file - CConfigFile configFile; - try - { - configFile.load( "skill_extractor.cfg" ); - } - catch(const Exception &e ) - { - nlwarning(" skill_extractor.cfg %s",e.what()); - return 1; - } - - //get the csv file - CConfigFile::CVar * cfgVar = configFile.getVarPtr("CsvDir"); - if (!cfgVar) - { - printf("var 'CsvDir' not found in the skill_extractor.cfg"); - return 1; - } - const string& CSVDir = cfgVar->asString() + string("/"); - - //get the path for the generated source files - cfgVar = configFile.getVarPtr("SrcDir"); - if (!cfgVar) - { - printf("var 'SrcDir' not found in the skill_extractor.cfg"); - return 1; - } - const string& srcDir = cfgVar->asString() + string("/"); - - //get the path for the generated source files - cfgVar = configFile.getVarPtr("PdsDir"); - if (!cfgVar) - { - printf("var 'PdsDir' not found in the skill_extractor.cfg"); - return 1; - } - const string& pdsDir = cfgVar->asString() + string("/"); - - //get the path for the generated dfn - cfgVar = configFile.getVarPtr("DfnDir"); - if (!cfgVar) - { - printf("var 'DfnDir' not found in the skill_extractor.cfg"); - return 1; - } - const string& dfnDir = cfgVar->asString() + string("/"); - - //get the path for the generated skill tree - cfgVar = configFile.getVarPtr("SkillTreeDir"); - if (!cfgVar) - { - printf("var 'DfnDir' not found in the skill_extractor.cfg"); - return 1; - } - const string& treeDir = cfgVar->asString() + string("/"); - - - ///////////////////////////////////////////////////////////////////////////////////// - // Export .typ and .dfn file - // open skill file - CIFile f; - if( ! f.open( CSVDir + string( argv[3] ) ) ) - { - nlwarning( "File %s open failed", argv[3] ); - return 1; - } - - // read all input file - uint col; - string skillName; - char * ptr; - map< string, CSkill>::const_iterator itSkillStruct; - - while( ! f.eof() ) - { - f.getline( buffer, 4096 ); - col = 0; - ptr = strtok( buffer, separators ); - CSkill skill; - while( ptr && string( ptr ) != string(" ") ) - { - switch(col) - { - case 0: // skill name - { - skillName = strupr( string( ptr ) ); - vector< string > emptyVectorOfString; - skill.skillName(skillName); - } - break; - case 1: // code - skill.Code = toUpper(string( ptr )); - break; - case 2: // parent skill - skill.ParentSkill = toUpper(string( ptr )); - break; - case 3: // max skill value - NLMISC::fromString(std::string(ptr), skill.MaxValue); - break; - case 4: // stage type - NLMISC::fromString(std::string(ptr), skill.StageType); - break; - case 5: // main category - skill.MainCategory = string( ptr ); - break; - case 6: // secondary category - skill.SecondaryCategory = string( ptr ); - break; - default: // error ? - break; - }; - - ++col; - ptr = strtok( 0, separators ); - } - - if ( !skill.SkillName.empty()) - { - // insert skill in the Map - //pair< map< string, CSkill>::const_iterator, bool> skillInsert = SkillNameToStruct.insert( make_pair(skill.SkillName, skill) ); - //nlinfo("Insert skill %s, parent %s", skill.SkillName.c_str(), skill.ParentSkill.c_str() ); - SkillNameToStruct.insert( make_pair(skill.SkillName, skill) ); - } - } - f.close(); - - // create the tree - map< string, CSkill>::iterator itSkill; - map< string, CSkill>::iterator itSkillEnd = SkillNameToStruct.end(); - uint count = 0; - for ( itSkill = SkillNameToStruct.begin() ; itSkill != itSkillEnd ; ++itSkill ) - { - ++count; - if ( (*itSkill).second.ParentSkill == string("NONE") || (*itSkill).second.ParentSkill.empty() ) - { - SkillTree.RootSkills.push_back(&((*itSkill).second)); - } - else - { - map< string, CSkill>::iterator its = SkillNameToStruct.find((*itSkill).second.ParentSkill); - if (its == itSkillEnd) - { - nlwarning("ERROR : cannot find the parent skill %s for skill %s (skill %u)", (*itSkill).second.ParentSkill.c_str(), (*itSkill).second.SkillName.c_str(), count ); - nlstop; - } - (*itSkill).second.ParentSkillPtr = &((*its).second); - (*its).second.Children.push_back(&((*itSkill).second)); - } - } - - SkillTree.buildCode(); - - COFile fo; - // create the skill tree if first param == yes - if ( string( argv[1] ) == string("yes") ) - { - if( ! fo.open( treeDir + string("skills.skill_tree"), false ) ) - { - nlwarning(" Can't open file skills.skill_tree for writing"); - return 1; - } - - string out("\n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - out = string("
    \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - - for ( vector::const_iterator itTree = SkillTree.RootSkills.begin() ; itTree != SkillTree.RootSkills.end() ; ++itTree) - { - (*itTree)->writeInSheet(fo); - } - - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - out = string("\n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - fo.close(); - - // create the code .typ - if( ! fo.open( string("_skillsCode.typ"), false ) ) - { - nlwarning(" Can't open file _skillsCode.typ for writing"); - return 1; - } - - out = string("\n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - - set::const_iterator itCode; - for ( itCode = Codes.begin() ; itCode != Codes.end() ; ++itCode ) - { - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - } - - out = string("\n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - fo.close(); - } - - - // read category in command line - for( sint i = 4; i < argc; ++i ) - { - selector.push_back( string( argv[ i ] ) ); - } - - // generate a file containing skills and associated Code - if( ! fo.open( string( "skill_codes.txt" ) ) ) - { - nlwarning(" Can't open file %s for writing", "skill_codes.txt" ); - return 1; - } - for ( itSkill = SkillNameToStruct.begin() ; itSkill != itSkillEnd ; ++itSkill) - { - string out; - string space; - if ( (*itSkill).second.NormalizedSkillName.size() < 50) - space.resize( 50 - (*itSkill).second.NormalizedSkillName.size(), ' ' ); - outLine((*itSkill).second.NormalizedSkillName + space + string("\t") + (*itSkill).second.Code + string("\n") ); - } - - - // generate .typ or .dfn file - if( ! fo.open( dfnDir + string( argv[2] ), false ) ) - { - nlwarning(" Can't open file %s for writing", argv[2] ); - return 1; - } - - // output header of .typ or .dfn file - string out("\n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - if( string( argv[2] ).find(".typ") != string::npos ) - { - out = string("\n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - out = string(" \n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - } - else - { - out = string("\n"); - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - } - - // parse all skills to export selected ones - for ( itSkillStruct = SkillNameToStruct.begin() ; itSkillStruct != SkillNameToStruct.end() ; ++itSkillStruct ) - { - bool selected = false; - bool found = false; - - const CSkill &skill = (*itSkillStruct).second; - - for( vector< string >::iterator its = selector.begin(); its != selector.end(); ++its ) - { - found = false; - - if ( skill.MainCategory == (*its).substr(1) ) - { - found = true; - } - else if ( skill.SecondaryCategory == (*its).substr(1) ) - { - found = true; - } - - if( found ) - { - if( (*its).substr( 0, 1) == string("+") ) // or operation - { - selected = true; - } - else if( (*its).substr( 0, 1) == string(".") ) // and operation - { - selected &= true; - } - } - else if( (*its).substr( 0, 1) == string(".") ) - { - selected = false; - } - } - - if( selected ) - { - if( string( argv[2] ).find(".typ") != string::npos ) - { - out = string(" \n"); - } - else - { - out = string(" \n"); - } - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - } - } - - if( string( argv[2] ).find(".typ") != string::npos ) - { - out = string("\n"); - } - else - { - out = string("\n"); - } - fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); - fo.close(); - - ///////////////////////////////////////////////////////////////////////////////////// - // Generate skill.cpp and skill.h code file - - - // output begin skill.h file - //if( ! fo.open( string( "r:/code/ryzom/src_v2/game_share/skills.h" ) ) ) - if( ! fo.open( srcDir + string( "skills.h" ) ) ) - { - nlwarning(" Can't open file %s for writing", "skills.h" ); - return 1; - } - - // write header of header file - outLine("/** \\file skills.h\n"); - outLine(" * skills enumeration: generated by skill extractor program\n"); - outLine(" *\n"); - outLine(" */\n"); - outLine("\n"); - outLine("#ifndef RY_SKILLS_H\n"); - outLine("#define RY_SKILLS_H\n"); - outLine("\n"); - outLine("#include \"nel/misc/types_nl.h\"\n"); - outLine("\n"); - outLine("#include \n"); - outLine("\n"); - outLine( string("// NbSkills in enum : ") + toString( SkillNameToStruct.size() ) + string(" Report this in database.xml \n\n") ); - outLine("namespace SKILLS\n"); - outLine("{\n"); - outLine(" enum ESkills\n"); - outLine(" {\n"); - - itSkill = SkillNameToStruct.begin(); - if (itSkill != itSkillEnd) - { - outLine(string(" ") + (*itSkill).second.NormalizedSkillName + string(" = 0,\n") ); - for ( ++itSkill; itSkill != itSkillEnd ; ++itSkill) - { - outLine(string(" ") + (*itSkill).second.NormalizedSkillName + string(",\n") ); - } - } - // output end skill enum and skill type enum and skill api - outLine("\n"); - outLine(" NUM_SKILLS,\n"); - outLine(" unknown,\n"); - outLine(" };\n"); - outLine("\n"); - - // output all skills -/* for( it = skillsAndSelector.begin(); it != skillsAndSelector.end(); ++it ) - { - uint idxSpace; - out = (*it).first; - while( ( idxSpace = out.find(" ") ) != string::npos ) - { - string tmp = out.substr( 0, idxSpace ); - if( idxSpace < ( out.size() - 1 ) ) - { - tmp = tmp + string("_") + out.substr( idxSpace + 1 ); - } - out = tmp; - } - outLine( string(" ") + out + string(",\n") ); - } - - // output end skill enum and skill type enum and skill api - outLine("\n"); - outLine(" NUM_SKILLS,\n"); - outLine(" unknown\n"); - outLine(" };\n"); - outLine("\n"); - - outLine(" enum ESkillType\n"); - outLine(" {\n"); - outLine(" skill,\n"); - outLine(" specialized_skill,\n"); - outLine(" training_characteristic,\n"); - outLine(" training_resist,\n"); - outLine(" training_score,\n"); - outLine("\n"); - outLine(" unknown_skill_type\n"); - outLine(" };\n"); - outLine("\n"); -*/ - outLine(" /**\n"); - outLine(" * get the right skill enum from the input string\n"); - outLine(" * \\param str the input string\n"); - outLine(" * \\return the ESkills associated to this string (Unknown if the string cannot be interpreted)\n"); - outLine(" */\n"); - outLine(" ESkills toSkill ( const std::string &str );\n"); - outLine("\n"); - outLine(" /**\n"); - outLine(" * get the right skill string from the gived enum\n"); - outLine(" * \\param skill the skill to convert\n"); - outLine(" * \\return the string associated to this enum number (Unknown if the enum number not exist)\n"); - outLine(" */\n"); - outLine(" const std::string& toString( uint16 skill );\n"); - outLine("\n"); - outLine(" /**\n"); - outLine(" * get the skill category name\n"); - outLine(" * \\param s is the enum number\n"); - outLine(" * \\return the string name of skill type (Unknown if the enum number not exist)\n"); - outLine(" */\n"); - outLine(" const std::string& getSkillCategoryName( uint16 s );\n"); - outLine("\n"); - outLine("}; // SKILLS\n"); - outLine("\n"); - outLine("#endif // RY_SKILLS_H\n"); - outLine("/* End of skills.h */\n"); - - ///////////////////////////////////////////////////////////////////////////////////// - // begin output skill.cpp file -// if( ! fo.open( string( "r:/code/ryzom/src_v2/game_share/skills.cpp" ) ) ) - if( ! fo.open( srcDir + string( "skills.cpp" ) ) ) - { - nlwarning(" Can't open file skills.cpp for writing"); - return 1; - } - - outLine("/** \\file skills.cpp\n"); - outLine(" * \n"); - outLine(" */\n\n"); - - outLine("#include \"stdpch.h\"\n"); - outLine("\n"); - outLine("#include \"nel/misc/debug.h\"\n"); - outLine("#include \"skills.h\"\n"); - outLine("#include \"nel/misc/string_conversion.h\"\n"); - outLine("\n"); - outLine("using namespace std;\n"); - outLine("using namespace NLMISC;\n"); - outLine("\n"); - outLine("namespace SKILLS\n"); - outLine("{\n"); - outLine("\n"); - outLine("static string UnknownString(\"Unknown\");\n"); - outLine("\n"); - outLine("\tNL_BEGIN_STRING_CONVERSION_TABLE (ESkills)\n"); - - // parser all skills and init the conversion map - for ( itSkill = SkillNameToStruct.begin() ; itSkill != itSkillEnd ; ++itSkill) - { - outLine (string ("\t NL_STRING_CONVERSION_TABLE_ENTRY(") + (*itSkill).second.NormalizedSkillName + string(")\n") ); - } - //outLine (string (" { \"unknown\", unknown },\n" ) ); - outLine (string("\t NL_STRING_CONVERSION_TABLE_ENTRY(unknown)\n") ); - - outLine("\tNL_END_STRING_CONVERSION_TABLE(ESkills, SkillsConversion, unknown)\n"); - outLine("\n"); - outLine("\n"); - outLine("\tESkills toSkill( const std::string &str )\n"); - outLine("\t{\n"); - outLine("\t return SkillsConversion.fromString(str);\n"); - outLine("\t}\n"); - outLine("\n"); - outLine("\tconst std::string& toString( uint16 skill )\n"); - outLine("\t{\n"); - outLine("\t return SkillsConversion.toString((ESkills)skill);\n"); - outLine("\t}\n"); - outLine("\n"); - outLine("\n"); - outLine("\tconst std::string& getSkillCategoryName( uint16 s )\n"); - outLine("\t{\n"); - /*outLine(" if( s < sizeof(SkillCategoryStrings)/sizeof(SkillCategoryStrings[0]) )\n"); - outLine(" {\n"); - outLine(" return SkillCategoryStrings[ s ];\n"); - outLine(" }\n"); - outLine(" else return UnknownString;\n"); - */ - outLine("\t return UnknownString;\n"); - outLine("\t}\n"); - outLine("\n"); - outLine("}; // SKILLS\n"); - fo.close(); - - ///////////////////////////////////////////////////////////////////////////////////// - // Generate skills.pds script file - - if( ! fo.open( pdsDir + string( "skills.pds" ) ) ) - { - nlwarning(" Can't open file %s for writing", "skills.pds" ); - return 1; - } - - outLine( string("// NbSkills in enum : ") + toString( SkillNameToStruct.size() ) + string(" Report this in database.xml \n\n") ); - outLine("file \"skills.h\"\n"); - outLine("{\n"); - outLine("\tenum TSkill\n"); - outLine("\t{\n"); - outLine("\t\tBeginSkill\n"); - outLine("\t\t{\n"); - - itSkill = SkillNameToStruct.begin(); - if (itSkill != itSkillEnd) - { - outLine(string("\t\t\t") + (*itSkill).second.NormalizedSkillName); - for ( ++itSkill; itSkill != itSkillEnd ; ++itSkill) - { - outLine(",\n"); - outLine(string("\t\t\t") + (*itSkill).second.NormalizedSkillName); - } - } - outLine("\n\t\t}\n"); - outLine("\t} EndSkill\n"); - outLine("}\n"); - fo.close(); - - nlinfo("job finish"); - return EXIT_SUCCESS; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + + +#include "nel/misc/types_nl.h" +#include "nel/misc/file.h" +#include "nel/misc/config_file.h" + +#include "string.h" + +#include +#include + +using namespace std; +using namespace NLMISC; + +// define macro for outputone code line +#define outLine( s )\ +{\ + out = string(s);\ + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() );\ +}\ + + +// set of code +static set Codes; + +struct CSkill +{ + string SkillName; + string NormalizedSkillName; + CSkill *ParentSkillPtr; + string ParentSkill; + uint16 MaxValue; + string Code; + uint8 StageType; + string MainCategory; + string SecondaryCategory; + vector Children; + + CSkill() : ParentSkillPtr(NULL),MaxValue(0),StageType(0) + {} + + CSkill(const CSkill &skill) + { + *this = skill; + } + + CSkill &operator=(const CSkill &skill) + { + SkillName = skill.SkillName; + NormalizedSkillName = skill.NormalizedSkillName; + ParentSkillPtr = skill.ParentSkillPtr; + ParentSkill = skill.ParentSkill; + MaxValue = skill.MaxValue; + Code = skill.Code; + StageType = skill.StageType; + MainCategory = skill.MainCategory; + SecondaryCategory = skill.SecondaryCategory; + Children = skill.Children; + + return *this; + } + + void skillName(string name) + { + SkillName = name; +/* // fast correction to avoid strange cases when names end with a ' ' + sint i = SkillName.size(); + for ( ; i > 0; i-- ) + { + if ( SkillName[i-1] != ' ' ) + break; + } + SkillName.resize( i ); + + uint idxSpace; + char c[2]; + c[0] = SkillName.substr( 0, 1).c_str()[0] - 32; + c[1] = 0; + NormalizedSkillName = string( c ) + SkillName.substr( 1 ); + while( ( idxSpace = NormalizedSkillName.find(" ") ) != string::npos ) + { + string skillNameTmp = NormalizedSkillName.substr( 0, idxSpace ); + if( idxSpace < ( SkillName.size() - 1 ) ) + { + c[0] = (*NormalizedSkillName.substr( idxSpace + 1, 1 ).c_str()); + if( c[0] >= 'a' ) c[0] -= 32; + skillNameTmp = skillNameTmp + string( c ) + NormalizedSkillName.substr( idxSpace + 2 ); + } + NormalizedSkillName = skillNameTmp; + } +*/ + NormalizedSkillName = SkillName; + } + + void buildCode() + { + if (ParentSkillPtr != NULL) + Code = ParentSkillPtr->Code + Code; + + Codes.insert( Code ); + + for (uint i = 0 ; i < Children.size() ; ++i) + Children[i]->buildCode(); + } + + void writeInSheet(COFile &fo) + { + /* + + + + + + + + + + */ + string out; + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + + if (ParentSkillPtr != NULL) + { + out = string(" \n"); + } + else + { + out = string(" \n"); + } + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + + if( !Children.empty()) + { + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + for (uint i = 0 ; i < Children.size() ; ++i) + { + out = string(" NormalizedSkillName + string("\" Value=\"")+ Children[i]->SkillName + string("\"/>\n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + } + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + } + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + + for (uint i = 0 ; i < Children.size() ; ++i) + Children[i]->writeInSheet(fo); + } +}; + +struct CSkillTree +{ + void buildCode() + { + for (uint i = 0 ; i < RootSkills.size() ; ++i) + RootSkills[i]->buildCode(); + } + + vector RootSkills; +}; + +static CSkillTree SkillTree; +static map< string, CSkill> SkillNameToStruct; +char separators[] = ";,"; + + +//----------------------------------------------- +// main +// +//----------------------------------------------- +sint main( sint argc, char ** argv ) +{ + ///////////////////////////////////////////////////////////////////////////////////// + // Somes working variables + char buffer[4096]; + + // vector contained selector category + vector< string > selector; + + ///////////////////////////////////////////////////////////////////////////////////// + // Check number of arguments + if( argc < 4 ) + { + printf("Create a file .typ for george contained a subset of skills\n\n"); + printf("SKILL_EXTRACTOR <[ ...]\n"); + printf(" param 1 : create tree (yes) or no (no)\n"); + printf(" if output file have .typ extension, generate .typ george file format\n"); + printf(" if output file have .dfn extension, generate .dfn george file format\n"); + printf(" param 3 is sheet2 of SkillCategory.xls exported in csv format\n"); + printf(" Selector is category present in input file, selectors begins by '+' for or operation and by '.' for and operation\n"); + printf(" the first selector must be or operation (begin by '+' character)\n"); + return 1; + } + + // parse the config file + CConfigFile configFile; + try + { + configFile.load( "skill_extractor.cfg" ); + } + catch(const Exception &e ) + { + nlwarning(" skill_extractor.cfg %s",e.what()); + return 1; + } + + //get the csv file + CConfigFile::CVar * cfgVar = configFile.getVarPtr("CsvDir"); + if (!cfgVar) + { + printf("var 'CsvDir' not found in the skill_extractor.cfg"); + return 1; + } + const string& CSVDir = cfgVar->asString() + string("/"); + + //get the path for the generated source files + cfgVar = configFile.getVarPtr("SrcDir"); + if (!cfgVar) + { + printf("var 'SrcDir' not found in the skill_extractor.cfg"); + return 1; + } + const string& srcDir = cfgVar->asString() + string("/"); + + //get the path for the generated source files + cfgVar = configFile.getVarPtr("PdsDir"); + if (!cfgVar) + { + printf("var 'PdsDir' not found in the skill_extractor.cfg"); + return 1; + } + const string& pdsDir = cfgVar->asString() + string("/"); + + //get the path for the generated dfn + cfgVar = configFile.getVarPtr("DfnDir"); + if (!cfgVar) + { + printf("var 'DfnDir' not found in the skill_extractor.cfg"); + return 1; + } + const string& dfnDir = cfgVar->asString() + string("/"); + + //get the path for the generated skill tree + cfgVar = configFile.getVarPtr("SkillTreeDir"); + if (!cfgVar) + { + printf("var 'DfnDir' not found in the skill_extractor.cfg"); + return 1; + } + const string& treeDir = cfgVar->asString() + string("/"); + + + ///////////////////////////////////////////////////////////////////////////////////// + // Export .typ and .dfn file + // open skill file + CIFile f; + if( ! f.open( CSVDir + string( argv[3] ) ) ) + { + nlwarning( "File %s open failed", argv[3] ); + return 1; + } + + // read all input file + uint col; + string skillName; + char * ptr; + map< string, CSkill>::const_iterator itSkillStruct; + + while( ! f.eof() ) + { + f.getline( buffer, 4096 ); + col = 0; + ptr = strtok( buffer, separators ); + CSkill skill; + while( ptr && string( ptr ) != string(" ") ) + { + switch(col) + { + case 0: // skill name + { + skillName = strupr( string( ptr ) ); + vector< string > emptyVectorOfString; + skill.skillName(skillName); + } + break; + case 1: // code + skill.Code = toUpper(string( ptr )); + break; + case 2: // parent skill + skill.ParentSkill = toUpper(string( ptr )); + break; + case 3: // max skill value + NLMISC::fromString(std::string(ptr), skill.MaxValue); + break; + case 4: // stage type + NLMISC::fromString(std::string(ptr), skill.StageType); + break; + case 5: // main category + skill.MainCategory = string( ptr ); + break; + case 6: // secondary category + skill.SecondaryCategory = string( ptr ); + break; + default: // error ? + break; + }; + + ++col; + ptr = strtok( 0, separators ); + } + + if ( !skill.SkillName.empty()) + { + // insert skill in the Map + //pair< map< string, CSkill>::const_iterator, bool> skillInsert = SkillNameToStruct.insert( make_pair(skill.SkillName, skill) ); + //nlinfo("Insert skill %s, parent %s", skill.SkillName.c_str(), skill.ParentSkill.c_str() ); + SkillNameToStruct.insert( make_pair(skill.SkillName, skill) ); + } + } + f.close(); + + // create the tree + map< string, CSkill>::iterator itSkill; + map< string, CSkill>::iterator itSkillEnd = SkillNameToStruct.end(); + uint count = 0; + for ( itSkill = SkillNameToStruct.begin() ; itSkill != itSkillEnd ; ++itSkill ) + { + ++count; + if ( (*itSkill).second.ParentSkill == string("NONE") || (*itSkill).second.ParentSkill.empty() ) + { + SkillTree.RootSkills.push_back(&((*itSkill).second)); + } + else + { + map< string, CSkill>::iterator its = SkillNameToStruct.find((*itSkill).second.ParentSkill); + if (its == itSkillEnd) + { + nlwarning("ERROR : cannot find the parent skill %s for skill %s (skill %u)", (*itSkill).second.ParentSkill.c_str(), (*itSkill).second.SkillName.c_str(), count ); + nlstop; + } + (*itSkill).second.ParentSkillPtr = &((*its).second); + (*its).second.Children.push_back(&((*itSkill).second)); + } + } + + SkillTree.buildCode(); + + COFile fo; + // create the skill tree if first param == yes + if ( string( argv[1] ) == string("yes") ) + { + if( ! fo.open( treeDir + string("skills.skill_tree"), false ) ) + { + nlwarning(" Can't open file skills.skill_tree for writing"); + return 1; + } + + string out("\n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + out = string("
    \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + + for ( vector::const_iterator itTree = SkillTree.RootSkills.begin() ; itTree != SkillTree.RootSkills.end() ; ++itTree) + { + (*itTree)->writeInSheet(fo); + } + + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + out = string("\n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + fo.close(); + + // create the code .typ + if( ! fo.open( string("_skillsCode.typ"), false ) ) + { + nlwarning(" Can't open file _skillsCode.typ for writing"); + return 1; + } + + out = string("\n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + + set::const_iterator itCode; + for ( itCode = Codes.begin() ; itCode != Codes.end() ; ++itCode ) + { + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + } + + out = string("\n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + fo.close(); + } + + + // read category in command line + for( sint i = 4; i < argc; ++i ) + { + selector.push_back( string( argv[ i ] ) ); + } + + // generate a file containing skills and associated Code + if( ! fo.open( string( "skill_codes.txt" ) ) ) + { + nlwarning(" Can't open file %s for writing", "skill_codes.txt" ); + return 1; + } + for ( itSkill = SkillNameToStruct.begin() ; itSkill != itSkillEnd ; ++itSkill) + { + string out; + string space; + if ( (*itSkill).second.NormalizedSkillName.size() < 50) + space.resize( 50 - (*itSkill).second.NormalizedSkillName.size(), ' ' ); + outLine((*itSkill).second.NormalizedSkillName + space + string("\t") + (*itSkill).second.Code + string("\n") ); + } + + + // generate .typ or .dfn file + if( ! fo.open( dfnDir + string( argv[2] ), false ) ) + { + nlwarning(" Can't open file %s for writing", argv[2] ); + return 1; + } + + // output header of .typ or .dfn file + string out("\n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + if( string( argv[2] ).find(".typ") != string::npos ) + { + out = string("\n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + out = string(" \n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + } + else + { + out = string("\n"); + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + } + + // parse all skills to export selected ones + for ( itSkillStruct = SkillNameToStruct.begin() ; itSkillStruct != SkillNameToStruct.end() ; ++itSkillStruct ) + { + bool selected = false; + bool found = false; + + const CSkill &skill = (*itSkillStruct).second; + + for( vector< string >::iterator its = selector.begin(); its != selector.end(); ++its ) + { + found = false; + + if ( skill.MainCategory == (*its).substr(1) ) + { + found = true; + } + else if ( skill.SecondaryCategory == (*its).substr(1) ) + { + found = true; + } + + if( found ) + { + if( (*its).substr( 0, 1) == string("+") ) // or operation + { + selected = true; + } + else if( (*its).substr( 0, 1) == string(".") ) // and operation + { + selected &= true; + } + } + else if( (*its).substr( 0, 1) == string(".") ) + { + selected = false; + } + } + + if( selected ) + { + if( string( argv[2] ).find(".typ") != string::npos ) + { + out = string(" \n"); + } + else + { + out = string(" \n"); + } + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + } + } + + if( string( argv[2] ).find(".typ") != string::npos ) + { + out = string("\n"); + } + else + { + out = string("\n"); + } + fo.serialBuffer( (uint8 *) const_cast< char * >(out.c_str()), (uint)out.size() ); + fo.close(); + + ///////////////////////////////////////////////////////////////////////////////////// + // Generate skill.cpp and skill.h code file + + + // output begin skill.h file + //if( ! fo.open( string( "r:/code/ryzom/src_v2/game_share/skills.h" ) ) ) + if( ! fo.open( srcDir + string( "skills.h" ) ) ) + { + nlwarning(" Can't open file %s for writing", "skills.h" ); + return 1; + } + + // write header of header file + outLine("/** \\file skills.h\n"); + outLine(" * skills enumeration: generated by skill extractor program\n"); + outLine(" *\n"); + outLine(" */\n"); + outLine("\n"); + outLine("#ifndef RY_SKILLS_H\n"); + outLine("#define RY_SKILLS_H\n"); + outLine("\n"); + outLine("#include \"nel/misc/types_nl.h\"\n"); + outLine("\n"); + outLine("#include \n"); + outLine("\n"); + outLine( string("// NbSkills in enum : ") + toString( SkillNameToStruct.size() ) + string(" Report this in database.xml \n\n") ); + outLine("namespace SKILLS\n"); + outLine("{\n"); + outLine(" enum ESkills\n"); + outLine(" {\n"); + + itSkill = SkillNameToStruct.begin(); + if (itSkill != itSkillEnd) + { + outLine(string(" ") + (*itSkill).second.NormalizedSkillName + string(" = 0,\n") ); + for ( ++itSkill; itSkill != itSkillEnd ; ++itSkill) + { + outLine(string(" ") + (*itSkill).second.NormalizedSkillName + string(",\n") ); + } + } + // output end skill enum and skill type enum and skill api + outLine("\n"); + outLine(" NUM_SKILLS,\n"); + outLine(" unknown,\n"); + outLine(" };\n"); + outLine("\n"); + + // output all skills +/* for( it = skillsAndSelector.begin(); it != skillsAndSelector.end(); ++it ) + { + uint idxSpace; + out = (*it).first; + while( ( idxSpace = out.find(" ") ) != string::npos ) + { + string tmp = out.substr( 0, idxSpace ); + if( idxSpace < ( out.size() - 1 ) ) + { + tmp = tmp + string("_") + out.substr( idxSpace + 1 ); + } + out = tmp; + } + outLine( string(" ") + out + string(",\n") ); + } + + // output end skill enum and skill type enum and skill api + outLine("\n"); + outLine(" NUM_SKILLS,\n"); + outLine(" unknown\n"); + outLine(" };\n"); + outLine("\n"); + + outLine(" enum ESkillType\n"); + outLine(" {\n"); + outLine(" skill,\n"); + outLine(" specialized_skill,\n"); + outLine(" training_characteristic,\n"); + outLine(" training_resist,\n"); + outLine(" training_score,\n"); + outLine("\n"); + outLine(" unknown_skill_type\n"); + outLine(" };\n"); + outLine("\n"); +*/ + outLine(" /**\n"); + outLine(" * get the right skill enum from the input string\n"); + outLine(" * \\param str the input string\n"); + outLine(" * \\return the ESkills associated to this string (Unknown if the string cannot be interpreted)\n"); + outLine(" */\n"); + outLine(" ESkills toSkill ( const std::string &str );\n"); + outLine("\n"); + outLine(" /**\n"); + outLine(" * get the right skill string from the gived enum\n"); + outLine(" * \\param skill the skill to convert\n"); + outLine(" * \\return the string associated to this enum number (Unknown if the enum number not exist)\n"); + outLine(" */\n"); + outLine(" const std::string& toString( uint16 skill );\n"); + outLine("\n"); + outLine(" /**\n"); + outLine(" * get the skill category name\n"); + outLine(" * \\param s is the enum number\n"); + outLine(" * \\return the string name of skill type (Unknown if the enum number not exist)\n"); + outLine(" */\n"); + outLine(" const std::string& getSkillCategoryName( uint16 s );\n"); + outLine("\n"); + outLine("}; // SKILLS\n"); + outLine("\n"); + outLine("#endif // RY_SKILLS_H\n"); + outLine("/* End of skills.h */\n"); + + ///////////////////////////////////////////////////////////////////////////////////// + // begin output skill.cpp file +// if( ! fo.open( string( "r:/code/ryzom/src_v2/game_share/skills.cpp" ) ) ) + if( ! fo.open( srcDir + string( "skills.cpp" ) ) ) + { + nlwarning(" Can't open file skills.cpp for writing"); + return 1; + } + + outLine("/** \\file skills.cpp\n"); + outLine(" * \n"); + outLine(" */\n\n"); + + outLine("#include \"stdpch.h\"\n"); + outLine("\n"); + outLine("#include \"nel/misc/debug.h\"\n"); + outLine("#include \"skills.h\"\n"); + outLine("#include \"nel/misc/string_conversion.h\"\n"); + outLine("\n"); + outLine("using namespace std;\n"); + outLine("using namespace NLMISC;\n"); + outLine("\n"); + outLine("namespace SKILLS\n"); + outLine("{\n"); + outLine("\n"); + outLine("static string UnknownString(\"Unknown\");\n"); + outLine("\n"); + outLine("\tNL_BEGIN_STRING_CONVERSION_TABLE (ESkills)\n"); + + // parser all skills and init the conversion map + for ( itSkill = SkillNameToStruct.begin() ; itSkill != itSkillEnd ; ++itSkill) + { + outLine (string ("\t NL_STRING_CONVERSION_TABLE_ENTRY(") + (*itSkill).second.NormalizedSkillName + string(")\n") ); + } + //outLine (string (" { \"unknown\", unknown },\n" ) ); + outLine (string("\t NL_STRING_CONVERSION_TABLE_ENTRY(unknown)\n") ); + + outLine("\tNL_END_STRING_CONVERSION_TABLE(ESkills, SkillsConversion, unknown)\n"); + outLine("\n"); + outLine("\n"); + outLine("\tESkills toSkill( const std::string &str )\n"); + outLine("\t{\n"); + outLine("\t return SkillsConversion.fromString(str);\n"); + outLine("\t}\n"); + outLine("\n"); + outLine("\tconst std::string& toString( uint16 skill )\n"); + outLine("\t{\n"); + outLine("\t return SkillsConversion.toString((ESkills)skill);\n"); + outLine("\t}\n"); + outLine("\n"); + outLine("\n"); + outLine("\tconst std::string& getSkillCategoryName( uint16 s )\n"); + outLine("\t{\n"); + /*outLine(" if( s < sizeof(SkillCategoryStrings)/sizeof(SkillCategoryStrings[0]) )\n"); + outLine(" {\n"); + outLine(" return SkillCategoryStrings[ s ];\n"); + outLine(" }\n"); + outLine(" else return UnknownString;\n"); + */ + outLine("\t return UnknownString;\n"); + outLine("\t}\n"); + outLine("\n"); + outLine("}; // SKILLS\n"); + fo.close(); + + ///////////////////////////////////////////////////////////////////////////////////// + // Generate skills.pds script file + + if( ! fo.open( pdsDir + string( "skills.pds" ) ) ) + { + nlwarning(" Can't open file %s for writing", "skills.pds" ); + return 1; + } + + outLine( string("// NbSkills in enum : ") + toString( SkillNameToStruct.size() ) + string(" Report this in database.xml \n\n") ); + outLine("file \"skills.h\"\n"); + outLine("{\n"); + outLine("\tenum TSkill\n"); + outLine("\t{\n"); + outLine("\t\tBeginSkill\n"); + outLine("\t\t{\n"); + + itSkill = SkillNameToStruct.begin(); + if (itSkill != itSkillEnd) + { + outLine(string("\t\t\t") + (*itSkill).second.NormalizedSkillName); + for ( ++itSkill; itSkill != itSkillEnd ; ++itSkill) + { + outLine(",\n"); + outLine(string("\t\t\t") + (*itSkill).second.NormalizedSkillName); + } + } + outLine("\n\t\t}\n"); + outLine("\t} EndSkill\n"); + outLine("}\n"); + fo.close(); + + nlinfo("job finish"); + return EXIT_SUCCESS; +} diff --git a/code/ryzom/tools/stats_scan/char_commands.cpp b/code/ryzom/tools/stats_scan/char_commands.cpp index 261e1f2e3..6e6247c42 100644 --- a/code/ryzom/tools/stats_scan/char_commands.cpp +++ b/code/ryzom/tools/stats_scan/char_commands.cpp @@ -1,302 +1,302 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -/** - * todo: - * - charScanScript commands - * * path for script files in cfg - * - charScanScriptNew - * - charScanScriptLoad - * - charScanScriptSave - * - charScanScriptListFiles - * - charScanScriptListLines - * - charScanScriptDeleteLine - * - charScanScriptAddInputFiles - * - charScanScriptAddInfoExtractor [] - * - charScanScriptAddFilter [] - * - charScanScriptAddPreInclude - * - charScanScriptAddPostInclude - * - charScanScriptSetOutputDirectory - * - charScanScriptSetDescription - * - charScanScriptRun [-s ] [-o ] - * - addJobCharScanScript [-s ] [-o ] - * - charScanScriptListOutputFiles [] - * - charScanScriptListOutputFileContents [] - * - charScanScriptTestFileList - * - charScanScriptTestOutput - * - charScanScriptHelp - * - path for generated files (from cfg + override) => managed incrementally with directory numbering - * - add incremental update systems - * - add tables with a column per day () - * - add tables with a column per week (limited number of weeks) - * - add tables with a column per month (limited number of months) - */ - -/* -bool CCharFilterFactory::beginScanJob(const std::vector& files, const std::vector& filters) -{ - bool noErrors= true; - - // create a new job - NLMISC::CSmartPtr job=new CCharacterScanJob; - - // look after the filters - for (uint32 i=0;igetName()) - break; - - // if none found then warn and skip passed - if(j>=_Filters.size()) - { - nlwarning("Unknown info extractor: %s",filters[i].c_str()); - noErrors=false; - continue; - } - - // add the info extractor to the new job - job->addFilter(_Filters[j]); - } - - // look after the files - job->addFiles(files); - - // add the job to the job manager - if (noErrors==true) - CJobManager::getInstance()->addJob(&*job); - - return noErrors; -} - -*/ -//----------------------------------------------------------------------------- -// includes -//----------------------------------------------------------------------------- - -#include "nel/misc/path.h" -#include "nel/misc/command.h" -#include "nel/misc/variable.h" -#include "nel/misc/algo.h" -#include "game_share/persistent_data.h" - -#include "character.h" -#include "job_manager.h" -#include "char_info_extractor_factory.h" - - -//----------------------------------------------------------------------------- -// Namespaces -//----------------------------------------------------------------------------- - -using namespace std; -using namespace NLMISC; - -//----------------------------------------------------------------------------- -// Variables -//----------------------------------------------------------------------------- - -CVariable SourceDirectory("variables", "SourceDirectory", "Directory we scan for files", string("."), 0, true); - - -//----------------------------------------------------------------------------- -// Commands - misc character related -//----------------------------------------------------------------------------- - -NLMISC_COMMAND(listCharNames,"display the names of the characters int he listed save files","") -{ - if (args.size()!=1 && args.size()!=0) - return false; - - std::string wildcard="pdr_account*"; - if (args.size()==1) - wildcard=args[0]; - - std::vector files; - NLMISC::CPath::getPathContent(SourceDirectory.get().c_str(),false,false,true,files); - for (uint32 i=(uint32)files.size();i--;) - { - if (!NLMISC::testWildCard(NLMISC::CFile::getFilename(files[i]),wildcard)) - { - files[i]=files.back(); - files.pop_back(); - } - } - std::sort(files.begin(),files.end()); - for (uint32 i=0;idisplayInfoExtractorList(&log); - - return true; -} - -//----------------------------------------------------------------------------- -// Commands - jobsManager -//----------------------------------------------------------------------------- - -NLMISC_COMMAND(jobsPause,"pause execution of jobs","") -{ - if (args.size()!=0) - return false; - - CJobManager::getInstance()->pause(); - - return true; -} - -NLMISC_COMMAND(jobsResume,"resume execution of jobs","") -{ - if (args.size()!=0) - return false; - - CJobManager::getInstance()->resume(); - - return true; -} - -NLMISC_COMMAND(jobsPromote,"pause execution of jobs","") -{ - if (args.size()!=1) - return false; - - uint32 idx; - NLMISC::fromString(args[0], idx); - - if ( (idx==0 && args[0]!="0") ) - { - nlwarning("Argument is not a valid job id - should be a number"); - return false; - } - - CJobManager::getInstance()->promoteJob(idx); - CJobManager::getInstance()->listJobs(&log); - - return true; -} - -NLMISC_COMMAND(JobUpdatesPerUpdate,"set or display the number of job updates per service update","[]") -{ - if (args.size()>1) - return false; - - if (args.size()==1) - { - uint32 count; - NLMISC::fromString(args[0], count); - - if ( (count==0 && args[0]!="0") ) - { - nlwarning("Argument is not a valid number"); - return false; - } - CJobManager::getInstance()->setJobUpdatesPerUpdate(count); - } - - nlinfo("JobUpdatesPerUpdate %d",CJobManager::getInstance()->getJobUpdatesPerUpdate()); - - return true; -} - -NLMISC_COMMAND(jobsStatus,"display the status of the job manager","") -{ - if (args.size()!=0) - return false; - - log.displayNL("%s",CJobManager::getInstance()->getStatus().c_str()); - - return true; -} - -NLMISC_COMMAND(jobsList,"display the list of unfinished jobs","") -{ - if (args.size()!=0) - return false; - - CJobManager::getInstance()->listJobs(&log); - - return true; -} - -NLMISC_COMMAND(jobsListAll,"display the list of all jobs (unfinished jobs are marked with a '*')","") -{ - if (args.size()!=0) - return false; - - CJobManager::getInstance()->listJobHistory(&log); - - return true; -} - -NLMISC_COMMAND(jobsDisplayDetails,"display detailed info for the current job (or a given job)","[]") -{ - switch (args.size()) - { - case 0: - CJobManager::getInstance()->displayCurrentJob(&log); - break; - - case 1: - { - uint32 idx; - NLMISC::fromString(args[0], idx); - - if ( (idx==0 && args[0]!="0") ) - { - nlwarning("Argument is not a valid job id - should be a number"); - return false; - } - CJobManager::getInstance()->displayJob(idx,&log); - } - break; - - - default: - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- -// Commands - charScanScript -//----------------------------------------------------------------------------- - - -//----------------------------------------------------------------------------- +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +/** + * todo: + * - charScanScript commands + * * path for script files in cfg + * - charScanScriptNew + * - charScanScriptLoad + * - charScanScriptSave + * - charScanScriptListFiles + * - charScanScriptListLines + * - charScanScriptDeleteLine + * - charScanScriptAddInputFiles + * - charScanScriptAddInfoExtractor [] + * - charScanScriptAddFilter [] + * - charScanScriptAddPreInclude + * - charScanScriptAddPostInclude + * - charScanScriptSetOutputDirectory + * - charScanScriptSetDescription + * - charScanScriptRun [-s ] [-o ] + * - addJobCharScanScript [-s ] [-o ] + * - charScanScriptListOutputFiles [] + * - charScanScriptListOutputFileContents [] + * - charScanScriptTestFileList + * - charScanScriptTestOutput + * - charScanScriptHelp + * - path for generated files (from cfg + override) => managed incrementally with directory numbering + * - add incremental update systems + * - add tables with a column per day () + * - add tables with a column per week (limited number of weeks) + * - add tables with a column per month (limited number of months) + */ + +/* +bool CCharFilterFactory::beginScanJob(const std::vector& files, const std::vector& filters) +{ + bool noErrors= true; + + // create a new job + NLMISC::CSmartPtr job=new CCharacterScanJob; + + // look after the filters + for (uint32 i=0;igetName()) + break; + + // if none found then warn and skip passed + if(j>=_Filters.size()) + { + nlwarning("Unknown info extractor: %s",filters[i].c_str()); + noErrors=false; + continue; + } + + // add the info extractor to the new job + job->addFilter(_Filters[j]); + } + + // look after the files + job->addFiles(files); + + // add the job to the job manager + if (noErrors==true) + CJobManager::getInstance()->addJob(&*job); + + return noErrors; +} + +*/ +//----------------------------------------------------------------------------- +// includes +//----------------------------------------------------------------------------- + +#include "nel/misc/path.h" +#include "nel/misc/command.h" +#include "nel/misc/variable.h" +#include "nel/misc/algo.h" +#include "game_share/persistent_data.h" + +#include "character.h" +#include "job_manager.h" +#include "char_info_extractor_factory.h" + + +//----------------------------------------------------------------------------- +// Namespaces +//----------------------------------------------------------------------------- + +using namespace std; +using namespace NLMISC; + +//----------------------------------------------------------------------------- +// Variables +//----------------------------------------------------------------------------- + +CVariable SourceDirectory("variables", "SourceDirectory", "Directory we scan for files", string("."), 0, true); + + +//----------------------------------------------------------------------------- +// Commands - misc character related +//----------------------------------------------------------------------------- + +NLMISC_COMMAND(listCharNames,"display the names of the characters int he listed save files","") +{ + if (args.size()!=1 && args.size()!=0) + return false; + + std::string wildcard="pdr_account*"; + if (args.size()==1) + wildcard=args[0]; + + std::vector files; + NLMISC::CPath::getPathContent(SourceDirectory.get().c_str(),false,false,true,files); + for (uint32 i=(uint32)files.size();i--;) + { + if (!NLMISC::testWildCard(NLMISC::CFile::getFilename(files[i]),wildcard)) + { + files[i]=files.back(); + files.pop_back(); + } + } + std::sort(files.begin(),files.end()); + for (uint32 i=0;idisplayInfoExtractorList(&log); + + return true; +} + +//----------------------------------------------------------------------------- +// Commands - jobsManager +//----------------------------------------------------------------------------- + +NLMISC_COMMAND(jobsPause,"pause execution of jobs","") +{ + if (args.size()!=0) + return false; + + CJobManager::getInstance()->pause(); + + return true; +} + +NLMISC_COMMAND(jobsResume,"resume execution of jobs","") +{ + if (args.size()!=0) + return false; + + CJobManager::getInstance()->resume(); + + return true; +} + +NLMISC_COMMAND(jobsPromote,"pause execution of jobs","") +{ + if (args.size()!=1) + return false; + + uint32 idx; + NLMISC::fromString(args[0], idx); + + if ( (idx==0 && args[0]!="0") ) + { + nlwarning("Argument is not a valid job id - should be a number"); + return false; + } + + CJobManager::getInstance()->promoteJob(idx); + CJobManager::getInstance()->listJobs(&log); + + return true; +} + +NLMISC_COMMAND(JobUpdatesPerUpdate,"set or display the number of job updates per service update","[]") +{ + if (args.size()>1) + return false; + + if (args.size()==1) + { + uint32 count; + NLMISC::fromString(args[0], count); + + if ( (count==0 && args[0]!="0") ) + { + nlwarning("Argument is not a valid number"); + return false; + } + CJobManager::getInstance()->setJobUpdatesPerUpdate(count); + } + + nlinfo("JobUpdatesPerUpdate %d",CJobManager::getInstance()->getJobUpdatesPerUpdate()); + + return true; +} + +NLMISC_COMMAND(jobsStatus,"display the status of the job manager","") +{ + if (args.size()!=0) + return false; + + log.displayNL("%s",CJobManager::getInstance()->getStatus().c_str()); + + return true; +} + +NLMISC_COMMAND(jobsList,"display the list of unfinished jobs","") +{ + if (args.size()!=0) + return false; + + CJobManager::getInstance()->listJobs(&log); + + return true; +} + +NLMISC_COMMAND(jobsListAll,"display the list of all jobs (unfinished jobs are marked with a '*')","") +{ + if (args.size()!=0) + return false; + + CJobManager::getInstance()->listJobHistory(&log); + + return true; +} + +NLMISC_COMMAND(jobsDisplayDetails,"display detailed info for the current job (or a given job)","[]") +{ + switch (args.size()) + { + case 0: + CJobManager::getInstance()->displayCurrentJob(&log); + break; + + case 1: + { + uint32 idx; + NLMISC::fromString(args[0], idx); + + if ( (idx==0 && args[0]!="0") ) + { + nlwarning("Argument is not a valid job id - should be a number"); + return false; + } + CJobManager::getInstance()->displayJob(idx,&log); + } + break; + + + default: + return false; + } + + return true; +} + +//----------------------------------------------------------------------------- +// Commands - charScanScript +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- diff --git a/code/ryzom/tools/stats_scan/char_filter_factory.cpp b/code/ryzom/tools/stats_scan/char_filter_factory.cpp index adeab857f..b78aba4f8 100644 --- a/code/ryzom/tools/stats_scan/char_filter_factory.cpp +++ b/code/ryzom/tools/stats_scan/char_filter_factory.cpp @@ -1,104 +1,104 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -//------------------------------------------------------------------------------------------------- -// includes -//------------------------------------------------------------------------------------------------- - -#include "char_filter_factory.h" - - -//------------------------------------------------------------------------------------------------- -// namespaces -//------------------------------------------------------------------------------------------------- - -using namespace std; -using namespace NLMISC; - - -//------------------------------------------------------------------------------------------------- -// methods CCharFilterFactory -//------------------------------------------------------------------------------------------------- - -CCharFilterFactory* CCharFilterFactory::getInstance() -{ - static CCharFilterFactory* ptr=NULL; - if (ptr==NULL) - ptr=new CCharFilterFactory; - return ptr; -} - -void CCharFilterFactory::registerFilter(NLMISC::CSmartPtr filter) -{ - // ensure that we don't have a name conflict with an existing info extractor - for (uint32 i=0;i<_Filters.size();++i) - { - nlassert(filter->getName()!=_Filters[i]->getName()); - } - - // add the new info extractor - _Filters.push_back(filter); -} - -void CCharFilterFactory::displayFilterList(NLMISC::CLog* log) -{ - uint32 longestName=4; - - // iterate over the filters to determine the length of the longest name - for (uint32 i=0;i<_Filters.size();++i) - { - std::string s= _Filters[i]->getName(); - if (s.size()>longestName) - longestName=(uint32)s.size(); - } - - // iterate over the filters displaying names and description - for (uint32 i=0;i<_Filters.size();++i) - { - log->displayNL("%-*s %s",longestName,_Filters[i]->getName(),_Filters[i]->getDescription()); - } -} - -uint32 CCharFilterFactory::getFilterBuilderCount() -{ - return (uint32)_Filters.size(); -} - -ICharFilterBuilder* CCharFilterFactory::getFilterBuilder(uint32 idx) -{ - nlassert(idx<_Filters.size()); - return _Filters[idx]; -} - -ICharFilter* CCharFilterFactory::build(const NLMISC::CSString& cmdLine) -{ - // split the command line into a command and a command tail (or arg set) - CSString cmdTail=cmdLine; - CSString cmd=cmdTail.firstWord(true).strip(); - - for (uint32 i=0;i<_Filters.size();++i) - { - if (cmd==_Filters[i]->getName()) - { - nlinfo("Adding filter: %s",cmdLine.c_str()); - return _Filters[i]->build(cmdTail); - } - } - - nlwarning("Unknown filter '%s' in line: %s",cmd.c_str(),cmdLine.c_str()); - return NULL; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +//------------------------------------------------------------------------------------------------- +// includes +//------------------------------------------------------------------------------------------------- + +#include "char_filter_factory.h" + + +//------------------------------------------------------------------------------------------------- +// namespaces +//------------------------------------------------------------------------------------------------- + +using namespace std; +using namespace NLMISC; + + +//------------------------------------------------------------------------------------------------- +// methods CCharFilterFactory +//------------------------------------------------------------------------------------------------- + +CCharFilterFactory* CCharFilterFactory::getInstance() +{ + static CCharFilterFactory* ptr=NULL; + if (ptr==NULL) + ptr=new CCharFilterFactory; + return ptr; +} + +void CCharFilterFactory::registerFilter(NLMISC::CSmartPtr filter) +{ + // ensure that we don't have a name conflict with an existing info extractor + for (uint32 i=0;i<_Filters.size();++i) + { + nlassert(filter->getName()!=_Filters[i]->getName()); + } + + // add the new info extractor + _Filters.push_back(filter); +} + +void CCharFilterFactory::displayFilterList(NLMISC::CLog* log) +{ + uint32 longestName=4; + + // iterate over the filters to determine the length of the longest name + for (uint32 i=0;i<_Filters.size();++i) + { + std::string s= _Filters[i]->getName(); + if (s.size()>longestName) + longestName=(uint32)s.size(); + } + + // iterate over the filters displaying names and description + for (uint32 i=0;i<_Filters.size();++i) + { + log->displayNL("%-*s %s",longestName,_Filters[i]->getName(),_Filters[i]->getDescription()); + } +} + +uint32 CCharFilterFactory::getFilterBuilderCount() +{ + return (uint32)_Filters.size(); +} + +ICharFilterBuilder* CCharFilterFactory::getFilterBuilder(uint32 idx) +{ + nlassert(idx<_Filters.size()); + return _Filters[idx]; +} + +ICharFilter* CCharFilterFactory::build(const NLMISC::CSString& cmdLine) +{ + // split the command line into a command and a command tail (or arg set) + CSString cmdTail=cmdLine; + CSString cmd=cmdTail.firstWord(true).strip(); + + for (uint32 i=0;i<_Filters.size();++i) + { + if (cmd==_Filters[i]->getName()) + { + nlinfo("Adding filter: %s",cmdLine.c_str()); + return _Filters[i]->build(cmdTail); + } + } + + nlwarning("Unknown filter '%s' in line: %s",cmd.c_str(),cmdLine.c_str()); + return NULL; +} diff --git a/code/ryzom/tools/stats_scan/char_filter_factory.h b/code/ryzom/tools/stats_scan/char_filter_factory.h index 35ee52a07..6dd929c36 100644 --- a/code/ryzom/tools/stats_scan/char_filter_factory.h +++ b/code/ryzom/tools/stats_scan/char_filter_factory.h @@ -1,135 +1,135 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CHAR_FILTER_FACTORY_H -#define CHAR_FILTER_FACTORY_H - -//------------------------------------------------------------------------------------------------- -// includes -//------------------------------------------------------------------------------------------------- - -#include "nel/misc/smart_ptr.h" -#include "nel/misc/sstring.h" - - -//------------------------------------------------------------------------------------------------- -// forward class declarations -//------------------------------------------------------------------------------------------------- - -class CStatsScanCharacter; - - -//------------------------------------------------------------------------------------------------- -// class ICharFilter -//------------------------------------------------------------------------------------------------- - -class ICharFilter: public NLMISC::CRefCount -{ -public: - virtual ~ICharFilter() {} - virtual std::string toString() const=0; - virtual bool evaluate(const CStatsScanCharacter* c)=0; -}; - - -//------------------------------------------------------------------------------------------------- -// class ICharFilterBuilder -//------------------------------------------------------------------------------------------------- - -class ICharFilterBuilder: public NLMISC::CRefCount -{ -public: - virtual ~ICharFilterBuilder() {} - virtual const char* getName()=0; - virtual const char* getDescription()=0; - virtual ICharFilter* build(const std::string& rawArgs)=0; -}; - - -//------------------------------------------------------------------------------------------------- -// class CCharFilterFactory -//------------------------------------------------------------------------------------------------- - -class CCharFilterFactory -{ -public: - static CCharFilterFactory* getInstance(); - -public: - // register an info extractor instance - void registerFilter(NLMISC::CSmartPtr filter); - - // display the set of names and descriptions of info extractor instances - void displayFilterList(NLMISC::CLog* log=NLMISC::InfoLog); - - // basic accessors for getting hold of the registered info extractors - uint32 getFilterBuilderCount(); - ICharFilterBuilder* getFilterBuilder(uint32 idx); - - // the all important build method - ICharFilter* build(const NLMISC::CSString& cmdLine); - -private: - // this is a singleton so ctor is private - CCharFilterFactory() {} - - typedef std::vector > TFilters; - TFilters _Filters; -}; - - -//------------------------------------------------------------------------------------------------- -// class CFilterRegisterer -//------------------------------------------------------------------------------------------------- - -template -class CFilterRegisterer -{ -public: - CFilterRegisterer() - { - CCharFilterFactory::getInstance()->registerFilter(new C); - } -}; - - -//------------------------------------------------------------------------------------------------- -// MACRO FILTER() -//------------------------------------------------------------------------------------------------- - -#define FILTER(name,description)\ -class CFilter_##name: public ICharFilter\ -{\ -public:\ - CFilter_##name(const std::string& rawArgs) {_RawArgs=rawArgs;}\ - virtual std::string toString() const {return std::string(#name)+" "+_RawArgs;}\ - virtual bool evaluate(const CStatsScanCharacter* c);\ -private:\ - NLMISC::CSString _RawArgs;\ -};\ -class CFilterBuilder_##name: public ICharFilterBuilder\ -{\ -public:\ - virtual const char* getName() {return #name;}\ - virtual const char* getDescription() {return description;}\ - virtual ICharFilter* build(const std::string& rawArgs) {return new CFilter_##name(rawArgs);}\ -};\ -CFilterRegisterer __Registerer_CFilter_##name;\ -bool CFilter_##name::evaluate(const CStatsScanCharacter* c) - - -//------------------------------------------------------------------------------------------------- +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CHAR_FILTER_FACTORY_H +#define CHAR_FILTER_FACTORY_H + +//------------------------------------------------------------------------------------------------- +// includes +//------------------------------------------------------------------------------------------------- + +#include "nel/misc/smart_ptr.h" +#include "nel/misc/sstring.h" + + +//------------------------------------------------------------------------------------------------- +// forward class declarations +//------------------------------------------------------------------------------------------------- + +class CStatsScanCharacter; + + +//------------------------------------------------------------------------------------------------- +// class ICharFilter +//------------------------------------------------------------------------------------------------- + +class ICharFilter: public NLMISC::CRefCount +{ +public: + virtual ~ICharFilter() {} + virtual std::string toString() const=0; + virtual bool evaluate(const CStatsScanCharacter* c)=0; +}; + + +//------------------------------------------------------------------------------------------------- +// class ICharFilterBuilder +//------------------------------------------------------------------------------------------------- + +class ICharFilterBuilder: public NLMISC::CRefCount +{ +public: + virtual ~ICharFilterBuilder() {} + virtual const char* getName()=0; + virtual const char* getDescription()=0; + virtual ICharFilter* build(const std::string& rawArgs)=0; +}; + + +//------------------------------------------------------------------------------------------------- +// class CCharFilterFactory +//------------------------------------------------------------------------------------------------- + +class CCharFilterFactory +{ +public: + static CCharFilterFactory* getInstance(); + +public: + // register an info extractor instance + void registerFilter(NLMISC::CSmartPtr filter); + + // display the set of names and descriptions of info extractor instances + void displayFilterList(NLMISC::CLog* log=NLMISC::InfoLog); + + // basic accessors for getting hold of the registered info extractors + uint32 getFilterBuilderCount(); + ICharFilterBuilder* getFilterBuilder(uint32 idx); + + // the all important build method + ICharFilter* build(const NLMISC::CSString& cmdLine); + +private: + // this is a singleton so ctor is private + CCharFilterFactory() {} + + typedef std::vector > TFilters; + TFilters _Filters; +}; + + +//------------------------------------------------------------------------------------------------- +// class CFilterRegisterer +//------------------------------------------------------------------------------------------------- + +template +class CFilterRegisterer +{ +public: + CFilterRegisterer() + { + CCharFilterFactory::getInstance()->registerFilter(new C); + } +}; + + +//------------------------------------------------------------------------------------------------- +// MACRO FILTER() +//------------------------------------------------------------------------------------------------- + +#define FILTER(name,description)\ +class CFilter_##name: public ICharFilter\ +{\ +public:\ + CFilter_##name(const std::string& rawArgs) {_RawArgs=rawArgs;}\ + virtual std::string toString() const {return std::string(#name)+" "+_RawArgs;}\ + virtual bool evaluate(const CStatsScanCharacter* c);\ +private:\ + NLMISC::CSString _RawArgs;\ +};\ +class CFilterBuilder_##name: public ICharFilterBuilder\ +{\ +public:\ + virtual const char* getName() {return #name;}\ + virtual const char* getDescription() {return description;}\ + virtual ICharFilter* build(const std::string& rawArgs) {return new CFilter_##name(rawArgs);}\ +};\ +CFilterRegisterer __Registerer_CFilter_##name;\ +bool CFilter_##name::evaluate(const CStatsScanCharacter* c) + + +//------------------------------------------------------------------------------------------------- #endif \ No newline at end of file diff --git a/code/ryzom/tools/stats_scan/char_info_extractor_factory.cpp b/code/ryzom/tools/stats_scan/char_info_extractor_factory.cpp index 6e99c3d1f..2135ac3ed 100644 --- a/code/ryzom/tools/stats_scan/char_info_extractor_factory.cpp +++ b/code/ryzom/tools/stats_scan/char_info_extractor_factory.cpp @@ -1,104 +1,104 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -//------------------------------------------------------------------------------------------------- -// includes -//------------------------------------------------------------------------------------------------- - -#include "char_info_extractor_factory.h" - - -//------------------------------------------------------------------------------------------------- -// namespaces -//------------------------------------------------------------------------------------------------- - -using namespace std; -using namespace NLMISC; - - -//------------------------------------------------------------------------------------------------- -// methods CCharInfoExtractorFactory -//------------------------------------------------------------------------------------------------- - -CCharInfoExtractorFactory* CCharInfoExtractorFactory::getInstance() -{ - static CCharInfoExtractorFactory* ptr=NULL; - if (ptr==NULL) - ptr=new CCharInfoExtractorFactory; - return ptr; -} - -void CCharInfoExtractorFactory::registerInfoExtractor(NLMISC::CSmartPtr infoExtractor) -{ - // ensure that we don't have a name conflict with an existing info extractor - for (uint32 i=0;i<_InfoExtractors.size();++i) - { - nlassert(infoExtractor->getName()!=_InfoExtractors[i]->getName()); - } - - // add the new info extractor - _InfoExtractors.push_back(infoExtractor); -} - -void CCharInfoExtractorFactory::displayInfoExtractorList(NLMISC::CLog* log) -{ - uint32 longestName=4; - - // iterate over the infoExtractors to determine the length of the longest name - for (uint32 i=0;i<_InfoExtractors.size();++i) - { - std::string s= _InfoExtractors[i]->getName(); - if (s.size()>longestName) - longestName=(uint32)s.size(); - } - - // iterate over the infoExtractors displaying names and description - for (uint32 i=0;i<_InfoExtractors.size();++i) - { - log->displayNL("%-*s %s",longestName,_InfoExtractors[i]->getName(),_InfoExtractors[i]->getDescription()); - } -} - -uint32 CCharInfoExtractorFactory::getInfoExtractorBuilderCount() -{ - return (uint32)_InfoExtractors.size(); -} - -ICharInfoExtractorBuilder* CCharInfoExtractorFactory::getInfoExtractorBuilder(uint32 idx) -{ - nlassert(idx<_InfoExtractors.size()); - return _InfoExtractors[idx]; -} - -ICharInfoExtractor* CCharInfoExtractorFactory::build(const NLMISC::CSString& cmdLine) -{ - // split the command line into a command and a command tail (or arg set) - CSString cmdTail=cmdLine; - CSString cmd=cmdTail.firstWord(true).strip(); - - for (uint32 i=0;i<_InfoExtractors.size();++i) - { - if (cmd==_InfoExtractors[i]->getName()) - { - nlinfo("Adding info extractor: %s",cmdLine.c_str()); - return _InfoExtractors[i]->build(cmdTail); - } - } - - nlwarning("Unknown info extractor '%s' in line: %s",cmd.c_str(),cmdLine.c_str()); - return NULL; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +//------------------------------------------------------------------------------------------------- +// includes +//------------------------------------------------------------------------------------------------- + +#include "char_info_extractor_factory.h" + + +//------------------------------------------------------------------------------------------------- +// namespaces +//------------------------------------------------------------------------------------------------- + +using namespace std; +using namespace NLMISC; + + +//------------------------------------------------------------------------------------------------- +// methods CCharInfoExtractorFactory +//------------------------------------------------------------------------------------------------- + +CCharInfoExtractorFactory* CCharInfoExtractorFactory::getInstance() +{ + static CCharInfoExtractorFactory* ptr=NULL; + if (ptr==NULL) + ptr=new CCharInfoExtractorFactory; + return ptr; +} + +void CCharInfoExtractorFactory::registerInfoExtractor(NLMISC::CSmartPtr infoExtractor) +{ + // ensure that we don't have a name conflict with an existing info extractor + for (uint32 i=0;i<_InfoExtractors.size();++i) + { + nlassert(infoExtractor->getName()!=_InfoExtractors[i]->getName()); + } + + // add the new info extractor + _InfoExtractors.push_back(infoExtractor); +} + +void CCharInfoExtractorFactory::displayInfoExtractorList(NLMISC::CLog* log) +{ + uint32 longestName=4; + + // iterate over the infoExtractors to determine the length of the longest name + for (uint32 i=0;i<_InfoExtractors.size();++i) + { + std::string s= _InfoExtractors[i]->getName(); + if (s.size()>longestName) + longestName=(uint32)s.size(); + } + + // iterate over the infoExtractors displaying names and description + for (uint32 i=0;i<_InfoExtractors.size();++i) + { + log->displayNL("%-*s %s",longestName,_InfoExtractors[i]->getName(),_InfoExtractors[i]->getDescription()); + } +} + +uint32 CCharInfoExtractorFactory::getInfoExtractorBuilderCount() +{ + return (uint32)_InfoExtractors.size(); +} + +ICharInfoExtractorBuilder* CCharInfoExtractorFactory::getInfoExtractorBuilder(uint32 idx) +{ + nlassert(idx<_InfoExtractors.size()); + return _InfoExtractors[idx]; +} + +ICharInfoExtractor* CCharInfoExtractorFactory::build(const NLMISC::CSString& cmdLine) +{ + // split the command line into a command and a command tail (or arg set) + CSString cmdTail=cmdLine; + CSString cmd=cmdTail.firstWord(true).strip(); + + for (uint32 i=0;i<_InfoExtractors.size();++i) + { + if (cmd==_InfoExtractors[i]->getName()) + { + nlinfo("Adding info extractor: %s",cmdLine.c_str()); + return _InfoExtractors[i]->build(cmdTail); + } + } + + nlwarning("Unknown info extractor '%s' in line: %s",cmd.c_str(),cmdLine.c_str()); + return NULL; +} diff --git a/code/ryzom/tools/stats_scan/char_info_extractor_factory.h b/code/ryzom/tools/stats_scan/char_info_extractor_factory.h index 35e3e7b68..c167683cd 100644 --- a/code/ryzom/tools/stats_scan/char_info_extractor_factory.h +++ b/code/ryzom/tools/stats_scan/char_info_extractor_factory.h @@ -1,139 +1,139 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CHAR_INFO_EXTRACTOR_FACTORY_H -#define CHAR_INFO_EXTRACTOR_FACTORY_H - - -//------------------------------------------------------------------------------------------------- -// includes -//------------------------------------------------------------------------------------------------- - -#include "nel/misc/smart_ptr.h" -#include "nel/misc/sstring.h" - - -//------------------------------------------------------------------------------------------------- -// forward class declarations -//------------------------------------------------------------------------------------------------- - -class CCharacterScanJob; -class CStatsScanCharacter; - - -//------------------------------------------------------------------------------------------------- -// class ICharInfoExtractor -//------------------------------------------------------------------------------------------------- - -class ICharInfoExtractor: public NLMISC::CRefCount -{ -public: - virtual ~ICharInfoExtractor() {} - virtual std::string toString() const=0; - virtual void execute(CCharacterScanJob* job,const CStatsScanCharacter* c)=0; -}; - - -//------------------------------------------------------------------------------------------------- -// class ICharInfoExtractorBuilder -//------------------------------------------------------------------------------------------------- - -class ICharInfoExtractorBuilder: public NLMISC::CRefCount -{ -public: - virtual ~ICharInfoExtractorBuilder() {} - virtual const char* getName()=0; - virtual const char* getDescription()=0; - virtual const char* getFields()=0; - virtual ICharInfoExtractor* build(const std::string& rawArgs)=0; -}; - - -//------------------------------------------------------------------------------------------------- -// class CCharInfoExtractorFactory -//------------------------------------------------------------------------------------------------- - -class CCharInfoExtractorFactory -{ -public: - static CCharInfoExtractorFactory* getInstance(); - -public: - // register an info extractor instance - void registerInfoExtractor(NLMISC::CSmartPtr infoExtractor); - - // display the set of names and descriptions of info extractor instances - void displayInfoExtractorList(NLMISC::CLog* log=NLMISC::InfoLog); - - // basic accessors for getting hold of the registered info extractors - uint32 getInfoExtractorBuilderCount(); - ICharInfoExtractorBuilder* getInfoExtractorBuilder(uint32 idx); - - // the all important build method - ICharInfoExtractor* build(const NLMISC::CSString& cmdLine); - -private: - // this is a singleton so ctor is private - CCharInfoExtractorFactory() {} - - typedef std::vector > TInfoExtractors; - TInfoExtractors _InfoExtractors; -}; - - -//------------------------------------------------------------------------------------------------- -// class CInfoExtractorRegisterer -//------------------------------------------------------------------------------------------------- - -template -class CInfoExtractorRegisterer -{ -public: - CInfoExtractorRegisterer() - { - CCharInfoExtractorFactory::getInstance()->registerInfoExtractor(new C); - } -}; - - -//------------------------------------------------------------------------------------------------- -// MACRO INFO_EXTRACTOR() -//------------------------------------------------------------------------------------------------- - -#define INFO_EXTRACTOR(name,description,fields)\ -class CInfoExtractor_##name: public ICharInfoExtractor\ -{\ -public:\ - CInfoExtractor_##name(const std::string& rawArgs) {_RawArgs=rawArgs;}\ - virtual std::string toString() const {return std::string(#name)+" "+_RawArgs;}\ - virtual void execute(CCharacterScanJob* job,const CStatsScanCharacter* c);\ -private:\ - NLMISC::CSString _RawArgs;\ -};\ -class CInfoExtractorBuilder_##name: public ICharInfoExtractorBuilder\ -{\ -public:\ - virtual const char* getName() {return #name;}\ - virtual const char* getDescription() {return description;}\ - virtual const char* getFields() {return fields;}\ - virtual ICharInfoExtractor* build(const std::string& rawArgs) {return new CInfoExtractor_##name(rawArgs);}\ -};\ -CInfoExtractorRegisterer __Registerer_CInfoExtractor_##name;\ -void CInfoExtractor_##name::execute(CCharacterScanJob* job,const CStatsScanCharacter* c) - - -//------------------------------------------------------------------------------------------------- +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CHAR_INFO_EXTRACTOR_FACTORY_H +#define CHAR_INFO_EXTRACTOR_FACTORY_H + + +//------------------------------------------------------------------------------------------------- +// includes +//------------------------------------------------------------------------------------------------- + +#include "nel/misc/smart_ptr.h" +#include "nel/misc/sstring.h" + + +//------------------------------------------------------------------------------------------------- +// forward class declarations +//------------------------------------------------------------------------------------------------- + +class CCharacterScanJob; +class CStatsScanCharacter; + + +//------------------------------------------------------------------------------------------------- +// class ICharInfoExtractor +//------------------------------------------------------------------------------------------------- + +class ICharInfoExtractor: public NLMISC::CRefCount +{ +public: + virtual ~ICharInfoExtractor() {} + virtual std::string toString() const=0; + virtual void execute(CCharacterScanJob* job,const CStatsScanCharacter* c)=0; +}; + + +//------------------------------------------------------------------------------------------------- +// class ICharInfoExtractorBuilder +//------------------------------------------------------------------------------------------------- + +class ICharInfoExtractorBuilder: public NLMISC::CRefCount +{ +public: + virtual ~ICharInfoExtractorBuilder() {} + virtual const char* getName()=0; + virtual const char* getDescription()=0; + virtual const char* getFields()=0; + virtual ICharInfoExtractor* build(const std::string& rawArgs)=0; +}; + + +//------------------------------------------------------------------------------------------------- +// class CCharInfoExtractorFactory +//------------------------------------------------------------------------------------------------- + +class CCharInfoExtractorFactory +{ +public: + static CCharInfoExtractorFactory* getInstance(); + +public: + // register an info extractor instance + void registerInfoExtractor(NLMISC::CSmartPtr infoExtractor); + + // display the set of names and descriptions of info extractor instances + void displayInfoExtractorList(NLMISC::CLog* log=NLMISC::InfoLog); + + // basic accessors for getting hold of the registered info extractors + uint32 getInfoExtractorBuilderCount(); + ICharInfoExtractorBuilder* getInfoExtractorBuilder(uint32 idx); + + // the all important build method + ICharInfoExtractor* build(const NLMISC::CSString& cmdLine); + +private: + // this is a singleton so ctor is private + CCharInfoExtractorFactory() {} + + typedef std::vector > TInfoExtractors; + TInfoExtractors _InfoExtractors; +}; + + +//------------------------------------------------------------------------------------------------- +// class CInfoExtractorRegisterer +//------------------------------------------------------------------------------------------------- + +template +class CInfoExtractorRegisterer +{ +public: + CInfoExtractorRegisterer() + { + CCharInfoExtractorFactory::getInstance()->registerInfoExtractor(new C); + } +}; + + +//------------------------------------------------------------------------------------------------- +// MACRO INFO_EXTRACTOR() +//------------------------------------------------------------------------------------------------- + +#define INFO_EXTRACTOR(name,description,fields)\ +class CInfoExtractor_##name: public ICharInfoExtractor\ +{\ +public:\ + CInfoExtractor_##name(const std::string& rawArgs) {_RawArgs=rawArgs;}\ + virtual std::string toString() const {return std::string(#name)+" "+_RawArgs;}\ + virtual void execute(CCharacterScanJob* job,const CStatsScanCharacter* c);\ +private:\ + NLMISC::CSString _RawArgs;\ +};\ +class CInfoExtractorBuilder_##name: public ICharInfoExtractorBuilder\ +{\ +public:\ + virtual const char* getName() {return #name;}\ + virtual const char* getDescription() {return description;}\ + virtual const char* getFields() {return fields;}\ + virtual ICharInfoExtractor* build(const std::string& rawArgs) {return new CInfoExtractor_##name(rawArgs);}\ +};\ +CInfoExtractorRegisterer __Registerer_CInfoExtractor_##name;\ +void CInfoExtractor_##name::execute(CCharacterScanJob* job,const CStatsScanCharacter* c) + + +//------------------------------------------------------------------------------------------------- #endif \ No newline at end of file diff --git a/code/ryzom/tools/stats_scan/char_scan_script.cpp b/code/ryzom/tools/stats_scan/char_scan_script.cpp index 99fee67cf..9ad0c0d8a 100644 --- a/code/ryzom/tools/stats_scan/char_scan_script.cpp +++ b/code/ryzom/tools/stats_scan/char_scan_script.cpp @@ -1,322 +1,322 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -//----------------------------------------------------------------------------- -// includes -//----------------------------------------------------------------------------- - -#include "nel/misc/variable.h" -#include "nel/misc/path.h" -#include "game_share/file_description_container.h" -#include "game_share/utils.h" -#include "char_scan_script.h" - - -//----------------------------------------------------------------------------- -// Namespaces -//----------------------------------------------------------------------------- - -using namespace std; -using namespace NLMISC; - - -//----------------------------------------------------------------------------- -// Variables -//----------------------------------------------------------------------------- - -CVariable ScriptDirectory("variables", "ScriptDirectory", "Directory containing script files", string("./"), 0, true); -CVariable OutputDirectory("variables", "OutputDirectory", "Directory containing output files", string("./"), 0, true); - - -//------------------------------------------------------------------------------------------------- -// methods CCharScanScript -//------------------------------------------------------------------------------------------------- - -bool CCharScanScript::addScriptFile(const std::string& fileName) -{ - std::string fullFileName=NLMISC::CPath::standardizePath(ScriptDirectory)+fileName; - - // make sure the file exists - if (!NLMISC::CFile::fileExists(fullFileName)) - { - nlwarning("script file not found: %s",fullFileName.c_str()); - return false; - } - - // make sure the file hasn't already been included previously - for (uint32 i=0;i<_ScriptFiles.size();++i) - { - if (_ScriptFiles[i].getFileName()==fullFileName) - { - nlwarning("attempt to include script file '%s' more than once",fullFileName.c_str()); - return true; - } - } - - // add & parse the new file - return vectAppend(_ScriptFiles).parseFile(fullFileName); -} - -void CCharScanScript::applyToJob(CCharacterScanJob& job) -{ - // iterate backwards over the script files in order to apply the most important files last - for (uint32 i=(uint32)_ScriptFiles.size();i--;) - { - _ScriptFiles[i].applyToJob(job); - } -} - -//------------------------------------------------------------------------------------------------- -// methods CCharScanScriptFile -//------------------------------------------------------------------------------------------------- - -bool CCharScanScriptFile::parseFile(const std::string& fileName, CCharScanScript* container) -{ - _FileName= fileName; - - // read the content of the input file - bool result; - NLMISC::CSString fileContent; - result=fileContent.readFromFile(fileName); - if (result==false) - { - nlwarning("Failed to read script file: %s",fileName.c_str()); - return false; - } - - // split the file into lines and execute them one by one - NLMISC::CVectorSString lines; - fileContent.splitLines(lines); - for (uint32 i=0;iexecute(*this,theLine,container); - } - return true; -} - -bool CCharScanScriptFile::applyToJob(CCharacterScanJob& job) -{ - bool result=true; - - // apply the file names - CFileDescriptionContainer fdc; - for (uint32 i=0;i<_InputFiles.size();++i) - { - fdc.addFileSpec(_InputFiles[i]); - } - job.addFiles(fdc); - - // apply the filters - for (uint32 i=0;i<_Filters.size();++i) - { - ICharFilter* filter= CCharFilterFactory::getInstance()->build(_Filters[i]); - if (filter==NULL) - { - nlwarning("Failed to build filter description from line: %s",_Filters[i].c_str()); - result=false; - continue; - } - job.addFilter(filter); - } - - // apply the info extractors - for (uint32 i=0;i<_InfoExtractors.size();++i) - { - ICharInfoExtractor* infoExtractor= CCharInfoExtractorFactory::getInstance()->build(_InfoExtractors[i]); - if (infoExtractor==NULL) - { - nlwarning("Failed to build filter description from line: %s",_InfoExtractors[i].c_str()); - result=false; - continue; - } - job.addInfoExtractor(infoExtractor); - } - - // apply the output path - job.setOutputPath(_OutputPath); - - return result; -} - -const std::string& CCharScanScriptFile::getFileName() const -{ - return _FileName; -} - -const std::string& CCharScanScriptFile::getDescription() const -{ - return _Description; -} - -bool CCharScanScriptFile::setDescription(const std::string& description) -{ - _Description= description; - return true; -} - -bool CCharScanScriptFile::setOutputPath(const std::string& path) -{ - _OutputPath= path; - return true; -} - -bool CCharScanScriptFile::addFilter(const std::string& rawArgs) -{ - _Filters.push_back(rawArgs); - return true; -} - -bool CCharScanScriptFile::addInfoExtractor(const std::string& rawArgs) -{ - _InfoExtractors.push_back(rawArgs); - return true; -} - -bool CCharScanScriptFile::addInputFiles(const std::string& rawArgs) -{ - _InputFiles.push_back(rawArgs); - return true; -} - - -//------------------------------------------------------------------------------------------------- -// methods CCharScanScriptCommandRegistry -//------------------------------------------------------------------------------------------------- - -CCharScanScriptCommandRegistry* CCharScanScriptCommandRegistry::getInstance() -{ - static CCharScanScriptCommandRegistry* ptr=NULL; - if (ptr==NULL) - ptr= new CCharScanScriptCommandRegistry; - return ptr; -} - -void CCharScanScriptCommandRegistry::registerScriptCommand(NLMISC::CSmartPtr scriptCommand) -{ - // ensure that we don't have a name conflict with an existing script command - for (uint32 i=0;i<_ScriptCommands.size();++i) - { - nlassert(scriptCommand->getName()!=_ScriptCommands[i]->getName()); - } - - // add the new script command - _ScriptCommands.push_back(scriptCommand); -} - -void CCharScanScriptCommandRegistry::displayScriptCommands(NLMISC::CLog* log) -{ - uint32 longestName=4; - - // iterate over the script commands to determine the length of the longest name - for (uint32 i=0;i<_ScriptCommands.size();++i) - { - std::string s= _ScriptCommands[i]->getName(); - if (s.size()>longestName) - longestName=(uint32)s.size(); - } - - // iterate over the script commands displaying names and description - for (uint32 i=0;i<_ScriptCommands.size();++i) - { - log->displayNL("%-*s %s",longestName,_ScriptCommands[i]->getName(),_ScriptCommands[i]->getDescription()); - } -} - -bool CCharScanScriptCommandRegistry::execute(CCharScanScriptFile& scriptFile,const CSString& commandLine,CCharScanScript* container) -{ - // split the command line into its constituent parts - CSString theCommand= commandLine.firstWordConst(); - CSString theRawArgs= commandLine.tailFromFirstWord().strip(); - CVectorSString theArgs; - theRawArgs.splitByOneOfSeparators(" \t",theArgs,false,false,false,false,true); - - // try to locate and execute the given command - for (uint32 i=0;i<_ScriptCommands.size();++i) - { - if (theCommand==_ScriptCommands[i]->getName()) - { - return _ScriptCommands[i]->execute(scriptFile,theArgs,theRawArgs,commandLine,container); - } - } - - // we failed to find the command so bomb - nlwarning("Unknown script command '%s' in line: %s",theCommand.c_str(),commandLine.c_str()); - return false; -} - - -//----------------------------------------------------------------------------- -// CHAR_SCAN_SCRIPT_COMMAND: instances -//----------------------------------------------------------------------------- - -CHAR_SCAN_SCRIPT_COMMAND(description,"","Set the description phrase for the script - displayed by the listScripts command") -{ - if (rawArgs.strip().empty()) - return false; - - return scriptFile.setDescription(rawArgs); -} - -CHAR_SCAN_SCRIPT_COMMAND(include,"","Include another script file") -{ - if (args.size()!=1) - return false; - - if (container==NULL) - return true; - - return container->addScriptFile(args[0]); -} - -CHAR_SCAN_SCRIPT_COMMAND(inputFiles,"[/]","Add a set of files to be parsed") -{ - if (rawArgs.strip().empty()) - return false; - - return scriptFile.addInputFiles(rawArgs); -} - -CHAR_SCAN_SCRIPT_COMMAND(filter," []","Add a filter to limit the set criteria to determine which files' content to reflect in output") -{ - if (rawArgs.strip().empty()) - return false; - - return scriptFile.addFilter(rawArgs); -} - -CHAR_SCAN_SCRIPT_COMMAND(infoExtactor," []","Add an info extractor") -{ - if (rawArgs.strip().empty()) - return false; - - return scriptFile.addInfoExtractor(rawArgs); -} - -CHAR_SCAN_SCRIPT_COMMAND(outputPath,"","Set the directory to which the output will be written") -{ - if (args.size()!=1) - return false; - - return scriptFile.setOutputPath(args[0]); -} - - -//----------------------------------------------------------------------------- +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +//----------------------------------------------------------------------------- +// includes +//----------------------------------------------------------------------------- + +#include "nel/misc/variable.h" +#include "nel/misc/path.h" +#include "game_share/file_description_container.h" +#include "game_share/utils.h" +#include "char_scan_script.h" + + +//----------------------------------------------------------------------------- +// Namespaces +//----------------------------------------------------------------------------- + +using namespace std; +using namespace NLMISC; + + +//----------------------------------------------------------------------------- +// Variables +//----------------------------------------------------------------------------- + +CVariable ScriptDirectory("variables", "ScriptDirectory", "Directory containing script files", string("./"), 0, true); +CVariable OutputDirectory("variables", "OutputDirectory", "Directory containing output files", string("./"), 0, true); + + +//------------------------------------------------------------------------------------------------- +// methods CCharScanScript +//------------------------------------------------------------------------------------------------- + +bool CCharScanScript::addScriptFile(const std::string& fileName) +{ + std::string fullFileName=NLMISC::CPath::standardizePath(ScriptDirectory)+fileName; + + // make sure the file exists + if (!NLMISC::CFile::fileExists(fullFileName)) + { + nlwarning("script file not found: %s",fullFileName.c_str()); + return false; + } + + // make sure the file hasn't already been included previously + for (uint32 i=0;i<_ScriptFiles.size();++i) + { + if (_ScriptFiles[i].getFileName()==fullFileName) + { + nlwarning("attempt to include script file '%s' more than once",fullFileName.c_str()); + return true; + } + } + + // add & parse the new file + return vectAppend(_ScriptFiles).parseFile(fullFileName); +} + +void CCharScanScript::applyToJob(CCharacterScanJob& job) +{ + // iterate backwards over the script files in order to apply the most important files last + for (uint32 i=(uint32)_ScriptFiles.size();i--;) + { + _ScriptFiles[i].applyToJob(job); + } +} + +//------------------------------------------------------------------------------------------------- +// methods CCharScanScriptFile +//------------------------------------------------------------------------------------------------- + +bool CCharScanScriptFile::parseFile(const std::string& fileName, CCharScanScript* container) +{ + _FileName= fileName; + + // read the content of the input file + bool result; + NLMISC::CSString fileContent; + result=fileContent.readFromFile(fileName); + if (result==false) + { + nlwarning("Failed to read script file: %s",fileName.c_str()); + return false; + } + + // split the file into lines and execute them one by one + NLMISC::CVectorSString lines; + fileContent.splitLines(lines); + for (uint32 i=0;iexecute(*this,theLine,container); + } + return true; +} + +bool CCharScanScriptFile::applyToJob(CCharacterScanJob& job) +{ + bool result=true; + + // apply the file names + CFileDescriptionContainer fdc; + for (uint32 i=0;i<_InputFiles.size();++i) + { + fdc.addFileSpec(_InputFiles[i]); + } + job.addFiles(fdc); + + // apply the filters + for (uint32 i=0;i<_Filters.size();++i) + { + ICharFilter* filter= CCharFilterFactory::getInstance()->build(_Filters[i]); + if (filter==NULL) + { + nlwarning("Failed to build filter description from line: %s",_Filters[i].c_str()); + result=false; + continue; + } + job.addFilter(filter); + } + + // apply the info extractors + for (uint32 i=0;i<_InfoExtractors.size();++i) + { + ICharInfoExtractor* infoExtractor= CCharInfoExtractorFactory::getInstance()->build(_InfoExtractors[i]); + if (infoExtractor==NULL) + { + nlwarning("Failed to build filter description from line: %s",_InfoExtractors[i].c_str()); + result=false; + continue; + } + job.addInfoExtractor(infoExtractor); + } + + // apply the output path + job.setOutputPath(_OutputPath); + + return result; +} + +const std::string& CCharScanScriptFile::getFileName() const +{ + return _FileName; +} + +const std::string& CCharScanScriptFile::getDescription() const +{ + return _Description; +} + +bool CCharScanScriptFile::setDescription(const std::string& description) +{ + _Description= description; + return true; +} + +bool CCharScanScriptFile::setOutputPath(const std::string& path) +{ + _OutputPath= path; + return true; +} + +bool CCharScanScriptFile::addFilter(const std::string& rawArgs) +{ + _Filters.push_back(rawArgs); + return true; +} + +bool CCharScanScriptFile::addInfoExtractor(const std::string& rawArgs) +{ + _InfoExtractors.push_back(rawArgs); + return true; +} + +bool CCharScanScriptFile::addInputFiles(const std::string& rawArgs) +{ + _InputFiles.push_back(rawArgs); + return true; +} + + +//------------------------------------------------------------------------------------------------- +// methods CCharScanScriptCommandRegistry +//------------------------------------------------------------------------------------------------- + +CCharScanScriptCommandRegistry* CCharScanScriptCommandRegistry::getInstance() +{ + static CCharScanScriptCommandRegistry* ptr=NULL; + if (ptr==NULL) + ptr= new CCharScanScriptCommandRegistry; + return ptr; +} + +void CCharScanScriptCommandRegistry::registerScriptCommand(NLMISC::CSmartPtr scriptCommand) +{ + // ensure that we don't have a name conflict with an existing script command + for (uint32 i=0;i<_ScriptCommands.size();++i) + { + nlassert(scriptCommand->getName()!=_ScriptCommands[i]->getName()); + } + + // add the new script command + _ScriptCommands.push_back(scriptCommand); +} + +void CCharScanScriptCommandRegistry::displayScriptCommands(NLMISC::CLog* log) +{ + uint32 longestName=4; + + // iterate over the script commands to determine the length of the longest name + for (uint32 i=0;i<_ScriptCommands.size();++i) + { + std::string s= _ScriptCommands[i]->getName(); + if (s.size()>longestName) + longestName=(uint32)s.size(); + } + + // iterate over the script commands displaying names and description + for (uint32 i=0;i<_ScriptCommands.size();++i) + { + log->displayNL("%-*s %s",longestName,_ScriptCommands[i]->getName(),_ScriptCommands[i]->getDescription()); + } +} + +bool CCharScanScriptCommandRegistry::execute(CCharScanScriptFile& scriptFile,const CSString& commandLine,CCharScanScript* container) +{ + // split the command line into its constituent parts + CSString theCommand= commandLine.firstWordConst(); + CSString theRawArgs= commandLine.tailFromFirstWord().strip(); + CVectorSString theArgs; + theRawArgs.splitByOneOfSeparators(" \t",theArgs,false,false,false,false,true); + + // try to locate and execute the given command + for (uint32 i=0;i<_ScriptCommands.size();++i) + { + if (theCommand==_ScriptCommands[i]->getName()) + { + return _ScriptCommands[i]->execute(scriptFile,theArgs,theRawArgs,commandLine,container); + } + } + + // we failed to find the command so bomb + nlwarning("Unknown script command '%s' in line: %s",theCommand.c_str(),commandLine.c_str()); + return false; +} + + +//----------------------------------------------------------------------------- +// CHAR_SCAN_SCRIPT_COMMAND: instances +//----------------------------------------------------------------------------- + +CHAR_SCAN_SCRIPT_COMMAND(description,"","Set the description phrase for the script - displayed by the listScripts command") +{ + if (rawArgs.strip().empty()) + return false; + + return scriptFile.setDescription(rawArgs); +} + +CHAR_SCAN_SCRIPT_COMMAND(include,"","Include another script file") +{ + if (args.size()!=1) + return false; + + if (container==NULL) + return true; + + return container->addScriptFile(args[0]); +} + +CHAR_SCAN_SCRIPT_COMMAND(inputFiles,"[/]","Add a set of files to be parsed") +{ + if (rawArgs.strip().empty()) + return false; + + return scriptFile.addInputFiles(rawArgs); +} + +CHAR_SCAN_SCRIPT_COMMAND(filter," []","Add a filter to limit the set criteria to determine which files' content to reflect in output") +{ + if (rawArgs.strip().empty()) + return false; + + return scriptFile.addFilter(rawArgs); +} + +CHAR_SCAN_SCRIPT_COMMAND(infoExtactor," []","Add an info extractor") +{ + if (rawArgs.strip().empty()) + return false; + + return scriptFile.addInfoExtractor(rawArgs); +} + +CHAR_SCAN_SCRIPT_COMMAND(outputPath,"","Set the directory to which the output will be written") +{ + if (args.size()!=1) + return false; + + return scriptFile.setOutputPath(args[0]); +} + + +//----------------------------------------------------------------------------- diff --git a/code/ryzom/tools/stats_scan/char_scan_script.h b/code/ryzom/tools/stats_scan/char_scan_script.h index ac3a6780b..7e7a7833b 100644 --- a/code/ryzom/tools/stats_scan/char_scan_script.h +++ b/code/ryzom/tools/stats_scan/char_scan_script.h @@ -1,173 +1,173 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CHAR_SCAN_SCRIPT_H -#define CHAR_SCAN_SCRIPT_H - -//------------------------------------------------------------------------------------------------- -// includes -//------------------------------------------------------------------------------------------------- - -#include "nel/misc/smart_ptr.h" -#include "character_scan_job.h" - - -//------------------------------------------------------------------------------------------------- -// forward class declarations -//------------------------------------------------------------------------------------------------- - -class CCharScanScript; // an object that represents a script (one or more cumulated files) -class CCharScanScriptFile; // an object that represents a script file -class ICharScanScriptCommand; // virtual base class for objects that represents commands that can be used in script files -class CCharScanScriptCommandRegistry; // singleton registry for ICharScanScriptCommand objects -template class CCharScanScriptCommandRegisterer; // template class used to register script commands in the registry - - -//------------------------------------------------------------------------------------------------- -// class CCharScanScript -//------------------------------------------------------------------------------------------------- - -class CCharScanScript -{ -public: - // public interface - bool addScriptFile(const std::string& fileName); - void applyToJob(CCharacterScanJob& job); - -private: - // prohibit implicit copy - CCharScanScript(const CCharScanScript&); - -private: - // private data - std::vector _ScriptFiles; -}; - - -//------------------------------------------------------------------------------------------------- -// class CCharScanScriptFile -//------------------------------------------------------------------------------------------------- - -class CCharScanScriptFile -{ -public: - // public interface - bool parseFile(const std::string& fileName, CCharScanScript* container=NULL); - bool applyToJob(CCharacterScanJob& job); - - const std::string& getFileName() const; - const std::string& getDescription() const; - -public: - // interface for script commands - bool setDescription(const std::string& description); - bool setOutputPath(const std::string& path); - bool addFilter(const std::string& rawArgs); - bool addInfoExtractor(const std::string& rawArgs); - bool addInputFiles(const std::string& rawArgs); - -private: - // private data - std::string _FileName; - std::string _Description; - std::string _OutputPath; - std::vector _Filters; - std::vector _InfoExtractors; - std::vector _InputFiles; -}; - - -//------------------------------------------------------------------------------------------------- -// class ICharScanScriptCommand -//------------------------------------------------------------------------------------------------- - -class ICharScanScriptCommand: public NLMISC::CRefCount -{ -public: - virtual ~ICharScanScriptCommand() {} - virtual const char* getName()=0; - virtual const char* getSyntax()=0; - virtual const char* getDescription()=0; - virtual bool execute(CCharScanScriptFile& scriptFile,const NLMISC::CVectorSString& args,const NLMISC::CSString& rawArgs,const NLMISC::CSString& rawCmdLine,CCharScanScript* container)=0; -}; - - -//------------------------------------------------------------------------------------------------- -// class CCharScanScriptCommandRegistry -//------------------------------------------------------------------------------------------------- - -class CCharScanScriptCommandRegistry -{ -public: - // accessor for the singleton instance - static CCharScanScriptCommandRegistry* getInstance(); - -public: - // register a script command - void registerScriptCommand(NLMISC::CSmartPtr scriptCommand); - - // display the set of script commands - void displayScriptCommands(NLMISC::CLog* log=NLMISC::InfoLog); - - // execute a script command for a given script file object - bool execute(CCharScanScriptFile& scriptFile,const NLMISC::CSString& commandLine,CCharScanScript* container); - -private: - // this is a singleton so ctor is private - CCharScanScriptCommandRegistry() {} - -private: - // singleton data - typedef std::vector > TScriptCommands; - TScriptCommands _ScriptCommands; -}; - - -//------------------------------------------------------------------------------------------------- -// class CCharScanScriptCommandRegisterer -//------------------------------------------------------------------------------------------------- - -template -class CCharScanScriptCommandRegisterer -{ -public: - CCharScanScriptCommandRegisterer() - { - CCharScanScriptCommandRegistry::getInstance()->registerScriptCommand(new C); - } -}; - - -//------------------------------------------------------------------------------------------------- -// MACRO CHAR_SCAN_SCRIPT_COMMAND() -//------------------------------------------------------------------------------------------------- - -#define CHAR_SCAN_SCRIPT_COMMAND(name,syntax,description)\ - class CCharScriptCommand_##name: public ICharScanScriptCommand\ -{\ -public:\ - virtual const char* getName() {return #name;}\ - virtual const char* getSyntax() {return syntax;}\ - virtual const char* getDescription() {return description;}\ -\ - virtual bool execute(CCharScanScriptFile& scriptFile,const NLMISC::CVectorSString& args,const NLMISC::CSString& rawArgs,const NLMISC::CSString& rawCmdLine,CCharScanScript* container);\ -};\ -CCharScanScriptCommandRegisterer __Registerer_CCharScriptCommand_##name;\ -bool CCharScriptCommand_##name::execute(CCharScanScriptFile& scriptFile,const NLMISC::CVectorSString& args,const NLMISC::CSString& rawArgs,const NLMISC::CSString& rawCmdLine,CCharScanScript* container) - - -//------------------------------------------------------------------------------------------------- -#endif +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CHAR_SCAN_SCRIPT_H +#define CHAR_SCAN_SCRIPT_H + +//------------------------------------------------------------------------------------------------- +// includes +//------------------------------------------------------------------------------------------------- + +#include "nel/misc/smart_ptr.h" +#include "character_scan_job.h" + + +//------------------------------------------------------------------------------------------------- +// forward class declarations +//------------------------------------------------------------------------------------------------- + +class CCharScanScript; // an object that represents a script (one or more cumulated files) +class CCharScanScriptFile; // an object that represents a script file +class ICharScanScriptCommand; // virtual base class for objects that represents commands that can be used in script files +class CCharScanScriptCommandRegistry; // singleton registry for ICharScanScriptCommand objects +template class CCharScanScriptCommandRegisterer; // template class used to register script commands in the registry + + +//------------------------------------------------------------------------------------------------- +// class CCharScanScript +//------------------------------------------------------------------------------------------------- + +class CCharScanScript +{ +public: + // public interface + bool addScriptFile(const std::string& fileName); + void applyToJob(CCharacterScanJob& job); + +private: + // prohibit implicit copy + CCharScanScript(const CCharScanScript&); + +private: + // private data + std::vector _ScriptFiles; +}; + + +//------------------------------------------------------------------------------------------------- +// class CCharScanScriptFile +//------------------------------------------------------------------------------------------------- + +class CCharScanScriptFile +{ +public: + // public interface + bool parseFile(const std::string& fileName, CCharScanScript* container=NULL); + bool applyToJob(CCharacterScanJob& job); + + const std::string& getFileName() const; + const std::string& getDescription() const; + +public: + // interface for script commands + bool setDescription(const std::string& description); + bool setOutputPath(const std::string& path); + bool addFilter(const std::string& rawArgs); + bool addInfoExtractor(const std::string& rawArgs); + bool addInputFiles(const std::string& rawArgs); + +private: + // private data + std::string _FileName; + std::string _Description; + std::string _OutputPath; + std::vector _Filters; + std::vector _InfoExtractors; + std::vector _InputFiles; +}; + + +//------------------------------------------------------------------------------------------------- +// class ICharScanScriptCommand +//------------------------------------------------------------------------------------------------- + +class ICharScanScriptCommand: public NLMISC::CRefCount +{ +public: + virtual ~ICharScanScriptCommand() {} + virtual const char* getName()=0; + virtual const char* getSyntax()=0; + virtual const char* getDescription()=0; + virtual bool execute(CCharScanScriptFile& scriptFile,const NLMISC::CVectorSString& args,const NLMISC::CSString& rawArgs,const NLMISC::CSString& rawCmdLine,CCharScanScript* container)=0; +}; + + +//------------------------------------------------------------------------------------------------- +// class CCharScanScriptCommandRegistry +//------------------------------------------------------------------------------------------------- + +class CCharScanScriptCommandRegistry +{ +public: + // accessor for the singleton instance + static CCharScanScriptCommandRegistry* getInstance(); + +public: + // register a script command + void registerScriptCommand(NLMISC::CSmartPtr scriptCommand); + + // display the set of script commands + void displayScriptCommands(NLMISC::CLog* log=NLMISC::InfoLog); + + // execute a script command for a given script file object + bool execute(CCharScanScriptFile& scriptFile,const NLMISC::CSString& commandLine,CCharScanScript* container); + +private: + // this is a singleton so ctor is private + CCharScanScriptCommandRegistry() {} + +private: + // singleton data + typedef std::vector > TScriptCommands; + TScriptCommands _ScriptCommands; +}; + + +//------------------------------------------------------------------------------------------------- +// class CCharScanScriptCommandRegisterer +//------------------------------------------------------------------------------------------------- + +template +class CCharScanScriptCommandRegisterer +{ +public: + CCharScanScriptCommandRegisterer() + { + CCharScanScriptCommandRegistry::getInstance()->registerScriptCommand(new C); + } +}; + + +//------------------------------------------------------------------------------------------------- +// MACRO CHAR_SCAN_SCRIPT_COMMAND() +//------------------------------------------------------------------------------------------------- + +#define CHAR_SCAN_SCRIPT_COMMAND(name,syntax,description)\ + class CCharScriptCommand_##name: public ICharScanScriptCommand\ +{\ +public:\ + virtual const char* getName() {return #name;}\ + virtual const char* getSyntax() {return syntax;}\ + virtual const char* getDescription() {return description;}\ +\ + virtual bool execute(CCharScanScriptFile& scriptFile,const NLMISC::CVectorSString& args,const NLMISC::CSString& rawArgs,const NLMISC::CSString& rawCmdLine,CCharScanScript* container);\ +};\ +CCharScanScriptCommandRegisterer __Registerer_CCharScriptCommand_##name;\ +bool CCharScriptCommand_##name::execute(CCharScanScriptFile& scriptFile,const NLMISC::CVectorSString& args,const NLMISC::CSString& rawArgs,const NLMISC::CSString& rawCmdLine,CCharScanScript* container) + + +//------------------------------------------------------------------------------------------------- +#endif diff --git a/code/ryzom/tools/stats_scan/character.cpp b/code/ryzom/tools/stats_scan/character.cpp index bc3eba003..56ab134b2 100644 --- a/code/ryzom/tools/stats_scan/character.cpp +++ b/code/ryzom/tools/stats_scan/character.cpp @@ -1,506 +1,506 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -//----------------------------------------------------------------------------- -// includes -//----------------------------------------------------------------------------- - -#include "character.h" - - -//----------------------------------------------------------------------------- -// namespaces -//----------------------------------------------------------------------------- - -using namespace std; -using namespace NLMISC; - - -#define PERSISTENT_TOKEN_FAMILY RyzomTokenFamily - - -//----------------------------------------------------------------------------- -// Globals -//----------------------------------------------------------------------------- - -// If the following macro is defined then the macros such as PERSISTENT_CLASS, PERSISTENT_DATA, PERSISTENT_PRE_STORE, etc -// are undefined after inclusion of perstent_data_template.h -#define PERSISTENT_MACROS_AUTO_UNDEF - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanMissionHistory -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanMissionHistory - -#define PERSISTENT_DATA\ - PROP(bool, Successfull)\ - PROP(TGameCycle, LastSuccessDate)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanDeathPenalties -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanDeathPenalties - -#define PERSISTENT_DATA\ - PROP(uint8,_NbDeath)\ - PROP(double,_CurrentDeathXP)\ - PROP(double,_DeathXPToGain)\ - PROP(uint32,_BonusUpdateTime)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanRespawnPoints -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanRespawnPoints - -#define PERSISTENT_DATA\ - PROP_VECT(string,RespawnPoints)\ - - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanFameContainerEntry -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanFameContainerEntry - -#define PERSISTENT_DATA\ - PROP(sint32,Fame)\ - PROP(sint32,FameMemory)\ - PROP(string,LastFameChangeTrend)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanFameContainer -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanFameContainer - -#define PERSISTENT_DATA\ - STRUCT_MAP(CSheetId,CStatsScanFameContainerEntry,_Fame)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanEncyCharThema -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanEncyCharThema - -#define PERSISTENT_DATA\ - PROP(uint8,ThemaState)\ - PROP(uint16,RiteTaskStatePacked)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanEncyCharAlbum -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanEncyCharAlbum - -#define PERSISTENT_DATA\ - PROP(uint8,AlbumState)\ - STRUCT_VECT(Themas)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanCharaterEncyclopedia -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanCharaterEncyclopedia - -#define PERSISTENT_DATA\ - STRUCT_VECT(_EncyCharAlbums)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanGameEvent -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanGameEvent - -#define PERSISTENT_DATA\ - PROP(uint32,_Date)\ - PROP(string,_EventFaction)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanPact -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanPact - -#define PERSISTENT_DATA\ - PROP(uint8,PactNature)\ - PROP(uint8,PactType)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanPetAnimal -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanPetAnimal - -#define PERSISTENT_DATA\ - PROP(CSheetId,TicketPetSheetId)\ - PROP(CSheetId,PetSheetId)\ - PROP(uint32,Price)\ - PROP(CEntityId,OwnerId)\ - PROP(TAIAlias,StableAlias)\ - PROP(sint32,Landscape_X)\ - PROP(sint32,Landscape_Y)\ - PROP(sint32,Landscape_Z)\ - PROP(uint32,DeathTick)\ - PROP(uint16,PetStatus)\ - PROP(sint16,Slot)\ - PROP(bool,IsFollowing)\ - PROP(bool,IsMounted)\ - PROP(bool,IsTpAllowed)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanPhysCharacs -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanPhysCharacs - -#define PERSISTENT_DATA\ - PROP_MAP(string,sint32,_PhysicalCharacteristics)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanPhysScoresEntry -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanPhysScoresEntry - -#define PERSISTENT_DATA\ - PROP(sint32,Current)\ - PROP(sint32,Base)\ - PROP(sint32,Max)\ - PROP(float,BaseRegenerateRepos)\ - PROP(float,BaseRegenerateAction)\ - PROP(float,CurrentRegenerate)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanPhysScores -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanPhysScores - -#define PERSISTENT_DATA\ - PROP(float,BaseWalkSpeed)\ - PROP(float,BaseRunSpeed)\ - PROP(float,CurrentWalkSpeed)\ - PROP(float,CurrentRunSpeed)\ - STRUCT_MAP(string,CStatsScanPhysScoresEntry,PhysicalScores)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanSkillsEntry -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanSkillsEntry - -#define PERSISTENT_DATA\ - PROP(sint32,Base)\ - PROP(sint32,Current)\ - PROP(sint32,MaxLvlReached)\ - PROP(double,Xp)\ - PROP(double,XpNextLvl)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanSkills -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanSkills - -#define PERSISTENT_DATA\ - STRUCT_MAP(string,CStatsScanSkillsEntry,Skills)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanItemCraftParameters -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanItemCraftParameters - -#define PERSISTENT_DATA\ - PROP(float,Durability)\ - PROP(float,Weight)\ - PROP(float,SapLoad)\ - PROP(float,StatEnergy)\ - PROP(float,Dmg)\ - PROP(float,Speed)\ - PROP(float,Range)\ - PROP(float,DodgeModifier)\ - PROP(float,ParryModifier)\ - PROP(float,AdversaryDodgeModifier)\ - PROP(float,AdversaryParryModifier)\ - PROP(float,ProtectionFactor)\ - PROP(float,MaxSlashingProtection)\ - PROP(float,MaxBluntProtection)\ - PROP(float,MaxPiercingProtection)\ - PROP(float,ElementalCastingTimeFactor)\ - PROP(float,ElementalPowerFactor)\ - PROP(float,OffensiveAfflictionCastingTimeFactor)\ - PROP(float,OffensiveAfflictionPowerFactor)\ - PROP(float,HealCastingTimeFactor)\ - PROP(float,HealPowerFactor)\ - PROP(float,DefensiveAfflictionCastingTimeFactor)\ - PROP(float,DefensiveAfflictionPowerFactor)\ - PROP(uint8,Color)\ - PROP(sint32,HpBuff)\ - PROP(sint32,SapBuff)\ - PROP(sint32,StaBuff)\ - PROP(sint32,FocusBuff)\ - PROP(string,Protection)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanItem -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanItem - -#define PERSISTENT_DATA\ - PROP(CSheetId,_SheetId)\ - PROP(sint16,_ClientInventoryPosition)\ - PROP(uint32,_HP)\ - PROP(uint32,_Recommended)\ - PROP(CEntityId,_CreatorId)\ - PROP(uint8,_LocSlot)\ - PROP(string,_PhraseId)\ - PROP(uint16,_SlotImage)\ - PROP(sint16,_SlotCount)\ - PROP(uint32,_SapLoad)\ - PROP(bool,_Dropable)\ - PROP(bool,_Destroyable)\ - PROP(uint32,StackSize)\ - STRUCT(_CraftParameters)\ - PROP_VECT(CSheetId,_Enchantment)\ - STRUCT_VECT(Child)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanInventory -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanInventory - -#define PERSISTENT_DATA\ - STRUCT_VECT(_Item)\ - - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanPlayerRoom -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanPlayerRoom - -#define PERSISTENT_DATA\ - PROP(TAIAlias,Building)\ - STRUCT(Inventory)\ - PROP(sint32,Bulk)\ - PROP(sint32,MaxBulk)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanEntityPosition -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanEntityPosition - -#define PERSISTENT_DATA\ - PROP(sint32,X)\ - PROP(sint32,Y)\ - PROP(sint32,Z)\ - PROP(float,Heading)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanEntityBase -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanEntityBase - -#define PERSISTENT_DATA\ - STRUCT(_EntityPosition)\ - PROP(uint32,_SheetId)\ - PROP(string,_Name)\ - PROP(string,_Race)\ - PROP(uint8,_Gender)\ - PROP(uint8,_Size)\ - PROP(bool,_DodgeAsDefense)\ - STRUCT(_PhysCharacs)\ - STRUCT(_PhysScores)\ - STRUCT(_Skills)\ - \ - PROP(sint32,MeleeAttackModifierOnEnemy)\ - PROP(sint32,MeleeAttackModifierOnSelf)\ - PROP(sint32,MagicCastingModifierOnSelf)\ - PROP(sint32,MagicCastingModifierOnEnemy)\ - PROP(sint32,RangeAttackModifierOnEnemy)\ - PROP(sint32,RangeAttackModifierOnSelf)\ - PROP(sint32,AttackModifierOnSelf)\ - PROP(sint32,ChanceToFailStrategy)\ - PROP(sint32,ChanceToFailSpell)\ - PROP(sint32,ChanceToFailFaber)\ - PROP(sint32,ChanceToFailHarvest)\ - PROP(sint32,ChanceToFailTracking)\ - PROP(sint32,MeleeAttackSlow)\ - PROP(sint32,MeleeSlashingDamageArmor)\ - PROP(sint32,MeleeBluntDamageArmor)\ - PROP(sint32,MeleePiercingDamageArmor)\ - PROP(sint32,MeleeDamageModifierFactor)\ - PROP(sint32,RangeDamageModifierFactor)\ - PROP(sint32,CreatureMeleeTakenDamageFactor)\ - PROP(sint32,CreatureRangeTakenDamageFactor)\ - PROP(sint32,CombatBrickLatencyMultiplier)\ - PROP(sint32,MagicBrickLatencyMultiplier)\ - PROP(sint32,ArmorQualityModifier)\ - PROP(sint32,WeaponQualityModifier)\ - PROP(sint32,ArmorAbsorbtionMultiplier)\ - -#include "game_share/persistent_data_template.h" - - -//----------------------------------------------------------------------------- -// Persistent data for CCharacter -//----------------------------------------------------------------------------- - -#define PERSISTENT_CLASS CStatsScanCharacter - -#define PERSISTENT_DATA\ - PROP(uint32,VERSION)\ - \ - PROP(uint8, _HairType)\ - PROP(uint8, _HairColor)\ - PROP(uint8, _HatColor)\ - PROP(uint8, _JacketColor)\ - PROP(uint8, _ArmsColor)\ - PROP(uint8, _TrousersColor)\ - PROP(uint8, _FeetColor)\ - PROP(uint8, _HandsColor)\ - PROP(uint64,_Money)\ - PROP(uint32,_GuildId)\ - PROP(bool, _NewCharacter)\ - PROP(uint8, _CreationPointsRepartition)\ - PROP(uint32,_ForbidAuraUseEndDate)\ - PROP(string,_Title)\ -\ - /* Visual Properties */\ - PROP(uint8,HairType)\ - PROP(uint8,HairColor)\ - PROP(uint8,GabaritHeight)\ - PROP(uint8,GabaritTorsoWidth)\ - PROP(uint8,GabaritArmsWidth)\ - PROP(uint8,GabaritLegsWidth)\ - PROP(uint8,GabaritBreastSize)\ - PROP(uint8,MorphTarget1)\ - PROP(uint8,MorphTarget2)\ - PROP(uint8,MorphTarget3)\ - PROP(uint8,MorphTarget4)\ - PROP(uint8,MorphTarget5)\ - PROP(uint8,MorphTarget6)\ - PROP(uint8,MorphTarget7)\ - PROP(uint8,MorphTarget8)\ - PROP(uint8,EyesColor)\ - PROP(uint8,Tattoo)\ - PROP(uint8,NameStringId)\ -\ - PROP(bool, _HairCuteDiscount )\ - PROP(float,_NextDeathPenaltyFactor)\ -\ - STRUCT(_DeathPenalties)\ - STRUCT(_PlayerRoom)\ - STRUCT(EntityBase)\ - STRUCT(RespawnPoints)\ - STRUCT(_Fames)\ - STRUCT(_EncycloChar)\ - STRUCT(_GameEvent)\ -\ - PROP_VECT(CSheetId,_BoughtPhrases)\ - PROP_VECT(CSheetId,_KnownBricks)\ - PROP_VECT(CEntityId,_FriendsList)\ - PROP_VECT(CEntityId,_IgnoreList)\ - PROP_VECT(CEntityId,_IsFriendOf)\ - PROP_VECT(CEntityId,_IsIgnoredBy)\ -\ - STRUCT_VECT(_Pact)\ -\ - PROP_MAP(string,double,SkillPoints)\ - PROP_MAP(string,uint32,SpentSkillPoints)\ - PROP_MAP(string,sint32,ScorePermanentModifiers)\ - PROP_MAP(string,uint8,StartingCharacteristicValues)\ -\ - STRUCT_MAP(TAIAlias,CStatsScanMissionHistory,_MissionHistories)\ - STRUCT_MAP(uint32,CStatsScanPetAnimal,_PlayerPets)\ - STRUCT_MAP(string,CStatsScanInventory,Inventory)\ - - -#include "game_share/persistent_data_template.h" - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +//----------------------------------------------------------------------------- +// includes +//----------------------------------------------------------------------------- + +#include "character.h" + + +//----------------------------------------------------------------------------- +// namespaces +//----------------------------------------------------------------------------- + +using namespace std; +using namespace NLMISC; + + +#define PERSISTENT_TOKEN_FAMILY RyzomTokenFamily + + +//----------------------------------------------------------------------------- +// Globals +//----------------------------------------------------------------------------- + +// If the following macro is defined then the macros such as PERSISTENT_CLASS, PERSISTENT_DATA, PERSISTENT_PRE_STORE, etc +// are undefined after inclusion of perstent_data_template.h +#define PERSISTENT_MACROS_AUTO_UNDEF + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanMissionHistory +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanMissionHistory + +#define PERSISTENT_DATA\ + PROP(bool, Successfull)\ + PROP(TGameCycle, LastSuccessDate)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanDeathPenalties +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanDeathPenalties + +#define PERSISTENT_DATA\ + PROP(uint8,_NbDeath)\ + PROP(double,_CurrentDeathXP)\ + PROP(double,_DeathXPToGain)\ + PROP(uint32,_BonusUpdateTime)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanRespawnPoints +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanRespawnPoints + +#define PERSISTENT_DATA\ + PROP_VECT(string,RespawnPoints)\ + + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanFameContainerEntry +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanFameContainerEntry + +#define PERSISTENT_DATA\ + PROP(sint32,Fame)\ + PROP(sint32,FameMemory)\ + PROP(string,LastFameChangeTrend)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanFameContainer +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanFameContainer + +#define PERSISTENT_DATA\ + STRUCT_MAP(CSheetId,CStatsScanFameContainerEntry,_Fame)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanEncyCharThema +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanEncyCharThema + +#define PERSISTENT_DATA\ + PROP(uint8,ThemaState)\ + PROP(uint16,RiteTaskStatePacked)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanEncyCharAlbum +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanEncyCharAlbum + +#define PERSISTENT_DATA\ + PROP(uint8,AlbumState)\ + STRUCT_VECT(Themas)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanCharaterEncyclopedia +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanCharaterEncyclopedia + +#define PERSISTENT_DATA\ + STRUCT_VECT(_EncyCharAlbums)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanGameEvent +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanGameEvent + +#define PERSISTENT_DATA\ + PROP(uint32,_Date)\ + PROP(string,_EventFaction)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanPact +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanPact + +#define PERSISTENT_DATA\ + PROP(uint8,PactNature)\ + PROP(uint8,PactType)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanPetAnimal +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanPetAnimal + +#define PERSISTENT_DATA\ + PROP(CSheetId,TicketPetSheetId)\ + PROP(CSheetId,PetSheetId)\ + PROP(uint32,Price)\ + PROP(CEntityId,OwnerId)\ + PROP(TAIAlias,StableAlias)\ + PROP(sint32,Landscape_X)\ + PROP(sint32,Landscape_Y)\ + PROP(sint32,Landscape_Z)\ + PROP(uint32,DeathTick)\ + PROP(uint16,PetStatus)\ + PROP(sint16,Slot)\ + PROP(bool,IsFollowing)\ + PROP(bool,IsMounted)\ + PROP(bool,IsTpAllowed)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanPhysCharacs +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanPhysCharacs + +#define PERSISTENT_DATA\ + PROP_MAP(string,sint32,_PhysicalCharacteristics)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanPhysScoresEntry +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanPhysScoresEntry + +#define PERSISTENT_DATA\ + PROP(sint32,Current)\ + PROP(sint32,Base)\ + PROP(sint32,Max)\ + PROP(float,BaseRegenerateRepos)\ + PROP(float,BaseRegenerateAction)\ + PROP(float,CurrentRegenerate)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanPhysScores +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanPhysScores + +#define PERSISTENT_DATA\ + PROP(float,BaseWalkSpeed)\ + PROP(float,BaseRunSpeed)\ + PROP(float,CurrentWalkSpeed)\ + PROP(float,CurrentRunSpeed)\ + STRUCT_MAP(string,CStatsScanPhysScoresEntry,PhysicalScores)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanSkillsEntry +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanSkillsEntry + +#define PERSISTENT_DATA\ + PROP(sint32,Base)\ + PROP(sint32,Current)\ + PROP(sint32,MaxLvlReached)\ + PROP(double,Xp)\ + PROP(double,XpNextLvl)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanSkills +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanSkills + +#define PERSISTENT_DATA\ + STRUCT_MAP(string,CStatsScanSkillsEntry,Skills)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanItemCraftParameters +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanItemCraftParameters + +#define PERSISTENT_DATA\ + PROP(float,Durability)\ + PROP(float,Weight)\ + PROP(float,SapLoad)\ + PROP(float,StatEnergy)\ + PROP(float,Dmg)\ + PROP(float,Speed)\ + PROP(float,Range)\ + PROP(float,DodgeModifier)\ + PROP(float,ParryModifier)\ + PROP(float,AdversaryDodgeModifier)\ + PROP(float,AdversaryParryModifier)\ + PROP(float,ProtectionFactor)\ + PROP(float,MaxSlashingProtection)\ + PROP(float,MaxBluntProtection)\ + PROP(float,MaxPiercingProtection)\ + PROP(float,ElementalCastingTimeFactor)\ + PROP(float,ElementalPowerFactor)\ + PROP(float,OffensiveAfflictionCastingTimeFactor)\ + PROP(float,OffensiveAfflictionPowerFactor)\ + PROP(float,HealCastingTimeFactor)\ + PROP(float,HealPowerFactor)\ + PROP(float,DefensiveAfflictionCastingTimeFactor)\ + PROP(float,DefensiveAfflictionPowerFactor)\ + PROP(uint8,Color)\ + PROP(sint32,HpBuff)\ + PROP(sint32,SapBuff)\ + PROP(sint32,StaBuff)\ + PROP(sint32,FocusBuff)\ + PROP(string,Protection)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanItem +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanItem + +#define PERSISTENT_DATA\ + PROP(CSheetId,_SheetId)\ + PROP(sint16,_ClientInventoryPosition)\ + PROP(uint32,_HP)\ + PROP(uint32,_Recommended)\ + PROP(CEntityId,_CreatorId)\ + PROP(uint8,_LocSlot)\ + PROP(string,_PhraseId)\ + PROP(uint16,_SlotImage)\ + PROP(sint16,_SlotCount)\ + PROP(uint32,_SapLoad)\ + PROP(bool,_Dropable)\ + PROP(bool,_Destroyable)\ + PROP(uint32,StackSize)\ + STRUCT(_CraftParameters)\ + PROP_VECT(CSheetId,_Enchantment)\ + STRUCT_VECT(Child)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanInventory +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanInventory + +#define PERSISTENT_DATA\ + STRUCT_VECT(_Item)\ + + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanPlayerRoom +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanPlayerRoom + +#define PERSISTENT_DATA\ + PROP(TAIAlias,Building)\ + STRUCT(Inventory)\ + PROP(sint32,Bulk)\ + PROP(sint32,MaxBulk)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanEntityPosition +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanEntityPosition + +#define PERSISTENT_DATA\ + PROP(sint32,X)\ + PROP(sint32,Y)\ + PROP(sint32,Z)\ + PROP(float,Heading)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanEntityBase +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanEntityBase + +#define PERSISTENT_DATA\ + STRUCT(_EntityPosition)\ + PROP(uint32,_SheetId)\ + PROP(string,_Name)\ + PROP(string,_Race)\ + PROP(uint8,_Gender)\ + PROP(uint8,_Size)\ + PROP(bool,_DodgeAsDefense)\ + STRUCT(_PhysCharacs)\ + STRUCT(_PhysScores)\ + STRUCT(_Skills)\ + \ + PROP(sint32,MeleeAttackModifierOnEnemy)\ + PROP(sint32,MeleeAttackModifierOnSelf)\ + PROP(sint32,MagicCastingModifierOnSelf)\ + PROP(sint32,MagicCastingModifierOnEnemy)\ + PROP(sint32,RangeAttackModifierOnEnemy)\ + PROP(sint32,RangeAttackModifierOnSelf)\ + PROP(sint32,AttackModifierOnSelf)\ + PROP(sint32,ChanceToFailStrategy)\ + PROP(sint32,ChanceToFailSpell)\ + PROP(sint32,ChanceToFailFaber)\ + PROP(sint32,ChanceToFailHarvest)\ + PROP(sint32,ChanceToFailTracking)\ + PROP(sint32,MeleeAttackSlow)\ + PROP(sint32,MeleeSlashingDamageArmor)\ + PROP(sint32,MeleeBluntDamageArmor)\ + PROP(sint32,MeleePiercingDamageArmor)\ + PROP(sint32,MeleeDamageModifierFactor)\ + PROP(sint32,RangeDamageModifierFactor)\ + PROP(sint32,CreatureMeleeTakenDamageFactor)\ + PROP(sint32,CreatureRangeTakenDamageFactor)\ + PROP(sint32,CombatBrickLatencyMultiplier)\ + PROP(sint32,MagicBrickLatencyMultiplier)\ + PROP(sint32,ArmorQualityModifier)\ + PROP(sint32,WeaponQualityModifier)\ + PROP(sint32,ArmorAbsorbtionMultiplier)\ + +#include "game_share/persistent_data_template.h" + + +//----------------------------------------------------------------------------- +// Persistent data for CCharacter +//----------------------------------------------------------------------------- + +#define PERSISTENT_CLASS CStatsScanCharacter + +#define PERSISTENT_DATA\ + PROP(uint32,VERSION)\ + \ + PROP(uint8, _HairType)\ + PROP(uint8, _HairColor)\ + PROP(uint8, _HatColor)\ + PROP(uint8, _JacketColor)\ + PROP(uint8, _ArmsColor)\ + PROP(uint8, _TrousersColor)\ + PROP(uint8, _FeetColor)\ + PROP(uint8, _HandsColor)\ + PROP(uint64,_Money)\ + PROP(uint32,_GuildId)\ + PROP(bool, _NewCharacter)\ + PROP(uint8, _CreationPointsRepartition)\ + PROP(uint32,_ForbidAuraUseEndDate)\ + PROP(string,_Title)\ +\ + /* Visual Properties */\ + PROP(uint8,HairType)\ + PROP(uint8,HairColor)\ + PROP(uint8,GabaritHeight)\ + PROP(uint8,GabaritTorsoWidth)\ + PROP(uint8,GabaritArmsWidth)\ + PROP(uint8,GabaritLegsWidth)\ + PROP(uint8,GabaritBreastSize)\ + PROP(uint8,MorphTarget1)\ + PROP(uint8,MorphTarget2)\ + PROP(uint8,MorphTarget3)\ + PROP(uint8,MorphTarget4)\ + PROP(uint8,MorphTarget5)\ + PROP(uint8,MorphTarget6)\ + PROP(uint8,MorphTarget7)\ + PROP(uint8,MorphTarget8)\ + PROP(uint8,EyesColor)\ + PROP(uint8,Tattoo)\ + PROP(uint8,NameStringId)\ +\ + PROP(bool, _HairCuteDiscount )\ + PROP(float,_NextDeathPenaltyFactor)\ +\ + STRUCT(_DeathPenalties)\ + STRUCT(_PlayerRoom)\ + STRUCT(EntityBase)\ + STRUCT(RespawnPoints)\ + STRUCT(_Fames)\ + STRUCT(_EncycloChar)\ + STRUCT(_GameEvent)\ +\ + PROP_VECT(CSheetId,_BoughtPhrases)\ + PROP_VECT(CSheetId,_KnownBricks)\ + PROP_VECT(CEntityId,_FriendsList)\ + PROP_VECT(CEntityId,_IgnoreList)\ + PROP_VECT(CEntityId,_IsFriendOf)\ + PROP_VECT(CEntityId,_IsIgnoredBy)\ +\ + STRUCT_VECT(_Pact)\ +\ + PROP_MAP(string,double,SkillPoints)\ + PROP_MAP(string,uint32,SpentSkillPoints)\ + PROP_MAP(string,sint32,ScorePermanentModifiers)\ + PROP_MAP(string,uint8,StartingCharacteristicValues)\ +\ + STRUCT_MAP(TAIAlias,CStatsScanMissionHistory,_MissionHistories)\ + STRUCT_MAP(uint32,CStatsScanPetAnimal,_PlayerPets)\ + STRUCT_MAP(string,CStatsScanInventory,Inventory)\ + + +#include "game_share/persistent_data_template.h" + diff --git a/code/ryzom/tools/stats_scan/character.h b/code/ryzom/tools/stats_scan/character.h index 071265eb2..1655711eb 100644 --- a/code/ryzom/tools/stats_scan/character.h +++ b/code/ryzom/tools/stats_scan/character.h @@ -1,698 +1,698 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef CHARACTER_H -#define CHARACTER_H - -//----------------------------------------------------------------------------- -// includes -//----------------------------------------------------------------------------- - -#include "nel/misc/sstring.h" -#include "game_share/persistent_data.h" - - -//----------------------------------------------------------------------------- -// Data types -//----------------------------------------------------------------------------- - -typedef uint32 TAIAlias; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanMissionHistory -//----------------------------------------------------------------------------- - -class CStatsScanMissionHistory -{ -public: - DECLARE_PERSISTENCE_METHODS - - bool Successfull; - NLMISC::TGameCycle LastSuccessDate; - - CStatsScanMissionHistory() - { - Successfull=false; - LastSuccessDate=0; - } -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanDeathPenalties -//----------------------------------------------------------------------------- - -class CStatsScanDeathPenalties -{ -public: - DECLARE_PERSISTENCE_METHODS - - CStatsScanDeathPenalties() - { - _NbDeath=0; - _CurrentDeathXP=0.0; - _DeathXPToGain=0.0; - _BonusUpdateTime=0; - } - - uint8 _NbDeath; - double _CurrentDeathXP; - double _DeathXPToGain; - uint32 _BonusUpdateTime; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanRespawnPoints -//----------------------------------------------------------------------------- - -class CStatsScanRespawnPoints -{ -public: - DECLARE_PERSISTENCE_METHODS - - std::vector RespawnPoints; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanFameContainerEntry -//----------------------------------------------------------------------------- - -class CStatsScanFameContainerEntry -{ -public: - DECLARE_PERSISTENCE_METHODS - - sint32 Fame; - sint32 FameMemory; - std::string LastFameChangeTrend; - - CStatsScanFameContainerEntry() - { - Fame=0; - FameMemory=0; - } - -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanFameContainer -//----------------------------------------------------------------------------- - -class CStatsScanFameContainer -{ -public: - DECLARE_PERSISTENCE_METHODS - - std::map _Fame; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanEncyCharThema -//----------------------------------------------------------------------------- - -class CStatsScanEncyCharThema -{ -public: - DECLARE_PERSISTENCE_METHODS - - uint8 ThemaState; - uint16 RiteTaskStatePacked; - - CStatsScanEncyCharThema() - { - ThemaState=0; - RiteTaskStatePacked=0; - } -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanEncyCharAlbum -//----------------------------------------------------------------------------- - -class CStatsScanEncyCharAlbum -{ -public: - DECLARE_PERSISTENCE_METHODS - - uint8 AlbumState; - std::vector Themas; - - CStatsScanEncyCharAlbum() - { - AlbumState=0; - } -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanCharaterEncyclopedia -//----------------------------------------------------------------------------- - -class CStatsScanCharaterEncyclopedia -{ -public: - DECLARE_PERSISTENCE_METHODS - - std::vector _EncyCharAlbums; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanGameEvent -//----------------------------------------------------------------------------- - -class CStatsScanGameEvent -{ -public: - DECLARE_PERSISTENCE_METHODS - - CStatsScanGameEvent() - { - _Date=0; - } - - uint32 _Date; - std::string _EventFaction; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanPact -//----------------------------------------------------------------------------- - -class CStatsScanPact -{ -public: - DECLARE_PERSISTENCE_METHODS - - CStatsScanPact() - { - PactNature=0; - PactType=0; - } - - uint8 PactNature; - uint8 PactType; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanPetAnimal -//----------------------------------------------------------------------------- - -class CStatsScanPetAnimal -{ -public: - DECLARE_PERSISTENCE_METHODS - - NLMISC::CSheetId TicketPetSheetId; - NLMISC::CSheetId PetSheetId; - uint32 Price; - NLMISC::CEntityId OwnerId; - TAIAlias StableAlias; - sint32 Landscape_X; - sint32 Landscape_Y; - sint32 Landscape_Z; - uint32 DeathTick; - uint16 PetStatus; - sint16 Slot; - bool IsFollowing; - bool IsMounted; - bool IsTpAllowed; - - CStatsScanPetAnimal() - { - Price=0; - StableAlias=0; - Landscape_X=0; - Landscape_Y=0; - Landscape_Z=0; - DeathTick=0; - PetStatus=0; - Slot=0; - IsFollowing=false; - IsMounted=false; - IsTpAllowed=false; - } -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanPhysCharacs -//----------------------------------------------------------------------------- - -class CStatsScanPhysCharacs -{ -public: - DECLARE_PERSISTENCE_METHODS - - std::map _PhysicalCharacteristics; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanPhysScoresEntry -//----------------------------------------------------------------------------- - -class CStatsScanPhysScoresEntry -{ -public: - DECLARE_PERSISTENCE_METHODS - - CStatsScanPhysScoresEntry() - { - Current=0; - Base=0; - Max=0; - BaseRegenerateRepos=0.0f; - BaseRegenerateAction=0.0f; - CurrentRegenerate=0.0f; - } - - sint32 Current; - sint32 Base; - sint32 Max; - float BaseRegenerateRepos; - float BaseRegenerateAction; - float CurrentRegenerate; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanPhysScores -//----------------------------------------------------------------------------- - -class CStatsScanPhysScores -{ -public: - DECLARE_PERSISTENCE_METHODS - - CStatsScanPhysScores() - { - BaseWalkSpeed=0.0f; - BaseRunSpeed=0.0f; - CurrentWalkSpeed=0.0f; - CurrentRunSpeed=0.0f; - } - - float BaseWalkSpeed; - float BaseRunSpeed; - float CurrentWalkSpeed; - float CurrentRunSpeed; - std::map PhysicalScores; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanSkillsEntry -//----------------------------------------------------------------------------- - -class CStatsScanSkillsEntry -{ -public: - DECLARE_PERSISTENCE_METHODS - - CStatsScanSkillsEntry() - { - Base=0; - Current=0; - MaxLvlReached=0; - Xp=0.0; - XpNextLvl=0.0; - } - - sint32 Base; - sint32 Current; - sint32 MaxLvlReached; - double Xp; - double XpNextLvl; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanSkills -//----------------------------------------------------------------------------- - -class CStatsScanSkills -{ -public: - DECLARE_PERSISTENCE_METHODS - - std::map Skills; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanItemCraftParameters -//----------------------------------------------------------------------------- - -class CStatsScanItemCraftParameters -{ -public: - DECLARE_PERSISTENCE_METHODS - - CStatsScanItemCraftParameters() - { - Durability=0.0f; - Weight=0.0f; - SapLoad=0.0f; - StatEnergy=0.0f; - Dmg=0.0f; - Speed=0.0f; - Range=0.0f; - DodgeModifier=0.0f; - ParryModifier=0.0f; - AdversaryDodgeModifier=0.0f; - AdversaryParryModifier=0.0f; - ProtectionFactor=0.0f; - MaxSlashingProtection=0.0f; - MaxBluntProtection=0.0f; - MaxPiercingProtection=0.0f; - ElementalCastingTimeFactor=0.0f; - ElementalPowerFactor=0.0f; - OffensiveAfflictionCastingTimeFactor=0.0f; - OffensiveAfflictionPowerFactor=0.0f; - HealCastingTimeFactor=0.0f; - HealPowerFactor=0.0f; - DefensiveAfflictionCastingTimeFactor=0.0f; - DefensiveAfflictionPowerFactor=0.0f; - Color=0; - HpBuff=0; - SapBuff=0; - StaBuff=0; - FocusBuff=0; - } - - float Durability; - float Weight; - float SapLoad; - float StatEnergy; - float Dmg; - float Speed; - float Range; - float DodgeModifier; - float ParryModifier; - float AdversaryDodgeModifier; - float AdversaryParryModifier; - float ProtectionFactor; - float MaxSlashingProtection; - float MaxBluntProtection; - float MaxPiercingProtection; - float ElementalCastingTimeFactor; - float ElementalPowerFactor; - float OffensiveAfflictionCastingTimeFactor; - float OffensiveAfflictionPowerFactor; - float HealCastingTimeFactor; - float HealPowerFactor; - float DefensiveAfflictionCastingTimeFactor; - float DefensiveAfflictionPowerFactor; - uint8 Color; - sint32 HpBuff; - sint32 SapBuff; - sint32 StaBuff; - sint32 FocusBuff; - std::string Protection; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanItem -//----------------------------------------------------------------------------- - -class CStatsScanItem -{ -public: - DECLARE_PERSISTENCE_METHODS - - CStatsScanItem() - { - _ClientInventoryPosition=0; - _HP=0; - _Recommended=0; - _LocSlot=0; - _SlotImage=0; - _SlotCount=0; - _SapLoad=0; - _Dropable=true; - _Destroyable=true; - StackSize=0; - } - - NLMISC::CSheetId _SheetId; - sint16 _ClientInventoryPosition; - uint32 _HP; - uint32 _Recommended; - NLMISC::CEntityId _CreatorId; - uint8 _LocSlot; - std::string _PhraseId; - uint16 _SlotImage; - sint16 _SlotCount; - uint32 _SapLoad; - bool _Dropable; - bool _Destroyable; - uint32 StackSize; - CStatsScanItemCraftParameters _CraftParameters; - std::vector _Enchantment; - std::vector Child; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanInventory -//----------------------------------------------------------------------------- - -class CStatsScanInventory -{ -public: - DECLARE_PERSISTENCE_METHODS - - std::vector _Item; -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanPlayerRoom -//----------------------------------------------------------------------------- - -class CStatsScanPlayerRoom -{ -public: - DECLARE_PERSISTENCE_METHODS - - TAIAlias Building; - CStatsScanItem Inventory; - sint32 Bulk; - sint32 MaxBulk; - - CStatsScanPlayerRoom() - { - Building=0; - Bulk=0; - MaxBulk=0; - } -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanEntityPosition -//----------------------------------------------------------------------------- - -class CStatsScanEntityPosition -{ -public: - DECLARE_PERSISTENCE_METHODS - - sint32 X; - sint32 Y; - sint32 Z; - float Heading; - - CStatsScanEntityPosition() - { - X=0; - Y=0; - Z=0; - Heading=0.0f; - } -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanEntityBase -//----------------------------------------------------------------------------- - -class CStatsScanEntityBase -{ -public: - DECLARE_PERSISTENCE_METHODS - - CStatsScanEntityPosition _EntityPosition; - uint32 _SheetId; - std::string _Name; - std::string _Race; - uint8 _Gender; - uint8 _Size; - bool _DodgeAsDefense; - CStatsScanPhysCharacs _PhysCharacs; - CStatsScanPhysScores _PhysScores; - CStatsScanSkills _Skills; - - sint32 MeleeAttackModifierOnEnemy; - sint32 MeleeAttackModifierOnSelf; - sint32 MagicCastingModifierOnSelf; - sint32 MagicCastingModifierOnEnemy; - sint32 RangeAttackModifierOnEnemy; - sint32 RangeAttackModifierOnSelf; - sint32 AttackModifierOnSelf; - sint32 ChanceToFailStrategy; - sint32 ChanceToFailSpell; - sint32 ChanceToFailFaber; - sint32 ChanceToFailHarvest; - sint32 ChanceToFailTracking; - sint32 MeleeAttackSlow; - sint32 MeleeSlashingDamageArmor; - sint32 MeleeBluntDamageArmor; - sint32 MeleePiercingDamageArmor; - sint32 MeleeDamageModifierFactor; - sint32 RangeDamageModifierFactor; - sint32 CreatureMeleeTakenDamageFactor; - sint32 CreatureRangeTakenDamageFactor; - sint32 CombatBrickLatencyMultiplier; - sint32 MagicBrickLatencyMultiplier; - sint32 ArmorQualityModifier; - sint32 WeaponQualityModifier; - sint32 ArmorAbsorbtionMultiplier; - - CStatsScanEntityBase() - { - _DodgeAsDefense=false; - _SheetId=0; - _Gender=0; - _Size=0; - - MeleeAttackModifierOnEnemy=0; - MeleeAttackModifierOnSelf=0; - MagicCastingModifierOnSelf=0; - MagicCastingModifierOnEnemy=0; - RangeAttackModifierOnEnemy=0; - RangeAttackModifierOnSelf=0; - AttackModifierOnSelf=0; - ChanceToFailStrategy=0; - ChanceToFailSpell=0; - ChanceToFailFaber=0; - ChanceToFailHarvest=0; - ChanceToFailTracking=0; - MeleeAttackSlow=0; - MeleeSlashingDamageArmor=0; - MeleeBluntDamageArmor=0; - MeleePiercingDamageArmor=0; - MeleeDamageModifierFactor=0; - RangeDamageModifierFactor=0; - CreatureMeleeTakenDamageFactor=0; - CreatureRangeTakenDamageFactor=0; - CombatBrickLatencyMultiplier=0; - MagicBrickLatencyMultiplier=0; - ArmorQualityModifier=0; - WeaponQualityModifier=0; - ArmorAbsorbtionMultiplier=0; - } -}; - - -//----------------------------------------------------------------------------- -// Persistent data for CStatsScanCharacter -//----------------------------------------------------------------------------- - -class CStatsScanCharacter -{ -public: - DECLARE_PERSISTENCE_METHODS - - uint32 VERSION; - - uint8 _HairType; - uint8 _HairColor; - uint8 _HatColor; - uint8 _JacketColor; - uint8 _ArmsColor; - uint8 _TrousersColor; - uint8 _FeetColor; - uint8 _HandsColor; - uint64 _Money; - uint32 _GuildId; - bool _NewCharacter; - uint8 _CreationPointsRepartition; - uint32 _ForbidAuraUseEndDate; - std::string _Title; - - /* Visual Properties */ - uint8 HairType; - uint8 HairColor; - uint8 GabaritHeight; - uint8 GabaritTorsoWidth; - uint8 GabaritArmsWidth; - uint8 GabaritLegsWidth; - uint8 GabaritBreastSize; - uint8 MorphTarget1; - uint8 MorphTarget2; - uint8 MorphTarget3; - uint8 MorphTarget4; - uint8 MorphTarget5; - uint8 MorphTarget6; - uint8 MorphTarget7; - uint8 MorphTarget8; - uint8 EyesColor; - uint8 Tattoo; - uint8 NameStringId; - - bool _HairCuteDiscount ; - float _NextDeathPenaltyFactor; - - CStatsScanDeathPenalties _DeathPenalties; - CStatsScanPlayerRoom _PlayerRoom; - CStatsScanEntityBase EntityBase; - CStatsScanRespawnPoints RespawnPoints; - CStatsScanFameContainer _Fames; - CStatsScanCharaterEncyclopedia _EncycloChar; - CStatsScanGameEvent _GameEvent; - - std::vector _BoughtPhrases; - std::vector _KnownBricks; - std::vector _FriendsList; - std::vector _IgnoreList; - std::vector _IsFriendOf; - std::vector _IsIgnoredBy; - - std::vector _Pact; - - std::map _MissionHistories; - std::map SkillPoints; - std::map SpentSkillPoints; - std::map ScorePermanentModifiers; - std::map StartingCharacteristicValues; - std::map Inventory; - std::map _PlayerPets; -}; - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef CHARACTER_H +#define CHARACTER_H + +//----------------------------------------------------------------------------- +// includes +//----------------------------------------------------------------------------- + +#include "nel/misc/sstring.h" +#include "game_share/persistent_data.h" + + +//----------------------------------------------------------------------------- +// Data types +//----------------------------------------------------------------------------- + +typedef uint32 TAIAlias; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanMissionHistory +//----------------------------------------------------------------------------- + +class CStatsScanMissionHistory +{ +public: + DECLARE_PERSISTENCE_METHODS + + bool Successfull; + NLMISC::TGameCycle LastSuccessDate; + + CStatsScanMissionHistory() + { + Successfull=false; + LastSuccessDate=0; + } +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanDeathPenalties +//----------------------------------------------------------------------------- + +class CStatsScanDeathPenalties +{ +public: + DECLARE_PERSISTENCE_METHODS + + CStatsScanDeathPenalties() + { + _NbDeath=0; + _CurrentDeathXP=0.0; + _DeathXPToGain=0.0; + _BonusUpdateTime=0; + } + + uint8 _NbDeath; + double _CurrentDeathXP; + double _DeathXPToGain; + uint32 _BonusUpdateTime; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanRespawnPoints +//----------------------------------------------------------------------------- + +class CStatsScanRespawnPoints +{ +public: + DECLARE_PERSISTENCE_METHODS + + std::vector RespawnPoints; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanFameContainerEntry +//----------------------------------------------------------------------------- + +class CStatsScanFameContainerEntry +{ +public: + DECLARE_PERSISTENCE_METHODS + + sint32 Fame; + sint32 FameMemory; + std::string LastFameChangeTrend; + + CStatsScanFameContainerEntry() + { + Fame=0; + FameMemory=0; + } + +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanFameContainer +//----------------------------------------------------------------------------- + +class CStatsScanFameContainer +{ +public: + DECLARE_PERSISTENCE_METHODS + + std::map _Fame; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanEncyCharThema +//----------------------------------------------------------------------------- + +class CStatsScanEncyCharThema +{ +public: + DECLARE_PERSISTENCE_METHODS + + uint8 ThemaState; + uint16 RiteTaskStatePacked; + + CStatsScanEncyCharThema() + { + ThemaState=0; + RiteTaskStatePacked=0; + } +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanEncyCharAlbum +//----------------------------------------------------------------------------- + +class CStatsScanEncyCharAlbum +{ +public: + DECLARE_PERSISTENCE_METHODS + + uint8 AlbumState; + std::vector Themas; + + CStatsScanEncyCharAlbum() + { + AlbumState=0; + } +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanCharaterEncyclopedia +//----------------------------------------------------------------------------- + +class CStatsScanCharaterEncyclopedia +{ +public: + DECLARE_PERSISTENCE_METHODS + + std::vector _EncyCharAlbums; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanGameEvent +//----------------------------------------------------------------------------- + +class CStatsScanGameEvent +{ +public: + DECLARE_PERSISTENCE_METHODS + + CStatsScanGameEvent() + { + _Date=0; + } + + uint32 _Date; + std::string _EventFaction; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanPact +//----------------------------------------------------------------------------- + +class CStatsScanPact +{ +public: + DECLARE_PERSISTENCE_METHODS + + CStatsScanPact() + { + PactNature=0; + PactType=0; + } + + uint8 PactNature; + uint8 PactType; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanPetAnimal +//----------------------------------------------------------------------------- + +class CStatsScanPetAnimal +{ +public: + DECLARE_PERSISTENCE_METHODS + + NLMISC::CSheetId TicketPetSheetId; + NLMISC::CSheetId PetSheetId; + uint32 Price; + NLMISC::CEntityId OwnerId; + TAIAlias StableAlias; + sint32 Landscape_X; + sint32 Landscape_Y; + sint32 Landscape_Z; + uint32 DeathTick; + uint16 PetStatus; + sint16 Slot; + bool IsFollowing; + bool IsMounted; + bool IsTpAllowed; + + CStatsScanPetAnimal() + { + Price=0; + StableAlias=0; + Landscape_X=0; + Landscape_Y=0; + Landscape_Z=0; + DeathTick=0; + PetStatus=0; + Slot=0; + IsFollowing=false; + IsMounted=false; + IsTpAllowed=false; + } +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanPhysCharacs +//----------------------------------------------------------------------------- + +class CStatsScanPhysCharacs +{ +public: + DECLARE_PERSISTENCE_METHODS + + std::map _PhysicalCharacteristics; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanPhysScoresEntry +//----------------------------------------------------------------------------- + +class CStatsScanPhysScoresEntry +{ +public: + DECLARE_PERSISTENCE_METHODS + + CStatsScanPhysScoresEntry() + { + Current=0; + Base=0; + Max=0; + BaseRegenerateRepos=0.0f; + BaseRegenerateAction=0.0f; + CurrentRegenerate=0.0f; + } + + sint32 Current; + sint32 Base; + sint32 Max; + float BaseRegenerateRepos; + float BaseRegenerateAction; + float CurrentRegenerate; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanPhysScores +//----------------------------------------------------------------------------- + +class CStatsScanPhysScores +{ +public: + DECLARE_PERSISTENCE_METHODS + + CStatsScanPhysScores() + { + BaseWalkSpeed=0.0f; + BaseRunSpeed=0.0f; + CurrentWalkSpeed=0.0f; + CurrentRunSpeed=0.0f; + } + + float BaseWalkSpeed; + float BaseRunSpeed; + float CurrentWalkSpeed; + float CurrentRunSpeed; + std::map PhysicalScores; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanSkillsEntry +//----------------------------------------------------------------------------- + +class CStatsScanSkillsEntry +{ +public: + DECLARE_PERSISTENCE_METHODS + + CStatsScanSkillsEntry() + { + Base=0; + Current=0; + MaxLvlReached=0; + Xp=0.0; + XpNextLvl=0.0; + } + + sint32 Base; + sint32 Current; + sint32 MaxLvlReached; + double Xp; + double XpNextLvl; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanSkills +//----------------------------------------------------------------------------- + +class CStatsScanSkills +{ +public: + DECLARE_PERSISTENCE_METHODS + + std::map Skills; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanItemCraftParameters +//----------------------------------------------------------------------------- + +class CStatsScanItemCraftParameters +{ +public: + DECLARE_PERSISTENCE_METHODS + + CStatsScanItemCraftParameters() + { + Durability=0.0f; + Weight=0.0f; + SapLoad=0.0f; + StatEnergy=0.0f; + Dmg=0.0f; + Speed=0.0f; + Range=0.0f; + DodgeModifier=0.0f; + ParryModifier=0.0f; + AdversaryDodgeModifier=0.0f; + AdversaryParryModifier=0.0f; + ProtectionFactor=0.0f; + MaxSlashingProtection=0.0f; + MaxBluntProtection=0.0f; + MaxPiercingProtection=0.0f; + ElementalCastingTimeFactor=0.0f; + ElementalPowerFactor=0.0f; + OffensiveAfflictionCastingTimeFactor=0.0f; + OffensiveAfflictionPowerFactor=0.0f; + HealCastingTimeFactor=0.0f; + HealPowerFactor=0.0f; + DefensiveAfflictionCastingTimeFactor=0.0f; + DefensiveAfflictionPowerFactor=0.0f; + Color=0; + HpBuff=0; + SapBuff=0; + StaBuff=0; + FocusBuff=0; + } + + float Durability; + float Weight; + float SapLoad; + float StatEnergy; + float Dmg; + float Speed; + float Range; + float DodgeModifier; + float ParryModifier; + float AdversaryDodgeModifier; + float AdversaryParryModifier; + float ProtectionFactor; + float MaxSlashingProtection; + float MaxBluntProtection; + float MaxPiercingProtection; + float ElementalCastingTimeFactor; + float ElementalPowerFactor; + float OffensiveAfflictionCastingTimeFactor; + float OffensiveAfflictionPowerFactor; + float HealCastingTimeFactor; + float HealPowerFactor; + float DefensiveAfflictionCastingTimeFactor; + float DefensiveAfflictionPowerFactor; + uint8 Color; + sint32 HpBuff; + sint32 SapBuff; + sint32 StaBuff; + sint32 FocusBuff; + std::string Protection; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanItem +//----------------------------------------------------------------------------- + +class CStatsScanItem +{ +public: + DECLARE_PERSISTENCE_METHODS + + CStatsScanItem() + { + _ClientInventoryPosition=0; + _HP=0; + _Recommended=0; + _LocSlot=0; + _SlotImage=0; + _SlotCount=0; + _SapLoad=0; + _Dropable=true; + _Destroyable=true; + StackSize=0; + } + + NLMISC::CSheetId _SheetId; + sint16 _ClientInventoryPosition; + uint32 _HP; + uint32 _Recommended; + NLMISC::CEntityId _CreatorId; + uint8 _LocSlot; + std::string _PhraseId; + uint16 _SlotImage; + sint16 _SlotCount; + uint32 _SapLoad; + bool _Dropable; + bool _Destroyable; + uint32 StackSize; + CStatsScanItemCraftParameters _CraftParameters; + std::vector _Enchantment; + std::vector Child; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanInventory +//----------------------------------------------------------------------------- + +class CStatsScanInventory +{ +public: + DECLARE_PERSISTENCE_METHODS + + std::vector _Item; +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanPlayerRoom +//----------------------------------------------------------------------------- + +class CStatsScanPlayerRoom +{ +public: + DECLARE_PERSISTENCE_METHODS + + TAIAlias Building; + CStatsScanItem Inventory; + sint32 Bulk; + sint32 MaxBulk; + + CStatsScanPlayerRoom() + { + Building=0; + Bulk=0; + MaxBulk=0; + } +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanEntityPosition +//----------------------------------------------------------------------------- + +class CStatsScanEntityPosition +{ +public: + DECLARE_PERSISTENCE_METHODS + + sint32 X; + sint32 Y; + sint32 Z; + float Heading; + + CStatsScanEntityPosition() + { + X=0; + Y=0; + Z=0; + Heading=0.0f; + } +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanEntityBase +//----------------------------------------------------------------------------- + +class CStatsScanEntityBase +{ +public: + DECLARE_PERSISTENCE_METHODS + + CStatsScanEntityPosition _EntityPosition; + uint32 _SheetId; + std::string _Name; + std::string _Race; + uint8 _Gender; + uint8 _Size; + bool _DodgeAsDefense; + CStatsScanPhysCharacs _PhysCharacs; + CStatsScanPhysScores _PhysScores; + CStatsScanSkills _Skills; + + sint32 MeleeAttackModifierOnEnemy; + sint32 MeleeAttackModifierOnSelf; + sint32 MagicCastingModifierOnSelf; + sint32 MagicCastingModifierOnEnemy; + sint32 RangeAttackModifierOnEnemy; + sint32 RangeAttackModifierOnSelf; + sint32 AttackModifierOnSelf; + sint32 ChanceToFailStrategy; + sint32 ChanceToFailSpell; + sint32 ChanceToFailFaber; + sint32 ChanceToFailHarvest; + sint32 ChanceToFailTracking; + sint32 MeleeAttackSlow; + sint32 MeleeSlashingDamageArmor; + sint32 MeleeBluntDamageArmor; + sint32 MeleePiercingDamageArmor; + sint32 MeleeDamageModifierFactor; + sint32 RangeDamageModifierFactor; + sint32 CreatureMeleeTakenDamageFactor; + sint32 CreatureRangeTakenDamageFactor; + sint32 CombatBrickLatencyMultiplier; + sint32 MagicBrickLatencyMultiplier; + sint32 ArmorQualityModifier; + sint32 WeaponQualityModifier; + sint32 ArmorAbsorbtionMultiplier; + + CStatsScanEntityBase() + { + _DodgeAsDefense=false; + _SheetId=0; + _Gender=0; + _Size=0; + + MeleeAttackModifierOnEnemy=0; + MeleeAttackModifierOnSelf=0; + MagicCastingModifierOnSelf=0; + MagicCastingModifierOnEnemy=0; + RangeAttackModifierOnEnemy=0; + RangeAttackModifierOnSelf=0; + AttackModifierOnSelf=0; + ChanceToFailStrategy=0; + ChanceToFailSpell=0; + ChanceToFailFaber=0; + ChanceToFailHarvest=0; + ChanceToFailTracking=0; + MeleeAttackSlow=0; + MeleeSlashingDamageArmor=0; + MeleeBluntDamageArmor=0; + MeleePiercingDamageArmor=0; + MeleeDamageModifierFactor=0; + RangeDamageModifierFactor=0; + CreatureMeleeTakenDamageFactor=0; + CreatureRangeTakenDamageFactor=0; + CombatBrickLatencyMultiplier=0; + MagicBrickLatencyMultiplier=0; + ArmorQualityModifier=0; + WeaponQualityModifier=0; + ArmorAbsorbtionMultiplier=0; + } +}; + + +//----------------------------------------------------------------------------- +// Persistent data for CStatsScanCharacter +//----------------------------------------------------------------------------- + +class CStatsScanCharacter +{ +public: + DECLARE_PERSISTENCE_METHODS + + uint32 VERSION; + + uint8 _HairType; + uint8 _HairColor; + uint8 _HatColor; + uint8 _JacketColor; + uint8 _ArmsColor; + uint8 _TrousersColor; + uint8 _FeetColor; + uint8 _HandsColor; + uint64 _Money; + uint32 _GuildId; + bool _NewCharacter; + uint8 _CreationPointsRepartition; + uint32 _ForbidAuraUseEndDate; + std::string _Title; + + /* Visual Properties */ + uint8 HairType; + uint8 HairColor; + uint8 GabaritHeight; + uint8 GabaritTorsoWidth; + uint8 GabaritArmsWidth; + uint8 GabaritLegsWidth; + uint8 GabaritBreastSize; + uint8 MorphTarget1; + uint8 MorphTarget2; + uint8 MorphTarget3; + uint8 MorphTarget4; + uint8 MorphTarget5; + uint8 MorphTarget6; + uint8 MorphTarget7; + uint8 MorphTarget8; + uint8 EyesColor; + uint8 Tattoo; + uint8 NameStringId; + + bool _HairCuteDiscount ; + float _NextDeathPenaltyFactor; + + CStatsScanDeathPenalties _DeathPenalties; + CStatsScanPlayerRoom _PlayerRoom; + CStatsScanEntityBase EntityBase; + CStatsScanRespawnPoints RespawnPoints; + CStatsScanFameContainer _Fames; + CStatsScanCharaterEncyclopedia _EncycloChar; + CStatsScanGameEvent _GameEvent; + + std::vector _BoughtPhrases; + std::vector _KnownBricks; + std::vector _FriendsList; + std::vector _IgnoreList; + std::vector _IsFriendOf; + std::vector _IsIgnoredBy; + + std::vector _Pact; + + std::map _MissionHistories; + std::map SkillPoints; + std::map SpentSkillPoints; + std::map ScorePermanentModifiers; + std::map StartingCharacteristicValues; + std::map Inventory; + std::map _PlayerPets; +}; + + #endif \ No newline at end of file diff --git a/code/ryzom/tools/stats_scan/character_scan_job.cpp b/code/ryzom/tools/stats_scan/character_scan_job.cpp index fc5a3cb01..be0b785b4 100644 --- a/code/ryzom/tools/stats_scan/character_scan_job.cpp +++ b/code/ryzom/tools/stats_scan/character_scan_job.cpp @@ -1,283 +1,283 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -//------------------------------------------------------------------------------------------------- -// includes -//------------------------------------------------------------------------------------------------- - -#include "nel/misc/variable.h" -#include "nel/misc/path.h" - -#include "game_share/persistent_data.h" - -#include "character_scan_job.h" -#include "character.h" - - -//------------------------------------------------------------------------------------------------- -// Variables -//------------------------------------------------------------------------------------------------- - -extern NLMISC::CVariable OutputDirectory; - - -//------------------------------------------------------------------------------------------------- -// methods CCharacterScanJob -//------------------------------------------------------------------------------------------------- - -CCharacterScanJob::CCharacterScanJob() -{ - // start by initialising simple properties - _CharTblFile=NULL; - _NextFile=0; - _State=INIT; - - // setup the special reserved table columns 'account' and 'accountSlot' - charTblAddCol("account"); - charTblAddCol("accountSlot"); - - // open the output file for the character table - std::string filename= "char_tbl.csv"; - _CharTblFile=fopen(filename.c_str(),"wb"); - if (_CharTblFile==NULL) - { - nlwarning("Failed to open output file: %s",filename.c_str()); - _State=ERROR; - } -} - -CCharacterScanJob::~CCharacterScanJob() -{ - if (_State!=ERROR) - _State=CLOSED; - - if (_CharTblFile!=NULL) - fclose(_CharTblFile); - - // flush the stats maps to their respective output files - for (TCharStatsMap::iterator it=_CharStatsMap.begin();it!=_CharStatsMap.end();++it) - { - // create the output file name and open the file for writing - std::string filename="char_stats_"+(*it).first+".csv"; - FILE* f=fopen(filename.c_str(),"wb"); - if (f==NULL) - { - nlwarning("Failed to open output file: %s",filename.c_str()); - continue; - } - - // dump data to the file - for (TCharStatsMapTbl::iterator it2=it->second.begin();it2!=it->second.end();++it2) - { - fprintf(f,"%s,%d,\n",it2->first.c_str(),it2->second); - } - - // the writing is finished so close the file - fclose(f); - } -} - -void CCharacterScanJob::update() -{ - if (_NextFile>=_Files.size()) - return; - - // load the file into a pdr record - static CPersistentDataRecord pdr; - pdr.clear(); - pdr.readFromFile(_Files[_NextFile].c_str()); - ++_NextFile; - - // create a character representation and apply the pdr - CStatsScanCharacter c; - c.apply(pdr); - - // iterate over the info extractors executing their core code - for (uint32 i=0;i<_InfoExtractors.size();++i) - { - _InfoExtractors[i]->execute(this,&c); - } - - // flush the info collected by the info extractors to the output file - charTblFlushRow(123,456); -} - -bool CCharacterScanJob::charTblAddCol(const std::string& name) -{ - nlassert(_State==INIT); - - // make sure the col doesn't already exist in the table - for (uint32 i=0;i<_TblCols.size();++i) - { - nlassert(_TblCols[i]!=name); - } - - // add the colt ot he table - _TblCols.push_back(name); - - return true; -} - -bool CCharacterScanJob::addInfoExtractor(ICharInfoExtractor* infoExtractor) -{ - // make sure this info extractor doesn't already exist - for (uint32 i=0;i<_InfoExtractors.size();++i) - { - if(_InfoExtractors[i]->toString()== infoExtractor->toString()) - { - nlwarning("Attempt to add info extractor to the same job more than once: %s",infoExtractor->toString().c_str()); - return false; - } - } - - // append the new info extractor to the buffer - _InfoExtractors.push_back(infoExtractor); - - return true; -} - -bool CCharacterScanJob::addFilter(ICharFilter* filter) -{ - // make sure this info extractor doesn't already exist - for (uint32 i=0;i<_Filters.size();++i) - { - if(_Filters[i]->toString()== filter->toString()) - { - nlwarning("Attempt to add filter to the same job more than once: %s",filter->toString().c_str()); - return false; - } - } - - // append the new info extractor to the buffer - _Filters.push_back(filter); - - return true; -} - -bool CCharacterScanJob::addFiles(const CFileDescriptionContainer& fdc) -{ - for (uint32 i=0;i= _Files.size(); -} - -std::string CCharacterScanJob::getShortStatus() -{ - return NLMISC::toString("CharacterFiles %d/%d",_NextFile,_Files.size()); -} - -std::string CCharacterScanJob::getStatus() -{ - return getShortStatus(); -} - -void CCharacterScanJob::display(NLMISC::CLog* log) -{ - log->displayNL("%s",getStatus().c_str()); - for (uint32 i=0;i<_InfoExtractors.size();++i) - { - log->displayNL("- %s",_InfoExtractors[i]->toString().c_str()); - } -} - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +//------------------------------------------------------------------------------------------------- +// includes +//------------------------------------------------------------------------------------------------- + +#include "nel/misc/variable.h" +#include "nel/misc/path.h" + +#include "game_share/persistent_data.h" + +#include "character_scan_job.h" +#include "character.h" + + +//------------------------------------------------------------------------------------------------- +// Variables +//------------------------------------------------------------------------------------------------- + +extern NLMISC::CVariable OutputDirectory; + + +//------------------------------------------------------------------------------------------------- +// methods CCharacterScanJob +//------------------------------------------------------------------------------------------------- + +CCharacterScanJob::CCharacterScanJob() +{ + // start by initialising simple properties + _CharTblFile=NULL; + _NextFile=0; + _State=INIT; + + // setup the special reserved table columns 'account' and 'accountSlot' + charTblAddCol("account"); + charTblAddCol("accountSlot"); + + // open the output file for the character table + std::string filename= "char_tbl.csv"; + _CharTblFile=fopen(filename.c_str(),"wb"); + if (_CharTblFile==NULL) + { + nlwarning("Failed to open output file: %s",filename.c_str()); + _State=ERROR; + } +} + +CCharacterScanJob::~CCharacterScanJob() +{ + if (_State!=ERROR) + _State=CLOSED; + + if (_CharTblFile!=NULL) + fclose(_CharTblFile); + + // flush the stats maps to their respective output files + for (TCharStatsMap::iterator it=_CharStatsMap.begin();it!=_CharStatsMap.end();++it) + { + // create the output file name and open the file for writing + std::string filename="char_stats_"+(*it).first+".csv"; + FILE* f=fopen(filename.c_str(),"wb"); + if (f==NULL) + { + nlwarning("Failed to open output file: %s",filename.c_str()); + continue; + } + + // dump data to the file + for (TCharStatsMapTbl::iterator it2=it->second.begin();it2!=it->second.end();++it2) + { + fprintf(f,"%s,%d,\n",it2->first.c_str(),it2->second); + } + + // the writing is finished so close the file + fclose(f); + } +} + +void CCharacterScanJob::update() +{ + if (_NextFile>=_Files.size()) + return; + + // load the file into a pdr record + static CPersistentDataRecord pdr; + pdr.clear(); + pdr.readFromFile(_Files[_NextFile].c_str()); + ++_NextFile; + + // create a character representation and apply the pdr + CStatsScanCharacter c; + c.apply(pdr); + + // iterate over the info extractors executing their core code + for (uint32 i=0;i<_InfoExtractors.size();++i) + { + _InfoExtractors[i]->execute(this,&c); + } + + // flush the info collected by the info extractors to the output file + charTblFlushRow(123,456); +} + +bool CCharacterScanJob::charTblAddCol(const std::string& name) +{ + nlassert(_State==INIT); + + // make sure the col doesn't already exist in the table + for (uint32 i=0;i<_TblCols.size();++i) + { + nlassert(_TblCols[i]!=name); + } + + // add the colt ot he table + _TblCols.push_back(name); + + return true; +} + +bool CCharacterScanJob::addInfoExtractor(ICharInfoExtractor* infoExtractor) +{ + // make sure this info extractor doesn't already exist + for (uint32 i=0;i<_InfoExtractors.size();++i) + { + if(_InfoExtractors[i]->toString()== infoExtractor->toString()) + { + nlwarning("Attempt to add info extractor to the same job more than once: %s",infoExtractor->toString().c_str()); + return false; + } + } + + // append the new info extractor to the buffer + _InfoExtractors.push_back(infoExtractor); + + return true; +} + +bool CCharacterScanJob::addFilter(ICharFilter* filter) +{ + // make sure this info extractor doesn't already exist + for (uint32 i=0;i<_Filters.size();++i) + { + if(_Filters[i]->toString()== filter->toString()) + { + nlwarning("Attempt to add filter to the same job more than once: %s",filter->toString().c_str()); + return false; + } + } + + // append the new info extractor to the buffer + _Filters.push_back(filter); + + return true; +} + +bool CCharacterScanJob::addFiles(const CFileDescriptionContainer& fdc) +{ + for (uint32 i=0;i= _Files.size(); +} + +std::string CCharacterScanJob::getShortStatus() +{ + return NLMISC::toString("CharacterFiles %d/%d",_NextFile,_Files.size()); +} + +std::string CCharacterScanJob::getStatus() +{ + return getShortStatus(); +} + +void CCharacterScanJob::display(NLMISC::CLog* log) +{ + log->displayNL("%s",getStatus().c_str()); + for (uint32 i=0;i<_InfoExtractors.size();++i) + { + log->displayNL("- %s",_InfoExtractors[i]->toString().c_str()); + } +} + + diff --git a/code/ryzom/tools/stats_scan/character_scan_job.h b/code/ryzom/tools/stats_scan/character_scan_job.h index e2692fcb7..925076114 100644 --- a/code/ryzom/tools/stats_scan/character_scan_job.h +++ b/code/ryzom/tools/stats_scan/character_scan_job.h @@ -1,95 +1,95 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CHARACTER_SCAN_JOB_H -#define CHARACTER_SCAN_JOB_H - -//------------------------------------------------------------------------------------------------- -// includes -//------------------------------------------------------------------------------------------------- - -#include "stdio.h" - -#include "game_share/file_description_container.h" - -#include "job_manager.h" -#include "char_info_extractor_factory.h" -#include "char_filter_factory.h" - - -//------------------------------------------------------------------------------------------------- -// class CCharacterScanJob -//------------------------------------------------------------------------------------------------- - -class CCharacterScanJob: public CJobManager::IJob -{ -public: - // inherited virtual interface - virtual bool finished(); - virtual std::string getShortStatus(); - virtual std::string getStatus(); - virtual void display(NLMISC::CLog* log=NLMISC::InfoLog); - virtual void update(); - -public: - CCharacterScanJob(); - ~CCharacterScanJob(); - -public: - // interface for initialisation and configuration of the job - bool charTblAddCol(const std::string& name); - bool addInfoExtractor(ICharInfoExtractor* infoExtractor); - bool addFilter(ICharFilter* filter); - bool addFiles(const CFileDescriptionContainer& fdc); - bool setOutputPath(const std::string& path); - - // interface for the InfoExtractors to use - void charTblSetEntry(const std::string& colName,const std::string& value); - void charTblFlushRow(uint32 account,uint32 slot); - void freqTblAddEntry(const std::string& tblName, const std::string& key); - -private: - typedef std::vector > TInfoExtractors; - TInfoExtractors _InfoExtractors; - - typedef std::vector > TFilters; - TFilters _Filters; - - typedef std::vector TFiles; - TFiles _Files; - - typedef std::map TCharStatsMapTbl; - typedef std::map TCharStatsMap; - TCharStatsMap _CharStatsMap; - - typedef std::vector TTblCols; - TTblCols _TblCols; - - typedef std::map TCurrentRowEntries; - TCurrentRowEntries _CurrentRowEntries; - - typedef enum { INIT, WORK, CLOSED, ERROR } TState; - TState _State; - - std::string _OutputPath; - - FILE* _CharTblFile; - uint32 _NextFile; -}; - - -//------------------------------------------------------------------------------------------------- +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CHARACTER_SCAN_JOB_H +#define CHARACTER_SCAN_JOB_H + +//------------------------------------------------------------------------------------------------- +// includes +//------------------------------------------------------------------------------------------------- + +#include "stdio.h" + +#include "game_share/file_description_container.h" + +#include "job_manager.h" +#include "char_info_extractor_factory.h" +#include "char_filter_factory.h" + + +//------------------------------------------------------------------------------------------------- +// class CCharacterScanJob +//------------------------------------------------------------------------------------------------- + +class CCharacterScanJob: public CJobManager::IJob +{ +public: + // inherited virtual interface + virtual bool finished(); + virtual std::string getShortStatus(); + virtual std::string getStatus(); + virtual void display(NLMISC::CLog* log=NLMISC::InfoLog); + virtual void update(); + +public: + CCharacterScanJob(); + ~CCharacterScanJob(); + +public: + // interface for initialisation and configuration of the job + bool charTblAddCol(const std::string& name); + bool addInfoExtractor(ICharInfoExtractor* infoExtractor); + bool addFilter(ICharFilter* filter); + bool addFiles(const CFileDescriptionContainer& fdc); + bool setOutputPath(const std::string& path); + + // interface for the InfoExtractors to use + void charTblSetEntry(const std::string& colName,const std::string& value); + void charTblFlushRow(uint32 account,uint32 slot); + void freqTblAddEntry(const std::string& tblName, const std::string& key); + +private: + typedef std::vector > TInfoExtractors; + TInfoExtractors _InfoExtractors; + + typedef std::vector > TFilters; + TFilters _Filters; + + typedef std::vector TFiles; + TFiles _Files; + + typedef std::map TCharStatsMapTbl; + typedef std::map TCharStatsMap; + TCharStatsMap _CharStatsMap; + + typedef std::vector TTblCols; + TTblCols _TblCols; + + typedef std::map TCurrentRowEntries; + TCurrentRowEntries _CurrentRowEntries; + + typedef enum { INIT, WORK, CLOSED, ERROR } TState; + TState _State; + + std::string _OutputPath; + + FILE* _CharTblFile; + uint32 _NextFile; +}; + + +//------------------------------------------------------------------------------------------------- #endif \ No newline at end of file diff --git a/code/ryzom/tools/stats_scan/job_manager.cpp b/code/ryzom/tools/stats_scan/job_manager.cpp index f1fa8bf91..dbaaad2b4 100644 --- a/code/ryzom/tools/stats_scan/job_manager.cpp +++ b/code/ryzom/tools/stats_scan/job_manager.cpp @@ -1,179 +1,179 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "job_manager.h" - -class CFinishedJob: public CJobManager::IJob -{ -public: - bool finished() { return true; } - std::string getShortStatus() { return _ShortStatus; } - std::string getStatus() { return _Status; } - void display(NLMISC::CLog* log=NLMISC::InfoLog) { log->displayNL("%s",_Status.c_str()); } - void update() {} - - CFinishedJob(CJobManager::IJob* theFinishedJob) - { - if (theFinishedJob==NULL) - return; - _Status=theFinishedJob->getStatus(); - _ShortStatus=theFinishedJob->getShortStatus(); - } - -private: - std::string _Status; - std::string _ShortStatus; - -}; - -CJobManager* CJobManager::getInstance() -{ - static CJobManager* mgr=NULL; - if (mgr==NULL) - { - mgr=new CJobManager; - } - return mgr; -} - -CJobManager::CJobManager() -{ - _Paused=false; - _JobUpdatesPerUpdate=1; -} - -void CJobManager::serviceUpdate() -{ - if (_Paused) - return; - - for (uint32 count=0;count<_JobUpdatesPerUpdate &&!_UnfinishedJobs.empty();++count) - { - nlassert(_UnfinishedJobs.front()<_Jobs.size()); - NLMISC::CSmartPtr& theJob= _Jobs[_UnfinishedJobs.front()]; - if (theJob->finished()) - { - // delete the job and replace it with a light weight 'finished job' marker - theJob= new CFinishedJob(theJob); - - // remove this job from the list of unfinished jobs - _UnfinishedJobs.pop_front(); - - // decrement the updates counter to counteract the auto incrment - --count; - } - else - { - theJob->update(); - } - } -} - - -uint32 CJobManager::addJob(NLMISC::CSmartPtr job) -{ - nlassert(job!=NULL); - uint32 id= (uint32)_Jobs.size(); - _UnfinishedJobs.push_back(id); - _Jobs.push_back(job); - return id; -} - -void CJobManager::promoteJob(uint32 idx) -{ - TUnfinishedJobs::iterator it; - for (it=_UnfinishedJobs.begin(); it!=_UnfinishedJobs.end(); ++it) - { - if (*it==idx) - { - _UnfinishedJobs.erase(it); - _UnfinishedJobs.push_front(idx); - return; - } - } - nlwarning("Failed to promote job with ID %d as not found in unfinished jobs list",idx); -} - -void CJobManager::pause() -{ - _Paused= true; -} - -void CJobManager::resume() -{ - _Paused= false; -} - -void CJobManager::setJobUpdatesPerUpdate(uint32 count) -{ - _JobUpdatesPerUpdate= count; - if (count==0 || count>100) - nlwarning("Suspicious value of JobUpdatesPerUpdate: %d",count); -} - -uint32 CJobManager::getJobUpdatesPerUpdate() -{ - return _JobUpdatesPerUpdate; -} - -std::string CJobManager::getStatus() -{ - std::string result; - - if (_Paused) result+="[Paused] "; - - if (!_UnfinishedJobs.empty()) - { - uint32 idx=_UnfinishedJobs.front(); - nlassert(idx<_Jobs.size()); - result+=_Jobs[idx]->getStatus(); - } - - result+=NLMISC::toString(" [Updates per cycle: %d]",_JobUpdatesPerUpdate); - - return result; -} - -void CJobManager::listJobs(NLMISC::CLog* log) -{ - for (uint32 i=0;i< _Jobs.size(); ++i) - { - if (!_Jobs[i]->finished()) - nlinfo("%4d*: %s",i,_Jobs[i]->getStatus().c_str()); - } - nlinfo("%d unfinished jobs (%d in total)",_UnfinishedJobs.size(),_Jobs.size()); -} - -void CJobManager::listJobHistory(NLMISC::CLog* log) -{ - for (uint32 i=0;i< _Jobs.size(); ++i) - { - nlinfo("%4d%c: %s",i,_Jobs[i]->finished()? ' ': '*',_Jobs[i]->getStatus().c_str()); - } - nlinfo("%d unfinished jobs (%d in total)",_UnfinishedJobs.size(),_Jobs.size()); -} - -void CJobManager::displayCurrentJob(NLMISC::CLog* log) -{ - if (!_UnfinishedJobs.empty()) - displayJob(_UnfinishedJobs.front(),log); -} - -void CJobManager::displayJob(uint32 jobId,NLMISC::CLog* log) -{ - nlassert(jobId<_Jobs.size()); - _Jobs[jobId]->display(log); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "job_manager.h" + +class CFinishedJob: public CJobManager::IJob +{ +public: + bool finished() { return true; } + std::string getShortStatus() { return _ShortStatus; } + std::string getStatus() { return _Status; } + void display(NLMISC::CLog* log=NLMISC::InfoLog) { log->displayNL("%s",_Status.c_str()); } + void update() {} + + CFinishedJob(CJobManager::IJob* theFinishedJob) + { + if (theFinishedJob==NULL) + return; + _Status=theFinishedJob->getStatus(); + _ShortStatus=theFinishedJob->getShortStatus(); + } + +private: + std::string _Status; + std::string _ShortStatus; + +}; + +CJobManager* CJobManager::getInstance() +{ + static CJobManager* mgr=NULL; + if (mgr==NULL) + { + mgr=new CJobManager; + } + return mgr; +} + +CJobManager::CJobManager() +{ + _Paused=false; + _JobUpdatesPerUpdate=1; +} + +void CJobManager::serviceUpdate() +{ + if (_Paused) + return; + + for (uint32 count=0;count<_JobUpdatesPerUpdate &&!_UnfinishedJobs.empty();++count) + { + nlassert(_UnfinishedJobs.front()<_Jobs.size()); + NLMISC::CSmartPtr& theJob= _Jobs[_UnfinishedJobs.front()]; + if (theJob->finished()) + { + // delete the job and replace it with a light weight 'finished job' marker + theJob= new CFinishedJob(theJob); + + // remove this job from the list of unfinished jobs + _UnfinishedJobs.pop_front(); + + // decrement the updates counter to counteract the auto incrment + --count; + } + else + { + theJob->update(); + } + } +} + + +uint32 CJobManager::addJob(NLMISC::CSmartPtr job) +{ + nlassert(job!=NULL); + uint32 id= (uint32)_Jobs.size(); + _UnfinishedJobs.push_back(id); + _Jobs.push_back(job); + return id; +} + +void CJobManager::promoteJob(uint32 idx) +{ + TUnfinishedJobs::iterator it; + for (it=_UnfinishedJobs.begin(); it!=_UnfinishedJobs.end(); ++it) + { + if (*it==idx) + { + _UnfinishedJobs.erase(it); + _UnfinishedJobs.push_front(idx); + return; + } + } + nlwarning("Failed to promote job with ID %d as not found in unfinished jobs list",idx); +} + +void CJobManager::pause() +{ + _Paused= true; +} + +void CJobManager::resume() +{ + _Paused= false; +} + +void CJobManager::setJobUpdatesPerUpdate(uint32 count) +{ + _JobUpdatesPerUpdate= count; + if (count==0 || count>100) + nlwarning("Suspicious value of JobUpdatesPerUpdate: %d",count); +} + +uint32 CJobManager::getJobUpdatesPerUpdate() +{ + return _JobUpdatesPerUpdate; +} + +std::string CJobManager::getStatus() +{ + std::string result; + + if (_Paused) result+="[Paused] "; + + if (!_UnfinishedJobs.empty()) + { + uint32 idx=_UnfinishedJobs.front(); + nlassert(idx<_Jobs.size()); + result+=_Jobs[idx]->getStatus(); + } + + result+=NLMISC::toString(" [Updates per cycle: %d]",_JobUpdatesPerUpdate); + + return result; +} + +void CJobManager::listJobs(NLMISC::CLog* log) +{ + for (uint32 i=0;i< _Jobs.size(); ++i) + { + if (!_Jobs[i]->finished()) + nlinfo("%4d*: %s",i,_Jobs[i]->getStatus().c_str()); + } + nlinfo("%d unfinished jobs (%d in total)",_UnfinishedJobs.size(),_Jobs.size()); +} + +void CJobManager::listJobHistory(NLMISC::CLog* log) +{ + for (uint32 i=0;i< _Jobs.size(); ++i) + { + nlinfo("%4d%c: %s",i,_Jobs[i]->finished()? ' ': '*',_Jobs[i]->getStatus().c_str()); + } + nlinfo("%d unfinished jobs (%d in total)",_UnfinishedJobs.size(),_Jobs.size()); +} + +void CJobManager::displayCurrentJob(NLMISC::CLog* log) +{ + if (!_UnfinishedJobs.empty()) + displayJob(_UnfinishedJobs.front(),log); +} + +void CJobManager::displayJob(uint32 jobId,NLMISC::CLog* log) +{ + nlassert(jobId<_Jobs.size()); + _Jobs[jobId]->display(log); +} diff --git a/code/ryzom/tools/stats_scan/job_manager.h b/code/ryzom/tools/stats_scan/job_manager.h index a318cffdc..67b7f7335 100644 --- a/code/ryzom/tools/stats_scan/job_manager.h +++ b/code/ryzom/tools/stats_scan/job_manager.h @@ -1,100 +1,100 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef JOB_MANAGER_H -#define JOB_MANAGER_H - -#include "nel/misc/types_nl.h" -#include "nel/misc/debug.h" -#include "nel/misc/smart_ptr.h" -#include "game_share/singleton_registry.h" - -class CJobManager: public IServiceSingleton -{ -public: - static CJobManager* getInstance(); - -public: - class IJob: public NLMISC::CRefCount - { - public: - // virtual dtor - virtual ~IJob() {} - - // return true if the job is finished -> the job object can be deleted - virtual bool finished()=0; - - // return a status string that can be displayed in an update variable - virtual std::string getShortStatus()=0; - - // get a detailed status string for display in a job list etc - virtual std::string getStatus()=0; - - // display the details of the job... eg the list of files being processed with related info - virtual void display(NLMISC::CLog* log=NLMISC::InfoLog)=0; - - // run the job's update to do a bit of work - virtual void update()=0; - }; - -public: - // add a job to the job vector and assign it a new id - uint32 addJob(NLMISC::CSmartPtr job); - - // move a job to the front of the queue - treat it as the active job - void promoteJob(uint32 idx); - - // the update method used to call job updates - void serviceUpdate(); - - // do nothing during the service updates until 'resume()' - void pause(); - - // resume after a 'pause()' - void resume(); - - // accessors for the number of job updates per call to serviceUpdate() - void setJobUpdatesPerUpdate(uint32 count); - uint32 getJobUpdatesPerUpdate(); - - // get the 'pause'/'resume' state, the number of jobsUpdatesPerUpdate and the status of the active job - std::string getStatus(); - - // list the status of all jobs that are not finished - void listJobs(NLMISC::CLog* log=NLMISC::InfoLog); - - // list the status of all jobs including those that are finished - void listJobHistory(NLMISC::CLog* log=NLMISC::InfoLog); - - // call the currently active job's 'display' method - void displayCurrentJob(NLMISC::CLog* log=NLMISC::InfoLog); - - // call the given job's 'display' method - void displayJob(uint32 jobId,NLMISC::CLog* log=NLMISC::InfoLog); - -private: - CJobManager(); - - typedef std::list TUnfinishedJobs; - typedef std::vector > TJobs; - - bool _Paused; - uint32 _JobUpdatesPerUpdate; - TJobs _Jobs; - TUnfinishedJobs _UnfinishedJobs; -}; - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef JOB_MANAGER_H +#define JOB_MANAGER_H + +#include "nel/misc/types_nl.h" +#include "nel/misc/debug.h" +#include "nel/misc/smart_ptr.h" +#include "game_share/singleton_registry.h" + +class CJobManager: public IServiceSingleton +{ +public: + static CJobManager* getInstance(); + +public: + class IJob: public NLMISC::CRefCount + { + public: + // virtual dtor + virtual ~IJob() {} + + // return true if the job is finished -> the job object can be deleted + virtual bool finished()=0; + + // return a status string that can be displayed in an update variable + virtual std::string getShortStatus()=0; + + // get a detailed status string for display in a job list etc + virtual std::string getStatus()=0; + + // display the details of the job... eg the list of files being processed with related info + virtual void display(NLMISC::CLog* log=NLMISC::InfoLog)=0; + + // run the job's update to do a bit of work + virtual void update()=0; + }; + +public: + // add a job to the job vector and assign it a new id + uint32 addJob(NLMISC::CSmartPtr job); + + // move a job to the front of the queue - treat it as the active job + void promoteJob(uint32 idx); + + // the update method used to call job updates + void serviceUpdate(); + + // do nothing during the service updates until 'resume()' + void pause(); + + // resume after a 'pause()' + void resume(); + + // accessors for the number of job updates per call to serviceUpdate() + void setJobUpdatesPerUpdate(uint32 count); + uint32 getJobUpdatesPerUpdate(); + + // get the 'pause'/'resume' state, the number of jobsUpdatesPerUpdate and the status of the active job + std::string getStatus(); + + // list the status of all jobs that are not finished + void listJobs(NLMISC::CLog* log=NLMISC::InfoLog); + + // list the status of all jobs including those that are finished + void listJobHistory(NLMISC::CLog* log=NLMISC::InfoLog); + + // call the currently active job's 'display' method + void displayCurrentJob(NLMISC::CLog* log=NLMISC::InfoLog); + + // call the given job's 'display' method + void displayJob(uint32 jobId,NLMISC::CLog* log=NLMISC::InfoLog); + +private: + CJobManager(); + + typedef std::list TUnfinishedJobs; + typedef std::vector > TJobs; + + bool _Paused; + uint32 _JobUpdatesPerUpdate; + TJobs _Jobs; + TUnfinishedJobs _UnfinishedJobs; +}; + #endif \ No newline at end of file diff --git a/code/ryzom/tools/stats_scan/service_main.cpp b/code/ryzom/tools/stats_scan/service_main.cpp index 40e4c3611..ec4a1d30d 100644 --- a/code/ryzom/tools/stats_scan/service_main.cpp +++ b/code/ryzom/tools/stats_scan/service_main.cpp @@ -1,94 +1,94 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/misc/types_nl.h" -#include "nel/misc/time_nl.h" -#include "nel/misc/common.h" -#include "nel/misc/sheet_id.h" - -#include "nel/net/service.h" - -#include "game_share/ryzom_version.h" -#include "game_share/tick_event_handler.h" -#include "game_share/singleton_registry.h" - -#ifdef NL_OS_WINDOWS -# define NOMINMAX -# include -#endif // NL_OS_WINDOWS - -using namespace std; -using namespace NLMISC; -using namespace NLNET; - - -/** - * CStatsScanServiceSingleton - */ -class CStatsScanServiceSingleton : public NLNET::IService -{ -public : - - /* - * Initialise the service - */ - void init() - { - setVersion (RYZOM_VERSION); - - // initialise sheet id file - CSheetId::init(false); - - // if we are connecting to a shard then start by initializing the tick interface - if (IService::getInstance()->ConfigFile.getVarPtr("DontUseTS")==NULL || IService::getInstance()->ConfigFile.getVarPtr("DontUseTS")->asInt()==0) - CTickEventHandler::init(CStatsScanServiceSingleton::tickUpdate); - - CSingletonRegistry::getInstance()->init(); - } - - /* - * Service Update - */ - bool update() - { - CSingletonRegistry::getInstance()->serviceUpdate(); - return true; - } - - /* - * Tick Update - */ - static void tickUpdate() - { - CSingletonRegistry::getInstance()->tickUpdate(); - } - - /* - * Release - */ - void release() - { - CSingletonRegistry::getInstance()->release(); - } - -}; - - -//----------------------------------------------- -// NLNET_SERVICE_MAIN -//----------------------------------------------- -NLNET_SERVICE_MAIN( CStatsScanServiceSingleton, "stats_scan", "stats_scan_service", 0, EmptyCallbackArray, "", "" ); - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/misc/types_nl.h" +#include "nel/misc/time_nl.h" +#include "nel/misc/common.h" +#include "nel/misc/sheet_id.h" + +#include "nel/net/service.h" + +#include "game_share/ryzom_version.h" +#include "game_share/tick_event_handler.h" +#include "game_share/singleton_registry.h" + +#ifdef NL_OS_WINDOWS +# define NOMINMAX +# include +#endif // NL_OS_WINDOWS + +using namespace std; +using namespace NLMISC; +using namespace NLNET; + + +/** + * CStatsScanServiceSingleton + */ +class CStatsScanServiceSingleton : public NLNET::IService +{ +public : + + /* + * Initialise the service + */ + void init() + { + setVersion (RYZOM_VERSION); + + // initialise sheet id file + CSheetId::init(false); + + // if we are connecting to a shard then start by initializing the tick interface + if (IService::getInstance()->ConfigFile.getVarPtr("DontUseTS")==NULL || IService::getInstance()->ConfigFile.getVarPtr("DontUseTS")->asInt()==0) + CTickEventHandler::init(CStatsScanServiceSingleton::tickUpdate); + + CSingletonRegistry::getInstance()->init(); + } + + /* + * Service Update + */ + bool update() + { + CSingletonRegistry::getInstance()->serviceUpdate(); + return true; + } + + /* + * Tick Update + */ + static void tickUpdate() + { + CSingletonRegistry::getInstance()->tickUpdate(); + } + + /* + * Release + */ + void release() + { + CSingletonRegistry::getInstance()->release(); + } + +}; + + +//----------------------------------------------- +// NLNET_SERVICE_MAIN +//----------------------------------------------- +NLNET_SERVICE_MAIN( CStatsScanServiceSingleton, "stats_scan", "stats_scan_service", 0, EmptyCallbackArray, "", "" ); + diff --git a/code/ryzom/tools/stats_scan/user_char_filters.cpp b/code/ryzom/tools/stats_scan/user_char_filters.cpp index a4af96753..29c0b4b9f 100644 --- a/code/ryzom/tools/stats_scan/user_char_filters.cpp +++ b/code/ryzom/tools/stats_scan/user_char_filters.cpp @@ -1,53 +1,53 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -//------------------------------------------------------------------------------------------------- -// includes -//------------------------------------------------------------------------------------------------- - -#include "char_filter_factory.h" -#include "character.h" - -#include - -//------------------------------------------------------------------------------------------------- -// namespaces -//------------------------------------------------------------------------------------------------- - -using namespace std; -using namespace NLMISC; - -//------------------------------------------------------------------------------------------------- -// INFO_EXTRACTOR Implementations -//------------------------------------------------------------------------------------------------- - -FILTER(Money," []") -{ - CVectorSString args; - CSString s= _RawArgs; - CSString s0= s.firstWord(true); - CSString s1= s.firstWord(true); - uint32 min= s0.atoi(); - uint32 max= (s1.empty()? std::numeric_limits::max(): s1.atoi()); - if ( (min==0 && s0!="0") || (max==0 && s1!="0") || !s.strip().empty() ) - { - nlwarning("Bad arguments in filter: should be []"); - return false; - } - return (c->_Money>= min) && (c->_Money<= max); -} - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +//------------------------------------------------------------------------------------------------- +// includes +//------------------------------------------------------------------------------------------------- + +#include "char_filter_factory.h" +#include "character.h" + +#include + +//------------------------------------------------------------------------------------------------- +// namespaces +//------------------------------------------------------------------------------------------------- + +using namespace std; +using namespace NLMISC; + +//------------------------------------------------------------------------------------------------- +// INFO_EXTRACTOR Implementations +//------------------------------------------------------------------------------------------------- + +FILTER(Money," []") +{ + CVectorSString args; + CSString s= _RawArgs; + CSString s0= s.firstWord(true); + CSString s1= s.firstWord(true); + uint32 min= s0.atoi(); + uint32 max= (s1.empty()? std::numeric_limits::max(): s1.atoi()); + if ( (min==0 && s0!="0") || (max==0 && s1!="0") || !s.strip().empty() ) + { + nlwarning("Bad arguments in filter: should be []"); + return false; + } + return (c->_Money>= min) && (c->_Money<= max); +} + diff --git a/code/ryzom/tools/stats_scan/user_char_info_extractors.cpp b/code/ryzom/tools/stats_scan/user_char_info_extractors.cpp index 9dff025fb..883b062a3 100644 --- a/code/ryzom/tools/stats_scan/user_char_info_extractors.cpp +++ b/code/ryzom/tools/stats_scan/user_char_info_extractors.cpp @@ -1,78 +1,78 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -//------------------------------------------------------------------------------------------------- -// includes -//------------------------------------------------------------------------------------------------- - -#include "char_info_extractor_factory.h" -#include "character_scan_job.h" -#include "character.h" - - -//------------------------------------------------------------------------------------------------- -// INFO_EXTRACTOR Implementations -//------------------------------------------------------------------------------------------------- - -INFO_EXTRACTOR(Name,"The character name","name") -{ - job->charTblSetEntry("name",c->EntityBase._Name); -} - -INFO_EXTRACTOR(Money,"Cash in hand","money") -{ - job->charTblSetEntry("money",NLMISC::toString(c->_Money)); -} - -INFO_EXTRACTOR(PlayerRoomAndPets,"The Id of the room and number of pets owned by the character","room,petCount") -{ - job->charTblSetEntry("room",NLMISC::toString(c->_PlayerRoom.Building)); - job->charTblSetEntry("petCount",NLMISC::toString(c->_PlayerPets.size())); -} - -INFO_EXTRACTOR(PlayerRoomStats,"The stats of number of players who have access to each room type","") -{ - job->freqTblAddEntry("room",NLMISC::toString(c->_PlayerRoom.Building)); -} - -INFO_EXTRACTOR(RespawnPointCount,"Number of respawn points","respawnPointCount") -{ - job->charTblSetEntry("respawnPointCount",NLMISC::toString(c->RespawnPoints.RespawnPoints.size())); -} - -INFO_EXTRACTOR(RespawnPointStats,"Stats on number of players who have access to each of the respawn points","") -{ - for (uint32 i=0;iRespawnPoints.RespawnPoints.size();++i) - { - job->freqTblAddEntry("RespawnPoints",c->RespawnPoints.RespawnPoints[i]); - } -} - -INFO_EXTRACTOR(StanzaStats,"Stats on number of players who know each stanza","") -{ - for (uint32 i=0;i_KnownBricks.size();++i) - { - job->freqTblAddEntry("RespawnPoints",c->_KnownBricks[i].toString()); - } -} - -INFO_EXTRACTOR(VisPropStats,"Stats on race and visual props","") -{ - job->freqTblAddEntry("race_sex",c->EntityBase._Race+(c->EntityBase._Gender==0?"_MALE":"_FEMALE")); - job->freqTblAddEntry("hair",c->EntityBase._Race+(c->EntityBase._Gender==0?"_MALE_":"_FEMALE_")+NLMISC::toString(c->HairType)); - job->freqTblAddEntry("tattoo",c->EntityBase._Race+(c->EntityBase._Gender==0?"_MALE_":"_FEMALE_")+NLMISC::toString(c->Tattoo)); -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +//------------------------------------------------------------------------------------------------- +// includes +//------------------------------------------------------------------------------------------------- + +#include "char_info_extractor_factory.h" +#include "character_scan_job.h" +#include "character.h" + + +//------------------------------------------------------------------------------------------------- +// INFO_EXTRACTOR Implementations +//------------------------------------------------------------------------------------------------- + +INFO_EXTRACTOR(Name,"The character name","name") +{ + job->charTblSetEntry("name",c->EntityBase._Name); +} + +INFO_EXTRACTOR(Money,"Cash in hand","money") +{ + job->charTblSetEntry("money",NLMISC::toString(c->_Money)); +} + +INFO_EXTRACTOR(PlayerRoomAndPets,"The Id of the room and number of pets owned by the character","room,petCount") +{ + job->charTblSetEntry("room",NLMISC::toString(c->_PlayerRoom.Building)); + job->charTblSetEntry("petCount",NLMISC::toString(c->_PlayerPets.size())); +} + +INFO_EXTRACTOR(PlayerRoomStats,"The stats of number of players who have access to each room type","") +{ + job->freqTblAddEntry("room",NLMISC::toString(c->_PlayerRoom.Building)); +} + +INFO_EXTRACTOR(RespawnPointCount,"Number of respawn points","respawnPointCount") +{ + job->charTblSetEntry("respawnPointCount",NLMISC::toString(c->RespawnPoints.RespawnPoints.size())); +} + +INFO_EXTRACTOR(RespawnPointStats,"Stats on number of players who have access to each of the respawn points","") +{ + for (uint32 i=0;iRespawnPoints.RespawnPoints.size();++i) + { + job->freqTblAddEntry("RespawnPoints",c->RespawnPoints.RespawnPoints[i]); + } +} + +INFO_EXTRACTOR(StanzaStats,"Stats on number of players who know each stanza","") +{ + for (uint32 i=0;i_KnownBricks.size();++i) + { + job->freqTblAddEntry("RespawnPoints",c->_KnownBricks[i].toString()); + } +} + +INFO_EXTRACTOR(VisPropStats,"Stats on race and visual props","") +{ + job->freqTblAddEntry("race_sex",c->EntityBase._Race+(c->EntityBase._Gender==0?"_MALE":"_FEMALE")); + job->freqTblAddEntry("hair",c->EntityBase._Race+(c->EntityBase._Gender==0?"_MALE_":"_FEMALE_")+NLMISC::toString(c->HairType)); + job->freqTblAddEntry("tattoo",c->EntityBase._Race+(c->EntityBase._Gender==0?"_MALE_":"_FEMALE_")+NLMISC::toString(c->Tattoo)); +} diff --git a/code/ryzom/tools/translation_tools/extract_bot_names.cpp b/code/ryzom/tools/translation_tools/extract_bot_names.cpp index 01f50d6cd..e8198e63d 100644 --- a/code/ryzom/tools/translation_tools/extract_bot_names.cpp +++ b/code/ryzom/tools/translation_tools/extract_bot_names.cpp @@ -1,755 +1,755 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/misc/types_nl.h" -#include "nel/misc/config_file.h" -#include "nel/misc/sheet_id.h" -#include "nel/misc/path.h" -#include "nel/misc/diff_tool.h" -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" -#include "nel/georges/load_form.h" -#include "nel/ligo/ligo_config.h" -#include "nel/ligo/primitive.h" -#include "nel/ligo/primitive_utils.h" - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; -using namespace STRING_MANAGER; - -vector Filters; - -static CLigoConfig LigoConfig; -static bool RemoveOlds = false; - -struct TCreatureInfo -{ - CSheetId SheetId; - bool ForceSheetName; - bool DisplayName; - - - void readGeorges (const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId) - { - const NLGEORGES::UFormElm &item=form->getRootNode(); - - SheetId=sheetId; - item.getValueByName(ForceSheetName, "3d data.ForceDisplayCreatureName"); - item.getValueByName(DisplayName, "3d data.DisplayName"); - } - - void serial(NLMISC::IStream &f) - { - f.serial(SheetId); - f.serial(ForceSheetName); - f.serial(DisplayName); - } - - - static uint getVersion () - { - return 1; - } - - void removed() - { - } - -}; - -std::map Creatures; - -TCreatureInfo *getCreature(const std::string &sheetName) -{ - CSheetId id(sheetName+".creature"); - - if (Creatures.find(id) != Creatures.end()) - return &(Creatures.find(id)->second); - else - return NULL; -} - -string cleanupName(const std::string &name) -{ - string ret; - - for (uint i=0; i= 2) - { - if ( *ret.begin() == ucchar('$')) - { - ret=ret.substr(1); - } - if ( *ret.rbegin() == ucchar('$')) - { - ret = ret.substr(0, ret.size()-1); - } - } - ret = cleanupUcName(ret); - return ret; -} - -struct TEntryInfo -{ - string SheetName; -}; - -set GenericNames; -map SimpleNames; -set Functions; - - -string removeAndStoreFunction(const std::string &fullName) -{ - string::size_type pos = fullName.find("$"); - if (pos == string::npos) - return fullName; - else - { - // extract and store the function name - string ret; - - ret = fullName.substr(0, pos); - string::size_type pos2 = fullName.find("$", pos+1); - - string fct = fullName.substr(pos+1, pos2-(pos+1)); - - ret += fullName.substr(pos2+1); - - if (Functions.find(fct) == Functions.end()) - { - nldebug("Adding function '%s'", fct.c_str()); - Functions.insert(fct); - } - - return ret; - } -} - - -void addGenericName(const std::string &name, const std::string &sheetName) -{ - TCreatureInfo *c = getCreature(sheetName); - if (!c || c->ForceSheetName || !c->DisplayName) - return; - - if (SimpleNames.find(name) != SimpleNames.end()) - { - nldebug("Name '%s' is now a generic name", name.c_str()); - GenericNames.insert(name); - SimpleNames.erase(name); - - } - else if (GenericNames.find(name) == GenericNames.end()) - { - nldebug("Adding generic name '%s'", name.c_str()); - GenericNames.insert(name); - } -} - -void addSimpleName(const std::string &name, const std::string &sheetName) -{ - TCreatureInfo *c = getCreature(sheetName); - if (!c || c->ForceSheetName || !c->DisplayName) - return; - - if (SimpleNames.find(name) != SimpleNames.end()) - { - addGenericName(name, sheetName); - } - else if (GenericNames.find(name) != GenericNames.end()) - { - return; - } - else - { - nldebug("Adding simple name '%s'", name.c_str()); - - TEntryInfo ei; - ei.SheetName = sheetName; - - SimpleNames.insert(make_pair(name, ei)); - } -} - -int extractBotNames(int argc, char *argv[]) -{ - //------------------------------------------------------------------- - // read the parameters - for (int i=2; i files; - CPath::getFileList("primitive", files); - - for (uint i=0; i ps; - ps.buildSet(primDoc.RootNode, pred, result); - - for (uint i=0; igetPropertyByName("name", name); - result[i]->getPropertyByName("count", countStr); - result[i]->getPropertyByName("bot_sheet_look", sheetStr); - - uint32 count; - NLMISC::fromString(countStr, count); - - if (count != 0) - { - if (sheetStr.empty()) - { - nlwarning("In '%s', empty sheet !", buildPrimPath(result[i]).c_str()); - } - else - { - addGenericName(removeAndStoreFunction(name), sheetStr); - } - } - } - } - // look for bot template - { - TPrimitiveClassPredicate pred("bot_template_npc"); - TPrimitiveSet result; - - CPrimitiveSet ps; - ps.buildSet(primDoc.RootNode, pred, result); - - for (uint i=0; igetPropertyByName("name", name); - result[i]->getPropertyByName("sheet_look", sheetStr); - - if (sheetStr.empty()) - { - // take the sheet in the parent - result[i]->getParent()->getPropertyByName("bot_sheet_look", sheetStr); - } - - if (sheetStr.empty()) - { - nlwarning("In '%s', empty sheet !", buildPrimPath(result[i]).c_str()); - } - else - { - addGenericName(removeAndStoreFunction(name), sheetStr); - } - } - } - // look for npc_group - { - TPrimitiveClassPredicate pred("npc_group"); - TPrimitiveSet result; - - CPrimitiveSet ps; - ps.buildSet(primDoc.RootNode, pred, result); - - for (uint i=0; igetPropertyByName("name", name); - result[i]->getPropertyByName("count", countStr); - result[i]->getPropertyByName("bot_sheet_client", sheetStr); - - uint32 count; - NLMISC::fromString(countStr, count); - - if (count > 0 && sheetStr.empty()) - { - nlwarning("In '%s', empty sheet !", buildPrimPath(result[i]).c_str()); - } - else - { - if (count == 1) - { - addSimpleName(removeAndStoreFunction(name), sheetStr); - } - else if (count > 1) - { - addGenericName(removeAndStoreFunction(name), sheetStr); - } - } - } - } - // look for bot - { - TPrimitiveClassPredicate pred("npc_bot"); - TPrimitiveSet result; - - CPrimitiveSet ps; - ps.buildSet(primDoc.RootNode, pred, result); - - for (uint i=0; igetPropertyByName("name", name); - result[i]->getPropertyByName("sheet_client", sheetStr); - - if (sheetStr.empty()) - { - // take the sheet in the parent - result[i]->getParent()->getPropertyByName("bot_sheet_client", sheetStr); - } - - if (sheetStr.empty()) - { - nlwarning("In '%s', empty sheet !", buildPrimPath(result[i]).c_str()); - } - else - { - TEntryInfo ei; - addSimpleName(removeAndStoreFunction(name), sheetStr); - } - } - } - } - - //------------------------------------------------------------------- - // step 2 : load the reference file - - nlinfo("Looking for missing translation:"); - - TWorksheet botNames; - loadExcelSheet(workBotNamesFile.asString(), botNames, true); - TWorksheet transBotNames; - loadExcelSheet(transBotNamesFile.asString(), transBotNames, true); - - TWorksheet fcts; - loadExcelSheet(workTitleFile.asString(), fcts, true); - - - // add missing element - - uint nbAddSimpleName = 0; - uint nbAddFunction = 0; - uint nbAddGenericName = 0; - - uint botIdCol; - nlverify(botNames.findId(botIdCol)); - uint transIdCol; - nlverify(transBotNames.findId(transIdCol)); - uint fctsIdCol; - nlverify(fcts.findId(fctsIdCol)); - - // special treatment to add the sheet_name col - { - uint sheetCol; - if (!botNames.findCol(ucstring("sheet_name"), sheetCol)) - { - botNames.insertColumn(botNames.ColCount); - botNames.setData(0, botNames.ColCount-1, ucstring("sheet_name")); - } - - if (!transBotNames.findCol(ucstring("sheet_name"), sheetCol)) - { - transBotNames.insertColumn(transBotNames.ColCount); - transBotNames.setData(0, transBotNames.ColCount-1, ucstring("sheet_name")); - } - } - // 1 - simple names - { - nlinfo(" Simple names..."); - - - map::iterator first(SimpleNames.begin()), last(SimpleNames.end()); - for (; first != last; ++first) - { - uint rowIdx; - if (!botNames.findRow(botIdCol, first->first, rowIdx)) - { - // we need to add the entry - rowIdx = botNames.size(); - botNames.resize(botNames.size()+1); - - botNames.setData(rowIdx, ucstring("bot name"), first->first); - botNames.setData(rowIdx, ucstring("translated name"), first->first); - botNames.setData(rowIdx, ucstring("sheet_name"), first->second.SheetName); - - nbAddSimpleName++; - } - else - { - // set/update the sheet name info - // try to restore the existing translation - uint transRowIdx; - if (transBotNames.findRow(transIdCol, first->first, transRowIdx)) - { - ucstring wkBotName = botNames.getData(rowIdx, ucstring("bot name")); - ucstring wkSheetName = botNames.getData(rowIdx, ucstring("sheet_name")); - ucstring wkTranslationName = botNames.getData(rowIdx, ucstring("translated name")); - ucstring ucWkHash; - uint64 hash = CI18N::makeHash(wkBotName + wkTranslationName +wkSheetName); - CI18N::hashToUCString(hash, ucWkHash); - ucstring trUcHash = transBotNames[transRowIdx][0]; - bool isWkTranslationNameAGroupName = wkTranslationName.find(ucstring("$")) != ucstring::npos; - bool hashIsValide = std::equal(ucWkHash.begin(), ucWkHash.end(), trUcHash.begin()+1); - // Hash is equal get the translation - if (hashIsValide && !isWkTranslationNameAGroupName) - { - wkTranslationName = transBotNames.getData(transRowIdx, ucstring("translated name")); - wkSheetName = transBotNames.getData(transRowIdx, ucstring("sheet_name")); - botNames.setData(rowIdx, ucstring("translated name"), wkTranslationName); - botNames.setData(rowIdx, ucstring("sheet_name"), wkSheetName); - hash = CI18N::makeHash(wkBotName + wkTranslationName + wkSheetName); - // update the hash code - CI18N::hashToUCString(hash, transBotNames[transRowIdx][0]); - } - // bots_name.txt has been manually changed. We trust what the Level Designer has done. We don't destroy is work. - // or it is a simple - else - { - //use the "translated name" of the manually changed work/bot_name.txt - botNames.setData(rowIdx, ucstring("translated name"), wkTranslationName); - botNames.setData(rowIdx, ucstring("sheet_name"), wkSheetName); - } - } - } - } - } - - // 2 - generic names - - { - nlinfo(" Generic names..."); - - set::iterator first(GenericNames.begin()), last(GenericNames.end()); - for (; first != last; ++first) - { - string gnName = "gn_" + cleanupName(*first); - - ucstring fctsTitleId; - ucstring fctsName; - // add or modify the bot names - uint rowIdx; - if (!botNames.findRow(botIdCol, *first, rowIdx)) - { - // we need to add the entry - rowIdx = botNames.size(); - botNames.resize(botNames.size()+1); - - botNames.setData(rowIdx, ucstring("bot name"), *first); - botNames.setData(rowIdx, ucstring("translated name"), ucstring("$") + gnName + "$"); - botNames.setData(rowIdx, ucstring("sheet_name"), ucstring()); - fctsTitleId = gnName; - fctsName = *first; - - nbAddSimpleName++; - } - else - { - // look in the translated table to remember the translated name to write it in the string file - ucstring wkBotName = botNames.getData(rowIdx, ucstring("bot name")); - ucstring wkTranslationName = botNames.getData(rowIdx, ucstring("translated name")); - ucstring wkSheetName = botNames.getData(rowIdx, ucstring("sheet_name")); - - - nlinfo("Bot name:%s\n",wkBotName.toString().c_str()); - bool isWkTranslationNameAGroupName = wkTranslationName.find(ucstring("$")) != ucstring::npos; - - if ( isWkTranslationNameAGroupName ) //work name looks like "$gn_***$: do not modify - { - - //Do not change work/bot_name.txt - // update work/world_title.txt - - ucstring transName; - fctsTitleId = makeGroupName(wkTranslationName); - uint transRowIdx; - if (transBotNames.findRow(transIdCol, *first, transRowIdx)) - { - transName = transBotNames.getData(transRowIdx, ucstring("translated name")); - - if (transName.find(ucstring("$")) != ucstring::npos) - { - transName = fctsTitleId; - } - } - else - { - transName = fctsTitleId; - } - //Do not touch anything - botNames.setData(rowIdx, ucstring("translated name"), wkTranslationName); - botNames.setData(rowIdx, ucstring("sheet_name"), wkSheetName); - // fctsTitleId = makeGroupName(wkTranslationName); - fctsName = transName; - - } - else // WkTranslationName != "$gn*$" - { - uint transRowIdx; - ucstring transName; - ucstring wkSheetName; - // Get the translation as a simple name. - if (transBotNames.findRow(transIdCol, *first, transRowIdx)) - { - - transName = transBotNames.getData(transRowIdx, ucstring("translated name")); - ucstring trSheetName = transBotNames.getData(transRowIdx, ucstring("sheet_name")); - - //tr."translation name" is - if (transName.find(ucstring("$")) != ucstring::npos) - { - //get Translation, update hash - botNames[rowIdx][1] = transName; - botNames[rowIdx][2] = trSheetName; - fctsTitleId = makeGroupName(transName); - fctsName = makeGroupName(transName); - ucstring trNewUcHash; - uint64 hash = CI18N::makeHash(wkBotName + transName +trSheetName); - CI18N::hashToUCString(hash, trNewUcHash); - transBotNames[transRowIdx][0] = ucstring("_") + trNewUcHash; - } - else //botNames."translated name" != $gn_$ && tansName."translated name" != $gn_$ - { - - // get the translation back - //update work/bot_name.txt - wkTranslationName = ucstring("$")+gnName+"$"; - botNames[rowIdx][0] = wkBotName; - botNames[rowIdx][1] = wkTranslationName; - botNames[rowIdx][2] = wkSheetName; - - //update translated/bot_name.txt - - fctsName = transName; //transName - fctsTitleId = gnName; - ucstring trNewUcHash; - uint64 hash = CI18N::makeHash(botNames[rowIdx][0] + botNames[rowIdx][1] +botNames[rowIdx][2]); - CI18N::hashToUCString(hash, trNewUcHash); - transBotNames[transRowIdx][0] = ucstring("_") + trNewUcHash; - } - - } - else //There is no translation yet - { - fctsName = wkTranslationName; - wkTranslationName = ucstring("$")+gnName+"$"; - botNames[rowIdx][0] = wkBotName; - botNames[rowIdx][1] = wkTranslationName; - botNames[rowIdx][2] = wkSheetName; - fctsTitleId = gnName; - - - } - } - - } - - - // look for a corresponding entry - uint gnNameRow; - - - if (!fcts.findRow(fctsIdCol, fctsTitleId, gnNameRow)) - { - - // not found, add it - gnNameRow = fcts.size(); - fcts.resize(fcts.size()+1); - fcts.setData(gnNameRow, ucstring("title_id"), fctsTitleId); - fcts.setData(gnNameRow, ucstring("name"), fctsName); - nbAddGenericName++; - - } - else //Update - { - - } - } - } - - - // 3 - functions - { - nlinfo(" Functions..."); - - set::iterator first(Functions.begin()), last(Functions.end()); - for (; first != last; ++first) - { - string fctName = *first; - // look for a corresponding entry - uint functionRow; - if (!fcts.findRow(fctsIdCol, fctName, functionRow)) - { - // not found, add it - functionRow = fcts.size(); - fcts.resize(fcts.size()+1); - - fcts.setData(functionRow, ucstring("title_id"), fctName); - fcts.setData(functionRow, ucstring("name"), *first); - - nbAddFunction++; - } - } - } - - // display summary - nlinfo("Adding %u new simple name", nbAddSimpleName); - nlinfo("Adding %u new generic name", nbAddGenericName); - nlinfo("Adding %u new function name", nbAddFunction); - - // saving the modified files - - ucstring s = prepareExcelSheet(botNames); - CI18N::writeTextFile(workBotNamesFile.asString(), s, false); - s = prepareExcelSheet(transBotNames); - CI18N::writeTextFile(transBotNamesFile.asString(), s, false); - s = prepareExcelSheet(fcts); - CI18N::writeTextFile(workTitleFile.asString(), s, false); - - return 0; -} +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/misc/types_nl.h" +#include "nel/misc/config_file.h" +#include "nel/misc/sheet_id.h" +#include "nel/misc/path.h" +#include "nel/misc/diff_tool.h" +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" +#include "nel/georges/load_form.h" +#include "nel/ligo/ligo_config.h" +#include "nel/ligo/primitive.h" +#include "nel/ligo/primitive_utils.h" + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; +using namespace STRING_MANAGER; + +vector Filters; + +static CLigoConfig LigoConfig; +static bool RemoveOlds = false; + +struct TCreatureInfo +{ + CSheetId SheetId; + bool ForceSheetName; + bool DisplayName; + + + void readGeorges (const NLMISC::CSmartPtr &form, const NLMISC::CSheetId &sheetId) + { + const NLGEORGES::UFormElm &item=form->getRootNode(); + + SheetId=sheetId; + item.getValueByName(ForceSheetName, "3d data.ForceDisplayCreatureName"); + item.getValueByName(DisplayName, "3d data.DisplayName"); + } + + void serial(NLMISC::IStream &f) + { + f.serial(SheetId); + f.serial(ForceSheetName); + f.serial(DisplayName); + } + + + static uint getVersion () + { + return 1; + } + + void removed() + { + } + +}; + +std::map Creatures; + +TCreatureInfo *getCreature(const std::string &sheetName) +{ + CSheetId id(sheetName+".creature"); + + if (Creatures.find(id) != Creatures.end()) + return &(Creatures.find(id)->second); + else + return NULL; +} + +string cleanupName(const std::string &name) +{ + string ret; + + for (uint i=0; i= 2) + { + if ( *ret.begin() == ucchar('$')) + { + ret=ret.substr(1); + } + if ( *ret.rbegin() == ucchar('$')) + { + ret = ret.substr(0, ret.size()-1); + } + } + ret = cleanupUcName(ret); + return ret; +} + +struct TEntryInfo +{ + string SheetName; +}; + +set GenericNames; +map SimpleNames; +set Functions; + + +string removeAndStoreFunction(const std::string &fullName) +{ + string::size_type pos = fullName.find("$"); + if (pos == string::npos) + return fullName; + else + { + // extract and store the function name + string ret; + + ret = fullName.substr(0, pos); + string::size_type pos2 = fullName.find("$", pos+1); + + string fct = fullName.substr(pos+1, pos2-(pos+1)); + + ret += fullName.substr(pos2+1); + + if (Functions.find(fct) == Functions.end()) + { + nldebug("Adding function '%s'", fct.c_str()); + Functions.insert(fct); + } + + return ret; + } +} + + +void addGenericName(const std::string &name, const std::string &sheetName) +{ + TCreatureInfo *c = getCreature(sheetName); + if (!c || c->ForceSheetName || !c->DisplayName) + return; + + if (SimpleNames.find(name) != SimpleNames.end()) + { + nldebug("Name '%s' is now a generic name", name.c_str()); + GenericNames.insert(name); + SimpleNames.erase(name); + + } + else if (GenericNames.find(name) == GenericNames.end()) + { + nldebug("Adding generic name '%s'", name.c_str()); + GenericNames.insert(name); + } +} + +void addSimpleName(const std::string &name, const std::string &sheetName) +{ + TCreatureInfo *c = getCreature(sheetName); + if (!c || c->ForceSheetName || !c->DisplayName) + return; + + if (SimpleNames.find(name) != SimpleNames.end()) + { + addGenericName(name, sheetName); + } + else if (GenericNames.find(name) != GenericNames.end()) + { + return; + } + else + { + nldebug("Adding simple name '%s'", name.c_str()); + + TEntryInfo ei; + ei.SheetName = sheetName; + + SimpleNames.insert(make_pair(name, ei)); + } +} + +int extractBotNames(int argc, char *argv[]) +{ + //------------------------------------------------------------------- + // read the parameters + for (int i=2; i files; + CPath::getFileList("primitive", files); + + for (uint i=0; i ps; + ps.buildSet(primDoc.RootNode, pred, result); + + for (uint i=0; igetPropertyByName("name", name); + result[i]->getPropertyByName("count", countStr); + result[i]->getPropertyByName("bot_sheet_look", sheetStr); + + uint32 count; + NLMISC::fromString(countStr, count); + + if (count != 0) + { + if (sheetStr.empty()) + { + nlwarning("In '%s', empty sheet !", buildPrimPath(result[i]).c_str()); + } + else + { + addGenericName(removeAndStoreFunction(name), sheetStr); + } + } + } + } + // look for bot template + { + TPrimitiveClassPredicate pred("bot_template_npc"); + TPrimitiveSet result; + + CPrimitiveSet ps; + ps.buildSet(primDoc.RootNode, pred, result); + + for (uint i=0; igetPropertyByName("name", name); + result[i]->getPropertyByName("sheet_look", sheetStr); + + if (sheetStr.empty()) + { + // take the sheet in the parent + result[i]->getParent()->getPropertyByName("bot_sheet_look", sheetStr); + } + + if (sheetStr.empty()) + { + nlwarning("In '%s', empty sheet !", buildPrimPath(result[i]).c_str()); + } + else + { + addGenericName(removeAndStoreFunction(name), sheetStr); + } + } + } + // look for npc_group + { + TPrimitiveClassPredicate pred("npc_group"); + TPrimitiveSet result; + + CPrimitiveSet ps; + ps.buildSet(primDoc.RootNode, pred, result); + + for (uint i=0; igetPropertyByName("name", name); + result[i]->getPropertyByName("count", countStr); + result[i]->getPropertyByName("bot_sheet_client", sheetStr); + + uint32 count; + NLMISC::fromString(countStr, count); + + if (count > 0 && sheetStr.empty()) + { + nlwarning("In '%s', empty sheet !", buildPrimPath(result[i]).c_str()); + } + else + { + if (count == 1) + { + addSimpleName(removeAndStoreFunction(name), sheetStr); + } + else if (count > 1) + { + addGenericName(removeAndStoreFunction(name), sheetStr); + } + } + } + } + // look for bot + { + TPrimitiveClassPredicate pred("npc_bot"); + TPrimitiveSet result; + + CPrimitiveSet ps; + ps.buildSet(primDoc.RootNode, pred, result); + + for (uint i=0; igetPropertyByName("name", name); + result[i]->getPropertyByName("sheet_client", sheetStr); + + if (sheetStr.empty()) + { + // take the sheet in the parent + result[i]->getParent()->getPropertyByName("bot_sheet_client", sheetStr); + } + + if (sheetStr.empty()) + { + nlwarning("In '%s', empty sheet !", buildPrimPath(result[i]).c_str()); + } + else + { + TEntryInfo ei; + addSimpleName(removeAndStoreFunction(name), sheetStr); + } + } + } + } + + //------------------------------------------------------------------- + // step 2 : load the reference file + + nlinfo("Looking for missing translation:"); + + TWorksheet botNames; + loadExcelSheet(workBotNamesFile.asString(), botNames, true); + TWorksheet transBotNames; + loadExcelSheet(transBotNamesFile.asString(), transBotNames, true); + + TWorksheet fcts; + loadExcelSheet(workTitleFile.asString(), fcts, true); + + + // add missing element + + uint nbAddSimpleName = 0; + uint nbAddFunction = 0; + uint nbAddGenericName = 0; + + uint botIdCol; + nlverify(botNames.findId(botIdCol)); + uint transIdCol; + nlverify(transBotNames.findId(transIdCol)); + uint fctsIdCol; + nlverify(fcts.findId(fctsIdCol)); + + // special treatment to add the sheet_name col + { + uint sheetCol; + if (!botNames.findCol(ucstring("sheet_name"), sheetCol)) + { + botNames.insertColumn(botNames.ColCount); + botNames.setData(0, botNames.ColCount-1, ucstring("sheet_name")); + } + + if (!transBotNames.findCol(ucstring("sheet_name"), sheetCol)) + { + transBotNames.insertColumn(transBotNames.ColCount); + transBotNames.setData(0, transBotNames.ColCount-1, ucstring("sheet_name")); + } + } + // 1 - simple names + { + nlinfo(" Simple names..."); + + + map::iterator first(SimpleNames.begin()), last(SimpleNames.end()); + for (; first != last; ++first) + { + uint rowIdx; + if (!botNames.findRow(botIdCol, first->first, rowIdx)) + { + // we need to add the entry + rowIdx = botNames.size(); + botNames.resize(botNames.size()+1); + + botNames.setData(rowIdx, ucstring("bot name"), first->first); + botNames.setData(rowIdx, ucstring("translated name"), first->first); + botNames.setData(rowIdx, ucstring("sheet_name"), first->second.SheetName); + + nbAddSimpleName++; + } + else + { + // set/update the sheet name info + // try to restore the existing translation + uint transRowIdx; + if (transBotNames.findRow(transIdCol, first->first, transRowIdx)) + { + ucstring wkBotName = botNames.getData(rowIdx, ucstring("bot name")); + ucstring wkSheetName = botNames.getData(rowIdx, ucstring("sheet_name")); + ucstring wkTranslationName = botNames.getData(rowIdx, ucstring("translated name")); + ucstring ucWkHash; + uint64 hash = CI18N::makeHash(wkBotName + wkTranslationName +wkSheetName); + CI18N::hashToUCString(hash, ucWkHash); + ucstring trUcHash = transBotNames[transRowIdx][0]; + bool isWkTranslationNameAGroupName = wkTranslationName.find(ucstring("$")) != ucstring::npos; + bool hashIsValide = std::equal(ucWkHash.begin(), ucWkHash.end(), trUcHash.begin()+1); + // Hash is equal get the translation + if (hashIsValide && !isWkTranslationNameAGroupName) + { + wkTranslationName = transBotNames.getData(transRowIdx, ucstring("translated name")); + wkSheetName = transBotNames.getData(transRowIdx, ucstring("sheet_name")); + botNames.setData(rowIdx, ucstring("translated name"), wkTranslationName); + botNames.setData(rowIdx, ucstring("sheet_name"), wkSheetName); + hash = CI18N::makeHash(wkBotName + wkTranslationName + wkSheetName); + // update the hash code + CI18N::hashToUCString(hash, transBotNames[transRowIdx][0]); + } + // bots_name.txt has been manually changed. We trust what the Level Designer has done. We don't destroy is work. + // or it is a simple + else + { + //use the "translated name" of the manually changed work/bot_name.txt + botNames.setData(rowIdx, ucstring("translated name"), wkTranslationName); + botNames.setData(rowIdx, ucstring("sheet_name"), wkSheetName); + } + } + } + } + } + + // 2 - generic names + + { + nlinfo(" Generic names..."); + + set::iterator first(GenericNames.begin()), last(GenericNames.end()); + for (; first != last; ++first) + { + string gnName = "gn_" + cleanupName(*first); + + ucstring fctsTitleId; + ucstring fctsName; + // add or modify the bot names + uint rowIdx; + if (!botNames.findRow(botIdCol, *first, rowIdx)) + { + // we need to add the entry + rowIdx = botNames.size(); + botNames.resize(botNames.size()+1); + + botNames.setData(rowIdx, ucstring("bot name"), *first); + botNames.setData(rowIdx, ucstring("translated name"), ucstring("$") + gnName + "$"); + botNames.setData(rowIdx, ucstring("sheet_name"), ucstring()); + fctsTitleId = gnName; + fctsName = *first; + + nbAddSimpleName++; + } + else + { + // look in the translated table to remember the translated name to write it in the string file + ucstring wkBotName = botNames.getData(rowIdx, ucstring("bot name")); + ucstring wkTranslationName = botNames.getData(rowIdx, ucstring("translated name")); + ucstring wkSheetName = botNames.getData(rowIdx, ucstring("sheet_name")); + + + nlinfo("Bot name:%s\n",wkBotName.toString().c_str()); + bool isWkTranslationNameAGroupName = wkTranslationName.find(ucstring("$")) != ucstring::npos; + + if ( isWkTranslationNameAGroupName ) //work name looks like "$gn_***$: do not modify + { + + //Do not change work/bot_name.txt + // update work/world_title.txt + + ucstring transName; + fctsTitleId = makeGroupName(wkTranslationName); + uint transRowIdx; + if (transBotNames.findRow(transIdCol, *first, transRowIdx)) + { + transName = transBotNames.getData(transRowIdx, ucstring("translated name")); + + if (transName.find(ucstring("$")) != ucstring::npos) + { + transName = fctsTitleId; + } + } + else + { + transName = fctsTitleId; + } + //Do not touch anything + botNames.setData(rowIdx, ucstring("translated name"), wkTranslationName); + botNames.setData(rowIdx, ucstring("sheet_name"), wkSheetName); + // fctsTitleId = makeGroupName(wkTranslationName); + fctsName = transName; + + } + else // WkTranslationName != "$gn*$" + { + uint transRowIdx; + ucstring transName; + ucstring wkSheetName; + // Get the translation as a simple name. + if (transBotNames.findRow(transIdCol, *first, transRowIdx)) + { + + transName = transBotNames.getData(transRowIdx, ucstring("translated name")); + ucstring trSheetName = transBotNames.getData(transRowIdx, ucstring("sheet_name")); + + //tr."translation name" is + if (transName.find(ucstring("$")) != ucstring::npos) + { + //get Translation, update hash + botNames[rowIdx][1] = transName; + botNames[rowIdx][2] = trSheetName; + fctsTitleId = makeGroupName(transName); + fctsName = makeGroupName(transName); + ucstring trNewUcHash; + uint64 hash = CI18N::makeHash(wkBotName + transName +trSheetName); + CI18N::hashToUCString(hash, trNewUcHash); + transBotNames[transRowIdx][0] = ucstring("_") + trNewUcHash; + } + else //botNames."translated name" != $gn_$ && tansName."translated name" != $gn_$ + { + + // get the translation back + //update work/bot_name.txt + wkTranslationName = ucstring("$")+gnName+"$"; + botNames[rowIdx][0] = wkBotName; + botNames[rowIdx][1] = wkTranslationName; + botNames[rowIdx][2] = wkSheetName; + + //update translated/bot_name.txt + + fctsName = transName; //transName + fctsTitleId = gnName; + ucstring trNewUcHash; + uint64 hash = CI18N::makeHash(botNames[rowIdx][0] + botNames[rowIdx][1] +botNames[rowIdx][2]); + CI18N::hashToUCString(hash, trNewUcHash); + transBotNames[transRowIdx][0] = ucstring("_") + trNewUcHash; + } + + } + else //There is no translation yet + { + fctsName = wkTranslationName; + wkTranslationName = ucstring("$")+gnName+"$"; + botNames[rowIdx][0] = wkBotName; + botNames[rowIdx][1] = wkTranslationName; + botNames[rowIdx][2] = wkSheetName; + fctsTitleId = gnName; + + + } + } + + } + + + // look for a corresponding entry + uint gnNameRow; + + + if (!fcts.findRow(fctsIdCol, fctsTitleId, gnNameRow)) + { + + // not found, add it + gnNameRow = fcts.size(); + fcts.resize(fcts.size()+1); + fcts.setData(gnNameRow, ucstring("title_id"), fctsTitleId); + fcts.setData(gnNameRow, ucstring("name"), fctsName); + nbAddGenericName++; + + } + else //Update + { + + } + } + } + + + // 3 - functions + { + nlinfo(" Functions..."); + + set::iterator first(Functions.begin()), last(Functions.end()); + for (; first != last; ++first) + { + string fctName = *first; + // look for a corresponding entry + uint functionRow; + if (!fcts.findRow(fctsIdCol, fctName, functionRow)) + { + // not found, add it + functionRow = fcts.size(); + fcts.resize(fcts.size()+1); + + fcts.setData(functionRow, ucstring("title_id"), fctName); + fcts.setData(functionRow, ucstring("name"), *first); + + nbAddFunction++; + } + } + } + + // display summary + nlinfo("Adding %u new simple name", nbAddSimpleName); + nlinfo("Adding %u new generic name", nbAddGenericName); + nlinfo("Adding %u new function name", nbAddFunction); + + // saving the modified files + + ucstring s = prepareExcelSheet(botNames); + CI18N::writeTextFile(workBotNamesFile.asString(), s, false); + s = prepareExcelSheet(transBotNames); + CI18N::writeTextFile(transBotNamesFile.asString(), s, false); + s = prepareExcelSheet(fcts); + CI18N::writeTextFile(workTitleFile.asString(), s, false); + + return 0; +} diff --git a/code/ryzom/tools/translation_tools/extract_new_sheet_names.cpp b/code/ryzom/tools/translation_tools/extract_new_sheet_names.cpp index 431108ca1..dbc4d0c0b 100644 --- a/code/ryzom/tools/translation_tools/extract_new_sheet_names.cpp +++ b/code/ryzom/tools/translation_tools/extract_new_sheet_names.cpp @@ -1,417 +1,417 @@ -// Ryzom - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "nel/misc/types_nl.h" -#include "nel/misc/config_file.h" -#include "nel/misc/sheet_id.h" -#include "nel/misc/path.h" -#include "nel/misc/diff_tool.h" -#include "nel/misc/algo.h" -#include "nel/georges/u_form.h" -#include "nel/georges/u_form_elm.h" -#include "nel/georges/load_form.h" -#include "nel/ligo/ligo_config.h" -#include "nel/ligo/primitive.h" -#include "nel/ligo/primitive_utils.h" - -using namespace std; -using namespace NLMISC; -using namespace NLLIGO; -using namespace STRING_MANAGER; - - -static CLigoConfig LigoConfig; -static bool RemoveOlds = false; - - -// *************************************************************************** -/* - * Interface to build the whole list of words (key id) for a specific worksheet - */ -struct IWordListBuilder -{ - virtual bool buildWordList(std::vector &allWords, string workSheetFileName) =0; -}; - - -// *************************************************************************** -/* - * Specialisation of IWordListBuilder to list sheets in a directory - */ -struct CSheetWordListBuilder : public IWordListBuilder -{ - string SheetExt; - string SheetPath; - - virtual bool buildWordList(std::vector &allWords, string workSheetFileName) - { - SheetExt= toLower(SheetExt); - - // verify the directory is correct - if(!CFile::isDirectory(SheetPath)) - { - nlwarning("Error: Directory '%s' not found. '%s' Aborted", SheetPath.c_str(), workSheetFileName.c_str()); - return false; - } - - // list all files. - std::vector allFiles; - allFiles.reserve(100000); - CPath::getPathContent(SheetPath, true, false, true, allFiles, NULL); - - // Keep only the extension we want, and remove "_" (parent) - allWords.clear(); - allWords.reserve(allFiles.size()); - for(uint i=0;i PrimFilter; - - virtual bool buildWordList(std::vector &allWords, string workSheetFileName) - { - // verify the directory is correct - if(!CFile::isDirectory(PrimPath)) - { - nlwarning("Error: Directory '%s' not found. '%s' Aborted", PrimPath.c_str(), workSheetFileName.c_str()); - return false; - } - - // list all files. - std::vector allFiles; - allFiles.reserve(100000); - CPath::getPathContent(PrimPath, true, false, true, allFiles, NULL); - - // parse all primitive that match the filter - allWords.clear(); - allWords.reserve(100000); - // to avoid duplicate - set allWordSet; - for(uint i=0;i setPlace; - TPrimitiveSet placeRes; - setPlace.buildSet(PrimDoc.RootNode, predCont, placeRes); - // for all found - for (uint placeId= 0; placeId < placeRes.size(); ++placeId) - { - string primName; - if(placeRes[placeId]->getPropertyByName(listProp[cid], primName) && !primName.empty()) - { - primName= toLower(primName); - // avoid duplicate - if(allWordSet.insert(primName).second) - { - allWords.push_back(primName); - } - } - } - } - } - - return true; - } -}; - - -// *************************************************************************** -void extractNewWords(string workSheetFileName, string columnId, IWordListBuilder &wordListBuilder) -{ - uint i; - - // **** Load the excel sheet - // load - TWorksheet workSheet; - if(!loadExcelSheet(workSheetFileName, workSheet, true)) - { - nlwarning("Error reading '%s'. Aborted", workSheetFileName.c_str()); - return; - } - // get the key column index - uint keyColIndex = 0; - - if(!workSheet.findCol(columnId, keyColIndex)) - { - nlwarning("Error: Don't find the column '%s'. '%s' Aborted", columnId.c_str(), workSheetFileName.c_str()); - return; - } - // get the name column index - uint nameColIndex; - if(!workSheet.findCol(ucstring("name"), nameColIndex)) - { - nlwarning("Error: Don't find the column 'name'. '%s' Aborted", workSheetFileName.c_str()); - return; - } - // Make a copy of this worksheet, with strlwr on the key - // Yoyo: I prefer not modify the original worksheet (don't know what bad side effect it can have....) - TWorksheet workSheetLwr= workSheet; - for(i=0;i allWords; - if(!wordListBuilder.buildWordList(allWords, workSheetFileName)) - return; - - - // **** Append new one to the worksheet - uint nbAdd= 0; - for(i=0;i")+keyName); - // add to the workSheet - workSheet.resize(workSheet.size()+1); - workSheet.setData(rowIdx, keyColIndex, keyName); - workSheet.setData(rowIdx, nameColIndex, string("")+keyName); - - nbAdd++; - } - } - - - // **** Remove no more present ones (and log) - uint nbRemove= 0; - if(RemoveOlds) - { - // Build as a set - std::set allWordSet; - for(i=0;idisplayRawNL("'%s': '%s' entry erased at line '%d'.", workSheetFileName.c_str(), - keyStr.c_str(), i); - } - } - // resize to correct new size - tmpCopy.resize(dstRowId); - tmpCopyLwr.resize(dstRowId); - - // copy back - workSheet= tmpCopy; - workSheetLwr= tmpCopyLwr; - } - - - // **** Save - if(nbAdd==0 && nbRemove==0) - { - if(RemoveOlds) - NLMISC::InfoLog->displayRawNL("'%s': No deprecated entry found.", workSheetFileName.c_str()); - NLMISC::InfoLog->displayRawNL("'%s': No new entry found.", workSheetFileName.c_str()); - // Don't save - } - else - { - if(RemoveOlds) - NLMISC::InfoLog->displayRawNL("'%s': %d deprecated entry erased.", workSheetFileName.c_str(), nbRemove); - NLMISC::InfoLog->displayRawNL("'%s': %d new entry found.", workSheetFileName.c_str(), nbAdd); - // Save the not lowered worksheet - ucstring s = prepareExcelSheet(workSheet); - try - { - CI18N::writeTextFile(workSheetFileName.c_str(), s, false); - } - catch (const Exception &e) - { - nlwarning("cannot save file: '%s'. Reason: %s", workSheetFileName.c_str(), e.what()); - } - } -} - - -// *************************************************************************** -int extractNewSheetNames(int argc, char *argv[]) -{ - // **** read the parameters - for (int i=2; iaddNegativeFilter("numCol changed to"); - NLMISC::InfoLog->addNegativeFilter("CPath::addSearchPath"); - - - // **** read the configuration file - CConfigFile cf; - cf.load("bin/translation_tools.cfg"); - CConfigFile::CVar &paths = cf.getVar("Paths"); - CConfigFile::CVar &pathNoRecurse= cf.getVar("PathsNoRecurse"); - CConfigFile::CVar &ligoClassFile= cf.getVar("LigoClassFile"); - - // parse path - for (uint i=0; i +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "nel/misc/types_nl.h" +#include "nel/misc/config_file.h" +#include "nel/misc/sheet_id.h" +#include "nel/misc/path.h" +#include "nel/misc/diff_tool.h" +#include "nel/misc/algo.h" +#include "nel/georges/u_form.h" +#include "nel/georges/u_form_elm.h" +#include "nel/georges/load_form.h" +#include "nel/ligo/ligo_config.h" +#include "nel/ligo/primitive.h" +#include "nel/ligo/primitive_utils.h" + +using namespace std; +using namespace NLMISC; +using namespace NLLIGO; +using namespace STRING_MANAGER; + + +static CLigoConfig LigoConfig; +static bool RemoveOlds = false; + + +// *************************************************************************** +/* + * Interface to build the whole list of words (key id) for a specific worksheet + */ +struct IWordListBuilder +{ + virtual bool buildWordList(std::vector &allWords, string workSheetFileName) =0; +}; + + +// *************************************************************************** +/* + * Specialisation of IWordListBuilder to list sheets in a directory + */ +struct CSheetWordListBuilder : public IWordListBuilder +{ + string SheetExt; + string SheetPath; + + virtual bool buildWordList(std::vector &allWords, string workSheetFileName) + { + SheetExt= toLower(SheetExt); + + // verify the directory is correct + if(!CFile::isDirectory(SheetPath)) + { + nlwarning("Error: Directory '%s' not found. '%s' Aborted", SheetPath.c_str(), workSheetFileName.c_str()); + return false; + } + + // list all files. + std::vector allFiles; + allFiles.reserve(100000); + CPath::getPathContent(SheetPath, true, false, true, allFiles, NULL); + + // Keep only the extension we want, and remove "_" (parent) + allWords.clear(); + allWords.reserve(allFiles.size()); + for(uint i=0;i PrimFilter; + + virtual bool buildWordList(std::vector &allWords, string workSheetFileName) + { + // verify the directory is correct + if(!CFile::isDirectory(PrimPath)) + { + nlwarning("Error: Directory '%s' not found. '%s' Aborted", PrimPath.c_str(), workSheetFileName.c_str()); + return false; + } + + // list all files. + std::vector allFiles; + allFiles.reserve(100000); + CPath::getPathContent(PrimPath, true, false, true, allFiles, NULL); + + // parse all primitive that match the filter + allWords.clear(); + allWords.reserve(100000); + // to avoid duplicate + set allWordSet; + for(uint i=0;i setPlace; + TPrimitiveSet placeRes; + setPlace.buildSet(PrimDoc.RootNode, predCont, placeRes); + // for all found + for (uint placeId= 0; placeId < placeRes.size(); ++placeId) + { + string primName; + if(placeRes[placeId]->getPropertyByName(listProp[cid], primName) && !primName.empty()) + { + primName= toLower(primName); + // avoid duplicate + if(allWordSet.insert(primName).second) + { + allWords.push_back(primName); + } + } + } + } + } + + return true; + } +}; + + +// *************************************************************************** +void extractNewWords(string workSheetFileName, string columnId, IWordListBuilder &wordListBuilder) +{ + uint i; + + // **** Load the excel sheet + // load + TWorksheet workSheet; + if(!loadExcelSheet(workSheetFileName, workSheet, true)) + { + nlwarning("Error reading '%s'. Aborted", workSheetFileName.c_str()); + return; + } + // get the key column index + uint keyColIndex = 0; + + if(!workSheet.findCol(columnId, keyColIndex)) + { + nlwarning("Error: Don't find the column '%s'. '%s' Aborted", columnId.c_str(), workSheetFileName.c_str()); + return; + } + // get the name column index + uint nameColIndex; + if(!workSheet.findCol(ucstring("name"), nameColIndex)) + { + nlwarning("Error: Don't find the column 'name'. '%s' Aborted", workSheetFileName.c_str()); + return; + } + // Make a copy of this worksheet, with strlwr on the key + // Yoyo: I prefer not modify the original worksheet (don't know what bad side effect it can have....) + TWorksheet workSheetLwr= workSheet; + for(i=0;i allWords; + if(!wordListBuilder.buildWordList(allWords, workSheetFileName)) + return; + + + // **** Append new one to the worksheet + uint nbAdd= 0; + for(i=0;i")+keyName); + // add to the workSheet + workSheet.resize(workSheet.size()+1); + workSheet.setData(rowIdx, keyColIndex, keyName); + workSheet.setData(rowIdx, nameColIndex, string("")+keyName); + + nbAdd++; + } + } + + + // **** Remove no more present ones (and log) + uint nbRemove= 0; + if(RemoveOlds) + { + // Build as a set + std::set allWordSet; + for(i=0;idisplayRawNL("'%s': '%s' entry erased at line '%d'.", workSheetFileName.c_str(), + keyStr.c_str(), i); + } + } + // resize to correct new size + tmpCopy.resize(dstRowId); + tmpCopyLwr.resize(dstRowId); + + // copy back + workSheet= tmpCopy; + workSheetLwr= tmpCopyLwr; + } + + + // **** Save + if(nbAdd==0 && nbRemove==0) + { + if(RemoveOlds) + NLMISC::InfoLog->displayRawNL("'%s': No deprecated entry found.", workSheetFileName.c_str()); + NLMISC::InfoLog->displayRawNL("'%s': No new entry found.", workSheetFileName.c_str()); + // Don't save + } + else + { + if(RemoveOlds) + NLMISC::InfoLog->displayRawNL("'%s': %d deprecated entry erased.", workSheetFileName.c_str(), nbRemove); + NLMISC::InfoLog->displayRawNL("'%s': %d new entry found.", workSheetFileName.c_str(), nbAdd); + // Save the not lowered worksheet + ucstring s = prepareExcelSheet(workSheet); + try + { + CI18N::writeTextFile(workSheetFileName.c_str(), s, false); + } + catch (const Exception &e) + { + nlwarning("cannot save file: '%s'. Reason: %s", workSheetFileName.c_str(), e.what()); + } + } +} + + +// *************************************************************************** +int extractNewSheetNames(int argc, char *argv[]) +{ + // **** read the parameters + for (int i=2; iaddNegativeFilter("numCol changed to"); + NLMISC::InfoLog->addNegativeFilter("CPath::addSearchPath"); + + + // **** read the configuration file + CConfigFile cf; + cf.load("bin/translation_tools.cfg"); + CConfigFile::CVar &paths = cf.getVar("Paths"); + CConfigFile::CVar &pathNoRecurse= cf.getVar("PathsNoRecurse"); + CConfigFile::CVar &ligoClassFile= cf.getVar("LigoClassFile"); + + // parse path + for (uint i=0; i -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - - - -/** This tool is used to managed translation file. -* I work with two different file format : -* - phrase file witch contain a complex grammar description -* - string file withc contain only pair of identifier / string value. -* -* This tool can do 6 different work : -* - make diff string file file for each language from a reference string file. -* -* - merge the translated diff string file into there respective string file after -* translation -* -* - make diff phrase file for each language from a reference phrase file -* -* - merge the translated diff phrase file into there respective phrase file after -* translation -* -* - make clause diff for each language by examining phrase files. Add comments -* in the diff files for phrase parameter information. -* -* - merge clause diff in all the clause file. -* -* - remove "\*OLDVALUE: \*\/" from clause file or phrase file -* -* -* Before invocation, you must be in the translation repository (see localisation_system_in_ryzom.doc) -* Invocation should be as folow : -* trans_tool make_string_diff -* trans_tool merge_string_diff -* trans_tool make_words_diff -* trans_tool merge_words_diff -* trans_tool make_phrase_diff -* trans_tool merge_phrase_diff -* trans_tool make_clause_diff -* trans_tool merge_clause_diff -* trans_tool clean_string_diff -* trans_tool clean_words_diff -* trans_tool clean_clause_diff -* trans_tool clean_phrase_diff -* trans_tool make_phrase_diff_old -* trans_tool merge_phrase_diff_old -* trans_tool forget_phrase_diff -* trans_tool update_phrase_work -* trans_tool inject_clause -* trans_tool sort_trans_phrase -* trans_tool make_worksheet_diff -* trans_tool merge_worksheet_diff -* trans_tool crop_lines -* trans_tool extract_bot_names -* trans_tool extract_new_sheet_names - -*/ - -#include "nel/misc/app_context.h" -#include "nel/misc/i18n.h" -#include "nel/misc/file.h" -#include "nel/misc/path.h" -#include "nel/misc/diff_tool.h" -#include "nel/misc/algo.h" -#include -#include -#include -#include -#include -#include - -using namespace std; -using namespace NLMISC; -using namespace STRING_MANAGER; - -int extractBotNames(int argc, char *argv[]); -int extractNewSheetNames(int argc, char *argv[]); -const std::string addDir("work/"); -const std::string diffDir("diff/"); -const std::string transDir("translated/"); -const std::string historyDir("history/"); - -string diffVersion; - -#ifndef NL_OS_WINDOWS -char* itoa(int val, char *buffer, int base){ - static char buf[32] = {0}; - int i = 30; - for(; val && i ; --i, val /= base) - buf[i] = "0123456789abcdef"[val % base]; - return &buf[i+1]; -} -#endif // NL_OS_WINDOWS - -#ifdef NL_DEBUG -# define LOG nldebug -#else -# define LOG printf -#endif - -enum TDiffCommand -{ - diff_none, - diff_add, - diff_changed, - diff_removed, - diff_swap -}; - -struct TDiffInfo -{ - TDiffCommand Command; - uint Index1; - uint Index2; -}; - -/// Store the list of language extracted from the languages.txt file -vector Languages; - - -void showUsage(char *exeName) -{ - LOG("%s usage : \n", exeName); - LOG(" %s []\n", exeName); - LOG(" Where command can be :\n"); - LOG(" make_string_diff\n"); - LOG(" merge_string_diff\n"); - LOG(" clean_string_diff\n"); - LOG(" make_phrase_diff\n"); - LOG(" merge_phrase_diff\n"); - LOG(" clean_phrase_diff\n"); - LOG(" make_clause_diff\n"); - LOG(" merge_clause_diff\n"); - LOG(" clean_clause_diff\n"); - LOG(" make_phrase_diff_old\n"); - LOG(" merge_phrase_diff_old\n"); - LOG(" forget_phrase_diff\n"); - LOG(" inject_clause\n"); - LOG(" sort_trans_phrase\n"); - LOG(" make_worksheet_diff \n"); - LOG(" merge_worksheet_diff \n"); - LOG(" crop_lines \n"); - LOG(" extract_bot_names [-r]\n"); - LOG(" extract_new_sheet_names [-r]\n"); - LOG("\n"); - LOG("Language code are ISO 639-2 + optionally ISO 3166 country code.\n"); - LOG("Reference language is always the first language in languages.txt\n"); -} - - - -void verifyVersion(ucstring& doc, int versionId) -{ - ucstring version1("// DIFF_VERSION 1\r\n"); - ucstring::size_type version1Size = version1.size(); - ucstring version2("// DIFF_VERSION 2\r\n"); - ucstring::size_type version2Size = version2.size(); - - switch (versionId) - { - case 1: - if (doc.size() < version1Size|| doc.substr(0, version1Size) != version1 ) - { - nlerror("Loading wrong diff version"); - nlassert(0); - } - doc = doc.substr(version1Size); - break; - - case 2: - if (doc.size() < version2Size || doc.substr(0, version2Size) != version2 ) - { - nlerror("Loading wrong diff version"); - nlassert(0); - } - doc = doc.substr(version2Size); - break; - - default: - nlassert(0); - } - - -} -bool readPhraseFile1(const std::string &filename, vector &phrases, bool forceRehash) -{ - ucstring doc; - - CI18N::readTextFile(filename, doc, false, false, false, CI18N::LINE_FMT_CRLF); - verifyVersion(doc, 1); - return readPhraseFileFromString(doc, filename, phrases, forceRehash); -} - -bool readPhraseFile2(const std::string &filename, vector &phrases, bool forceRehash) -{ - ucstring doc; - - CI18N::readTextFile(filename, doc, false, false, false, CI18N::LINE_FMT_CRLF); - verifyVersion(doc, 2); - return readPhraseFileFromString(doc, filename, phrases, forceRehash); -} - - - -void getPathContentFiltered(const string &baseName, const string &ext, vector &result) -{ - CPath::getPathContent(diffDir, false, false, true, result); - - uint i; - for (i=0; i>8) & 0xff, fp); - } - - fclose(fp); - } -} -*/ - - -bool mergeStringDiff(vector &strings, const string &language, const string &baseName, const string &ext, bool onlyTranslated, bool archiveDiff = false) -{ - vector diffs; - - getPathContentFiltered(diffDir+baseName+language+"_diff_", ext, diffs); - - for (uint i=0; i diff; - if (!loadStringFile(diffs[i], diff, false)) - return false; - - for (uint j=0; j::IDiffCallback -{ -public: - void run(const vector &addition, vector &reference, vector &diff) - { - TStringDiffContext context(addition, reference, diff); - - CMakeDiff differ; - differ.makeDiff(this, context); - } - - void onEquivalent(uint addIndex, uint refIndex, TStringDiffContext &context) - { - // nothing to do - } - void onAdd(uint addIndex, uint refIndex, TStringDiffContext &context) - { - TStringInfo si = context.Addition[addIndex]; - char temp[1024]; - sprintf(temp, "// DIFF ADD %u ", addIndex); - si.Comments = ucstring(temp) + nl + si.Comments; - - nlinfo("Added %s at %u", si.Identifier.c_str(), addIndex); - context.Diff.push_back(si); - } - void onRemove(uint addIndex, uint refIndex, TStringDiffContext &context) - { - TStringInfo si = context.Reference[refIndex]; - char temp[1024]; - sprintf(temp, "// DIFF REMOVED %u ", addIndex); - // NB : on vire les commentaires car il pourrais contenir des merdes.. - si.Comments = ucstring(temp) + nl; - - nlinfo("Removed %s at %u", si.Identifier.c_str(), addIndex); - context.Diff.push_back(si); - } - void onChanged(uint addIndex, uint refIndex, TStringDiffContext &context) - { - TStringInfo si = context.Addition[addIndex]; - char temp[1024]; - sprintf(temp, "// DIFF CHANGED %u ", addIndex); - si.Comments = ucstring(temp) + nl + si.Comments; - si.Comments = si.Comments + ucstring("/* OLD VALUE : [") + context.Reference[refIndex].Text + "] */" + nl; - - nlinfo("Changed %s at %u", si.Identifier.c_str(), addIndex); - context.Diff.push_back(si); - } - - void onSwap(uint newIndex, uint refIndex, TStringDiffContext &context) - { - TStringInfo si; - char temp[1024]; - sprintf(temp, "// DIFF SWAP %u %u (swaping %s and %s)", newIndex, refIndex, context.Reference[newIndex].Identifier.c_str(), context.Reference[refIndex].Identifier.c_str()); -// sprintf(temp, "// DIFF SWAP %u %u", newIndex, refIndex); - - si.Comments = ucstring(temp) + nl +nl; - context.Diff.push_back(si); - } - - -}; - - -void makeStringDiff(const vector &addition, vector &reference, vector &diff) -{ - // just building the object will to the job ! - CMakeStringDiff differ; - differ.run(addition, reference, diff); - -/* - // compare the reference an addition file, remove any equivalent strings. - uint addCount=0, refCount=0; - - while (addCount < addition.size() || refCount < reference.size()) - { - bool equal = true; - if (addCount != addition.size() && refCount != reference.size()) - { - equal = addition[addCount].HashValue == reference[refCount].HashValue; - } - - vector::iterator it; - - if (addCount == addition.size() - || - ( - !equal -// && find_if(addition.begin()+addCount, addition.end(), TFindStringInfo(reference[refCount].Identifier)) == addition.end() - && find_if(addition.begin(), addition.end(), TFindStringInfo(reference[refCount].Identifier)) == addition.end() - ) - ) - { - // this can only be removed elements - TStringInfo si = reference[refCount]; - char temp[1024]; - sprintf(temp, "// DIFF REMOVED %u ", addCount); - // NB : on vire les commentaires car il pourrais contenir des merdes.. - si.Comments = ucstring(temp) + nl; - - nlinfo("Removed %s at %u", si.Identifier.c_str(), addCount); - diff.push_back(si); - ++refCount; - } - else if (refCount == reference.size() - || - ( - !equal -// && find_if(reference.begin()+refCount, reference.end(), TFindStringInfo(addition[addCount].Identifier)) == reference.end() - && find_if(reference.begin(), reference.end(), TFindStringInfo(addition[addCount].Identifier)) == reference.end() - ) - ) - { - // this can only be addition - TStringInfo si = addition[addCount]; - char temp[1024]; - sprintf(temp, "// DIFF ADD %u ", addCount); - si.Comments = ucstring(temp) + nl + si.Comments; - - nlinfo("Added %s at %u", si.Identifier.c_str(), addCount); - diff.push_back(si); - ++addCount; - } - else if (addition[addCount].Identifier != reference[refCount].Identifier) - { - // swap two element. - vector::iterator it = find_if(reference.begin(), reference.end(), TFindStringInfo(addition[addCount].Identifier)); - if (it == reference.end()) - { - // addition - TStringInfo si = addition[addCount]; - char temp[1024]; - sprintf(temp, "// DIFF ADD %u ", addCount); - si.Comments = ucstring(temp) + nl + si.Comments; - - nlinfo("Added %s at %u", si.Identifier.c_str(), addCount); - diff.push_back(si); - ++addCount; - } - else - { - nlassert(it != reference.begin()+refCount); - - swap(*it, reference[refCount]); - - TStringInfo si; - char temp[1024]; - sprintf(temp, "// DIFF SWAP %u %u", it - reference.begin(), refCount); - - si.Comments = ucstring(temp) + nl; - diff.push_back(si); - } - } - else if (addition[addCount].HashValue != reference[refCount].HashValue) - { - // changed element - TStringInfo si = addition[addCount]; - char temp[1024]; - sprintf(temp, "// DIFF CHANGED %u ", addCount); - si.Comments = ucstring(temp) + nl + si.Comments; - si.Comments = si.Comments + ucstring("// OLD VALUE : [") + reference[refCount].Text + ']' + nl; - - nlinfo("Changed %s at %u", si.Identifier.c_str(), addCount); - diff.push_back(si); - ++refCount; - ++addCount; - } - else - { - // same entry - nlinfo("Same %s at %u", addition[addCount].Identifier.c_str(), addCount); - addCount++; - refCount++; - } - } -*/ -} - -int makeStringDiff(int argc, char *argv[]) -{ - // this will generate diff from 'addition' directory - // for the reference .uxt file - // with the same file in the 'translated' directory. - - // NB : we use standard C file access because there are mutiple file with the same name in different place. - - vector addition; - - LOG("Generating string diffs\nLoading the working file for language %s\n", Languages[0].c_str()); - // load the addition file - std::string addFile(Languages[0]+".uxt"); - if (!loadStringFile(addDir+addFile, addition, true)) - { - LOG("Error loading file %s\n", (addDir+addFile).c_str()); - return 1; - } - - // for each language - for (uint l=0; l reference; - // load the reference file - std::string refFile(Languages[l]+".uxt"); - if (!loadStringFile(transDir+refFile, reference, false)) - { - LOG("Error loading file %s\n", (transDir+refFile).c_str()); - return 1; - } - - // load any not merged diff file - if (!mergeStringDiff(reference, Languages[l], "", ".uxt", false)) - { - LOG("Error will mergin diff file(s)\n"); - return 1; - } - - vector diff; - makeStringDiff(addition, reference, diff); - - if (diff.empty()) - { - LOG("No difference for %s.\n", Languages[l].c_str()); - } - else - { - LOG("Writting difference file for %s.\n", Languages[l].c_str()); - // build the diff file for each language. - ucstring str = prepareStringFile(diff, false); - - // add the tag for non translation - str += nl + ucstring ("// REMOVE THE FOLOWING LINE WHEN TRANSLATION IS DONE")+nl+ucstring("// DIFF NOT TRANSLATED")+nl; - - std::string diffName(diffDir+Languages[l]+"_diff_"+diffVersion+".uxt"); - CI18N::writeTextFile(diffName, str); - - } - } - - return 0; -} - -/* -Remove the OLD VALUE from a file. -*/ -void cleanComment(const std::string & filename) -{ - ucstring text; - uint nbOldValue=0; - - CI18N::readTextFile(filename, text, false, false, false, CI18N::LINE_FMT_CRLF); - - ucstring newText; - ucstring::size_type last = 0; - while ( last != ucstring::npos) - { - ucstring::size_type commentBegin = text.find(ucstring("/* OLD VALUE :"), last); - if (commentBegin == ucstring::npos) - { - newText += text.substr(last); - last = ucstring::npos; - } - else - { - ucstring::size_type size = commentBegin - last; - ucstring toAdd = text.substr(last, size); - newText += toAdd; - ucstring::size_type commentEnd = text.find(ucstring("*/"), commentBegin); - if (commentEnd != ucstring::npos) { commentEnd += 4; } - last = commentEnd; - ++nbOldValue; - } - } - text = newText; - newText = ucstring(""); - last = 0; - while ( last != ucstring::npos) - { - ucstring::size_type commentBegin = text.find(ucstring("//"), last); - if (commentBegin == ucstring::npos) - { - newText += text.substr(last); - last = ucstring::npos; - } - else - { - ucstring::size_type size = commentBegin - last; - ucstring toAdd = text.substr(last, size); - newText += toAdd; - // case where // is the part of an url and isn't a comment - if (commentBegin > 4 && text.substr(commentBegin-1, 1) == ucstring(":")) - { - newText += "//"; - last = commentBegin+2; - } - else - { - ucstring::size_type commentEnd = text.find(ucstring("\n"), commentBegin); - if (commentEnd != ucstring::npos) - { - commentEnd += 1; - ucstring comment = text.substr(commentBegin, commentEnd - commentBegin); - if (comment.find(ucstring("// HASH_VALUE")) != ucstring::npos - || comment.find(ucstring("// DIFF")) != ucstring::npos - || comment.find(ucstring("// REMOVE")) != ucstring::npos - || comment.find(ucstring("// INDEX")) != ucstring::npos - ) - { - newText += comment; - } - } - last = commentEnd; - ++nbOldValue; - } - } - } - nlinfo("cleaning : %s, (%d comments deleted)...\n", filename.c_str(), nbOldValue); - CI18N::writeTextFile(filename , newText); -} - -/* -REMOVE OLDVALUE: from a diff string file -*/ -int cleanStringDiff(int argc, char *argv[]) -{ - - LOG("Cleaning string diffs\n"); - - uint i,l; - - for (l=0; l diffs; - - getPathContentFiltered(diffDir+Languages[l]+"_diff_", ".uxt", diffs); - for (i=0; i translated; - if (!loadStringFile(filename, translated, false)) - { - LOG("Error will loading file %s\n", filename.c_str()); - return 1; - } - - // append the translated diffs - mergeStringDiff(translated, Languages[l], "", ".uxt", true, true); - - // prepare the addition string - ucstring str = prepareStringFile(translated, true); - - { - // backup the original file - ucstring old; - CI18N::readTextFile(filename, old, false, true, false, CI18N::LINE_FMT_CRLF); - if (old != str) - CFile::moveFile((historyDir+CFile::getFilenameWithoutExtension(filename)+"_"+diffVersion+"."+CFile::getExtension(filename)).c_str(), filename.c_str()); - } - - CI18N::writeTextFile(filename, str); - } - - return 0; -} - - -/* -struct TFindPhrase : unary_function -{ - string Identifier; - TFindPhrase (const string &identifier) - : Identifier(identifier) - {} - bool operator () (const TPhrase &phrase) - { - return phrase.Identifier == Identifier; - } -}; -*/ - - -bool mergePhraseDiff2(vector &phrases, const string &language, bool onlyTranslated, bool archiveDiff); -bool mergePhraseDiff(vector &phrases, const string &language, bool onlyTranslated, bool archiveDiff = false) -{ - vector diffs; - - getPathContentFiltered(diffDir+"phrase_"+language+"_diff_", ".txt", diffs); - - for (uint i=0; i diff; - if (!readPhraseFile1(diffs[i], diff, false)) - return false; - - for (uint j=0; j::IDiffCallback -{ -public: - void run(const vector &addition, vector &reference, vector &diff) - { - TPhraseDiffContext context(addition, reference, diff); - - CMakeDiff differ; - differ.makeDiff(this, context); - } - - void onEquivalent(uint addIndex, uint refIndex, TPhraseDiffContext &context) - { - // nothing to do - } - void onAdd(uint addIndex, uint refIndex, TPhraseDiffContext &context) - { - TPhrase phrase = context.Addition[addIndex]; - char temp[1024]; - sprintf(temp, "// DIFF ADD %u ", addIndex); - phrase.Comments = ucstring(temp) + nl + phrase.Comments; - - nlinfo("Added %s at %u", phrase.Identifier.c_str(), addIndex); - context.Diff.push_back(phrase); - } - void onRemove(uint addIndex, uint refIndex, TPhraseDiffContext &context) - { - TPhrase phrase = context.Reference[refIndex]; - char temp[1024]; - sprintf(temp, "// DIFF REMOVED %u ", addIndex); - // NB : on vire les commentaires car il pourrai contenir des merdes.. - phrase.Comments = ucstring(temp) + nl; - for (uint i=0; i tempV; - tempV.push_back(context.Reference[refIndex]); - ucstring tempT = preparePhraseFile(tempV, false); - CI18N::removeCComment(tempT); - phrase.Comments = ucstring(temp) + nl + phrase.Comments; - phrase.Comments = phrase.Comments + ucstring("/* OLD VALUE : ["+nl) + tabLines(1, tempT) +nl + "] */" + nl; - phrase.Comments = phrase.Comments + chg; - - nlinfo("Changed %s at %u", phrase.Identifier.c_str(), addIndex); - context.Diff.push_back(phrase); - } - - void onSwap(uint newIndex, uint refIndex, TPhraseDiffContext &context) - { - TPhrase phrase; - char temp[1024]; - sprintf(temp, "// DIFF SWAP %u %u (swaping %s and %s)", newIndex, refIndex, context.Reference[newIndex].Identifier.c_str(), context.Reference[refIndex].Identifier.c_str()); - - nldebug("Swap for %u %u", newIndex, refIndex); - phrase.Comments = ucstring(temp) + nl; - context.Diff.push_back(phrase); - } - -}; - - - -int makePhraseDiff(int argc, char *argv[]) -{ - // Generate the diff file from phrase_.txt compared to the same file in translated. - // The diff is generated only from the reference language for and all the languages - - LOG("Generating phrase diffs\nLoading the working file for language %s\n", Languages[0].c_str()); - - - vector addition; - - // read addition - if (!readPhraseFile(addDir+"phrase_"+Languages[0]+".txt", addition, true)) - { - LOG("Error will loading file %s", (addDir+"phrase_"+Languages[0]+".txt").c_str()); - return 1; - } - - for (uint l =0; l reference; - // read the reference file - if (!readPhraseFile(transDir+"phrase_"+Languages[l]+".txt", reference, false)) - { - LOG("Error will loading file %s", (transDir+"phrase_"+Languages[l]+".txt").c_str()); - return 1; - } - - if (!mergePhraseDiff(reference, Languages[l], false)) - { - LOG("Error will merging phrase diff for language %s\n", Languages[l].c_str()); - return 1; - } - - // compare the reference an addition file, remove any equivalent strings. - uint addCount=0, refCount=0; - vector diff; - - CMakePhraseDiff differ; - differ.run(addition, reference, diff); - - if (diff.empty()) - { - LOG("No difference for language %s\n", Languages[l].c_str()); - } - else - { - LOG("Writing difference file for language %s\n", Languages[l].c_str()); - ucstring text; - text += "// DIFF_VERSION 1\r\n"; - text += preparePhraseFile(diff, false); - // add the tag for non translation - text += nl + ucstring ("// REMOVE THE FOLOWING LINE WHEN TRANSLATION IS DONE")+nl+ucstring("// DIFF NOT TRANSLATED")+nl; - CI18N::writeTextFile(diffDir+"phrase_"+Languages[l]+"_diff_"+diffVersion+".txt", text); - } - } - - return 0; -} - - -/* -REMOVE OLDVALUE: from a diff clause file -*/ -int cleanPhraseDiff(int argc, char *argv[]) -{ - - LOG("Cleaning phrase diffs\n"); - - uint i,l; - - for (l=0; l diffs; - - getPathContentFiltered(diffDir+"phrase_"+Languages[l]+"_diff_", ".txt", diffs); - for (i=0; i reference; - - ucstring doc; - - - if (!readPhraseFile(transDir+basename+".txt", reference, false)) - { - LOG("Error will loading file %s", (transDir+basename+".txt").c_str()); - return 1; - } - - - switch(version) - { - case 1: - if (!mergePhraseDiff(reference, Languages[l], true, true)) - { - LOG("Error will merging phrase diff"); - return 1; - } - break; - - case 2: - - if (!mergePhraseDiff2(reference, Languages[l], true, true)) - { - LOG("Error will merging phrase diff"); - return 1; - } - break; - - default: - nlassert(0); - - } - - ucstring str = preparePhraseFile(reference, true); - - { - // backup the original file - ucstring old; - CI18N::readTextFile(filename, old, false, true, false, CI18N::LINE_FMT_CRLF); - if (old != str) - CFile::moveFile((historyDir+CFile::getFilenameWithoutExtension(filename)+"_"+diffVersion+"."+CFile::getExtension(filename)).c_str(), filename.c_str()); - } - - CI18N::writeTextFile(transDir+basename+".txt", str); - - } - - return 0; -} - - -int makeClauseDiff(int argc, char *argv[]) -{ - // this will generate diff from 'addition' directory - // for all the clause_.txt file - // with the same file in the 'translated' directory. - - // NB : we use standard C file access because there are mutiple file with the same name in different place. - - LOG("Generating clause diffs\n"); - - uint i,l; - - for (l=0; l addition; - vector reference; - vector phrases; - std::vector warnings; - - // load the reference file - std::string refFile(basename+".txt"); - if (!loadStringFile(transDir+refFile, reference, false)) - { - LOG("Error will loading file %s", (transDir+refFile).c_str()); - return 1; - } - - // load the addition file - std::string addFile("phrase_"+Languages[l]+".txt"); - if (!readPhraseFile(transDir+addFile, phrases, true)) - { - LOG("Error will loading file %s", (transDir+addFile).c_str()); - return 1; - } - - // extract all the clauses from the phrases file - vector::iterator first(phrases.begin()), last(phrases.end()); - for (; first != last; ++first) - { - TPhrase &p = *first; - for (i=0; i::const_iterator first2 = addition.begin(); - vector::const_iterator last2 = addition.end(); - for ( ;first2!=last2 && first2->Identifier != si.Identifier; ++first2) {} - bool isAllreadyThere = first2 != last2; - if (isAllreadyThere) - { - warnings.push_back("The clause " +si.Identifier +" in the phrase " + p.Identifier +" exists more than once."); - } - else - { - addition.push_back(si); - } - } - } - } - - if (!warnings.empty()) - { - std::vector::const_iterator first = warnings.begin(); - std::vector::const_iterator last = warnings.end(); - for (;first != last; ++first) { nlwarning("%s", first->c_str()); } - return -1; - } - mergeStringDiff(reference, Languages[l], "clause_", ".txt", false); - - vector diff; - - makeStringDiff(addition, reference, diff); - - if (diff.empty()) - { - LOG("No difference for language %s\n", Languages[l].c_str()); - } - else - { - LOG("Writing difference file for %s.\n", Languages[l].c_str()); - // build the diff file for each language. - ucstring str = prepareStringFile(diff, false); - - // add the tag for non translation - str += nl + ucstring ("// REMOVE THE FOLOWING LINE WHEN TRANSLATION IS DONE")+nl+ucstring("// DIFF NOT TRANSLATED")+nl; - - std::string diffName(diffDir+"clause_"+Languages[l]+"_diff_"+diffVersion+".txt"); - CI18N::writeTextFile(diffName, str); - } - } - - return 0; -} - - -/* -REMOVE OLDVALUE: from a diff clause file -*/ -int cleanClauseDiff(int argc, char *argv[]) -{ - - LOG("Cleaning clause diffs\n"); - - uint i,l; - - for (l=0; l diffs; - - getPathContentFiltered(diffDir+"clause_"+Languages[l]+"_diff_", ".txt", diffs); - for (i=0; i translated; - if (!loadStringFile(filename, translated, false)) - { - LOG("Error will loading file %s", filename.c_str()); - return 1; - } - - // append the translated diffs - mergeStringDiff(translated, Languages[l], "clause_", ".txt", true, true); - - // prepare the addition string - ucstring str = prepareStringFile(translated, true); - - { - // backup the original file - ucstring old; - CI18N::readTextFile(filename, old, false, true, false, CI18N::LINE_FMT_CRLF); - if (old != str) - CFile::moveFile((historyDir+CFile::getFilenameWithoutExtension(filename)+"_"+diffVersion+"."+CFile::getExtension(filename)).c_str(), filename.c_str()); - } - - CI18N::writeTextFile(filename, str); - } - - return 0; - - return 0; -} - -bool mergeWorksheetDiff(const std::string filename, TWorksheet &sheet, bool onlyTranslated, bool archiveDiff) -{ - std::string fn(CFile::getFilenameWithoutExtension(filename)), ext(CFile::getExtension(filename)); - vector fileList; - getPathContentFiltered(diffDir+fn+"_diff_", ext, fileList); - - uint i; - for (i=0; i 0); - sheet.Data.erase(sheet.Data.begin() + diffInfo.Index1); - break; - case diff_swap: - nlassertex(diffInfo.Index1 < sheet.Data.size(), - ("SWAP cmd in diff file, first index reference row %u, but worksheet only contains %u entries", - diffInfo.Index1, sheet.Data.size())); -// nlassertex(diffInfo.Index1 > 0); - nlassertex(diffInfo.Index2 < sheet.Data.size(), - ("SWAP cmd in diff file, second index reference row %u, but worksheet only contains %u entries", - diffInfo.Index1, sheet.Data.size())); -// nlassertex(diffInfo.Index2 > 0); - swap(sheet[diffInfo.Index1], sheet[diffInfo.Index2]); - break; - default: - nlassert(false); - } - - } - - if (archiveDiff) - { - // move the diff file in the history dir - CFile::moveFile((historyDir+CFile::getFilename(fileList[i])).c_str(), fileList[i].c_str()); - } - } - - return true; -} - - - -bool mergeSheetDiff(const string &type, TWorksheet &sheet, const string &language, bool onlyTranslated, bool archiveDiff) -{ - return mergeWorksheetDiff(type+"_words_"+language+".txt", sheet, onlyTranslated, archiveDiff); -} - - -class CMakeWordsDiff : public TWorkSheetDiff::IDiffCallback -{ -public: - void run(const TWorksheet &addition, TWorksheet &reference, TWorksheet &diff) - { - TWordsDiffContext context(addition, reference, diff); - - TWorkSheetDiff differ; - differ.makeDiff(this, context, true); - } - - void onEquivalent(uint addIndex, uint refIndex, TWordsDiffContext &context) - { - // nothing to do - } - void onAdd(uint addIndex, uint refIndex, TWordsDiffContext &context) - { - TWorksheet::TRow row(context.Reference.ColCount+1); - for (uint j=0; j diffs; - - getPathContentFiltered(diffDir+"clause_"+Languages[l]+"_diff_", ".txt", diffs); - for (i=0; i 0) - CI18N::writeTextFile(transDir+filename, str, false); - - return 0; -} - - -int makeWordsDiff(int argc, char *argv[]) -{ - vector fileList; - CPath::getPathContent(addDir, false, false, true, fileList); - - // filter in words file only - uint i; - for (i=0; i fileList; - CPath::getPathContent(addDir, false, false, true, fileList); - - // filter in words file only - for (uint i=0; i count(c2.Conditions.begin(), c2.Conditions.end(), '&'); - } -}; - -int recupAround(int argc, char *argv[]) -{ - string clause1(diffDir+"clause_en_diff_3E896220.txt"); - string clause2(addDir+"clause_en_diff_3E7B4CE4 TRANSLATED.txt"); - - vector reference; - loadStringFile(clause1, reference, true); - vector around; - loadStringFile(clause2, around, true, '[', ']', true); - - vector result; - - nlassert(reference.size() == around.size()); - - for (uint i=0; i lines; - explode(text, std::string("\n"), lines); - - text.clear(); - if (lines.size() > nbLines) - { - for (uint i=0; i files; - uint i; - - // move en.uxt file to wk.uxt - CFile::moveFile((CPath::standardizePath(addDir)+"wk.uxt").c_str(), (CPath::standardizePath(addDir)+"en.uxt").c_str()); - - files.clear(); - CPath::getPathContent(addDir, true, false, true, files); - - string strreplaced("_en.txt"); - string strtoreplace("_wk.txt"); - - for (i=0; i > & outputResult); - -void assertUniq(const vector& reference) -{ - - std::set< std::string > phraseIdentifier; - std::set< std::string > clauseIdentifier; - vector::const_iterator first( reference.begin() ); - vector::const_iterator last( reference.end() ); - for( ; first != last; ++first) - { - if ( phraseIdentifier.find(first->Identifier) != phraseIdentifier.end()) - { - nlwarning("Phrase %s defined more than once.", first->Identifier.c_str()); - exit(-1); - } - else - { - phraseIdentifier.insert(first->Identifier); - vector::const_iterator first2( first->Clauses.begin() ); - vector::const_iterator last2( first->Clauses.end() ); - if (clauseIdentifier.find(first2->Identifier) != clauseIdentifier.end() ) - { - nlwarning("Clause %s defined more than once.", first2->Identifier.c_str()); - exit(-1); - } - } - } - -} - - -void mergePhraseDiff2Impl(vector& reference, const vector& addition) -{ - assertUniq(reference); - assertUniq(addition); - - typedef std::map TMap; - - TMap phrases; - - { - vector::const_iterator first( reference.begin() ); - vector::const_iterator last( reference.end() ); - for( ; first != last ; ++first ) - { - std::string identifier = first->Identifier; - phrases[identifier] = *first; - } - } - - { - vector::const_iterator first( addition.begin() ); - vector::const_iterator last( addition.end() ); - for( ; first != last ; ++first ) - { - if ( first->Comments.find(ucstring("DIFF CHANGED")) != ucstring::npos) - { - nlassert( phrases.find(first->Identifier) != phrases.end() ); - phrases[first->Identifier] = *first; - } - else if ( first->Comments.find(ucstring("DIFF ADD")) != ucstring::npos) - { - nlassert( phrases.find(first->Identifier) == phrases.end() ); - phrases[first->Identifier] = *first; - - } - else if ( first->Comments.find(ucstring("DIFF REMOVED")) != ucstring::npos) - { - nlassert( phrases.find(first->Identifier) != phrases.end() ); - phrases.erase( phrases.find(first->Identifier)); - } - else - { - // nlassert(0 && "INVALID DIFF COMMAND"); - } - } - } - - { - reference.clear(); - reference.reserve(phrases.size()); - TMap::const_iterator first( phrases.begin() ); - TMap::const_iterator last( phrases.end() ); - for( ; first != last; ++first) { reference.push_back(first->second); } - } - -} - -void removeHashValueComment(ucstring & comments) -{ - ucstring::size_type first; - ucstring::size_type last; - first = comments.rfind(ucstring("// HASH_VALUE")); - if (first != ucstring::npos) - { - last = comments.find(ucstring("\n"), first); - if (last != ucstring::npos) - { - last += 1; - ucstring tmp1 = comments.substr(0, first); - ucstring tmp2 = last !=comments.size() - ? comments.substr(last) - : ucstring(""); - comments = tmp1 + tmp2; - } - else - { - comments = comments.substr(0, first); - } - } - else - { - //comments = comments; - } - -} - -bool updateClauseHashValue(const std::map >& validValues, const std::string & dirPath = "") -{ - - for (uint l=0; l clauses; - std::string refFile(basename+".txt"); - if (!loadStringFile(transDir+refFile, clauses, false)) - { - LOG("Error will loading file %s", (transDir+refFile).c_str()); - return false; - } - - bool changed = false; - for ( uint i=0; i < clauses.size() ; ++i) - { - std::string Identifier = clauses[i].Identifier; - if ( validValues.find(Identifier) != validValues.end()) - { - if (!validValues.find(Identifier)->second.second - || clauses[i].HashValue == validValues.find(Identifier)->second.second) - { - clauses[i].HashValue = validValues.find(Identifier)->second.first; - removeHashValueComment(clauses[i].Comments); - changed = true; - } - } - } - - if (!changed) - { - nlwarning("Clauses file don't need update for language %s\n", Languages[l].c_str()); - } - else - { - nlinfo("Updating hashcode of clause file for %s.\n", Languages[l].c_str()); - // build the diff file for each language. - ucstring str = prepareStringFile(clauses, false); - std::string clauseName(dirPath+ transDir + basename +".txt"); - CFile::createDirectoryTree( CFile::getPath(clauseName) ); - CI18N::writeTextFile(clauseName, str); - } - - } - return true; -} - -ucstring preparePhraseFile2(const vector &phrases, bool removeDiffComments) -{ - ucstring ret; - vector::const_iterator first(phrases.begin()), last(phrases.end()); - for (; first != last; ++first) - { - const TPhrase &p = *first; - - if (removeDiffComments) - { - string comment = p.Comments.toString(); - vector lines; - explode(comment, std::string("\n"), lines, true); - - uint i; - for (i=0; i > & validValues, const std::string & dirPath = "") -{ - - for (uint l=0; l phrases; - std::string refFile(basename+".txt"); - if (!readPhraseFile(transDir+refFile, phrases, false)) - { - LOG("Error will loading file %s", (transDir+refFile).c_str()); - return false; - } - - bool changed = false; - for ( uint i=0; i < phrases.size() ; ++i) - { - std::string Identifier = phrases[i].Identifier; - if ( validValues.find(Identifier) != validValues.end()) - { - if (!validValues.find(Identifier)->second.second || phrases[i].HashValue == validValues.find(Identifier)->second.second ) - { - - phrases[i].HashValue = validValues.find(Identifier)->second.first; - removeHashValueComment(phrases[i].Comments); - changed = true; - } - } - } - - if (!changed) - { - nlinfo("Phrase file don't need update for language %s\n", Languages[l].c_str()); - } - else - { - nlinfo("Updating hashcode of phrase file for %s.\n", Languages[l].c_str()); - // build the diff file for each language. - ucstring str = preparePhraseFile(phrases, false); - std::string pharseName(dirPath+ transDir + basename +".txt"); - CFile::createDirectoryTree( CFile::getPath(pharseName) ); - CI18N::writeTextFile(pharseName, str); - } - - } - return true; -} - - -bool sortTransPhrase() -{ - - for (uint l=0; l phrases; - vector phrases2; - std::map phraseMap; - std::string refFile(basename+".txt"); - if (!readPhraseFile(transDir+refFile, phrases, false)) - { - LOG("Error will loading file %s", (transDir+refFile).c_str()); - return false; - } - - { - - std::vector::const_iterator first(phrases.begin()); - std::vector::const_iterator last(phrases.end()); - for ( ; first != last; ++first) - { - phraseMap[first->Identifier] = *first; - } - } - { - std::map::const_iterator first(phraseMap.begin()); - std::map::const_iterator last(phraseMap.end()); - for ( ; first != last; ++first) - { - phrases2.push_back( first->second); - } - } - - - nlinfo("Updating hashcode of phrase file for %s.\n", Languages[l].c_str()); - // build the diff file for each language. - ucstring str = preparePhraseFile(phrases2, false); - std::string pharseName(transDir+refFile); - CFile::createDirectoryTree( CFile::getPath(pharseName) ); - CI18N::writeTextFile(pharseName, str); - } - return true; -} - - - -void patchWorkFile(vector &updatedPhrase, const std::string & filename) -{ - ucstring text; - if ( updatedPhrase.empty() ) { return; } - CI18N::readTextFile(filename, text, false, false, false, CI18N::LINE_FMT_CRLF); - vector::const_iterator first(updatedPhrase.begin()); - vector::const_iterator last(updatedPhrase.end()); - for (; first != last; ++first) - { - - ucstring::size_type firstFun = text.find( ucstring(first->Identifier)); - if (firstFun == ucstring::npos) - { - nlwarning("Error can't patch %s: %s not found", filename.c_str(), first->Identifier.c_str()); - } - else - { - ucstring::size_type lastFun = text.find( ucstring("}") , firstFun); - if (lastFun == ucstring::npos) - { - nlwarning("Error can't patch %s: syntax error near %s", filename.c_str(), first->Identifier.c_str()); - } - else - { - std::vector param; - param.push_back(*first); - - ucstring before = text.substr(0,firstFun); - ucstring str = preparePhraseFile2(param, false); - ucstring after = text.substr(lastFun+1); - text = ""; - text += before; - text += str; - text += after; - } - } - } - CI18N::writeTextFile( filename, text); - -} - -int updatePhraseWork() -{ - std::string saveDir = diffDir + "update_"+ diffVersion + "/"; - vector transPhrase; - std::map transPhraseMap; - std::map > validClauseHashValue; - std::map > validPhraseHashValue; - std::vector< std::pair > outputResult; - - if (!readPhraseFile(transDir+"phrase_wk.txt", transPhrase, false)) - { - LOG("Error will loading file %s", (addDir+"phrase_"+Languages[0]+".txt").c_str()); - return 1; - } - - { - std::vector::const_iterator first(transPhrase.begin()); - std::vector::const_iterator last(transPhrase.end()); - for (; first != last;++first) - { - transPhraseMap[first->Identifier] = *first; - } - } - - preprocessTextFile(addDir+"phrase_wk.txt", outputResult); - - uint firstFile = 0; - uint lastFile = (uint)outputResult.size(); - for (; firstFile != lastFile ; ++firstFile) - { - - ucstring doc = outputResult[firstFile].first; - std::vector phrases; - readPhraseFileFromString(outputResult[firstFile].first, outputResult[firstFile].second, phrases, true); - - std::vector::iterator first(phrases.begin()); - std::vector::iterator last(phrases.end()); - std::vector updatedPhrases; - for (; first != last; ++first) - { - if (transPhraseMap.find(first->Identifier) != transPhraseMap.end() ) - { - TPhrase workPhrase = *first; - TPhrase& transPhrase = transPhraseMap[first->Identifier]; - if (first->HashValue == transPhrase.HashValue) - { - uint64 oldHash = transPhrase.HashValue; - uint64 newHash = STRING_MANAGER::makePhraseHash(transPhrase); - if (newHash != transPhrase.HashValue) - { - //translation phrase_wk.txt has been manually changed - validPhraseHashValue[transPhrase.Identifier] = std::pair(newHash, oldHash); - std::vector::iterator firstClause ( transPhrase.Clauses.begin() ); - std::vector::iterator lastClause ( transPhrase.Clauses.end() ); - for (; firstClause != lastClause; ++firstClause) - { - uint64 clauseHashValue = CI18N::makeHash(firstClause->Text); - - validClauseHashValue[firstClause->Identifier] = std::pair(clauseHashValue, firstClause->HashValue); - firstClause->HashValue = clauseHashValue; - } - updatedPhrases.push_back(transPhrase); - updatedPhrases.back().Comments= ucstring(""); - } - } - } - } - - - std::string newFile = saveDir + outputResult[firstFile].second; - std::string oldFile = outputResult[firstFile].second; - CFile::createDirectoryTree(CFile::getPath(newFile)); - if ( CFile::copyFile(newFile, oldFile) ) - { - - patchWorkFile(updatedPhrases, newFile); - } - else - { - nlwarning("Can't copy %s", newFile.c_str()); - } - - } - - updatePhraseHashValue(validPhraseHashValue, saveDir); - updateClauseHashValue(validClauseHashValue, saveDir); - return 0; -} - - - - -bool mergePhraseDiff2(vector &phrases, const string &language, bool onlyTranslated, bool archiveDiff = false) -{ - vector diffs; - - getPathContentFiltered(diffDir+"phrase_"+language+"_diff_", ".txt", diffs); - - for (uint i=0; i diff; - if (!readPhraseFile2(diffs[i], diff, false)) - return false; - - - mergePhraseDiff2Impl(phrases, diff); - - - if (archiveDiff) - { - // move the diff file in the history dir - CFile::moveFile((historyDir+CFile::getFilename(diffs[i])).c_str(), diffs[i].c_str()); - } - } - - return true; -} - - - -class CMakePhraseDiff2 -{ -public: - - class CPhraseEqual - { - - public: - CPhraseEqual(){} - - bool operator()( const TPhrase& left, const TPhrase& right) const; - -// bool clausesEqual( const std::vector& left, const std::vector& right) const; - -// bool clauseEqual(const TClause& left, const TClause& right) const; - - }; - - void run(const vector &addition, vector &reference, vector &diff); - - void onEquivalent(uint addIndex, uint refIndex, TPhraseDiffContext &context); - - void onAdd(uint addIndex, uint refIndex, TPhraseDiffContext &context); - - void onRemove(uint addIndex, uint refIndex, TPhraseDiffContext &context); - - void onChanged(uint addIndex, uint refIndex, TPhraseDiffContext &context); - - -}; - - - - - - -void CMakePhraseDiff2::run(const vector &addition, vector &reference, vector &diff) -{ - - TPhraseDiffContext context(addition, reference, diff); - - std::set phraseIdentifier; - std::map mapAdd; - std::map mapRef; - - { - uint first = 0; - uint last = (uint)reference.size(); - - for ( ;first != last; ++first) - { - std::string Identifier(reference[first].Identifier); - mapRef[Identifier] = first; - phraseIdentifier.insert(Identifier); - } - } - - { - uint first = 0; - uint last = (uint)addition.size(); - - for ( ;first != last; ++first) - { - std::string Identifier(addition[first].Identifier); - mapAdd[Identifier] = first; - phraseIdentifier.insert(Identifier); - } - } - - if (mapAdd.size() != addition.size()) - { - nlwarning("Phrases are defined more than once in works directory"); - } - - if (mapAdd.size() != addition.size()) - { - nlwarning("Phrases are defined more than once in translation directory"); - } - - - std::set::iterator first(phraseIdentifier.begin()); - std::set::iterator last(phraseIdentifier.end()); - - for (; first != last; ++first) - { - if ( mapAdd.find(*first) != mapAdd.end() - && mapRef.find(*first) != mapRef.end()) - { - - if ( CPhraseEqual()(addition[mapAdd[*first]], reference[mapRef[*first]]) ) - { - onEquivalent(mapAdd[*first], mapRef[*first], context); - } - else - { - onChanged(mapAdd[*first], mapRef[*first], context); - } - } - else if ( mapAdd.find(*first) != mapAdd.end() - && mapRef.find(*first) == mapRef.end()) - { - onAdd(mapAdd[*first], 0, context); - } - else if ( mapAdd.find(*first) == mapAdd.end() - && mapRef.find(*first) != mapRef.end()) - { - onRemove(0, mapRef[*first], context); - } - - } - -} - - -void CMakePhraseDiff2::onEquivalent(uint addIndex, uint refIndex, TPhraseDiffContext &context) -{ - // nothing to do -} -void CMakePhraseDiff2::onAdd(uint addIndex, uint refIndex, TPhraseDiffContext &context) -{ - TPhrase phrase = context.Addition[addIndex]; - char temp[1024]; - sprintf(temp, "// DIFF ADD"); - phrase.Comments = ucstring(temp) + nl + phrase.Comments; - - nlinfo("Added %s at %u", phrase.Identifier.c_str(), addIndex); - context.Diff.push_back(phrase); -} - -void CMakePhraseDiff2::onRemove(uint addIndex, uint refIndex, TPhraseDiffContext &context) -{ - TPhrase phrase = context.Reference[refIndex]; - char temp[1024]; - sprintf(temp, "// DIFF REMOVED"); - // NB : on vire les commentaires car il pourrai contenir des merdes.. - phrase.Comments = ucstring(temp) + nl; - for (uint i=0; i tempV; - tempV.push_back(context.Reference[refIndex]); - ucstring tempT = preparePhraseFile(tempV, false); - CI18N::removeCComment(tempT); - phrase.Comments = ucstring(temp) + nl + phrase.Comments; - phrase.Comments = phrase.Comments + ucstring("/* OLD VALUE : ["+nl) + tabLines(1, tempT) +nl + "] */" + nl; - phrase.Comments = phrase.Comments + chg; - - nlinfo("Changed %s at %u", phrase.Identifier.c_str(), addIndex); - context.Diff.push_back(phrase); -} - - -bool CMakePhraseDiff2::CPhraseEqual::operator()( const TPhrase& left, const TPhrase& right) const -{ - bool identifierOk = left.Identifier == right.Identifier; -// bool parameterOk = left.Parameters == right.Parameters; -// bool commentsOk = left.Comments == right.Comments; -// bool clausesOk = clausesEqual(left.Clauses, right.Clauses); - bool hashOk = left.HashValue== right.HashValue; - - return identifierOk && hashOk;// && parameterOk && clausesOk; - -} -/* -bool CMakePhraseDiff2::CPhraseEqual::clausesEqual( const std::vector& left, const std::vector& right) const -{ - std::vector::const_iterator first1(left.begin()); - std::vector::const_iterator last1(left.end()); - std::vector::const_iterator first2(right.begin()); - - if (left.size() != right.size()) return false; - - for ( ; first1 != last1 && !clauseEqual(*first1, *first2); ++first1, ++first2){} - - return first1 == last1; -} - -bool CMakePhraseDiff2::CPhraseEqual::clauseEqual(const TClause& left, const TClause& right) const -{ - return left.Identifier != right.Identifier - && left.Conditions != right.Conditions - && left.Text != right.Text - && left.Comments != right.Comments - && left.HashValue != right.HashValue; -} - -*/ - - - -int makePhraseDiff2(int argc, char *argv[]) -{ - // Generate the diff file from phrase_.txt compared to the same file in translated. - // The diff is generated only from the reference language for and all the languages - - LOG("Generating phrase diffs\nLoading the working file for language %s\n", Languages[0].c_str()); - - - vector addition; - - // read addition - if (!readPhraseFile(addDir+"phrase_"+Languages[0]+".txt", addition, true)) - { - LOG("Error will loading file %s", (addDir+"phrase_"+Languages[0]+".txt").c_str()); - return 1; - } - - for (uint l =0; l reference; - // read the reference file - if (!readPhraseFile(transDir+"phrase_"+Languages[l]+".txt", reference, false)) - { - LOG("Error will loading file %s", (transDir+"phrase_"+Languages[l]+".txt").c_str()); - return 1; - } - - if (!mergePhraseDiff2(reference, Languages[l], false)) - { - LOG("Error will merging phrase diff for language %s\n", Languages[l].c_str()); - return 1; - } - - // compare the reference an addition file, remove any equivalent strings. - uint addCount=0, refCount=0; - vector diff; - - CMakePhraseDiff2 differ; - differ.run(addition, reference, diff); - - if (diff.empty()) - { - LOG("No difference for language %s\n", Languages[l].c_str()); - } - else - { - LOG("Writing difference file for language %s\n", Languages[l].c_str()); - ucstring text; - text += "// DIFF_VERSION 2\r\n"; - text += preparePhraseFile(diff, false); - // add the tag for non translation - text += nl + ucstring ("// REMOVE THE FOLOWING LINE WHEN TRANSLATION IS DONE")+nl+ucstring("// DIFF NOT TRANSLATED")+nl; - CI18N::writeTextFile(diffDir+"phrase_"+Languages[l]+"_diff_"+diffVersion+".txt", text); - } - } - - return 0; -} - - - -int forgetPhraseDiff(int argc, char *argv[]) -{ - // merge all the phrase diff back into there repective translated phrase. - - LOG("forgeting phrase diffs\n"); - - std::string basename("phrase_"+Languages[0]); - string filename = transDir+basename+".txt"; - // build the addition diff - vector reference; - - - if (!readPhraseFile(transDir+basename+".txt", reference, false)) - { - LOG("Error will loading file %s", (transDir+basename+".txt").c_str()); - return 1; - } - //assert only change - - std::vector diffs; - getPathContentFiltered(diffDir+"phrase_wk_diff_", ".txt", diffs); - std::vector newPhrase; - for (uint i=0; i subDiff; - if (!readPhraseFile2(diffs[i], subDiff, false)) - return false; - std::copy (subDiff.begin (), subDiff.end (), std::back_inserter (newPhrase)); - } - - // a optimiser par une map - std::map > validClauseHashValue; - std::map > validPhraseHashValue; - for (uint i=0; i < newPhrase.size() ; ++i) - { - for (uint j=0; j < reference.size() ; ++j) - { - if (newPhrase[i].Identifier == reference[j].Identifier) - { - - - uint64 newPhraseHash = STRING_MANAGER::makePhraseHash( newPhrase[i] ); - uint64 oldPhraseHash = reference[j].HashValue; - validPhraseHashValue[newPhrase[i].Identifier] = std::pair(newPhraseHash, oldPhraseHash); - - for (uint k=0; k < newPhrase[i].Clauses.size() ; ++k) - { - if (reference[j] .Clauses.size() != newPhrase[i].Clauses.size()) - { - nlwarning("Want to forget minor update but phrase %s changes too much. The number of clauses has changed.", newPhrase[i].Identifier.c_str() ); - exit(-1); - } - const TClause& newClause = newPhrase[i].Clauses[k]; - const TClause& oldClause = reference[j].Clauses[k]; - - if (!newClause.Identifier.empty() ) - { - if (newClause.Identifier != oldClause.Identifier) - { - nlwarning("Want to forget minor update but phrase %s changes too much. Clauses order or clause identifier changed (%s).", newPhrase[i].Identifier.c_str(), newClause.Identifier.c_str()); - exit(-1); - } - uint64 newClauseHashValue = CI18N::makeHash(newClause.Text); - uint64 oldClauseHashValue = CI18N::makeHash(oldClause.Text); - validClauseHashValue[ newClause.Identifier ] = std::pair(newClauseHashValue, oldClauseHashValue); - } - } - } - } - } - - - if (!mergePhraseDiff2(reference, Languages[0], true, false)) - { - LOG("Error will merging phrase diff"); - return 1; - } - ucstring str = preparePhraseFile(reference, true); - CI18N::writeTextFile(transDir+basename+".txt", str); - - - updatePhraseHashValue(validPhraseHashValue); -// updateClauseHashValue(validClauseHashValue); - - - for (uint i=0; i > & outputResult - ) - -{ - //nlinfo("preprocessing %s", filename.c_str()); - ucstring result; - std::string fullName; - fullName = filename; - - if (fullName.empty()) - return; - - NLMISC::CIFile file; - - /// Open a file for reading. false if failed. close() if a file was opened. - if (!file.open (fullName)) - { - nlwarning("Can't open %s", fullName.c_str()); - return ; - } - - - - // Fast read all the text in binary mode. - std::string text; - text.resize(file.getFileSize()); - file.serialBuffer((uint8*)(&text[0]), (uint)text.size()); - - - // Transform the string in ucstring according to format header - if (!text.empty()) - CI18N::readTextBuffer((uint8*)&text[0], (uint)text.size(), result, false); - - - - ucstring final; - // parse the file, looking for preprocessor command. - ucstring::size_type pos = 0; - ucstring::size_type lastPos = 0; - ucstring includeCmd("#include"); - ucstring current; - - while ( pos != ucstring::npos) - { - pos = result.find(ucstring("\n"), pos); - if (pos != ucstring::npos) { ++pos; } - - ucstring line( result.substr(lastPos, pos - lastPos) ); - - - if ( line.find(includeCmd) != ucstring::npos) - { - ucstring::size_type firstFilename = line.find(ucstring("\"")); - ucstring::size_type lastFilename = line.find(ucstring("\""), firstFilename+1); - - ucstring name = line.substr(firstFilename +1, lastFilename - firstFilename -1); - string subFilename = name.toString(); - { - CIFile testFile; - if (!testFile.open(subFilename)) - { - // try to open the include file relative to current file - subFilename = CFile::getPath(filename)+subFilename; - } - } - preprocessTextFile(subFilename, outputResult); - } - else - { - current += line; - } - lastPos = pos; - - } - - - - outputResult.push_back( std::pair ( current, fullName ) ); -} - -int mergePhraseDiff(int argc, char *argv[]) -{ - // merge all the phrase diff back into there repective translated phrase. - uint l; - - LOG("Merging phrase diffs\n"); - - for (l=0; l reference; - - if (!readPhraseFile(transDir+basename+".txt", reference, false)) - { - LOG("Error will loading file %s", (transDir+basename+".txt").c_str()); - return 1; - } - - if (!mergePhraseDiff(reference, Languages[l], true, true)) - { - LOG("Error will merging phrase diff"); - return 1; - - } - - ucstring str = preparePhraseFile(reference, true); - - { - // backup the original file - ucstring old; - CI18N::readTextFile(filename, old, false, true, false, CI18N::LINE_FMT_CRLF); - if (old != str) - CFile::moveFile((historyDir+CFile::getFilenameWithoutExtension(filename)+"_"+diffVersion+"."+CFile::getExtension(filename)).c_str(), filename.c_str()); - } - - CI18N::writeTextFile(transDir+basename+".txt", str); - - } - - return 0; -} - - -int injectClause() -{ - uint l; - - LOG("Update translation from clauses.\n"); - - for (l=0; l clauses; - vector phrases; - - // load the clause file - std::string clausePath( transDir+"clause_"+Languages[l]+".txt" ); - if (!loadStringFile(clausePath, clauses, false)) - { - LOG("Error will loading file %s", clausePath.c_str()); - return 1; - } - - // load the phrase file - std::string phrasePath( transDir+"phrase_"+Languages[l]+".txt" ); - if (!readPhraseFile(phrasePath, phrases, false)) - { - LOG("Error will loading file %s", phrasePath.c_str()); - return 1; - } - - vector::iterator first(phrases.begin()); - vector::iterator last(phrases.end()); - for ( ; first != last; ++first) - { - - vector::iterator firstClause( first->Clauses.begin()); - vector::iterator lastClause( first->Clauses.end()); - for ( ; firstClause != lastClause; ++firstClause) - { - uint64 hashValue = CI18N::makeHash(firstClause->Text); - vector::iterator firstRefClause(clauses.begin()); - vector::iterator lastRefClause(clauses.end()); - for ( ; firstRefClause != lastRefClause ; ++firstRefClause) - { - if (hashValue == firstRefClause->HashValue && firstClause->Text != firstRefClause->Text) - { - firstClause->Text = firstRefClause->Text; - firstClause->HashValue = CI18N::makeHash(firstClause->Text); - firstRefClause->HashValue = firstClause->HashValue; - - - nlinfo("update clause %s from clause file %s.", firstClause->Identifier.c_str(), clausePath.c_str()); - } - } - } - } - - std::string desDir(diffDir + "inject_clause_" + diffVersion + "/"); - CFile::createDirectoryTree(desDir+ CFile::getPath(phrasePath)); - ucstring str = preparePhraseFile(phrases, true); - CI18N::writeTextFile(desDir + phrasePath, str); - - str = prepareStringFile(clauses, true); - CI18N::writeTextFile(desDir + clausePath, str); - } - - - return 0; -} - - - -int main(int argc, char *argv[]) -{ - NLMISC::CApplicationContext context; -/* createDebug(); - CStdDisplayer *display = new CStdDisplayer; - NLMISC::InfoLog->addDisplayer(display); - NLMISC::WarningLog->addDisplayer(display); - NLMISC::ErrorLog->addDisplayer(display); -*/ - -/* for (uint i=0; i<20; ++i) - { - uint64 hash = makeHash(ucstring("Bonjour le monde !")); - nldebug("%s", hashToString(hash).c_str()); - hash = makeHash(ucstring("Une autre cléf")); - nldebug("%s", hashToString(hash).c_str()); - } -*/ - - if (argc < 2) - { - showUsage(argv[0]); - return 1; - } - std::string argv1(argv[1]); - - // create the diff version. - char temp[16]; - sprintf(temp, "%8.8X", (uint) ::time(NULL)); - diffVersion = temp; - - if (strcmp(argv[1], "make_work") == 0) - { - return makeWork(); - } - - // generic worksheet comparison - if (strcmp(argv[1], "make_worksheet_diff") == 0) - { - if (argc != 3) - { - showUsage(argv[0]); - return 1; - } - - return makeWorksheetDiff(argc, argv, argv[2], argv[2], true); - } - else if (strcmp(argv[1], "merge_worksheet_diff") == 0) - { - if (argc != 3) - { - showUsage(argv[0]); - return 1; - } - - return mergeWorksheetDiff(argc, argv, argv[2], argv[2]); - } - else if (strcmp(argv[1], "crop_lines") == 0) - { - if (argc != 4) - { - showUsage(argv[0]); - return 1; - } - - uint nbLines; - NLMISC::fromString(argv[3], nbLines); - - cropLines(argv[2], nbLines); - - return 0; - } - else if (strcmp(argv[1], "extract_bot_names") == 0) - return extractBotNames(argc, argv); - else if (strcmp(argv[1], "extract_new_sheet_names") == 0) - return extractNewSheetNames(argc, argv); - - - - - if (argc != 2) - { - showUsage(argv[0]); - return 1; - } - -// if (strcmp(argv[1], "yann") == 0) -// return mergeYannTaf(); - - - string currentPath("./"); - CPath::addSearchPath(currentPath+addDir, true, false); - CPath::addSearchPath(currentPath+diffDir, true, false); -// CPath::addSearchPath(currentPath+transDir, true, false); - if (readLanguages() != 0) - { - LOG("Error will loading language file (language.txt)"); - return 1; - } - - if (strcmp(argv[1], "make_string_diff") == 0) - return makeStringDiff(argc, argv); - else if (strcmp(argv[1], "merge_string_diff") == 0) - return mergeStringDiff(argc, argv); - else if (strcmp(argv[1], "clean_string_diff") == 0) - return cleanStringDiff(argc, argv); - - else if (argv1 == "make_phrase_diff_old") - return makePhraseDiff(argc, argv); - else if (argv1 == "merge_phrase_diff_old") - return mergePhraseDiff(argc, argv, 1); - - - else if (argv1 == "make_phrase_diff") - return makePhraseDiff2(argc, argv); - else if (argv1 == "merge_phrase_diff") - return mergePhraseDiff(argc, argv, 2); - else if (argv1 == "forget_phrase_diff") - return forgetPhraseDiff(argc, argv); - else if (argv1 == "update_phrase_work") - return updatePhraseWork(); - else if (argv1 == "clean_phrase_diff") - return cleanPhraseDiff(argc, argv); - - else if (argv1 == "inject_clause") - return injectClause(); - - else if (argv1 == "sort_trans_phrase") - return sortTransPhrase(); - - else if (strcmp(argv[1], "make_clause_diff") == 0) - return makeClauseDiff(argc, argv); - else if (strcmp(argv[1], "merge_clause_diff") == 0) - return mergeClauseDiff(argc, argv); - else if (argv1 == "clean_clause_diff") - return cleanClauseDiff(argc, argv); - - else if (strcmp(argv[1], "make_words_diff") == 0) - return makeWordsDiff(argc, argv); - else if (strcmp(argv[1], "merge_words_diff") == 0) - return mergeWordsDiff(argc, argv); - else if (strcmp(argv[1], "clean_words_diff") == 0) - return cleanWordsDiff(argc, argv); - - else if (strcmp(argv[1], "recup_around") == 0) - return recupAround(argc, argv); - else if (strcmp(argv[1], "add_string_number") == 0) - return addStringNumber(); - - - return -1; - -} - - - -int addStringNumber() -{ - vector strings; - - LOG("Generating string diffs\nLoading the working file for language %s\n", Languages[0].c_str()); - // load the addition file - std::string addFile(Languages[0]+".uxt"); - if (!loadStringFile(addDir+addFile, strings, true)) - { - LOG("Error loading file %s\n", (addDir+addFile).c_str()); - return 1; - } - - ucstring str = prepareStringFile(strings, false); - - string filename = addDir+Languages[0]+".uxt"; - CI18N::writeTextFile(filename, str); - - return 0; -} - - +// Ryzom - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + + + +/** This tool is used to managed translation file. +* I work with two different file format : +* - phrase file witch contain a complex grammar description +* - string file withc contain only pair of identifier / string value. +* +* This tool can do 6 different work : +* - make diff string file file for each language from a reference string file. +* +* - merge the translated diff string file into there respective string file after +* translation +* +* - make diff phrase file for each language from a reference phrase file +* +* - merge the translated diff phrase file into there respective phrase file after +* translation +* +* - make clause diff for each language by examining phrase files. Add comments +* in the diff files for phrase parameter information. +* +* - merge clause diff in all the clause file. +* +* - remove "\*OLDVALUE: \*\/" from clause file or phrase file +* +* +* Before invocation, you must be in the translation repository (see localisation_system_in_ryzom.doc) +* Invocation should be as folow : +* trans_tool make_string_diff +* trans_tool merge_string_diff +* trans_tool make_words_diff +* trans_tool merge_words_diff +* trans_tool make_phrase_diff +* trans_tool merge_phrase_diff +* trans_tool make_clause_diff +* trans_tool merge_clause_diff +* trans_tool clean_string_diff +* trans_tool clean_words_diff +* trans_tool clean_clause_diff +* trans_tool clean_phrase_diff +* trans_tool make_phrase_diff_old +* trans_tool merge_phrase_diff_old +* trans_tool forget_phrase_diff +* trans_tool update_phrase_work +* trans_tool inject_clause +* trans_tool sort_trans_phrase +* trans_tool make_worksheet_diff +* trans_tool merge_worksheet_diff +* trans_tool crop_lines +* trans_tool extract_bot_names +* trans_tool extract_new_sheet_names + +*/ + +#include "nel/misc/app_context.h" +#include "nel/misc/i18n.h" +#include "nel/misc/file.h" +#include "nel/misc/path.h" +#include "nel/misc/diff_tool.h" +#include "nel/misc/algo.h" +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace NLMISC; +using namespace STRING_MANAGER; + +int extractBotNames(int argc, char *argv[]); +int extractNewSheetNames(int argc, char *argv[]); +const std::string addDir("work/"); +const std::string diffDir("diff/"); +const std::string transDir("translated/"); +const std::string historyDir("history/"); + +string diffVersion; + +#ifndef NL_OS_WINDOWS +char* itoa(int val, char *buffer, int base){ + static char buf[32] = {0}; + int i = 30; + for(; val && i ; --i, val /= base) + buf[i] = "0123456789abcdef"[val % base]; + return &buf[i+1]; +} +#endif // NL_OS_WINDOWS + +#ifdef NL_DEBUG +# define LOG nldebug +#else +# define LOG printf +#endif + +enum TDiffCommand +{ + diff_none, + diff_add, + diff_changed, + diff_removed, + diff_swap +}; + +struct TDiffInfo +{ + TDiffCommand Command; + uint Index1; + uint Index2; +}; + +/// Store the list of language extracted from the languages.txt file +vector Languages; + + +void showUsage(char *exeName) +{ + LOG("%s usage : \n", exeName); + LOG(" %s []\n", exeName); + LOG(" Where command can be :\n"); + LOG(" make_string_diff\n"); + LOG(" merge_string_diff\n"); + LOG(" clean_string_diff\n"); + LOG(" make_phrase_diff\n"); + LOG(" merge_phrase_diff\n"); + LOG(" clean_phrase_diff\n"); + LOG(" make_clause_diff\n"); + LOG(" merge_clause_diff\n"); + LOG(" clean_clause_diff\n"); + LOG(" make_phrase_diff_old\n"); + LOG(" merge_phrase_diff_old\n"); + LOG(" forget_phrase_diff\n"); + LOG(" inject_clause\n"); + LOG(" sort_trans_phrase\n"); + LOG(" make_worksheet_diff \n"); + LOG(" merge_worksheet_diff \n"); + LOG(" crop_lines \n"); + LOG(" extract_bot_names [-r]\n"); + LOG(" extract_new_sheet_names [-r]\n"); + LOG("\n"); + LOG("Language code are ISO 639-2 + optionally ISO 3166 country code.\n"); + LOG("Reference language is always the first language in languages.txt\n"); +} + + + +void verifyVersion(ucstring& doc, int versionId) +{ + ucstring version1("// DIFF_VERSION 1\r\n"); + ucstring::size_type version1Size = version1.size(); + ucstring version2("// DIFF_VERSION 2\r\n"); + ucstring::size_type version2Size = version2.size(); + + switch (versionId) + { + case 1: + if (doc.size() < version1Size|| doc.substr(0, version1Size) != version1 ) + { + nlerror("Loading wrong diff version"); + nlassert(0); + } + doc = doc.substr(version1Size); + break; + + case 2: + if (doc.size() < version2Size || doc.substr(0, version2Size) != version2 ) + { + nlerror("Loading wrong diff version"); + nlassert(0); + } + doc = doc.substr(version2Size); + break; + + default: + nlassert(0); + } + + +} +bool readPhraseFile1(const std::string &filename, vector &phrases, bool forceRehash) +{ + ucstring doc; + + CI18N::readTextFile(filename, doc, false, false, false, CI18N::LINE_FMT_CRLF); + verifyVersion(doc, 1); + return readPhraseFileFromString(doc, filename, phrases, forceRehash); +} + +bool readPhraseFile2(const std::string &filename, vector &phrases, bool forceRehash) +{ + ucstring doc; + + CI18N::readTextFile(filename, doc, false, false, false, CI18N::LINE_FMT_CRLF); + verifyVersion(doc, 2); + return readPhraseFileFromString(doc, filename, phrases, forceRehash); +} + + + +void getPathContentFiltered(const string &baseName, const string &ext, vector &result) +{ + CPath::getPathContent(diffDir, false, false, true, result); + + uint i; + for (i=0; i>8) & 0xff, fp); + } + + fclose(fp); + } +} +*/ + + +bool mergeStringDiff(vector &strings, const string &language, const string &baseName, const string &ext, bool onlyTranslated, bool archiveDiff = false) +{ + vector diffs; + + getPathContentFiltered(diffDir+baseName+language+"_diff_", ext, diffs); + + for (uint i=0; i diff; + if (!loadStringFile(diffs[i], diff, false)) + return false; + + for (uint j=0; j::IDiffCallback +{ +public: + void run(const vector &addition, vector &reference, vector &diff) + { + TStringDiffContext context(addition, reference, diff); + + CMakeDiff differ; + differ.makeDiff(this, context); + } + + void onEquivalent(uint addIndex, uint refIndex, TStringDiffContext &context) + { + // nothing to do + } + void onAdd(uint addIndex, uint refIndex, TStringDiffContext &context) + { + TStringInfo si = context.Addition[addIndex]; + char temp[1024]; + sprintf(temp, "// DIFF ADD %u ", addIndex); + si.Comments = ucstring(temp) + nl + si.Comments; + + nlinfo("Added %s at %u", si.Identifier.c_str(), addIndex); + context.Diff.push_back(si); + } + void onRemove(uint addIndex, uint refIndex, TStringDiffContext &context) + { + TStringInfo si = context.Reference[refIndex]; + char temp[1024]; + sprintf(temp, "// DIFF REMOVED %u ", addIndex); + // NB : on vire les commentaires car il pourrais contenir des merdes.. + si.Comments = ucstring(temp) + nl; + + nlinfo("Removed %s at %u", si.Identifier.c_str(), addIndex); + context.Diff.push_back(si); + } + void onChanged(uint addIndex, uint refIndex, TStringDiffContext &context) + { + TStringInfo si = context.Addition[addIndex]; + char temp[1024]; + sprintf(temp, "// DIFF CHANGED %u ", addIndex); + si.Comments = ucstring(temp) + nl + si.Comments; + si.Comments = si.Comments + ucstring("/* OLD VALUE : [") + context.Reference[refIndex].Text + "] */" + nl; + + nlinfo("Changed %s at %u", si.Identifier.c_str(), addIndex); + context.Diff.push_back(si); + } + + void onSwap(uint newIndex, uint refIndex, TStringDiffContext &context) + { + TStringInfo si; + char temp[1024]; + sprintf(temp, "// DIFF SWAP %u %u (swaping %s and %s)", newIndex, refIndex, context.Reference[newIndex].Identifier.c_str(), context.Reference[refIndex].Identifier.c_str()); +// sprintf(temp, "// DIFF SWAP %u %u", newIndex, refIndex); + + si.Comments = ucstring(temp) + nl +nl; + context.Diff.push_back(si); + } + + +}; + + +void makeStringDiff(const vector &addition, vector &reference, vector &diff) +{ + // just building the object will to the job ! + CMakeStringDiff differ; + differ.run(addition, reference, diff); + +/* + // compare the reference an addition file, remove any equivalent strings. + uint addCount=0, refCount=0; + + while (addCount < addition.size() || refCount < reference.size()) + { + bool equal = true; + if (addCount != addition.size() && refCount != reference.size()) + { + equal = addition[addCount].HashValue == reference[refCount].HashValue; + } + + vector::iterator it; + + if (addCount == addition.size() + || + ( + !equal +// && find_if(addition.begin()+addCount, addition.end(), TFindStringInfo(reference[refCount].Identifier)) == addition.end() + && find_if(addition.begin(), addition.end(), TFindStringInfo(reference[refCount].Identifier)) == addition.end() + ) + ) + { + // this can only be removed elements + TStringInfo si = reference[refCount]; + char temp[1024]; + sprintf(temp, "// DIFF REMOVED %u ", addCount); + // NB : on vire les commentaires car il pourrais contenir des merdes.. + si.Comments = ucstring(temp) + nl; + + nlinfo("Removed %s at %u", si.Identifier.c_str(), addCount); + diff.push_back(si); + ++refCount; + } + else if (refCount == reference.size() + || + ( + !equal +// && find_if(reference.begin()+refCount, reference.end(), TFindStringInfo(addition[addCount].Identifier)) == reference.end() + && find_if(reference.begin(), reference.end(), TFindStringInfo(addition[addCount].Identifier)) == reference.end() + ) + ) + { + // this can only be addition + TStringInfo si = addition[addCount]; + char temp[1024]; + sprintf(temp, "// DIFF ADD %u ", addCount); + si.Comments = ucstring(temp) + nl + si.Comments; + + nlinfo("Added %s at %u", si.Identifier.c_str(), addCount); + diff.push_back(si); + ++addCount; + } + else if (addition[addCount].Identifier != reference[refCount].Identifier) + { + // swap two element. + vector::iterator it = find_if(reference.begin(), reference.end(), TFindStringInfo(addition[addCount].Identifier)); + if (it == reference.end()) + { + // addition + TStringInfo si = addition[addCount]; + char temp[1024]; + sprintf(temp, "// DIFF ADD %u ", addCount); + si.Comments = ucstring(temp) + nl + si.Comments; + + nlinfo("Added %s at %u", si.Identifier.c_str(), addCount); + diff.push_back(si); + ++addCount; + } + else + { + nlassert(it != reference.begin()+refCount); + + swap(*it, reference[refCount]); + + TStringInfo si; + char temp[1024]; + sprintf(temp, "// DIFF SWAP %u %u", it - reference.begin(), refCount); + + si.Comments = ucstring(temp) + nl; + diff.push_back(si); + } + } + else if (addition[addCount].HashValue != reference[refCount].HashValue) + { + // changed element + TStringInfo si = addition[addCount]; + char temp[1024]; + sprintf(temp, "// DIFF CHANGED %u ", addCount); + si.Comments = ucstring(temp) + nl + si.Comments; + si.Comments = si.Comments + ucstring("// OLD VALUE : [") + reference[refCount].Text + ']' + nl; + + nlinfo("Changed %s at %u", si.Identifier.c_str(), addCount); + diff.push_back(si); + ++refCount; + ++addCount; + } + else + { + // same entry + nlinfo("Same %s at %u", addition[addCount].Identifier.c_str(), addCount); + addCount++; + refCount++; + } + } +*/ +} + +int makeStringDiff(int argc, char *argv[]) +{ + // this will generate diff from 'addition' directory + // for the reference .uxt file + // with the same file in the 'translated' directory. + + // NB : we use standard C file access because there are mutiple file with the same name in different place. + + vector addition; + + LOG("Generating string diffs\nLoading the working file for language %s\n", Languages[0].c_str()); + // load the addition file + std::string addFile(Languages[0]+".uxt"); + if (!loadStringFile(addDir+addFile, addition, true)) + { + LOG("Error loading file %s\n", (addDir+addFile).c_str()); + return 1; + } + + // for each language + for (uint l=0; l reference; + // load the reference file + std::string refFile(Languages[l]+".uxt"); + if (!loadStringFile(transDir+refFile, reference, false)) + { + LOG("Error loading file %s\n", (transDir+refFile).c_str()); + return 1; + } + + // load any not merged diff file + if (!mergeStringDiff(reference, Languages[l], "", ".uxt", false)) + { + LOG("Error will mergin diff file(s)\n"); + return 1; + } + + vector diff; + makeStringDiff(addition, reference, diff); + + if (diff.empty()) + { + LOG("No difference for %s.\n", Languages[l].c_str()); + } + else + { + LOG("Writting difference file for %s.\n", Languages[l].c_str()); + // build the diff file for each language. + ucstring str = prepareStringFile(diff, false); + + // add the tag for non translation + str += nl + ucstring ("// REMOVE THE FOLOWING LINE WHEN TRANSLATION IS DONE")+nl+ucstring("// DIFF NOT TRANSLATED")+nl; + + std::string diffName(diffDir+Languages[l]+"_diff_"+diffVersion+".uxt"); + CI18N::writeTextFile(diffName, str); + + } + } + + return 0; +} + +/* +Remove the OLD VALUE from a file. +*/ +void cleanComment(const std::string & filename) +{ + ucstring text; + uint nbOldValue=0; + + CI18N::readTextFile(filename, text, false, false, false, CI18N::LINE_FMT_CRLF); + + ucstring newText; + ucstring::size_type last = 0; + while ( last != ucstring::npos) + { + ucstring::size_type commentBegin = text.find(ucstring("/* OLD VALUE :"), last); + if (commentBegin == ucstring::npos) + { + newText += text.substr(last); + last = ucstring::npos; + } + else + { + ucstring::size_type size = commentBegin - last; + ucstring toAdd = text.substr(last, size); + newText += toAdd; + ucstring::size_type commentEnd = text.find(ucstring("*/"), commentBegin); + if (commentEnd != ucstring::npos) { commentEnd += 4; } + last = commentEnd; + ++nbOldValue; + } + } + text = newText; + newText = ucstring(""); + last = 0; + while ( last != ucstring::npos) + { + ucstring::size_type commentBegin = text.find(ucstring("//"), last); + if (commentBegin == ucstring::npos) + { + newText += text.substr(last); + last = ucstring::npos; + } + else + { + ucstring::size_type size = commentBegin - last; + ucstring toAdd = text.substr(last, size); + newText += toAdd; + // case where // is the part of an url and isn't a comment + if (commentBegin > 4 && text.substr(commentBegin-1, 1) == ucstring(":")) + { + newText += "//"; + last = commentBegin+2; + } + else + { + ucstring::size_type commentEnd = text.find(ucstring("\n"), commentBegin); + if (commentEnd != ucstring::npos) + { + commentEnd += 1; + ucstring comment = text.substr(commentBegin, commentEnd - commentBegin); + if (comment.find(ucstring("// HASH_VALUE")) != ucstring::npos + || comment.find(ucstring("// DIFF")) != ucstring::npos + || comment.find(ucstring("// REMOVE")) != ucstring::npos + || comment.find(ucstring("// INDEX")) != ucstring::npos + ) + { + newText += comment; + } + } + last = commentEnd; + ++nbOldValue; + } + } + } + nlinfo("cleaning : %s, (%d comments deleted)...\n", filename.c_str(), nbOldValue); + CI18N::writeTextFile(filename , newText); +} + +/* +REMOVE OLDVALUE: from a diff string file +*/ +int cleanStringDiff(int argc, char *argv[]) +{ + + LOG("Cleaning string diffs\n"); + + uint i,l; + + for (l=0; l diffs; + + getPathContentFiltered(diffDir+Languages[l]+"_diff_", ".uxt", diffs); + for (i=0; i translated; + if (!loadStringFile(filename, translated, false)) + { + LOG("Error will loading file %s\n", filename.c_str()); + return 1; + } + + // append the translated diffs + mergeStringDiff(translated, Languages[l], "", ".uxt", true, true); + + // prepare the addition string + ucstring str = prepareStringFile(translated, true); + + { + // backup the original file + ucstring old; + CI18N::readTextFile(filename, old, false, true, false, CI18N::LINE_FMT_CRLF); + if (old != str) + CFile::moveFile((historyDir+CFile::getFilenameWithoutExtension(filename)+"_"+diffVersion+"."+CFile::getExtension(filename)).c_str(), filename.c_str()); + } + + CI18N::writeTextFile(filename, str); + } + + return 0; +} + + +/* +struct TFindPhrase : unary_function +{ + string Identifier; + TFindPhrase (const string &identifier) + : Identifier(identifier) + {} + bool operator () (const TPhrase &phrase) + { + return phrase.Identifier == Identifier; + } +}; +*/ + + +bool mergePhraseDiff2(vector &phrases, const string &language, bool onlyTranslated, bool archiveDiff); +bool mergePhraseDiff(vector &phrases, const string &language, bool onlyTranslated, bool archiveDiff = false) +{ + vector diffs; + + getPathContentFiltered(diffDir+"phrase_"+language+"_diff_", ".txt", diffs); + + for (uint i=0; i diff; + if (!readPhraseFile1(diffs[i], diff, false)) + return false; + + for (uint j=0; j::IDiffCallback +{ +public: + void run(const vector &addition, vector &reference, vector &diff) + { + TPhraseDiffContext context(addition, reference, diff); + + CMakeDiff differ; + differ.makeDiff(this, context); + } + + void onEquivalent(uint addIndex, uint refIndex, TPhraseDiffContext &context) + { + // nothing to do + } + void onAdd(uint addIndex, uint refIndex, TPhraseDiffContext &context) + { + TPhrase phrase = context.Addition[addIndex]; + char temp[1024]; + sprintf(temp, "// DIFF ADD %u ", addIndex); + phrase.Comments = ucstring(temp) + nl + phrase.Comments; + + nlinfo("Added %s at %u", phrase.Identifier.c_str(), addIndex); + context.Diff.push_back(phrase); + } + void onRemove(uint addIndex, uint refIndex, TPhraseDiffContext &context) + { + TPhrase phrase = context.Reference[refIndex]; + char temp[1024]; + sprintf(temp, "// DIFF REMOVED %u ", addIndex); + // NB : on vire les commentaires car il pourrai contenir des merdes.. + phrase.Comments = ucstring(temp) + nl; + for (uint i=0; i tempV; + tempV.push_back(context.Reference[refIndex]); + ucstring tempT = preparePhraseFile(tempV, false); + CI18N::removeCComment(tempT); + phrase.Comments = ucstring(temp) + nl + phrase.Comments; + phrase.Comments = phrase.Comments + ucstring("/* OLD VALUE : ["+nl) + tabLines(1, tempT) +nl + "] */" + nl; + phrase.Comments = phrase.Comments + chg; + + nlinfo("Changed %s at %u", phrase.Identifier.c_str(), addIndex); + context.Diff.push_back(phrase); + } + + void onSwap(uint newIndex, uint refIndex, TPhraseDiffContext &context) + { + TPhrase phrase; + char temp[1024]; + sprintf(temp, "// DIFF SWAP %u %u (swaping %s and %s)", newIndex, refIndex, context.Reference[newIndex].Identifier.c_str(), context.Reference[refIndex].Identifier.c_str()); + + nldebug("Swap for %u %u", newIndex, refIndex); + phrase.Comments = ucstring(temp) + nl; + context.Diff.push_back(phrase); + } + +}; + + + +int makePhraseDiff(int argc, char *argv[]) +{ + // Generate the diff file from phrase_.txt compared to the same file in translated. + // The diff is generated only from the reference language for and all the languages + + LOG("Generating phrase diffs\nLoading the working file for language %s\n", Languages[0].c_str()); + + + vector addition; + + // read addition + if (!readPhraseFile(addDir+"phrase_"+Languages[0]+".txt", addition, true)) + { + LOG("Error will loading file %s", (addDir+"phrase_"+Languages[0]+".txt").c_str()); + return 1; + } + + for (uint l =0; l reference; + // read the reference file + if (!readPhraseFile(transDir+"phrase_"+Languages[l]+".txt", reference, false)) + { + LOG("Error will loading file %s", (transDir+"phrase_"+Languages[l]+".txt").c_str()); + return 1; + } + + if (!mergePhraseDiff(reference, Languages[l], false)) + { + LOG("Error will merging phrase diff for language %s\n", Languages[l].c_str()); + return 1; + } + + // compare the reference an addition file, remove any equivalent strings. + uint addCount=0, refCount=0; + vector diff; + + CMakePhraseDiff differ; + differ.run(addition, reference, diff); + + if (diff.empty()) + { + LOG("No difference for language %s\n", Languages[l].c_str()); + } + else + { + LOG("Writing difference file for language %s\n", Languages[l].c_str()); + ucstring text; + text += "// DIFF_VERSION 1\r\n"; + text += preparePhraseFile(diff, false); + // add the tag for non translation + text += nl + ucstring ("// REMOVE THE FOLOWING LINE WHEN TRANSLATION IS DONE")+nl+ucstring("// DIFF NOT TRANSLATED")+nl; + CI18N::writeTextFile(diffDir+"phrase_"+Languages[l]+"_diff_"+diffVersion+".txt", text); + } + } + + return 0; +} + + +/* +REMOVE OLDVALUE: from a diff clause file +*/ +int cleanPhraseDiff(int argc, char *argv[]) +{ + + LOG("Cleaning phrase diffs\n"); + + uint i,l; + + for (l=0; l diffs; + + getPathContentFiltered(diffDir+"phrase_"+Languages[l]+"_diff_", ".txt", diffs); + for (i=0; i reference; + + ucstring doc; + + + if (!readPhraseFile(transDir+basename+".txt", reference, false)) + { + LOG("Error will loading file %s", (transDir+basename+".txt").c_str()); + return 1; + } + + + switch(version) + { + case 1: + if (!mergePhraseDiff(reference, Languages[l], true, true)) + { + LOG("Error will merging phrase diff"); + return 1; + } + break; + + case 2: + + if (!mergePhraseDiff2(reference, Languages[l], true, true)) + { + LOG("Error will merging phrase diff"); + return 1; + } + break; + + default: + nlassert(0); + + } + + ucstring str = preparePhraseFile(reference, true); + + { + // backup the original file + ucstring old; + CI18N::readTextFile(filename, old, false, true, false, CI18N::LINE_FMT_CRLF); + if (old != str) + CFile::moveFile((historyDir+CFile::getFilenameWithoutExtension(filename)+"_"+diffVersion+"."+CFile::getExtension(filename)).c_str(), filename.c_str()); + } + + CI18N::writeTextFile(transDir+basename+".txt", str); + + } + + return 0; +} + + +int makeClauseDiff(int argc, char *argv[]) +{ + // this will generate diff from 'addition' directory + // for all the clause_.txt file + // with the same file in the 'translated' directory. + + // NB : we use standard C file access because there are mutiple file with the same name in different place. + + LOG("Generating clause diffs\n"); + + uint i,l; + + for (l=0; l addition; + vector reference; + vector phrases; + std::vector warnings; + + // load the reference file + std::string refFile(basename+".txt"); + if (!loadStringFile(transDir+refFile, reference, false)) + { + LOG("Error will loading file %s", (transDir+refFile).c_str()); + return 1; + } + + // load the addition file + std::string addFile("phrase_"+Languages[l]+".txt"); + if (!readPhraseFile(transDir+addFile, phrases, true)) + { + LOG("Error will loading file %s", (transDir+addFile).c_str()); + return 1; + } + + // extract all the clauses from the phrases file + vector::iterator first(phrases.begin()), last(phrases.end()); + for (; first != last; ++first) + { + TPhrase &p = *first; + for (i=0; i::const_iterator first2 = addition.begin(); + vector::const_iterator last2 = addition.end(); + for ( ;first2!=last2 && first2->Identifier != si.Identifier; ++first2) {} + bool isAllreadyThere = first2 != last2; + if (isAllreadyThere) + { + warnings.push_back("The clause " +si.Identifier +" in the phrase " + p.Identifier +" exists more than once."); + } + else + { + addition.push_back(si); + } + } + } + } + + if (!warnings.empty()) + { + std::vector::const_iterator first = warnings.begin(); + std::vector::const_iterator last = warnings.end(); + for (;first != last; ++first) { nlwarning("%s", first->c_str()); } + return -1; + } + mergeStringDiff(reference, Languages[l], "clause_", ".txt", false); + + vector diff; + + makeStringDiff(addition, reference, diff); + + if (diff.empty()) + { + LOG("No difference for language %s\n", Languages[l].c_str()); + } + else + { + LOG("Writing difference file for %s.\n", Languages[l].c_str()); + // build the diff file for each language. + ucstring str = prepareStringFile(diff, false); + + // add the tag for non translation + str += nl + ucstring ("// REMOVE THE FOLOWING LINE WHEN TRANSLATION IS DONE")+nl+ucstring("// DIFF NOT TRANSLATED")+nl; + + std::string diffName(diffDir+"clause_"+Languages[l]+"_diff_"+diffVersion+".txt"); + CI18N::writeTextFile(diffName, str); + } + } + + return 0; +} + + +/* +REMOVE OLDVALUE: from a diff clause file +*/ +int cleanClauseDiff(int argc, char *argv[]) +{ + + LOG("Cleaning clause diffs\n"); + + uint i,l; + + for (l=0; l diffs; + + getPathContentFiltered(diffDir+"clause_"+Languages[l]+"_diff_", ".txt", diffs); + for (i=0; i translated; + if (!loadStringFile(filename, translated, false)) + { + LOG("Error will loading file %s", filename.c_str()); + return 1; + } + + // append the translated diffs + mergeStringDiff(translated, Languages[l], "clause_", ".txt", true, true); + + // prepare the addition string + ucstring str = prepareStringFile(translated, true); + + { + // backup the original file + ucstring old; + CI18N::readTextFile(filename, old, false, true, false, CI18N::LINE_FMT_CRLF); + if (old != str) + CFile::moveFile((historyDir+CFile::getFilenameWithoutExtension(filename)+"_"+diffVersion+"."+CFile::getExtension(filename)).c_str(), filename.c_str()); + } + + CI18N::writeTextFile(filename, str); + } + + return 0; + + return 0; +} + +bool mergeWorksheetDiff(const std::string filename, TWorksheet &sheet, bool onlyTranslated, bool archiveDiff) +{ + std::string fn(CFile::getFilenameWithoutExtension(filename)), ext(CFile::getExtension(filename)); + vector fileList; + getPathContentFiltered(diffDir+fn+"_diff_", ext, fileList); + + uint i; + for (i=0; i 0); + sheet.Data.erase(sheet.Data.begin() + diffInfo.Index1); + break; + case diff_swap: + nlassertex(diffInfo.Index1 < sheet.Data.size(), + ("SWAP cmd in diff file, first index reference row %u, but worksheet only contains %u entries", + diffInfo.Index1, sheet.Data.size())); +// nlassertex(diffInfo.Index1 > 0); + nlassertex(diffInfo.Index2 < sheet.Data.size(), + ("SWAP cmd in diff file, second index reference row %u, but worksheet only contains %u entries", + diffInfo.Index1, sheet.Data.size())); +// nlassertex(diffInfo.Index2 > 0); + swap(sheet[diffInfo.Index1], sheet[diffInfo.Index2]); + break; + default: + nlassert(false); + } + + } + + if (archiveDiff) + { + // move the diff file in the history dir + CFile::moveFile((historyDir+CFile::getFilename(fileList[i])).c_str(), fileList[i].c_str()); + } + } + + return true; +} + + + +bool mergeSheetDiff(const string &type, TWorksheet &sheet, const string &language, bool onlyTranslated, bool archiveDiff) +{ + return mergeWorksheetDiff(type+"_words_"+language+".txt", sheet, onlyTranslated, archiveDiff); +} + + +class CMakeWordsDiff : public TWorkSheetDiff::IDiffCallback +{ +public: + void run(const TWorksheet &addition, TWorksheet &reference, TWorksheet &diff) + { + TWordsDiffContext context(addition, reference, diff); + + TWorkSheetDiff differ; + differ.makeDiff(this, context, true); + } + + void onEquivalent(uint addIndex, uint refIndex, TWordsDiffContext &context) + { + // nothing to do + } + void onAdd(uint addIndex, uint refIndex, TWordsDiffContext &context) + { + TWorksheet::TRow row(context.Reference.ColCount+1); + for (uint j=0; j diffs; + + getPathContentFiltered(diffDir+"clause_"+Languages[l]+"_diff_", ".txt", diffs); + for (i=0; i 0) + CI18N::writeTextFile(transDir+filename, str, false); + + return 0; +} + + +int makeWordsDiff(int argc, char *argv[]) +{ + vector fileList; + CPath::getPathContent(addDir, false, false, true, fileList); + + // filter in words file only + uint i; + for (i=0; i fileList; + CPath::getPathContent(addDir, false, false, true, fileList); + + // filter in words file only + for (uint i=0; i count(c2.Conditions.begin(), c2.Conditions.end(), '&'); + } +}; + +int recupAround(int argc, char *argv[]) +{ + string clause1(diffDir+"clause_en_diff_3E896220.txt"); + string clause2(addDir+"clause_en_diff_3E7B4CE4 TRANSLATED.txt"); + + vector reference; + loadStringFile(clause1, reference, true); + vector around; + loadStringFile(clause2, around, true, '[', ']', true); + + vector result; + + nlassert(reference.size() == around.size()); + + for (uint i=0; i lines; + explode(text, std::string("\n"), lines); + + text.clear(); + if (lines.size() > nbLines) + { + for (uint i=0; i files; + uint i; + + // move en.uxt file to wk.uxt + CFile::moveFile((CPath::standardizePath(addDir)+"wk.uxt").c_str(), (CPath::standardizePath(addDir)+"en.uxt").c_str()); + + files.clear(); + CPath::getPathContent(addDir, true, false, true, files); + + string strreplaced("_en.txt"); + string strtoreplace("_wk.txt"); + + for (i=0; i > & outputResult); + +void assertUniq(const vector& reference) +{ + + std::set< std::string > phraseIdentifier; + std::set< std::string > clauseIdentifier; + vector::const_iterator first( reference.begin() ); + vector::const_iterator last( reference.end() ); + for( ; first != last; ++first) + { + if ( phraseIdentifier.find(first->Identifier) != phraseIdentifier.end()) + { + nlwarning("Phrase %s defined more than once.", first->Identifier.c_str()); + exit(-1); + } + else + { + phraseIdentifier.insert(first->Identifier); + vector::const_iterator first2( first->Clauses.begin() ); + vector::const_iterator last2( first->Clauses.end() ); + if (clauseIdentifier.find(first2->Identifier) != clauseIdentifier.end() ) + { + nlwarning("Clause %s defined more than once.", first2->Identifier.c_str()); + exit(-1); + } + } + } + +} + + +void mergePhraseDiff2Impl(vector& reference, const vector& addition) +{ + assertUniq(reference); + assertUniq(addition); + + typedef std::map TMap; + + TMap phrases; + + { + vector::const_iterator first( reference.begin() ); + vector::const_iterator last( reference.end() ); + for( ; first != last ; ++first ) + { + std::string identifier = first->Identifier; + phrases[identifier] = *first; + } + } + + { + vector::const_iterator first( addition.begin() ); + vector::const_iterator last( addition.end() ); + for( ; first != last ; ++first ) + { + if ( first->Comments.find(ucstring("DIFF CHANGED")) != ucstring::npos) + { + nlassert( phrases.find(first->Identifier) != phrases.end() ); + phrases[first->Identifier] = *first; + } + else if ( first->Comments.find(ucstring("DIFF ADD")) != ucstring::npos) + { + nlassert( phrases.find(first->Identifier) == phrases.end() ); + phrases[first->Identifier] = *first; + + } + else if ( first->Comments.find(ucstring("DIFF REMOVED")) != ucstring::npos) + { + nlassert( phrases.find(first->Identifier) != phrases.end() ); + phrases.erase( phrases.find(first->Identifier)); + } + else + { + // nlassert(0 && "INVALID DIFF COMMAND"); + } + } + } + + { + reference.clear(); + reference.reserve(phrases.size()); + TMap::const_iterator first( phrases.begin() ); + TMap::const_iterator last( phrases.end() ); + for( ; first != last; ++first) { reference.push_back(first->second); } + } + +} + +void removeHashValueComment(ucstring & comments) +{ + ucstring::size_type first; + ucstring::size_type last; + first = comments.rfind(ucstring("// HASH_VALUE")); + if (first != ucstring::npos) + { + last = comments.find(ucstring("\n"), first); + if (last != ucstring::npos) + { + last += 1; + ucstring tmp1 = comments.substr(0, first); + ucstring tmp2 = last !=comments.size() + ? comments.substr(last) + : ucstring(""); + comments = tmp1 + tmp2; + } + else + { + comments = comments.substr(0, first); + } + } + else + { + //comments = comments; + } + +} + +bool updateClauseHashValue(const std::map >& validValues, const std::string & dirPath = "") +{ + + for (uint l=0; l clauses; + std::string refFile(basename+".txt"); + if (!loadStringFile(transDir+refFile, clauses, false)) + { + LOG("Error will loading file %s", (transDir+refFile).c_str()); + return false; + } + + bool changed = false; + for ( uint i=0; i < clauses.size() ; ++i) + { + std::string Identifier = clauses[i].Identifier; + if ( validValues.find(Identifier) != validValues.end()) + { + if (!validValues.find(Identifier)->second.second + || clauses[i].HashValue == validValues.find(Identifier)->second.second) + { + clauses[i].HashValue = validValues.find(Identifier)->second.first; + removeHashValueComment(clauses[i].Comments); + changed = true; + } + } + } + + if (!changed) + { + nlwarning("Clauses file don't need update for language %s\n", Languages[l].c_str()); + } + else + { + nlinfo("Updating hashcode of clause file for %s.\n", Languages[l].c_str()); + // build the diff file for each language. + ucstring str = prepareStringFile(clauses, false); + std::string clauseName(dirPath+ transDir + basename +".txt"); + CFile::createDirectoryTree( CFile::getPath(clauseName) ); + CI18N::writeTextFile(clauseName, str); + } + + } + return true; +} + +ucstring preparePhraseFile2(const vector &phrases, bool removeDiffComments) +{ + ucstring ret; + vector::const_iterator first(phrases.begin()), last(phrases.end()); + for (; first != last; ++first) + { + const TPhrase &p = *first; + + if (removeDiffComments) + { + string comment = p.Comments.toString(); + vector lines; + explode(comment, std::string("\n"), lines, true); + + uint i; + for (i=0; i > & validValues, const std::string & dirPath = "") +{ + + for (uint l=0; l phrases; + std::string refFile(basename+".txt"); + if (!readPhraseFile(transDir+refFile, phrases, false)) + { + LOG("Error will loading file %s", (transDir+refFile).c_str()); + return false; + } + + bool changed = false; + for ( uint i=0; i < phrases.size() ; ++i) + { + std::string Identifier = phrases[i].Identifier; + if ( validValues.find(Identifier) != validValues.end()) + { + if (!validValues.find(Identifier)->second.second || phrases[i].HashValue == validValues.find(Identifier)->second.second ) + { + + phrases[i].HashValue = validValues.find(Identifier)->second.first; + removeHashValueComment(phrases[i].Comments); + changed = true; + } + } + } + + if (!changed) + { + nlinfo("Phrase file don't need update for language %s\n", Languages[l].c_str()); + } + else + { + nlinfo("Updating hashcode of phrase file for %s.\n", Languages[l].c_str()); + // build the diff file for each language. + ucstring str = preparePhraseFile(phrases, false); + std::string pharseName(dirPath+ transDir + basename +".txt"); + CFile::createDirectoryTree( CFile::getPath(pharseName) ); + CI18N::writeTextFile(pharseName, str); + } + + } + return true; +} + + +bool sortTransPhrase() +{ + + for (uint l=0; l phrases; + vector phrases2; + std::map phraseMap; + std::string refFile(basename+".txt"); + if (!readPhraseFile(transDir+refFile, phrases, false)) + { + LOG("Error will loading file %s", (transDir+refFile).c_str()); + return false; + } + + { + + std::vector::const_iterator first(phrases.begin()); + std::vector::const_iterator last(phrases.end()); + for ( ; first != last; ++first) + { + phraseMap[first->Identifier] = *first; + } + } + { + std::map::const_iterator first(phraseMap.begin()); + std::map::const_iterator last(phraseMap.end()); + for ( ; first != last; ++first) + { + phrases2.push_back( first->second); + } + } + + + nlinfo("Updating hashcode of phrase file for %s.\n", Languages[l].c_str()); + // build the diff file for each language. + ucstring str = preparePhraseFile(phrases2, false); + std::string pharseName(transDir+refFile); + CFile::createDirectoryTree( CFile::getPath(pharseName) ); + CI18N::writeTextFile(pharseName, str); + } + return true; +} + + + +void patchWorkFile(vector &updatedPhrase, const std::string & filename) +{ + ucstring text; + if ( updatedPhrase.empty() ) { return; } + CI18N::readTextFile(filename, text, false, false, false, CI18N::LINE_FMT_CRLF); + vector::const_iterator first(updatedPhrase.begin()); + vector::const_iterator last(updatedPhrase.end()); + for (; first != last; ++first) + { + + ucstring::size_type firstFun = text.find( ucstring(first->Identifier)); + if (firstFun == ucstring::npos) + { + nlwarning("Error can't patch %s: %s not found", filename.c_str(), first->Identifier.c_str()); + } + else + { + ucstring::size_type lastFun = text.find( ucstring("}") , firstFun); + if (lastFun == ucstring::npos) + { + nlwarning("Error can't patch %s: syntax error near %s", filename.c_str(), first->Identifier.c_str()); + } + else + { + std::vector param; + param.push_back(*first); + + ucstring before = text.substr(0,firstFun); + ucstring str = preparePhraseFile2(param, false); + ucstring after = text.substr(lastFun+1); + text = ""; + text += before; + text += str; + text += after; + } + } + } + CI18N::writeTextFile( filename, text); + +} + +int updatePhraseWork() +{ + std::string saveDir = diffDir + "update_"+ diffVersion + "/"; + vector transPhrase; + std::map transPhraseMap; + std::map > validClauseHashValue; + std::map > validPhraseHashValue; + std::vector< std::pair > outputResult; + + if (!readPhraseFile(transDir+"phrase_wk.txt", transPhrase, false)) + { + LOG("Error will loading file %s", (addDir+"phrase_"+Languages[0]+".txt").c_str()); + return 1; + } + + { + std::vector::const_iterator first(transPhrase.begin()); + std::vector::const_iterator last(transPhrase.end()); + for (; first != last;++first) + { + transPhraseMap[first->Identifier] = *first; + } + } + + preprocessTextFile(addDir+"phrase_wk.txt", outputResult); + + uint firstFile = 0; + uint lastFile = (uint)outputResult.size(); + for (; firstFile != lastFile ; ++firstFile) + { + + ucstring doc = outputResult[firstFile].first; + std::vector phrases; + readPhraseFileFromString(outputResult[firstFile].first, outputResult[firstFile].second, phrases, true); + + std::vector::iterator first(phrases.begin()); + std::vector::iterator last(phrases.end()); + std::vector updatedPhrases; + for (; first != last; ++first) + { + if (transPhraseMap.find(first->Identifier) != transPhraseMap.end() ) + { + TPhrase workPhrase = *first; + TPhrase& transPhrase = transPhraseMap[first->Identifier]; + if (first->HashValue == transPhrase.HashValue) + { + uint64 oldHash = transPhrase.HashValue; + uint64 newHash = STRING_MANAGER::makePhraseHash(transPhrase); + if (newHash != transPhrase.HashValue) + { + //translation phrase_wk.txt has been manually changed + validPhraseHashValue[transPhrase.Identifier] = std::pair(newHash, oldHash); + std::vector::iterator firstClause ( transPhrase.Clauses.begin() ); + std::vector::iterator lastClause ( transPhrase.Clauses.end() ); + for (; firstClause != lastClause; ++firstClause) + { + uint64 clauseHashValue = CI18N::makeHash(firstClause->Text); + + validClauseHashValue[firstClause->Identifier] = std::pair(clauseHashValue, firstClause->HashValue); + firstClause->HashValue = clauseHashValue; + } + updatedPhrases.push_back(transPhrase); + updatedPhrases.back().Comments= ucstring(""); + } + } + } + } + + + std::string newFile = saveDir + outputResult[firstFile].second; + std::string oldFile = outputResult[firstFile].second; + CFile::createDirectoryTree(CFile::getPath(newFile)); + if ( CFile::copyFile(newFile, oldFile) ) + { + + patchWorkFile(updatedPhrases, newFile); + } + else + { + nlwarning("Can't copy %s", newFile.c_str()); + } + + } + + updatePhraseHashValue(validPhraseHashValue, saveDir); + updateClauseHashValue(validClauseHashValue, saveDir); + return 0; +} + + + + +bool mergePhraseDiff2(vector &phrases, const string &language, bool onlyTranslated, bool archiveDiff = false) +{ + vector diffs; + + getPathContentFiltered(diffDir+"phrase_"+language+"_diff_", ".txt", diffs); + + for (uint i=0; i diff; + if (!readPhraseFile2(diffs[i], diff, false)) + return false; + + + mergePhraseDiff2Impl(phrases, diff); + + + if (archiveDiff) + { + // move the diff file in the history dir + CFile::moveFile((historyDir+CFile::getFilename(diffs[i])).c_str(), diffs[i].c_str()); + } + } + + return true; +} + + + +class CMakePhraseDiff2 +{ +public: + + class CPhraseEqual + { + + public: + CPhraseEqual(){} + + bool operator()( const TPhrase& left, const TPhrase& right) const; + +// bool clausesEqual( const std::vector& left, const std::vector& right) const; + +// bool clauseEqual(const TClause& left, const TClause& right) const; + + }; + + void run(const vector &addition, vector &reference, vector &diff); + + void onEquivalent(uint addIndex, uint refIndex, TPhraseDiffContext &context); + + void onAdd(uint addIndex, uint refIndex, TPhraseDiffContext &context); + + void onRemove(uint addIndex, uint refIndex, TPhraseDiffContext &context); + + void onChanged(uint addIndex, uint refIndex, TPhraseDiffContext &context); + + +}; + + + + + + +void CMakePhraseDiff2::run(const vector &addition, vector &reference, vector &diff) +{ + + TPhraseDiffContext context(addition, reference, diff); + + std::set phraseIdentifier; + std::map mapAdd; + std::map mapRef; + + { + uint first = 0; + uint last = (uint)reference.size(); + + for ( ;first != last; ++first) + { + std::string Identifier(reference[first].Identifier); + mapRef[Identifier] = first; + phraseIdentifier.insert(Identifier); + } + } + + { + uint first = 0; + uint last = (uint)addition.size(); + + for ( ;first != last; ++first) + { + std::string Identifier(addition[first].Identifier); + mapAdd[Identifier] = first; + phraseIdentifier.insert(Identifier); + } + } + + if (mapAdd.size() != addition.size()) + { + nlwarning("Phrases are defined more than once in works directory"); + } + + if (mapAdd.size() != addition.size()) + { + nlwarning("Phrases are defined more than once in translation directory"); + } + + + std::set::iterator first(phraseIdentifier.begin()); + std::set::iterator last(phraseIdentifier.end()); + + for (; first != last; ++first) + { + if ( mapAdd.find(*first) != mapAdd.end() + && mapRef.find(*first) != mapRef.end()) + { + + if ( CPhraseEqual()(addition[mapAdd[*first]], reference[mapRef[*first]]) ) + { + onEquivalent(mapAdd[*first], mapRef[*first], context); + } + else + { + onChanged(mapAdd[*first], mapRef[*first], context); + } + } + else if ( mapAdd.find(*first) != mapAdd.end() + && mapRef.find(*first) == mapRef.end()) + { + onAdd(mapAdd[*first], 0, context); + } + else if ( mapAdd.find(*first) == mapAdd.end() + && mapRef.find(*first) != mapRef.end()) + { + onRemove(0, mapRef[*first], context); + } + + } + +} + + +void CMakePhraseDiff2::onEquivalent(uint addIndex, uint refIndex, TPhraseDiffContext &context) +{ + // nothing to do +} +void CMakePhraseDiff2::onAdd(uint addIndex, uint refIndex, TPhraseDiffContext &context) +{ + TPhrase phrase = context.Addition[addIndex]; + char temp[1024]; + sprintf(temp, "// DIFF ADD"); + phrase.Comments = ucstring(temp) + nl + phrase.Comments; + + nlinfo("Added %s at %u", phrase.Identifier.c_str(), addIndex); + context.Diff.push_back(phrase); +} + +void CMakePhraseDiff2::onRemove(uint addIndex, uint refIndex, TPhraseDiffContext &context) +{ + TPhrase phrase = context.Reference[refIndex]; + char temp[1024]; + sprintf(temp, "// DIFF REMOVED"); + // NB : on vire les commentaires car il pourrai contenir des merdes.. + phrase.Comments = ucstring(temp) + nl; + for (uint i=0; i tempV; + tempV.push_back(context.Reference[refIndex]); + ucstring tempT = preparePhraseFile(tempV, false); + CI18N::removeCComment(tempT); + phrase.Comments = ucstring(temp) + nl + phrase.Comments; + phrase.Comments = phrase.Comments + ucstring("/* OLD VALUE : ["+nl) + tabLines(1, tempT) +nl + "] */" + nl; + phrase.Comments = phrase.Comments + chg; + + nlinfo("Changed %s at %u", phrase.Identifier.c_str(), addIndex); + context.Diff.push_back(phrase); +} + + +bool CMakePhraseDiff2::CPhraseEqual::operator()( const TPhrase& left, const TPhrase& right) const +{ + bool identifierOk = left.Identifier == right.Identifier; +// bool parameterOk = left.Parameters == right.Parameters; +// bool commentsOk = left.Comments == right.Comments; +// bool clausesOk = clausesEqual(left.Clauses, right.Clauses); + bool hashOk = left.HashValue== right.HashValue; + + return identifierOk && hashOk;// && parameterOk && clausesOk; + +} +/* +bool CMakePhraseDiff2::CPhraseEqual::clausesEqual( const std::vector& left, const std::vector& right) const +{ + std::vector::const_iterator first1(left.begin()); + std::vector::const_iterator last1(left.end()); + std::vector::const_iterator first2(right.begin()); + + if (left.size() != right.size()) return false; + + for ( ; first1 != last1 && !clauseEqual(*first1, *first2); ++first1, ++first2){} + + return first1 == last1; +} + +bool CMakePhraseDiff2::CPhraseEqual::clauseEqual(const TClause& left, const TClause& right) const +{ + return left.Identifier != right.Identifier + && left.Conditions != right.Conditions + && left.Text != right.Text + && left.Comments != right.Comments + && left.HashValue != right.HashValue; +} + +*/ + + + +int makePhraseDiff2(int argc, char *argv[]) +{ + // Generate the diff file from phrase_.txt compared to the same file in translated. + // The diff is generated only from the reference language for and all the languages + + LOG("Generating phrase diffs\nLoading the working file for language %s\n", Languages[0].c_str()); + + + vector addition; + + // read addition + if (!readPhraseFile(addDir+"phrase_"+Languages[0]+".txt", addition, true)) + { + LOG("Error will loading file %s", (addDir+"phrase_"+Languages[0]+".txt").c_str()); + return 1; + } + + for (uint l =0; l reference; + // read the reference file + if (!readPhraseFile(transDir+"phrase_"+Languages[l]+".txt", reference, false)) + { + LOG("Error will loading file %s", (transDir+"phrase_"+Languages[l]+".txt").c_str()); + return 1; + } + + if (!mergePhraseDiff2(reference, Languages[l], false)) + { + LOG("Error will merging phrase diff for language %s\n", Languages[l].c_str()); + return 1; + } + + // compare the reference an addition file, remove any equivalent strings. + uint addCount=0, refCount=0; + vector diff; + + CMakePhraseDiff2 differ; + differ.run(addition, reference, diff); + + if (diff.empty()) + { + LOG("No difference for language %s\n", Languages[l].c_str()); + } + else + { + LOG("Writing difference file for language %s\n", Languages[l].c_str()); + ucstring text; + text += "// DIFF_VERSION 2\r\n"; + text += preparePhraseFile(diff, false); + // add the tag for non translation + text += nl + ucstring ("// REMOVE THE FOLOWING LINE WHEN TRANSLATION IS DONE")+nl+ucstring("// DIFF NOT TRANSLATED")+nl; + CI18N::writeTextFile(diffDir+"phrase_"+Languages[l]+"_diff_"+diffVersion+".txt", text); + } + } + + return 0; +} + + + +int forgetPhraseDiff(int argc, char *argv[]) +{ + // merge all the phrase diff back into there repective translated phrase. + + LOG("forgeting phrase diffs\n"); + + std::string basename("phrase_"+Languages[0]); + string filename = transDir+basename+".txt"; + // build the addition diff + vector reference; + + + if (!readPhraseFile(transDir+basename+".txt", reference, false)) + { + LOG("Error will loading file %s", (transDir+basename+".txt").c_str()); + return 1; + } + //assert only change + + std::vector diffs; + getPathContentFiltered(diffDir+"phrase_wk_diff_", ".txt", diffs); + std::vector newPhrase; + for (uint i=0; i subDiff; + if (!readPhraseFile2(diffs[i], subDiff, false)) + return false; + std::copy (subDiff.begin (), subDiff.end (), std::back_inserter (newPhrase)); + } + + // a optimiser par une map + std::map > validClauseHashValue; + std::map > validPhraseHashValue; + for (uint i=0; i < newPhrase.size() ; ++i) + { + for (uint j=0; j < reference.size() ; ++j) + { + if (newPhrase[i].Identifier == reference[j].Identifier) + { + + + uint64 newPhraseHash = STRING_MANAGER::makePhraseHash( newPhrase[i] ); + uint64 oldPhraseHash = reference[j].HashValue; + validPhraseHashValue[newPhrase[i].Identifier] = std::pair(newPhraseHash, oldPhraseHash); + + for (uint k=0; k < newPhrase[i].Clauses.size() ; ++k) + { + if (reference[j] .Clauses.size() != newPhrase[i].Clauses.size()) + { + nlwarning("Want to forget minor update but phrase %s changes too much. The number of clauses has changed.", newPhrase[i].Identifier.c_str() ); + exit(-1); + } + const TClause& newClause = newPhrase[i].Clauses[k]; + const TClause& oldClause = reference[j].Clauses[k]; + + if (!newClause.Identifier.empty() ) + { + if (newClause.Identifier != oldClause.Identifier) + { + nlwarning("Want to forget minor update but phrase %s changes too much. Clauses order or clause identifier changed (%s).", newPhrase[i].Identifier.c_str(), newClause.Identifier.c_str()); + exit(-1); + } + uint64 newClauseHashValue = CI18N::makeHash(newClause.Text); + uint64 oldClauseHashValue = CI18N::makeHash(oldClause.Text); + validClauseHashValue[ newClause.Identifier ] = std::pair(newClauseHashValue, oldClauseHashValue); + } + } + } + } + } + + + if (!mergePhraseDiff2(reference, Languages[0], true, false)) + { + LOG("Error will merging phrase diff"); + return 1; + } + ucstring str = preparePhraseFile(reference, true); + CI18N::writeTextFile(transDir+basename+".txt", str); + + + updatePhraseHashValue(validPhraseHashValue); +// updateClauseHashValue(validClauseHashValue); + + + for (uint i=0; i > & outputResult + ) + +{ + //nlinfo("preprocessing %s", filename.c_str()); + ucstring result; + std::string fullName; + fullName = filename; + + if (fullName.empty()) + return; + + NLMISC::CIFile file; + + /// Open a file for reading. false if failed. close() if a file was opened. + if (!file.open (fullName)) + { + nlwarning("Can't open %s", fullName.c_str()); + return ; + } + + + + // Fast read all the text in binary mode. + std::string text; + text.resize(file.getFileSize()); + file.serialBuffer((uint8*)(&text[0]), (uint)text.size()); + + + // Transform the string in ucstring according to format header + if (!text.empty()) + CI18N::readTextBuffer((uint8*)&text[0], (uint)text.size(), result, false); + + + + ucstring final; + // parse the file, looking for preprocessor command. + ucstring::size_type pos = 0; + ucstring::size_type lastPos = 0; + ucstring includeCmd("#include"); + ucstring current; + + while ( pos != ucstring::npos) + { + pos = result.find(ucstring("\n"), pos); + if (pos != ucstring::npos) { ++pos; } + + ucstring line( result.substr(lastPos, pos - lastPos) ); + + + if ( line.find(includeCmd) != ucstring::npos) + { + ucstring::size_type firstFilename = line.find(ucstring("\"")); + ucstring::size_type lastFilename = line.find(ucstring("\""), firstFilename+1); + + ucstring name = line.substr(firstFilename +1, lastFilename - firstFilename -1); + string subFilename = name.toString(); + { + CIFile testFile; + if (!testFile.open(subFilename)) + { + // try to open the include file relative to current file + subFilename = CFile::getPath(filename)+subFilename; + } + } + preprocessTextFile(subFilename, outputResult); + } + else + { + current += line; + } + lastPos = pos; + + } + + + + outputResult.push_back( std::pair ( current, fullName ) ); +} + +int mergePhraseDiff(int argc, char *argv[]) +{ + // merge all the phrase diff back into there repective translated phrase. + uint l; + + LOG("Merging phrase diffs\n"); + + for (l=0; l reference; + + if (!readPhraseFile(transDir+basename+".txt", reference, false)) + { + LOG("Error will loading file %s", (transDir+basename+".txt").c_str()); + return 1; + } + + if (!mergePhraseDiff(reference, Languages[l], true, true)) + { + LOG("Error will merging phrase diff"); + return 1; + + } + + ucstring str = preparePhraseFile(reference, true); + + { + // backup the original file + ucstring old; + CI18N::readTextFile(filename, old, false, true, false, CI18N::LINE_FMT_CRLF); + if (old != str) + CFile::moveFile((historyDir+CFile::getFilenameWithoutExtension(filename)+"_"+diffVersion+"."+CFile::getExtension(filename)).c_str(), filename.c_str()); + } + + CI18N::writeTextFile(transDir+basename+".txt", str); + + } + + return 0; +} + + +int injectClause() +{ + uint l; + + LOG("Update translation from clauses.\n"); + + for (l=0; l clauses; + vector phrases; + + // load the clause file + std::string clausePath( transDir+"clause_"+Languages[l]+".txt" ); + if (!loadStringFile(clausePath, clauses, false)) + { + LOG("Error will loading file %s", clausePath.c_str()); + return 1; + } + + // load the phrase file + std::string phrasePath( transDir+"phrase_"+Languages[l]+".txt" ); + if (!readPhraseFile(phrasePath, phrases, false)) + { + LOG("Error will loading file %s", phrasePath.c_str()); + return 1; + } + + vector::iterator first(phrases.begin()); + vector::iterator last(phrases.end()); + for ( ; first != last; ++first) + { + + vector::iterator firstClause( first->Clauses.begin()); + vector::iterator lastClause( first->Clauses.end()); + for ( ; firstClause != lastClause; ++firstClause) + { + uint64 hashValue = CI18N::makeHash(firstClause->Text); + vector::iterator firstRefClause(clauses.begin()); + vector::iterator lastRefClause(clauses.end()); + for ( ; firstRefClause != lastRefClause ; ++firstRefClause) + { + if (hashValue == firstRefClause->HashValue && firstClause->Text != firstRefClause->Text) + { + firstClause->Text = firstRefClause->Text; + firstClause->HashValue = CI18N::makeHash(firstClause->Text); + firstRefClause->HashValue = firstClause->HashValue; + + + nlinfo("update clause %s from clause file %s.", firstClause->Identifier.c_str(), clausePath.c_str()); + } + } + } + } + + std::string desDir(diffDir + "inject_clause_" + diffVersion + "/"); + CFile::createDirectoryTree(desDir+ CFile::getPath(phrasePath)); + ucstring str = preparePhraseFile(phrases, true); + CI18N::writeTextFile(desDir + phrasePath, str); + + str = prepareStringFile(clauses, true); + CI18N::writeTextFile(desDir + clausePath, str); + } + + + return 0; +} + + + +int main(int argc, char *argv[]) +{ + NLMISC::CApplicationContext context; +/* createDebug(); + CStdDisplayer *display = new CStdDisplayer; + NLMISC::InfoLog->addDisplayer(display); + NLMISC::WarningLog->addDisplayer(display); + NLMISC::ErrorLog->addDisplayer(display); +*/ + +/* for (uint i=0; i<20; ++i) + { + uint64 hash = makeHash(ucstring("Bonjour le monde !")); + nldebug("%s", hashToString(hash).c_str()); + hash = makeHash(ucstring("Une autre cléf")); + nldebug("%s", hashToString(hash).c_str()); + } +*/ + + if (argc < 2) + { + showUsage(argv[0]); + return 1; + } + std::string argv1(argv[1]); + + // create the diff version. + char temp[16]; + sprintf(temp, "%8.8X", (uint) ::time(NULL)); + diffVersion = temp; + + if (strcmp(argv[1], "make_work") == 0) + { + return makeWork(); + } + + // generic worksheet comparison + if (strcmp(argv[1], "make_worksheet_diff") == 0) + { + if (argc != 3) + { + showUsage(argv[0]); + return 1; + } + + return makeWorksheetDiff(argc, argv, argv[2], argv[2], true); + } + else if (strcmp(argv[1], "merge_worksheet_diff") == 0) + { + if (argc != 3) + { + showUsage(argv[0]); + return 1; + } + + return mergeWorksheetDiff(argc, argv, argv[2], argv[2]); + } + else if (strcmp(argv[1], "crop_lines") == 0) + { + if (argc != 4) + { + showUsage(argv[0]); + return 1; + } + + uint nbLines; + NLMISC::fromString(argv[3], nbLines); + + cropLines(argv[2], nbLines); + + return 0; + } + else if (strcmp(argv[1], "extract_bot_names") == 0) + return extractBotNames(argc, argv); + else if (strcmp(argv[1], "extract_new_sheet_names") == 0) + return extractNewSheetNames(argc, argv); + + + + + if (argc != 2) + { + showUsage(argv[0]); + return 1; + } + +// if (strcmp(argv[1], "yann") == 0) +// return mergeYannTaf(); + + + string currentPath("./"); + CPath::addSearchPath(currentPath+addDir, true, false); + CPath::addSearchPath(currentPath+diffDir, true, false); +// CPath::addSearchPath(currentPath+transDir, true, false); + if (readLanguages() != 0) + { + LOG("Error will loading language file (language.txt)"); + return 1; + } + + if (strcmp(argv[1], "make_string_diff") == 0) + return makeStringDiff(argc, argv); + else if (strcmp(argv[1], "merge_string_diff") == 0) + return mergeStringDiff(argc, argv); + else if (strcmp(argv[1], "clean_string_diff") == 0) + return cleanStringDiff(argc, argv); + + else if (argv1 == "make_phrase_diff_old") + return makePhraseDiff(argc, argv); + else if (argv1 == "merge_phrase_diff_old") + return mergePhraseDiff(argc, argv, 1); + + + else if (argv1 == "make_phrase_diff") + return makePhraseDiff2(argc, argv); + else if (argv1 == "merge_phrase_diff") + return mergePhraseDiff(argc, argv, 2); + else if (argv1 == "forget_phrase_diff") + return forgetPhraseDiff(argc, argv); + else if (argv1 == "update_phrase_work") + return updatePhraseWork(); + else if (argv1 == "clean_phrase_diff") + return cleanPhraseDiff(argc, argv); + + else if (argv1 == "inject_clause") + return injectClause(); + + else if (argv1 == "sort_trans_phrase") + return sortTransPhrase(); + + else if (strcmp(argv[1], "make_clause_diff") == 0) + return makeClauseDiff(argc, argv); + else if (strcmp(argv[1], "merge_clause_diff") == 0) + return mergeClauseDiff(argc, argv); + else if (argv1 == "clean_clause_diff") + return cleanClauseDiff(argc, argv); + + else if (strcmp(argv[1], "make_words_diff") == 0) + return makeWordsDiff(argc, argv); + else if (strcmp(argv[1], "merge_words_diff") == 0) + return mergeWordsDiff(argc, argv); + else if (strcmp(argv[1], "clean_words_diff") == 0) + return cleanWordsDiff(argc, argv); + + else if (strcmp(argv[1], "recup_around") == 0) + return recupAround(argc, argv); + else if (strcmp(argv[1], "add_string_number") == 0) + return addStringNumber(); + + + return -1; + +} + + + +int addStringNumber() +{ + vector strings; + + LOG("Generating string diffs\nLoading the working file for language %s\n", Languages[0].c_str()); + // load the addition file + std::string addFile(Languages[0]+".uxt"); + if (!loadStringFile(addDir+addFile, strings, true)) + { + LOG("Error loading file %s\n", (addDir+addFile).c_str()); + return 1; + } + + ucstring str = prepareStringFile(strings, false); + + string filename = addDir+Languages[0]+".uxt"; + CI18N::writeTextFile(filename, str); + + return 0; +} + + diff --git a/code/ryzom/tools/xml_packer/xml_packer.cpp b/code/ryzom/tools/xml_packer/xml_packer.cpp index 5d1ff93f9..310721ddf 100644 --- a/code/ryzom/tools/xml_packer/xml_packer.cpp +++ b/code/ryzom/tools/xml_packer/xml_packer.cpp @@ -1,366 +1,366 @@ - - -#include "nel/misc/types_nl.h" -#include "nel/misc/app_context.h" -#include "nel/misc/path.h" -#include "nel/misc/sstring.h" -#include "nel/misc/algo.h" - -using namespace std; -using namespace NLMISC; - -enum TAction -{ - pack, - unpack, - undefined -}; - -const string DefaultExt("xml_pack"); -const uint32 MaxLineSize = 16*1024; - -const string ExcludeFiles(".#*;*.log;*.bin"); -const string ExcludeDirs("CVS"); - -bool isExcludedFile(const std::string &fileName) -{ - static vector excludeFileVect; - static bool init = false; - - if (!init) - { - explode(ExcludeFiles, ";", excludeFileVect, true); - init = true; - } - - bool excluded = false; - - for (uint i=0; i excludeDirVect; - static bool init = false; - - if (!init) - { - explode(ExcludeDirs, ";", excludeDirVect, true); - } - - bool excluded = false; - - for (uint i=0; i 0 && (path[pos] == '\\' || path[pos] == '/')) - --pos; - - while(pos > 0 && path[pos] != '\\' && path[pos] != '/' ) - dirName = path[pos--] + dirName; - - return dirName; -} - -int main(int argc, char *argv[]) -{ - printf("XML Packer/Unpacker V0.1\n(C) Nevrax 2006\n"); - CApplicationContext appContext; - - TAction action = undefined; - bool recursive = false; - - // compute the current folder name - string currentPath = CPath::getCurrentPath(); - string dirName = getLastDirName(currentPath);; - - string filename = dirName + "."+DefaultExt; - - // check the params to choose action - for (uint i=0; i]\n", argv[0]); - printf(" -p : pack the current folder\n"); - printf(" -u : unpack the current folder\n"); - printf(" -r : pack or unpack subdirectories recursively\n"); - // printf(" -f : use the specified filename instead of current directory name\n"); - - return -1; - } - - vector dirStack; - - printf("Current patch is '%s'\n", CPath::getCurrentPath().c_str()); - - // push the current directory to start the loop - dirStack.push_back(CPath::getCurrentPath()); - - - while(!dirStack.empty()) - { - string dirName = dirStack.back(); - dirStack.pop_back(); - string filename = dirName+"/"+getLastDirName(dirName) + "."+DefaultExt; - switch (action) - { - case pack: - { - printf("Packing directory '%s'...\n", dirName.c_str()); -// string packFileName = dirName+"/tmp."+DefaultExt; - string packFileName = filename; - - // get the current directory content - vector files; - CPath::getPathContent(dirName, false, false, true, files); - - vector validFiles; - - // first loop to build the list of valid file - for (uint i=0; i= packDate) - // no more to check - break; - } - - // all files are older than the pack file ! no repack needed - needRepack = false; - } - - if (needRepack) - { - // open the pack file - // FILE *fp = fopen(filename.c_str(), "wt"); - FILE *fp = fopen(packFileName.c_str(), "wt"); - - fprintf(fp, "\n"); - - for (uint i=0; i\n", CFile::getFilename(subFileName).c_str()); - - FILE *subFp = fopen(subFileName.c_str(), "rt"); - nlassert(subFp != NULL); - char buffer[MaxLineSize]; - char *result; - bool needFinalReturn = false; - result = fgets(buffer, MaxLineSize, subFp); - needFinalReturn = result != NULL ? buffer[strlen(buffer)-1] != '\n' : true; - while(result != 0) - { - fputs(buffer, fp); - result = fgets(buffer, MaxLineSize, subFp); - needFinalReturn = result != NULL ? buffer[strlen(buffer)-1] != '\n' : needFinalReturn; - } - if (needFinalReturn) - { - char *finalReturn = "\n"; - fputs(finalReturn, fp); - } - - fclose(subFp); - - fprintf(fp, " \n"); - } - - fprintf(fp, "\n"); - - fclose(fp); - } - else - { - printf("Directory %s is up to date, no repack\n", dirName.c_str()); - } - } - break; - case unpack: - { - printf("Unpacking directory '%s'...\n", dirName.c_str()); - // open the pack file -// FILE *fp = fopen((dirName+"/tmp."+DefaultExt).c_str(), "rt"); - FILE *fp = fopen(filename.c_str(), "rt"); - nlassert(fp != NULL); - uint linecount = 0; - - // read the first line - char buffer[MaxLineSize]; - fgets(buffer, MaxLineSize, fp); - linecount++; - if (strcmp(buffer, "\n") != 0) - { - printf ("Error : invalid pack file '%s'\n", filename.c_str()); - exit(-1); - } - - char *result = NULL; - do - { - // read a file line - fgets(buffer, MaxLineSize, fp); - CSString parser(buffer); - linecount++; - if (parser.find(" ") == 0) - { - // end of pack file - fclose(fp); - break; - } - printf ("Error : invalid pack file '%s' at line %u", filename.c_str(), linecount); - exit(-1); - } - - CSString subFileName = parser.leftCrop(sizeof(" \n") != 0) - { - fputs(result, output); - // read next line - result = fgets(buffer, MaxLineSize, fp); - linecount++; - } - - fclose(output); - - } while(result != NULL); - - } - // break; - } - - if (recursive) - { - vector subDirs; - CPath::getPathContent(dirName, false, true, false, subDirs); - - // filter the directories - for (uint i=subDirs.size(); i>0; --i) - { - if (!isExcludedDir(subDirs[i-1])) - dirStack.push_back(subDirs[i-1]); - } - } -} -return 0; -} - - - - - - - - - - - - - - - - - - - - - + + +#include "nel/misc/types_nl.h" +#include "nel/misc/app_context.h" +#include "nel/misc/path.h" +#include "nel/misc/sstring.h" +#include "nel/misc/algo.h" + +using namespace std; +using namespace NLMISC; + +enum TAction +{ + pack, + unpack, + undefined +}; + +const string DefaultExt("xml_pack"); +const uint32 MaxLineSize = 16*1024; + +const string ExcludeFiles(".#*;*.log;*.bin"); +const string ExcludeDirs("CVS"); + +bool isExcludedFile(const std::string &fileName) +{ + static vector excludeFileVect; + static bool init = false; + + if (!init) + { + explode(ExcludeFiles, ";", excludeFileVect, true); + init = true; + } + + bool excluded = false; + + for (uint i=0; i excludeDirVect; + static bool init = false; + + if (!init) + { + explode(ExcludeDirs, ";", excludeDirVect, true); + } + + bool excluded = false; + + for (uint i=0; i 0 && (path[pos] == '\\' || path[pos] == '/')) + --pos; + + while(pos > 0 && path[pos] != '\\' && path[pos] != '/' ) + dirName = path[pos--] + dirName; + + return dirName; +} + +int main(int argc, char *argv[]) +{ + printf("XML Packer/Unpacker V0.1\n(C) Nevrax 2006\n"); + CApplicationContext appContext; + + TAction action = undefined; + bool recursive = false; + + // compute the current folder name + string currentPath = CPath::getCurrentPath(); + string dirName = getLastDirName(currentPath);; + + string filename = dirName + "."+DefaultExt; + + // check the params to choose action + for (uint i=0; i]\n", argv[0]); + printf(" -p : pack the current folder\n"); + printf(" -u : unpack the current folder\n"); + printf(" -r : pack or unpack subdirectories recursively\n"); + // printf(" -f : use the specified filename instead of current directory name\n"); + + return -1; + } + + vector dirStack; + + printf("Current patch is '%s'\n", CPath::getCurrentPath().c_str()); + + // push the current directory to start the loop + dirStack.push_back(CPath::getCurrentPath()); + + + while(!dirStack.empty()) + { + string dirName = dirStack.back(); + dirStack.pop_back(); + string filename = dirName+"/"+getLastDirName(dirName) + "."+DefaultExt; + switch (action) + { + case pack: + { + printf("Packing directory '%s'...\n", dirName.c_str()); +// string packFileName = dirName+"/tmp."+DefaultExt; + string packFileName = filename; + + // get the current directory content + vector files; + CPath::getPathContent(dirName, false, false, true, files); + + vector validFiles; + + // first loop to build the list of valid file + for (uint i=0; i= packDate) + // no more to check + break; + } + + // all files are older than the pack file ! no repack needed + needRepack = false; + } + + if (needRepack) + { + // open the pack file + // FILE *fp = fopen(filename.c_str(), "wt"); + FILE *fp = fopen(packFileName.c_str(), "wt"); + + fprintf(fp, "\n"); + + for (uint i=0; i\n", CFile::getFilename(subFileName).c_str()); + + FILE *subFp = fopen(subFileName.c_str(), "rt"); + nlassert(subFp != NULL); + char buffer[MaxLineSize]; + char *result; + bool needFinalReturn = false; + result = fgets(buffer, MaxLineSize, subFp); + needFinalReturn = result != NULL ? buffer[strlen(buffer)-1] != '\n' : true; + while(result != 0) + { + fputs(buffer, fp); + result = fgets(buffer, MaxLineSize, subFp); + needFinalReturn = result != NULL ? buffer[strlen(buffer)-1] != '\n' : needFinalReturn; + } + if (needFinalReturn) + { + char *finalReturn = "\n"; + fputs(finalReturn, fp); + } + + fclose(subFp); + + fprintf(fp, " \n"); + } + + fprintf(fp, "\n"); + + fclose(fp); + } + else + { + printf("Directory %s is up to date, no repack\n", dirName.c_str()); + } + } + break; + case unpack: + { + printf("Unpacking directory '%s'...\n", dirName.c_str()); + // open the pack file +// FILE *fp = fopen((dirName+"/tmp."+DefaultExt).c_str(), "rt"); + FILE *fp = fopen(filename.c_str(), "rt"); + nlassert(fp != NULL); + uint linecount = 0; + + // read the first line + char buffer[MaxLineSize]; + fgets(buffer, MaxLineSize, fp); + linecount++; + if (strcmp(buffer, "\n") != 0) + { + printf ("Error : invalid pack file '%s'\n", filename.c_str()); + exit(-1); + } + + char *result = NULL; + do + { + // read a file line + fgets(buffer, MaxLineSize, fp); + CSString parser(buffer); + linecount++; + if (parser.find(" ") == 0) + { + // end of pack file + fclose(fp); + break; + } + printf ("Error : invalid pack file '%s' at line %u", filename.c_str(), linecount); + exit(-1); + } + + CSString subFileName = parser.leftCrop(sizeof(" \n") != 0) + { + fputs(result, output); + // read next line + result = fgets(buffer, MaxLineSize, fp); + linecount++; + } + + fclose(output); + + } while(result != NULL); + + } + // break; + } + + if (recursive) + { + vector subDirs; + CPath::getPathContent(dirName, false, true, false, subDirs); + + // filter the directories + for (uint i=subDirs.size(); i>0; --i) + { + if (!isExcludedDir(subDirs[i-1])) + dirStack.push_back(subDirs[i-1]); + } + } +} +return 0; +} + + + + + + + + + + + + + + + + + + + + + diff --git a/code/snowballs2/CMakeLists.txt b/code/snowballs2/CMakeLists.txt index 3107726e0..8a8363d4f 100644 --- a/code/snowballs2/CMakeLists.txt +++ b/code/snowballs2/CMakeLists.txt @@ -1,31 +1,31 @@ -IF(WIN32) - SET(SNOWBALLS_CONFIG_FILE "." CACHE FILEPATH "Snowballs config file location") -ELSE(WIN32) - SET(SNOWBALLS_CONFIG_FILE "${NL_ETC_PREFIX}/snowballs" CACHE FILEPATH "Snowballs config file location") -ENDIF(WIN32) -SET(SNOWBALLS_DATA_FILE "${NL_SHARE_PREFIX}/games/snowballs" CACHE FILEPATH "Snowballs data file location") -SET(SNOWBALLS_LOG_FILE "${NL_LOG_PREFIX}/snowballs" CACHE FILEPATH "Snowballs log file location") - -# Note: Not sure if this is still the best way to do this... -#INSTALL(CODE "FILE(MAKE_DIRECTORY ${SNOWBALLS_LOG_FILE})") - -#----------------------------------------------------------------------------- -#Platform specifics - -### -# An example of finding NeL 3D and CEGUI Renderer. -### -ADD_DEFINITIONS(-DSNOWBALLS_CONFIG="${SNOWBALLS_CONFIG_FILE}/" -DSNOWBALLS_STATE="${SNOWBALLS_LOG_FILE}/" -DSNOWBALLS_LOGS="${SNOWBALLS_LOG_FILE}/") - -IF(WITH_SNOWBALLS_CLIENT) - ADD_SUBDIRECTORY(client) -ENDIF(WITH_SNOWBALLS_CLIENT) - -IF(WITH_SNOWBALLS_SERVER) - ADD_SUBDIRECTORY(server) -ENDIF(WITH_SNOWBALLS_SERVER) - -IF(WITH_SNOWBALLS_PACKAGE) - INCLUDE(CMakePackaging.txt) -ENDIF(WITH_SNOWBALLS_PACKAGE) - +IF(WIN32) + SET(SNOWBALLS_CONFIG_FILE "." CACHE FILEPATH "Snowballs config file location") +ELSE(WIN32) + SET(SNOWBALLS_CONFIG_FILE "${NL_ETC_PREFIX}/snowballs" CACHE FILEPATH "Snowballs config file location") +ENDIF(WIN32) +SET(SNOWBALLS_DATA_FILE "${NL_SHARE_PREFIX}/games/snowballs" CACHE FILEPATH "Snowballs data file location") +SET(SNOWBALLS_LOG_FILE "${NL_LOG_PREFIX}/snowballs" CACHE FILEPATH "Snowballs log file location") + +# Note: Not sure if this is still the best way to do this... +#INSTALL(CODE "FILE(MAKE_DIRECTORY ${SNOWBALLS_LOG_FILE})") + +#----------------------------------------------------------------------------- +#Platform specifics + +### +# An example of finding NeL 3D and CEGUI Renderer. +### +ADD_DEFINITIONS(-DSNOWBALLS_CONFIG="${SNOWBALLS_CONFIG_FILE}/" -DSNOWBALLS_STATE="${SNOWBALLS_LOG_FILE}/" -DSNOWBALLS_LOGS="${SNOWBALLS_LOG_FILE}/") + +IF(WITH_SNOWBALLS_CLIENT) + ADD_SUBDIRECTORY(client) +ENDIF(WITH_SNOWBALLS_CLIENT) + +IF(WITH_SNOWBALLS_SERVER) + ADD_SUBDIRECTORY(server) +ENDIF(WITH_SNOWBALLS_SERVER) + +IF(WITH_SNOWBALLS_PACKAGE) + INCLUDE(CMakePackaging.txt) +ENDIF(WITH_SNOWBALLS_PACKAGE) + diff --git a/code/snowballs2/client/CMakeLists.txt b/code/snowballs2/client/CMakeLists.txt index a4a257383..502b01c28 100644 --- a/code/snowballs2/client/CMakeLists.txt +++ b/code/snowballs2/client/CMakeLists.txt @@ -1,12 +1,12 @@ -ADD_SUBDIRECTORY(src) - -SET(database "${SNOWBALLS_DATA_FILE}") -CONFIGURE_FILE(client.cfg.in client.cfg) - -INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/client.cfg DESTINATION etc/snowballs COMPONENT snowballsclient) -INSTALL(DIRECTORY data/ - DESTINATION share/games/snowballs - COMPONENT snowballsdata - PATTERN "CVS" EXCLUDE - PATTERN ".svn" EXCLUDE - PATTERN "Makefile*" EXCLUDE) +ADD_SUBDIRECTORY(src) + +SET(database "${SNOWBALLS_DATA_FILE}") +CONFIGURE_FILE(client.cfg.in client.cfg) + +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/client.cfg DESTINATION etc/snowballs COMPONENT snowballsclient) +INSTALL(DIRECTORY data/ + DESTINATION share/games/snowballs + COMPONENT snowballsdata + PATTERN "CVS" EXCLUDE + PATTERN ".svn" EXCLUDE + PATTERN "Makefile*" EXCLUDE) diff --git a/code/snowballs2/client/src/CMakeLists.txt b/code/snowballs2/client/src/CMakeLists.txt index 3ba88c629..b08ee3a43 100644 --- a/code/snowballs2/client/src/CMakeLists.txt +++ b/code/snowballs2/client/src/CMakeLists.txt @@ -1,20 +1,20 @@ -FILE(GLOB SRC *.cpp *.h) - -ADD_EXECUTABLE(snowballs_client WIN32 ${SRC}) - -TARGET_LINK_LIBRARIES(snowballs_client - nelmisc - nelpacs - nelnet - nel3d) - -NL_DEFAULT_PROPS(snowballs_client "Snowballs, Client: Snowballs Client") -NL_ADD_RUNTIME_FLAGS(snowballs_client) - -# If sound is enabled then add the definitions and link the libraries. -IF(ENABLE_SOUND) - ADD_DEFINITIONS(-DSBCLIENT_WITH_SOUND) - TARGET_LINK_LIBRARIES(snowballs_client ${NELSOUND_LIBRARY}) -ENDIF(ENABLE_SOUND) - -INSTALL(TARGETS snowballs_client RUNTIME DESTINATION bin COMPONENT snowballsclient) +FILE(GLOB SRC *.cpp *.h) + +ADD_EXECUTABLE(snowballs_client WIN32 ${SRC}) + +TARGET_LINK_LIBRARIES(snowballs_client + nelmisc + nelpacs + nelnet + nel3d) + +NL_DEFAULT_PROPS(snowballs_client "Snowballs, Client: Snowballs Client") +NL_ADD_RUNTIME_FLAGS(snowballs_client) + +# If sound is enabled then add the definitions and link the libraries. +IF(ENABLE_SOUND) + ADD_DEFINITIONS(-DSBCLIENT_WITH_SOUND) + TARGET_LINK_LIBRARIES(snowballs_client ${NELSOUND_LIBRARY}) +ENDIF(ENABLE_SOUND) + +INSTALL(TARGETS snowballs_client RUNTIME DESTINATION bin COMPONENT snowballsclient) diff --git a/code/snowballs2/client/src/animation.cpp b/code/snowballs2/client/src/animation.cpp index a30b35e06..ab873ffbc 100644 --- a/code/snowballs2/client/src/animation.cpp +++ b/code/snowballs2/client/src/animation.cpp @@ -1,286 +1,286 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "animation.h" -#include "entities.h" -#include "snowballs_client.h" - -// -// Namespaces -// - -using namespace std; -using namespace NLMISC; -using namespace NL3D; - -namespace SBCLIENT { - -// -// Constantes -// - -// Amount of time for the transistion between 2 animations -CAnimationTime TransitionTime = 0.25f; - -// -// Variables -// - -UAnimationSet *AnimationSet = NULL; -UPlayListManager *PlayListManager = NULL; - -struct Anim -{ - const char *Name; - bool Loop; - uint Id; - UAnimation *Animation; -}; - -Anim AnimIdArray[][2] = -{ - { { "patterfeet.anim", false, 0, NULL }, { "", false, 0, NULL } }, - { { "marche.anim", true, 0, NULL }, { "", false, 0, NULL } }, - { { "idle.anim", true, 0, NULL }, { "", false, 0, NULL } }, - { { "log_on.anim", false, 0, NULL }, { "", false, 0, NULL } }, - { { "log_off.anim", false, 0, NULL }, { "", false, 0, NULL } }, - { { "lancelaboule.anim", false, 0, NULL }, { "", false, 0, NULL } }, - { { "prepaboule.anim", false, 0, NULL }, { "", false, 0, NULL } }, - { { "prepaboulecycle.anim", true, 0, NULL }, { "", false, 0, NULL } }, - { { "impact.anim", false, 0, NULL }, { "", false, 0, NULL } }, -}; - - -// -// Functions -// - -void computeAnimation (CEntity &entity, EAnim anim) -{ - // Get the current time - double currentTime = double (CTime::getLocalTime ())/1000.0f; - -// nlinfo ("%d playing animation", anim); -// nlinfo ("%d playing animation %s ct%f st%f et%f", anim, AnimIdArray[anim][0].Name, currentTime, AnimIdArray[anim][0].Animation->getBeginTime (), AnimIdArray[anim][0].Animation->getEndTime ()); - - // Find the new slot for the full animation (0 or 1) - uint newSlot = entity.NextEmptySlot; - uint oldSlot = 1 - entity.NextEmptySlot; - entity.NextEmptySlot = 1 - entity.NextEmptySlot; - - UPlayList::TWrapMode wrapMode = AnimIdArray[anim][0].Loop ? UPlayList::Repeat : UPlayList::Clamp; - - entity.PlayList->setAnimation (newSlot, AnimIdArray[anim][0].Id); - entity.PlayList->setTimeOrigin (newSlot, currentTime); - entity.PlayList->setWeightSmoothness (newSlot, 1.0f); - entity.PlayList->setWrapMode (newSlot, wrapMode); - - double OldStartTime, OldEndTime; - double NewStartTime, NewEndTime; - - // Get the starting time of the old animation slot - entity.PlayList->getStartWeight (oldSlot, OldStartTime); - - // Compute the time delta between start of the old animation and now - double dt = currentTime - OldStartTime; - - // Compute the new transition value depending of the current time - - if (dt > TransitionTime) - dt = TransitionTime; - - OldStartTime = currentTime - (TransitionTime - dt); - OldEndTime = currentTime + dt; - - NewStartTime = currentTime; - NewEndTime = currentTime + dt; - - // Set new weights on the old and the new animation slot - - entity.PlayList->setStartWeight (oldSlot, 1.0f, OldStartTime); - entity.PlayList->setEndWeight (oldSlot, 0.0f, OldEndTime); - - entity.PlayList->setStartWeight (newSlot, 0.0f, NewStartTime); - entity.PlayList->setEndWeight (newSlot, 1.0f, OldEndTime); - - // Keep in mind what is the last animation id we set - entity.StartAnimationTime = (float)currentTime; -} - - -void playAnimation (CEntity &entity, EAnim anim, bool force) -{ - nlassert (anim > -2 && anim < 20); -// nlinfo ("playAnimation() %d", anim); - - // Get the current time - CAnimationTime currentTime = CAnimationTime(CTime::getLocalTime ())/1000.0f; - - // Can't do animation without skeleton - if (entity.Skeleton.empty()) - return; - - // If the first time we play an animation, creates the animation class - if (entity.PlayList == NULL) - createAnimation (entity); - - if (force || entity.AnimQueue.empty()) - { - computeAnimation (entity, anim); - - // clear the animation queue - //nlinfo ("clearing animation queue"); - while (!entity.AnimQueue.empty()) - entity.AnimQueue.pop (); - } - -// nlinfo ("pushing animation %d", anim); -// nlinfo ("pushing animation %s", AnimIdArray[anim][0].Name); - entity.AnimQueue.push (anim); -} - -void createAnimation (CEntity &entity) -{ - nlassert (!entity.Instance.empty() && !entity.Skeleton.empty() && AnimationSet != NULL); - - entity.PlayList = PlayListManager->createPlayList (AnimationSet); - entity.PlayList->registerTransform (entity.Instance); - entity.PlayList->registerTransform (entity.Skeleton); -} - -void deleteAnimation (CEntity &entity) -{ - if (entity.PlayList == NULL) - return; - - PlayListManager->deletePlayList (entity.PlayList); - entity.PlayList= NULL; -} - - -void initAnimation() -{ - AnimationSet = Driver->createAnimationSet (); - - // Add all animations in the animation set - for (uint i = 0; i < sizeof (AnimIdArray) / sizeof (AnimIdArray[0]); i++) - { - if (AnimIdArray[i][0].Name[0] != '\0') - { - AnimIdArray[i][0].Id = AnimationSet->addAnimation (AnimIdArray[i][0].Name, AnimIdArray[i][0].Name); - AnimIdArray[i][0].Animation = AnimationSet->getAnimation (AnimIdArray[i][0].Id); - } - - if (AnimIdArray[i][1].Name[0] != '\0') - { - AnimIdArray[i][1].Id = AnimationSet->addAnimation (AnimIdArray[i][1].Name, AnimIdArray[i][1].Name); - AnimIdArray[i][1].Animation = AnimationSet->getAnimation (AnimIdArray[i][1].Id); - } - } - AnimationSet->build (); - - PlayListManager = Scene->createPlayListManager (); -} - -void updateAnimation() -{ - // Get the current time - CAnimationTime currentTime = CAnimationTime(CTime::getLocalTime ())/1000.0f; - - for (EIT eit = Entities.begin (); eit != Entities.end (); eit++) - { - CEntity &entity = (*eit).second; - - if (entity.AnimQueue.empty ()) - { -// nlwarning ("empty queue update!!!"); - continue; - } - - EAnim currentAnim = entity.AnimQueue.front (); - if (!AnimIdArray[currentAnim][0].Loop && currentTime >= entity.StartAnimationTime + AnimIdArray[currentAnim][0].Animation->getEndTime () - TransitionTime/2) - { - // remove the current anim - entity.AnimQueue.pop (); - - if (entity.AnimQueue.empty ()) - { -// nlwarning ("empty queue!!!!!!"); - continue; - } - - EAnim newAnim = entity.AnimQueue.front (); - - computeAnimation (entity, newAnim); -/* - nlinfo ("playing animation %s ct%f st%f et%f", AnimIdArray[newAnim][0].Name, currentTime, AnimIdArray[newAnim][0].Animation->getBeginTime (), AnimIdArray[newAnim][0].Animation->getEndTime ()); - // setup the new anim - entity.PlayList->setAnimation (0, AnimIdArray[newAnim][0].Id); - entity.PlayList->setTimeOrigin (0, currentTime); - entity.PlayList->setStartWeight (0, 1.0f, currentTime); - entity.PlayList->setEndWeight (0, 1.0f, currentTime+TransitionTime); - entity.PlayList->setWeightSmoothness (0, 1.0f); - - if (AnimIdArray[newAnim][0].Loop) - entity.PlayList->setWrapMode (0, UPlayList::Repeat); - else - entity.PlayList->setWrapMode (0, UPlayList::Clamp); - - entity.StartAnimationTime = currentTime; -*/ } - } - - // compute new animation position depending of the current time - PlayListManager->animate (double(CTime::getLocalTime ())/1000.0f); -} - -void releaseAnimation() -{ - Scene->deletePlayListManager (PlayListManager); - -// The next line doesn t work (say that AnimationSet is not a valid AnimationSet Ptr) so we comment it. -// Scene->deleteAnimationSet (AnimationSet); -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "animation.h" +#include "entities.h" +#include "snowballs_client.h" + +// +// Namespaces +// + +using namespace std; +using namespace NLMISC; +using namespace NL3D; + +namespace SBCLIENT { + +// +// Constantes +// + +// Amount of time for the transistion between 2 animations +CAnimationTime TransitionTime = 0.25f; + +// +// Variables +// + +UAnimationSet *AnimationSet = NULL; +UPlayListManager *PlayListManager = NULL; + +struct Anim +{ + const char *Name; + bool Loop; + uint Id; + UAnimation *Animation; +}; + +Anim AnimIdArray[][2] = +{ + { { "patterfeet.anim", false, 0, NULL }, { "", false, 0, NULL } }, + { { "marche.anim", true, 0, NULL }, { "", false, 0, NULL } }, + { { "idle.anim", true, 0, NULL }, { "", false, 0, NULL } }, + { { "log_on.anim", false, 0, NULL }, { "", false, 0, NULL } }, + { { "log_off.anim", false, 0, NULL }, { "", false, 0, NULL } }, + { { "lancelaboule.anim", false, 0, NULL }, { "", false, 0, NULL } }, + { { "prepaboule.anim", false, 0, NULL }, { "", false, 0, NULL } }, + { { "prepaboulecycle.anim", true, 0, NULL }, { "", false, 0, NULL } }, + { { "impact.anim", false, 0, NULL }, { "", false, 0, NULL } }, +}; + + +// +// Functions +// + +void computeAnimation (CEntity &entity, EAnim anim) +{ + // Get the current time + double currentTime = double (CTime::getLocalTime ())/1000.0f; + +// nlinfo ("%d playing animation", anim); +// nlinfo ("%d playing animation %s ct%f st%f et%f", anim, AnimIdArray[anim][0].Name, currentTime, AnimIdArray[anim][0].Animation->getBeginTime (), AnimIdArray[anim][0].Animation->getEndTime ()); + + // Find the new slot for the full animation (0 or 1) + uint newSlot = entity.NextEmptySlot; + uint oldSlot = 1 - entity.NextEmptySlot; + entity.NextEmptySlot = 1 - entity.NextEmptySlot; + + UPlayList::TWrapMode wrapMode = AnimIdArray[anim][0].Loop ? UPlayList::Repeat : UPlayList::Clamp; + + entity.PlayList->setAnimation (newSlot, AnimIdArray[anim][0].Id); + entity.PlayList->setTimeOrigin (newSlot, currentTime); + entity.PlayList->setWeightSmoothness (newSlot, 1.0f); + entity.PlayList->setWrapMode (newSlot, wrapMode); + + double OldStartTime, OldEndTime; + double NewStartTime, NewEndTime; + + // Get the starting time of the old animation slot + entity.PlayList->getStartWeight (oldSlot, OldStartTime); + + // Compute the time delta between start of the old animation and now + double dt = currentTime - OldStartTime; + + // Compute the new transition value depending of the current time + + if (dt > TransitionTime) + dt = TransitionTime; + + OldStartTime = currentTime - (TransitionTime - dt); + OldEndTime = currentTime + dt; + + NewStartTime = currentTime; + NewEndTime = currentTime + dt; + + // Set new weights on the old and the new animation slot + + entity.PlayList->setStartWeight (oldSlot, 1.0f, OldStartTime); + entity.PlayList->setEndWeight (oldSlot, 0.0f, OldEndTime); + + entity.PlayList->setStartWeight (newSlot, 0.0f, NewStartTime); + entity.PlayList->setEndWeight (newSlot, 1.0f, OldEndTime); + + // Keep in mind what is the last animation id we set + entity.StartAnimationTime = (float)currentTime; +} + + +void playAnimation (CEntity &entity, EAnim anim, bool force) +{ + nlassert (anim > -2 && anim < 20); +// nlinfo ("playAnimation() %d", anim); + + // Get the current time + CAnimationTime currentTime = CAnimationTime(CTime::getLocalTime ())/1000.0f; + + // Can't do animation without skeleton + if (entity.Skeleton.empty()) + return; + + // If the first time we play an animation, creates the animation class + if (entity.PlayList == NULL) + createAnimation (entity); + + if (force || entity.AnimQueue.empty()) + { + computeAnimation (entity, anim); + + // clear the animation queue + //nlinfo ("clearing animation queue"); + while (!entity.AnimQueue.empty()) + entity.AnimQueue.pop (); + } + +// nlinfo ("pushing animation %d", anim); +// nlinfo ("pushing animation %s", AnimIdArray[anim][0].Name); + entity.AnimQueue.push (anim); +} + +void createAnimation (CEntity &entity) +{ + nlassert (!entity.Instance.empty() && !entity.Skeleton.empty() && AnimationSet != NULL); + + entity.PlayList = PlayListManager->createPlayList (AnimationSet); + entity.PlayList->registerTransform (entity.Instance); + entity.PlayList->registerTransform (entity.Skeleton); +} + +void deleteAnimation (CEntity &entity) +{ + if (entity.PlayList == NULL) + return; + + PlayListManager->deletePlayList (entity.PlayList); + entity.PlayList= NULL; +} + + +void initAnimation() +{ + AnimationSet = Driver->createAnimationSet (); + + // Add all animations in the animation set + for (uint i = 0; i < sizeof (AnimIdArray) / sizeof (AnimIdArray[0]); i++) + { + if (AnimIdArray[i][0].Name[0] != '\0') + { + AnimIdArray[i][0].Id = AnimationSet->addAnimation (AnimIdArray[i][0].Name, AnimIdArray[i][0].Name); + AnimIdArray[i][0].Animation = AnimationSet->getAnimation (AnimIdArray[i][0].Id); + } + + if (AnimIdArray[i][1].Name[0] != '\0') + { + AnimIdArray[i][1].Id = AnimationSet->addAnimation (AnimIdArray[i][1].Name, AnimIdArray[i][1].Name); + AnimIdArray[i][1].Animation = AnimationSet->getAnimation (AnimIdArray[i][1].Id); + } + } + AnimationSet->build (); + + PlayListManager = Scene->createPlayListManager (); +} + +void updateAnimation() +{ + // Get the current time + CAnimationTime currentTime = CAnimationTime(CTime::getLocalTime ())/1000.0f; + + for (EIT eit = Entities.begin (); eit != Entities.end (); eit++) + { + CEntity &entity = (*eit).second; + + if (entity.AnimQueue.empty ()) + { +// nlwarning ("empty queue update!!!"); + continue; + } + + EAnim currentAnim = entity.AnimQueue.front (); + if (!AnimIdArray[currentAnim][0].Loop && currentTime >= entity.StartAnimationTime + AnimIdArray[currentAnim][0].Animation->getEndTime () - TransitionTime/2) + { + // remove the current anim + entity.AnimQueue.pop (); + + if (entity.AnimQueue.empty ()) + { +// nlwarning ("empty queue!!!!!!"); + continue; + } + + EAnim newAnim = entity.AnimQueue.front (); + + computeAnimation (entity, newAnim); +/* + nlinfo ("playing animation %s ct%f st%f et%f", AnimIdArray[newAnim][0].Name, currentTime, AnimIdArray[newAnim][0].Animation->getBeginTime (), AnimIdArray[newAnim][0].Animation->getEndTime ()); + // setup the new anim + entity.PlayList->setAnimation (0, AnimIdArray[newAnim][0].Id); + entity.PlayList->setTimeOrigin (0, currentTime); + entity.PlayList->setStartWeight (0, 1.0f, currentTime); + entity.PlayList->setEndWeight (0, 1.0f, currentTime+TransitionTime); + entity.PlayList->setWeightSmoothness (0, 1.0f); + + if (AnimIdArray[newAnim][0].Loop) + entity.PlayList->setWrapMode (0, UPlayList::Repeat); + else + entity.PlayList->setWrapMode (0, UPlayList::Clamp); + + entity.StartAnimationTime = currentTime; +*/ } + } + + // compute new animation position depending of the current time + PlayListManager->animate (double(CTime::getLocalTime ())/1000.0f); +} + +void releaseAnimation() +{ + Scene->deletePlayListManager (PlayListManager); + +// The next line doesn t work (say that AnimationSet is not a valid AnimationSet Ptr) so we comment it. +// Scene->deleteAnimationSet (AnimationSet); +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/animation.h b/code/snowballs2/client/src/animation.h index 4d7da4d64..5fc0abd1b 100644 --- a/code/snowballs2/client/src/animation.h +++ b/code/snowballs2/client/src/animation.h @@ -1,56 +1,56 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef ANIMATION_H -#define ANIMATION_H - -namespace SBCLIENT { - -// -// External definitions -// - -class CEntity; - -// -// External variables -// - -// Animation id used by playAnimation() -enum EAnim { NoAnim = -1, PrepareWalkAnim, WalkAnim, IdleAnim, LogInAnim, LogOffAnim, ThrowSnowball, PrepareSnowBall, PrepareSnowBallCycle, HitAnim }; - -// -// External functions -// - -// This function is automatically called by playAnimation() the first time -void createAnimation (CEntity &entity); - -// Change the animation of an entity. You have to give the animation id -void playAnimation (CEntity &entity, EAnim anim, bool force = false); - -// This function must be called before releasing the entity to delete the entity animation -void deleteAnimation (CEntity &entity); - -void initAnimation (); -void updateAnimation (); -void releaseAnimation (); - -} /* namespace SBCLIENT */ - -#endif // ANIMATION_H - -/* End of animation.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef ANIMATION_H +#define ANIMATION_H + +namespace SBCLIENT { + +// +// External definitions +// + +class CEntity; + +// +// External variables +// + +// Animation id used by playAnimation() +enum EAnim { NoAnim = -1, PrepareWalkAnim, WalkAnim, IdleAnim, LogInAnim, LogOffAnim, ThrowSnowball, PrepareSnowBall, PrepareSnowBallCycle, HitAnim }; + +// +// External functions +// + +// This function is automatically called by playAnimation() the first time +void createAnimation (CEntity &entity); + +// Change the animation of an entity. You have to give the animation id +void playAnimation (CEntity &entity, EAnim anim, bool force = false); + +// This function must be called before releasing the entity to delete the entity animation +void deleteAnimation (CEntity &entity); + +void initAnimation (); +void updateAnimation (); +void releaseAnimation (); + +} /* namespace SBCLIENT */ + +#endif // ANIMATION_H + +/* End of animation.h */ diff --git a/code/snowballs2/client/src/camera.cpp b/code/snowballs2/client/src/camera.cpp index 5b2524b9a..b202fba63 100644 --- a/code/snowballs2/client/src/camera.cpp +++ b/code/snowballs2/client/src/camera.cpp @@ -1,169 +1,169 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "snowballs_client.h" -#include "entities.h" -#include "mouse_listener.h" -#include "pacs.h" - -// -// Namespaces -// - -using namespace std; -using namespace NLMISC; -using namespace NL3D; - -namespace SBCLIENT { - -// -// Variables -// - -// The camera for the whole scene -UCamera Camera = NULL; -// The collision entity use to snap the camera on the ground -UVisualCollisionEntity *CamCollisionEntity = NULL; - -// The particle system for the snowing effect -static UInstance Snow = NULL; - -// The sky 3D objects -static UScene *SkyScene = NULL; -static UCamera SkyCamera = NULL; -static UInstance Sky = NULL; - -static UCloudScape *Clouds = NULL; - -// -// Functions -// - -void initCamera() -{ - // Set up directly the camera - Camera = Scene->getCam(); - Camera.setTransformMode (UTransformable::DirectMatrix); - Camera.setPerspective ((float)Pi/2.f, 1.33f, 0.1f, 1000); - Camera.lookAt (CVector(ConfigFile->getVar("StartPoint").asFloat(0), - ConfigFile->getVar("StartPoint").asFloat(1), - ConfigFile->getVar("StartPoint").asFloat(2)), - CVectorD (0,0,0)); - - CamCollisionEntity = VisualCollisionManager->createEntity(); - CamCollisionEntity->setCeilMode(true); - - // Create the snowing particle system - Snow = Scene->createInstance("snow.ps"); - // And setup it - Snow.setTransformMode (UTransformable::DirectMatrix); - - // - // Setup the sky scene - // - - // -- -- not sure what the sky has to do with the camera - - SkyScene = Driver->createScene(false); - - SkyCamera = SkyScene->getCam (); - SkyCamera.setTransformMode (UTransformable::DirectMatrix); - // Set the very same frustum as the main camera - SkyCamera.setFrustum (Camera.getFrustum ()); - - Sky = SkyScene->createInstance("sky.shape"); - Sky.setTransformMode (UTransformable::DirectMatrix); - Sky.setMatrix(CMatrix::Identity); -} - -void releaseCamera() -{ - SkyScene->deleteInstance(Sky); - Driver->deleteScene(SkyScene); - Scene->deleteInstance(Snow); - VisualCollisionManager->deleteEntity(CamCollisionEntity); -} - -void updateCamera() -{ - // Set the new position of the snow emitter - CMatrix mat = CMatrix::Identity; - mat.setPos (Camera.getMatrix().getPos()/*+CVector (0.0f, 0.0f, -10.0f)*/); - Snow.setMatrix(mat); -} - -void initSky() -{ - // -- -- or what the clouds have to do with the sky - - SCloudScapeSetup css; - Clouds = Scene->createCloudScape (); - Clouds->init (&css); - Clouds->setQuality (160); - Clouds->setNbCloudToUpdateIn80ms (1); -} - -void releaseSky() -{ - Scene->deleteCloudScape(Clouds); -} - -// -- -- random note: update and render makes more sense than animate and update -void animateSky(double dt) -{ - Clouds->anim(dt); -} - -// this is actually render -void updateSky() -{ - CMatrix skyCameraMatrix; - skyCameraMatrix.identity(); - // - skyCameraMatrix= Camera.getMatrix(); - skyCameraMatrix.setPos(CVector::Null); - SkyCamera.setMatrix(skyCameraMatrix); - - SkyScene->animate(AnimationTime); - SkyScene->render(); - // Must clear ZBuffer For incoming rendering. - Driver->clearZBuffer(); - - Clouds->render(); -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "snowballs_client.h" +#include "entities.h" +#include "mouse_listener.h" +#include "pacs.h" + +// +// Namespaces +// + +using namespace std; +using namespace NLMISC; +using namespace NL3D; + +namespace SBCLIENT { + +// +// Variables +// + +// The camera for the whole scene +UCamera Camera = NULL; +// The collision entity use to snap the camera on the ground +UVisualCollisionEntity *CamCollisionEntity = NULL; + +// The particle system for the snowing effect +static UInstance Snow = NULL; + +// The sky 3D objects +static UScene *SkyScene = NULL; +static UCamera SkyCamera = NULL; +static UInstance Sky = NULL; + +static UCloudScape *Clouds = NULL; + +// +// Functions +// + +void initCamera() +{ + // Set up directly the camera + Camera = Scene->getCam(); + Camera.setTransformMode (UTransformable::DirectMatrix); + Camera.setPerspective ((float)Pi/2.f, 1.33f, 0.1f, 1000); + Camera.lookAt (CVector(ConfigFile->getVar("StartPoint").asFloat(0), + ConfigFile->getVar("StartPoint").asFloat(1), + ConfigFile->getVar("StartPoint").asFloat(2)), + CVectorD (0,0,0)); + + CamCollisionEntity = VisualCollisionManager->createEntity(); + CamCollisionEntity->setCeilMode(true); + + // Create the snowing particle system + Snow = Scene->createInstance("snow.ps"); + // And setup it + Snow.setTransformMode (UTransformable::DirectMatrix); + + // + // Setup the sky scene + // + + // -- -- not sure what the sky has to do with the camera + + SkyScene = Driver->createScene(false); + + SkyCamera = SkyScene->getCam (); + SkyCamera.setTransformMode (UTransformable::DirectMatrix); + // Set the very same frustum as the main camera + SkyCamera.setFrustum (Camera.getFrustum ()); + + Sky = SkyScene->createInstance("sky.shape"); + Sky.setTransformMode (UTransformable::DirectMatrix); + Sky.setMatrix(CMatrix::Identity); +} + +void releaseCamera() +{ + SkyScene->deleteInstance(Sky); + Driver->deleteScene(SkyScene); + Scene->deleteInstance(Snow); + VisualCollisionManager->deleteEntity(CamCollisionEntity); +} + +void updateCamera() +{ + // Set the new position of the snow emitter + CMatrix mat = CMatrix::Identity; + mat.setPos (Camera.getMatrix().getPos()/*+CVector (0.0f, 0.0f, -10.0f)*/); + Snow.setMatrix(mat); +} + +void initSky() +{ + // -- -- or what the clouds have to do with the sky + + SCloudScapeSetup css; + Clouds = Scene->createCloudScape (); + Clouds->init (&css); + Clouds->setQuality (160); + Clouds->setNbCloudToUpdateIn80ms (1); +} + +void releaseSky() +{ + Scene->deleteCloudScape(Clouds); +} + +// -- -- random note: update and render makes more sense than animate and update +void animateSky(double dt) +{ + Clouds->anim(dt); +} + +// this is actually render +void updateSky() +{ + CMatrix skyCameraMatrix; + skyCameraMatrix.identity(); + // + skyCameraMatrix= Camera.getMatrix(); + skyCameraMatrix.setPos(CVector::Null); + SkyCamera.setMatrix(skyCameraMatrix); + + SkyScene->animate(AnimationTime); + SkyScene->render(); + // Must clear ZBuffer For incoming rendering. + Driver->clearZBuffer(); + + Clouds->render(); +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/camera.h b/code/snowballs2/client/src/camera.h index 9779b43ce..c7718c653 100644 --- a/code/snowballs2/client/src/camera.h +++ b/code/snowballs2/client/src/camera.h @@ -1,69 +1,69 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef CAMERA_H -#define CAMERA_H - -// -// Includes -// - -#include - -// -// External definitions -// - -namespace NL3D -{ - class UVisualCollisionEntity; -}; - -namespace SBCLIENT { - -// -// External variables -// - -extern NL3D::UCamera Camera; -extern NL3D::UVisualCollisionEntity *CamCollisionEntity; - -// -// External functions -// - -void initCamera(); -void updateCamera(); -void releaseCamera(); - - -void initSky (); -void releaseSky(); - -// Update the sky for this frame, and render it. -// Must be called before ANY rendering -// this is actually render -void updateSky (); - -// this is update :x -void animateSky (double dt); - -} /* namespace SBCLIENT */ - - -#endif // CAMERA_H - -/* End of camera.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef CAMERA_H +#define CAMERA_H + +// +// Includes +// + +#include + +// +// External definitions +// + +namespace NL3D +{ + class UVisualCollisionEntity; +}; + +namespace SBCLIENT { + +// +// External variables +// + +extern NL3D::UCamera Camera; +extern NL3D::UVisualCollisionEntity *CamCollisionEntity; + +// +// External functions +// + +void initCamera(); +void updateCamera(); +void releaseCamera(); + + +void initSky (); +void releaseSky(); + +// Update the sky for this frame, and render it. +// Must be called before ANY rendering +// this is actually render +void updateSky (); + +// this is update :x +void animateSky (double dt); + +} /* namespace SBCLIENT */ + + +#endif // CAMERA_H + +/* End of camera.h */ diff --git a/code/snowballs2/client/src/commands.cpp b/code/snowballs2/client/src/commands.cpp index 69ce78d46..70dd3b247 100644 --- a/code/snowballs2/client/src/commands.cpp +++ b/code/snowballs2/client/src/commands.cpp @@ -1,375 +1,375 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "network.h" -#include "snowballs_client.h" -#include "interface.h" - -// -// Namespaces -// - -using namespace std; -using namespace NLMISC; -using namespace NL3D; - -namespace SBCLIENT { - -// -// Variables -// - -CLog CommandsLog; - -static list StoredLines; -static uint32 NbStoredLines = 100; - -// These variables are automatically set with the config file - -static float CommandsBoxX, CommandsBoxY, CommandsBoxWidth; -static float CommandsBoxBorder; -static int CommandsNbLines; -static float CommandsLineHeight; -static int CommandsFontSize; -static CRGBA CommandsBackColor, CommandsFrontColor; -static UMaterial CommandsMaterial = NULL; - -// -// Functions -// - -// Display a string to the commands interface -void addLine (const string &line) -{ - // Add the line - StoredLines.push_back (line); - - // Clear old lines if too much lines are stored - while (StoredLines.size () > NbStoredLines) - { - StoredLines.pop_front (); - } -} - -// Display used to display on the commands interface -class CCommandsDisplayer : public IDisplayer -{ - virtual void doDisplay (const CLog::TDisplayInfo &args, const char *message) - { - bool needSpace = false; - string str; - - if (args.LogType != CLog::LOG_NO) - { - str += logTypeToString(args.LogType); - needSpace = true; - } - - if (needSpace) { str += ": "; needSpace = false; } - str += message; - addLine (str); - } -}; - -// Instance of the displayer -static CCommandsDisplayer CommandsDisplayer; - -// Check if the user line is a command or not (a commands precede by a '/') -bool commandLine (const string &str) -{ - string command = ""; - - if (str[0]=='/') - { - // If it's a command call it - command = str.substr(1); - // add the string in to the chat - addLine (string ("command> ") + str); - ICommand::execute (command, CommandsLog); - return true; - } - else - { - return false; - } -} - -// Manage the user keyboard input -class CCommandsListener : public IEventListener -{ - virtual void operator() ( const CEvent& event ) - { - // If the interface is open, ignore keys for the command interface - if (interfaceOpen ()) return; - - // Get the key - CEventChar &ec = (CEventChar&)event; - - switch ( ec.Char ) - { - case 13 : // RETURN : Send the chat message - - // If the line is empty, do nothing - if ( _Line.size() == 0 ) break; - - // If it's a command, execute it and don't send the command to the network - if ( ! commandLine( _Line ) ) - { - // If online, send the chat line, otherwise, locally displays it - if (isOnline ()) - sendChatLine (_Line); - else - addLine (string ("you said> ") + _Line); - } - // Reset the command line - _LastCommand = _Line; - _Line = ""; - _MaxWidthReached = false; - break; - - case 8 : // BACKSPACE : remove the last character - - if ( _Line.size() != 0 ) - { - _Line.erase( _Line.end()-1 ); - } - break; - - case 9 : // TAB : If it's a command, try to auto complete it - - if (_Line.empty()) - { - _Line = _LastCommand; - } - else if (!_Line.empty() && _Line[0] == '/') - { - string command = _Line.substr(1); - ICommand::expand(command); - _Line = '/' + command; - } - break; - - case 27 : // ESCAPE : clear the command - - _Line = ""; - _MaxWidthReached = false; - break; - - default: // OTHERWISE : add the character to the line - - if (! _MaxWidthReached) - { - _Line += (char)ec.Char; - } - } - } - -public: - CCommandsListener() : _MaxWidthReached( false ) - {} - - const string& line() const - { - return _Line; - } - - void setMaxWidthReached( bool b ) - { - _MaxWidthReached = b; - } - -private: - string _Line; - bool _MaxWidthReached; - string _LastCommand; -}; - -// Instance of the listener -static CCommandsListener CommandsListener; - -// This functions is automatically called when the config file changed (dynamically) -void cbUpdateCommands (CConfigFile::CVar &var) -{ - if (var.Name == "CommandsBoxX") CommandsBoxX = var.asFloat (); - else if (var.Name == "CommandsBoxY") CommandsBoxY = var.asFloat (); - else if (var.Name == "CommandsBoxWidth") CommandsBoxWidth = var.asFloat (); - else if (var.Name == "CommandsBoxBorder") CommandsBoxBorder = var.asFloat (); - else if (var.Name == "CommandsNbLines") CommandsNbLines = var.asInt (); - else if (var.Name == "CommandsLineHeight") CommandsLineHeight = var.asFloat (); - else if (var.Name == "CommandsBackColor") CommandsBackColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); - else if (var.Name == "CommandsFrontColor") CommandsFrontColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); - else if (var.Name == "CommandsFontSize") CommandsFontSize = var.asInt (); - else nlwarning ("Unknown variable update %s", var.Name.c_str()); -} - -void initCommands() -{ - // Add the keyboard listener in the event server - Driver->EventServer.addListener (EventCharId, &CommandsListener); - - // Add the command displayer to the standard log (to display NeL info) - CommandsLog.addDisplayer (&CommandsDisplayer); -#ifndef NL_RELEASE - DebugLog->addDisplayer (&CommandsDisplayer); - InfoLog->addDisplayer (&CommandsDisplayer); - WarningLog->addDisplayer (&CommandsDisplayer); - AssertLog->addDisplayer (&CommandsDisplayer); - ErrorLog->addDisplayer (&CommandsDisplayer); -#endif - - // Add callback for the config file - ConfigFile->setCallback ("CommandsBoxX", cbUpdateCommands); - ConfigFile->setCallback ("CommandsBoxY", cbUpdateCommands); - ConfigFile->setCallback ("CommandsBoxWidth", cbUpdateCommands); - ConfigFile->setCallback ("CommandsBoxBorder", cbUpdateCommands); - ConfigFile->setCallback ("CommandsNbLines", cbUpdateCommands); - ConfigFile->setCallback ("CommandsLineHeight", cbUpdateCommands); - ConfigFile->setCallback ("CommandsBackColor", cbUpdateCommands); - ConfigFile->setCallback ("CommandsFrontColor", cbUpdateCommands); - ConfigFile->setCallback ("CommandsFontSize", cbUpdateCommands); - - // Init the config file variable - cbUpdateCommands (ConfigFile->getVar ("CommandsBoxX")); - cbUpdateCommands (ConfigFile->getVar ("CommandsBoxY")); - cbUpdateCommands (ConfigFile->getVar ("CommandsBoxWidth")); - cbUpdateCommands (ConfigFile->getVar ("CommandsBoxBorder")); - cbUpdateCommands (ConfigFile->getVar ("CommandsNbLines")); - cbUpdateCommands (ConfigFile->getVar ("CommandsLineHeight")); - cbUpdateCommands (ConfigFile->getVar ("CommandsBackColor")); - cbUpdateCommands (ConfigFile->getVar ("CommandsFrontColor")); - cbUpdateCommands (ConfigFile->getVar ("CommandsFontSize")); - - CommandsMaterial = Driver->createMaterial(); - CommandsMaterial.initUnlit(); - CommandsMaterial.setBlendFunc(UMaterial::srcalpha, UMaterial::invsrcalpha); - CommandsMaterial.setBlend(true); -} - -void updateCommands() -{ - // Snap to pixels (kind of ugly code, but looks better ingame) - uint32 _width, _height; - Driver->getWindowSize(_width, _height); - float width = (float)_width, height = (float)_height; - float CommandsLineHeight = CommandsFontSize / height; - float CommandsBoxX = ((float)(sint32)(SBCLIENT::CommandsBoxX * width)) / width; - float CommandsBoxWidth = ((float)(sint32)(SBCLIENT::CommandsBoxWidth * width)) / width; - float CommandsBoxY = ((float)(sint32)(SBCLIENT::CommandsBoxY * height)) / height; - float CommandsBoxHeight = ((float)(sint32)((CommandsNbLines + 1) * CommandsLineHeight * width)) / width; - float CommandsBoxBorderX = ((float)(sint32)(SBCLIENT::CommandsBoxBorder * width)) / width; - float CommandsBoxBorderY = ((float)(sint32)(SBCLIENT::CommandsBoxBorder * height)) / height; - - // Display the background - Driver->setMatrixMode2D11 (); - CommandsMaterial.setColor(CommandsBackColor); - float x0 = CommandsBoxX - CommandsBoxBorderX; - float y0 = CommandsBoxY - CommandsBoxBorderY; - float x1 = CommandsBoxX + CommandsBoxWidth + CommandsBoxBorderX; - float y1 = CommandsBoxY + CommandsBoxHeight + CommandsBoxBorderY; - Driver->drawQuad(CQuad(CVector(x0, y0, 0), CVector(x1, y0, 0), CVector(x1, y1, 0), CVector(x0, y1, 0)), CommandsMaterial); - - // Set the text context - TextContext->setHotSpot (UTextContext::BottomLeft); - TextContext->setColor (CommandsFrontColor); - TextContext->setFontSize (CommandsFontSize); - - // Display the user input line - ucstring line = ucstring("> ") + ucstring(CommandsListener.line()) + ucstring("_"); - uint32 csi = TextContext->textPush(line); - float sw = TextContext->getStringInfo(csi).StringWidth / width; // make sure newly typed text is visible - TextContext->printAt(sw > CommandsBoxWidth ? CommandsBoxX - sw + CommandsBoxWidth : CommandsBoxX, CommandsBoxY, csi); - TextContext->erase(csi); - - // Display stored lines - float yPos = CommandsBoxY; - list::reverse_iterator rit = StoredLines.rbegin(); - for (sint32 i = 0; i < CommandsNbLines; ++i) - { - yPos += CommandsLineHeight; - if (rit == StoredLines.rend()) break; - TextContext->printfAt(CommandsBoxX, yPos, (*rit).c_str()); - rit++; - } -} - -void clearCommands () -{ - StoredLines.clear (); -} - -void releaseCommands() -{ - // Remove the displayers - CommandsLog.removeDisplayer(&CommandsDisplayer); -#ifndef NL_RELEASE - DebugLog->removeDisplayer(&CommandsDisplayer); - InfoLog->removeDisplayer(&CommandsDisplayer); - WarningLog->removeDisplayer(&CommandsDisplayer); - AssertLog->removeDisplayer(&CommandsDisplayer); - ErrorLog->removeDisplayer(&CommandsDisplayer); -#endif - - // Remove callbacks for the config file - ConfigFile->setCallback("CommandsBoxX", NULL); - ConfigFile->setCallback("CommandsBoxY", NULL); - ConfigFile->setCallback("CommandsBoxWidth", NULL); - ConfigFile->setCallback("CommandsBoxBorder", NULL); - ConfigFile->setCallback("CommandsNbLines", NULL); - ConfigFile->setCallback("CommandsLineHeight", NULL); - ConfigFile->setCallback("CommandsBackColor", NULL); - ConfigFile->setCallback("CommandsFrontColor", NULL); - ConfigFile->setCallback("CommandsFontSize", NULL); - - // Remove the keyboard listener from the server - Driver->EventServer.removeListener(EventCharId, &CommandsListener); - - // Remove the material - Driver->deleteMaterial(CommandsMaterial); -} - -NLMISC_COMMAND(clear,"clear the chat history","") -{ - // check args, if there s not the right number of parameter, return bad - if(args.size() != 0) return false; - clearCommands (); - return true; -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "network.h" +#include "snowballs_client.h" +#include "interface.h" + +// +// Namespaces +// + +using namespace std; +using namespace NLMISC; +using namespace NL3D; + +namespace SBCLIENT { + +// +// Variables +// + +CLog CommandsLog; + +static list StoredLines; +static uint32 NbStoredLines = 100; + +// These variables are automatically set with the config file + +static float CommandsBoxX, CommandsBoxY, CommandsBoxWidth; +static float CommandsBoxBorder; +static int CommandsNbLines; +static float CommandsLineHeight; +static int CommandsFontSize; +static CRGBA CommandsBackColor, CommandsFrontColor; +static UMaterial CommandsMaterial = NULL; + +// +// Functions +// + +// Display a string to the commands interface +void addLine (const string &line) +{ + // Add the line + StoredLines.push_back (line); + + // Clear old lines if too much lines are stored + while (StoredLines.size () > NbStoredLines) + { + StoredLines.pop_front (); + } +} + +// Display used to display on the commands interface +class CCommandsDisplayer : public IDisplayer +{ + virtual void doDisplay (const CLog::TDisplayInfo &args, const char *message) + { + bool needSpace = false; + string str; + + if (args.LogType != CLog::LOG_NO) + { + str += logTypeToString(args.LogType); + needSpace = true; + } + + if (needSpace) { str += ": "; needSpace = false; } + str += message; + addLine (str); + } +}; + +// Instance of the displayer +static CCommandsDisplayer CommandsDisplayer; + +// Check if the user line is a command or not (a commands precede by a '/') +bool commandLine (const string &str) +{ + string command = ""; + + if (str[0]=='/') + { + // If it's a command call it + command = str.substr(1); + // add the string in to the chat + addLine (string ("command> ") + str); + ICommand::execute (command, CommandsLog); + return true; + } + else + { + return false; + } +} + +// Manage the user keyboard input +class CCommandsListener : public IEventListener +{ + virtual void operator() ( const CEvent& event ) + { + // If the interface is open, ignore keys for the command interface + if (interfaceOpen ()) return; + + // Get the key + CEventChar &ec = (CEventChar&)event; + + switch ( ec.Char ) + { + case 13 : // RETURN : Send the chat message + + // If the line is empty, do nothing + if ( _Line.size() == 0 ) break; + + // If it's a command, execute it and don't send the command to the network + if ( ! commandLine( _Line ) ) + { + // If online, send the chat line, otherwise, locally displays it + if (isOnline ()) + sendChatLine (_Line); + else + addLine (string ("you said> ") + _Line); + } + // Reset the command line + _LastCommand = _Line; + _Line = ""; + _MaxWidthReached = false; + break; + + case 8 : // BACKSPACE : remove the last character + + if ( _Line.size() != 0 ) + { + _Line.erase( _Line.end()-1 ); + } + break; + + case 9 : // TAB : If it's a command, try to auto complete it + + if (_Line.empty()) + { + _Line = _LastCommand; + } + else if (!_Line.empty() && _Line[0] == '/') + { + string command = _Line.substr(1); + ICommand::expand(command); + _Line = '/' + command; + } + break; + + case 27 : // ESCAPE : clear the command + + _Line = ""; + _MaxWidthReached = false; + break; + + default: // OTHERWISE : add the character to the line + + if (! _MaxWidthReached) + { + _Line += (char)ec.Char; + } + } + } + +public: + CCommandsListener() : _MaxWidthReached( false ) + {} + + const string& line() const + { + return _Line; + } + + void setMaxWidthReached( bool b ) + { + _MaxWidthReached = b; + } + +private: + string _Line; + bool _MaxWidthReached; + string _LastCommand; +}; + +// Instance of the listener +static CCommandsListener CommandsListener; + +// This functions is automatically called when the config file changed (dynamically) +void cbUpdateCommands (CConfigFile::CVar &var) +{ + if (var.Name == "CommandsBoxX") CommandsBoxX = var.asFloat (); + else if (var.Name == "CommandsBoxY") CommandsBoxY = var.asFloat (); + else if (var.Name == "CommandsBoxWidth") CommandsBoxWidth = var.asFloat (); + else if (var.Name == "CommandsBoxBorder") CommandsBoxBorder = var.asFloat (); + else if (var.Name == "CommandsNbLines") CommandsNbLines = var.asInt (); + else if (var.Name == "CommandsLineHeight") CommandsLineHeight = var.asFloat (); + else if (var.Name == "CommandsBackColor") CommandsBackColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); + else if (var.Name == "CommandsFrontColor") CommandsFrontColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); + else if (var.Name == "CommandsFontSize") CommandsFontSize = var.asInt (); + else nlwarning ("Unknown variable update %s", var.Name.c_str()); +} + +void initCommands() +{ + // Add the keyboard listener in the event server + Driver->EventServer.addListener (EventCharId, &CommandsListener); + + // Add the command displayer to the standard log (to display NeL info) + CommandsLog.addDisplayer (&CommandsDisplayer); +#ifndef NL_RELEASE + DebugLog->addDisplayer (&CommandsDisplayer); + InfoLog->addDisplayer (&CommandsDisplayer); + WarningLog->addDisplayer (&CommandsDisplayer); + AssertLog->addDisplayer (&CommandsDisplayer); + ErrorLog->addDisplayer (&CommandsDisplayer); +#endif + + // Add callback for the config file + ConfigFile->setCallback ("CommandsBoxX", cbUpdateCommands); + ConfigFile->setCallback ("CommandsBoxY", cbUpdateCommands); + ConfigFile->setCallback ("CommandsBoxWidth", cbUpdateCommands); + ConfigFile->setCallback ("CommandsBoxBorder", cbUpdateCommands); + ConfigFile->setCallback ("CommandsNbLines", cbUpdateCommands); + ConfigFile->setCallback ("CommandsLineHeight", cbUpdateCommands); + ConfigFile->setCallback ("CommandsBackColor", cbUpdateCommands); + ConfigFile->setCallback ("CommandsFrontColor", cbUpdateCommands); + ConfigFile->setCallback ("CommandsFontSize", cbUpdateCommands); + + // Init the config file variable + cbUpdateCommands (ConfigFile->getVar ("CommandsBoxX")); + cbUpdateCommands (ConfigFile->getVar ("CommandsBoxY")); + cbUpdateCommands (ConfigFile->getVar ("CommandsBoxWidth")); + cbUpdateCommands (ConfigFile->getVar ("CommandsBoxBorder")); + cbUpdateCommands (ConfigFile->getVar ("CommandsNbLines")); + cbUpdateCommands (ConfigFile->getVar ("CommandsLineHeight")); + cbUpdateCommands (ConfigFile->getVar ("CommandsBackColor")); + cbUpdateCommands (ConfigFile->getVar ("CommandsFrontColor")); + cbUpdateCommands (ConfigFile->getVar ("CommandsFontSize")); + + CommandsMaterial = Driver->createMaterial(); + CommandsMaterial.initUnlit(); + CommandsMaterial.setBlendFunc(UMaterial::srcalpha, UMaterial::invsrcalpha); + CommandsMaterial.setBlend(true); +} + +void updateCommands() +{ + // Snap to pixels (kind of ugly code, but looks better ingame) + uint32 _width, _height; + Driver->getWindowSize(_width, _height); + float width = (float)_width, height = (float)_height; + float CommandsLineHeight = CommandsFontSize / height; + float CommandsBoxX = ((float)(sint32)(SBCLIENT::CommandsBoxX * width)) / width; + float CommandsBoxWidth = ((float)(sint32)(SBCLIENT::CommandsBoxWidth * width)) / width; + float CommandsBoxY = ((float)(sint32)(SBCLIENT::CommandsBoxY * height)) / height; + float CommandsBoxHeight = ((float)(sint32)((CommandsNbLines + 1) * CommandsLineHeight * width)) / width; + float CommandsBoxBorderX = ((float)(sint32)(SBCLIENT::CommandsBoxBorder * width)) / width; + float CommandsBoxBorderY = ((float)(sint32)(SBCLIENT::CommandsBoxBorder * height)) / height; + + // Display the background + Driver->setMatrixMode2D11 (); + CommandsMaterial.setColor(CommandsBackColor); + float x0 = CommandsBoxX - CommandsBoxBorderX; + float y0 = CommandsBoxY - CommandsBoxBorderY; + float x1 = CommandsBoxX + CommandsBoxWidth + CommandsBoxBorderX; + float y1 = CommandsBoxY + CommandsBoxHeight + CommandsBoxBorderY; + Driver->drawQuad(CQuad(CVector(x0, y0, 0), CVector(x1, y0, 0), CVector(x1, y1, 0), CVector(x0, y1, 0)), CommandsMaterial); + + // Set the text context + TextContext->setHotSpot (UTextContext::BottomLeft); + TextContext->setColor (CommandsFrontColor); + TextContext->setFontSize (CommandsFontSize); + + // Display the user input line + ucstring line = ucstring("> ") + ucstring(CommandsListener.line()) + ucstring("_"); + uint32 csi = TextContext->textPush(line); + float sw = TextContext->getStringInfo(csi).StringWidth / width; // make sure newly typed text is visible + TextContext->printAt(sw > CommandsBoxWidth ? CommandsBoxX - sw + CommandsBoxWidth : CommandsBoxX, CommandsBoxY, csi); + TextContext->erase(csi); + + // Display stored lines + float yPos = CommandsBoxY; + list::reverse_iterator rit = StoredLines.rbegin(); + for (sint32 i = 0; i < CommandsNbLines; ++i) + { + yPos += CommandsLineHeight; + if (rit == StoredLines.rend()) break; + TextContext->printfAt(CommandsBoxX, yPos, (*rit).c_str()); + rit++; + } +} + +void clearCommands () +{ + StoredLines.clear (); +} + +void releaseCommands() +{ + // Remove the displayers + CommandsLog.removeDisplayer(&CommandsDisplayer); +#ifndef NL_RELEASE + DebugLog->removeDisplayer(&CommandsDisplayer); + InfoLog->removeDisplayer(&CommandsDisplayer); + WarningLog->removeDisplayer(&CommandsDisplayer); + AssertLog->removeDisplayer(&CommandsDisplayer); + ErrorLog->removeDisplayer(&CommandsDisplayer); +#endif + + // Remove callbacks for the config file + ConfigFile->setCallback("CommandsBoxX", NULL); + ConfigFile->setCallback("CommandsBoxY", NULL); + ConfigFile->setCallback("CommandsBoxWidth", NULL); + ConfigFile->setCallback("CommandsBoxBorder", NULL); + ConfigFile->setCallback("CommandsNbLines", NULL); + ConfigFile->setCallback("CommandsLineHeight", NULL); + ConfigFile->setCallback("CommandsBackColor", NULL); + ConfigFile->setCallback("CommandsFrontColor", NULL); + ConfigFile->setCallback("CommandsFontSize", NULL); + + // Remove the keyboard listener from the server + Driver->EventServer.removeListener(EventCharId, &CommandsListener); + + // Remove the material + Driver->deleteMaterial(CommandsMaterial); +} + +NLMISC_COMMAND(clear,"clear the chat history","") +{ + // check args, if there s not the right number of parameter, return bad + if(args.size() != 0) return false; + clearCommands (); + return true; +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/commands.h b/code/snowballs2/client/src/commands.h index 1255c3c21..4b1f06134 100644 --- a/code/snowballs2/client/src/commands.h +++ b/code/snowballs2/client/src/commands.h @@ -1,51 +1,51 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef COMMANDS_H -#define COMMANDS_H - -// -// Includes -// - -#include - -#include - -namespace SBCLIENT { - -// -// External variables -// - -extern NLMISC::CLog CommandsLog; - -// -// External functions -// - -void initCommands (); -void updateCommands (); -void releaseCommands (); - -void clearCommands (); -void addLine (const std::string &line); - -} /* namespace SBCLIENT */ - -#endif // COMMANDS_H - -/* End of commands.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef COMMANDS_H +#define COMMANDS_H + +// +// Includes +// + +#include + +#include + +namespace SBCLIENT { + +// +// External variables +// + +extern NLMISC::CLog CommandsLog; + +// +// External functions +// + +void initCommands (); +void updateCommands (); +void releaseCommands (); + +void clearCommands (); +void addLine (const std::string &line); + +} /* namespace SBCLIENT */ + +#endif // COMMANDS_H + +/* End of commands.h */ diff --git a/code/snowballs2/client/src/compass.cpp b/code/snowballs2/client/src/compass.cpp index 02d5886a4..11d7ddefa 100644 --- a/code/snowballs2/client/src/compass.cpp +++ b/code/snowballs2/client/src/compass.cpp @@ -1,180 +1,180 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "mouse_listener.h" -#include "camera.h" -#include "snowballs_client.h" -#include "entities.h" - -// -// Namespaces -// - -using namespace NLMISC; -using namespace NL3D; -using namespace std; - -namespace SBCLIENT { - -// -// Variables -// - -static NL3D::UMaterial CompassMaterial = NULL; - -// These variables are automatically set with the config file - -static float CompassPosX, CompassPosY, CompassRadius; -static CRGBA CompassColor; - -// -// Functions -// - -void cbUpdateCompass (CConfigFile::CVar &var) -{ - if (var.Name == "CompassPosX") CompassPosX = var.asFloat (); - else if (var.Name == "CompassPosY") CompassPosY = var.asFloat (); - else if (var.Name == "CompassRadius") CompassRadius = var.asFloat (); - else if (var.Name == "CompassColor") - { - CompassColor.set(var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); - CompassMaterial.setColor(CompassColor); - } - else nlwarning ("Unknown variable update %s", var.Name.c_str()); -} - -void initCompass () -{ - CompassMaterial = Driver->createMaterial (); - CompassMaterial.initUnlit (); - CompassMaterial.setBlendFunc (UMaterial::srcalpha, UMaterial::invsrcalpha); - CompassMaterial.setBlend(true); - - ConfigFile->setCallback ("CompassPosX", cbUpdateCompass); - ConfigFile->setCallback ("CompassPosY", cbUpdateCompass); - ConfigFile->setCallback ("CompassRadius", cbUpdateCompass); - ConfigFile->setCallback ("CompassColor", cbUpdateCompass); - - cbUpdateCompass (ConfigFile->getVar ("CompassPosX")); - cbUpdateCompass (ConfigFile->getVar ("CompassPosY")); - cbUpdateCompass (ConfigFile->getVar ("CompassRadius")); - cbUpdateCompass (ConfigFile->getVar ("CompassColor")); -} - -void updateCompass () -{ - float x = CompassPosX; - float y = CompassPosY; - float radius = CompassRadius; - - // tri - CTriangle tri; - tri.V0.set (-radius, 0, 0); - tri.V1.set (radius, 0, 0); - tri.V2.set (0, 3*radius, 0); - - CQuad quad; - // quad - quad.V0.set (-radius, -radius, 0); - quad.V1.set ( radius, -radius, 0); - quad.V2.set ( radius, radius, 0); - quad.V3.set (-radius, radius, 0); - - Driver->setMatrixMode2D43 (); - - CMatrix mtx; - - // up - mtx.identity(); - mtx.translate(CVector(x,y,0)); - mtx.rotateZ(MouseListener->getOrientation() - (float)Pi/2); - mtx.translate(CVector(0,radius,0)); - Driver->setModelMatrix (mtx); - Driver->drawTriangle (tri, CompassMaterial); - - // down - mtx.identity(); - mtx.translate(CVector(x,y,0)); - mtx.rotateZ(MouseListener->getOrientation() + (float)Pi/2); - mtx.translate(CVector(0,radius,0)); - Driver->setModelMatrix (mtx); - Driver->drawTriangle (tri, CompassMaterial); - - // left - mtx.identity(); - mtx.translate(CVector(x,y,0)); - mtx.rotateZ(MouseListener->getOrientation()); - mtx.translate(CVector(0,radius,0)); - Driver->setModelMatrix (mtx); - Driver->drawTriangle (tri, CompassMaterial); - - // right - mtx.identity(); - mtx.translate(CVector(x,y,0)); - mtx.rotateZ(MouseListener->getOrientation() - (float)Pi); - mtx.translate(CVector(0,radius,0)); - Driver->setModelMatrix (mtx); - Driver->drawTriangle (tri, CompassMaterial); - - // center - mtx.identity(); - mtx.translate(CVector(x,y,0)); - mtx.rotateZ(MouseListener->getOrientation()); - Driver->setModelMatrix (mtx); - Driver->drawQuad (quad, CompassMaterial); - - x *= 3.0/4.0f; - - // Print position - TextContext->setHotSpot(UTextContext::MiddleTop); - TextContext->setColor(CompassColor); - TextContext->setFontSize(14); - if (Self != NULL) - TextContext->printfAt(x, y-4.0f*radius, "%.2f %.2f %.2f", Self->Position.x, Self->Position.y, Self->Position.z); - else - TextContext->printfAt(x, y-4.0f*radius, "%.2f %.2f %.2f", MouseListener->getPosition().x, MouseListener->getPosition().y, MouseListener->getPosition().z); -} - -void releaseCompass () -{ - ConfigFile->setCallback("CompassPosX", NULL); - ConfigFile->setCallback("CompassPosY", NULL); - ConfigFile->setCallback("CompassRadius", NULL); - ConfigFile->setCallback("CompassColor", NULL); - - Driver->deleteMaterial (CompassMaterial); - CompassMaterial = NULL; -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "mouse_listener.h" +#include "camera.h" +#include "snowballs_client.h" +#include "entities.h" + +// +// Namespaces +// + +using namespace NLMISC; +using namespace NL3D; +using namespace std; + +namespace SBCLIENT { + +// +// Variables +// + +static NL3D::UMaterial CompassMaterial = NULL; + +// These variables are automatically set with the config file + +static float CompassPosX, CompassPosY, CompassRadius; +static CRGBA CompassColor; + +// +// Functions +// + +void cbUpdateCompass (CConfigFile::CVar &var) +{ + if (var.Name == "CompassPosX") CompassPosX = var.asFloat (); + else if (var.Name == "CompassPosY") CompassPosY = var.asFloat (); + else if (var.Name == "CompassRadius") CompassRadius = var.asFloat (); + else if (var.Name == "CompassColor") + { + CompassColor.set(var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); + CompassMaterial.setColor(CompassColor); + } + else nlwarning ("Unknown variable update %s", var.Name.c_str()); +} + +void initCompass () +{ + CompassMaterial = Driver->createMaterial (); + CompassMaterial.initUnlit (); + CompassMaterial.setBlendFunc (UMaterial::srcalpha, UMaterial::invsrcalpha); + CompassMaterial.setBlend(true); + + ConfigFile->setCallback ("CompassPosX", cbUpdateCompass); + ConfigFile->setCallback ("CompassPosY", cbUpdateCompass); + ConfigFile->setCallback ("CompassRadius", cbUpdateCompass); + ConfigFile->setCallback ("CompassColor", cbUpdateCompass); + + cbUpdateCompass (ConfigFile->getVar ("CompassPosX")); + cbUpdateCompass (ConfigFile->getVar ("CompassPosY")); + cbUpdateCompass (ConfigFile->getVar ("CompassRadius")); + cbUpdateCompass (ConfigFile->getVar ("CompassColor")); +} + +void updateCompass () +{ + float x = CompassPosX; + float y = CompassPosY; + float radius = CompassRadius; + + // tri + CTriangle tri; + tri.V0.set (-radius, 0, 0); + tri.V1.set (radius, 0, 0); + tri.V2.set (0, 3*radius, 0); + + CQuad quad; + // quad + quad.V0.set (-radius, -radius, 0); + quad.V1.set ( radius, -radius, 0); + quad.V2.set ( radius, radius, 0); + quad.V3.set (-radius, radius, 0); + + Driver->setMatrixMode2D43 (); + + CMatrix mtx; + + // up + mtx.identity(); + mtx.translate(CVector(x,y,0)); + mtx.rotateZ(MouseListener->getOrientation() - (float)Pi/2); + mtx.translate(CVector(0,radius,0)); + Driver->setModelMatrix (mtx); + Driver->drawTriangle (tri, CompassMaterial); + + // down + mtx.identity(); + mtx.translate(CVector(x,y,0)); + mtx.rotateZ(MouseListener->getOrientation() + (float)Pi/2); + mtx.translate(CVector(0,radius,0)); + Driver->setModelMatrix (mtx); + Driver->drawTriangle (tri, CompassMaterial); + + // left + mtx.identity(); + mtx.translate(CVector(x,y,0)); + mtx.rotateZ(MouseListener->getOrientation()); + mtx.translate(CVector(0,radius,0)); + Driver->setModelMatrix (mtx); + Driver->drawTriangle (tri, CompassMaterial); + + // right + mtx.identity(); + mtx.translate(CVector(x,y,0)); + mtx.rotateZ(MouseListener->getOrientation() - (float)Pi); + mtx.translate(CVector(0,radius,0)); + Driver->setModelMatrix (mtx); + Driver->drawTriangle (tri, CompassMaterial); + + // center + mtx.identity(); + mtx.translate(CVector(x,y,0)); + mtx.rotateZ(MouseListener->getOrientation()); + Driver->setModelMatrix (mtx); + Driver->drawQuad (quad, CompassMaterial); + + x *= 3.0/4.0f; + + // Print position + TextContext->setHotSpot(UTextContext::MiddleTop); + TextContext->setColor(CompassColor); + TextContext->setFontSize(14); + if (Self != NULL) + TextContext->printfAt(x, y-4.0f*radius, "%.2f %.2f %.2f", Self->Position.x, Self->Position.y, Self->Position.z); + else + TextContext->printfAt(x, y-4.0f*radius, "%.2f %.2f %.2f", MouseListener->getPosition().x, MouseListener->getPosition().y, MouseListener->getPosition().z); +} + +void releaseCompass () +{ + ConfigFile->setCallback("CompassPosX", NULL); + ConfigFile->setCallback("CompassPosY", NULL); + ConfigFile->setCallback("CompassRadius", NULL); + ConfigFile->setCallback("CompassColor", NULL); + + Driver->deleteMaterial (CompassMaterial); + CompassMaterial = NULL; +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/compass.h b/code/snowballs2/client/src/compass.h index 779f1faa7..a08aa1e28 100644 --- a/code/snowballs2/client/src/compass.h +++ b/code/snowballs2/client/src/compass.h @@ -1,34 +1,34 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef COMPASS_H -#define COMPASS_H - -namespace SBCLIENT { - -// -// External functions -// - -void initCompass (); -void updateCompass (); -void releaseCompass (); - -} /* namespace SBCLIENT */ - -#endif // COMPASS_H - -/* End of compass.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef COMPASS_H +#define COMPASS_H + +namespace SBCLIENT { + +// +// External functions +// + +void initCompass (); +void updateCompass (); +void releaseCompass (); + +} /* namespace SBCLIENT */ + +#endif // COMPASS_H + +/* End of compass.h */ diff --git a/code/snowballs2/client/src/configuration.cpp b/code/snowballs2/client/src/configuration.cpp index 24e6aa12c..303db63ce 100644 --- a/code/snowballs2/client/src/configuration.cpp +++ b/code/snowballs2/client/src/configuration.cpp @@ -1,178 +1,178 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include -#include "configuration.h" - -// STL includes - -// NeL includes -// #include -#include -#include -#include - -// Project includes -#include "snowballs_client.h" -#include "snowballs_config.h" - -using namespace std; -using namespace NLMISC; - -namespace SBCLIENT { - -void CConfiguration::setAndCallback(const std::string &varName, void (*cb)(CConfigFile::CVar &var)) -{ - ConfigFile->setCallback(varName, cb); - cb(*ConfigFile->getVarPtr(varName)); -} - -void CConfiguration::dropCallback(const std::string &varName) -{ - ConfigFile->setCallback(varName, NULL); -} - -bool CConfiguration::init() -{ - nlassert(!ConfigFile); ConfigFile = new CConfigFile(); nlassert(ConfigFile); - ConfigFile->load(SBCLIENT_CONFIG_FILE); - - // set the search paths (kinda important) - CConfigFile::CVar *var; - var = ConfigFile->getVarPtr("SearchPaths"); - uint varsize = var->size(); - for (uint i = 0; i < varsize; ++i) - CPath::addSearchPath(var->asString(i), true, false); - var = ConfigFile->getVarPtr("RemapExtensions"); - varsize = var->size(); - for (uint i = 0; i < varsize; i += 2) - CPath::remapExtension(var->asString(i), var->asString(i + 1), true); - - return true; -} - -bool CConfiguration::release() -{ - // save and release the config file - if (ConfigFile) - { - if (ConfigFile->exists("SaveConfig") && ConfigFile->getVarPtr("SaveConfig")->asBool()) - { - ConfigFile->save(); - } - delete ConfigFile; - ConfigFile = NULL; - } - else nlwarning("!ConfigFile"); - - // release the search paths etc - CPath::releaseInstance(); - - return true; -} - -void CConfiguration::updateUtilities() -{ - CConfigFile::checkConfigFiles(); -} - -float CConfiguration::getValue(const string &varName, float defaultValue) -{ - if (ConfigFile->exists(varName)) return ConfigFile->getVar(varName).asFloat(); - CConfigFile::CVar varToCopy; - varToCopy.forceAsDouble((double)defaultValue); - ConfigFile->insertVar(varName, varToCopy); - return defaultValue; -} - -double CConfiguration::getValue(const string &varName, double defaultValue) -{ - if (ConfigFile->exists(varName)) return ConfigFile->getVar(varName).asDouble(); - CConfigFile::CVar varToCopy; - varToCopy.forceAsDouble(defaultValue); - ConfigFile->insertVar(varName, varToCopy); - return defaultValue; -} - -int CConfiguration::getValue(const string &varName, int defaultValue) -{ - if (ConfigFile->exists(varName)) return ConfigFile->getVar(varName).asInt(); - CConfigFile::CVar varToCopy; - varToCopy.forceAsInt(defaultValue); - ConfigFile->insertVar(varName, varToCopy); - return defaultValue; -} - -string CConfiguration::getValue(const string &varName, const string &defaultValue) -{ - if (ConfigFile->exists(varName)) return ConfigFile->getVar(varName).asString(); - CConfigFile::CVar varToCopy; - varToCopy.forceAsString(defaultValue); - ConfigFile->insertVar(varName, varToCopy); - return defaultValue; -} - -ucstring CConfiguration::getValue(const string &varName, const ucstring &defaultValue) -{ - if (ConfigFile->exists(varName)) return ucstring::makeFromUtf8(ConfigFile->getVar(varName).asString()); - CConfigFile::CVar varToCopy; - varToCopy.forceAsString(defaultValue.toUtf8()); - ConfigFile->insertVar(varName, varToCopy); - return defaultValue; -} - -bool CConfiguration::getValue(const string &varName, bool defaultValue) -{ - if (ConfigFile->exists(varName)) return ConfigFile->getVar(varName).asBool(); - CConfigFile::CVar varToCopy; - varToCopy.forceAsInt(defaultValue ? 1 : 0); - ConfigFile->insertVar(varName, varToCopy); - return defaultValue; -} - -CRGBA CConfiguration::getValue(const string &varName, const CRGBA &defaultValue) -{ - if (ConfigFile->exists(varName)) - { - return getValue(ConfigFile->getVar(varName), defaultValue); - } - else - { - // create a new value only if one doesn't exist - CConfigFile::CVar varToCopy; - varToCopy.forceAsInt(defaultValue.R); - varToCopy.setAsInt(defaultValue.G, 1); - varToCopy.setAsInt(defaultValue.B, 2); - varToCopy.setAsInt(defaultValue.A, 3); - ConfigFile->insertVar(varName, varToCopy); - } - return defaultValue; -} - -CRGBA CConfiguration::getValue(const CConfigFile::CVar &var, const CRGBA &defaultValue) -{ - if (var.size() >= 3) - { - if (var.size() > 4) nlwarning("RGBA value in config value '%s' is too long, ignoring unused values"); - return CRGBA(var.asInt(0), var.asInt(1), var.asInt(2), var.size() >= 4 ? var.asInt(3) : 255); - } - nlwarning("Invalid RGBA value in config value '%s', reverting to default { %i, %i, %i, %i }", var.Name.c_str(), (sint)defaultValue.R, (sint)defaultValue.G, (sint)defaultValue.B, (sint)defaultValue.A); - return defaultValue; -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include "configuration.h" + +// STL includes + +// NeL includes +// #include +#include +#include +#include + +// Project includes +#include "snowballs_client.h" +#include "snowballs_config.h" + +using namespace std; +using namespace NLMISC; + +namespace SBCLIENT { + +void CConfiguration::setAndCallback(const std::string &varName, void (*cb)(CConfigFile::CVar &var)) +{ + ConfigFile->setCallback(varName, cb); + cb(*ConfigFile->getVarPtr(varName)); +} + +void CConfiguration::dropCallback(const std::string &varName) +{ + ConfigFile->setCallback(varName, NULL); +} + +bool CConfiguration::init() +{ + nlassert(!ConfigFile); ConfigFile = new CConfigFile(); nlassert(ConfigFile); + ConfigFile->load(SBCLIENT_CONFIG_FILE); + + // set the search paths (kinda important) + CConfigFile::CVar *var; + var = ConfigFile->getVarPtr("SearchPaths"); + uint varsize = var->size(); + for (uint i = 0; i < varsize; ++i) + CPath::addSearchPath(var->asString(i), true, false); + var = ConfigFile->getVarPtr("RemapExtensions"); + varsize = var->size(); + for (uint i = 0; i < varsize; i += 2) + CPath::remapExtension(var->asString(i), var->asString(i + 1), true); + + return true; +} + +bool CConfiguration::release() +{ + // save and release the config file + if (ConfigFile) + { + if (ConfigFile->exists("SaveConfig") && ConfigFile->getVarPtr("SaveConfig")->asBool()) + { + ConfigFile->save(); + } + delete ConfigFile; + ConfigFile = NULL; + } + else nlwarning("!ConfigFile"); + + // release the search paths etc + CPath::releaseInstance(); + + return true; +} + +void CConfiguration::updateUtilities() +{ + CConfigFile::checkConfigFiles(); +} + +float CConfiguration::getValue(const string &varName, float defaultValue) +{ + if (ConfigFile->exists(varName)) return ConfigFile->getVar(varName).asFloat(); + CConfigFile::CVar varToCopy; + varToCopy.forceAsDouble((double)defaultValue); + ConfigFile->insertVar(varName, varToCopy); + return defaultValue; +} + +double CConfiguration::getValue(const string &varName, double defaultValue) +{ + if (ConfigFile->exists(varName)) return ConfigFile->getVar(varName).asDouble(); + CConfigFile::CVar varToCopy; + varToCopy.forceAsDouble(defaultValue); + ConfigFile->insertVar(varName, varToCopy); + return defaultValue; +} + +int CConfiguration::getValue(const string &varName, int defaultValue) +{ + if (ConfigFile->exists(varName)) return ConfigFile->getVar(varName).asInt(); + CConfigFile::CVar varToCopy; + varToCopy.forceAsInt(defaultValue); + ConfigFile->insertVar(varName, varToCopy); + return defaultValue; +} + +string CConfiguration::getValue(const string &varName, const string &defaultValue) +{ + if (ConfigFile->exists(varName)) return ConfigFile->getVar(varName).asString(); + CConfigFile::CVar varToCopy; + varToCopy.forceAsString(defaultValue); + ConfigFile->insertVar(varName, varToCopy); + return defaultValue; +} + +ucstring CConfiguration::getValue(const string &varName, const ucstring &defaultValue) +{ + if (ConfigFile->exists(varName)) return ucstring::makeFromUtf8(ConfigFile->getVar(varName).asString()); + CConfigFile::CVar varToCopy; + varToCopy.forceAsString(defaultValue.toUtf8()); + ConfigFile->insertVar(varName, varToCopy); + return defaultValue; +} + +bool CConfiguration::getValue(const string &varName, bool defaultValue) +{ + if (ConfigFile->exists(varName)) return ConfigFile->getVar(varName).asBool(); + CConfigFile::CVar varToCopy; + varToCopy.forceAsInt(defaultValue ? 1 : 0); + ConfigFile->insertVar(varName, varToCopy); + return defaultValue; +} + +CRGBA CConfiguration::getValue(const string &varName, const CRGBA &defaultValue) +{ + if (ConfigFile->exists(varName)) + { + return getValue(ConfigFile->getVar(varName), defaultValue); + } + else + { + // create a new value only if one doesn't exist + CConfigFile::CVar varToCopy; + varToCopy.forceAsInt(defaultValue.R); + varToCopy.setAsInt(defaultValue.G, 1); + varToCopy.setAsInt(defaultValue.B, 2); + varToCopy.setAsInt(defaultValue.A, 3); + ConfigFile->insertVar(varName, varToCopy); + } + return defaultValue; +} + +CRGBA CConfiguration::getValue(const CConfigFile::CVar &var, const CRGBA &defaultValue) +{ + if (var.size() >= 3) + { + if (var.size() > 4) nlwarning("RGBA value in config value '%s' is too long, ignoring unused values"); + return CRGBA(var.asInt(0), var.asInt(1), var.asInt(2), var.size() >= 4 ? var.asInt(3) : 255); + } + nlwarning("Invalid RGBA value in config value '%s', reverting to default { %i, %i, %i, %i }", var.Name.c_str(), (sint)defaultValue.R, (sint)defaultValue.G, (sint)defaultValue.B, (sint)defaultValue.A); + return defaultValue; +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/configuration.h b/code/snowballs2/client/src/configuration.h index 230e665b5..2f398e402 100644 --- a/code/snowballs2/client/src/configuration.h +++ b/code/snowballs2/client/src/configuration.h @@ -1,64 +1,64 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef SBCLIENT_CONFIGURATION_H -#define SBCLIENT_CONFIGURATION_H -#include - -// STL includes - -// NeL includes -#include -#include -#include - -// Project includes - -namespace SBCLIENT { - -/** - * \brief CConfiguration - * \date 2008-11-06 16:25GMT - * \author Jan Boon (Kaetemi) - * CConfiguration - */ -class CConfiguration -{ -public: - static bool init(); - static bool release(); - - static void updateUtilities(); - - static void setAndCallback(const std::string &varName, void (*cb)(NLMISC::CConfigFile::CVar &var)); - static void dropCallback(const std::string &varName); - - static float getValue(const std::string &varName, float defaultValue); - static double getValue(const std::string &varName, double defaultValue); - static int getValue(const std::string &varName, int defaultValue); - static std::string getValue(const std::string &varName, const std::string &defaultValue); - static ucstring getValue(const std::string &varName, const ucstring &defaultValue); - static bool getValue(const std::string &varName, bool defaultValue); - static NLMISC::CRGBA getValue(const std::string &varName, const NLMISC::CRGBA &defaultValue); - static NLMISC::CRGBA getValue(const NLMISC::CConfigFile::CVar &var, const NLMISC::CRGBA &defaultValue); - -}; /* class CConfiguration */ - -} /* namespace SBCLIENT */ - -#endif /* #ifndef SBCLIENT_CONFIGURATION_H */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SBCLIENT_CONFIGURATION_H +#define SBCLIENT_CONFIGURATION_H +#include + +// STL includes + +// NeL includes +#include +#include +#include + +// Project includes + +namespace SBCLIENT { + +/** + * \brief CConfiguration + * \date 2008-11-06 16:25GMT + * \author Jan Boon (Kaetemi) + * CConfiguration + */ +class CConfiguration +{ +public: + static bool init(); + static bool release(); + + static void updateUtilities(); + + static void setAndCallback(const std::string &varName, void (*cb)(NLMISC::CConfigFile::CVar &var)); + static void dropCallback(const std::string &varName); + + static float getValue(const std::string &varName, float defaultValue); + static double getValue(const std::string &varName, double defaultValue); + static int getValue(const std::string &varName, int defaultValue); + static std::string getValue(const std::string &varName, const std::string &defaultValue); + static ucstring getValue(const std::string &varName, const ucstring &defaultValue); + static bool getValue(const std::string &varName, bool defaultValue); + static NLMISC::CRGBA getValue(const std::string &varName, const NLMISC::CRGBA &defaultValue); + static NLMISC::CRGBA getValue(const NLMISC::CConfigFile::CVar &var, const NLMISC::CRGBA &defaultValue); + +}; /* class CConfiguration */ + +} /* namespace SBCLIENT */ + +#endif /* #ifndef SBCLIENT_CONFIGURATION_H */ + +/* end of file */ diff --git a/code/snowballs2/client/src/entities.cpp b/code/snowballs2/client/src/entities.cpp index 78531eacf..af879958c 100644 --- a/code/snowballs2/client/src/entities.cpp +++ b/code/snowballs2/client/src/entities.cpp @@ -1,1034 +1,1034 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include "snowballs_client.h" -#include "entities.h" -#include "pacs.h" -#include "animation.h" -#include "camera.h" -#ifdef NL_OS_WINDOWS -#include "sound.h" -#endif -#include "mouse_listener.h" -#include "landscape.h" - -// -// Namespaces -// - -using namespace std; -using namespace NLMISC; -using namespace NL3D; -using namespace NLPACS; - -namespace SBCLIENT { - -// -// Variables -// - -// A map of entities. All entities are later referred by their unique id -map Entities; - -CEntity *Self = NULL; - -// The size of the world, in meter -float WorldWidth = 20*160; -float WorldHeight = 6*160; - -// Entity Id, only used offline -uint32 NextEID = 1000000; - -// The speed settings -float PlayerSpeed = 10.0f; // 6.5 km/h -float SnowballSpeed = 15.0f; // 36 km/h - -// these variables are set with the config file - -// Setup for the name up the character -float EntityNameSize; -CRGBA EntityNameColor; - -bool _TestCLS = false; - - -// Set the state of the entity (Appear, Normal, Disappear) -void CEntity::setState (TState state) -{ - State = state; - StateStartTime = CTime::getLocalTime (); -} - - -// Get an map iterator on a entity, specified by its id -EIT findEntity (uint32 eid, bool needAssert) -{ - EIT entity = Entities.find (eid); - if (entity == Entities.end () && needAssert) - { - nlerror ("Entity %u not found", eid); - } - return entity; -} - -// -- -- things like Creature, Effect, Scenery seem more flexible than Self, Other, Snowball -// -- -- random keywords: entitybehavior (animations), entityinteraction (targetable, menu, ) -// Creates an entity, given its id, its type (Self, Other, Snowball), its start and server positions. -void addEntity (uint32 eid, std::string name, CEntity::TType type, const CVector &startPosition, const CVector &serverPosition) -{ -// nlinfo ("adding entity %u", eid); - - // Check that the entity doesn't exist yet - EIT eit = findEntity (eid, false); - if (eit != Entities.end ()) - { - nlerror ("Entity %d already exist", eid); - } - - // Create a new entity - eit = (Entities.insert (make_pair (eid, CEntity()))).first; - CEntity &entity = (*eit).second; - - // Check that in the case the entity newly created is a Self, there's not a Self yet. - if (type == CEntity::Self) - { - if (Self != NULL) - nlerror("Self entity already created"); - - Self = &entity; - } - - // Set the entity up - entity.Id = eid; - entity.Type = type; - entity.Name = name; - entity.Position = startPosition; - entity.Angle = 0.0f; - entity.ServerPosition = serverPosition; - entity.VisualCollisionEntity = VisualCollisionManager->createEntity(); - - // setup the move primitive and the mesh instance depending on the type of entity - switch (type) - { - case CEntity::Self: - // create a move primitive associated to the entity - entity.MovePrimitive = MoveContainer->addCollisionablePrimitive(0, 1); - // it's a cylinder - entity.MovePrimitive->setPrimitiveType(UMovePrimitive::_2DOrientedCylinder); - // the entity should slide against obstacles - entity.MovePrimitive->setReactionType(UMovePrimitive::Slide); - // do not generate event if there is a collision - entity.MovePrimitive->setTriggerType(UMovePrimitive::NotATrigger); - // which entity should collide against me - entity.MovePrimitive->setCollisionMask(OtherCollisionBit+SnowballCollisionBit+StaticCollisionBit); - // the self collision bit - entity.MovePrimitive->setOcclusionMask(SelfCollisionBit); - // the self is an obstacle - entity.MovePrimitive->setObstacle(true); - // the size of the cylinder - entity.MovePrimitive->setRadius(1.0f); - entity.MovePrimitive->setHeight(1.8f); - // only use one world image, so use insert in world image 0 - entity.MovePrimitive->insertInWorldImage(0); - // retrieve the start position of the entity - entity.MovePrimitive->setGlobalPosition(CVectorD(startPosition.x, startPosition.y, startPosition.z), 0); - - // create instance of the mesh character - entity.Instance = Scene->createInstance ("gnu.shape"); - entity.Skeleton = Scene->createSkeleton ("gnu.skel"); - // use the instance on the skeleton - entity.Skeleton.bindSkin (entity.Instance); - - // Allow the skeleton to cast shadows. - entity.Skeleton.enableCastShadowMap(true); - - entity.Instance.hide (); - - entity.Angle = MouseListener->getOrientation(); - - // setup final parameters - entity.Speed = PlayerSpeed; - entity.Particule = Scene->createInstance ("appear.ps"); - entity.setState (CEntity::Appear); - playAnimation (entity, LogInAnim); - playAnimation (entity, IdleAnim); - - break; - case CEntity::Other: - entity.MovePrimitive = MoveContainer->addCollisionablePrimitive(0, 1); - entity.MovePrimitive->setPrimitiveType(UMovePrimitive::_2DOrientedCylinder); - entity.MovePrimitive->setReactionType(UMovePrimitive::Slide); - entity.MovePrimitive->setTriggerType(UMovePrimitive::NotATrigger); - entity.MovePrimitive->setCollisionMask(OtherCollisionBit+SelfCollisionBit+SnowballCollisionBit); - entity.MovePrimitive->setOcclusionMask(OtherCollisionBit); - entity.MovePrimitive->setObstacle(true); - entity.MovePrimitive->setRadius(1.0f); - entity.MovePrimitive->setHeight(1.8f); - entity.MovePrimitive->insertInWorldImage(0); - entity.MovePrimitive->setGlobalPosition(CVectorD(startPosition.x, startPosition.y, startPosition.z), 0); - - entity.Instance = Scene->createInstance ("gnu.shape"); - entity.Skeleton = Scene->createSkeleton ("gnu.skel"); - entity.Skeleton.bindSkin (entity.Instance); - entity.Instance.hide (); - - entity.Speed = PlayerSpeed; - entity.Particule = Scene->createInstance ("appear.ps"); - entity.setState (CEntity::Appear); - playAnimation (entity, LogInAnim); - playAnimation (entity, IdleAnim); - - break; - case CEntity::Snowball: - entity.MovePrimitive = NULL; - - // allows collision snapping to the ceiling - entity.VisualCollisionEntity->setCeilMode(true); - - entity.Instance = Scene->createInstance ("snowball.shape"); - entity.Skeleton = NULL; - entity.Speed = SnowballSpeed; - - // -- -- riiiiight -//#ifdef NL_OS_WINDOWS -// playSound (entity, SoundId); -//#endif - entity.setState (CEntity::Normal); - break; - } - - if (!entity.Skeleton.empty()) - entity.Skeleton.setPos (startPosition); - - entity.Instance.setPos (startPosition); - -// todo sound -// if (entity.Source != NULL) -// entity.Source->setPosition (startPosition); - - if (!entity.Particule.empty()) - entity.Particule.setPos (startPosition); - -} - -// effectively remove the entity (don't play animation) -void deleteEntity (CEntity &entity) -{ - if (!entity.Particule.empty()) - { - Scene->deleteInstance (entity.Particule); - entity.Particule = NULL; - } - - deleteAnimation (entity); - - if (!entity.Skeleton.empty()) - { - entity.Skeleton.detachSkeletonSon (entity.Instance); - Scene->deleteSkeleton (entity.Skeleton); - entity.Skeleton = NULL; - } - - if (!entity.Instance.empty()) - { - Scene->deleteInstance (entity.Instance); - entity.Instance = NULL; - } - - if (entity.VisualCollisionEntity != NULL) - { - VisualCollisionManager->deleteEntity (entity.VisualCollisionEntity); - entity.VisualCollisionEntity = NULL; - } - - if (entity.MovePrimitive != NULL) - { - MoveContainer->removePrimitive(entity.MovePrimitive); - entity.MovePrimitive = NULL; - } - -//#ifdef NL_OS_WINDOWS -// deleteSound (entity); -//#endif - -// nlinfo ("Remove the entity %u from the Entities list", entity.Id); - EIT eit = findEntity (entity.Id); - Entities.erase (eit); -} - - -// Remove an entity specified by its id -// The entity passes into the Disappear state -void removeEntity (uint32 eid) -{ -// nlinfo ("removing entity %u", eid); - - // look for the entity - EIT eit = findEntity (eid); - CEntity &entity = (*eit).second; - - // if there is a particle system linked, delete it - if (!entity.Particule.empty()) - { - Scene->deleteInstance (entity.Particule); - entity.Particule = NULL; - } - -// if (entity.Type == CEntity::Other) - { - - entity.Particule = Scene->createInstance("disappear.ps"); - entity.Particule.setPos (entity.Position); - } - - playAnimation (entity, LogOffAnim, true); - entity.setState (CEntity::Disappear); -} - -void removeAllEntitiesExceptUs () -{ - EIT eit, nexteit; - - // move entities - for (eit = Entities.begin (); eit != Entities.end (); ) - { - nexteit = eit; nexteit++; - - CEntity &entity = (*eit).second; - - if (entity.Type != CEntity::Self) - { - // effectively remove the entity (don't play animation) - deleteEntity (entity); - } - - eit = nexteit; - } -} - -void deleteAllEntities() -{ - EIT eit, nexteit; - for (eit = Entities.begin(); eit != Entities.end(); ) - { - nexteit = eit; nexteit++; - CEntity &entity = (*eit).second; - deleteEntity (entity); - eit = nexteit; - } - Self = NULL; -} - - - - - -// What to do when the entity appears -void stateAppear (CEntity &entity) -{ - // after 1 second, show the instance - if (CTime::getLocalTime () > entity.StateStartTime + 1000) - { - if (entity.Instance.getVisibility () != UTransform::Show) - entity.Instance.show (); - } - - // after 5 seconds, delete the particle system (if any) - // and pass the entity into the Normal state - if (CTime::getLocalTime () > entity.StateStartTime + 3000) - { - if (!entity.Particule.empty()) - { - Scene->deleteInstance (entity.Particule); - entity.Particule = NULL; - } - - entity.setState (CEntity::Normal); - } - - if (entity.MovePrimitive != NULL) - entity.MovePrimitive->move(CVector(0,0,0), 0); -} - -// What to do when the entity disappears -void stateDisappear (CEntity &entity) -{ - // after 1 second, remove the mesh and all collision stuff - if (CTime::getLocalTime () > entity.StateStartTime + 1000) - { - if (entity.Instance.getVisibility () != UTransform::Hide) - { - if (entity.Type == CEntity::Self) - { - if (Self == NULL) - nlerror("Self entity doesn't exist"); - Self = NULL; - } - - entity.Instance.hide (); - } - } - - // after 5 seconds, remove the particle system and the entity entry - if (CTime::getLocalTime () > entity.StateStartTime + 3000) - { - deleteEntity (entity); - } - else - { - if (entity.MovePrimitive != NULL) - entity.MovePrimitive->move(CVector(0,0,0), 0); - } -} - -void stateNormal (CEntity &entity) -{ - double dt = LocalTimeDelta; - CVector oldPos; - CVector newPos; - - oldPos = entity.Position; - CVector pDelta = entity.Position - entity.ServerPosition; - CVector pDeltaOri = pDelta; - pDelta.z = 0.0f; - - // -- -- simple random bots =) share with server - - // find a new random server position - if (entity.Type == CEntity::Other && entity.AutoMove) - { - switch (entity.BotState) - { - case 0: - // choose something to do - if (frand(1.0f) > 0.5f) - entity.BotState = 5; - else - entity.BotState = 2; - break; - case 1: - // walk - if (pDelta.norm() < 0.1f || LocalTime - entity.BotStateStart > 3.000) - { - // reached the point - entity.BotState = 0; - } - else - { -// entity.IsWalking = true; -// entity.IsAiming = false; - } - break; - case 2: - // aim - entity.IsWalking = false; - entity.IsAiming = true; - entity.BotStateStart = LocalTime; - entity.BotState = 3; - break; - case 3: - // wait to shoot - entity.IsWalking = false; - entity.IsAiming = true; - if (LocalTime - entity.BotStateStart > 1.000) - { - entity.BotState = 4; - entity.BotStateStart = LocalTime; - CVector AimingPosition = entity.Position+CVector(0.0f, 0.0f, 2.0f); - CVector direction = CVector((float)(cos(entity.Angle)), (float)(sin(entity.Angle)), 0.3f).normed(); - CVector AimedTarget = getTarget(AimingPosition, - direction, - 100); - shotSnowball(NextEID++, entity.Id, AimingPosition, AimedTarget, SnowballSpeed, 3.0f); - } - break; - case 4: - // shoot - entity.IsWalking = false; - entity.IsAiming = false; - if (LocalTime - entity.BotStateStart > 1.000) - { - entity.BotState = 5; - entity.BotStateStart = LocalTime; - } - break; - case 5: - // choose a direction - float EntityMaxSpeed = 10.0f; - entity.AuxiliaryAngle += frand(1.5f)-0.75f; - entity.ServerPosition += CVector((float)cos(entity.AuxiliaryAngle), - (float)sin(entity.AuxiliaryAngle), - 0.0f)*EntityMaxSpeed; - entity.BotState = 1; - entity.BotStateStart = LocalTime; - break; - } - } - - - if (entity.Type == CEntity::Snowball && LocalTime >= entity.Trajectory.getStopTime()) - { -/* - CVector tp(1140,-833,30); - nlinfo("dist=%f", (entity.Position-tp).norm()); - if ((entity.Position-tp).norm()<30.0f) - { - static UInstance t = NULL; - if (t != NULL) - { - Scene->deleteInstance (t); - } - t = Scene->createInstance("pills.ps"); - t->setScale (10,10,10); - CVector tp2 = tp; - tp2.z+=20; - t->setPos (tp2); - nlinfo("touche"); - } -*/ - removeEntity(entity.Id); - } - - - - // control the character animation - if (entity.Type != CEntity::Snowball) - { - if (entity.IsAiming && !entity.WasAiming) - { - // start aiming - playAnimation (entity, PrepareSnowBall, true); - playAnimation (entity, PrepareSnowBallCycle, false); - } - else if (entity.WasAiming && !entity.IsAiming) - { -/* // end aiming - playAnimation (entity, ThrowSnowball, true); - - if (entity.IsWalking) - playAnimation (entity, WalkAnim); - else - playAnimation (entity, IdleAnim); -*/ } - else if (entity.WasAiming && entity.IsAiming) - { - // currently aiming => do northing - } - else if (!entity.WasWalking && entity.IsWalking) - { - playAnimation (entity, PrepareWalkAnim, true); - playAnimation (entity, WalkAnim); - } - else if (entity.WasWalking && !entity.IsWalking) - { - playAnimation (entity, IdleAnim, true); - } - - entity.WasAiming = entity.IsAiming; - entity.WasWalking = entity.IsWalking; - } - - - entity.ImmediateSpeed = CVector::Null; - - if (entity.Type == CEntity::Self) - { - // get new position - newPos = MouseListener->getPosition(); - // get new orientation - entity.Angle = MouseListener->getOrientation(); - - // Interpolate the character orientation towards the server angle - // for smoother movements - float sweepDistance = entity.AuxiliaryAngle-entity.InterpolatedAuxiliaryAngle; - if (sweepDistance > (float)Pi) - { - sweepDistance -= (float)Pi*2.0f; - entity.InterpolatedAuxiliaryAngle += (float)Pi*2.0f; - } - if (sweepDistance < -(float)Pi) - { - sweepDistance += (float)Pi*2.0f; - entity.InterpolatedAuxiliaryAngle -= (float)Pi*2.0f; - } - float sweepAngle = 4.0f*sweepDistance; - entity.InterpolatedAuxiliaryAngle += (float)(sweepAngle*dt); - if ((entity.AuxiliaryAngle-entity.InterpolatedAuxiliaryAngle)*sweepAngle <= 0.0) - entity.InterpolatedAuxiliaryAngle = entity.AuxiliaryAngle; - entity.Angle += entity.InterpolatedAuxiliaryAngle; - - // tell the move container how much the entity should move - if (entity.IsWalking) - { - entity.ImmediateSpeed = (newPos-oldPos)/(float)dt; - if (_TestCLS) entity.MovePrimitive->setGlobalPosition(newPos, 0); - else entity.MovePrimitive->move(entity.ImmediateSpeed, 0); - } - } - else if (entity.Type == CEntity::Other) - { - // go to the server position with linear interpolation - // -- -- useful for speed limiting on frontend service - // -- -- random note: also, get rid of the position service, - // and move the snowball physics to a more useful service - - // Interpolate orientation for smoother motions - // AuxiliaryAngle -> the server imposed angle - // InterpolatedAuxiliaryAngle -> the angle showed by the entity - float sweepDistance = entity.AuxiliaryAngle-entity.InterpolatedAuxiliaryAngle; - if (sweepDistance > (float)Pi) - { - sweepDistance -= (float)Pi*2.0f; - entity.InterpolatedAuxiliaryAngle += (float)Pi*2.0f; - } - if (sweepDistance < -(float)Pi) - { - sweepDistance += (float)Pi*2.0f; - entity.InterpolatedAuxiliaryAngle -= (float)Pi*2.0f; - } - float sweepAngle = 4.0f*sweepDistance; - entity.InterpolatedAuxiliaryAngle += (float)(sweepAngle*dt); - if ((entity.AuxiliaryAngle-entity.InterpolatedAuxiliaryAngle)*sweepAngle <= 0.0) - entity.InterpolatedAuxiliaryAngle = entity.AuxiliaryAngle; - - entity.Angle = entity.InterpolatedAuxiliaryAngle; - -// if (entity.IsWalking) - if (pDelta.norm() > 0.1f) - { - pDelta.normalize(); - entity.ImmediateSpeed = pDelta*(-entity.Speed); - entity.MovePrimitive->move(entity.ImmediateSpeed, 0); - entity.IsWalking = true; - } - else - { - entity.IsWalking = false; - } - } - else if (entity.Type == CEntity::Snowball) - { - // go to the server position using trajectory interpolation - CVector newPos = entity.Trajectory.eval(LocalTime); - if (newPos != entity.Position) - { - entity.Position = entity.Trajectory.eval(LocalTime); - entity.Instance.show (); - } - } - else - { - // automatic speed - newPos = oldPos; - } -} - - - - - -void updateEntities () -{ - // compute the delta t that has elapsed since the last update (in seconds) - double dt = LocalTimeDelta; - EIT eit, nexteit; - - // move entities - for (eit = Entities.begin (); eit != Entities.end (); ) - { - nexteit = eit; nexteit++; - - CEntity &entity = (*eit).second; - - switch (entity.State) - { - case CEntity::Appear: - stateAppear (entity); - break; - case CEntity::Normal: - stateNormal (entity); - break; - case CEntity::Disappear: - stateDisappear (entity); - break; - default: - nlstop; - break; - } - - eit = nexteit; - } - - // evaluate collisions - MoveContainer->evalCollision(dt, 0); - - // snap entities to the ground - for (eit = Entities.begin (); eit != Entities.end (); eit++) - { - CEntity &entity = (*eit).second; - UGlobalPosition gPos; - - if (entity.MovePrimitive != NULL) - { - // get the global position in pacs coordinates system - entity.MovePrimitive->getGlobalPosition(gPos, 0); - // convert it in a vector 3d - entity.Position = GlobalRetriever->getGlobalPosition(gPos); - // get the good z position - gPos.LocalPosition.Estimation.z = 0.0f; - entity.Position.z = GlobalRetriever->getMeanHeight(gPos); - - // check position retrieving -/* - UGlobalPosition gPosCheck; - gPosCheck = GlobalRetriever->retrievePosition(entity.Position); - if (gPos.InstanceId != gPosCheck.InstanceId || - gPos.LocalPosition.Surface != gPosCheck.LocalPosition.Surface) - { - nlwarning("Checked UGlobalPosition differs from store"); -// gPos.InstanceId = gPosCheck.InstanceId; -// gPos.LocalPosition.Surface = gPosCheck.LocalPosition.Surface; - } -*/ - // snap to the ground - if (!GlobalRetriever->isInterior(gPos)) - entity.VisualCollisionEntity->snapToGround(entity.Position); - - if (entity.Type == CEntity::Other && - (entity.ServerPosition-entity.Position)*entity.ImmediateSpeed < 0.0f) - { -// nlinfo("detected over entity %d", entity.Id); - entity.ServerPosition.z = entity.Position.z; - entity.Position = entity.ServerPosition; - if (!GlobalRetriever->isInterior(gPos)) - entity.VisualCollisionEntity->snapToGround(entity.Position); - entity.MovePrimitive->setGlobalPosition(CVectorD(entity.Position.x, entity.Position.y, entity.Position.z), 0); - } - - } - - if (!entity.Instance.empty()) - { - CVector jdir; - switch (entity.Type) - { - case CEntity::Self: - jdir = CVector(-(float)cos(entity.Angle), -(float)sin(entity.Angle), 0.0f); - break; - case CEntity::Other: - jdir = CVector(-(float)cos(entity.Angle), -(float)sin(entity.Angle), 0.0f); - break; - case CEntity::Snowball: - jdir = entity.Trajectory.evalSpeed(LocalTime).normed(); - break; - } - - if (!entity.Skeleton.empty()) - { - entity.Skeleton.setPos(entity.Position); - entity.Skeleton.setRotQuat(jdir); - } - - entity.Instance.setPos(entity.Position); - entity.Instance.setRotQuat(jdir); - } - -// todo sound -// if (entity.Source != NULL) -// entity.Source->setPosition (entity.Position); - - if (!entity.Particule.empty()) - { - entity.Particule.setPos(entity.Position); - } - - if (entity.Type == CEntity::Self) - { - MouseListener->setPosition(entity.Position); - } - } -} - -// Draw entities names up the characters -void renderEntitiesNames () -{ - // Setup the driver in matrix mode - Driver->setMatrixMode3D (Camera); - // Setup the drawing context - TextContext->setHotSpot (UTextContext::MiddleTop); - TextContext->setColor (EntityNameColor); - TextContext->setFontSize ((uint32)EntityNameSize); - // - for (EIT eit = Entities.begin (); eit != Entities.end (); eit++) - { - CEntity &entity = (*eit).second; - if (!entity.Instance.empty() && entity.Type == CEntity::Other) - { - CMatrix mat = Camera.getMatrix(); - mat.setPos(entity.Position + CVector(0.0f, 0.0f, 4.0f)); - mat.scale(10.0f); - TextContext->render3D(mat, entity.Name); - } - } -} - - -// The entities preferences callback -void cbUpdateEntities (CConfigFile::CVar &var) -{ - if (var.Name == "EntityNameColor") EntityNameColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); - else if (var.Name == "EntityNameSize") EntityNameSize = var.asFloat (); - else nlwarning ("Unknown variable update %s", var.Name.c_str()); -} - -void initEntities() -{ - ConfigFile->setCallback ("EntityNameColor", cbUpdateEntities); - ConfigFile->setCallback ("EntityNameSize", cbUpdateEntities); - - cbUpdateEntities (ConfigFile->getVar ("EntityNameColor")); - cbUpdateEntities (ConfigFile->getVar ("EntityNameSize")); -} - -void releaseEntities() -{ - // Remove config file callbacks - ConfigFile->setCallback("EntityNameColor", NULL); - ConfigFile->setCallback("EntityNameSize", NULL); - - // Delete all entities (should already have been called normally) - deleteAllEntities(); -} - - -// Reset the pacs position of an entity, in case pacs went wrong -void resetEntityPosition(uint32 eid) -{ - uint32 sbid = NextEID++; - EIT eit = findEntity (eid); - - CEntity &entity = (*eit).second; - - UGlobalPosition gPos; - // get the global position - gPos = GlobalRetriever->retrievePosition(entity.Position); - // convert it in a vector 3d - entity.Position = GlobalRetriever->getGlobalPosition(gPos); - // get the good z position - gPos.LocalPosition.Estimation.z = 0.0f; - entity.Position.z = GlobalRetriever->getMeanHeight(gPos); - - // snap to the ground - if (entity.VisualCollisionEntity != NULL && !GlobalRetriever->isInterior(gPos)) - entity.VisualCollisionEntity->snapToGround(entity.Position); - - if (entity.MovePrimitive != NULL) - entity.MovePrimitive->setGlobalPosition(CVector(entity.Position.x, entity.Position.y, entity.Position.z), 0); -} - - -void shotSnowball(uint32 sid, uint32 eid, const CVector &start, const CVector &target, float speed, float deflagRadius) -{ - // get direction - CVector direction = (target-start).normed(); - - // create a new snowball entity - addEntity(sid, "", CEntity::Snowball, start, target); - EIT sit = findEntity (sid); - CEntity &snowball = (*sit).second; - - snowball.AutoMove = 1; - snowball.Trajectory.init(start, target, speed, LocalTime + 1.000); - snowball.Instance.hide(); - - EIT eit = findEntity (eid); - CEntity &entity = (*eit).second; - - // end aiming - playAnimation (entity, ThrowSnowball, true); - - if (entity.IsWalking) - { - playAnimation (entity, PrepareWalkAnim, true); - playAnimation (entity, WalkAnim); - } - else - playAnimation (entity, IdleAnim); - -} - - -// -// Commands -// - -NLMISC_COMMAND(remove_entity,"remove a local entity","") -{ - // check args, if there s not the right number of parameter, return bad - if(args.size() != 1) return false; - - uint32 eid = (uint32)atoi(args[0].c_str()); - removeEntity (eid); - - return true; -} - - -NLMISC_COMMAND(add_entity,"add a local entity"," ") -{ - // check args, if there s not the right number of parameter, return bad - if(args.size() != 2) return false; - - uint nb = (uint)atoi(args[0].c_str()); - - for (uint i = 0; i < nb ; i++) - { - uint32 eid = NextEID++; - CVector start(ConfigFile->getVar("StartPoint").asFloat(0), ConfigFile->getVar("StartPoint").asFloat(1), ConfigFile->getVar("StartPoint").asFloat(2)); - addEntity (eid, "Entity"+toString(eid), CEntity::Other, start, start); - EIT eit = findEntity (eid); - (*eit).second.AutoMove = atoi(args[1].c_str()) == 1; - } - - return true; -} - -NLMISC_COMMAND(speed,"set the player speed","[] ") -{ - // check args, if there s not the right number of parameter, return bad - if(args.size() == 1) - { - float speed = min( max( (float)atof(args[0].c_str()), 0.1f ), 200.0f ); // speed range in km/h - if (Self != NULL) - { - MouseListener->setSpeed( speed / 3.6f ); - Self->Speed = speed / 3.6f; - } - } - else if(args.size() == 2) - { - float speed = min( max( (float)atof(args[1].c_str()), 0.1f ), 200.0f ); // speed range in km/h - - uint eid = (uint)atoi(args[0].c_str()); - EIT eit = findEntity (eid); - CEntity &entity = (*eit).second; - - entity.Speed = speed / 3.6f; - if (entity.Type == CEntity::Self) - { - MouseListener->setSpeed(entity.Speed); - } - } - return true; -} - -NLMISC_COMMAND(goto, "go to a given position", " ") -{ - // check args, if there s not the right number of parameter, return bad - if(args.size() != 2) return false; - - if (Self == NULL) return false; - - CEntity &entity = *Self; - - float x, y; - - x = (float)atof(args[0].c_str()); - y = (float)atof(args[1].c_str()); - - // - if (entity.MovePrimitive != NULL && entity.VisualCollisionEntity != NULL) - { - UGlobalPosition gPos; - entity.MovePrimitive->setGlobalPosition(CVectorD(x, y, 0.0f), 0); - // get the global position in pacs coordinates system - entity.MovePrimitive->getGlobalPosition(gPos, 0); - // convert it in a vector 3d - entity.Position = GlobalRetriever->getGlobalPosition(gPos); - // get the good z position - gPos.LocalPosition.Estimation.z = 0.0f; - entity.Position.z = GlobalRetriever->getMeanHeight(gPos); - // snap to the ground - if (!GlobalRetriever->isInterior(gPos)) - entity.VisualCollisionEntity->snapToGround( entity.Position ); - - if (entity.Type == CEntity::Self) - { - MouseListener->setPosition(entity.Position); - } - } - - return true; -} - -NLMISC_COMMAND(entities, "display all entities info", "") -{ - // check args, if there s not the right number of parameter, return bad - if(args.size() != 0) return false; - - for (EIT eit = Entities.begin (); eit != Entities.end (); eit++) - { - CEntity &e = (*eit).second; - log.displayNL("%s %u (k%u) %s %d", (Self==&e)?"*":" ", e.Id, (*eit).first, e.Name.c_str(), e.Type); - } - return true; -} - -NLMISC_COMMAND(test_cls, "test the collision service, disables collision test on self", "") -{ - _TestCLS = !_TestCLS; - return true; -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include "snowballs_client.h" +#include "entities.h" +#include "pacs.h" +#include "animation.h" +#include "camera.h" +#ifdef NL_OS_WINDOWS +#include "sound.h" +#endif +#include "mouse_listener.h" +#include "landscape.h" + +// +// Namespaces +// + +using namespace std; +using namespace NLMISC; +using namespace NL3D; +using namespace NLPACS; + +namespace SBCLIENT { + +// +// Variables +// + +// A map of entities. All entities are later referred by their unique id +map Entities; + +CEntity *Self = NULL; + +// The size of the world, in meter +float WorldWidth = 20*160; +float WorldHeight = 6*160; + +// Entity Id, only used offline +uint32 NextEID = 1000000; + +// The speed settings +float PlayerSpeed = 10.0f; // 6.5 km/h +float SnowballSpeed = 15.0f; // 36 km/h + +// these variables are set with the config file + +// Setup for the name up the character +float EntityNameSize; +CRGBA EntityNameColor; + +bool _TestCLS = false; + + +// Set the state of the entity (Appear, Normal, Disappear) +void CEntity::setState (TState state) +{ + State = state; + StateStartTime = CTime::getLocalTime (); +} + + +// Get an map iterator on a entity, specified by its id +EIT findEntity (uint32 eid, bool needAssert) +{ + EIT entity = Entities.find (eid); + if (entity == Entities.end () && needAssert) + { + nlerror ("Entity %u not found", eid); + } + return entity; +} + +// -- -- things like Creature, Effect, Scenery seem more flexible than Self, Other, Snowball +// -- -- random keywords: entitybehavior (animations), entityinteraction (targetable, menu, ) +// Creates an entity, given its id, its type (Self, Other, Snowball), its start and server positions. +void addEntity (uint32 eid, std::string name, CEntity::TType type, const CVector &startPosition, const CVector &serverPosition) +{ +// nlinfo ("adding entity %u", eid); + + // Check that the entity doesn't exist yet + EIT eit = findEntity (eid, false); + if (eit != Entities.end ()) + { + nlerror ("Entity %d already exist", eid); + } + + // Create a new entity + eit = (Entities.insert (make_pair (eid, CEntity()))).first; + CEntity &entity = (*eit).second; + + // Check that in the case the entity newly created is a Self, there's not a Self yet. + if (type == CEntity::Self) + { + if (Self != NULL) + nlerror("Self entity already created"); + + Self = &entity; + } + + // Set the entity up + entity.Id = eid; + entity.Type = type; + entity.Name = name; + entity.Position = startPosition; + entity.Angle = 0.0f; + entity.ServerPosition = serverPosition; + entity.VisualCollisionEntity = VisualCollisionManager->createEntity(); + + // setup the move primitive and the mesh instance depending on the type of entity + switch (type) + { + case CEntity::Self: + // create a move primitive associated to the entity + entity.MovePrimitive = MoveContainer->addCollisionablePrimitive(0, 1); + // it's a cylinder + entity.MovePrimitive->setPrimitiveType(UMovePrimitive::_2DOrientedCylinder); + // the entity should slide against obstacles + entity.MovePrimitive->setReactionType(UMovePrimitive::Slide); + // do not generate event if there is a collision + entity.MovePrimitive->setTriggerType(UMovePrimitive::NotATrigger); + // which entity should collide against me + entity.MovePrimitive->setCollisionMask(OtherCollisionBit+SnowballCollisionBit+StaticCollisionBit); + // the self collision bit + entity.MovePrimitive->setOcclusionMask(SelfCollisionBit); + // the self is an obstacle + entity.MovePrimitive->setObstacle(true); + // the size of the cylinder + entity.MovePrimitive->setRadius(1.0f); + entity.MovePrimitive->setHeight(1.8f); + // only use one world image, so use insert in world image 0 + entity.MovePrimitive->insertInWorldImage(0); + // retrieve the start position of the entity + entity.MovePrimitive->setGlobalPosition(CVectorD(startPosition.x, startPosition.y, startPosition.z), 0); + + // create instance of the mesh character + entity.Instance = Scene->createInstance ("gnu.shape"); + entity.Skeleton = Scene->createSkeleton ("gnu.skel"); + // use the instance on the skeleton + entity.Skeleton.bindSkin (entity.Instance); + + // Allow the skeleton to cast shadows. + entity.Skeleton.enableCastShadowMap(true); + + entity.Instance.hide (); + + entity.Angle = MouseListener->getOrientation(); + + // setup final parameters + entity.Speed = PlayerSpeed; + entity.Particule = Scene->createInstance ("appear.ps"); + entity.setState (CEntity::Appear); + playAnimation (entity, LogInAnim); + playAnimation (entity, IdleAnim); + + break; + case CEntity::Other: + entity.MovePrimitive = MoveContainer->addCollisionablePrimitive(0, 1); + entity.MovePrimitive->setPrimitiveType(UMovePrimitive::_2DOrientedCylinder); + entity.MovePrimitive->setReactionType(UMovePrimitive::Slide); + entity.MovePrimitive->setTriggerType(UMovePrimitive::NotATrigger); + entity.MovePrimitive->setCollisionMask(OtherCollisionBit+SelfCollisionBit+SnowballCollisionBit); + entity.MovePrimitive->setOcclusionMask(OtherCollisionBit); + entity.MovePrimitive->setObstacle(true); + entity.MovePrimitive->setRadius(1.0f); + entity.MovePrimitive->setHeight(1.8f); + entity.MovePrimitive->insertInWorldImage(0); + entity.MovePrimitive->setGlobalPosition(CVectorD(startPosition.x, startPosition.y, startPosition.z), 0); + + entity.Instance = Scene->createInstance ("gnu.shape"); + entity.Skeleton = Scene->createSkeleton ("gnu.skel"); + entity.Skeleton.bindSkin (entity.Instance); + entity.Instance.hide (); + + entity.Speed = PlayerSpeed; + entity.Particule = Scene->createInstance ("appear.ps"); + entity.setState (CEntity::Appear); + playAnimation (entity, LogInAnim); + playAnimation (entity, IdleAnim); + + break; + case CEntity::Snowball: + entity.MovePrimitive = NULL; + + // allows collision snapping to the ceiling + entity.VisualCollisionEntity->setCeilMode(true); + + entity.Instance = Scene->createInstance ("snowball.shape"); + entity.Skeleton = NULL; + entity.Speed = SnowballSpeed; + + // -- -- riiiiight +//#ifdef NL_OS_WINDOWS +// playSound (entity, SoundId); +//#endif + entity.setState (CEntity::Normal); + break; + } + + if (!entity.Skeleton.empty()) + entity.Skeleton.setPos (startPosition); + + entity.Instance.setPos (startPosition); + +// todo sound +// if (entity.Source != NULL) +// entity.Source->setPosition (startPosition); + + if (!entity.Particule.empty()) + entity.Particule.setPos (startPosition); + +} + +// effectively remove the entity (don't play animation) +void deleteEntity (CEntity &entity) +{ + if (!entity.Particule.empty()) + { + Scene->deleteInstance (entity.Particule); + entity.Particule = NULL; + } + + deleteAnimation (entity); + + if (!entity.Skeleton.empty()) + { + entity.Skeleton.detachSkeletonSon (entity.Instance); + Scene->deleteSkeleton (entity.Skeleton); + entity.Skeleton = NULL; + } + + if (!entity.Instance.empty()) + { + Scene->deleteInstance (entity.Instance); + entity.Instance = NULL; + } + + if (entity.VisualCollisionEntity != NULL) + { + VisualCollisionManager->deleteEntity (entity.VisualCollisionEntity); + entity.VisualCollisionEntity = NULL; + } + + if (entity.MovePrimitive != NULL) + { + MoveContainer->removePrimitive(entity.MovePrimitive); + entity.MovePrimitive = NULL; + } + +//#ifdef NL_OS_WINDOWS +// deleteSound (entity); +//#endif + +// nlinfo ("Remove the entity %u from the Entities list", entity.Id); + EIT eit = findEntity (entity.Id); + Entities.erase (eit); +} + + +// Remove an entity specified by its id +// The entity passes into the Disappear state +void removeEntity (uint32 eid) +{ +// nlinfo ("removing entity %u", eid); + + // look for the entity + EIT eit = findEntity (eid); + CEntity &entity = (*eit).second; + + // if there is a particle system linked, delete it + if (!entity.Particule.empty()) + { + Scene->deleteInstance (entity.Particule); + entity.Particule = NULL; + } + +// if (entity.Type == CEntity::Other) + { + + entity.Particule = Scene->createInstance("disappear.ps"); + entity.Particule.setPos (entity.Position); + } + + playAnimation (entity, LogOffAnim, true); + entity.setState (CEntity::Disappear); +} + +void removeAllEntitiesExceptUs () +{ + EIT eit, nexteit; + + // move entities + for (eit = Entities.begin (); eit != Entities.end (); ) + { + nexteit = eit; nexteit++; + + CEntity &entity = (*eit).second; + + if (entity.Type != CEntity::Self) + { + // effectively remove the entity (don't play animation) + deleteEntity (entity); + } + + eit = nexteit; + } +} + +void deleteAllEntities() +{ + EIT eit, nexteit; + for (eit = Entities.begin(); eit != Entities.end(); ) + { + nexteit = eit; nexteit++; + CEntity &entity = (*eit).second; + deleteEntity (entity); + eit = nexteit; + } + Self = NULL; +} + + + + + +// What to do when the entity appears +void stateAppear (CEntity &entity) +{ + // after 1 second, show the instance + if (CTime::getLocalTime () > entity.StateStartTime + 1000) + { + if (entity.Instance.getVisibility () != UTransform::Show) + entity.Instance.show (); + } + + // after 5 seconds, delete the particle system (if any) + // and pass the entity into the Normal state + if (CTime::getLocalTime () > entity.StateStartTime + 3000) + { + if (!entity.Particule.empty()) + { + Scene->deleteInstance (entity.Particule); + entity.Particule = NULL; + } + + entity.setState (CEntity::Normal); + } + + if (entity.MovePrimitive != NULL) + entity.MovePrimitive->move(CVector(0,0,0), 0); +} + +// What to do when the entity disappears +void stateDisappear (CEntity &entity) +{ + // after 1 second, remove the mesh and all collision stuff + if (CTime::getLocalTime () > entity.StateStartTime + 1000) + { + if (entity.Instance.getVisibility () != UTransform::Hide) + { + if (entity.Type == CEntity::Self) + { + if (Self == NULL) + nlerror("Self entity doesn't exist"); + Self = NULL; + } + + entity.Instance.hide (); + } + } + + // after 5 seconds, remove the particle system and the entity entry + if (CTime::getLocalTime () > entity.StateStartTime + 3000) + { + deleteEntity (entity); + } + else + { + if (entity.MovePrimitive != NULL) + entity.MovePrimitive->move(CVector(0,0,0), 0); + } +} + +void stateNormal (CEntity &entity) +{ + double dt = LocalTimeDelta; + CVector oldPos; + CVector newPos; + + oldPos = entity.Position; + CVector pDelta = entity.Position - entity.ServerPosition; + CVector pDeltaOri = pDelta; + pDelta.z = 0.0f; + + // -- -- simple random bots =) share with server + + // find a new random server position + if (entity.Type == CEntity::Other && entity.AutoMove) + { + switch (entity.BotState) + { + case 0: + // choose something to do + if (frand(1.0f) > 0.5f) + entity.BotState = 5; + else + entity.BotState = 2; + break; + case 1: + // walk + if (pDelta.norm() < 0.1f || LocalTime - entity.BotStateStart > 3.000) + { + // reached the point + entity.BotState = 0; + } + else + { +// entity.IsWalking = true; +// entity.IsAiming = false; + } + break; + case 2: + // aim + entity.IsWalking = false; + entity.IsAiming = true; + entity.BotStateStart = LocalTime; + entity.BotState = 3; + break; + case 3: + // wait to shoot + entity.IsWalking = false; + entity.IsAiming = true; + if (LocalTime - entity.BotStateStart > 1.000) + { + entity.BotState = 4; + entity.BotStateStart = LocalTime; + CVector AimingPosition = entity.Position+CVector(0.0f, 0.0f, 2.0f); + CVector direction = CVector((float)(cos(entity.Angle)), (float)(sin(entity.Angle)), 0.3f).normed(); + CVector AimedTarget = getTarget(AimingPosition, + direction, + 100); + shotSnowball(NextEID++, entity.Id, AimingPosition, AimedTarget, SnowballSpeed, 3.0f); + } + break; + case 4: + // shoot + entity.IsWalking = false; + entity.IsAiming = false; + if (LocalTime - entity.BotStateStart > 1.000) + { + entity.BotState = 5; + entity.BotStateStart = LocalTime; + } + break; + case 5: + // choose a direction + float EntityMaxSpeed = 10.0f; + entity.AuxiliaryAngle += frand(1.5f)-0.75f; + entity.ServerPosition += CVector((float)cos(entity.AuxiliaryAngle), + (float)sin(entity.AuxiliaryAngle), + 0.0f)*EntityMaxSpeed; + entity.BotState = 1; + entity.BotStateStart = LocalTime; + break; + } + } + + + if (entity.Type == CEntity::Snowball && LocalTime >= entity.Trajectory.getStopTime()) + { +/* + CVector tp(1140,-833,30); + nlinfo("dist=%f", (entity.Position-tp).norm()); + if ((entity.Position-tp).norm()<30.0f) + { + static UInstance t = NULL; + if (t != NULL) + { + Scene->deleteInstance (t); + } + t = Scene->createInstance("pills.ps"); + t->setScale (10,10,10); + CVector tp2 = tp; + tp2.z+=20; + t->setPos (tp2); + nlinfo("touche"); + } +*/ + removeEntity(entity.Id); + } + + + + // control the character animation + if (entity.Type != CEntity::Snowball) + { + if (entity.IsAiming && !entity.WasAiming) + { + // start aiming + playAnimation (entity, PrepareSnowBall, true); + playAnimation (entity, PrepareSnowBallCycle, false); + } + else if (entity.WasAiming && !entity.IsAiming) + { +/* // end aiming + playAnimation (entity, ThrowSnowball, true); + + if (entity.IsWalking) + playAnimation (entity, WalkAnim); + else + playAnimation (entity, IdleAnim); +*/ } + else if (entity.WasAiming && entity.IsAiming) + { + // currently aiming => do northing + } + else if (!entity.WasWalking && entity.IsWalking) + { + playAnimation (entity, PrepareWalkAnim, true); + playAnimation (entity, WalkAnim); + } + else if (entity.WasWalking && !entity.IsWalking) + { + playAnimation (entity, IdleAnim, true); + } + + entity.WasAiming = entity.IsAiming; + entity.WasWalking = entity.IsWalking; + } + + + entity.ImmediateSpeed = CVector::Null; + + if (entity.Type == CEntity::Self) + { + // get new position + newPos = MouseListener->getPosition(); + // get new orientation + entity.Angle = MouseListener->getOrientation(); + + // Interpolate the character orientation towards the server angle + // for smoother movements + float sweepDistance = entity.AuxiliaryAngle-entity.InterpolatedAuxiliaryAngle; + if (sweepDistance > (float)Pi) + { + sweepDistance -= (float)Pi*2.0f; + entity.InterpolatedAuxiliaryAngle += (float)Pi*2.0f; + } + if (sweepDistance < -(float)Pi) + { + sweepDistance += (float)Pi*2.0f; + entity.InterpolatedAuxiliaryAngle -= (float)Pi*2.0f; + } + float sweepAngle = 4.0f*sweepDistance; + entity.InterpolatedAuxiliaryAngle += (float)(sweepAngle*dt); + if ((entity.AuxiliaryAngle-entity.InterpolatedAuxiliaryAngle)*sweepAngle <= 0.0) + entity.InterpolatedAuxiliaryAngle = entity.AuxiliaryAngle; + entity.Angle += entity.InterpolatedAuxiliaryAngle; + + // tell the move container how much the entity should move + if (entity.IsWalking) + { + entity.ImmediateSpeed = (newPos-oldPos)/(float)dt; + if (_TestCLS) entity.MovePrimitive->setGlobalPosition(newPos, 0); + else entity.MovePrimitive->move(entity.ImmediateSpeed, 0); + } + } + else if (entity.Type == CEntity::Other) + { + // go to the server position with linear interpolation + // -- -- useful for speed limiting on frontend service + // -- -- random note: also, get rid of the position service, + // and move the snowball physics to a more useful service + + // Interpolate orientation for smoother motions + // AuxiliaryAngle -> the server imposed angle + // InterpolatedAuxiliaryAngle -> the angle showed by the entity + float sweepDistance = entity.AuxiliaryAngle-entity.InterpolatedAuxiliaryAngle; + if (sweepDistance > (float)Pi) + { + sweepDistance -= (float)Pi*2.0f; + entity.InterpolatedAuxiliaryAngle += (float)Pi*2.0f; + } + if (sweepDistance < -(float)Pi) + { + sweepDistance += (float)Pi*2.0f; + entity.InterpolatedAuxiliaryAngle -= (float)Pi*2.0f; + } + float sweepAngle = 4.0f*sweepDistance; + entity.InterpolatedAuxiliaryAngle += (float)(sweepAngle*dt); + if ((entity.AuxiliaryAngle-entity.InterpolatedAuxiliaryAngle)*sweepAngle <= 0.0) + entity.InterpolatedAuxiliaryAngle = entity.AuxiliaryAngle; + + entity.Angle = entity.InterpolatedAuxiliaryAngle; + +// if (entity.IsWalking) + if (pDelta.norm() > 0.1f) + { + pDelta.normalize(); + entity.ImmediateSpeed = pDelta*(-entity.Speed); + entity.MovePrimitive->move(entity.ImmediateSpeed, 0); + entity.IsWalking = true; + } + else + { + entity.IsWalking = false; + } + } + else if (entity.Type == CEntity::Snowball) + { + // go to the server position using trajectory interpolation + CVector newPos = entity.Trajectory.eval(LocalTime); + if (newPos != entity.Position) + { + entity.Position = entity.Trajectory.eval(LocalTime); + entity.Instance.show (); + } + } + else + { + // automatic speed + newPos = oldPos; + } +} + + + + + +void updateEntities () +{ + // compute the delta t that has elapsed since the last update (in seconds) + double dt = LocalTimeDelta; + EIT eit, nexteit; + + // move entities + for (eit = Entities.begin (); eit != Entities.end (); ) + { + nexteit = eit; nexteit++; + + CEntity &entity = (*eit).second; + + switch (entity.State) + { + case CEntity::Appear: + stateAppear (entity); + break; + case CEntity::Normal: + stateNormal (entity); + break; + case CEntity::Disappear: + stateDisappear (entity); + break; + default: + nlstop; + break; + } + + eit = nexteit; + } + + // evaluate collisions + MoveContainer->evalCollision(dt, 0); + + // snap entities to the ground + for (eit = Entities.begin (); eit != Entities.end (); eit++) + { + CEntity &entity = (*eit).second; + UGlobalPosition gPos; + + if (entity.MovePrimitive != NULL) + { + // get the global position in pacs coordinates system + entity.MovePrimitive->getGlobalPosition(gPos, 0); + // convert it in a vector 3d + entity.Position = GlobalRetriever->getGlobalPosition(gPos); + // get the good z position + gPos.LocalPosition.Estimation.z = 0.0f; + entity.Position.z = GlobalRetriever->getMeanHeight(gPos); + + // check position retrieving +/* + UGlobalPosition gPosCheck; + gPosCheck = GlobalRetriever->retrievePosition(entity.Position); + if (gPos.InstanceId != gPosCheck.InstanceId || + gPos.LocalPosition.Surface != gPosCheck.LocalPosition.Surface) + { + nlwarning("Checked UGlobalPosition differs from store"); +// gPos.InstanceId = gPosCheck.InstanceId; +// gPos.LocalPosition.Surface = gPosCheck.LocalPosition.Surface; + } +*/ + // snap to the ground + if (!GlobalRetriever->isInterior(gPos)) + entity.VisualCollisionEntity->snapToGround(entity.Position); + + if (entity.Type == CEntity::Other && + (entity.ServerPosition-entity.Position)*entity.ImmediateSpeed < 0.0f) + { +// nlinfo("detected over entity %d", entity.Id); + entity.ServerPosition.z = entity.Position.z; + entity.Position = entity.ServerPosition; + if (!GlobalRetriever->isInterior(gPos)) + entity.VisualCollisionEntity->snapToGround(entity.Position); + entity.MovePrimitive->setGlobalPosition(CVectorD(entity.Position.x, entity.Position.y, entity.Position.z), 0); + } + + } + + if (!entity.Instance.empty()) + { + CVector jdir; + switch (entity.Type) + { + case CEntity::Self: + jdir = CVector(-(float)cos(entity.Angle), -(float)sin(entity.Angle), 0.0f); + break; + case CEntity::Other: + jdir = CVector(-(float)cos(entity.Angle), -(float)sin(entity.Angle), 0.0f); + break; + case CEntity::Snowball: + jdir = entity.Trajectory.evalSpeed(LocalTime).normed(); + break; + } + + if (!entity.Skeleton.empty()) + { + entity.Skeleton.setPos(entity.Position); + entity.Skeleton.setRotQuat(jdir); + } + + entity.Instance.setPos(entity.Position); + entity.Instance.setRotQuat(jdir); + } + +// todo sound +// if (entity.Source != NULL) +// entity.Source->setPosition (entity.Position); + + if (!entity.Particule.empty()) + { + entity.Particule.setPos(entity.Position); + } + + if (entity.Type == CEntity::Self) + { + MouseListener->setPosition(entity.Position); + } + } +} + +// Draw entities names up the characters +void renderEntitiesNames () +{ + // Setup the driver in matrix mode + Driver->setMatrixMode3D (Camera); + // Setup the drawing context + TextContext->setHotSpot (UTextContext::MiddleTop); + TextContext->setColor (EntityNameColor); + TextContext->setFontSize ((uint32)EntityNameSize); + // + for (EIT eit = Entities.begin (); eit != Entities.end (); eit++) + { + CEntity &entity = (*eit).second; + if (!entity.Instance.empty() && entity.Type == CEntity::Other) + { + CMatrix mat = Camera.getMatrix(); + mat.setPos(entity.Position + CVector(0.0f, 0.0f, 4.0f)); + mat.scale(10.0f); + TextContext->render3D(mat, entity.Name); + } + } +} + + +// The entities preferences callback +void cbUpdateEntities (CConfigFile::CVar &var) +{ + if (var.Name == "EntityNameColor") EntityNameColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); + else if (var.Name == "EntityNameSize") EntityNameSize = var.asFloat (); + else nlwarning ("Unknown variable update %s", var.Name.c_str()); +} + +void initEntities() +{ + ConfigFile->setCallback ("EntityNameColor", cbUpdateEntities); + ConfigFile->setCallback ("EntityNameSize", cbUpdateEntities); + + cbUpdateEntities (ConfigFile->getVar ("EntityNameColor")); + cbUpdateEntities (ConfigFile->getVar ("EntityNameSize")); +} + +void releaseEntities() +{ + // Remove config file callbacks + ConfigFile->setCallback("EntityNameColor", NULL); + ConfigFile->setCallback("EntityNameSize", NULL); + + // Delete all entities (should already have been called normally) + deleteAllEntities(); +} + + +// Reset the pacs position of an entity, in case pacs went wrong +void resetEntityPosition(uint32 eid) +{ + uint32 sbid = NextEID++; + EIT eit = findEntity (eid); + + CEntity &entity = (*eit).second; + + UGlobalPosition gPos; + // get the global position + gPos = GlobalRetriever->retrievePosition(entity.Position); + // convert it in a vector 3d + entity.Position = GlobalRetriever->getGlobalPosition(gPos); + // get the good z position + gPos.LocalPosition.Estimation.z = 0.0f; + entity.Position.z = GlobalRetriever->getMeanHeight(gPos); + + // snap to the ground + if (entity.VisualCollisionEntity != NULL && !GlobalRetriever->isInterior(gPos)) + entity.VisualCollisionEntity->snapToGround(entity.Position); + + if (entity.MovePrimitive != NULL) + entity.MovePrimitive->setGlobalPosition(CVector(entity.Position.x, entity.Position.y, entity.Position.z), 0); +} + + +void shotSnowball(uint32 sid, uint32 eid, const CVector &start, const CVector &target, float speed, float deflagRadius) +{ + // get direction + CVector direction = (target-start).normed(); + + // create a new snowball entity + addEntity(sid, "", CEntity::Snowball, start, target); + EIT sit = findEntity (sid); + CEntity &snowball = (*sit).second; + + snowball.AutoMove = 1; + snowball.Trajectory.init(start, target, speed, LocalTime + 1.000); + snowball.Instance.hide(); + + EIT eit = findEntity (eid); + CEntity &entity = (*eit).second; + + // end aiming + playAnimation (entity, ThrowSnowball, true); + + if (entity.IsWalking) + { + playAnimation (entity, PrepareWalkAnim, true); + playAnimation (entity, WalkAnim); + } + else + playAnimation (entity, IdleAnim); + +} + + +// +// Commands +// + +NLMISC_COMMAND(remove_entity,"remove a local entity","") +{ + // check args, if there s not the right number of parameter, return bad + if(args.size() != 1) return false; + + uint32 eid = (uint32)atoi(args[0].c_str()); + removeEntity (eid); + + return true; +} + + +NLMISC_COMMAND(add_entity,"add a local entity"," ") +{ + // check args, if there s not the right number of parameter, return bad + if(args.size() != 2) return false; + + uint nb = (uint)atoi(args[0].c_str()); + + for (uint i = 0; i < nb ; i++) + { + uint32 eid = NextEID++; + CVector start(ConfigFile->getVar("StartPoint").asFloat(0), ConfigFile->getVar("StartPoint").asFloat(1), ConfigFile->getVar("StartPoint").asFloat(2)); + addEntity (eid, "Entity"+toString(eid), CEntity::Other, start, start); + EIT eit = findEntity (eid); + (*eit).second.AutoMove = atoi(args[1].c_str()) == 1; + } + + return true; +} + +NLMISC_COMMAND(speed,"set the player speed","[] ") +{ + // check args, if there s not the right number of parameter, return bad + if(args.size() == 1) + { + float speed = min( max( (float)atof(args[0].c_str()), 0.1f ), 200.0f ); // speed range in km/h + if (Self != NULL) + { + MouseListener->setSpeed( speed / 3.6f ); + Self->Speed = speed / 3.6f; + } + } + else if(args.size() == 2) + { + float speed = min( max( (float)atof(args[1].c_str()), 0.1f ), 200.0f ); // speed range in km/h + + uint eid = (uint)atoi(args[0].c_str()); + EIT eit = findEntity (eid); + CEntity &entity = (*eit).second; + + entity.Speed = speed / 3.6f; + if (entity.Type == CEntity::Self) + { + MouseListener->setSpeed(entity.Speed); + } + } + return true; +} + +NLMISC_COMMAND(goto, "go to a given position", " ") +{ + // check args, if there s not the right number of parameter, return bad + if(args.size() != 2) return false; + + if (Self == NULL) return false; + + CEntity &entity = *Self; + + float x, y; + + x = (float)atof(args[0].c_str()); + y = (float)atof(args[1].c_str()); + + // + if (entity.MovePrimitive != NULL && entity.VisualCollisionEntity != NULL) + { + UGlobalPosition gPos; + entity.MovePrimitive->setGlobalPosition(CVectorD(x, y, 0.0f), 0); + // get the global position in pacs coordinates system + entity.MovePrimitive->getGlobalPosition(gPos, 0); + // convert it in a vector 3d + entity.Position = GlobalRetriever->getGlobalPosition(gPos); + // get the good z position + gPos.LocalPosition.Estimation.z = 0.0f; + entity.Position.z = GlobalRetriever->getMeanHeight(gPos); + // snap to the ground + if (!GlobalRetriever->isInterior(gPos)) + entity.VisualCollisionEntity->snapToGround( entity.Position ); + + if (entity.Type == CEntity::Self) + { + MouseListener->setPosition(entity.Position); + } + } + + return true; +} + +NLMISC_COMMAND(entities, "display all entities info", "") +{ + // check args, if there s not the right number of parameter, return bad + if(args.size() != 0) return false; + + for (EIT eit = Entities.begin (); eit != Entities.end (); eit++) + { + CEntity &e = (*eit).second; + log.displayNL("%s %u (k%u) %s %d", (Self==&e)?"*":" ", e.Id, (*eit).first, e.Name.c_str(), e.Type); + } + return true; +} + +NLMISC_COMMAND(test_cls, "test the collision service, disables collision test on self", "") +{ + _TestCLS = !_TestCLS; + return true; +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/entities.h b/code/snowballs2/client/src/entities.h index 602e02775..0ad7819ee 100644 --- a/code/snowballs2/client/src/entities.h +++ b/code/snowballs2/client/src/entities.h @@ -1,213 +1,213 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef ENTITIES_H -#define ENTITIES_H - -// -// Includes -// - -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "physics.h" -#include "animation.h" - -// -// External definitions -// - -namespace NLSOUND -{ - class USource; -} - -namespace NLPACS -{ - class UMovePrimitive; -} - -namespace NL3D -{ - class UVisualCollisionEntity; - class UPlayList; -} - -namespace SBCLIENT { - -// -// External classes -// - -// An entity that will move through the landscape. -// The possible entities are the Self (the player's avatar), the Other and the Snowball -class CEntity -{ -public: - - // Create a default entity - CEntity () : - Id(0xffffffff), Name(""), Angle(0.0f), AuxiliaryAngle(0.0f), InterpolatedAuxiliaryAngle(0.0f), - AutoMove(false), Instance(NULL), Skeleton(NULL), - Particule(NULL), Source(NULL), IsWalking(false), WasWalking(false), IsAiming(false), WasAiming(false), - /*CurrentAnim(NoAnim), */NextEmptySlot(0), PlayList(NULL), BotState(0) - { } - - - // The id of the entity - uint32 Id; - - // The name of the entity - std::string Name; - - // Contain the target position for this entity - NLMISC::CVector ServerPosition; - - // Contain the current position of the entity - NLMISC::CVector Position; - - // The immediate speed of the entity - NLMISC::CVector ImmediateSpeed; - - // The maximum speed of the entity - float Speed, - // The angle of the entity - Angle, - // Various angle controls for the interpolation - AuxiliaryAngle, InterpolatedAuxiliaryAngle; - - // The trajectory (only for snowballs, defined in physics.h) - CTrajectory Trajectory; - - - // The state enum of the entity - enum TState { Appear, Normal, Disappear }; - - // The state of this entity - TState State; - // The date of the beginning of this state - NLMISC::TTime StateStartTime; - - // The type enum of the entity - enum TType { Self, Other, Snowball }; - - // The type of this entity - TType Type; - - // Is it an auto-moving entity - bool AutoMove; - - // The PACS move primitive - NLPACS::UMovePrimitive *MovePrimitive; - // The collision entity (for ground snapping) - NL3D::UVisualCollisionEntity *VisualCollisionEntity; - // The mesh instance associated to this entity - NL3D::UInstance Instance; - // The skeleton binded to the instance - NL3D::USkeleton Skeleton; - // The particle system (for appear and disappear effects) - NL3D::UInstance Particule; - - // The sound source associated to the entity - NLSOUND::USource *Source; - - void setState (TState state); - - bool IsWalking; - bool WasWalking; - bool IsAiming; - bool WasAiming; - - // Playlist linked to this entity -// EAnim CurrentAnim; - uint NextEmptySlot; - NL3D::UPlayList *PlayList; - std::queue AnimQueue; - NL3D::CAnimationTime StartAnimationTime; - - uint BotState; - NLMISC::TLocalTime BotStateStart; -}; - -// -// Enums -// - -// The collision bits used by pacs (dynamic collisions) -enum -{ - SelfCollisionBit = 1, - OtherCollisionBit = 2, - SnowballCollisionBit = 4, - StaticCollisionBit = 8 -}; - -// -// External variables -// - -// The entity representing the player avatar -extern CEntity *Self; - -// The speed of the player -extern float PlayerSpeed; -// The speed of the snowball -extern float SnowballSpeed; - -// The entities storage -extern std::map Entities; -typedef std::map::iterator EIT; - -extern uint32 NextEID; - -// -// External functions -// - -EIT findEntity (uint32 eid, bool needAssert = true); - -void addEntity (uint32 eid, std::string name, CEntity::TType type, const NLMISC::CVector &startPosition, const NLMISC::CVector &serverPosition); -void removeEntity (uint32 eid); - -// when we turn online, we need to clear all offline entities -void removeAllEntitiesExceptUs (); -void deleteAllEntities(); - -void initEntities(); -void updateEntities(); -void releaseEntities(); - -// Reset the pacs position of an entity (in case pacs went wrong) -void resetEntityPosition(uint32 eid); -// Process the event when an entity shoots a snowball -void shotSnowball(uint32 sid, uint32 eid, const NLMISC::CVector &start, const NLMISC::CVector &target, float speed, float deflagRadius); - -void renderEntitiesNames (); - -} /* namespace SBCLIENT */ - -#endif // ENTITIES_H - -/* End of entities.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef ENTITIES_H +#define ENTITIES_H + +// +// Includes +// + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "physics.h" +#include "animation.h" + +// +// External definitions +// + +namespace NLSOUND +{ + class USource; +} + +namespace NLPACS +{ + class UMovePrimitive; +} + +namespace NL3D +{ + class UVisualCollisionEntity; + class UPlayList; +} + +namespace SBCLIENT { + +// +// External classes +// + +// An entity that will move through the landscape. +// The possible entities are the Self (the player's avatar), the Other and the Snowball +class CEntity +{ +public: + + // Create a default entity + CEntity () : + Id(0xffffffff), Name(""), Angle(0.0f), AuxiliaryAngle(0.0f), InterpolatedAuxiliaryAngle(0.0f), + AutoMove(false), Instance(NULL), Skeleton(NULL), + Particule(NULL), Source(NULL), IsWalking(false), WasWalking(false), IsAiming(false), WasAiming(false), + /*CurrentAnim(NoAnim), */NextEmptySlot(0), PlayList(NULL), BotState(0) + { } + + + // The id of the entity + uint32 Id; + + // The name of the entity + std::string Name; + + // Contain the target position for this entity + NLMISC::CVector ServerPosition; + + // Contain the current position of the entity + NLMISC::CVector Position; + + // The immediate speed of the entity + NLMISC::CVector ImmediateSpeed; + + // The maximum speed of the entity + float Speed, + // The angle of the entity + Angle, + // Various angle controls for the interpolation + AuxiliaryAngle, InterpolatedAuxiliaryAngle; + + // The trajectory (only for snowballs, defined in physics.h) + CTrajectory Trajectory; + + + // The state enum of the entity + enum TState { Appear, Normal, Disappear }; + + // The state of this entity + TState State; + // The date of the beginning of this state + NLMISC::TTime StateStartTime; + + // The type enum of the entity + enum TType { Self, Other, Snowball }; + + // The type of this entity + TType Type; + + // Is it an auto-moving entity + bool AutoMove; + + // The PACS move primitive + NLPACS::UMovePrimitive *MovePrimitive; + // The collision entity (for ground snapping) + NL3D::UVisualCollisionEntity *VisualCollisionEntity; + // The mesh instance associated to this entity + NL3D::UInstance Instance; + // The skeleton binded to the instance + NL3D::USkeleton Skeleton; + // The particle system (for appear and disappear effects) + NL3D::UInstance Particule; + + // The sound source associated to the entity + NLSOUND::USource *Source; + + void setState (TState state); + + bool IsWalking; + bool WasWalking; + bool IsAiming; + bool WasAiming; + + // Playlist linked to this entity +// EAnim CurrentAnim; + uint NextEmptySlot; + NL3D::UPlayList *PlayList; + std::queue AnimQueue; + NL3D::CAnimationTime StartAnimationTime; + + uint BotState; + NLMISC::TLocalTime BotStateStart; +}; + +// +// Enums +// + +// The collision bits used by pacs (dynamic collisions) +enum +{ + SelfCollisionBit = 1, + OtherCollisionBit = 2, + SnowballCollisionBit = 4, + StaticCollisionBit = 8 +}; + +// +// External variables +// + +// The entity representing the player avatar +extern CEntity *Self; + +// The speed of the player +extern float PlayerSpeed; +// The speed of the snowball +extern float SnowballSpeed; + +// The entities storage +extern std::map Entities; +typedef std::map::iterator EIT; + +extern uint32 NextEID; + +// +// External functions +// + +EIT findEntity (uint32 eid, bool needAssert = true); + +void addEntity (uint32 eid, std::string name, CEntity::TType type, const NLMISC::CVector &startPosition, const NLMISC::CVector &serverPosition); +void removeEntity (uint32 eid); + +// when we turn online, we need to clear all offline entities +void removeAllEntitiesExceptUs (); +void deleteAllEntities(); + +void initEntities(); +void updateEntities(); +void releaseEntities(); + +// Reset the pacs position of an entity (in case pacs went wrong) +void resetEntityPosition(uint32 eid); +// Process the event when an entity shoots a snowball +void shotSnowball(uint32 sid, uint32 eid, const NLMISC::CVector &start, const NLMISC::CVector &target, float speed, float deflagRadius); + +void renderEntitiesNames (); + +} /* namespace SBCLIENT */ + +#endif // ENTITIES_H + +/* End of entities.h */ diff --git a/code/snowballs2/client/src/game_time.cpp b/code/snowballs2/client/src/game_time.cpp index 5ec0be687..62bfc2b2b 100644 --- a/code/snowballs2/client/src/game_time.cpp +++ b/code/snowballs2/client/src/game_time.cpp @@ -1,115 +1,115 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include -#include "game_time.h" - -// STL includes - -// NeL includes -// #include -#include -#include -#include - -// Project includes -#include "snowballs_client.h" -#include "configuration.h" - -using namespace std; -using namespace NLMISC; -using namespace NL3D; - -namespace SBCLIENT { - -// impl note: at some point animation time can be linked to server as well -// see version of time.cpp in snowballs5 experimental code - -static bool _SkipAnimationOnce; -static NLMISC::TTime _TimeMs; -static CValueSmootherTemplate _FpsSmoother; - -static void cbFpsSmoothing(CConfigFile::CVar &var) -{ - _FpsSmoother.init((uint)var.asInt()); -} - -void CGameTime::init() -{ - _SkipAnimationOnce = true; // since we're loading ... ;) - _TimeMs = NLMISC::CTime::getLocalTime(); - LocalTime = ((TLocalTime)_TimeMs) / 1000.0; - LocalTimeDelta = 0.0; - AnimationTime = 0.0; - AnimationTimeDelta = 0.f; - FramesPerSecond = 0.f; - FramesPerSecondSmooth = 0.f; - CConfiguration::setAndCallback("FpsSmoothing", cbFpsSmoothing); -} - -void CGameTime::release() -{ - // could also call init again here just for fun but nothing useful otherwise - CConfiguration::dropCallback("FpsSmoothing"); - _FpsSmoother.reset(); -} - -void CGameTime::updateTime() -{ - TTime timems = NLMISC::CTime::getLocalTime(); - TTime deltams = timems - _TimeMs; - _TimeMs = timems; - - if (!deltams) // time has not moved - { - // average of previous fps and this fps should be ok - FramesPerSecond *= 3; - - LocalTimeDelta = 0.f; - AnimationTimeDelta = 0.f; - } - else - { - FramesPerSecond = 1000.0f / (float)deltams; - - TLocalTime localTime = ((TLocalTime)timems) / 1000.0; - LocalTimeDelta = localTime - LocalTime; - LocalTime = localTime; - - if (_SkipAnimationOnce) - { - AnimationTimeDelta = 0.f; - _SkipAnimationOnce = false; - } - else - { - AnimationTimeDelta = (TAnimationTime)LocalTimeDelta; - AnimationTime += (TGlobalAnimationTime)LocalTimeDelta; - } - } - - _FpsSmoother.addValue(FramesPerSecond); - FramesPerSecondSmooth = _FpsSmoother.getSmoothValue(); -} - -void CGameTime::skipAnimationOnce() -{ - _SkipAnimationOnce = true; -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include "game_time.h" + +// STL includes + +// NeL includes +// #include +#include +#include +#include + +// Project includes +#include "snowballs_client.h" +#include "configuration.h" + +using namespace std; +using namespace NLMISC; +using namespace NL3D; + +namespace SBCLIENT { + +// impl note: at some point animation time can be linked to server as well +// see version of time.cpp in snowballs5 experimental code + +static bool _SkipAnimationOnce; +static NLMISC::TTime _TimeMs; +static CValueSmootherTemplate _FpsSmoother; + +static void cbFpsSmoothing(CConfigFile::CVar &var) +{ + _FpsSmoother.init((uint)var.asInt()); +} + +void CGameTime::init() +{ + _SkipAnimationOnce = true; // since we're loading ... ;) + _TimeMs = NLMISC::CTime::getLocalTime(); + LocalTime = ((TLocalTime)_TimeMs) / 1000.0; + LocalTimeDelta = 0.0; + AnimationTime = 0.0; + AnimationTimeDelta = 0.f; + FramesPerSecond = 0.f; + FramesPerSecondSmooth = 0.f; + CConfiguration::setAndCallback("FpsSmoothing", cbFpsSmoothing); +} + +void CGameTime::release() +{ + // could also call init again here just for fun but nothing useful otherwise + CConfiguration::dropCallback("FpsSmoothing"); + _FpsSmoother.reset(); +} + +void CGameTime::updateTime() +{ + TTime timems = NLMISC::CTime::getLocalTime(); + TTime deltams = timems - _TimeMs; + _TimeMs = timems; + + if (!deltams) // time has not moved + { + // average of previous fps and this fps should be ok + FramesPerSecond *= 3; + + LocalTimeDelta = 0.f; + AnimationTimeDelta = 0.f; + } + else + { + FramesPerSecond = 1000.0f / (float)deltams; + + TLocalTime localTime = ((TLocalTime)timems) / 1000.0; + LocalTimeDelta = localTime - LocalTime; + LocalTime = localTime; + + if (_SkipAnimationOnce) + { + AnimationTimeDelta = 0.f; + _SkipAnimationOnce = false; + } + else + { + AnimationTimeDelta = (TAnimationTime)LocalTimeDelta; + AnimationTime += (TGlobalAnimationTime)LocalTimeDelta; + } + } + + _FpsSmoother.addValue(FramesPerSecond); + FramesPerSecondSmooth = _FpsSmoother.getSmoothValue(); +} + +void CGameTime::skipAnimationOnce() +{ + _SkipAnimationOnce = true; +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/game_time.h b/code/snowballs2/client/src/game_time.h index fd8b6b802..72a671d43 100644 --- a/code/snowballs2/client/src/game_time.h +++ b/code/snowballs2/client/src/game_time.h @@ -1,53 +1,53 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef SBCLIENT_GAME_TIME_H -#define SBCLIENT_GAME_TIME_H -#include - -// STL includes - -// NeL includes - -// Project includes - -namespace SBCLIENT { - -/** - * \brief CGameTime - * \date 2008-11-26 14:44GMT - * \author Jan Boon (Kaetemi) - * CGameTime - */ -class CGameTime -{ -public: - static void init(); - static void release(); - - static void updateTime(); - - /// Used when loading, this will skip changing animation time on the next update - /// (updates aren't called during loading) - static void skipAnimationOnce(); - -}; /* class CGameTime */ - -} /* namespace SBCLIENT */ - -#endif /* #ifndef SBCLIENT_GAME_TIME_H */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SBCLIENT_GAME_TIME_H +#define SBCLIENT_GAME_TIME_H +#include + +// STL includes + +// NeL includes + +// Project includes + +namespace SBCLIENT { + +/** + * \brief CGameTime + * \date 2008-11-26 14:44GMT + * \author Jan Boon (Kaetemi) + * CGameTime + */ +class CGameTime +{ +public: + static void init(); + static void release(); + + static void updateTime(); + + /// Used when loading, this will skip changing animation time on the next update + /// (updates aren't called during loading) + static void skipAnimationOnce(); + +}; /* class CGameTime */ + +} /* namespace SBCLIENT */ + +#endif /* #ifndef SBCLIENT_GAME_TIME_H */ + +/* end of file */ diff --git a/code/snowballs2/client/src/graph.cpp b/code/snowballs2/client/src/graph.cpp index 886bd04e8..73ac726f5 100644 --- a/code/snowballs2/client/src/graph.cpp +++ b/code/snowballs2/client/src/graph.cpp @@ -1,169 +1,169 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "graph.h" -#include "snowballs_client.h" - -// -// Namespaces -// - -using namespace NLMISC; -using namespace NL3D; -using namespace std; - - -namespace SBCLIENT { - -// -// Classes -// - -void CGraph::render () -{ - // Display the background - uint32 w, h; - Driver->getWindowSize (w, h); - float ScreenWidth = (float) w; - float ScreenHeight = (float) h; - Driver->setMatrixMode2D (CFrustum (0.0f, ScreenWidth, 0.0f, ScreenHeight, 0.0f, 1.0f, false)); - Driver->drawQuad (X, Y, X+Width, Y+Height, BackColor); - - float pos = X+Width-1; - for (deque::reverse_iterator it = Values.rbegin(); it != Values.rend(); it++) - { - float value = (*it) * Height / MaxValue; - if (value > Height) value = Height; - Driver->drawLine (pos, Y, pos, Y+value, CRGBA (255,255,255,BackColor.A)); - pos--; - } - - float value = Peak * Height / MaxValue; - if (value > Height) value = Height; - CRGBA frontCol (min(BackColor.R*2,255),min(BackColor.G*2,255),min(BackColor.B*2,255),min(BackColor.A*2,255)); - Driver->drawLine (X, Y+value, X+Width, Y+value, frontCol); - - TextContext->setHotSpot (UTextContext::MiddleLeft); - TextContext->setColor (frontCol); - TextContext->setFontSize (10); - TextContext->printfAt ((X+Width+2)/ScreenWidth, (Y+value)/ScreenHeight, toString(Peak).c_str()); - - TextContext->setHotSpot (UTextContext::TopLeft); - TextContext->printfAt ((X+1)/ScreenWidth, (Y+Height-1)/ScreenHeight, Name.c_str()); -} - -void CGraph::addOneValue (float value) -{ - Values.push_back (value); - while (Values.size () > Width) - Values.pop_front (); - - if (Values.back() > Peak) - Peak = Values.back(); -} - - -void CGraph::addValue (float value) -{ - TTime currentTime = CTime::getLocalTime (); - - while (currentTime > CurrentQuantumStart + Quantum) - { - CurrentQuantumStart += Quantum; - addOneValue (); - } - - Values.back() += value; - - if (Values.back() > Peak) - Peak = Values.back(); -} - -// -// Variables -// - -CGraph FpsGraph ("fps", 10.0f, 10.0f, 100.0f, 100.0f, CRGBA(128,0,0,128), 1000, 40.0f); -CGraph SpfGraph ("spf", 10.0f, 110.0f, 100.0f, 100.0f, CRGBA(0,128,0,128), 0, 200.0f); - -CGraph DownloadGraph ("download", 10.0f, 260.0f, 100.0f, 100.0f, CRGBA(0,0,128,128), 1000, 1000.0f); -CGraph UploadGraph ("upload", 10.0f, 360.0f, 100.0f, 100.0f, CRGBA(0,128,128,128), 1000, 1000.0f); - -bool ShowGraph; - -// -// Functions -// - -void cbUpdateGraph (CConfigFile::CVar &var) -{ - if (var.Name == "ShowGraph") ShowGraph = var.asInt() == 1; - else nlwarning ("Unknown variable update %s", var.Name.c_str()); -} - -void initGraph () -{ - ConfigFile->setCallback ("ShowGraph", cbUpdateGraph); - - cbUpdateGraph (ConfigFile->getVar ("ShowGraph")); -} - -void updateGraph () -{ - if (!ShowGraph) return; - - FpsGraph.render (); - SpfGraph.render (); - - DownloadGraph.render (); - UploadGraph.render (); -} - -void releaseGraph () -{ - ConfigFile->setCallback("ShowGraph", NULL); -} - -NLMISC_COMMAND(graph,"swith on/off graphs","") -{ - // check args, if there s not the right number of parameter, return bad - if (args.size() != 0) return false; - - ShowGraph = !ShowGraph; - return true; -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "graph.h" +#include "snowballs_client.h" + +// +// Namespaces +// + +using namespace NLMISC; +using namespace NL3D; +using namespace std; + + +namespace SBCLIENT { + +// +// Classes +// + +void CGraph::render () +{ + // Display the background + uint32 w, h; + Driver->getWindowSize (w, h); + float ScreenWidth = (float) w; + float ScreenHeight = (float) h; + Driver->setMatrixMode2D (CFrustum (0.0f, ScreenWidth, 0.0f, ScreenHeight, 0.0f, 1.0f, false)); + Driver->drawQuad (X, Y, X+Width, Y+Height, BackColor); + + float pos = X+Width-1; + for (deque::reverse_iterator it = Values.rbegin(); it != Values.rend(); it++) + { + float value = (*it) * Height / MaxValue; + if (value > Height) value = Height; + Driver->drawLine (pos, Y, pos, Y+value, CRGBA (255,255,255,BackColor.A)); + pos--; + } + + float value = Peak * Height / MaxValue; + if (value > Height) value = Height; + CRGBA frontCol (min(BackColor.R*2,255),min(BackColor.G*2,255),min(BackColor.B*2,255),min(BackColor.A*2,255)); + Driver->drawLine (X, Y+value, X+Width, Y+value, frontCol); + + TextContext->setHotSpot (UTextContext::MiddleLeft); + TextContext->setColor (frontCol); + TextContext->setFontSize (10); + TextContext->printfAt ((X+Width+2)/ScreenWidth, (Y+value)/ScreenHeight, toString(Peak).c_str()); + + TextContext->setHotSpot (UTextContext::TopLeft); + TextContext->printfAt ((X+1)/ScreenWidth, (Y+Height-1)/ScreenHeight, Name.c_str()); +} + +void CGraph::addOneValue (float value) +{ + Values.push_back (value); + while (Values.size () > Width) + Values.pop_front (); + + if (Values.back() > Peak) + Peak = Values.back(); +} + + +void CGraph::addValue (float value) +{ + TTime currentTime = CTime::getLocalTime (); + + while (currentTime > CurrentQuantumStart + Quantum) + { + CurrentQuantumStart += Quantum; + addOneValue (); + } + + Values.back() += value; + + if (Values.back() > Peak) + Peak = Values.back(); +} + +// +// Variables +// + +CGraph FpsGraph ("fps", 10.0f, 10.0f, 100.0f, 100.0f, CRGBA(128,0,0,128), 1000, 40.0f); +CGraph SpfGraph ("spf", 10.0f, 110.0f, 100.0f, 100.0f, CRGBA(0,128,0,128), 0, 200.0f); + +CGraph DownloadGraph ("download", 10.0f, 260.0f, 100.0f, 100.0f, CRGBA(0,0,128,128), 1000, 1000.0f); +CGraph UploadGraph ("upload", 10.0f, 360.0f, 100.0f, 100.0f, CRGBA(0,128,128,128), 1000, 1000.0f); + +bool ShowGraph; + +// +// Functions +// + +void cbUpdateGraph (CConfigFile::CVar &var) +{ + if (var.Name == "ShowGraph") ShowGraph = var.asInt() == 1; + else nlwarning ("Unknown variable update %s", var.Name.c_str()); +} + +void initGraph () +{ + ConfigFile->setCallback ("ShowGraph", cbUpdateGraph); + + cbUpdateGraph (ConfigFile->getVar ("ShowGraph")); +} + +void updateGraph () +{ + if (!ShowGraph) return; + + FpsGraph.render (); + SpfGraph.render (); + + DownloadGraph.render (); + UploadGraph.render (); +} + +void releaseGraph () +{ + ConfigFile->setCallback("ShowGraph", NULL); +} + +NLMISC_COMMAND(graph,"swith on/off graphs","") +{ + // check args, if there s not the right number of parameter, return bad + if (args.size() != 0) return false; + + ShowGraph = !ShowGraph; + return true; +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/graph.h b/code/snowballs2/client/src/graph.h index 3eb09bd59..19f6045c0 100644 --- a/code/snowballs2/client/src/graph.h +++ b/code/snowballs2/client/src/graph.h @@ -1,85 +1,85 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef GRAPH_H -#define GRAPH_H - -// -// Includes -// - -#include -#include - -#include -#include - -namespace SBCLIENT { - -// -// External classes -// - -class CGraph -{ -public: - std::string Name; - float X, Y, Width, Height; - NLMISC::CRGBA BackColor; - float MaxValue; - float Peak; - - std::deque Values; - - NLMISC::TTime Quantum; - - NLMISC::TTime CurrentQuantumStart; - - CGraph (std::string name, float x, float y, float width, float height, NLMISC::CRGBA backColor, NLMISC::TTime quantum, float maxValue) - : Name(name), X(x), Y(y), Width(width), Height(height), BackColor(backColor), MaxValue(maxValue), - Peak(0.0f), Quantum(quantum), CurrentQuantumStart(NLMISC::CTime::getLocalTime()) - { - } - - void render (); - void addOneValue (float value = 0.0f); - void addValue (float value); -}; - -// -// External variables -// - -extern CGraph FpsGraph; -extern CGraph SpfGraph; -extern CGraph DownloadGraph; -extern CGraph UploadGraph; - -// -// External functions -// - -void initGraph (); -void updateGraph (); -void releaseGraph (); - -} /* namespace SBCLIENT */ - -#endif // GRAPH_H - -/* End of graph.h */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef GRAPH_H +#define GRAPH_H + +// +// Includes +// + +#include +#include + +#include +#include + +namespace SBCLIENT { + +// +// External classes +// + +class CGraph +{ +public: + std::string Name; + float X, Y, Width, Height; + NLMISC::CRGBA BackColor; + float MaxValue; + float Peak; + + std::deque Values; + + NLMISC::TTime Quantum; + + NLMISC::TTime CurrentQuantumStart; + + CGraph (std::string name, float x, float y, float width, float height, NLMISC::CRGBA backColor, NLMISC::TTime quantum, float maxValue) + : Name(name), X(x), Y(y), Width(width), Height(height), BackColor(backColor), MaxValue(maxValue), + Peak(0.0f), Quantum(quantum), CurrentQuantumStart(NLMISC::CTime::getLocalTime()) + { + } + + void render (); + void addOneValue (float value = 0.0f); + void addValue (float value); +}; + +// +// External variables +// + +extern CGraph FpsGraph; +extern CGraph SpfGraph; +extern CGraph DownloadGraph; +extern CGraph UploadGraph; + +// +// External functions +// + +void initGraph (); +void updateGraph (); +void releaseGraph (); + +} /* namespace SBCLIENT */ + +#endif // GRAPH_H + +/* End of graph.h */ + +/* end of file */ diff --git a/code/snowballs2/client/src/interface.cpp b/code/snowballs2/client/src/interface.cpp index b8acd33f0..7f66c18d2 100644 --- a/code/snowballs2/client/src/interface.cpp +++ b/code/snowballs2/client/src/interface.cpp @@ -1,274 +1,274 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "snowballs_client.h" -#include "interface.h" - -// -// Namespaces -// - -using namespace std; -using namespace NLMISC; -using namespace NL3D; - -namespace SBCLIENT { - -// -// Variables -// - -static string QueryString, AnswerString; -static float DisplayWidth; -static float DisplayHeight, nbLines; -static CRGBA DisplayColor; - -static sint Prompt; - -static uint FontSize = 20; - -// -// Functions -// - -// Class that handle the keyboard input when an interface is displayed (login request for example) -class CInterfaceListener : public IEventListener -{ - virtual void operator() ( const CEvent& event ) - { - // ignore keys if interface is not open - if (!interfaceOpen ()) return; - - CEventChar &ec = (CEventChar&)event; - - // prompt = 2 then we wait a any user key - if (Prompt == 2) - { - QueryString = ""; - AnswerString = ""; - _Line = ""; - return; - } - - switch ( ec.Char ) - { - case 13 : // RETURN : Send the chat message - - if (_Line.size() == 0) - break; - - QueryString = ""; - AnswerString = _Line; - - _LastCommand = _Line; - _Line = ""; - _MaxWidthReached = false; - break; - - case 8 : // BACKSPACE - if ( _Line.size() != 0 ) - { - _Line.erase( _Line.end()-1 ); - // _MaxWidthReached = false; // no need - } - break; - - case 27 : // ESCAPE - QueryString = ""; - AnswerString = ""; - _LastCommand = _Line; - _Line = ""; - _MaxWidthReached = false; - break; - - default: - - if ( ! _MaxWidthReached ) - { - _Line += (char)ec.Char; - } - } - } - -public: - CInterfaceListener() : _MaxWidthReached( false ) - {} - - const string& line() const - { - return _Line; - } - - void setLine(const string &str) { _Line = str; } - - void setMaxWidthReached( bool b ) - { - _MaxWidthReached = b; - } - -private: - string _Line; - bool _MaxWidthReached; - string _LastCommand; -}; - -// Instance of the listener -static CInterfaceListener InterfaceListener; -static UMaterial InterfaceMaterial = NULL; - - -void initInterface() -{ - // Add the keyboard listener in the event server - Driver->EventServer.addListener (EventCharId, &InterfaceListener); - - InterfaceMaterial = Driver->createMaterial(); - InterfaceMaterial.initUnlit(); - InterfaceMaterial.setBlendFunc(UMaterial::srcalpha, UMaterial::invsrcalpha); - InterfaceMaterial.setBlend(true); -} - -void updateInterface() -{ - if (QueryString.empty()) return; - - // Draw background - Driver->setMatrixMode2D11 (); - InterfaceMaterial.setColor(DisplayColor); - CQuad quad; - quad.V0.set(0.5f-DisplayWidth/2.0f, 0.5f+DisplayHeight/2.0f, 0); - quad.V1.set(0.5f+DisplayWidth/2.0f, 0.5f+DisplayHeight/2.0f, 0); - quad.V2.set(0.5f+DisplayWidth/2.0f, 0.5f-DisplayHeight/2.0f, 0); - quad.V3.set(0.5f-DisplayWidth/2.0f, 0.5f-DisplayHeight/2.0f, 0); - Driver->drawQuad(quad, InterfaceMaterial); - //Driver->drawQuad (0.5f-DisplayWidth/2.0f, 0.5f-DisplayHeight/2.0f, 0.5f+DisplayWidth/2.0f, 0.5f+DisplayHeight/2.0f, DisplayColor); - - // Set the text context - TextContext->setHotSpot (UTextContext::MiddleMiddle); - TextContext->setColor (CRGBA (255,255,255,255)); - TextContext->setFontSize (FontSize); - - // Display the text - string str; - float y = (nbLines * FontSize / 2.0f) / 600.0f; - - for (uint i = 0; i < QueryString.size (); i++) - { - if (QueryString[i] == '\n') - { - TextContext->printfAt (0.5f, 0.5f+y, str.c_str()); - str = ""; - y -= FontSize / 600.0f; - } - else - { - str += QueryString[i]; - } - } - TextContext->printfAt (0.5f, 0.5f+y, str.c_str()); - - // Display the user input line - y-= (2.0f * FontSize) / 600.0f; - string str2; - switch (Prompt) - { - case 0: - str2 = InterfaceListener.line(); - str2 += "_"; - break; - case 1: - str2.resize (InterfaceListener.line().size (), '*'); - str2 += "_"; - break; - case 2: - str2 = ""; - break; - } - TextContext->printfAt (0.5f, 0.5f+y, str2.c_str()); -} - -void releaseInterface() -{ - // Delete the material - Driver->deleteMaterial(InterfaceMaterial); - - // Remove the keyboard listener from the server - Driver->EventServer.removeListener (EventCharId, &InterfaceListener); -} - -void askString (const string &queryString, const string &defaultString, sint prompt, const CRGBA &color) -{ - nldebug("called askString"); -nlinfo(queryString.c_str()); - QueryString = queryString; - - if (prompt == 2) - QueryString += "\n\n(Press any key to continue)"; - else - QueryString += "\n\n(Press enter to validate and ESC to cancel)"; - - nbLines = 1; - for (uint i = 0; i < QueryString.size (); i++) - { - if (QueryString[i] == '\n') nbLines++; - } - - DisplayWidth = float(queryString.size () * FontSize) / 600.0f; - DisplayHeight = float((nbLines + 4) * FontSize) / 600.0f; - DisplayColor = color; - - InterfaceListener.setLine (defaultString); - Prompt = prompt; -} - -bool haveAnswer (string &answer) -{ - bool haveIt = !AnswerString.empty(); - if (haveIt) - { - answer = AnswerString; - AnswerString = ""; - } - return haveIt; -} - -bool interfaceOpen () -{ - return !QueryString.empty(); -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "snowballs_client.h" +#include "interface.h" + +// +// Namespaces +// + +using namespace std; +using namespace NLMISC; +using namespace NL3D; + +namespace SBCLIENT { + +// +// Variables +// + +static string QueryString, AnswerString; +static float DisplayWidth; +static float DisplayHeight, nbLines; +static CRGBA DisplayColor; + +static sint Prompt; + +static uint FontSize = 20; + +// +// Functions +// + +// Class that handle the keyboard input when an interface is displayed (login request for example) +class CInterfaceListener : public IEventListener +{ + virtual void operator() ( const CEvent& event ) + { + // ignore keys if interface is not open + if (!interfaceOpen ()) return; + + CEventChar &ec = (CEventChar&)event; + + // prompt = 2 then we wait a any user key + if (Prompt == 2) + { + QueryString = ""; + AnswerString = ""; + _Line = ""; + return; + } + + switch ( ec.Char ) + { + case 13 : // RETURN : Send the chat message + + if (_Line.size() == 0) + break; + + QueryString = ""; + AnswerString = _Line; + + _LastCommand = _Line; + _Line = ""; + _MaxWidthReached = false; + break; + + case 8 : // BACKSPACE + if ( _Line.size() != 0 ) + { + _Line.erase( _Line.end()-1 ); + // _MaxWidthReached = false; // no need + } + break; + + case 27 : // ESCAPE + QueryString = ""; + AnswerString = ""; + _LastCommand = _Line; + _Line = ""; + _MaxWidthReached = false; + break; + + default: + + if ( ! _MaxWidthReached ) + { + _Line += (char)ec.Char; + } + } + } + +public: + CInterfaceListener() : _MaxWidthReached( false ) + {} + + const string& line() const + { + return _Line; + } + + void setLine(const string &str) { _Line = str; } + + void setMaxWidthReached( bool b ) + { + _MaxWidthReached = b; + } + +private: + string _Line; + bool _MaxWidthReached; + string _LastCommand; +}; + +// Instance of the listener +static CInterfaceListener InterfaceListener; +static UMaterial InterfaceMaterial = NULL; + + +void initInterface() +{ + // Add the keyboard listener in the event server + Driver->EventServer.addListener (EventCharId, &InterfaceListener); + + InterfaceMaterial = Driver->createMaterial(); + InterfaceMaterial.initUnlit(); + InterfaceMaterial.setBlendFunc(UMaterial::srcalpha, UMaterial::invsrcalpha); + InterfaceMaterial.setBlend(true); +} + +void updateInterface() +{ + if (QueryString.empty()) return; + + // Draw background + Driver->setMatrixMode2D11 (); + InterfaceMaterial.setColor(DisplayColor); + CQuad quad; + quad.V0.set(0.5f-DisplayWidth/2.0f, 0.5f+DisplayHeight/2.0f, 0); + quad.V1.set(0.5f+DisplayWidth/2.0f, 0.5f+DisplayHeight/2.0f, 0); + quad.V2.set(0.5f+DisplayWidth/2.0f, 0.5f-DisplayHeight/2.0f, 0); + quad.V3.set(0.5f-DisplayWidth/2.0f, 0.5f-DisplayHeight/2.0f, 0); + Driver->drawQuad(quad, InterfaceMaterial); + //Driver->drawQuad (0.5f-DisplayWidth/2.0f, 0.5f-DisplayHeight/2.0f, 0.5f+DisplayWidth/2.0f, 0.5f+DisplayHeight/2.0f, DisplayColor); + + // Set the text context + TextContext->setHotSpot (UTextContext::MiddleMiddle); + TextContext->setColor (CRGBA (255,255,255,255)); + TextContext->setFontSize (FontSize); + + // Display the text + string str; + float y = (nbLines * FontSize / 2.0f) / 600.0f; + + for (uint i = 0; i < QueryString.size (); i++) + { + if (QueryString[i] == '\n') + { + TextContext->printfAt (0.5f, 0.5f+y, str.c_str()); + str = ""; + y -= FontSize / 600.0f; + } + else + { + str += QueryString[i]; + } + } + TextContext->printfAt (0.5f, 0.5f+y, str.c_str()); + + // Display the user input line + y-= (2.0f * FontSize) / 600.0f; + string str2; + switch (Prompt) + { + case 0: + str2 = InterfaceListener.line(); + str2 += "_"; + break; + case 1: + str2.resize (InterfaceListener.line().size (), '*'); + str2 += "_"; + break; + case 2: + str2 = ""; + break; + } + TextContext->printfAt (0.5f, 0.5f+y, str2.c_str()); +} + +void releaseInterface() +{ + // Delete the material + Driver->deleteMaterial(InterfaceMaterial); + + // Remove the keyboard listener from the server + Driver->EventServer.removeListener (EventCharId, &InterfaceListener); +} + +void askString (const string &queryString, const string &defaultString, sint prompt, const CRGBA &color) +{ + nldebug("called askString"); +nlinfo(queryString.c_str()); + QueryString = queryString; + + if (prompt == 2) + QueryString += "\n\n(Press any key to continue)"; + else + QueryString += "\n\n(Press enter to validate and ESC to cancel)"; + + nbLines = 1; + for (uint i = 0; i < QueryString.size (); i++) + { + if (QueryString[i] == '\n') nbLines++; + } + + DisplayWidth = float(queryString.size () * FontSize) / 600.0f; + DisplayHeight = float((nbLines + 4) * FontSize) / 600.0f; + DisplayColor = color; + + InterfaceListener.setLine (defaultString); + Prompt = prompt; +} + +bool haveAnswer (string &answer) +{ + bool haveIt = !AnswerString.empty(); + if (haveIt) + { + answer = AnswerString; + AnswerString = ""; + } + return haveIt; +} + +bool interfaceOpen () +{ + return !QueryString.empty(); +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/interface.h b/code/snowballs2/client/src/interface.h index 708c8c15a..406279ad2 100644 --- a/code/snowballs2/client/src/interface.h +++ b/code/snowballs2/client/src/interface.h @@ -1,55 +1,55 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef INTERFACE_H -#define INTERFACE_H - -// -// Includes -// - -#include - -#include - -namespace SBCLIENT { - -// -// External functions -// - -void initInterface (); -void updateInterface (); -void releaseInterface (); - -// Display the interface with a string and waiting a user event -// queryString -> the string that will be display to the user -// defaultString -> default prompt string -// prompt -> set the user prompt format (0=normal, 1=with_star 2=no_prompt) -// color -> the background color -void askString (const std::string &queryString, const std::string &defaultString="", sint prompt=0, const NLMISC::CRGBA &color=NLMISC::CRGBA(0,0,64,128)); - -// Return true if the answer have answered with the user answer in answer string -bool haveAnswer (std::string &answer); - -// Return true if the interface is open -bool interfaceOpen (); - -} /* namespace SBCLIENT */ - -#endif // INTERFACE_H - -/* End of interface.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef INTERFACE_H +#define INTERFACE_H + +// +// Includes +// + +#include + +#include + +namespace SBCLIENT { + +// +// External functions +// + +void initInterface (); +void updateInterface (); +void releaseInterface (); + +// Display the interface with a string and waiting a user event +// queryString -> the string that will be display to the user +// defaultString -> default prompt string +// prompt -> set the user prompt format (0=normal, 1=with_star 2=no_prompt) +// color -> the background color +void askString (const std::string &queryString, const std::string &defaultString="", sint prompt=0, const NLMISC::CRGBA &color=NLMISC::CRGBA(0,0,64,128)); + +// Return true if the answer have answered with the user answer in answer string +bool haveAnswer (std::string &answer); + +// Return true if the interface is open +bool interfaceOpen (); + +} /* namespace SBCLIENT */ + +#endif // INTERFACE_H + +/* End of interface.h */ diff --git a/code/snowballs2/client/src/internationalization.cpp b/code/snowballs2/client/src/internationalization.cpp index 8dcb373b5..de7bddfcc 100644 --- a/code/snowballs2/client/src/internationalization.cpp +++ b/code/snowballs2/client/src/internationalization.cpp @@ -1,118 +1,118 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include -#include "internationalization.h" - -// STL includes - -// NeL includes -// #include -#include - -// Project includes -#include "snowballs_client.h" -#include "snowballs_config.h" -#include "configuration.h" - -using namespace std; -using namespace NLMISC; - -namespace SBCLIENT { - -class _CI18NLoadProxy : public CI18N::ILoadProxy -{ -public: - _CI18NLoadProxy() { } - virtual ~_CI18NLoadProxy() { } - virtual void loadStringFile(const std::string &filename, ucstring &text) - { - CI18N::readTextFile(filename, text); - text += ucstring("\n" -#if defined (NL_DEBUG) -# if defined (NL_DEBUG_FAST) - "COMPILE_MODE [NL_DEBUG (NL_DEBUG_FAST)]\n" -# elif defined (NL_DEBUG_INSTRUMENT) - "COMPILE_MODE [NL_DEBUG (NL_DEBUG_INSTRUMENT)]\n" -# else - "COMPILE_MODE [NL_DEBUG]\n" -# endif -#elif defined (NL_RELEASE_DEBUG) - "COMPILE_MODE [NL_RELEASE_DEBUG]\n" -#elif defined (NL_RELEASE) -# if defined (NL_NO_DEBUG) - "COMPILE_MODE [NL_RELEASE (NL_NO_DEBUG)]\n" -# else - "COMPILE_MODE [NL_RELEASE]\n" -# endif -#endif -#if FINAL_VERSION - "RELEASE_TYPE [FINAL_VERSION]\n" -#else - "RELEASE_TYPE [DEVELOPER_VERSION]\n" -#endif - "VERSION_NUMBER [" SBCLIENT_VERSION "]\n"); - } -}; - -static _CI18NLoadProxy _I18NLoadProxy; -static std::vector _Callbacks; - -void CInternationalization::enableCallback(void (*cb)()) -{ - _Callbacks.push_back(cb); -} - -void CInternationalization::disableCallback(void (*cb)()) -{ - std::vector::iterator it(_Callbacks.begin()), end(_Callbacks.end()); - for (; it != end; ++it) if (*it == cb) { _Callbacks.erase(it); return; } - nlassert(false); -} - -static void cbLanguageCode(CConfigFile::CVar &var) -{ - CI18N::load(var.asString()); - std::vector::iterator it(_Callbacks.begin()), end(_Callbacks.end()); - for (; it != end; ++it) (*it)(); -} - -void CInternationalization::init() -{ - // check stuff we need - nlassert(ConfigFile); - - // set the load proxy - nlassert(!_Callbacks.size()); - CI18N::setLoadProxy(&_I18NLoadProxy); - - // set the language code - CConfiguration::setAndCallback("LanguageCode", cbLanguageCode); -} - -void CInternationalization::release() -{ - // i18n itself cannot be released, but is 'ok' since static - CConfiguration::dropCallback("LanguageCode"); - - // drop the load proxy - CI18N::setLoadProxy(NULL); - nlassert(!_Callbacks.size()); -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include "internationalization.h" + +// STL includes + +// NeL includes +// #include +#include + +// Project includes +#include "snowballs_client.h" +#include "snowballs_config.h" +#include "configuration.h" + +using namespace std; +using namespace NLMISC; + +namespace SBCLIENT { + +class _CI18NLoadProxy : public CI18N::ILoadProxy +{ +public: + _CI18NLoadProxy() { } + virtual ~_CI18NLoadProxy() { } + virtual void loadStringFile(const std::string &filename, ucstring &text) + { + CI18N::readTextFile(filename, text); + text += ucstring("\n" +#if defined (NL_DEBUG) +# if defined (NL_DEBUG_FAST) + "COMPILE_MODE [NL_DEBUG (NL_DEBUG_FAST)]\n" +# elif defined (NL_DEBUG_INSTRUMENT) + "COMPILE_MODE [NL_DEBUG (NL_DEBUG_INSTRUMENT)]\n" +# else + "COMPILE_MODE [NL_DEBUG]\n" +# endif +#elif defined (NL_RELEASE_DEBUG) + "COMPILE_MODE [NL_RELEASE_DEBUG]\n" +#elif defined (NL_RELEASE) +# if defined (NL_NO_DEBUG) + "COMPILE_MODE [NL_RELEASE (NL_NO_DEBUG)]\n" +# else + "COMPILE_MODE [NL_RELEASE]\n" +# endif +#endif +#if FINAL_VERSION + "RELEASE_TYPE [FINAL_VERSION]\n" +#else + "RELEASE_TYPE [DEVELOPER_VERSION]\n" +#endif + "VERSION_NUMBER [" SBCLIENT_VERSION "]\n"); + } +}; + +static _CI18NLoadProxy _I18NLoadProxy; +static std::vector _Callbacks; + +void CInternationalization::enableCallback(void (*cb)()) +{ + _Callbacks.push_back(cb); +} + +void CInternationalization::disableCallback(void (*cb)()) +{ + std::vector::iterator it(_Callbacks.begin()), end(_Callbacks.end()); + for (; it != end; ++it) if (*it == cb) { _Callbacks.erase(it); return; } + nlassert(false); +} + +static void cbLanguageCode(CConfigFile::CVar &var) +{ + CI18N::load(var.asString()); + std::vector::iterator it(_Callbacks.begin()), end(_Callbacks.end()); + for (; it != end; ++it) (*it)(); +} + +void CInternationalization::init() +{ + // check stuff we need + nlassert(ConfigFile); + + // set the load proxy + nlassert(!_Callbacks.size()); + CI18N::setLoadProxy(&_I18NLoadProxy); + + // set the language code + CConfiguration::setAndCallback("LanguageCode", cbLanguageCode); +} + +void CInternationalization::release() +{ + // i18n itself cannot be released, but is 'ok' since static + CConfiguration::dropCallback("LanguageCode"); + + // drop the load proxy + CI18N::setLoadProxy(NULL); + nlassert(!_Callbacks.size()); +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/internationalization.h b/code/snowballs2/client/src/internationalization.h index e131978aa..adc50c2a4 100644 --- a/code/snowballs2/client/src/internationalization.h +++ b/code/snowballs2/client/src/internationalization.h @@ -1,50 +1,50 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef SBCLIENT_INTERNATIONALIZATION_H -#define SBCLIENT_INTERNATIONALIZATION_H -#include - -// STL includes - -// NeL includes - -// Project includes - -namespace SBCLIENT { - -/** - * \brief CInternationalization - * \date 2008-11-07 16:59GMT - * \author Jan Boon (Kaetemi) - * CInternationalization - */ -class CInternationalization -{ -public: - static void init(); - static void release(); - - static void enableCallback(void (*cb)()); - static void disableCallback(void (*cb)()); - -}; /* class CInternationalization */ - -} /* namespace SBCLIENT */ - -#endif /* #ifndef SBCLIENT_INTERNATIONALIZATION_H */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SBCLIENT_INTERNATIONALIZATION_H +#define SBCLIENT_INTERNATIONALIZATION_H +#include + +// STL includes + +// NeL includes + +// Project includes + +namespace SBCLIENT { + +/** + * \brief CInternationalization + * \date 2008-11-07 16:59GMT + * \author Jan Boon (Kaetemi) + * CInternationalization + */ +class CInternationalization +{ +public: + static void init(); + static void release(); + + static void enableCallback(void (*cb)()); + static void disableCallback(void (*cb)()); + +}; /* class CInternationalization */ + +} /* namespace SBCLIENT */ + +#endif /* #ifndef SBCLIENT_INTERNATIONALIZATION_H */ + +/* end of file */ diff --git a/code/snowballs2/client/src/landscape.cpp b/code/snowballs2/client/src/landscape.cpp index d7944218c..14aba0fb7 100644 --- a/code/snowballs2/client/src/landscape.cpp +++ b/code/snowballs2/client/src/landscape.cpp @@ -1,492 +1,492 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include "nel/misc/types_nl.h" - -#include -#include -#include - -#include "nel/misc/variable.h" -#include "nel/misc/command.h" -#include "nel/misc/variable.h" -#include "nel/misc/debug.h" -#include "nel/misc/path.h" -#include "nel/misc/i18n.h" -#include "nel/misc/config_file.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "snowballs_client.h" -#include "pacs.h" -#include "commands.h" -#include "mouse_listener.h" -#include "physics.h" -#include "configuration.h" -#include "entities.h" - -// -// Namespaces -// - -using namespace std; -using namespace NLMISC; -using namespace NL3D; - -// -// Variables -// - - -namespace SBCLIENT { - -/******************************************************************* - * GLOBALS * - *******************************************************************/ - -vector InstanceGroups; -NLMISC::CVector SunDirection; - -/******************************************************************* - * LANDSCAPE * - *******************************************************************/ - -static UVisualCollisionEntity *_AimingEntity = NULL; -static ULight *_Sun = NULL; - -// -// Functions -// - -void cbUpdateLandscape (CConfigFile::CVar &var) -{ - // -- -- split this whole thing up, lol - - if (var.Name == "FogStart") - Driver->setupFog (var.asFloat (), - ConfigFile->getVar ("FogEnd").asFloat (), - CRGBA(ConfigFile->getVar ("FogColor").asInt (0), - ConfigFile->getVar ("FogColor").asInt (1), - ConfigFile->getVar ("FogColor").asInt (2))); - else if (var.Name == "FogEnd") - Driver->setupFog (ConfigFile->getVar ("FogStart").asFloat (), - var.asFloat (), - CRGBA(ConfigFile->getVar ("FogColor").asInt (0), - ConfigFile->getVar ("FogColor").asInt (1), - ConfigFile->getVar ("FogColor").asInt (2))); - else if (var.Name == "FogColor") - Driver->setupFog( - ConfigFile->getVar ("FogStart").asFloat (), - ConfigFile->getVar ("FogEnd").asFloat (), - CRGBA(var.asInt (0), var.asInt (1), var.asInt (2))); - else if (var.Name == "FogEnable") - { - Driver->enableFog(var.asBool()); - Driver->setupFog( - ConfigFile->getVar("FogStart").asFloat(), - ConfigFile->getVar("FogEnd").asFloat(), - CRGBA(ConfigFile->getVar("FogColor").asInt(0), - ConfigFile->getVar ("FogColor").asInt(1), - ConfigFile->getVar ("FogColor").asInt(2))); - } - else if (var.Name == "SunAmbientColor") - { - _Sun->setAmbiant (CRGBA (var.asInt(0), var.asInt(1), var.asInt(2))); - Driver->setLight (0, *_Sun); - } - else if (var.Name == "SunDiffuseColor") - { - _Sun->setDiffuse (CRGBA (var.asInt(0), var.asInt(1), var.asInt(2))); - Driver->setLight (0, *_Sun); - } - else if (var.Name == "SunSpecularColor") - { - _Sun->setSpecular (CRGBA (var.asInt(0), var.asInt(1), var.asInt(2))); - Driver->setLight (0, *_Sun); - } - else if (var.Name == "SunDirection") - { - SunDirection.set (var.asFloat(0), var.asFloat(1), var.asFloat(2)); - _Sun->setDirection (SunDirection); - Driver->setLight (0, *_Sun); - } - else nlwarning ("Unknown variable update %s", var.Name.c_str()); -} - -static float _LandscapeVision; -static float _LandscapeVisionInitial; - -static void cbMoreLandscapeStuff(CConfigFile::CVar &var) -{ - if (var.Name == "LandscapeTileNear") - Landscape->setTileNear(var.asFloat()); - - else if (var.Name == "LandscapeThreshold") - Landscape->setThreshold(var.asFloat()); - - else if (var.Name == "LandscapeVision") - _LandscapeVision = var.asFloat(); - - else if (var.Name == "LandscapeVisionInitial") - _LandscapeVisionInitial = var.asFloat(); - - else if (var.Name == "LandscapeReceiveShadowMap") - Landscape->enableReceiveShadowMap(var.asBool()); - - else nlwarning("Unknown variable update %s", var.Name.c_str()); -} - -void initLight() -{ - // -- -- sun or whatever light, simple use, doesn't need class yet - - _Sun = ULight::createLight(); - nlassert(_Sun); - _Sun->setMode(ULight::DirectionalLight); - Driver->enableLight(0); - - ConfigFile->setCallback("SunAmbientColor", cbUpdateLandscape); - ConfigFile->setCallback("SunDiffuseColor", cbUpdateLandscape); - ConfigFile->setCallback("SunSpecularColor", cbUpdateLandscape); - ConfigFile->setCallback("SunDirection", cbUpdateLandscape); - - cbUpdateLandscape(ConfigFile->getVar("SunAmbientColor")); - cbUpdateLandscape(ConfigFile->getVar("SunDiffuseColor")); - cbUpdateLandscape(ConfigFile->getVar("SunSpecularColor")); - cbUpdateLandscape(ConfigFile->getVar("SunDirection")); -} - -void releaseLight() -{ - // -- -- just data - - ConfigFile->setCallback("SunAmbientColor", NULL); - ConfigFile->setCallback("SunDiffuseColor", NULL); - ConfigFile->setCallback("SunSpecularColor", NULL); - ConfigFile->setCallback("SunDirection", NULL); - - delete _Sun; _Sun = NULL; -} - -void initLandscape() -{ - - - - ConfigFile->setCallback ("FogStart", cbUpdateLandscape); - ConfigFile->setCallback ("FogEnd", cbUpdateLandscape); - ConfigFile->setCallback ("FogColor", cbUpdateLandscape); - ConfigFile->setCallback ("FogEnable", cbUpdateLandscape); - - cbUpdateLandscape (ConfigFile->getVar ("FogStart")); - cbUpdateLandscape (ConfigFile->getVar ("FogEnd")); - cbUpdateLandscape (ConfigFile->getVar ("FogColor")); - cbUpdateLandscape (ConfigFile->getVar ("FogEnable")); - - - - - - // -- -- start of init for "instance groups loaded from config" - - CConfigFile::CVar igv = ConfigFile->getVar("InstanceGroups"); - for (uint32 i = 0; i < igv.size (); i++) - { - UInstanceGroup *inst = UInstanceGroup::createInstanceGroup (igv.asString (i)); - if (inst == NULL) - { - nlwarning ("Instance group '%s' not found", igv.asString (i).c_str ()); - } - else - { - inst->addToScene (*Scene); - InstanceGroups.push_back (inst); - } - } - - - - // -- -- start of init for "landscape around camera that gets data from config" - - // create the landscape - nlassert(!Landscape); - Landscape = Scene->createLandscape(); - - // load the bank files - Landscape->loadBankFiles( - CPath::lookup(ConfigFile->getVar("LandscapeBankName").asString()), - CPath::lookup(ConfigFile->getVar("LandscapeFarBankName").asString())); - Landscape->invalidateAllTiles(); - - // -- -- this doesn't do anything useful - //// setup the zone path - //Landscape->setZonePath(ConfigFile->getVar("DataPath").asString() + "zones/"); - - // -- -- do this when character appears or does far teleport - //// and eventually, load the zones around the starting point. - //Landscape->loadAllZonesAround (CVector(ConfigFile->getVar("StartPoint").asFloat(0), - // ConfigFile->getVar("StartPoint").asFloat(1), - // ConfigFile->getVar("StartPoint").asFloat(2)), - // 1000.0f); - - // color of the landscape shadow - CRGBA diffuse( - ConfigFile->getVar("LandscapeDiffuseColor").asInt(0), - ConfigFile->getVar("LandscapeDiffuseColor").asInt(1), - ConfigFile->getVar("LandscapeDiffuseColor").asInt(2)); - CRGBA ambient( - ConfigFile->getVar("LandscapeAmbiantColor").asInt(0), - ConfigFile->getVar("LandscapeAmbiantColor").asInt(1), - ConfigFile->getVar("LandscapeAmbiantColor").asInt(2)); - - Landscape->setupStaticLight( - diffuse, ambient, - ConfigFile->getVar("LandscapeMultiplyFactor").asFloat()); - - CConfiguration::setAndCallback("LandscapeReceiveShadowMap", cbMoreLandscapeStuff); - CConfiguration::setAndCallback("LandscapeTileNear", cbMoreLandscapeStuff); - CConfiguration::setAndCallback("LandscapeThreshold", cbMoreLandscapeStuff); - CConfiguration::setAndCallback("LandscapeVision", cbMoreLandscapeStuff); - CConfiguration::setAndCallback("LandscapeVisionInitial", cbMoreLandscapeStuff); -} - -void releaseLandscape() -{ - CConfiguration::dropCallback("LandscapeReceiveShadowMap"); - CConfiguration::dropCallback("LandscapeTileNear"); - CConfiguration::dropCallback("LandscapeThreshold"); - CConfiguration::dropCallback("LandscapeVision"); - CConfiguration::dropCallback("LandscapeVisionInitial"); - - - // release config'd instancegroups - for (vector::iterator it(InstanceGroups.begin()), end(InstanceGroups.end()); it != end; ++it) - { - (*it)->removeFromScene(*Scene); - delete (*it); - } - InstanceGroups.clear(); - - - // -- -- release for cameralandscape - Scene->deleteLandscape(Landscape); - Landscape = NULL; - - - - ConfigFile->setCallback("FogStart", NULL); - ConfigFile->setCallback("FogEnd", NULL); - ConfigFile->setCallback("FogColor", NULL); - ConfigFile->setCallback("FogEnable", NULL); - -} - - -void initAiming() -{ - // -- -- belongs in "camera that follows entity and can be used to aim" - // -- -- random note: is an extension of "camera that follows entity" - - // Create an aiming entity - _AimingEntity = VisualCollisionManager->createEntity(); - _AimingEntity->setCeilMode(true); -} - -void releaseAiming() -{ - // -- -- belongs in CAimingEntityCamera - - VisualCollisionManager->deleteEntity(_AimingEntity); -} - -// -- -- mix with following bit of code for higher accuracy -//NLMISC::CVector CSceneryMouse::getLandscape() -//{ -// if (_LandscapeCached) return _LandscapeCache; -// CViewport v = _Driver->getViewport(); -// CVector pos, dir; -- -- random note: this code gets the landscape position where the mouse is pointing at -// v.getRayWithPoint(_X * v.getWidth(), _Y * v.getHeight(), pos, dir, _Camera.getMatrix(), _Camera.getFrustum()); -// dir.normalize(); -// dir *= 50; -// -- -- float rc = _Landscape->getRayCollision(pos, pos + dir); -// -- -- _LandscapeCache = pos + (rc * dir); -// _LandscapeCached = true; -// return _LandscapeCache; -//} -// -- -- if higher than 50 or something, use code below -CVector getTarget(const CVector &start, const CVector &step, uint numSteps) -{ - CVector testPos = start; - - uint i; - for (i=0; isnapToGround(snapped, normal) && (testPos.z-snapped.z)*normal.z < 0.0f) - { - testPos -= step*0.5f; - break; - } - testPos += step; - } - return testPos; -} - -CVector getTarget(CTrajectory &trajectory, TLocalTime dtSteps, uint numSteps) -{ - TLocalTime t = trajectory.getStartTime(); - CVector testPos; - - uint i; - for (i=0; isnapToGround(snapped, normal) && (testPos.z-snapped.z)*normal.z < 0.0f) - { - t -= (dtSteps/2); - testPos = trajectory.eval(t); - break; - } - t += dtSteps; - } - return testPos; -} - -void updateLandscape() -{ - // -- -- update for CCameraLandscape - // -- -- no need to go to snowballs mouse listener, can probly get this - // from a NL3D::UCamera, NLPACS::UMovePrimitive or NL3D::UInstance too. - // -- -- random note: make a CControllableMovePrimitiveEntityInstance or something - // -- -- should get the player position and not the camera position, - // most optimal for camera rotating around player. - - // load the zones around the viewpoint - Landscape->refreshZonesAround( - Scene->getCam().getMatrix().getPos(), _LandscapeVision); - //_Landscape->refreshZonesAround(MouseListener->getViewMatrix().getPos(), 1000.0f); -} - -void loadAllZonesAround() -{ - /*Landscape->loadAllZonesAround( - Scene->getCam().getMatrix().getPos(), _LandscapeVisionInitial);*/ - Landscape->loadAllZonesAround(Self->Position, _LandscapeVisionInitial); -} - -/* -CVector getTarget(const CVector &start, const CVector &step, uint numSteps) -{ - CVector testPos = start; - - uint i; - for (i=0; isnapToGround(snapped, normal) && (testPos.z-snapped.z)*normal.z < 0.0f) - { - testPos -= step*0.5f; - break; - } - testPos += step; - } - - return testPos; -} -*/ - -// -- -- snowballs specific commands, not for the landscape class itself, it assumes using -// one landscape, and will get actual landscape from CSnowballsClient instance -// -- -- random note: there will only be one instance of CSnowballsClient, -// which is the class that takes care of what is currently done in client.cpp - -//NLMISC_DYNVARIABLE(float,tilenear,"landscape tile near") -//{ -// if (get) -// *pointer = Landscape->getTileNear(); -// else -// Landscape->setTileNear(*pointer); -//} -// -//NLMISC_DYNVARIABLE(float,threshold,"landscape threshold") -//{ -// if (get) -// *pointer = Landscape->getThreshold(); -// else -// Landscape->setThreshold(*pointer); -//} -// -//// boost to -//NLMISC_COMMAND(boost,"switch landscape parameters between high speed and high quality","0|1") -//{ -// if (args.size() != 1 ) return false; -// if ( args[0]=="1" ) -// { -// ICommand::execute( "tilenear 5", CommandsLog); -// ICommand::execute( "threshold 1", CommandsLog); -// } -// else -// { -// ICommand::execute( "tilenear 100", CommandsLog); -// ICommand::execute( "threshold 0.01", CommandsLog); -// } -// return true; -//} - - -NLMISC_COMMAND(add_ig, "add instance group", "name") -{ - if (args.size() != 1 ) return false; - UInstanceGroup *inst = UInstanceGroup::createInstanceGroup(args[0]); - if (inst == NULL) nlwarning("Instance group '%s' not found", args[0].c_str()); - else - { - inst->addToScene(*Scene); - InstanceGroups.push_back(inst); - } - return true; -} - - - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include "nel/misc/types_nl.h" + +#include +#include +#include + +#include "nel/misc/variable.h" +#include "nel/misc/command.h" +#include "nel/misc/variable.h" +#include "nel/misc/debug.h" +#include "nel/misc/path.h" +#include "nel/misc/i18n.h" +#include "nel/misc/config_file.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "snowballs_client.h" +#include "pacs.h" +#include "commands.h" +#include "mouse_listener.h" +#include "physics.h" +#include "configuration.h" +#include "entities.h" + +// +// Namespaces +// + +using namespace std; +using namespace NLMISC; +using namespace NL3D; + +// +// Variables +// + + +namespace SBCLIENT { + +/******************************************************************* + * GLOBALS * + *******************************************************************/ + +vector InstanceGroups; +NLMISC::CVector SunDirection; + +/******************************************************************* + * LANDSCAPE * + *******************************************************************/ + +static UVisualCollisionEntity *_AimingEntity = NULL; +static ULight *_Sun = NULL; + +// +// Functions +// + +void cbUpdateLandscape (CConfigFile::CVar &var) +{ + // -- -- split this whole thing up, lol + + if (var.Name == "FogStart") + Driver->setupFog (var.asFloat (), + ConfigFile->getVar ("FogEnd").asFloat (), + CRGBA(ConfigFile->getVar ("FogColor").asInt (0), + ConfigFile->getVar ("FogColor").asInt (1), + ConfigFile->getVar ("FogColor").asInt (2))); + else if (var.Name == "FogEnd") + Driver->setupFog (ConfigFile->getVar ("FogStart").asFloat (), + var.asFloat (), + CRGBA(ConfigFile->getVar ("FogColor").asInt (0), + ConfigFile->getVar ("FogColor").asInt (1), + ConfigFile->getVar ("FogColor").asInt (2))); + else if (var.Name == "FogColor") + Driver->setupFog( + ConfigFile->getVar ("FogStart").asFloat (), + ConfigFile->getVar ("FogEnd").asFloat (), + CRGBA(var.asInt (0), var.asInt (1), var.asInt (2))); + else if (var.Name == "FogEnable") + { + Driver->enableFog(var.asBool()); + Driver->setupFog( + ConfigFile->getVar("FogStart").asFloat(), + ConfigFile->getVar("FogEnd").asFloat(), + CRGBA(ConfigFile->getVar("FogColor").asInt(0), + ConfigFile->getVar ("FogColor").asInt(1), + ConfigFile->getVar ("FogColor").asInt(2))); + } + else if (var.Name == "SunAmbientColor") + { + _Sun->setAmbiant (CRGBA (var.asInt(0), var.asInt(1), var.asInt(2))); + Driver->setLight (0, *_Sun); + } + else if (var.Name == "SunDiffuseColor") + { + _Sun->setDiffuse (CRGBA (var.asInt(0), var.asInt(1), var.asInt(2))); + Driver->setLight (0, *_Sun); + } + else if (var.Name == "SunSpecularColor") + { + _Sun->setSpecular (CRGBA (var.asInt(0), var.asInt(1), var.asInt(2))); + Driver->setLight (0, *_Sun); + } + else if (var.Name == "SunDirection") + { + SunDirection.set (var.asFloat(0), var.asFloat(1), var.asFloat(2)); + _Sun->setDirection (SunDirection); + Driver->setLight (0, *_Sun); + } + else nlwarning ("Unknown variable update %s", var.Name.c_str()); +} + +static float _LandscapeVision; +static float _LandscapeVisionInitial; + +static void cbMoreLandscapeStuff(CConfigFile::CVar &var) +{ + if (var.Name == "LandscapeTileNear") + Landscape->setTileNear(var.asFloat()); + + else if (var.Name == "LandscapeThreshold") + Landscape->setThreshold(var.asFloat()); + + else if (var.Name == "LandscapeVision") + _LandscapeVision = var.asFloat(); + + else if (var.Name == "LandscapeVisionInitial") + _LandscapeVisionInitial = var.asFloat(); + + else if (var.Name == "LandscapeReceiveShadowMap") + Landscape->enableReceiveShadowMap(var.asBool()); + + else nlwarning("Unknown variable update %s", var.Name.c_str()); +} + +void initLight() +{ + // -- -- sun or whatever light, simple use, doesn't need class yet + + _Sun = ULight::createLight(); + nlassert(_Sun); + _Sun->setMode(ULight::DirectionalLight); + Driver->enableLight(0); + + ConfigFile->setCallback("SunAmbientColor", cbUpdateLandscape); + ConfigFile->setCallback("SunDiffuseColor", cbUpdateLandscape); + ConfigFile->setCallback("SunSpecularColor", cbUpdateLandscape); + ConfigFile->setCallback("SunDirection", cbUpdateLandscape); + + cbUpdateLandscape(ConfigFile->getVar("SunAmbientColor")); + cbUpdateLandscape(ConfigFile->getVar("SunDiffuseColor")); + cbUpdateLandscape(ConfigFile->getVar("SunSpecularColor")); + cbUpdateLandscape(ConfigFile->getVar("SunDirection")); +} + +void releaseLight() +{ + // -- -- just data + + ConfigFile->setCallback("SunAmbientColor", NULL); + ConfigFile->setCallback("SunDiffuseColor", NULL); + ConfigFile->setCallback("SunSpecularColor", NULL); + ConfigFile->setCallback("SunDirection", NULL); + + delete _Sun; _Sun = NULL; +} + +void initLandscape() +{ + + + + ConfigFile->setCallback ("FogStart", cbUpdateLandscape); + ConfigFile->setCallback ("FogEnd", cbUpdateLandscape); + ConfigFile->setCallback ("FogColor", cbUpdateLandscape); + ConfigFile->setCallback ("FogEnable", cbUpdateLandscape); + + cbUpdateLandscape (ConfigFile->getVar ("FogStart")); + cbUpdateLandscape (ConfigFile->getVar ("FogEnd")); + cbUpdateLandscape (ConfigFile->getVar ("FogColor")); + cbUpdateLandscape (ConfigFile->getVar ("FogEnable")); + + + + + + // -- -- start of init for "instance groups loaded from config" + + CConfigFile::CVar igv = ConfigFile->getVar("InstanceGroups"); + for (uint32 i = 0; i < igv.size (); i++) + { + UInstanceGroup *inst = UInstanceGroup::createInstanceGroup (igv.asString (i)); + if (inst == NULL) + { + nlwarning ("Instance group '%s' not found", igv.asString (i).c_str ()); + } + else + { + inst->addToScene (*Scene); + InstanceGroups.push_back (inst); + } + } + + + + // -- -- start of init for "landscape around camera that gets data from config" + + // create the landscape + nlassert(!Landscape); + Landscape = Scene->createLandscape(); + + // load the bank files + Landscape->loadBankFiles( + CPath::lookup(ConfigFile->getVar("LandscapeBankName").asString()), + CPath::lookup(ConfigFile->getVar("LandscapeFarBankName").asString())); + Landscape->invalidateAllTiles(); + + // -- -- this doesn't do anything useful + //// setup the zone path + //Landscape->setZonePath(ConfigFile->getVar("DataPath").asString() + "zones/"); + + // -- -- do this when character appears or does far teleport + //// and eventually, load the zones around the starting point. + //Landscape->loadAllZonesAround (CVector(ConfigFile->getVar("StartPoint").asFloat(0), + // ConfigFile->getVar("StartPoint").asFloat(1), + // ConfigFile->getVar("StartPoint").asFloat(2)), + // 1000.0f); + + // color of the landscape shadow + CRGBA diffuse( + ConfigFile->getVar("LandscapeDiffuseColor").asInt(0), + ConfigFile->getVar("LandscapeDiffuseColor").asInt(1), + ConfigFile->getVar("LandscapeDiffuseColor").asInt(2)); + CRGBA ambient( + ConfigFile->getVar("LandscapeAmbiantColor").asInt(0), + ConfigFile->getVar("LandscapeAmbiantColor").asInt(1), + ConfigFile->getVar("LandscapeAmbiantColor").asInt(2)); + + Landscape->setupStaticLight( + diffuse, ambient, + ConfigFile->getVar("LandscapeMultiplyFactor").asFloat()); + + CConfiguration::setAndCallback("LandscapeReceiveShadowMap", cbMoreLandscapeStuff); + CConfiguration::setAndCallback("LandscapeTileNear", cbMoreLandscapeStuff); + CConfiguration::setAndCallback("LandscapeThreshold", cbMoreLandscapeStuff); + CConfiguration::setAndCallback("LandscapeVision", cbMoreLandscapeStuff); + CConfiguration::setAndCallback("LandscapeVisionInitial", cbMoreLandscapeStuff); +} + +void releaseLandscape() +{ + CConfiguration::dropCallback("LandscapeReceiveShadowMap"); + CConfiguration::dropCallback("LandscapeTileNear"); + CConfiguration::dropCallback("LandscapeThreshold"); + CConfiguration::dropCallback("LandscapeVision"); + CConfiguration::dropCallback("LandscapeVisionInitial"); + + + // release config'd instancegroups + for (vector::iterator it(InstanceGroups.begin()), end(InstanceGroups.end()); it != end; ++it) + { + (*it)->removeFromScene(*Scene); + delete (*it); + } + InstanceGroups.clear(); + + + // -- -- release for cameralandscape + Scene->deleteLandscape(Landscape); + Landscape = NULL; + + + + ConfigFile->setCallback("FogStart", NULL); + ConfigFile->setCallback("FogEnd", NULL); + ConfigFile->setCallback("FogColor", NULL); + ConfigFile->setCallback("FogEnable", NULL); + +} + + +void initAiming() +{ + // -- -- belongs in "camera that follows entity and can be used to aim" + // -- -- random note: is an extension of "camera that follows entity" + + // Create an aiming entity + _AimingEntity = VisualCollisionManager->createEntity(); + _AimingEntity->setCeilMode(true); +} + +void releaseAiming() +{ + // -- -- belongs in CAimingEntityCamera + + VisualCollisionManager->deleteEntity(_AimingEntity); +} + +// -- -- mix with following bit of code for higher accuracy +//NLMISC::CVector CSceneryMouse::getLandscape() +//{ +// if (_LandscapeCached) return _LandscapeCache; +// CViewport v = _Driver->getViewport(); +// CVector pos, dir; -- -- random note: this code gets the landscape position where the mouse is pointing at +// v.getRayWithPoint(_X * v.getWidth(), _Y * v.getHeight(), pos, dir, _Camera.getMatrix(), _Camera.getFrustum()); +// dir.normalize(); +// dir *= 50; +// -- -- float rc = _Landscape->getRayCollision(pos, pos + dir); +// -- -- _LandscapeCache = pos + (rc * dir); +// _LandscapeCached = true; +// return _LandscapeCache; +//} +// -- -- if higher than 50 or something, use code below +CVector getTarget(const CVector &start, const CVector &step, uint numSteps) +{ + CVector testPos = start; + + uint i; + for (i=0; isnapToGround(snapped, normal) && (testPos.z-snapped.z)*normal.z < 0.0f) + { + testPos -= step*0.5f; + break; + } + testPos += step; + } + return testPos; +} + +CVector getTarget(CTrajectory &trajectory, TLocalTime dtSteps, uint numSteps) +{ + TLocalTime t = trajectory.getStartTime(); + CVector testPos; + + uint i; + for (i=0; isnapToGround(snapped, normal) && (testPos.z-snapped.z)*normal.z < 0.0f) + { + t -= (dtSteps/2); + testPos = trajectory.eval(t); + break; + } + t += dtSteps; + } + return testPos; +} + +void updateLandscape() +{ + // -- -- update for CCameraLandscape + // -- -- no need to go to snowballs mouse listener, can probly get this + // from a NL3D::UCamera, NLPACS::UMovePrimitive or NL3D::UInstance too. + // -- -- random note: make a CControllableMovePrimitiveEntityInstance or something + // -- -- should get the player position and not the camera position, + // most optimal for camera rotating around player. + + // load the zones around the viewpoint + Landscape->refreshZonesAround( + Scene->getCam().getMatrix().getPos(), _LandscapeVision); + //_Landscape->refreshZonesAround(MouseListener->getViewMatrix().getPos(), 1000.0f); +} + +void loadAllZonesAround() +{ + /*Landscape->loadAllZonesAround( + Scene->getCam().getMatrix().getPos(), _LandscapeVisionInitial);*/ + Landscape->loadAllZonesAround(Self->Position, _LandscapeVisionInitial); +} + +/* +CVector getTarget(const CVector &start, const CVector &step, uint numSteps) +{ + CVector testPos = start; + + uint i; + for (i=0; isnapToGround(snapped, normal) && (testPos.z-snapped.z)*normal.z < 0.0f) + { + testPos -= step*0.5f; + break; + } + testPos += step; + } + + return testPos; +} +*/ + +// -- -- snowballs specific commands, not for the landscape class itself, it assumes using +// one landscape, and will get actual landscape from CSnowballsClient instance +// -- -- random note: there will only be one instance of CSnowballsClient, +// which is the class that takes care of what is currently done in client.cpp + +//NLMISC_DYNVARIABLE(float,tilenear,"landscape tile near") +//{ +// if (get) +// *pointer = Landscape->getTileNear(); +// else +// Landscape->setTileNear(*pointer); +//} +// +//NLMISC_DYNVARIABLE(float,threshold,"landscape threshold") +//{ +// if (get) +// *pointer = Landscape->getThreshold(); +// else +// Landscape->setThreshold(*pointer); +//} +// +//// boost to +//NLMISC_COMMAND(boost,"switch landscape parameters between high speed and high quality","0|1") +//{ +// if (args.size() != 1 ) return false; +// if ( args[0]=="1" ) +// { +// ICommand::execute( "tilenear 5", CommandsLog); +// ICommand::execute( "threshold 1", CommandsLog); +// } +// else +// { +// ICommand::execute( "tilenear 100", CommandsLog); +// ICommand::execute( "threshold 0.01", CommandsLog); +// } +// return true; +//} + + +NLMISC_COMMAND(add_ig, "add instance group", "name") +{ + if (args.size() != 1 ) return false; + UInstanceGroup *inst = UInstanceGroup::createInstanceGroup(args[0]); + if (inst == NULL) nlwarning("Instance group '%s' not found", args[0].c_str()); + else + { + inst->addToScene(*Scene); + InstanceGroups.push_back(inst); + } + return true; +} + + + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/landscape.h b/code/snowballs2/client/src/landscape.h index 41cbf4db1..890c09cbc 100644 --- a/code/snowballs2/client/src/landscape.h +++ b/code/snowballs2/client/src/landscape.h @@ -1,78 +1,78 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef LANDSCAPE_H -#define LANDSCAPE_H - -// -// Includes -// - -#include - -#include -#include -#include - -// -// External definitions -// - -namespace NL3D -{ - class UInstanceGroup; -} - -namespace SBCLIENT { - -class CTrajectory; - - -// -// External variables -// - -extern std::vector InstanceGroups; -extern NLMISC::CVector SunDirection; - - -// -// External functions -// - -void initLight(); -void releaseLight(); - -void initLandscape(); -void releaseLandscape(); - -void initAiming(); -void releaseAiming(); - -void updateLandscape(); - -void loadAllZonesAround(); - -// Compute the collision with the landscape from the start position, using the given step, -// at maximum numSteps steps from the start. It uses full (!) physics computation, and should be -// identical on the server -NLMISC::CVector getTarget(const NLMISC::CVector &start, const NLMISC::CVector &step, uint numSteps); - -} /* namespace SBCLIENT */ - -#endif // LANDSCAPE_H - -/* End of landscape.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef LANDSCAPE_H +#define LANDSCAPE_H + +// +// Includes +// + +#include + +#include +#include +#include + +// +// External definitions +// + +namespace NL3D +{ + class UInstanceGroup; +} + +namespace SBCLIENT { + +class CTrajectory; + + +// +// External variables +// + +extern std::vector InstanceGroups; +extern NLMISC::CVector SunDirection; + + +// +// External functions +// + +void initLight(); +void releaseLight(); + +void initLandscape(); +void releaseLandscape(); + +void initAiming(); +void releaseAiming(); + +void updateLandscape(); + +void loadAllZonesAround(); + +// Compute the collision with the landscape from the start position, using the given step, +// at maximum numSteps steps from the start. It uses full (!) physics computation, and should be +// identical on the server +NLMISC::CVector getTarget(const NLMISC::CVector &start, const NLMISC::CVector &step, uint numSteps); + +} /* namespace SBCLIENT */ + +#endif // LANDSCAPE_H + +/* End of landscape.h */ diff --git a/code/snowballs2/client/src/lens_flare.cpp b/code/snowballs2/client/src/lens_flare.cpp index d6be42a4c..e9f308529 100644 --- a/code/snowballs2/client/src/lens_flare.cpp +++ b/code/snowballs2/client/src/lens_flare.cpp @@ -1,327 +1,327 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "camera.h" -#include "landscape.h" -#include "snowballs_client.h" -#include "mouse_listener.h" - -// -// Namespaces -// - -using namespace NLMISC; -using namespace NL3D; -using namespace std; - -namespace SBCLIENT { - -/// If axis segment is longer than this value then no lens flare is displayed -static const float _MaxLensFlareLenght = 0.4f; - -// -// Functions -// - -/** - * A lens-flare class - * \author Stephane Coutelas - * \author Nevrax France - * \date 2000 - */ -class CLensFlare -{ - float _AlphaCoef; - - /// flare - struct _CFlare - { - NL3D::UMaterial Material; - - float Width; - float Height; - - float Location; - - float Scale; - - _CFlare(NL3D::UTexture *texture, float width, float height, float location, float scale) - { - // -- -- nicely re-usable class, but why should it know about the snowballs specific driver global - Material = Driver->createMaterial (); - Material.initUnlit (); - Material.setTexture (texture); - Material.setBlendFunc (UMaterial::srcalpha, UMaterial::one); - Material.setBlend(true); - Material.setZFunc (UMaterial::always); - Material.setZWrite (false); - - // quad dimension - Width = width; - Height = height; - - // location on the lens-flare ray - Location = location; - - // texture scale - Scale = scale; - } - - ~_CFlare() - { - Driver->deleteMaterial(Material); - } - }; - - /// flares due to light - std::vector<_CFlare *> _Flares; - -public: - - /// constructor - CLensFlare() - { - _AlphaCoef = 1.0f; - } - - ~CLensFlare() - { - for (std::vector<_CFlare *>::iterator it(_Flares.begin()), end(_Flares.end()); it != end; ++it) - delete (*it); - _Flares.clear(); - } - - /// add a flare to the flare list - void addFlare(NL3D::UTexture * texture, float width, float height, float location = 1.f, float scale = 1.f); - - void setAlphaCoef(float coef) - { - _AlphaCoef = coef; - } - - // -- -- random note: show actually shows and is used within update - /// lens flare display function - void show(); -}; - - -/*********************************************************\ - addFlare() -\*********************************************************/ -void CLensFlare::addFlare(UTexture * texture, float width, float height, float location, float scale) -{ - _Flares.push_back(new _CFlare(texture, width, height, location, scale)); -} - - -/*********************************************************\ - show() -\*********************************************************/ -void CLensFlare::show() -{ - CMatrix mtx; - mtx.identity(); - - nlassert(Driver!=NULL && !Camera.empty()); - - Driver->setMatrixMode2D11 (); - - // Determining axis "screen center - light" vector - CMatrix cameraMatrix = Camera.getMatrix(); - cameraMatrix.invert(); - CVector light = (-100000 * SunDirection); - light = cameraMatrix * light; - light = Camera.getFrustum().project(light); - - CVector screenCenter(0.5f,0.5f,0); - CVector axis = light - screenCenter; - - if(axis.norm()>_MaxLensFlareLenght) - { - return; - } - - // rendering flares - vector<_CFlare *>::iterator itflr; - for(itflr = _Flares.begin(); itflr!=_Flares.end(); itflr++) - { - (*itflr)->Material.setColor(CRGBA(255,255,255,(uint8)(_AlphaCoef*255))); - - CQuadUV quad; - - float xCenterQuad = screenCenter.x + (*itflr)->Location * axis.x; - float yCenterQuad = screenCenter.y + (*itflr)->Location * axis.y; - - float x,y; - - - x = xCenterQuad - (*itflr)->Width * (*itflr)->Scale / 2.f; - y = yCenterQuad - (*itflr)->Height * (*itflr)->Scale / 2.f; - quad.V0.set (x, y, 0); - - x = xCenterQuad + (*itflr)->Width * (*itflr)->Scale / 2.f; - y = yCenterQuad - (*itflr)->Height * (*itflr)->Scale / 2.f; - quad.V1.set (x, y, 0); - - x = xCenterQuad + (*itflr)->Width * (*itflr)->Scale / 2.f; - y = yCenterQuad + (*itflr)->Height * (*itflr)->Scale / 2.f; - quad.V2.set (x, y, 0); - - x = xCenterQuad - (*itflr)->Width * (*itflr)->Scale / 2.f; - y = yCenterQuad + (*itflr)->Height * (*itflr)->Scale / 2.f; - quad.V3.set (x, y, 0); - - quad.Uv0.U = 0.0f; quad.Uv0.V = 1.0f; - quad.Uv1.U = 1.0f; quad.Uv1.V = 1.0f; - quad.Uv2.U = 1.0f; quad.Uv2.V = 0.0f; - quad.Uv3.U = 0.0f; quad.Uv3.V = 0.0f; - - Driver->drawQuad (quad, (*itflr)->Material); - } -} - -static CLensFlare *LensFlare = NULL; -static UTextureFile *flareTexture1 = NULL; -static UTextureFile *flareTexture3 = NULL; -static UTextureFile *flareTexture4 = NULL; -static UTextureFile *flareTexture5 = NULL; -static UTextureFile *flareTexture6 = NULL; -static UTextureFile *flareTexture7 = NULL; - -void initLensFlare () -{ - // -- -- getting this from a config file would be more re-usable - - LensFlare = new CLensFlare (); - - flareTexture1 = Driver->createTextureFile("flare01.tga"); - flareTexture3 = Driver->createTextureFile("flare03.tga"); - flareTexture4 = Driver->createTextureFile("flare04.tga"); - flareTexture5 = Driver->createTextureFile("flare05.tga"); - flareTexture6 = Driver->createTextureFile("flare06.tga"); - flareTexture7 = Driver->createTextureFile("flare07.tga"); - - float w = 30/800.0f; - float h = 30/600.0f; - - // shine - LensFlare->addFlare (flareTexture3, w, h, 1.f, 16.f); - - LensFlare->addFlare (flareTexture1, w, h, 1.f, 6.f); - LensFlare->addFlare (flareTexture6, w, h, 1.3f, 1.2f); - LensFlare->addFlare (flareTexture7, w, h, 1.0f, 3.f); - LensFlare->addFlare (flareTexture6, w, h, 0.5f, 4.f); - LensFlare->addFlare (flareTexture5, w, h, 0.2f, 2.f); - LensFlare->addFlare (flareTexture7, w, h, 0.0f, 0.8f); - LensFlare->addFlare (flareTexture7, w, h, -0.25f, 2.f); - LensFlare->addFlare (flareTexture1, w, h, -0.4f, 1.f); - LensFlare->addFlare (flareTexture4, w, h, -1.0f, 12.f); - LensFlare->addFlare (flareTexture5, w, h, -0.6f, 6.f); -} - -void updateLensFlare () -{ - // -- -- todo: see how much of this can be modified to depend on nel - // things only, and moved into the lensflare class - - // vector to sun - //============== - CVector userLook = MouseListener->getViewDirection (); - - CVector sunDirection = (-100000 * SunDirection); - - // cosinus between the two previous vectors - //========================================= - float cosAngle = sunDirection*userLook/sunDirection.norm(); - - // alpha - //====== - float alphaf; - if(cosAngle<0) - { - alphaf = 0; - } - else - { - alphaf = 255*(float)(pow(cosAngle,20)); - } - - // landscape's masking sun ? - //========================== - CMatrix camMatrix; - camMatrix = Camera.getMatrix(); - camMatrix.setPos(CVector::Null); - camMatrix.invert(); - CVector tmp = camMatrix * sunDirection; - tmp = Camera.getFrustum().project(tmp); - uint32 w,h; - Driver->getWindowSize(w,h); - float sunRadius = 24; // -- -- why 24 - CRect rect((uint32)(tmp.x*w)-(uint32)sunRadius,(uint32)(tmp.y*h)-(uint32)sunRadius,2*(uint32)sunRadius,2*(uint32)sunRadius); - vector zbuff; - Driver->getZBufferPart(zbuff, rect); - float view = 0.f; - float sum = 0; - sint i; // -- -- signed? - for(i=0; i<(sint)zbuff.size(); i++) - { - if(zbuff[i]>=0.99999f) sum ++; - } - view = sum/(sunRadius*2*sunRadius*2); - - Driver->setMatrixMode2D11 (); - - // quad for dazzle - //================ - uint8 alpha = (uint8)(alphaf*view/2.0f); - if(alpha!=0) - { - Driver->drawQuad(0,0,1,1,CRGBA(255,255,255,alpha)); - } - - // Display lens-flare - LensFlare->setAlphaCoef( 1.f - (float)cos(alphaf*view*Pi/(2.f*255.f)) ); - LensFlare->show(); -} - -void releaseLensFlare () -{ - delete LensFlare; LensFlare = NULL; - Driver->deleteTextureFile(flareTexture1); flareTexture1 = NULL; - Driver->deleteTextureFile(flareTexture3); flareTexture3 = NULL; - Driver->deleteTextureFile(flareTexture4); flareTexture4 = NULL; - Driver->deleteTextureFile(flareTexture5); flareTexture5 = NULL; - Driver->deleteTextureFile(flareTexture6); flareTexture6 = NULL; - Driver->deleteTextureFile(flareTexture7); flareTexture7 = NULL; -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "camera.h" +#include "landscape.h" +#include "snowballs_client.h" +#include "mouse_listener.h" + +// +// Namespaces +// + +using namespace NLMISC; +using namespace NL3D; +using namespace std; + +namespace SBCLIENT { + +/// If axis segment is longer than this value then no lens flare is displayed +static const float _MaxLensFlareLenght = 0.4f; + +// +// Functions +// + +/** + * A lens-flare class + * \author Stephane Coutelas + * \author Nevrax France + * \date 2000 + */ +class CLensFlare +{ + float _AlphaCoef; + + /// flare + struct _CFlare + { + NL3D::UMaterial Material; + + float Width; + float Height; + + float Location; + + float Scale; + + _CFlare(NL3D::UTexture *texture, float width, float height, float location, float scale) + { + // -- -- nicely re-usable class, but why should it know about the snowballs specific driver global + Material = Driver->createMaterial (); + Material.initUnlit (); + Material.setTexture (texture); + Material.setBlendFunc (UMaterial::srcalpha, UMaterial::one); + Material.setBlend(true); + Material.setZFunc (UMaterial::always); + Material.setZWrite (false); + + // quad dimension + Width = width; + Height = height; + + // location on the lens-flare ray + Location = location; + + // texture scale + Scale = scale; + } + + ~_CFlare() + { + Driver->deleteMaterial(Material); + } + }; + + /// flares due to light + std::vector<_CFlare *> _Flares; + +public: + + /// constructor + CLensFlare() + { + _AlphaCoef = 1.0f; + } + + ~CLensFlare() + { + for (std::vector<_CFlare *>::iterator it(_Flares.begin()), end(_Flares.end()); it != end; ++it) + delete (*it); + _Flares.clear(); + } + + /// add a flare to the flare list + void addFlare(NL3D::UTexture * texture, float width, float height, float location = 1.f, float scale = 1.f); + + void setAlphaCoef(float coef) + { + _AlphaCoef = coef; + } + + // -- -- random note: show actually shows and is used within update + /// lens flare display function + void show(); +}; + + +/*********************************************************\ + addFlare() +\*********************************************************/ +void CLensFlare::addFlare(UTexture * texture, float width, float height, float location, float scale) +{ + _Flares.push_back(new _CFlare(texture, width, height, location, scale)); +} + + +/*********************************************************\ + show() +\*********************************************************/ +void CLensFlare::show() +{ + CMatrix mtx; + mtx.identity(); + + nlassert(Driver!=NULL && !Camera.empty()); + + Driver->setMatrixMode2D11 (); + + // Determining axis "screen center - light" vector + CMatrix cameraMatrix = Camera.getMatrix(); + cameraMatrix.invert(); + CVector light = (-100000 * SunDirection); + light = cameraMatrix * light; + light = Camera.getFrustum().project(light); + + CVector screenCenter(0.5f,0.5f,0); + CVector axis = light - screenCenter; + + if(axis.norm()>_MaxLensFlareLenght) + { + return; + } + + // rendering flares + vector<_CFlare *>::iterator itflr; + for(itflr = _Flares.begin(); itflr!=_Flares.end(); itflr++) + { + (*itflr)->Material.setColor(CRGBA(255,255,255,(uint8)(_AlphaCoef*255))); + + CQuadUV quad; + + float xCenterQuad = screenCenter.x + (*itflr)->Location * axis.x; + float yCenterQuad = screenCenter.y + (*itflr)->Location * axis.y; + + float x,y; + + + x = xCenterQuad - (*itflr)->Width * (*itflr)->Scale / 2.f; + y = yCenterQuad - (*itflr)->Height * (*itflr)->Scale / 2.f; + quad.V0.set (x, y, 0); + + x = xCenterQuad + (*itflr)->Width * (*itflr)->Scale / 2.f; + y = yCenterQuad - (*itflr)->Height * (*itflr)->Scale / 2.f; + quad.V1.set (x, y, 0); + + x = xCenterQuad + (*itflr)->Width * (*itflr)->Scale / 2.f; + y = yCenterQuad + (*itflr)->Height * (*itflr)->Scale / 2.f; + quad.V2.set (x, y, 0); + + x = xCenterQuad - (*itflr)->Width * (*itflr)->Scale / 2.f; + y = yCenterQuad + (*itflr)->Height * (*itflr)->Scale / 2.f; + quad.V3.set (x, y, 0); + + quad.Uv0.U = 0.0f; quad.Uv0.V = 1.0f; + quad.Uv1.U = 1.0f; quad.Uv1.V = 1.0f; + quad.Uv2.U = 1.0f; quad.Uv2.V = 0.0f; + quad.Uv3.U = 0.0f; quad.Uv3.V = 0.0f; + + Driver->drawQuad (quad, (*itflr)->Material); + } +} + +static CLensFlare *LensFlare = NULL; +static UTextureFile *flareTexture1 = NULL; +static UTextureFile *flareTexture3 = NULL; +static UTextureFile *flareTexture4 = NULL; +static UTextureFile *flareTexture5 = NULL; +static UTextureFile *flareTexture6 = NULL; +static UTextureFile *flareTexture7 = NULL; + +void initLensFlare () +{ + // -- -- getting this from a config file would be more re-usable + + LensFlare = new CLensFlare (); + + flareTexture1 = Driver->createTextureFile("flare01.tga"); + flareTexture3 = Driver->createTextureFile("flare03.tga"); + flareTexture4 = Driver->createTextureFile("flare04.tga"); + flareTexture5 = Driver->createTextureFile("flare05.tga"); + flareTexture6 = Driver->createTextureFile("flare06.tga"); + flareTexture7 = Driver->createTextureFile("flare07.tga"); + + float w = 30/800.0f; + float h = 30/600.0f; + + // shine + LensFlare->addFlare (flareTexture3, w, h, 1.f, 16.f); + + LensFlare->addFlare (flareTexture1, w, h, 1.f, 6.f); + LensFlare->addFlare (flareTexture6, w, h, 1.3f, 1.2f); + LensFlare->addFlare (flareTexture7, w, h, 1.0f, 3.f); + LensFlare->addFlare (flareTexture6, w, h, 0.5f, 4.f); + LensFlare->addFlare (flareTexture5, w, h, 0.2f, 2.f); + LensFlare->addFlare (flareTexture7, w, h, 0.0f, 0.8f); + LensFlare->addFlare (flareTexture7, w, h, -0.25f, 2.f); + LensFlare->addFlare (flareTexture1, w, h, -0.4f, 1.f); + LensFlare->addFlare (flareTexture4, w, h, -1.0f, 12.f); + LensFlare->addFlare (flareTexture5, w, h, -0.6f, 6.f); +} + +void updateLensFlare () +{ + // -- -- todo: see how much of this can be modified to depend on nel + // things only, and moved into the lensflare class + + // vector to sun + //============== + CVector userLook = MouseListener->getViewDirection (); + + CVector sunDirection = (-100000 * SunDirection); + + // cosinus between the two previous vectors + //========================================= + float cosAngle = sunDirection*userLook/sunDirection.norm(); + + // alpha + //====== + float alphaf; + if(cosAngle<0) + { + alphaf = 0; + } + else + { + alphaf = 255*(float)(pow(cosAngle,20)); + } + + // landscape's masking sun ? + //========================== + CMatrix camMatrix; + camMatrix = Camera.getMatrix(); + camMatrix.setPos(CVector::Null); + camMatrix.invert(); + CVector tmp = camMatrix * sunDirection; + tmp = Camera.getFrustum().project(tmp); + uint32 w,h; + Driver->getWindowSize(w,h); + float sunRadius = 24; // -- -- why 24 + CRect rect((uint32)(tmp.x*w)-(uint32)sunRadius,(uint32)(tmp.y*h)-(uint32)sunRadius,2*(uint32)sunRadius,2*(uint32)sunRadius); + vector zbuff; + Driver->getZBufferPart(zbuff, rect); + float view = 0.f; + float sum = 0; + sint i; // -- -- signed? + for(i=0; i<(sint)zbuff.size(); i++) + { + if(zbuff[i]>=0.99999f) sum ++; + } + view = sum/(sunRadius*2*sunRadius*2); + + Driver->setMatrixMode2D11 (); + + // quad for dazzle + //================ + uint8 alpha = (uint8)(alphaf*view/2.0f); + if(alpha!=0) + { + Driver->drawQuad(0,0,1,1,CRGBA(255,255,255,alpha)); + } + + // Display lens-flare + LensFlare->setAlphaCoef( 1.f - (float)cos(alphaf*view*Pi/(2.f*255.f)) ); + LensFlare->show(); +} + +void releaseLensFlare () +{ + delete LensFlare; LensFlare = NULL; + Driver->deleteTextureFile(flareTexture1); flareTexture1 = NULL; + Driver->deleteTextureFile(flareTexture3); flareTexture3 = NULL; + Driver->deleteTextureFile(flareTexture4); flareTexture4 = NULL; + Driver->deleteTextureFile(flareTexture5); flareTexture5 = NULL; + Driver->deleteTextureFile(flareTexture6); flareTexture6 = NULL; + Driver->deleteTextureFile(flareTexture7); flareTexture7 = NULL; +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/lens_flare.h b/code/snowballs2/client/src/lens_flare.h index bcbae57bc..569214c07 100644 --- a/code/snowballs2/client/src/lens_flare.h +++ b/code/snowballs2/client/src/lens_flare.h @@ -1,34 +1,34 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef LENS_FLARE_H -#define LENS_FLARE_H - -namespace SBCLIENT { - -// -// External functions -// - -void initLensFlare (); -void updateLensFlare (); -void releaseLensFlare (); - -} /* namespace SBCLIENT */ - -#endif // LENS_FLARE_H - -/* End of lens_flare.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef LENS_FLARE_H +#define LENS_FLARE_H + +namespace SBCLIENT { + +// +// External functions +// + +void initLensFlare (); +void updateLensFlare (); +void releaseLensFlare (); + +} /* namespace SBCLIENT */ + +#endif // LENS_FLARE_H + +/* End of lens_flare.h */ diff --git a/code/snowballs2/client/src/mouse_listener.cpp b/code/snowballs2/client/src/mouse_listener.cpp index 9cf16fed9..c459f6bd2 100644 --- a/code/snowballs2/client/src/mouse_listener.cpp +++ b/code/snowballs2/client/src/mouse_listener.cpp @@ -1,469 +1,469 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "snowballs_client.h" -#include "mouse_listener.h" -#include "entities.h" -#include "camera.h" -#include "landscape.h" -#include "network.h" - -// -// Namespaces -// - -using namespace NLMISC; -using namespace NL3D; - -namespace SBCLIENT { - -// -// Variables -// - -static float MouseZoomStep; - -static float GroundCamLimit = 0.5f; - -// -// Functions -// - -C3dMouseListener::C3dMouseListener() -{ - // -- -- a mouse listener that can aim at the ground with a shape - // and does a bunch of other random things that should be - // done by something else, really - - // -- -- half of this thing has to be split up into a - // CKeyboardControlledMovePrimitive or something - - _Matrix.identity(); - _ModelMatrix.identity() ; - _EnableModelMatrixEdition = false ; - _HotSpot.set (0,0,0); - _Viewport.initFullScreen(); - _Frustrum.init (2.f, 2.f, -1.f, 1.f); - _MouseMode=nelStyle; - setSpeed (10.f); - _LastTime=CTime::getLocalTime (); - - _ViewLagBehind = 20.0f; - _ViewHeight = 2.0f; - _ViewTargetHeight = 3.0f; - - _AimingState = false; - _AimingDamage = 0.0f; - _AimingSpeed = 1.0f; - _AimingMax = 5.0f; - _AimingStartTime = 0; - _AimingRefreshRate = 100; - _AimingInstance = Scene->createInstance("aim.shape"); - _AimingInstance.setTransformMode(UTransformable::RotQuat); - - _X = 0.5f; - _Y = 0.5f; - _InvertedMouse = false; -} - -C3dMouseListener::~C3dMouseListener() -{ - // -- -- doesn't need to know about the snowballs specific global, - // scene shout be passed at construction to create aiming instance - // -- -- random note: aiminginstance here and aimingentity in landscape.cpp ... - // one of them obviously is in the wrong place - Scene->deleteInstance(_AimingInstance); -} - - - -void C3dMouseListener::operator ()(const CEvent& event) -{ - CEventMouse* mouseEvent=(CEventMouse*)&event; - if (event==EventMouseMoveId) // && mouseEvent->Button&leftButton!=0) - { - // Rotate Axis - CVector axis; - - axis=_Matrix.getPos(); - - // First in the hotSpot - CMatrix comeFromHotSpot=_Matrix; - comeFromHotSpot.setPos (axis); - - // Then turn along the Z axis with X mouse - CMatrix turnZ; - turnZ.identity(); - turnZ.rotateZ ((float) Pi*2.f*(_X-mouseEvent->X)); - - // Then turn along the X axis with Y mouse - CMatrix turnX; - turnX.identity(); - if (_InvertedMouse) - _ViewHeight += 3.0f*(mouseEvent->Y-_Y); - else - _ViewHeight -= 3.0f*(mouseEvent->Y-_Y); - - // Then come back from hotspot - CMatrix goToHotSpot=comeFromHotSpot; - goToHotSpot.invert(); - - // Make the matrix - CMatrix negPivot, Pivot; - negPivot.identity(); - negPivot.setPos (-axis); - Pivot.identity(); - Pivot.setPos (axis); - - // Make this transformation \\// - //_Matrix=Pivot*turnZ*negPivot*comeFromHotSpot*turnX*goToHotSpot*_Matrix; - Pivot*=turnZ; - Pivot*=negPivot; - Pivot*=comeFromHotSpot; - Pivot*=turnX; - Pivot*=goToHotSpot; - - - Pivot*=_Matrix; - _Matrix=Pivot; - // Normalize, too much transformation could give an ugly matrix.. - _Matrix.normalize (CMatrix::XYZ); - - // Update mouse position - Driver->setMousePos(0.5f, 0.5f); - _X = 0.5f; - _Y = 0.5f; - } - else if (event==EventMouseDownId) - { - // aim - _AimingState = true; - _AimingDamage = 0.0f; - _AimingStartTime = CTime::getLocalTime(); - _AimingLastUpdateTime = 0; - } - else if (event==EventMouseUpId) - { - // throw snowball -// nlinfo("damage=%f", _AimingDamage); - _AimingState = false; - _AimingStartTime = 0; - CVector direction = (_AimedTarget-_AimingPosition).normed(); - - if (isOnline ()) - { - sendSnowBall (Self->Id, _AimingPosition, _AimedTarget, SnowballSpeed, _AimingDamage); - } - else - { - shotSnowball (NextEID++, Self->Id, _AimingPosition, _AimedTarget, SnowballSpeed, _AimingDamage); - } - } - else if (event==EventMouseWheelId) - { - CEventMouseWheel* mouseEvent=(CEventMouseWheel*)&event; - _ViewLagBehind += (mouseEvent->Direction? -MouseZoomStep : +MouseZoomStep); - if (_ViewLagBehind < 2.0f) - _ViewLagBehind = 2.0f; - } -} - -void C3dMouseListener::addToServer (CEventServer& server) -{ - server.addListener (EventMouseMoveId, this); - server.addListener (EventMouseDownId, this); - server.addListener (EventMouseUpId, this); - server.addListener (EventMouseWheelId, this); - _AsyncListener.addToServer (server); -} - -void C3dMouseListener::removeFromServer (CEventServer& server) -{ - server.removeListener (EventMouseMoveId, this); - server.removeListener (EventMouseDownId, this); - server.removeListener (EventMouseUpId, this); - server.removeListener (EventMouseWheelId, this); - _AsyncListener.removeFromServer (server); -} - -const NLMISC::CMatrix& C3dMouseListener::getViewMatrix () -{ - // Return the matrix - return _Matrix; -} - -void C3dMouseListener::update() -{ - // CVector - CVector dir (0,0,0); - bool find=false; - - // -- -- what does the mouse listener have to do with the keyboard?! - - // Key pushed ? - if (_AsyncListener.isKeyDown (KeyUP)) - { - dir+=CVector (0, 1, 0); - find=true; - } - if (_AsyncListener.isKeyDown (KeyDOWN)) - { - dir+=CVector (0, -1, 0); - find=true; - } - if (_AsyncListener.isKeyDown (KeyRIGHT)) - { - dir+=CVector (1, 0, 0); - find=true; - } - if (_AsyncListener.isKeyDown (KeyLEFT)) - { - dir+=CVector (-1, 0, 0); - find=true; - } - if (_AsyncListener.isKeyDown (KeyNEXT)) - { - dir+=CVector (0, 0, -1); - find=true; - } - if (_AsyncListener.isKeyDown (KeyPRIOR)) - { - dir+=CVector (0, 0, 1); - find=true; - } - - // Character state setup - if (Self != NULL) - { - // modify the orientation depending on the straff - // The straff is determined by the keys that are down simultaneously - if (_AsyncListener.isKeyDown (KeyUP)) - { - if (_AsyncListener.isKeyDown (KeyLEFT)) - { - Self->AuxiliaryAngle = (float)Pi/4.0f; - } - else if (_AsyncListener.isKeyDown (KeyRIGHT)) - { - Self->AuxiliaryAngle = -(float)Pi/4.0f; - } - else - { - Self->AuxiliaryAngle = 0; - } - _IsWalking = true; - } - else if (_AsyncListener.isKeyDown (KeyDOWN)) - { - if (_AsyncListener.isKeyDown (KeyLEFT)) - { - Self->AuxiliaryAngle = (float)Pi-(float)Pi/4.0f; - } - else if (_AsyncListener.isKeyDown (KeyRIGHT)) - { - Self->AuxiliaryAngle = -(float)Pi+(float)Pi/4.0f; - } - else - { - Self->AuxiliaryAngle = (float)Pi; - } - _IsWalking = true; - } - else if (_AsyncListener.isKeyDown (KeyLEFT)) - { - Self->AuxiliaryAngle = (float)Pi/2.0f; - _IsWalking = true; - } - else if (_AsyncListener.isKeyDown (KeyRIGHT)) - { - Self->AuxiliaryAngle = -(float)Pi/2.0f; - _IsWalking = true; - } - else - { - _IsWalking = false; - } - - if (isAiming()) - Self->AuxiliaryAngle = 0.0f; - - Self->IsAiming = isAiming(); - Self->IsWalking = isWalking(); - } - - - // if is aiming - if (_AimingState) - { - find = false; - TTime newTime = CTime::getLocalTime(); - float delta = (float)(newTime-_AimingStartTime)/1000.0f; - _AimingDamage = _AimingSpeed*delta; - _AimingDamage = std::min(_AimingDamage, _AimingMax); - - // if we have to update the aiming position - if (newTime - _AimingLastUpdateTime > _AimingRefreshRate) - { - // update the last target - _AimingLastUpdateTime = newTime; - // set up the aiming position - _AimingPosition = MouseListener->getPosition()+CVector(0.0f, 0.0f, 2.0f); - // compute the target - _AimedTarget = getTarget(_AimingPosition, - MouseListener->getViewDirection(), - 100); - } - - if (Self != NULL && !_AimingInstance.empty()) - { - _AimingInstance.lookAt(MouseListener->getAimedTarget(), Camera.getMatrix().getPos()); - float scale = MouseListener->getDamage(); - _AimingInstance.setScale(scale, scale, scale); - _AimingInstance.show(); - } - } - else - { - if (Self != NULL && !_AimingInstance.empty()) - _AimingInstance.hide(); - } - - - // key found ? - if (find) - { - // Time elapsed - uint32 milli=(uint32)(CTime::getLocalTime ()-_LastTime); - - // Speed - float dPos=_Speed*(float)milli/1000.f; - - // Good direction - dir.normalize (); - dir*=dPos; - - // Orientation - dir=_Matrix.mulVector (dir); - - // New position - _Matrix.setPos (_Matrix.getPos ()+dir); - } - - // Last time - _LastTime=CTime::getLocalTime (); - -} - - -void C3dMouseListener::setPosition(const CVector &position) -{ - _Matrix.setPos(position); -} - -NLMISC::CVector C3dMouseListener::getPosition() const -{ - return _Matrix.getPos(); -} - -void C3dMouseListener::setOrientation(float angle) -{ - /// todo -} - -float C3dMouseListener::getOrientation() -{ - CVector j = getViewMatrix().getJ(); - j.z = 0.0f; - j.normalize(); - return (float)atan2(j.y, j.x); -} - -CVector C3dMouseListener::getViewDirection() -{ -// float angle = getOrientation(); -// return CVector((float)cos(angle), (float)sin(angle), (_ViewTar-_ViewHeight)/_ViewLagBehind).normed(); - return Camera.getMatrix().getJ(); -} - -void C3dMouseListener::updateCamera() -{ - CVector tpos = getPosition()+CVector(0.0f, 0.0f, _ViewTargetHeight); - CVector cpos = getPosition()+CVector(-(float)cos(getOrientation())*_ViewLagBehind, -(float)sin(getOrientation())*_ViewLagBehind, _ViewHeight); - CVector snapped = cpos, - normal; - if (CamCollisionEntity->snapToGround(snapped, normal) && (cpos.z-(snapped.z+GroundCamLimit))*normal.z < 0.0f) - { - cpos = snapped+CVector(0.0f, 0.0f, GroundCamLimit); - _ViewHeight = cpos.z - getPosition().z; - } - _Camera.lookAt(cpos, tpos); -} - -void cbUpdateMouseListenerConfig(CConfigFile::CVar &var) -{ - if (var.Name == "MouseInvert") MouseListener->setInvertMouseMode(var.asInt() != 0); - else if (var.Name == "MouseZoomStep") MouseZoomStep = var.asFloat (); - else if (var.Name == "ViewLagBehind") MouseListener->setViewLagBehind(var.asFloat ()); - else if (var.Name == "ViewHeight") MouseListener->setViewHeight(var.asFloat ()); - else if (var.Name == "ViewTargetHeight") MouseListener->setViewTargetHeight(var.asFloat ()); - else nlwarning ("Unknown variable update %s", var.Name.c_str()); -} - -void initMouseListenerConfig() -{ - ConfigFile->setCallback ("MouseInvert", cbUpdateMouseListenerConfig); - ConfigFile->setCallback ("MouseZoomStep", cbUpdateMouseListenerConfig); - ConfigFile->setCallback ("ViewLagBehind", cbUpdateMouseListenerConfig); - ConfigFile->setCallback ("ViewHeight", cbUpdateMouseListenerConfig); - ConfigFile->setCallback ("ViewTargetHeight", cbUpdateMouseListenerConfig); - - cbUpdateMouseListenerConfig(ConfigFile->getVar ("MouseInvert")); - cbUpdateMouseListenerConfig(ConfigFile->getVar ("MouseZoomStep")); - cbUpdateMouseListenerConfig(ConfigFile->getVar ("ViewLagBehind")); - cbUpdateMouseListenerConfig(ConfigFile->getVar ("ViewHeight")); - cbUpdateMouseListenerConfig(ConfigFile->getVar ("ViewTargetHeight")); -} - -void releaseMouseListenerConfig() -{ - ConfigFile->setCallback("MouseInvert", NULL); - ConfigFile->setCallback("MouseZoomStep", NULL); - ConfigFile->setCallback("ViewLagBehind", NULL); - ConfigFile->setCallback("ViewHeight", NULL); - ConfigFile->setCallback("ViewTargetHeight", NULL); -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "snowballs_client.h" +#include "mouse_listener.h" +#include "entities.h" +#include "camera.h" +#include "landscape.h" +#include "network.h" + +// +// Namespaces +// + +using namespace NLMISC; +using namespace NL3D; + +namespace SBCLIENT { + +// +// Variables +// + +static float MouseZoomStep; + +static float GroundCamLimit = 0.5f; + +// +// Functions +// + +C3dMouseListener::C3dMouseListener() +{ + // -- -- a mouse listener that can aim at the ground with a shape + // and does a bunch of other random things that should be + // done by something else, really + + // -- -- half of this thing has to be split up into a + // CKeyboardControlledMovePrimitive or something + + _Matrix.identity(); + _ModelMatrix.identity() ; + _EnableModelMatrixEdition = false ; + _HotSpot.set (0,0,0); + _Viewport.initFullScreen(); + _Frustrum.init (2.f, 2.f, -1.f, 1.f); + _MouseMode=nelStyle; + setSpeed (10.f); + _LastTime=CTime::getLocalTime (); + + _ViewLagBehind = 20.0f; + _ViewHeight = 2.0f; + _ViewTargetHeight = 3.0f; + + _AimingState = false; + _AimingDamage = 0.0f; + _AimingSpeed = 1.0f; + _AimingMax = 5.0f; + _AimingStartTime = 0; + _AimingRefreshRate = 100; + _AimingInstance = Scene->createInstance("aim.shape"); + _AimingInstance.setTransformMode(UTransformable::RotQuat); + + _X = 0.5f; + _Y = 0.5f; + _InvertedMouse = false; +} + +C3dMouseListener::~C3dMouseListener() +{ + // -- -- doesn't need to know about the snowballs specific global, + // scene shout be passed at construction to create aiming instance + // -- -- random note: aiminginstance here and aimingentity in landscape.cpp ... + // one of them obviously is in the wrong place + Scene->deleteInstance(_AimingInstance); +} + + + +void C3dMouseListener::operator ()(const CEvent& event) +{ + CEventMouse* mouseEvent=(CEventMouse*)&event; + if (event==EventMouseMoveId) // && mouseEvent->Button&leftButton!=0) + { + // Rotate Axis + CVector axis; + + axis=_Matrix.getPos(); + + // First in the hotSpot + CMatrix comeFromHotSpot=_Matrix; + comeFromHotSpot.setPos (axis); + + // Then turn along the Z axis with X mouse + CMatrix turnZ; + turnZ.identity(); + turnZ.rotateZ ((float) Pi*2.f*(_X-mouseEvent->X)); + + // Then turn along the X axis with Y mouse + CMatrix turnX; + turnX.identity(); + if (_InvertedMouse) + _ViewHeight += 3.0f*(mouseEvent->Y-_Y); + else + _ViewHeight -= 3.0f*(mouseEvent->Y-_Y); + + // Then come back from hotspot + CMatrix goToHotSpot=comeFromHotSpot; + goToHotSpot.invert(); + + // Make the matrix + CMatrix negPivot, Pivot; + negPivot.identity(); + negPivot.setPos (-axis); + Pivot.identity(); + Pivot.setPos (axis); + + // Make this transformation \\// + //_Matrix=Pivot*turnZ*negPivot*comeFromHotSpot*turnX*goToHotSpot*_Matrix; + Pivot*=turnZ; + Pivot*=negPivot; + Pivot*=comeFromHotSpot; + Pivot*=turnX; + Pivot*=goToHotSpot; + + + Pivot*=_Matrix; + _Matrix=Pivot; + // Normalize, too much transformation could give an ugly matrix.. + _Matrix.normalize (CMatrix::XYZ); + + // Update mouse position + Driver->setMousePos(0.5f, 0.5f); + _X = 0.5f; + _Y = 0.5f; + } + else if (event==EventMouseDownId) + { + // aim + _AimingState = true; + _AimingDamage = 0.0f; + _AimingStartTime = CTime::getLocalTime(); + _AimingLastUpdateTime = 0; + } + else if (event==EventMouseUpId) + { + // throw snowball +// nlinfo("damage=%f", _AimingDamage); + _AimingState = false; + _AimingStartTime = 0; + CVector direction = (_AimedTarget-_AimingPosition).normed(); + + if (isOnline ()) + { + sendSnowBall (Self->Id, _AimingPosition, _AimedTarget, SnowballSpeed, _AimingDamage); + } + else + { + shotSnowball (NextEID++, Self->Id, _AimingPosition, _AimedTarget, SnowballSpeed, _AimingDamage); + } + } + else if (event==EventMouseWheelId) + { + CEventMouseWheel* mouseEvent=(CEventMouseWheel*)&event; + _ViewLagBehind += (mouseEvent->Direction? -MouseZoomStep : +MouseZoomStep); + if (_ViewLagBehind < 2.0f) + _ViewLagBehind = 2.0f; + } +} + +void C3dMouseListener::addToServer (CEventServer& server) +{ + server.addListener (EventMouseMoveId, this); + server.addListener (EventMouseDownId, this); + server.addListener (EventMouseUpId, this); + server.addListener (EventMouseWheelId, this); + _AsyncListener.addToServer (server); +} + +void C3dMouseListener::removeFromServer (CEventServer& server) +{ + server.removeListener (EventMouseMoveId, this); + server.removeListener (EventMouseDownId, this); + server.removeListener (EventMouseUpId, this); + server.removeListener (EventMouseWheelId, this); + _AsyncListener.removeFromServer (server); +} + +const NLMISC::CMatrix& C3dMouseListener::getViewMatrix () +{ + // Return the matrix + return _Matrix; +} + +void C3dMouseListener::update() +{ + // CVector + CVector dir (0,0,0); + bool find=false; + + // -- -- what does the mouse listener have to do with the keyboard?! + + // Key pushed ? + if (_AsyncListener.isKeyDown (KeyUP)) + { + dir+=CVector (0, 1, 0); + find=true; + } + if (_AsyncListener.isKeyDown (KeyDOWN)) + { + dir+=CVector (0, -1, 0); + find=true; + } + if (_AsyncListener.isKeyDown (KeyRIGHT)) + { + dir+=CVector (1, 0, 0); + find=true; + } + if (_AsyncListener.isKeyDown (KeyLEFT)) + { + dir+=CVector (-1, 0, 0); + find=true; + } + if (_AsyncListener.isKeyDown (KeyNEXT)) + { + dir+=CVector (0, 0, -1); + find=true; + } + if (_AsyncListener.isKeyDown (KeyPRIOR)) + { + dir+=CVector (0, 0, 1); + find=true; + } + + // Character state setup + if (Self != NULL) + { + // modify the orientation depending on the straff + // The straff is determined by the keys that are down simultaneously + if (_AsyncListener.isKeyDown (KeyUP)) + { + if (_AsyncListener.isKeyDown (KeyLEFT)) + { + Self->AuxiliaryAngle = (float)Pi/4.0f; + } + else if (_AsyncListener.isKeyDown (KeyRIGHT)) + { + Self->AuxiliaryAngle = -(float)Pi/4.0f; + } + else + { + Self->AuxiliaryAngle = 0; + } + _IsWalking = true; + } + else if (_AsyncListener.isKeyDown (KeyDOWN)) + { + if (_AsyncListener.isKeyDown (KeyLEFT)) + { + Self->AuxiliaryAngle = (float)Pi-(float)Pi/4.0f; + } + else if (_AsyncListener.isKeyDown (KeyRIGHT)) + { + Self->AuxiliaryAngle = -(float)Pi+(float)Pi/4.0f; + } + else + { + Self->AuxiliaryAngle = (float)Pi; + } + _IsWalking = true; + } + else if (_AsyncListener.isKeyDown (KeyLEFT)) + { + Self->AuxiliaryAngle = (float)Pi/2.0f; + _IsWalking = true; + } + else if (_AsyncListener.isKeyDown (KeyRIGHT)) + { + Self->AuxiliaryAngle = -(float)Pi/2.0f; + _IsWalking = true; + } + else + { + _IsWalking = false; + } + + if (isAiming()) + Self->AuxiliaryAngle = 0.0f; + + Self->IsAiming = isAiming(); + Self->IsWalking = isWalking(); + } + + + // if is aiming + if (_AimingState) + { + find = false; + TTime newTime = CTime::getLocalTime(); + float delta = (float)(newTime-_AimingStartTime)/1000.0f; + _AimingDamage = _AimingSpeed*delta; + _AimingDamage = std::min(_AimingDamage, _AimingMax); + + // if we have to update the aiming position + if (newTime - _AimingLastUpdateTime > _AimingRefreshRate) + { + // update the last target + _AimingLastUpdateTime = newTime; + // set up the aiming position + _AimingPosition = MouseListener->getPosition()+CVector(0.0f, 0.0f, 2.0f); + // compute the target + _AimedTarget = getTarget(_AimingPosition, + MouseListener->getViewDirection(), + 100); + } + + if (Self != NULL && !_AimingInstance.empty()) + { + _AimingInstance.lookAt(MouseListener->getAimedTarget(), Camera.getMatrix().getPos()); + float scale = MouseListener->getDamage(); + _AimingInstance.setScale(scale, scale, scale); + _AimingInstance.show(); + } + } + else + { + if (Self != NULL && !_AimingInstance.empty()) + _AimingInstance.hide(); + } + + + // key found ? + if (find) + { + // Time elapsed + uint32 milli=(uint32)(CTime::getLocalTime ()-_LastTime); + + // Speed + float dPos=_Speed*(float)milli/1000.f; + + // Good direction + dir.normalize (); + dir*=dPos; + + // Orientation + dir=_Matrix.mulVector (dir); + + // New position + _Matrix.setPos (_Matrix.getPos ()+dir); + } + + // Last time + _LastTime=CTime::getLocalTime (); + +} + + +void C3dMouseListener::setPosition(const CVector &position) +{ + _Matrix.setPos(position); +} + +NLMISC::CVector C3dMouseListener::getPosition() const +{ + return _Matrix.getPos(); +} + +void C3dMouseListener::setOrientation(float angle) +{ + /// todo +} + +float C3dMouseListener::getOrientation() +{ + CVector j = getViewMatrix().getJ(); + j.z = 0.0f; + j.normalize(); + return (float)atan2(j.y, j.x); +} + +CVector C3dMouseListener::getViewDirection() +{ +// float angle = getOrientation(); +// return CVector((float)cos(angle), (float)sin(angle), (_ViewTar-_ViewHeight)/_ViewLagBehind).normed(); + return Camera.getMatrix().getJ(); +} + +void C3dMouseListener::updateCamera() +{ + CVector tpos = getPosition()+CVector(0.0f, 0.0f, _ViewTargetHeight); + CVector cpos = getPosition()+CVector(-(float)cos(getOrientation())*_ViewLagBehind, -(float)sin(getOrientation())*_ViewLagBehind, _ViewHeight); + CVector snapped = cpos, + normal; + if (CamCollisionEntity->snapToGround(snapped, normal) && (cpos.z-(snapped.z+GroundCamLimit))*normal.z < 0.0f) + { + cpos = snapped+CVector(0.0f, 0.0f, GroundCamLimit); + _ViewHeight = cpos.z - getPosition().z; + } + _Camera.lookAt(cpos, tpos); +} + +void cbUpdateMouseListenerConfig(CConfigFile::CVar &var) +{ + if (var.Name == "MouseInvert") MouseListener->setInvertMouseMode(var.asInt() != 0); + else if (var.Name == "MouseZoomStep") MouseZoomStep = var.asFloat (); + else if (var.Name == "ViewLagBehind") MouseListener->setViewLagBehind(var.asFloat ()); + else if (var.Name == "ViewHeight") MouseListener->setViewHeight(var.asFloat ()); + else if (var.Name == "ViewTargetHeight") MouseListener->setViewTargetHeight(var.asFloat ()); + else nlwarning ("Unknown variable update %s", var.Name.c_str()); +} + +void initMouseListenerConfig() +{ + ConfigFile->setCallback ("MouseInvert", cbUpdateMouseListenerConfig); + ConfigFile->setCallback ("MouseZoomStep", cbUpdateMouseListenerConfig); + ConfigFile->setCallback ("ViewLagBehind", cbUpdateMouseListenerConfig); + ConfigFile->setCallback ("ViewHeight", cbUpdateMouseListenerConfig); + ConfigFile->setCallback ("ViewTargetHeight", cbUpdateMouseListenerConfig); + + cbUpdateMouseListenerConfig(ConfigFile->getVar ("MouseInvert")); + cbUpdateMouseListenerConfig(ConfigFile->getVar ("MouseZoomStep")); + cbUpdateMouseListenerConfig(ConfigFile->getVar ("ViewLagBehind")); + cbUpdateMouseListenerConfig(ConfigFile->getVar ("ViewHeight")); + cbUpdateMouseListenerConfig(ConfigFile->getVar ("ViewTargetHeight")); +} + +void releaseMouseListenerConfig() +{ + ConfigFile->setCallback("MouseInvert", NULL); + ConfigFile->setCallback("MouseZoomStep", NULL); + ConfigFile->setCallback("ViewLagBehind", NULL); + ConfigFile->setCallback("ViewHeight", NULL); + ConfigFile->setCallback("ViewTargetHeight", NULL); +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/mouse_listener.h b/code/snowballs2/client/src/mouse_listener.h index eebbc7495..900582cf8 100644 --- a/code/snowballs2/client/src/mouse_listener.h +++ b/code/snowballs2/client/src/mouse_listener.h @@ -1,308 +1,308 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef MOUSE_LISTENER_H -#define MOUSE_LISTENER_H - -// -// Includes -// - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "camera.h" - -// -// External definitions -// - -using NLMISC::CVector; -using NLMISC::CMatrix; - -namespace SBCLIENT { - -// -// External classes -// - -/** - * C3dMouseListener is a listener that handle a 3d matrix with mouse events. - * This can be the view matrix, or the matrix of any object. - * \author Cyril Corvazier - * \author Nevrax France - * \date 2000 - */ -class C3dMouseListener : public NLMISC::IEventListener, public NL3D::U3dMouseListener -{ -public: - /** - * Mouse mode. - * There is two move modes: 3d editor style and NeL style. Default mode is NeL style. - * - * (nelStyle) NeL style is: - * MouseRotateHotSpot: CTRL + RIGHTMOUSE - * MouseTranslateXYHotSpot: CTRL + LEFTMOUSE - * MouseTranslateZHotSpot: CTRL + SHIFT + LEFTMOUSE - * MouseZoomHotSpot: ALT + LEFTMOUSE - * - * (edit3dStyle) 3d editor style is: - * MouseRotateHotSpot: ALT + MIDDLEMOUSE - * MouseTranslateXYHotSpot: MIDDLEMOUSE - * MouseTranslateZHotSpot: CTRL + MIDDLEMOUSE - * - * (firstPerson) First person shooter style is: - * MouseRotateView: MOUSE MOVE - * KeyUp: MOVE FORWARD - * KeyDown: MOVE BACKWARD - * Left: STRAF LEFT - * Right: STRAF RIGHT - * PageUp: MOVE UP - * PageDown: MOVE DOWN - */ - //enum TMouseMode { nelStyle, edit3d, firstPerson }; - - /** - * Constructor. - * You should call setMatrix, setFrustrum, setViewport, setHotStop and setMouseMode to initialize - * the whole object. By default, the viewmatrix is identity, the frustrum is (-1,1,-1,1,1,-1), the hot spot is (0,0,0) - * and the viewport is fullscreen. The mouse mode is set to the NelStyle. - */ - C3dMouseListener(); - - ~C3dMouseListener(); - - /// \name Setup - - /// Setup the mouse mode. No op actually. - void setMouseMode(TMouseMode mouseMode) {} - - /// Setup the camera to be used - void setCamera (NL3D::UCamera camera) { _Camera = camera; } - - /** - * Set both the current view matrix to use. - * \param matrix is the matrix to set. - * \see getViewMatrix() - */ - void setMatrix (const NLMISC::CMatrix& matrix) - { - _Matrix=matrix; - } - - /** Set the model matrix only - * - * param matrix is the matrix to set. - * getModelMatrix() - */ - void setModelMatrix(const NLMISC::CMatrix& matrix) - { - _ModelMatrix = matrix ; - } - - /** - * Set the current frustrum to use. - * \param frustrum is the frustrum. - */ - void setFrustrum (const NL3D::CFrustum& frustrum) - { - _Frustrum=frustrum; - } - - /** - * Set the viewport in use in the window. By default, the viewport is fullwindow. - * \param viewport is the viewport to use. All events outside the viewport are ignored. - */ - void setViewport (const NL3D::CViewport& viewport) - { - _Viewport=viewport; - } - - /** - * Set the current hot spot. - * \param hotSpot is the target to use when the mouse move. It can be for exemple the center. - * of the selected object. The hotspot is not modified by mouse events. - * \see getViewMatrix() - */ - void setHotSpot (const CVector& hotSpot) - { - _HotSpot=hotSpot; - } - - - /** - * Set the speed for first person mode. Default 10.f; - * \param speed is in unit per second. - * \see TMouseMode - */ - void setSpeed (float speed) - { - _Speed=speed; - } - - /// \name Get - - /** - * Get the current view matrix. - * \return The current view matrix. - * \see setMatrix() - */ - const NLMISC::CMatrix& getViewMatrix () ; - - - /** - * Get the current model matrix. - * \return The current view matrix. - * \see setModelMatrix() - */ - const NLMISC::CMatrix& getModelMatrix() - { - return _ModelMatrix ; - } - - NLMISC::IEventListener &getEventListenerInterface() { return *this; } - - /** - * Get the current hot spot. - * \return the target used when the mouse move. It can be for exemple the center. - * of the selected object. The hotspot is not modified by mouse events. - * \see getViewMatrix() - */ - CVector getHotSpot () const - { - return _HotSpot; - } - - /** - * Register the listener to the server. - */ - void addToServer (NLMISC::CEventServer& server); - - /** - * Unregister the listener to the server. - */ - void removeFromServer (NLMISC::CEventServer& server); - - - /// update the position of the listener - void setPosition(const NLMISC::CVector &position); - /// get the position of the listener - NLMISC::CVector getPosition() const; - /// set the orientation angle of the listener - void setOrientation(float angle); - /// get orientiation angle - float getOrientation(); - /// get the view direction - CVector getViewDirection(); - /// get the aiming state - bool getAimingState() const { return _AimingState; } - /// get the target position (only if getAimingState() == true) - CVector getAimedTarget() const { return _AimedTarget; } - /// get the damage value - float getDamage() const { return _AimingDamage; } - - // get the various character states - bool isAiming() const { return _AimingState; } - bool isWalking() const { return _IsWalking; } - - /// Updates the mouselistener - void update(); - - /// Updates the camera - void updateCamera(); - - // - bool getInvertMouseMode() const { return _InvertedMouse; } - void setInvertMouseMode(bool invertMouse) { _InvertedMouse = invertMouse; } - - /// get the ViewLagBehind of the camera - float getViewLagBehind() const { return _ViewLagBehind; } - /// set the ViewLagBehind of the camera - void setViewLagBehind(float viewLagBehind) { _ViewLagBehind = viewLagBehind; } - /// get the ViewHeight of the camera - float getViewHeight() const { return _ViewHeight; } - /// set the ViewHeight of the camera - void setViewHeight(float viewHeight) { _ViewHeight = viewHeight; } - /// get the ViewTargetHeight of the camera - float getViewTargetHeight() const { return _ViewTargetHeight; } - /// set the ViewTargetHeight of the camera - void setViewTargetHeight(float viewTargetHeight) { _ViewTargetHeight = viewTargetHeight; } - - -private: - /// Internal use - virtual void operator ()(const NLMISC::CEvent& event); - - - - CMatrix _Matrix; - CMatrix _ModelMatrix ; - bool _EnableModelMatrixEdition ; - NL3D::CFrustum _Frustrum; - CVector _HotSpot; - NL3D::CViewport _Viewport; - bool _LeftPushed; - bool _MiddlePushed; - bool _RightPushed; - float _X; - float _Y; - float _Speed; - uint64 _LastTime; - TMouseMode _MouseMode; - NLMISC::CEventListenerAsync _AsyncListener; - - // viewing camera attributes - NL3D::UCamera _Camera; - float _ViewLagBehind; - float _ViewHeight; - float _ViewTargetHeight; - - // aiming system attributes - bool _AimingState; - float _AimingDamage; - float _AimingSpeed; - float _AimingMax; - NLMISC::TTime _AimingStartTime; - NLMISC::TTime _AimingLastUpdateTime; - NLMISC::TTime _AimingRefreshRate; - NLMISC::CVector _AimedTarget; - NLMISC::CVector _AimingPosition; - NL3D::UInstance _AimingInstance; - bool _InvertedMouse; - - // character state - bool _IsWalking; -}; - -// -// External functions -// - -void initMouseListenerConfig(); -void releaseMouseListenerConfig(); - -} /* namespace SBCLIENT */ - -#endif // MOUSE_LISTENER_H - -/* End of mouse_listener.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef MOUSE_LISTENER_H +#define MOUSE_LISTENER_H + +// +// Includes +// + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "camera.h" + +// +// External definitions +// + +using NLMISC::CVector; +using NLMISC::CMatrix; + +namespace SBCLIENT { + +// +// External classes +// + +/** + * C3dMouseListener is a listener that handle a 3d matrix with mouse events. + * This can be the view matrix, or the matrix of any object. + * \author Cyril Corvazier + * \author Nevrax France + * \date 2000 + */ +class C3dMouseListener : public NLMISC::IEventListener, public NL3D::U3dMouseListener +{ +public: + /** + * Mouse mode. + * There is two move modes: 3d editor style and NeL style. Default mode is NeL style. + * + * (nelStyle) NeL style is: + * MouseRotateHotSpot: CTRL + RIGHTMOUSE + * MouseTranslateXYHotSpot: CTRL + LEFTMOUSE + * MouseTranslateZHotSpot: CTRL + SHIFT + LEFTMOUSE + * MouseZoomHotSpot: ALT + LEFTMOUSE + * + * (edit3dStyle) 3d editor style is: + * MouseRotateHotSpot: ALT + MIDDLEMOUSE + * MouseTranslateXYHotSpot: MIDDLEMOUSE + * MouseTranslateZHotSpot: CTRL + MIDDLEMOUSE + * + * (firstPerson) First person shooter style is: + * MouseRotateView: MOUSE MOVE + * KeyUp: MOVE FORWARD + * KeyDown: MOVE BACKWARD + * Left: STRAF LEFT + * Right: STRAF RIGHT + * PageUp: MOVE UP + * PageDown: MOVE DOWN + */ + //enum TMouseMode { nelStyle, edit3d, firstPerson }; + + /** + * Constructor. + * You should call setMatrix, setFrustrum, setViewport, setHotStop and setMouseMode to initialize + * the whole object. By default, the viewmatrix is identity, the frustrum is (-1,1,-1,1,1,-1), the hot spot is (0,0,0) + * and the viewport is fullscreen. The mouse mode is set to the NelStyle. + */ + C3dMouseListener(); + + ~C3dMouseListener(); + + /// \name Setup + + /// Setup the mouse mode. No op actually. + void setMouseMode(TMouseMode mouseMode) {} + + /// Setup the camera to be used + void setCamera (NL3D::UCamera camera) { _Camera = camera; } + + /** + * Set both the current view matrix to use. + * \param matrix is the matrix to set. + * \see getViewMatrix() + */ + void setMatrix (const NLMISC::CMatrix& matrix) + { + _Matrix=matrix; + } + + /** Set the model matrix only + * + * param matrix is the matrix to set. + * getModelMatrix() + */ + void setModelMatrix(const NLMISC::CMatrix& matrix) + { + _ModelMatrix = matrix ; + } + + /** + * Set the current frustrum to use. + * \param frustrum is the frustrum. + */ + void setFrustrum (const NL3D::CFrustum& frustrum) + { + _Frustrum=frustrum; + } + + /** + * Set the viewport in use in the window. By default, the viewport is fullwindow. + * \param viewport is the viewport to use. All events outside the viewport are ignored. + */ + void setViewport (const NL3D::CViewport& viewport) + { + _Viewport=viewport; + } + + /** + * Set the current hot spot. + * \param hotSpot is the target to use when the mouse move. It can be for exemple the center. + * of the selected object. The hotspot is not modified by mouse events. + * \see getViewMatrix() + */ + void setHotSpot (const CVector& hotSpot) + { + _HotSpot=hotSpot; + } + + + /** + * Set the speed for first person mode. Default 10.f; + * \param speed is in unit per second. + * \see TMouseMode + */ + void setSpeed (float speed) + { + _Speed=speed; + } + + /// \name Get + + /** + * Get the current view matrix. + * \return The current view matrix. + * \see setMatrix() + */ + const NLMISC::CMatrix& getViewMatrix () ; + + + /** + * Get the current model matrix. + * \return The current view matrix. + * \see setModelMatrix() + */ + const NLMISC::CMatrix& getModelMatrix() + { + return _ModelMatrix ; + } + + NLMISC::IEventListener &getEventListenerInterface() { return *this; } + + /** + * Get the current hot spot. + * \return the target used when the mouse move. It can be for exemple the center. + * of the selected object. The hotspot is not modified by mouse events. + * \see getViewMatrix() + */ + CVector getHotSpot () const + { + return _HotSpot; + } + + /** + * Register the listener to the server. + */ + void addToServer (NLMISC::CEventServer& server); + + /** + * Unregister the listener to the server. + */ + void removeFromServer (NLMISC::CEventServer& server); + + + /// update the position of the listener + void setPosition(const NLMISC::CVector &position); + /// get the position of the listener + NLMISC::CVector getPosition() const; + /// set the orientation angle of the listener + void setOrientation(float angle); + /// get orientiation angle + float getOrientation(); + /// get the view direction + CVector getViewDirection(); + /// get the aiming state + bool getAimingState() const { return _AimingState; } + /// get the target position (only if getAimingState() == true) + CVector getAimedTarget() const { return _AimedTarget; } + /// get the damage value + float getDamage() const { return _AimingDamage; } + + // get the various character states + bool isAiming() const { return _AimingState; } + bool isWalking() const { return _IsWalking; } + + /// Updates the mouselistener + void update(); + + /// Updates the camera + void updateCamera(); + + // + bool getInvertMouseMode() const { return _InvertedMouse; } + void setInvertMouseMode(bool invertMouse) { _InvertedMouse = invertMouse; } + + /// get the ViewLagBehind of the camera + float getViewLagBehind() const { return _ViewLagBehind; } + /// set the ViewLagBehind of the camera + void setViewLagBehind(float viewLagBehind) { _ViewLagBehind = viewLagBehind; } + /// get the ViewHeight of the camera + float getViewHeight() const { return _ViewHeight; } + /// set the ViewHeight of the camera + void setViewHeight(float viewHeight) { _ViewHeight = viewHeight; } + /// get the ViewTargetHeight of the camera + float getViewTargetHeight() const { return _ViewTargetHeight; } + /// set the ViewTargetHeight of the camera + void setViewTargetHeight(float viewTargetHeight) { _ViewTargetHeight = viewTargetHeight; } + + +private: + /// Internal use + virtual void operator ()(const NLMISC::CEvent& event); + + + + CMatrix _Matrix; + CMatrix _ModelMatrix ; + bool _EnableModelMatrixEdition ; + NL3D::CFrustum _Frustrum; + CVector _HotSpot; + NL3D::CViewport _Viewport; + bool _LeftPushed; + bool _MiddlePushed; + bool _RightPushed; + float _X; + float _Y; + float _Speed; + uint64 _LastTime; + TMouseMode _MouseMode; + NLMISC::CEventListenerAsync _AsyncListener; + + // viewing camera attributes + NL3D::UCamera _Camera; + float _ViewLagBehind; + float _ViewHeight; + float _ViewTargetHeight; + + // aiming system attributes + bool _AimingState; + float _AimingDamage; + float _AimingSpeed; + float _AimingMax; + NLMISC::TTime _AimingStartTime; + NLMISC::TTime _AimingLastUpdateTime; + NLMISC::TTime _AimingRefreshRate; + NLMISC::CVector _AimedTarget; + NLMISC::CVector _AimingPosition; + NL3D::UInstance _AimingInstance; + bool _InvertedMouse; + + // character state + bool _IsWalking; +}; + +// +// External functions +// + +void initMouseListenerConfig(); +void releaseMouseListenerConfig(); + +} /* namespace SBCLIENT */ + +#endif // MOUSE_LISTENER_H + +/* End of mouse_listener.h */ diff --git a/code/snowballs2/client/src/network.cpp b/code/snowballs2/client/src/network.cpp index fb3fa03e2..819b89f29 100644 --- a/code/snowballs2/client/src/network.cpp +++ b/code/snowballs2/client/src/network.cpp @@ -1,420 +1,420 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#include - -#include "snowballs_client.h" -#include "commands.h" -#include "network.h" -#include "entities.h" -#include "interface.h" -#include "graph.h" -#include "mouse_listener.h" - -// -// Namespaces -// - -using namespace std; -using namespace NLMISC; -using namespace NLNET; -using namespace NL3D; - -namespace SBCLIENT { - -// -- -- random note: most of this needs to change completely anyway - -// -// Variables -// - -CCallbackClient *Connection = NULL; - -// -// Functions -// - -static void cbClientDisconnected (TSockId from, void *arg) -{ - nlwarning ("You lost the connection to the server"); - - askString ("You lost the connection to the server!!!", "", 2, CRGBA(64,0,0,128)); -} - -static void cbAddEntity (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - uint32 id; - string name; - uint8 race; - CVector startPosition; - - msgin.serial (id, name, race, startPosition); - -// nlinfo ("%s", stringFromVector (msgin.bufferAsVector())); - -// nlinfo ("Receive add entity %u '%s' %s (%f,%f,%f)", id, name.c_str(), race==0?"penguin":"gnu", startPosition.x, startPosition.y, startPosition.z); - - nlinfo ("New player named '%s' comes in at position (%8.2f, %8.2f, %8.2f)", name.c_str(), startPosition.x, startPosition.y, startPosition.z); - - if (Self == NULL && name == Login.toUtf8()) - { - addEntity(id, name, CEntity::Self, startPosition, startPosition); - } - else - { - addEntity(id, name, CEntity::Other, startPosition, startPosition); - } -} - -static void cbRemoveEntity (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - uint32 id; - - msgin.serial (id); - -// nlinfo ("Receive remove entity %u", id); - - EIT eit = findEntity (id); - CEntity &entity = (*eit).second; - - nlinfo ("Player named '%s' goes offline", entity.Name.c_str()); - - removeEntity (id); -} - -static void cbEntityPos (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - uint32 id; - CVector position; - float angle; - uint32 state; - - msgin.serial (id, position, angle, state); - -// nlinfo ("(%5d) Receive entity pos %u (%f,%f,%f) %f, %u", msgin.length(), id, position.x, position.y, position.z, angle, state); - - if (Self->Id == id) - { - // receive my info, ignore them, i know where i am - return; - } - - EIT eit = findEntity (id, false); - if (eit == Entities.end ()) - { - nlwarning ("can't find entity %u", id); - } - else - { - CEntity &entity = (*eit).second; - - entity.ServerPosition = position; - entity.AuxiliaryAngle = angle; - if (state&1) - { - entity.IsAiming = true; - entity.IsWalking = false; - } - } -} - -static void cbEntityTeleport(CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - // temp - uint32 id; - CVector position; - msgin.serial(id, position); - nldebug("Received entity %u teleport %f,%f,%f", id, position.x, position.y, position.z); - EIT eit = findEntity(id, false); - if (eit == Entities.end()) nlwarning("can't find entity %u", id); - else - { - CEntity &entity = eit->second; - entity.ServerPosition = position; - entity.Position = position; - entity.MovePrimitive->setGlobalPosition(CVectorD(position.x, position.y, position.z), 0); - if (&entity == Self) MouseListener->setPosition(position); - } -} - -static void cbHit(CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - uint32 sid, eid; - bool direct; - - msgin.serial (sid, eid, direct); - -// nlinfo ("Receive hit msg %u %u %d", sid, eid, direct); - - EIT eit = findEntity (eid); - CEntity &entity = (*eit).second; - - if (!entity.AnimQueue.empty()) - { - EAnim a = entity.AnimQueue.front (); - playAnimation (entity, HitAnim, true); - playAnimation (entity, a); - } - else - { - playAnimation (entity, HitAnim, true); - } - - removeEntity (sid); -} - -static void cbSnowball (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - uint32 eid, sid; - CVector position, target; - float speed, deflagRadius; - - msgin.serial (sid, eid, position, target, speed, deflagRadius); - -// nlinfo ("Receive a snowball message"); - - shotSnowball (sid, eid, position, target, speed, deflagRadius); -} - -static void cbChat (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - string line; - msgin.serial (line); - addLine (line); -} - -static void cbIdentification (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) -{ - uint32 id; - msgin.serial (id); - -// nlinfo ("my online id is %u", id); - -// if (Self == NULL) -// nlerror ("Self is NULL"); -// -// if (Self->Id != id) -// { -//// nlinfo ("remaping my entity from %u to %u", Self->Id, id); -// -// // copy my old entity -// CEntity me = *Self; -// -// // set my new online id -// me.Id = id; -// -// // add my new entity in the array -// EIT eit = (Entities.insert (make_pair (id, me))).first; -// -// // remove my old entity -// Entities.erase (Self->Id); -// -// // remap Self -// Self = &((*eit).second); -// } - - // send to the network my entity - std::string login_name(Login.toUtf8()); - sendAddEntity(id, login_name, 1); -} - -// Array that contains all callback that could comes from the server -static TCallbackItem ClientCallbackArray[] = -{ - { "ADD_ENTITY", cbAddEntity }, - { "REMOVE_ENTITY", cbRemoveEntity }, - { "ENTITY_POS", cbEntityPos }, - { "ENTITY_TP", cbEntityTeleport }, - { "HIT", cbHit }, - { "CHAT", cbChat }, - { "SNOWBALL", cbSnowball }, - { "IDENTIFICATION", cbIdentification }, -}; - - -bool isOnline () -{ - return Connection != NULL && Connection->connected (); -} - -void sendAddEntity (uint32 id, string &name, uint8 race) -{ - if (!isOnline ()) return; - - CMessage msgout("ADD_ENTITY"); - msgout.serial(id, name, race); - Connection->send(msgout); -} - -void sendChatLine (string Line) -{ - if (!isOnline ()) return; - - CMessage msgout ("CHAT"); - string s; - if (Self != NULL) - { - string line = Self->Name + string("> ") + Line; - msgout.serial (line); - } - else - { - string line = string("Unknown> ") + Line; - msgout.serial (line); - } - - Connection->send (msgout); -} - -void sendEntityPos (CEntity &entity) -{ - if (!isOnline ()) return; - - // is aiming? is launching etc... - uint32 state = 0; - state |= (entity.IsAiming?1:0); - - CMessage msgout ("ENTITY_POS"); - msgout.serial (entity.Id, entity.Position, entity.Angle, state); - - Connection->send (msgout); - -// nlinfo("(%5d) Sending pos to network (%f,%f,%f, %f), %u", msgout.length(), entity.Position.x, entity.Position.y, entity.Position.z, entity.Angle, state); -} - -void sendSnowBall (uint32 eid, const NLMISC::CVector &position, const NLMISC::CVector &target, float speed, float deflagRadius) -{ - if (!isOnline ()) return; - - CMessage msgout ("SNOWBALL"); - msgout.serial (eid, const_cast(position), const_cast(target), speed, deflagRadius); - Connection->send (msgout); - -// nlinfo("Sending snowball to network (%f,%f,%f) to (%f,%f,%f) with %f %f", position.x, position.y, position.z, target.x, target.y, target.z, speed, deflagRadius); -} - - -TTime LastPosSended; - -void initNetwork(const std::string &lc, const std::string &addr) -{ - // if lc and addr is valid, directly connect to the fs - Connection = new CCallbackClient; - Connection->addCallbackArray (ClientCallbackArray, sizeof (ClientCallbackArray) / sizeof (ClientCallbackArray[0])); - Connection->setDisconnectionCallback (cbClientDisconnected, NULL); - - string fsaddr; - if (addr.empty()) - fsaddr = ConfigFile->getVar("FSHost").asString (); - else - fsaddr = addr; - - if(fsaddr.find (":") == string::npos) - { - fsaddr += ":37000"; - } - - CLoginCookie loginCookie; - if (!lc.empty ()) - { - loginCookie.setFromString (lc); - } - - string res = CLoginClient::connectToShard (loginCookie, fsaddr, *Connection); - if (!res.empty ()) - { - string err = string ("Connection to shard failed: ") + res; - askString (err, "", 2, CRGBA(64,0,0,128)); - } - else - { - // we remove all offline entities - removeAllEntitiesExceptUs (); - - askString ("You are online!!!", "", 2, CRGBA(0,64,0,128)); - // now we have to wait the identification message to know my id - } - - LastPosSended = 0; -} - -void updateNetwork() -{ - if (Connection != NULL) - { - Connection->update (); - - sint64 newBytesDownloaded = (sint64) Connection->newBytesDownloaded (); - sint64 newBytesUploaded = (sint64) Connection->newBytesUploaded (); - - TextContext->setHotSpot (UTextContext::MiddleTop); - TextContext->setColor (CRGBA(255, 255, 255, 255)); - TextContext->setFontSize (14); - TextContext->printfAt (0.5f, 0.99f, "d:%"NL_I64"u u:%"NL_I64"u / d:%"NL_I64"u u:%"NL_I64"u / d:%"NL_I64"u u:%"NL_I64"u", - Connection->bytesDownloaded (), Connection->bytesUploaded (), - Connection->getBytesReceived (),Connection->getBytesSent (), - newBytesDownloaded, newBytesUploaded); - - DownloadGraph.addValue ((float)newBytesDownloaded); - UploadGraph.addValue ((float)newBytesUploaded); - - if (isOnline () && Self != NULL) - { - static float oldAngle = 0.0f; - - if ((Self->Angle != oldAngle || Self->IsAiming || Self->IsWalking) && CTime::getLocalTime () > LastPosSended + 100) - { - sendEntityPos (*Self); - - LastPosSended = CTime::getLocalTime (); - - oldAngle = Self->Angle; - } - } - } -} - -void releaseNetwork() -{ - if (Connection != NULL) - { - if (Connection->connected ()) - Connection->disconnect (); - - delete Connection; - Connection = NULL; - } -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include + +#include "snowballs_client.h" +#include "commands.h" +#include "network.h" +#include "entities.h" +#include "interface.h" +#include "graph.h" +#include "mouse_listener.h" + +// +// Namespaces +// + +using namespace std; +using namespace NLMISC; +using namespace NLNET; +using namespace NL3D; + +namespace SBCLIENT { + +// -- -- random note: most of this needs to change completely anyway + +// +// Variables +// + +CCallbackClient *Connection = NULL; + +// +// Functions +// + +static void cbClientDisconnected (TSockId from, void *arg) +{ + nlwarning ("You lost the connection to the server"); + + askString ("You lost the connection to the server!!!", "", 2, CRGBA(64,0,0,128)); +} + +static void cbAddEntity (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + uint32 id; + string name; + uint8 race; + CVector startPosition; + + msgin.serial (id, name, race, startPosition); + +// nlinfo ("%s", stringFromVector (msgin.bufferAsVector())); + +// nlinfo ("Receive add entity %u '%s' %s (%f,%f,%f)", id, name.c_str(), race==0?"penguin":"gnu", startPosition.x, startPosition.y, startPosition.z); + + nlinfo ("New player named '%s' comes in at position (%8.2f, %8.2f, %8.2f)", name.c_str(), startPosition.x, startPosition.y, startPosition.z); + + if (Self == NULL && name == Login.toUtf8()) + { + addEntity(id, name, CEntity::Self, startPosition, startPosition); + } + else + { + addEntity(id, name, CEntity::Other, startPosition, startPosition); + } +} + +static void cbRemoveEntity (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + uint32 id; + + msgin.serial (id); + +// nlinfo ("Receive remove entity %u", id); + + EIT eit = findEntity (id); + CEntity &entity = (*eit).second; + + nlinfo ("Player named '%s' goes offline", entity.Name.c_str()); + + removeEntity (id); +} + +static void cbEntityPos (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + uint32 id; + CVector position; + float angle; + uint32 state; + + msgin.serial (id, position, angle, state); + +// nlinfo ("(%5d) Receive entity pos %u (%f,%f,%f) %f, %u", msgin.length(), id, position.x, position.y, position.z, angle, state); + + if (Self->Id == id) + { + // receive my info, ignore them, i know where i am + return; + } + + EIT eit = findEntity (id, false); + if (eit == Entities.end ()) + { + nlwarning ("can't find entity %u", id); + } + else + { + CEntity &entity = (*eit).second; + + entity.ServerPosition = position; + entity.AuxiliaryAngle = angle; + if (state&1) + { + entity.IsAiming = true; + entity.IsWalking = false; + } + } +} + +static void cbEntityTeleport(CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + // temp + uint32 id; + CVector position; + msgin.serial(id, position); + nldebug("Received entity %u teleport %f,%f,%f", id, position.x, position.y, position.z); + EIT eit = findEntity(id, false); + if (eit == Entities.end()) nlwarning("can't find entity %u", id); + else + { + CEntity &entity = eit->second; + entity.ServerPosition = position; + entity.Position = position; + entity.MovePrimitive->setGlobalPosition(CVectorD(position.x, position.y, position.z), 0); + if (&entity == Self) MouseListener->setPosition(position); + } +} + +static void cbHit(CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + uint32 sid, eid; + bool direct; + + msgin.serial (sid, eid, direct); + +// nlinfo ("Receive hit msg %u %u %d", sid, eid, direct); + + EIT eit = findEntity (eid); + CEntity &entity = (*eit).second; + + if (!entity.AnimQueue.empty()) + { + EAnim a = entity.AnimQueue.front (); + playAnimation (entity, HitAnim, true); + playAnimation (entity, a); + } + else + { + playAnimation (entity, HitAnim, true); + } + + removeEntity (sid); +} + +static void cbSnowball (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + uint32 eid, sid; + CVector position, target; + float speed, deflagRadius; + + msgin.serial (sid, eid, position, target, speed, deflagRadius); + +// nlinfo ("Receive a snowball message"); + + shotSnowball (sid, eid, position, target, speed, deflagRadius); +} + +static void cbChat (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + string line; + msgin.serial (line); + addLine (line); +} + +static void cbIdentification (CMessage &msgin, TSockId from, CCallbackNetBase &netbase) +{ + uint32 id; + msgin.serial (id); + +// nlinfo ("my online id is %u", id); + +// if (Self == NULL) +// nlerror ("Self is NULL"); +// +// if (Self->Id != id) +// { +//// nlinfo ("remaping my entity from %u to %u", Self->Id, id); +// +// // copy my old entity +// CEntity me = *Self; +// +// // set my new online id +// me.Id = id; +// +// // add my new entity in the array +// EIT eit = (Entities.insert (make_pair (id, me))).first; +// +// // remove my old entity +// Entities.erase (Self->Id); +// +// // remap Self +// Self = &((*eit).second); +// } + + // send to the network my entity + std::string login_name(Login.toUtf8()); + sendAddEntity(id, login_name, 1); +} + +// Array that contains all callback that could comes from the server +static TCallbackItem ClientCallbackArray[] = +{ + { "ADD_ENTITY", cbAddEntity }, + { "REMOVE_ENTITY", cbRemoveEntity }, + { "ENTITY_POS", cbEntityPos }, + { "ENTITY_TP", cbEntityTeleport }, + { "HIT", cbHit }, + { "CHAT", cbChat }, + { "SNOWBALL", cbSnowball }, + { "IDENTIFICATION", cbIdentification }, +}; + + +bool isOnline () +{ + return Connection != NULL && Connection->connected (); +} + +void sendAddEntity (uint32 id, string &name, uint8 race) +{ + if (!isOnline ()) return; + + CMessage msgout("ADD_ENTITY"); + msgout.serial(id, name, race); + Connection->send(msgout); +} + +void sendChatLine (string Line) +{ + if (!isOnline ()) return; + + CMessage msgout ("CHAT"); + string s; + if (Self != NULL) + { + string line = Self->Name + string("> ") + Line; + msgout.serial (line); + } + else + { + string line = string("Unknown> ") + Line; + msgout.serial (line); + } + + Connection->send (msgout); +} + +void sendEntityPos (CEntity &entity) +{ + if (!isOnline ()) return; + + // is aiming? is launching etc... + uint32 state = 0; + state |= (entity.IsAiming?1:0); + + CMessage msgout ("ENTITY_POS"); + msgout.serial (entity.Id, entity.Position, entity.Angle, state); + + Connection->send (msgout); + +// nlinfo("(%5d) Sending pos to network (%f,%f,%f, %f), %u", msgout.length(), entity.Position.x, entity.Position.y, entity.Position.z, entity.Angle, state); +} + +void sendSnowBall (uint32 eid, const NLMISC::CVector &position, const NLMISC::CVector &target, float speed, float deflagRadius) +{ + if (!isOnline ()) return; + + CMessage msgout ("SNOWBALL"); + msgout.serial (eid, const_cast(position), const_cast(target), speed, deflagRadius); + Connection->send (msgout); + +// nlinfo("Sending snowball to network (%f,%f,%f) to (%f,%f,%f) with %f %f", position.x, position.y, position.z, target.x, target.y, target.z, speed, deflagRadius); +} + + +TTime LastPosSended; + +void initNetwork(const std::string &lc, const std::string &addr) +{ + // if lc and addr is valid, directly connect to the fs + Connection = new CCallbackClient; + Connection->addCallbackArray (ClientCallbackArray, sizeof (ClientCallbackArray) / sizeof (ClientCallbackArray[0])); + Connection->setDisconnectionCallback (cbClientDisconnected, NULL); + + string fsaddr; + if (addr.empty()) + fsaddr = ConfigFile->getVar("FSHost").asString (); + else + fsaddr = addr; + + if(fsaddr.find (":") == string::npos) + { + fsaddr += ":37000"; + } + + CLoginCookie loginCookie; + if (!lc.empty ()) + { + loginCookie.setFromString (lc); + } + + string res = CLoginClient::connectToShard (loginCookie, fsaddr, *Connection); + if (!res.empty ()) + { + string err = string ("Connection to shard failed: ") + res; + askString (err, "", 2, CRGBA(64,0,0,128)); + } + else + { + // we remove all offline entities + removeAllEntitiesExceptUs (); + + askString ("You are online!!!", "", 2, CRGBA(0,64,0,128)); + // now we have to wait the identification message to know my id + } + + LastPosSended = 0; +} + +void updateNetwork() +{ + if (Connection != NULL) + { + Connection->update (); + + sint64 newBytesDownloaded = (sint64) Connection->newBytesDownloaded (); + sint64 newBytesUploaded = (sint64) Connection->newBytesUploaded (); + + TextContext->setHotSpot (UTextContext::MiddleTop); + TextContext->setColor (CRGBA(255, 255, 255, 255)); + TextContext->setFontSize (14); + TextContext->printfAt (0.5f, 0.99f, "d:%"NL_I64"u u:%"NL_I64"u / d:%"NL_I64"u u:%"NL_I64"u / d:%"NL_I64"u u:%"NL_I64"u", + Connection->bytesDownloaded (), Connection->bytesUploaded (), + Connection->getBytesReceived (),Connection->getBytesSent (), + newBytesDownloaded, newBytesUploaded); + + DownloadGraph.addValue ((float)newBytesDownloaded); + UploadGraph.addValue ((float)newBytesUploaded); + + if (isOnline () && Self != NULL) + { + static float oldAngle = 0.0f; + + if ((Self->Angle != oldAngle || Self->IsAiming || Self->IsWalking) && CTime::getLocalTime () > LastPosSended + 100) + { + sendEntityPos (*Self); + + LastPosSended = CTime::getLocalTime (); + + oldAngle = Self->Angle; + } + } + } +} + +void releaseNetwork() +{ + if (Connection != NULL) + { + if (Connection->connected ()) + Connection->disconnect (); + + delete Connection; + Connection = NULL; + } +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/network.h b/code/snowballs2/client/src/network.h index 34186ef46..1c22eb273 100644 --- a/code/snowballs2/client/src/network.h +++ b/code/snowballs2/client/src/network.h @@ -1,80 +1,80 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef NETWORK_H -#define NETWORK_H - -// -// Includes -// - -#include - -#include - -#include "entities.h" - -// -// External definitions -// - -namespace NLMISC -{ - class CVector; -} - -namespace NLNET -{ - class CCallbackClient; -} - -namespace SBCLIENT { - -// -// External variables -// - -// Pointer to the connection to the server -extern NLNET::CCallbackClient *Connection; - -// -// External functions -// - -// Return true if the client is online -bool isOnline (); - -// Send the new entity (the player) -void sendAddEntity (uint32 id, std::string &name, uint8 race); - -// Send a chat line to the server -void sendChatLine (std::string Line); - -// Send the user entity position to the server -void sendEntityPos (CEntity &entity); - -// Send a new snowball to the server -void sendSnowBall (uint32 eid, const NLMISC::CVector &position, const NLMISC::CVector &target, float speed, float deflagRadius); - -void initNetwork (const std::string &lc, const std::string &addr); -void updateNetwork (); -void releaseNetwork (); - -} /* namespace SBCLIENT */ - -#endif // NETWORK_H - -/* End of network.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef NETWORK_H +#define NETWORK_H + +// +// Includes +// + +#include + +#include + +#include "entities.h" + +// +// External definitions +// + +namespace NLMISC +{ + class CVector; +} + +namespace NLNET +{ + class CCallbackClient; +} + +namespace SBCLIENT { + +// +// External variables +// + +// Pointer to the connection to the server +extern NLNET::CCallbackClient *Connection; + +// +// External functions +// + +// Return true if the client is online +bool isOnline (); + +// Send the new entity (the player) +void sendAddEntity (uint32 id, std::string &name, uint8 race); + +// Send a chat line to the server +void sendChatLine (std::string Line); + +// Send the user entity position to the server +void sendEntityPos (CEntity &entity); + +// Send a new snowball to the server +void sendSnowBall (uint32 eid, const NLMISC::CVector &position, const NLMISC::CVector &target, float speed, float deflagRadius); + +void initNetwork (const std::string &lc, const std::string &addr); +void updateNetwork (); +void releaseNetwork (); + +} /* namespace SBCLIENT */ + +#endif // NETWORK_H + +/* End of network.h */ diff --git a/code/snowballs2/client/src/pacs.cpp b/code/snowballs2/client/src/pacs.cpp index 6426e742c..8c14b4c03 100644 --- a/code/snowballs2/client/src/pacs.cpp +++ b/code/snowballs2/client/src/pacs.cpp @@ -1,184 +1,184 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include -#include - -#include "snowballs_client.h" -#include "landscape.h" -#include "pacs.h" -#include "entities.h" - -// -// Namespaces -// - -using namespace std; -using namespace NLMISC; -using namespace NL3D; -using namespace NLPACS; - -namespace SBCLIENT { - -extern ULandscape *Landscape; - -/******************************************************************* - * GLOBALS * - *******************************************************************/ - -// The retriever bank used in the world -URetrieverBank *RetrieverBank = NULL; -// The global retriever used for pacs -UGlobalRetriever *GlobalRetriever = NULL; -// The move container used for dynamic collisions -UMoveContainer *MoveContainer = NULL; - -// The collision manager for ground snapping -UVisualCollisionManager *VisualCollisionManager = NULL; - -/******************************************************************* - * COLLISIONS * - *******************************************************************/ - -// The collision primitive for the instances in the landscape -static vector _InstancesMovePrimitives; - -// -// Functions -// - -void initPACS() -{ - // check stuff we need for this to init correctly - nlassert(Landscape); - nlassert(ConfigFile); - nlassert(Scene); - - // check stuff we can't have yet - nlassert(!RetrieverBank); - nlassert(!GlobalRetriever); - nlassert(!MoveContainer); - nlassert(!VisualCollisionManager); - - // init the global retriever - RetrieverBank = URetrieverBank::createRetrieverBank(ConfigFile->getVar("RetrieverBankName").asString().c_str()); - nlassert(RetrieverBank); - - // create the retriever bank - GlobalRetriever = UGlobalRetriever::createGlobalRetriever(ConfigFile->getVar("GlobalRetrieverName").asString().c_str(), RetrieverBank); - nlassert(GlobalRetriever); - - // create the move primitive - MoveContainer = UMoveContainer::createMoveContainer(GlobalRetriever, 100, 100, 6.0); - nlassert(MoveContainer); - - // create a visual collision manager - // this should not be in pacs, but this is too close to pacs to be put elsewhere - // -- -- put it elsewhere anyways, the other code in this page can be made re-usable - // to share between the client and the collision service. - VisualCollisionManager = Scene->createVisualCollisionManager(); - nlassert(VisualCollisionManager); - VisualCollisionManager->setLandscape(Landscape); - - // -- -- move this to snowballs specific game task - // create a move primitive for each instance in the instance group - for (uint j = 0; j < InstanceGroups.size(); ++j) - { - for (uint i = 0; i < InstanceGroups[j]->getNumInstance(); ++i) - { - UMovePrimitive *primitive = MoveContainer->addCollisionablePrimitive(0, 1); - primitive->setPrimitiveType(UMovePrimitive::_2DOrientedCylinder); - primitive->setReactionType(UMovePrimitive::DoNothing); - primitive->setTriggerType(UMovePrimitive::NotATrigger); - primitive->setCollisionMask(OtherCollisionBit+SelfCollisionBit+SnowballCollisionBit); - primitive->setOcclusionMask(StaticCollisionBit); - primitive->setObstacle(true); - - // setup the radius of each mesh in the instance group - string name = InstanceGroups[j]->getShapeName(i); - float rad; - - // -- -- improve this - if (strlwr(name) == "pi_po_igloo_a") rad = 4.5f; - else if (strlwr(name) == "pi_po_snowman_a") rad = 1.0f; - else if (strlwr(name) == "pi_po_pinetree_a") rad = 2.0f; - else if (strlwr(name) == "pi_po_tree_a") rad = 2.0f; - else if (strlwr(name) == "pi_po_pingoo_stat_a") rad = 1.0f; - else if (strlwr(name) == "pi_po_gnu_stat_a") rad = 1.0f; - else - { - rad = 2.0f; - nlwarning ("Instance name '%s' doesn't have a good radius for collision", name.c_str()); - } - - primitive->setRadius(rad); - primitive->setHeight(6.0f); - - primitive->insertInWorldImage(0); - CVector pos = InstanceGroups[j]->getInstancePos(i); - primitive->setGlobalPosition(CVectorD(pos.x, pos.y, pos.z-1.5f), 0); - _InstancesMovePrimitives.push_back(primitive); - } - } -} - -void releasePACS() -{ - // delete all move primitives - if (!MoveContainer) nlwarning("_InstancesMovePrimitives: !MoveContainer"); - else - { - vector::iterator it(_InstancesMovePrimitives.begin()), end(_InstancesMovePrimitives.end()); - for (; it != end; ++it) MoveContainer->removePrimitive(*it); - _InstancesMovePrimitives.clear(); - } - - // delete all allocated objects - if (!GlobalRetriever) nlwarning("GlobalRetriever: !GlobalRetriever"); - else { UGlobalRetriever::deleteGlobalRetriever(GlobalRetriever); GlobalRetriever = NULL; } - if (!RetrieverBank) nlwarning("RetrieverBank: !RetrieverBank"); - else { URetrieverBank::deleteRetrieverBank(RetrieverBank); RetrieverBank = NULL; } - if (!MoveContainer) nlwarning("MoveContainer: !MoveContainer"); - else { UMoveContainer::deleteMoveContainer(MoveContainer); MoveContainer = NULL; } - - // delete the visual collision manager - if (!Scene) nlwarning("VisualCollisionManager: !Scene"); - else if (!VisualCollisionManager) nlwarning("VisualCollisionManager: !VisualCollisionManager"); - else { Scene->deleteVisualCollisionManager(VisualCollisionManager); VisualCollisionManager = NULL; } -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include + +#include "snowballs_client.h" +#include "landscape.h" +#include "pacs.h" +#include "entities.h" + +// +// Namespaces +// + +using namespace std; +using namespace NLMISC; +using namespace NL3D; +using namespace NLPACS; + +namespace SBCLIENT { + +extern ULandscape *Landscape; + +/******************************************************************* + * GLOBALS * + *******************************************************************/ + +// The retriever bank used in the world +URetrieverBank *RetrieverBank = NULL; +// The global retriever used for pacs +UGlobalRetriever *GlobalRetriever = NULL; +// The move container used for dynamic collisions +UMoveContainer *MoveContainer = NULL; + +// The collision manager for ground snapping +UVisualCollisionManager *VisualCollisionManager = NULL; + +/******************************************************************* + * COLLISIONS * + *******************************************************************/ + +// The collision primitive for the instances in the landscape +static vector _InstancesMovePrimitives; + +// +// Functions +// + +void initPACS() +{ + // check stuff we need for this to init correctly + nlassert(Landscape); + nlassert(ConfigFile); + nlassert(Scene); + + // check stuff we can't have yet + nlassert(!RetrieverBank); + nlassert(!GlobalRetriever); + nlassert(!MoveContainer); + nlassert(!VisualCollisionManager); + + // init the global retriever + RetrieverBank = URetrieverBank::createRetrieverBank(ConfigFile->getVar("RetrieverBankName").asString().c_str()); + nlassert(RetrieverBank); + + // create the retriever bank + GlobalRetriever = UGlobalRetriever::createGlobalRetriever(ConfigFile->getVar("GlobalRetrieverName").asString().c_str(), RetrieverBank); + nlassert(GlobalRetriever); + + // create the move primitive + MoveContainer = UMoveContainer::createMoveContainer(GlobalRetriever, 100, 100, 6.0); + nlassert(MoveContainer); + + // create a visual collision manager + // this should not be in pacs, but this is too close to pacs to be put elsewhere + // -- -- put it elsewhere anyways, the other code in this page can be made re-usable + // to share between the client and the collision service. + VisualCollisionManager = Scene->createVisualCollisionManager(); + nlassert(VisualCollisionManager); + VisualCollisionManager->setLandscape(Landscape); + + // -- -- move this to snowballs specific game task + // create a move primitive for each instance in the instance group + for (uint j = 0; j < InstanceGroups.size(); ++j) + { + for (uint i = 0; i < InstanceGroups[j]->getNumInstance(); ++i) + { + UMovePrimitive *primitive = MoveContainer->addCollisionablePrimitive(0, 1); + primitive->setPrimitiveType(UMovePrimitive::_2DOrientedCylinder); + primitive->setReactionType(UMovePrimitive::DoNothing); + primitive->setTriggerType(UMovePrimitive::NotATrigger); + primitive->setCollisionMask(OtherCollisionBit+SelfCollisionBit+SnowballCollisionBit); + primitive->setOcclusionMask(StaticCollisionBit); + primitive->setObstacle(true); + + // setup the radius of each mesh in the instance group + string name = InstanceGroups[j]->getShapeName(i); + float rad; + + // -- -- improve this + if (strlwr(name) == "pi_po_igloo_a") rad = 4.5f; + else if (strlwr(name) == "pi_po_snowman_a") rad = 1.0f; + else if (strlwr(name) == "pi_po_pinetree_a") rad = 2.0f; + else if (strlwr(name) == "pi_po_tree_a") rad = 2.0f; + else if (strlwr(name) == "pi_po_pingoo_stat_a") rad = 1.0f; + else if (strlwr(name) == "pi_po_gnu_stat_a") rad = 1.0f; + else + { + rad = 2.0f; + nlwarning ("Instance name '%s' doesn't have a good radius for collision", name.c_str()); + } + + primitive->setRadius(rad); + primitive->setHeight(6.0f); + + primitive->insertInWorldImage(0); + CVector pos = InstanceGroups[j]->getInstancePos(i); + primitive->setGlobalPosition(CVectorD(pos.x, pos.y, pos.z-1.5f), 0); + _InstancesMovePrimitives.push_back(primitive); + } + } +} + +void releasePACS() +{ + // delete all move primitives + if (!MoveContainer) nlwarning("_InstancesMovePrimitives: !MoveContainer"); + else + { + vector::iterator it(_InstancesMovePrimitives.begin()), end(_InstancesMovePrimitives.end()); + for (; it != end; ++it) MoveContainer->removePrimitive(*it); + _InstancesMovePrimitives.clear(); + } + + // delete all allocated objects + if (!GlobalRetriever) nlwarning("GlobalRetriever: !GlobalRetriever"); + else { UGlobalRetriever::deleteGlobalRetriever(GlobalRetriever); GlobalRetriever = NULL; } + if (!RetrieverBank) nlwarning("RetrieverBank: !RetrieverBank"); + else { URetrieverBank::deleteRetrieverBank(RetrieverBank); RetrieverBank = NULL; } + if (!MoveContainer) nlwarning("MoveContainer: !MoveContainer"); + else { UMoveContainer::deleteMoveContainer(MoveContainer); MoveContainer = NULL; } + + // delete the visual collision manager + if (!Scene) nlwarning("VisualCollisionManager: !Scene"); + else if (!VisualCollisionManager) nlwarning("VisualCollisionManager: !VisualCollisionManager"); + else { Scene->deleteVisualCollisionManager(VisualCollisionManager); VisualCollisionManager = NULL; } +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/pacs.h b/code/snowballs2/client/src/pacs.h index 8afb67270..b8bcc560d 100644 --- a/code/snowballs2/client/src/pacs.h +++ b/code/snowballs2/client/src/pacs.h @@ -1,59 +1,59 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef PACS_H -#define PACS_H - -// -// External definitions -// - -namespace NLPACS -{ - class URetrieverBank; - class UGlobalRetriever; - class UMoveContainer; -} - -namespace NL3D -{ - class UVisualCollisionManager; -} - -namespace SBCLIENT { - -// -// External variables -// - -extern NLPACS::URetrieverBank *RetrieverBank; -extern NLPACS::UGlobalRetriever *GlobalRetriever; -extern NLPACS::UMoveContainer *MoveContainer; - -extern NL3D::UVisualCollisionManager *VisualCollisionManager; - -// -// External functions -// - -void initPACS(); -void releasePACS(); - -} /* namespace SBCLIENT */ - -#endif // PACS_H - -/* End of pacs.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef PACS_H +#define PACS_H + +// +// External definitions +// + +namespace NLPACS +{ + class URetrieverBank; + class UGlobalRetriever; + class UMoveContainer; +} + +namespace NL3D +{ + class UVisualCollisionManager; +} + +namespace SBCLIENT { + +// +// External variables +// + +extern NLPACS::URetrieverBank *RetrieverBank; +extern NLPACS::UGlobalRetriever *GlobalRetriever; +extern NLPACS::UMoveContainer *MoveContainer; + +extern NL3D::UVisualCollisionManager *VisualCollisionManager; + +// +// External functions +// + +void initPACS(); +void releasePACS(); + +} /* namespace SBCLIENT */ + +#endif // PACS_H + +/* End of pacs.h */ diff --git a/code/snowballs2/client/src/physics.cpp b/code/snowballs2/client/src/physics.cpp index 1d38ccd0a..ba2b6cbbe 100644 --- a/code/snowballs2/client/src/physics.cpp +++ b/code/snowballs2/client/src/physics.cpp @@ -1,60 +1,60 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include - -#include "physics.h" - -// -// Namespaces -// - -using namespace std; -using namespace NLMISC; - -namespace SBCLIENT { - -// -- -- this file exists twice - -CVector CTrajectory::eval(NLMISC::TLocalTime t) const -{ - if (t < _StartTime) return _StartPosition; - - float ft = (float)(t-_StartTime)/(float)(_StopTime-_StartTime); - ft = min(ft, 1.0f); - CVector res = _EndPosition*ft + _StartPosition*(1.0f-ft); - res.z += 0.3f*_Distance*_Distance/90.0f*(float)sin(Pi*ft); - return res; -} - -CVector CTrajectory::evalSpeed(NLMISC::TLocalTime t) const -{ - if (t < _StartTime) return _StartPosition; - - float ft = (float)(t-_StartTime)/(float)(_StopTime-_StartTime); - ft = min(ft, 1.0f); - CVector res = (_EndPosition-_StartPosition).normed()*_Speed; - res.z += 0.3f*_Distance*_Distance/90.0f*(float)Pi*(float)cos(Pi*ft); - return res; -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include + +#include "physics.h" + +// +// Namespaces +// + +using namespace std; +using namespace NLMISC; + +namespace SBCLIENT { + +// -- -- this file exists twice + +CVector CTrajectory::eval(NLMISC::TLocalTime t) const +{ + if (t < _StartTime) return _StartPosition; + + float ft = (float)(t-_StartTime)/(float)(_StopTime-_StartTime); + ft = min(ft, 1.0f); + CVector res = _EndPosition*ft + _StartPosition*(1.0f-ft); + res.z += 0.3f*_Distance*_Distance/90.0f*(float)sin(Pi*ft); + return res; +} + +CVector CTrajectory::evalSpeed(NLMISC::TLocalTime t) const +{ + if (t < _StartTime) return _StartPosition; + + float ft = (float)(t-_StartTime)/(float)(_StopTime-_StartTime); + ft = min(ft, 1.0f); + CVector res = (_EndPosition-_StartPosition).normed()*_Speed; + res.z += 0.3f*_Distance*_Distance/90.0f*(float)Pi*(float)cos(Pi*ft); + return res; +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/physics.h b/code/snowballs2/client/src/physics.h index 33c995052..3d0acf10f 100644 --- a/code/snowballs2/client/src/physics.h +++ b/code/snowballs2/client/src/physics.h @@ -1,69 +1,69 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef PHYSICS_H -#define PHYSICS_H - -// -// Includes -// - -#include - -#include -#include - -namespace SBCLIENT { - -// -// External classes -// - -class CTrajectory -{ - NLMISC::CVector _StartPosition; - NLMISC::CVector _EndPosition; - float _Speed; - NLMISC::TLocalTime _StartTime; - NLMISC::TLocalTime _StopTime; - float _Distance; - -public: - void init(const NLMISC::CVector &position, const NLMISC::CVector &target, float speed, NLMISC::TLocalTime startTime) - { - _StartPosition = position; - _EndPosition = target; - _Speed = speed; - _StartTime = startTime; - _Distance = (_EndPosition-_StartPosition).norm(); - _StopTime = (NLMISC::TLocalTime)(_Distance / _Speed + _StartTime); - } - -// void compute(const NLMISC::CVector &position, const NLMISC::CVector &target, float speed, NLMISC::TTime startTime); - - NLMISC::CVector eval(NLMISC::TLocalTime t) const; - NLMISC::CVector evalSpeed(NLMISC::TLocalTime t) const; - - NLMISC::TLocalTime getStartTime() const { return _StartTime; } - NLMISC::CVector getStartPosition() const { return _StartPosition; } - NLMISC::TLocalTime getStopTime() const { return _StopTime; } -}; - -} /* namespace SBCLIENT */ - -#endif // PHYSICS_H - -/* End of physics.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef PHYSICS_H +#define PHYSICS_H + +// +// Includes +// + +#include + +#include +#include + +namespace SBCLIENT { + +// +// External classes +// + +class CTrajectory +{ + NLMISC::CVector _StartPosition; + NLMISC::CVector _EndPosition; + float _Speed; + NLMISC::TLocalTime _StartTime; + NLMISC::TLocalTime _StopTime; + float _Distance; + +public: + void init(const NLMISC::CVector &position, const NLMISC::CVector &target, float speed, NLMISC::TLocalTime startTime) + { + _StartPosition = position; + _EndPosition = target; + _Speed = speed; + _StartTime = startTime; + _Distance = (_EndPosition-_StartPosition).norm(); + _StopTime = (NLMISC::TLocalTime)(_Distance / _Speed + _StartTime); + } + +// void compute(const NLMISC::CVector &position, const NLMISC::CVector &target, float speed, NLMISC::TTime startTime); + + NLMISC::CVector eval(NLMISC::TLocalTime t) const; + NLMISC::CVector evalSpeed(NLMISC::TLocalTime t) const; + + NLMISC::TLocalTime getStartTime() const { return _StartTime; } + NLMISC::CVector getStartPosition() const { return _StartPosition; } + NLMISC::TLocalTime getStopTime() const { return _StopTime; } +}; + +} /* namespace SBCLIENT */ + +#endif // PHYSICS_H + +/* End of physics.h */ diff --git a/code/snowballs2/client/src/radar.cpp b/code/snowballs2/client/src/radar.cpp index f36ccb53e..1bfacb132 100644 --- a/code/snowballs2/client/src/radar.cpp +++ b/code/snowballs2/client/src/radar.cpp @@ -1,751 +1,751 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include - -#include - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "camera.h" -#include "snowballs_client.h" -#include "commands.h" -#include "mouse_listener.h" -#include "entities.h" - -// -// Namespaces -// - -using namespace NLMISC; -using namespace NL3D; -using namespace std; - -namespace SBCLIENT { - -// -// Variables -// - -// These variables are automatically set with the config file - -static float RadarPosX, RadarPosY, RadarWidth, RadarHeight; -static uint RadarMinDistance, RadarMaxDistance; -static CRGBA RadarBackColor, RadarFrontColor, RadarSelfColor, RadarOtherColor, RadarPlaceColor; -static float RadarEntitySize; -static uint RadarFontSize; -static float RadarLittlePosX, RadarLittlePosY, RadarLittleRadius; -static NL3D::UMaterial RadarMaterial = NULL; - -uint RadarState; -uint RadarDistance; - -// -// Functions -// - -// Structure for particular places -struct RadarParticularPlace -{ - RadarParticularPlace (float X, float Y, string Name) : x(X), y(Y), name(Name) { } - float x, y; - string name; -}; - -// Container for the particular places (automatically filled by the config file) -vector RadarParticularPlaces; - - -/*********************************************************\ - displayRadar() -\*********************************************************/ -void displayRadar () -{ - float xLeft = RadarPosX; - float xRight = RadarPosX + RadarWidth; - float yTop = RadarPosY + RadarHeight; - float yBottom = RadarPosY; - float xCenter = RadarPosX + RadarWidth/2.0f; - float yCenter = RadarPosY + RadarHeight/2.0f; - - Driver->setMatrixMode2D11 (); - - // Background - RadarMaterial.setColor(RadarBackColor); - CQuad quad; - quad.V0.set(xLeft,yBottom,0); - quad.V1.set(xRight,yBottom,0); - quad.V2.set(xRight,yTop,0); - quad.V3.set(xLeft,yTop,0); - Driver->drawQuad (quad, RadarMaterial); - - // Print radar's range - TextContext->setHotSpot(UTextContext::TopRight); - TextContext->setColor(RadarFrontColor); - TextContext->setFontSize(RadarFontSize); - TextContext->printfAt(xRight-0.01f,yTop-0.01f,"%d m",RadarDistance); - - // Radar unit - float stepV = 50.0f; - float stepH = stepV*3.f/4.f; - // Changing scale - stepV = 0.8f*stepV/RadarDistance; - stepH = 0.8f*stepH/RadarDistance; - - // Drawing radar's lines - float gapV = stepV/2; - float gapH = stepH/2; - - CLine line; - RadarMaterial.setColor(RadarFrontColor); - while(gapH<=RadarWidth/2.0) - { - // v lines - line.V0.set(xCenter+gapH, yTop, 0); - line.V1.set(xCenter+gapH, yBottom, 0); - Driver->drawLine(line, RadarMaterial); - //Driver->drawLine (xCenter+gapH,yTop,xCenter+gapH,yBottom,RadarFrontColor); - line.V0.set(xCenter-gapH, yTop, 0); - line.V1.set(xCenter-gapH, yBottom, 0); - Driver->drawLine(line, RadarMaterial); - //Driver->drawLine (xCenter-gapH,yTop,xCenter-gapH,yBottom,RadarFrontColor); - - gapH += stepH; - } - - while(gapV<=RadarHeight/2.0) - { - // h lines - line.V0.set(xLeft, yCenter+gapV, 0); - line.V1.set(xRight, yCenter+gapV, 0); - Driver->drawLine(line, RadarMaterial); - //Driver->drawLine (xLeft,yCenter+gapV,xRight,yCenter+gapV,RadarFrontColor); - line.V0.set(xLeft, yCenter-gapV, 0); - line.V1.set(xRight, yCenter-gapV, 0); - Driver->drawLine(line, RadarMaterial); - //Driver->drawLine (xLeft,yCenter-gapV,xRight,yCenter-gapV,RadarFrontColor); - - gapV += stepV; - } - - float scale = 1.0f; - - float xscreen = xCenter; - float yscreen = yCenter; - - Driver->setFrustum (CFrustum(0.f, 1.0f, 0.f, 1.f, -1.f, 1.f, false)); - - // distance between user and neighbour player - float myPosx = Self->Position.x; - float myPosy = Self->Position.y; - - // Quads size - float radius = RadarEntitySize; - - // Arrow in center (user) - RadarMaterial.setColor(RadarSelfColor); - CTriangle triangle; - triangle.V0.set(xscreen-2*radius, yscreen-2*radius, 0); - triangle.V1.set(xscreen, yscreen-radius, 0); - triangle.V2.set(xscreen, yscreen+2*radius, 0); - Driver->drawTriangle(triangle, RadarMaterial); - //Driver->drawTriangle(xscreen-2*radius,yscreen-2*radius, xscreen,yscreen-radius, xscreen,yscreen+2*radius, RadarSelfColor); - triangle.V0.set(xscreen, yscreen-radius, 0); - triangle.V1.set(xscreen+2*radius, yscreen-2*radius, 0); - triangle.V2.set(xscreen, yscreen+2*radius, 0); - Driver->drawTriangle(triangle, RadarMaterial); - //Driver->drawTriangle(xscreen,yscreen-radius, xscreen+2*radius,yscreen-2*radius, xscreen,yscreen+2*radius, RadarSelfColor); - - TextContext->setColor(RadarOtherColor); - RadarMaterial.setColor(RadarOtherColor); - - for(EIT eit=Entities.begin(); eit!=Entities.end(); eit++) - { - if((*eit).second.Type == CEntity::Other) - { - CVector playerPos = (*eit).second.Position; - - // position of neighbour - float posx = playerPos.x; - float posy = playerPos.y; - - // relative position - posx = (posx-myPosx)*0.4f/RadarDistance; - posy = (posy-myPosy)*0.4f/RadarDistance; - - float dist = (float) sqrt((posx*posx)+(posy*posy)); - - // Display a quad to show a player - float an; - float az; - float x; - float y; - az = MouseListener->getOrientation (); - if(posx==0) - { - if(posy==0) - { - x = xscreen; - y = yscreen; - } - else - { - if(posy>0) - { - x = (float) (xscreen - dist*cos(Pi-az)*3.f/4.f); - y = (float) (yscreen - dist*sin(Pi-az)); - } - else - { - x = (float) (xscreen - dist*cos(-az)*3.f/4.f); - y = (float) (yscreen - dist*sin(-az)); - } - } - } - else - { - an = (float) atan(posy/posx); - if(posx<0) an = an + (float)Pi; - x = (float) (xscreen - dist*cos(-Pi/2 + an-az)*3.f/4.f); - y = (float) (yscreen - dist*sin(-Pi/2 + an-az)); - } - - // Players out of range are not displayed - if(xxRight || y>yTop || ysetColor(RadarOtherColor); - - quad.V0.set(x-radius, y+radius, 0); - quad.V1.set(x+radius, y+radius, 0); - quad.V2.set(x+radius, y-radius, 0); - quad.V3.set(x-radius, y-radius, 0); - Driver->drawQuad(quad, RadarMaterial); - //Driver->drawQuad (x-radius,y-radius, x+radius,y+radius,RadarOtherColor); - - // Print his name - TextContext->setFontSize(RadarFontSize); - if(x>=xCenter) - { - if(y>=yCenter) - { - TextContext->setHotSpot(UTextContext::BottomLeft); - TextContext->printfAt(x+2*radius, y+2*radius, (*eit).second.Name.c_str()); - } - else - { - TextContext->setHotSpot(UTextContext::TopLeft); - TextContext->printfAt(x+2*radius, y-2*radius, (*eit).second.Name.c_str()); - } - } - else - { - if(y>=yCenter) - { - TextContext->setHotSpot(UTextContext::BottomRight); - TextContext->printfAt(x-2*radius, y+2*radius, (*eit).second.Name.c_str()); - } - else - { - TextContext->setHotSpot(UTextContext::TopRight); - TextContext->printfAt(x-2*radius, y-2*radius, (*eit).second.Name.c_str()); - } - } - } - } - - // display particular places - RadarMaterial.setColor(RadarPlaceColor); - for(uint i = 0; i < RadarParticularPlaces.size(); i++) - { - // relative position - float posx = (RadarParticularPlaces[i].x-myPosx)*0.4f/RadarDistance; - float posy = (RadarParticularPlaces[i].y-myPosy)*0.4f/RadarDistance; - - float dist = (float) sqrt((posx*posx)+(posy*posy)); - - // Display a quad to show a player - float an; - float az; - float x; - float y; - az = MouseListener->getOrientation (); - if(posx==0) - { - if(posy==0) - { - x = xscreen; - y = yscreen; - } - else - { - if(posy>0) - { - x = (float) (xscreen - dist*cos(Pi-az)*3.f/4.f); - y = (float) (yscreen - dist*sin(Pi-az)); - } - else - { - x = (float) (xscreen - dist*cos(-az)*3.f/4.f); - y = (float) (yscreen - dist*sin(-az)); - } - } - } - else - { - an = (float) atan(posy/posx); - if(posx<0) an = an + (float)Pi; - x = (float) (xscreen - dist*cos(-Pi/2 + an-az)*3.f/4.f); - y = (float) (yscreen - dist*sin(-Pi/2 + an-az)); - } - - - if(xxRight || y>yTop || ydrawTriangle(triangle, RadarMaterial); - //Driver->drawTriangle(x-radius,y-radius, x+radius,y-radius, x,y+radius, RadarPlaceColor); - - TextContext->setFontSize(RadarFontSize); - TextContext->setColor(RadarPlaceColor); - - if(x>=xCenter) - { - if(y>=yCenter) - { - TextContext->setHotSpot(UTextContext::BottomLeft); - TextContext->printfAt(x+2*radius, y+2*radius, RadarParticularPlaces[i].name.c_str()); - } - else - { - TextContext->setHotSpot(UTextContext::TopLeft); - TextContext->printfAt(x+2*radius, y-2*radius, RadarParticularPlaces[i].name.c_str()); - } - } - else - { - if(y>=yCenter) - { - TextContext->setHotSpot(UTextContext::BottomRight); - TextContext->printfAt(x-2*radius, y+2*radius, RadarParticularPlaces[i].name.c_str()); - } - else - { - TextContext->setHotSpot(UTextContext::TopRight); - TextContext->printfAt(x-2*radius, y-2*radius, RadarParticularPlaces[i].name.c_str()); - } - } - } -} - -/*********************************************************\ - displayLittleRadar() -\*********************************************************/ -void displayLittleRadar() -{ - float radius = RadarLittleRadius; - - float xLeft = RadarLittlePosX - radius*3.f/4.f; - float yBottom = RadarLittlePosY - radius; - - float xRight = RadarLittlePosX + radius*3.f/4.f; - float yTop = RadarLittlePosY + radius; - - Driver->setMatrixMode2D11 (); - - // Background - RadarMaterial.setColor(RadarBackColor); - CQuad quad; - quad.V0.set(xLeft,yBottom,0); - quad.V1.set(xRight,yBottom,0); - quad.V2.set(xRight,yTop,0); - quad.V3.set(xLeft,yTop,0); - - //Driver->drawQuad (xLeft,yBottom,xRight,yTop,RadarBackColor); - Driver->drawQuad(quad, RadarMaterial); - - // Print radar's range - TextContext->setHotSpot(UTextContext::MiddleBottom); - TextContext->setColor(RadarFrontColor); - TextContext->setFontSize(RadarFontSize); - TextContext->printfAt(xLeft+radius*3.f/4.f,yTop+0.01f,"%d m",RadarDistance); - - // Radar unit - float stepV = 50.0f; - float stepH = stepV*3.f/4.f; - // Changing scale - stepV = radius*stepV/RadarDistance; - stepH = radius*stepH/RadarDistance; - - // Drawing radar's lines - // h lines - RadarMaterial.setColor(RadarFrontColor); - CLine line; - line.V0.set(xLeft, yTop, 0); - line.V1.set(xRight, yTop, 0); - Driver->drawLine(line, RadarMaterial); - line.V0.set(xLeft, yBottom+radius, 0); - line.V1.set(xRight, yBottom+radius, 0); - Driver->drawLine(line, RadarMaterial); - line.V0.set(xLeft, yBottom, 0); - line.V1.set(xRight, yBottom, 0); - Driver->drawLine(line, RadarMaterial); - //Driver->drawLine (xLeft, yTop, xRight, yTop, RadarFrontColor); - //Driver->drawLine (xLeft, yBottom+radius,xRight, yBottom+radius, RadarFrontColor); - //Driver->drawLine (xLeft, yBottom, xRight, yBottom, RadarFrontColor); - - // v lines (assuming 4:3 screen) - line.V0.set(xLeft, yTop, 0); - line.V1.set(xLeft, yBottom, 0); - Driver->drawLine(line, RadarMaterial); - line.V0.set(xLeft + radius*0.75f, yTop, 0); - line.V1.set(xLeft + radius*0.75f, yBottom, 0); - Driver->drawLine(line, RadarMaterial); - line.V0.set(xRight, yTop, 0); - line.V1.set(xRight, yBottom, 0); - Driver->drawLine(line, RadarMaterial); - //Driver->drawLine (xLeft, yTop, xLeft, yBottom, RadarFrontColor); - //Driver->drawLine (xLeft+radius*3.f/4.f, yTop, xLeft+radius*3.f/4.f, yBottom, RadarFrontColor); - //Driver->drawLine (xRight, yTop, xRight, yBottom, RadarFrontColor); - - float scale = 1.0f; - - float xscreen = xLeft + radius*3.f/4.f; - float yscreen = yBottom + radius; - - Driver->setFrustum (CFrustum(0.f, 1.0f, 0.f, 1.f, -1.f, 1.f, false)); - - // distance between user and neighbour player - float myPosx = Self->Position.x; - float myPosy = Self->Position.y; - - // Quads size - float entitySize = RadarEntitySize/2.0f; - - TextContext->setColor(RadarOtherColor); - - for(EIT eit=Entities.begin(); eit!=Entities.end(); eit++) - { - if((*eit).second.Type == CEntity::Other) - { - CVector playerPos = (*eit).second.Position; - - // position of neighbour - float posx = playerPos.x; - float posy = playerPos.y; - - // relative position - posx = (posx-myPosx)*radius/RadarDistance; - posy = (posy-myPosy)*radius/RadarDistance; - - float dist = (float) sqrt((posx*posx)+(posy*posy)); - - // Display a quad to show a player - float an; - float az; - float x; - float y; - az = MouseListener->getOrientation (); - if(posx==0) - { - if(posy==0) - { - x = xscreen; - y = yscreen; - } - else - { - if(posy>0) - { - x = (float) (xscreen - dist*cos(Pi-az)*3.f/4.f); - y = (float) (yscreen - dist*sin(Pi-az)); - } - else - { - x = (float) (xscreen - dist*cos(-az)*3.f/4.f); - y = (float) (yscreen - dist*sin(-az)); - } - } - } - else - { - an = (float) atan(posy/posx); - if(posx<0) an = an + (float)Pi; - x = (float) (xscreen - dist*cos(-Pi/2 + an-az)*3.f/4.f); - y = (float) (yscreen - dist*sin(-Pi/2 + an-az)); - } - - // Players out of range are not displayed - if(xxRight || y>yTop || ysetColor(RadarOtherColor); - - quad.V0.set(x-entitySize, y+entitySize, 0); - quad.V1.set(x+entitySize, y+entitySize, 0); - quad.V2.set(x+entitySize, y-entitySize, 0); - quad.V3.set(x-entitySize, y-entitySize, 0); - RadarMaterial.setColor(RadarOtherColor); - Driver->drawQuad(quad, RadarMaterial); - //Driver->drawQuad (x-entitySize,y-entitySize,x+entitySize,y+entitySize,RadarOtherColor); - } - } - - - // display particular places - CTriangle triangle; - for(uint i = 0; i < RadarParticularPlaces.size(); i++) - { - // relative position - float posx = (RadarParticularPlaces[i].x-myPosx)*radius/RadarDistance; - float posy = (RadarParticularPlaces[i].y-myPosy)*radius/RadarDistance; - - float dist = (float) sqrt((posx*posx)+(posy*posy)); - - // Display a quad to show a player - float an; - float az; - float x; - float y; - az = MouseListener->getOrientation (); - if(posx==0) - { - if(posy==0) - { - x = xscreen; - y = yscreen; - } - else - { - if(posy>0) - { - x = (float) (xscreen - dist*cos(Pi-az)*3.f/4.f); - y = (float) (yscreen - dist*sin(Pi-az)); - } - else - { - x = (float) (xscreen - dist*cos(-az)*3.f/4.f); - y = (float) (yscreen - dist*sin(-az)); - } - } - } - else - { - an = (float) atan(posy/posx); - if(posx<0) an = an + (float)Pi; - x = (float) (xscreen - dist*cos(-Pi/2 + an-az)*3.f/4.f); - y = (float) (yscreen - dist*sin(-Pi/2 + an-az)); - } - - - if(xxRight || y>yTop || ydrawTriangle(triangle, RadarMaterial); - //Driver->drawTriangle(x-entitySize,y-entitySize, x+entitySize,y-entitySize, x,y+entitySize, RadarPlaceColor); - } -} - -void cbUpdateRadar (CConfigFile::CVar &var) -{ - if (var.Name == "RadarPosX") RadarPosX = var.asFloat (); - else if (var.Name == "RadarPosY") RadarPosY = var.asFloat (); - else if (var.Name == "RadarWidth") RadarWidth = var.asFloat (); - else if (var.Name == "RadarHeight") RadarHeight = var.asFloat (); - else if (var.Name == "RadarBackColor") RadarBackColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); - else if (var.Name == "RadarFrontColor") RadarFrontColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); - else if (var.Name == "RadarSelfColor") RadarSelfColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); - else if (var.Name == "RadarOtherColor") RadarOtherColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); - else if (var.Name == "RadarPlaceColor") RadarPlaceColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); - else if (var.Name == "RadarEntitySize") RadarEntitySize = var.asFloat (); - else if (var.Name == "RadarState") RadarState = var.asInt (); - else if (var.Name == "RadarDistance") RadarDistance = var.asInt (); - else if (var.Name == "RadarMinDistance") RadarMinDistance = var.asInt (); - else if (var.Name == "RadarMaxDistance") RadarMaxDistance = var.asInt (); - else if (var.Name == "RadarParticularPlaces") - { - RadarParticularPlaces.clear (); - for (uint i = 0; i < var.size(); i += 3) - { - RadarParticularPlaces.push_back (RadarParticularPlace(var.asFloat(i), var.asFloat(i+1), var.asString(i+2))); - } - } - else if (var.Name == "RadarFontSize") RadarFontSize = var.asInt (); - else if (var.Name == "RadarLittlePosX") RadarLittlePosX = var.asFloat (); - else if (var.Name == "RadarLittlePosY") RadarLittlePosY = var.asFloat (); - else if (var.Name == "RadarLittleRadius") RadarLittleRadius = var.asFloat (); - else nlwarning ("Unknown variable update %s", var.Name.c_str()); -} - -void initRadar () -{ - ConfigFile->setCallback ("RadarPosX", cbUpdateRadar); - ConfigFile->setCallback ("RadarPosY", cbUpdateRadar); - ConfigFile->setCallback ("RadarWidth", cbUpdateRadar); - ConfigFile->setCallback ("RadarHeight", cbUpdateRadar); - ConfigFile->setCallback ("RadarBackColor", cbUpdateRadar); - ConfigFile->setCallback ("RadarFrontColor", cbUpdateRadar); - ConfigFile->setCallback ("RadarSelfColor", cbUpdateRadar); - ConfigFile->setCallback ("RadarOtherColor", cbUpdateRadar); - ConfigFile->setCallback ("RadarPlaceColor", cbUpdateRadar); - ConfigFile->setCallback ("RadarEntitySize", cbUpdateRadar); - ConfigFile->setCallback ("RadarState", cbUpdateRadar); - ConfigFile->setCallback ("RadarDistance", cbUpdateRadar); - ConfigFile->setCallback ("RadarMinDistance", cbUpdateRadar); - ConfigFile->setCallback ("RadarMaxDistance", cbUpdateRadar); - ConfigFile->setCallback ("RadarParticularPlaces", cbUpdateRadar); - ConfigFile->setCallback ("RadarFontSize", cbUpdateRadar); - ConfigFile->setCallback ("RadarLittlePosX", cbUpdateRadar); - ConfigFile->setCallback ("RadarLittlePosY", cbUpdateRadar); - ConfigFile->setCallback ("RadarLittleRadius", cbUpdateRadar); - - cbUpdateRadar (ConfigFile->getVar ("RadarPosX")); - cbUpdateRadar (ConfigFile->getVar ("RadarPosY")); - cbUpdateRadar (ConfigFile->getVar ("RadarWidth")); - cbUpdateRadar (ConfigFile->getVar ("RadarHeight")); - cbUpdateRadar (ConfigFile->getVar ("RadarFrontColor")); - cbUpdateRadar (ConfigFile->getVar ("RadarBackColor")); - cbUpdateRadar (ConfigFile->getVar ("RadarSelfColor")); - cbUpdateRadar (ConfigFile->getVar ("RadarOtherColor")); - cbUpdateRadar (ConfigFile->getVar ("RadarPlaceColor")); - cbUpdateRadar (ConfigFile->getVar ("RadarEntitySize")); - cbUpdateRadar (ConfigFile->getVar ("RadarState")); - cbUpdateRadar (ConfigFile->getVar ("RadarDistance")); - cbUpdateRadar (ConfigFile->getVar ("RadarMinDistance")); - cbUpdateRadar (ConfigFile->getVar ("RadarMaxDistance")); - cbUpdateRadar (ConfigFile->getVar ("RadarParticularPlaces")); - cbUpdateRadar (ConfigFile->getVar ("RadarFontSize")); - cbUpdateRadar (ConfigFile->getVar ("RadarLittlePosX")); - cbUpdateRadar (ConfigFile->getVar ("RadarLittlePosY")); - cbUpdateRadar (ConfigFile->getVar ("RadarLittleRadius")); - - RadarMaterial = Driver->createMaterial (); - RadarMaterial.initUnlit (); - RadarMaterial.setBlendFunc (UMaterial::srcalpha, UMaterial::invsrcalpha); - RadarMaterial.setBlend(true); -} - -void updateRadar () -{ - if (RadarDistance > RadarMaxDistance) RadarDistance = RadarMaxDistance; - else if (RadarDistance < RadarMinDistance) RadarDistance = RadarMinDistance; - - switch (RadarState) - { - case 0: - break; - case 1: - displayRadar (); - break; - case 2: - displayLittleRadar(); - break; - } -} - -void releaseRadar () -{ - ConfigFile->setCallback ("RadarPosX", NULL); - ConfigFile->setCallback ("RadarPosY", NULL); - ConfigFile->setCallback ("RadarWidth", NULL); - ConfigFile->setCallback ("RadarHeight", NULL); - ConfigFile->setCallback ("RadarBackColor", NULL); - ConfigFile->setCallback ("RadarFrontColor", NULL); - ConfigFile->setCallback ("RadarSelfColor", NULL); - ConfigFile->setCallback ("RadarOtherColor", NULL); - ConfigFile->setCallback ("RadarPlaceColor", NULL); - ConfigFile->setCallback ("RadarEntitySize", NULL); - ConfigFile->setCallback ("RadarState", NULL); - ConfigFile->setCallback ("RadarDistance", NULL); - ConfigFile->setCallback ("RadarMinDistance", NULL); - ConfigFile->setCallback ("RadarMaxDistance", NULL); - ConfigFile->setCallback ("RadarParticularPlaces", NULL); - ConfigFile->setCallback ("RadarFontSize", NULL); - ConfigFile->setCallback ("RadarLittlePosX", NULL); - ConfigFile->setCallback ("RadarLittlePosY", NULL); - ConfigFile->setCallback ("RadarLittleRadius", NULL); - Driver->deleteMaterial(RadarMaterial); RadarMaterial = NULL; -} - -NLMISC_COMMAND(go,"change position of the player with a player name or location","|") -{ - // check args, if there s not the right number of parameter, return bad - if (args.size() == 1) - { - bool gotoplayer = true; - - vector::iterator itpp; - for(itpp = RadarParticularPlaces.begin(); itpp != RadarParticularPlaces.end(); itpp++) - { - if((*itpp).name==args[0]) - { - string cmd = "goto " + toString ((*itpp).x) + " " + toString ((*itpp).y); - ICommand::execute (cmd, CommandsLog); - - gotoplayer = false; - break; - } - } - - if(gotoplayer) - { - EIT itre; - for(itre=Entities.begin(); itre!=Entities.end(); itre++) - { - if((*itre).second.Type != CEntity::Snowball) - { - if((*itre).second.Name == args[0]) - { - string cmd = "goto " + toString ((*itre).second.Position.x) + " " + toString ((*itre).second.Position.y); - ICommand::execute (cmd, CommandsLog); - - break; - } - } - } - } - } - else - return false; - - - return true; -} - -} /* namespace SBCLIENT */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "camera.h" +#include "snowballs_client.h" +#include "commands.h" +#include "mouse_listener.h" +#include "entities.h" + +// +// Namespaces +// + +using namespace NLMISC; +using namespace NL3D; +using namespace std; + +namespace SBCLIENT { + +// +// Variables +// + +// These variables are automatically set with the config file + +static float RadarPosX, RadarPosY, RadarWidth, RadarHeight; +static uint RadarMinDistance, RadarMaxDistance; +static CRGBA RadarBackColor, RadarFrontColor, RadarSelfColor, RadarOtherColor, RadarPlaceColor; +static float RadarEntitySize; +static uint RadarFontSize; +static float RadarLittlePosX, RadarLittlePosY, RadarLittleRadius; +static NL3D::UMaterial RadarMaterial = NULL; + +uint RadarState; +uint RadarDistance; + +// +// Functions +// + +// Structure for particular places +struct RadarParticularPlace +{ + RadarParticularPlace (float X, float Y, string Name) : x(X), y(Y), name(Name) { } + float x, y; + string name; +}; + +// Container for the particular places (automatically filled by the config file) +vector RadarParticularPlaces; + + +/*********************************************************\ + displayRadar() +\*********************************************************/ +void displayRadar () +{ + float xLeft = RadarPosX; + float xRight = RadarPosX + RadarWidth; + float yTop = RadarPosY + RadarHeight; + float yBottom = RadarPosY; + float xCenter = RadarPosX + RadarWidth/2.0f; + float yCenter = RadarPosY + RadarHeight/2.0f; + + Driver->setMatrixMode2D11 (); + + // Background + RadarMaterial.setColor(RadarBackColor); + CQuad quad; + quad.V0.set(xLeft,yBottom,0); + quad.V1.set(xRight,yBottom,0); + quad.V2.set(xRight,yTop,0); + quad.V3.set(xLeft,yTop,0); + Driver->drawQuad (quad, RadarMaterial); + + // Print radar's range + TextContext->setHotSpot(UTextContext::TopRight); + TextContext->setColor(RadarFrontColor); + TextContext->setFontSize(RadarFontSize); + TextContext->printfAt(xRight-0.01f,yTop-0.01f,"%d m",RadarDistance); + + // Radar unit + float stepV = 50.0f; + float stepH = stepV*3.f/4.f; + // Changing scale + stepV = 0.8f*stepV/RadarDistance; + stepH = 0.8f*stepH/RadarDistance; + + // Drawing radar's lines + float gapV = stepV/2; + float gapH = stepH/2; + + CLine line; + RadarMaterial.setColor(RadarFrontColor); + while(gapH<=RadarWidth/2.0) + { + // v lines + line.V0.set(xCenter+gapH, yTop, 0); + line.V1.set(xCenter+gapH, yBottom, 0); + Driver->drawLine(line, RadarMaterial); + //Driver->drawLine (xCenter+gapH,yTop,xCenter+gapH,yBottom,RadarFrontColor); + line.V0.set(xCenter-gapH, yTop, 0); + line.V1.set(xCenter-gapH, yBottom, 0); + Driver->drawLine(line, RadarMaterial); + //Driver->drawLine (xCenter-gapH,yTop,xCenter-gapH,yBottom,RadarFrontColor); + + gapH += stepH; + } + + while(gapV<=RadarHeight/2.0) + { + // h lines + line.V0.set(xLeft, yCenter+gapV, 0); + line.V1.set(xRight, yCenter+gapV, 0); + Driver->drawLine(line, RadarMaterial); + //Driver->drawLine (xLeft,yCenter+gapV,xRight,yCenter+gapV,RadarFrontColor); + line.V0.set(xLeft, yCenter-gapV, 0); + line.V1.set(xRight, yCenter-gapV, 0); + Driver->drawLine(line, RadarMaterial); + //Driver->drawLine (xLeft,yCenter-gapV,xRight,yCenter-gapV,RadarFrontColor); + + gapV += stepV; + } + + float scale = 1.0f; + + float xscreen = xCenter; + float yscreen = yCenter; + + Driver->setFrustum (CFrustum(0.f, 1.0f, 0.f, 1.f, -1.f, 1.f, false)); + + // distance between user and neighbour player + float myPosx = Self->Position.x; + float myPosy = Self->Position.y; + + // Quads size + float radius = RadarEntitySize; + + // Arrow in center (user) + RadarMaterial.setColor(RadarSelfColor); + CTriangle triangle; + triangle.V0.set(xscreen-2*radius, yscreen-2*radius, 0); + triangle.V1.set(xscreen, yscreen-radius, 0); + triangle.V2.set(xscreen, yscreen+2*radius, 0); + Driver->drawTriangle(triangle, RadarMaterial); + //Driver->drawTriangle(xscreen-2*radius,yscreen-2*radius, xscreen,yscreen-radius, xscreen,yscreen+2*radius, RadarSelfColor); + triangle.V0.set(xscreen, yscreen-radius, 0); + triangle.V1.set(xscreen+2*radius, yscreen-2*radius, 0); + triangle.V2.set(xscreen, yscreen+2*radius, 0); + Driver->drawTriangle(triangle, RadarMaterial); + //Driver->drawTriangle(xscreen,yscreen-radius, xscreen+2*radius,yscreen-2*radius, xscreen,yscreen+2*radius, RadarSelfColor); + + TextContext->setColor(RadarOtherColor); + RadarMaterial.setColor(RadarOtherColor); + + for(EIT eit=Entities.begin(); eit!=Entities.end(); eit++) + { + if((*eit).second.Type == CEntity::Other) + { + CVector playerPos = (*eit).second.Position; + + // position of neighbour + float posx = playerPos.x; + float posy = playerPos.y; + + // relative position + posx = (posx-myPosx)*0.4f/RadarDistance; + posy = (posy-myPosy)*0.4f/RadarDistance; + + float dist = (float) sqrt((posx*posx)+(posy*posy)); + + // Display a quad to show a player + float an; + float az; + float x; + float y; + az = MouseListener->getOrientation (); + if(posx==0) + { + if(posy==0) + { + x = xscreen; + y = yscreen; + } + else + { + if(posy>0) + { + x = (float) (xscreen - dist*cos(Pi-az)*3.f/4.f); + y = (float) (yscreen - dist*sin(Pi-az)); + } + else + { + x = (float) (xscreen - dist*cos(-az)*3.f/4.f); + y = (float) (yscreen - dist*sin(-az)); + } + } + } + else + { + an = (float) atan(posy/posx); + if(posx<0) an = an + (float)Pi; + x = (float) (xscreen - dist*cos(-Pi/2 + an-az)*3.f/4.f); + y = (float) (yscreen - dist*sin(-Pi/2 + an-az)); + } + + // Players out of range are not displayed + if(xxRight || y>yTop || ysetColor(RadarOtherColor); + + quad.V0.set(x-radius, y+radius, 0); + quad.V1.set(x+radius, y+radius, 0); + quad.V2.set(x+radius, y-radius, 0); + quad.V3.set(x-radius, y-radius, 0); + Driver->drawQuad(quad, RadarMaterial); + //Driver->drawQuad (x-radius,y-radius, x+radius,y+radius,RadarOtherColor); + + // Print his name + TextContext->setFontSize(RadarFontSize); + if(x>=xCenter) + { + if(y>=yCenter) + { + TextContext->setHotSpot(UTextContext::BottomLeft); + TextContext->printfAt(x+2*radius, y+2*radius, (*eit).second.Name.c_str()); + } + else + { + TextContext->setHotSpot(UTextContext::TopLeft); + TextContext->printfAt(x+2*radius, y-2*radius, (*eit).second.Name.c_str()); + } + } + else + { + if(y>=yCenter) + { + TextContext->setHotSpot(UTextContext::BottomRight); + TextContext->printfAt(x-2*radius, y+2*radius, (*eit).second.Name.c_str()); + } + else + { + TextContext->setHotSpot(UTextContext::TopRight); + TextContext->printfAt(x-2*radius, y-2*radius, (*eit).second.Name.c_str()); + } + } + } + } + + // display particular places + RadarMaterial.setColor(RadarPlaceColor); + for(uint i = 0; i < RadarParticularPlaces.size(); i++) + { + // relative position + float posx = (RadarParticularPlaces[i].x-myPosx)*0.4f/RadarDistance; + float posy = (RadarParticularPlaces[i].y-myPosy)*0.4f/RadarDistance; + + float dist = (float) sqrt((posx*posx)+(posy*posy)); + + // Display a quad to show a player + float an; + float az; + float x; + float y; + az = MouseListener->getOrientation (); + if(posx==0) + { + if(posy==0) + { + x = xscreen; + y = yscreen; + } + else + { + if(posy>0) + { + x = (float) (xscreen - dist*cos(Pi-az)*3.f/4.f); + y = (float) (yscreen - dist*sin(Pi-az)); + } + else + { + x = (float) (xscreen - dist*cos(-az)*3.f/4.f); + y = (float) (yscreen - dist*sin(-az)); + } + } + } + else + { + an = (float) atan(posy/posx); + if(posx<0) an = an + (float)Pi; + x = (float) (xscreen - dist*cos(-Pi/2 + an-az)*3.f/4.f); + y = (float) (yscreen - dist*sin(-Pi/2 + an-az)); + } + + + if(xxRight || y>yTop || ydrawTriangle(triangle, RadarMaterial); + //Driver->drawTriangle(x-radius,y-radius, x+radius,y-radius, x,y+radius, RadarPlaceColor); + + TextContext->setFontSize(RadarFontSize); + TextContext->setColor(RadarPlaceColor); + + if(x>=xCenter) + { + if(y>=yCenter) + { + TextContext->setHotSpot(UTextContext::BottomLeft); + TextContext->printfAt(x+2*radius, y+2*radius, RadarParticularPlaces[i].name.c_str()); + } + else + { + TextContext->setHotSpot(UTextContext::TopLeft); + TextContext->printfAt(x+2*radius, y-2*radius, RadarParticularPlaces[i].name.c_str()); + } + } + else + { + if(y>=yCenter) + { + TextContext->setHotSpot(UTextContext::BottomRight); + TextContext->printfAt(x-2*radius, y+2*radius, RadarParticularPlaces[i].name.c_str()); + } + else + { + TextContext->setHotSpot(UTextContext::TopRight); + TextContext->printfAt(x-2*radius, y-2*radius, RadarParticularPlaces[i].name.c_str()); + } + } + } +} + +/*********************************************************\ + displayLittleRadar() +\*********************************************************/ +void displayLittleRadar() +{ + float radius = RadarLittleRadius; + + float xLeft = RadarLittlePosX - radius*3.f/4.f; + float yBottom = RadarLittlePosY - radius; + + float xRight = RadarLittlePosX + radius*3.f/4.f; + float yTop = RadarLittlePosY + radius; + + Driver->setMatrixMode2D11 (); + + // Background + RadarMaterial.setColor(RadarBackColor); + CQuad quad; + quad.V0.set(xLeft,yBottom,0); + quad.V1.set(xRight,yBottom,0); + quad.V2.set(xRight,yTop,0); + quad.V3.set(xLeft,yTop,0); + + //Driver->drawQuad (xLeft,yBottom,xRight,yTop,RadarBackColor); + Driver->drawQuad(quad, RadarMaterial); + + // Print radar's range + TextContext->setHotSpot(UTextContext::MiddleBottom); + TextContext->setColor(RadarFrontColor); + TextContext->setFontSize(RadarFontSize); + TextContext->printfAt(xLeft+radius*3.f/4.f,yTop+0.01f,"%d m",RadarDistance); + + // Radar unit + float stepV = 50.0f; + float stepH = stepV*3.f/4.f; + // Changing scale + stepV = radius*stepV/RadarDistance; + stepH = radius*stepH/RadarDistance; + + // Drawing radar's lines + // h lines + RadarMaterial.setColor(RadarFrontColor); + CLine line; + line.V0.set(xLeft, yTop, 0); + line.V1.set(xRight, yTop, 0); + Driver->drawLine(line, RadarMaterial); + line.V0.set(xLeft, yBottom+radius, 0); + line.V1.set(xRight, yBottom+radius, 0); + Driver->drawLine(line, RadarMaterial); + line.V0.set(xLeft, yBottom, 0); + line.V1.set(xRight, yBottom, 0); + Driver->drawLine(line, RadarMaterial); + //Driver->drawLine (xLeft, yTop, xRight, yTop, RadarFrontColor); + //Driver->drawLine (xLeft, yBottom+radius,xRight, yBottom+radius, RadarFrontColor); + //Driver->drawLine (xLeft, yBottom, xRight, yBottom, RadarFrontColor); + + // v lines (assuming 4:3 screen) + line.V0.set(xLeft, yTop, 0); + line.V1.set(xLeft, yBottom, 0); + Driver->drawLine(line, RadarMaterial); + line.V0.set(xLeft + radius*0.75f, yTop, 0); + line.V1.set(xLeft + radius*0.75f, yBottom, 0); + Driver->drawLine(line, RadarMaterial); + line.V0.set(xRight, yTop, 0); + line.V1.set(xRight, yBottom, 0); + Driver->drawLine(line, RadarMaterial); + //Driver->drawLine (xLeft, yTop, xLeft, yBottom, RadarFrontColor); + //Driver->drawLine (xLeft+radius*3.f/4.f, yTop, xLeft+radius*3.f/4.f, yBottom, RadarFrontColor); + //Driver->drawLine (xRight, yTop, xRight, yBottom, RadarFrontColor); + + float scale = 1.0f; + + float xscreen = xLeft + radius*3.f/4.f; + float yscreen = yBottom + radius; + + Driver->setFrustum (CFrustum(0.f, 1.0f, 0.f, 1.f, -1.f, 1.f, false)); + + // distance between user and neighbour player + float myPosx = Self->Position.x; + float myPosy = Self->Position.y; + + // Quads size + float entitySize = RadarEntitySize/2.0f; + + TextContext->setColor(RadarOtherColor); + + for(EIT eit=Entities.begin(); eit!=Entities.end(); eit++) + { + if((*eit).second.Type == CEntity::Other) + { + CVector playerPos = (*eit).second.Position; + + // position of neighbour + float posx = playerPos.x; + float posy = playerPos.y; + + // relative position + posx = (posx-myPosx)*radius/RadarDistance; + posy = (posy-myPosy)*radius/RadarDistance; + + float dist = (float) sqrt((posx*posx)+(posy*posy)); + + // Display a quad to show a player + float an; + float az; + float x; + float y; + az = MouseListener->getOrientation (); + if(posx==0) + { + if(posy==0) + { + x = xscreen; + y = yscreen; + } + else + { + if(posy>0) + { + x = (float) (xscreen - dist*cos(Pi-az)*3.f/4.f); + y = (float) (yscreen - dist*sin(Pi-az)); + } + else + { + x = (float) (xscreen - dist*cos(-az)*3.f/4.f); + y = (float) (yscreen - dist*sin(-az)); + } + } + } + else + { + an = (float) atan(posy/posx); + if(posx<0) an = an + (float)Pi; + x = (float) (xscreen - dist*cos(-Pi/2 + an-az)*3.f/4.f); + y = (float) (yscreen - dist*sin(-Pi/2 + an-az)); + } + + // Players out of range are not displayed + if(xxRight || y>yTop || ysetColor(RadarOtherColor); + + quad.V0.set(x-entitySize, y+entitySize, 0); + quad.V1.set(x+entitySize, y+entitySize, 0); + quad.V2.set(x+entitySize, y-entitySize, 0); + quad.V3.set(x-entitySize, y-entitySize, 0); + RadarMaterial.setColor(RadarOtherColor); + Driver->drawQuad(quad, RadarMaterial); + //Driver->drawQuad (x-entitySize,y-entitySize,x+entitySize,y+entitySize,RadarOtherColor); + } + } + + + // display particular places + CTriangle triangle; + for(uint i = 0; i < RadarParticularPlaces.size(); i++) + { + // relative position + float posx = (RadarParticularPlaces[i].x-myPosx)*radius/RadarDistance; + float posy = (RadarParticularPlaces[i].y-myPosy)*radius/RadarDistance; + + float dist = (float) sqrt((posx*posx)+(posy*posy)); + + // Display a quad to show a player + float an; + float az; + float x; + float y; + az = MouseListener->getOrientation (); + if(posx==0) + { + if(posy==0) + { + x = xscreen; + y = yscreen; + } + else + { + if(posy>0) + { + x = (float) (xscreen - dist*cos(Pi-az)*3.f/4.f); + y = (float) (yscreen - dist*sin(Pi-az)); + } + else + { + x = (float) (xscreen - dist*cos(-az)*3.f/4.f); + y = (float) (yscreen - dist*sin(-az)); + } + } + } + else + { + an = (float) atan(posy/posx); + if(posx<0) an = an + (float)Pi; + x = (float) (xscreen - dist*cos(-Pi/2 + an-az)*3.f/4.f); + y = (float) (yscreen - dist*sin(-Pi/2 + an-az)); + } + + + if(xxRight || y>yTop || ydrawTriangle(triangle, RadarMaterial); + //Driver->drawTriangle(x-entitySize,y-entitySize, x+entitySize,y-entitySize, x,y+entitySize, RadarPlaceColor); + } +} + +void cbUpdateRadar (CConfigFile::CVar &var) +{ + if (var.Name == "RadarPosX") RadarPosX = var.asFloat (); + else if (var.Name == "RadarPosY") RadarPosY = var.asFloat (); + else if (var.Name == "RadarWidth") RadarWidth = var.asFloat (); + else if (var.Name == "RadarHeight") RadarHeight = var.asFloat (); + else if (var.Name == "RadarBackColor") RadarBackColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); + else if (var.Name == "RadarFrontColor") RadarFrontColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); + else if (var.Name == "RadarSelfColor") RadarSelfColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); + else if (var.Name == "RadarOtherColor") RadarOtherColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); + else if (var.Name == "RadarPlaceColor") RadarPlaceColor.set (var.asInt(0), var.asInt(1), var.asInt(2), var.asInt(3)); + else if (var.Name == "RadarEntitySize") RadarEntitySize = var.asFloat (); + else if (var.Name == "RadarState") RadarState = var.asInt (); + else if (var.Name == "RadarDistance") RadarDistance = var.asInt (); + else if (var.Name == "RadarMinDistance") RadarMinDistance = var.asInt (); + else if (var.Name == "RadarMaxDistance") RadarMaxDistance = var.asInt (); + else if (var.Name == "RadarParticularPlaces") + { + RadarParticularPlaces.clear (); + for (uint i = 0; i < var.size(); i += 3) + { + RadarParticularPlaces.push_back (RadarParticularPlace(var.asFloat(i), var.asFloat(i+1), var.asString(i+2))); + } + } + else if (var.Name == "RadarFontSize") RadarFontSize = var.asInt (); + else if (var.Name == "RadarLittlePosX") RadarLittlePosX = var.asFloat (); + else if (var.Name == "RadarLittlePosY") RadarLittlePosY = var.asFloat (); + else if (var.Name == "RadarLittleRadius") RadarLittleRadius = var.asFloat (); + else nlwarning ("Unknown variable update %s", var.Name.c_str()); +} + +void initRadar () +{ + ConfigFile->setCallback ("RadarPosX", cbUpdateRadar); + ConfigFile->setCallback ("RadarPosY", cbUpdateRadar); + ConfigFile->setCallback ("RadarWidth", cbUpdateRadar); + ConfigFile->setCallback ("RadarHeight", cbUpdateRadar); + ConfigFile->setCallback ("RadarBackColor", cbUpdateRadar); + ConfigFile->setCallback ("RadarFrontColor", cbUpdateRadar); + ConfigFile->setCallback ("RadarSelfColor", cbUpdateRadar); + ConfigFile->setCallback ("RadarOtherColor", cbUpdateRadar); + ConfigFile->setCallback ("RadarPlaceColor", cbUpdateRadar); + ConfigFile->setCallback ("RadarEntitySize", cbUpdateRadar); + ConfigFile->setCallback ("RadarState", cbUpdateRadar); + ConfigFile->setCallback ("RadarDistance", cbUpdateRadar); + ConfigFile->setCallback ("RadarMinDistance", cbUpdateRadar); + ConfigFile->setCallback ("RadarMaxDistance", cbUpdateRadar); + ConfigFile->setCallback ("RadarParticularPlaces", cbUpdateRadar); + ConfigFile->setCallback ("RadarFontSize", cbUpdateRadar); + ConfigFile->setCallback ("RadarLittlePosX", cbUpdateRadar); + ConfigFile->setCallback ("RadarLittlePosY", cbUpdateRadar); + ConfigFile->setCallback ("RadarLittleRadius", cbUpdateRadar); + + cbUpdateRadar (ConfigFile->getVar ("RadarPosX")); + cbUpdateRadar (ConfigFile->getVar ("RadarPosY")); + cbUpdateRadar (ConfigFile->getVar ("RadarWidth")); + cbUpdateRadar (ConfigFile->getVar ("RadarHeight")); + cbUpdateRadar (ConfigFile->getVar ("RadarFrontColor")); + cbUpdateRadar (ConfigFile->getVar ("RadarBackColor")); + cbUpdateRadar (ConfigFile->getVar ("RadarSelfColor")); + cbUpdateRadar (ConfigFile->getVar ("RadarOtherColor")); + cbUpdateRadar (ConfigFile->getVar ("RadarPlaceColor")); + cbUpdateRadar (ConfigFile->getVar ("RadarEntitySize")); + cbUpdateRadar (ConfigFile->getVar ("RadarState")); + cbUpdateRadar (ConfigFile->getVar ("RadarDistance")); + cbUpdateRadar (ConfigFile->getVar ("RadarMinDistance")); + cbUpdateRadar (ConfigFile->getVar ("RadarMaxDistance")); + cbUpdateRadar (ConfigFile->getVar ("RadarParticularPlaces")); + cbUpdateRadar (ConfigFile->getVar ("RadarFontSize")); + cbUpdateRadar (ConfigFile->getVar ("RadarLittlePosX")); + cbUpdateRadar (ConfigFile->getVar ("RadarLittlePosY")); + cbUpdateRadar (ConfigFile->getVar ("RadarLittleRadius")); + + RadarMaterial = Driver->createMaterial (); + RadarMaterial.initUnlit (); + RadarMaterial.setBlendFunc (UMaterial::srcalpha, UMaterial::invsrcalpha); + RadarMaterial.setBlend(true); +} + +void updateRadar () +{ + if (RadarDistance > RadarMaxDistance) RadarDistance = RadarMaxDistance; + else if (RadarDistance < RadarMinDistance) RadarDistance = RadarMinDistance; + + switch (RadarState) + { + case 0: + break; + case 1: + displayRadar (); + break; + case 2: + displayLittleRadar(); + break; + } +} + +void releaseRadar () +{ + ConfigFile->setCallback ("RadarPosX", NULL); + ConfigFile->setCallback ("RadarPosY", NULL); + ConfigFile->setCallback ("RadarWidth", NULL); + ConfigFile->setCallback ("RadarHeight", NULL); + ConfigFile->setCallback ("RadarBackColor", NULL); + ConfigFile->setCallback ("RadarFrontColor", NULL); + ConfigFile->setCallback ("RadarSelfColor", NULL); + ConfigFile->setCallback ("RadarOtherColor", NULL); + ConfigFile->setCallback ("RadarPlaceColor", NULL); + ConfigFile->setCallback ("RadarEntitySize", NULL); + ConfigFile->setCallback ("RadarState", NULL); + ConfigFile->setCallback ("RadarDistance", NULL); + ConfigFile->setCallback ("RadarMinDistance", NULL); + ConfigFile->setCallback ("RadarMaxDistance", NULL); + ConfigFile->setCallback ("RadarParticularPlaces", NULL); + ConfigFile->setCallback ("RadarFontSize", NULL); + ConfigFile->setCallback ("RadarLittlePosX", NULL); + ConfigFile->setCallback ("RadarLittlePosY", NULL); + ConfigFile->setCallback ("RadarLittleRadius", NULL); + Driver->deleteMaterial(RadarMaterial); RadarMaterial = NULL; +} + +NLMISC_COMMAND(go,"change position of the player with a player name or location","|") +{ + // check args, if there s not the right number of parameter, return bad + if (args.size() == 1) + { + bool gotoplayer = true; + + vector::iterator itpp; + for(itpp = RadarParticularPlaces.begin(); itpp != RadarParticularPlaces.end(); itpp++) + { + if((*itpp).name==args[0]) + { + string cmd = "goto " + toString ((*itpp).x) + " " + toString ((*itpp).y); + ICommand::execute (cmd, CommandsLog); + + gotoplayer = false; + break; + } + } + + if(gotoplayer) + { + EIT itre; + for(itre=Entities.begin(); itre!=Entities.end(); itre++) + { + if((*itre).second.Type != CEntity::Snowball) + { + if((*itre).second.Name == args[0]) + { + string cmd = "goto " + toString ((*itre).second.Position.x) + " " + toString ((*itre).second.Position.y); + ICommand::execute (cmd, CommandsLog); + + break; + } + } + } + } + } + else + return false; + + + return true; +} + +} /* namespace SBCLIENT */ + +/* end of file */ diff --git a/code/snowballs2/client/src/radar.h b/code/snowballs2/client/src/radar.h index 34696ccbd..bd49d2373 100644 --- a/code/snowballs2/client/src/radar.h +++ b/code/snowballs2/client/src/radar.h @@ -1,41 +1,41 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef RADAR_H -#define RADAR_H - -namespace SBCLIENT { - -// -// External variables -// - -extern uint RadarDistance; -extern uint RadarState; - -// -// External functions -// - -void initRadar (); -void updateRadar (); -void releaseRadar (); - -} /* namespace SBCLIENT */ - -#endif // RADAR_H - -/* End of radar.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef RADAR_H +#define RADAR_H + +namespace SBCLIENT { + +// +// External variables +// + +extern uint RadarDistance; +extern uint RadarState; + +// +// External functions +// + +void initRadar (); +void updateRadar (); +void releaseRadar (); + +} /* namespace SBCLIENT */ + +#endif // RADAR_H + +/* End of radar.h */ diff --git a/code/snowballs2/client/src/snowballs_client.cpp b/code/snowballs2/client/src/snowballs_client.cpp index bde24ac83..c5cb73072 100644 --- a/code/snowballs2/client/src/snowballs_client.cpp +++ b/code/snowballs2/client/src/snowballs_client.cpp @@ -1,1344 +1,1344 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include -#include "snowballs_client.h" -#include "snowballs_config.h" - -// STL includes -#include -#include -#include -#include -#if defined(NL_OS_WINDOWS) -# include -# include -#endif - -// NeL includes -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if SBCLIENT_DEV_STEREO -# include -#endif /* #if SBCLIENT_DEV_STEREO */ - -// Project includes -#include "pacs.h" -#include "radar.h" -#include "graph.h" -#include "camera.h" -#include "compass.h" -#include "commands.h" -#include "entities.h" -#include "network.h" -#include "landscape.h" -#include "animation.h" -#include "interface.h" -#include "lens_flare.h" -#include "mouse_listener.h" -#include "configuration.h" -#include "internationalization.h" -#include "game_time.h" - -#ifdef NL_OS_WINDOWS -#include -#endif - -using namespace std; -using namespace NLMISC; -using namespace NL3D; -using namespace NLNET; - -namespace SBCLIENT { - -/******************************************************************* - * GLOBALS * - *******************************************************************/ - -void CGlobals::assertNull() -{ - // extra verification against stupid typos - nlassert(!Driver); - nlassert(!Scene); - nlassert(!TextContext); - nlassert(!ConfigFile); - nlassert(!Landscape); - nlassert(!MouseListener); -} - -// The 3d driver -NL3D::UDriver *Driver = NULL; // core -// This is the main scene -NL3D::UScene *Scene = NULL; // ingame -// This variable is used to display text on the screen -NL3D::UTextContext *TextContext = NULL; // core -// This class contains all variables that are in the snowballs_client.cfg -NLMISC::CConfigFile *ConfigFile = NULL; // core -NL3D::ULandscape *Landscape = NULL; // ingame -// This class is used to handle mouse/keyboard input for camera movement -C3dMouseListener *MouseListener = NULL; // ingame -//// Log file -//CFileDisplayer FileDisplayer; // main - -// stuff not initialized -// The previous and current frame dates -NLMISC::TLocalTime LocalTime; -NLMISC::TLocalTime LocalTimeDelta; -// NLMISC::TLocalTime ServerTime; -// NLMISC::TLocalTime ServerTimeDelta; -// NLMISC::TGameTime GameTime; -// NLMISC::TGameTime GameTimeDelta; -// NLMISC::TGameCycle GameCycle; -// NLMISC::TGameCycle GameCycleDelta; -NL3D::TGlobalAnimationTime AnimationTime; -NL3D::TAnimationTime AnimationTimeDelta; -float FramesPerSecond; -float FramesPerSecondSmooth; - -// Stuff for connection -ucstring Login; -static string FSAddr, Cookie; - -/******************************************************************* - * SNOWBALLS CLIENT * - *******************************************************************/ - -static CFileDisplayer *_FileDisplayer = NULL; -static const uint8 GameStateLoad = 0, GameStateUnload = 1, GameStateReset = 2, GameStateExit = 3, -GameStateLogin = 4, GameStateOnline = 5, GameStateOffline = 6; - -// true if the commands(chat) interface must be display. This variable is set automatically with the config file -static bool ShowCommands; // ingame -// if true, the mouse can't go out the client window(work only on Windows) -static bool CaptureState = false; // ingame -// Set NextGameState to switch the current game state -static uint8 CurrentGameState = -1, NextGameState = 0; // state -// To know which data has been loaded -static bool LoadedCore = false, LoadedIngame = false, LoadedLogin = false, -LoadedOnline = false, LoadedOffline = false; // state - -#if SBCLIENT_DEV_STEREO -static IStereoRender *_StereoRender = NULL; -#endif /* #if SBCLIENT_DEV_STEREO */ - -// -// Prototypes -// - -void initLoadingState(); -void releaseLoadingState(); -void renderLoadingState(const char *state, bool logo3d); -void updateLoadingState(const char *state, bool network, bool information); -void displayLoadingState(const char *state); -void renderLoadingState(ucstring state, bool logo3d); -void updateLoadingState(ucstring state, bool network, bool information); -void displayLoadingState(ucstring state); -void update3dLogo(); -void renderInformation(); -void switchGameState(); -void loopLogin(); -void loopIngame(); -void initCore(); -void initLogin(); -void initIngame(); -void initOnline(); -void initOffline(); -void releaseCore(); -void releaseLogin(); -void releaseIngame(); -void releaseOnline(); -void releaseOffline(); -void cbGraphicsDriver(CConfigFile::CVar &var); - -// -// Functions -// - -void switchGameState() -{ -SwitchNextGameState: - nlinfo("Switching to the next game state"); - if (CurrentGameState == NextGameState) - { - nlwarning("NextGameState wasn't changed"); - } - else - { - switch(CurrentGameState) - { - case GameStateOnline: - releaseOnline(); // always release online after switch - break; - case GameStateOffline: - releaseOffline(); // always releaes offline after switch - break; - } - switch(NextGameState) - { - case GameStateLoad: - try - { - initCore(); // core is required - } - catch (NLMISC::Exception e) - { -#ifdef NL_OS_WINDOWS - MessageBox(NULL, e.what(), "NeL Exception", MB_OK | MB_ICONSTOP); -#else - printf("%s\n", e.what()); -#endif - return; // exit if driver loading failed - } - break; - case GameStateUnload: - displayLoadingState("Unloading"); - releaseLogin(); // release all - releaseIngame(); - break; - case GameStateReset: - displayLoadingState("Reset"); - releaseLogin(); // release all - releaseIngame(); - releaseCore(); - break; - case GameStateExit: - displayLoadingState("See you later!"); - releaseLogin(); // release all - releaseIngame(); - releaseCore(); - break; - case GameStateLogin: - initCore(); // core is required - initLogin(); // login is required - break; - case GameStateOnline: - initCore(); // core is required - releaseLogin(); //login can be released - initIngame(); // ingame is required - initOnline(); // connection is required - break; - case GameStateOffline: - initCore(); // core is required - releaseLogin(); //login can be released - initIngame(); // ingame is required - initOffline(); // offline entity required - break; - } - } - CurrentGameState = NextGameState; - switch(CurrentGameState) - { - case GameStateLoad: // switch to the default state - NextGameState = GameStateLogin; - break; - case GameStateUnload: // test state, switch back to load for default - NextGameState = GameStateLoad; - break; - case GameStateReset: // used to reset everything - NextGameState = GameStateLoad; - break; - case GameStateExit: // exit the loop - return; - case GameStateLogin: // loop the login screen - loopLogin(); // must loop by itself - break; - case GameStateOnline: // start offline if not online - if (!LoadedOnline) - { - NextGameState = GameStateOffline; - break; - } - case GameStateOffline: // loop ingame - loopIngame(); // must loop by itself - break; - } - goto SwitchNextGameState; -} - -void initCore() -{ - if (!LoadedCore) - { - LoadedCore = true; - // Seed the randomizer - srand(uint(time(0))); - // Load configuration file, set paths, extension remapping - CConfiguration::init(); - // Load language file - CInternationalization::init(); - // Start timing system - CGameTime::init(); - // Set the ShowCommands with the value set in the client config file - ShowCommands = ConfigFile->getVar("ShowCommands").asInt() == 1; - // Create a driver - Driver = UDriver::createDriver(0, ConfigFile->getVar("OpenGL").asInt() == 0); - // Create the window with config file values - Driver->setDisplay(UDriver::CMode(ConfigFile->getVar("ScreenWidth").asInt(), - ConfigFile->getVar("ScreenHeight").asInt(), - ConfigFile->getVar("ScreenDepth").asInt(), - ConfigFile->getVar("ScreenFull").asInt()==0)); - // Set the cache size for the font manager(in bytes) - Driver->setFontManagerMaxMemory(2097152); - // Create a Text context for later text rendering - displayLoadingState("Initialize Text"); - TextContext = Driver->createTextContext(CPath::lookup(ConfigFile->getVar("FontName").asString())); - TextContext->setShaded(true); - TextContext->setKeep800x600Ratio(false); - // You can't call displayLoadingState() before init the loading state system - displayLoadingState("Initialize Loading"); - initLoadingState(); - // Initialize sound for loading screens etc -//#ifdef NL_OS_WINDOWS -// displayLoadingState("Initialize Sound"); -// initSound(); -// playMusic(SBCLIENT_MUSIC_WAIT); -//#endif - // Required for 3d rendering (3d nel logo etc) - displayLoadingState("Initialize Light"); - initLight(); -#if SBCLIENT_DEV_STEREO - displayLoadingState("Initialize Stereo Renderer"); - _StereoRender = Driver->createStereoRender(); - _StereoRender->setMode("AnaglyphRedCyan"); - //_StereoRender->setMode("SideBySideHalf"); - //_StereoRender->setMode("Mono"); -#endif /* #if SBCLIENT_DEV_STEREO */ - - ConfigFile->setCallback("OpenGL", cbGraphicsDriver); - } -} - -void initLogin() -{ - if (!LoadedLogin) - { - LoadedLogin = true; - } -} - -void initIngame() -{ - if (!LoadedIngame) - { - LoadedIngame = true; -//#ifdef NL_OS_WINDOWS -// playMusic(SBCLIENT_MUSIC_WAIT); -//#endif - - // Create a scene - Scene = Driver->createScene(false); - - // initialize bloom effect - CBloomEffect::instance().setDriver(Driver); - CBloomEffect::instance().setScene(Scene); - CBloomEffect::instance().init(ConfigFile->getVar("OpenGL").asInt() == 1); - - // Init the landscape using the previously created UScene - displayLoadingState("Initialize Landscape"); - initLandscape(); - // Init the pacs - displayLoadingState("Initialize PACS "); - initPACS(); - // Init the aiming system - displayLoadingState("Initialize Aiming "); - initAiming(); - // Init the user camera - displayLoadingState("Initialize Camera "); - initCamera(); - // Create a 3D mouse listener - displayLoadingState("Initialize MouseListener "); - MouseListener = new C3dMouseListener(); - MouseListener->addToServer(Driver->EventServer); - MouseListener->setCamera(Camera); - MouseListener->setHotSpot(CVectorD(0,0,0)); - MouseListener->setFrustrum(Camera.getFrustum()); - MouseListener->setMatrix(Camera.getMatrix()); - MouseListener->setSpeed(PlayerSpeed); - initMouseListenerConfig(); - // Init interface - displayLoadingState("Initialize Interface "); - initInterface(); - // Init radar - displayLoadingState("Initialize Radar "); - initRadar(); - // Init compass - displayLoadingState("Initialize Compass "); - initCompass(); - // Init graph - displayLoadingState("Initialize Graph "); - initGraph(); - // Init the command control - displayLoadingState("Initialize Commands "); - initCommands(); - // Init the entities prefs - displayLoadingState("Initialize Entities "); - initEntities(); - // Init animation system - displayLoadingState("Initialize Animation "); - initAnimation(); - // Init the lens flare - displayLoadingState("Initialize LensFlare "); - initLensFlare(); - // Init the sky - displayLoadingState("Initialize Sky "); - initSky(); - - // Init the mouse so it's trapped by the main window. - Driver->showCursor(false); - Driver->setCapture(true); - Driver->setMousePos(0.5f, 0.5f); - } -} - -void initOnline() -{ - if (LoadedOnline) return; -//#ifdef NL_OS_WINDOWS -// playMusic(SBCLIENT_MUSIC_WAIT); -//#endif - - displayLoadingState("Connecting"); - - // connect to the server - nlinfo("Try to connect to FS addr '%s' and identify with the cookie '%s'", FSAddr.c_str(), Cookie.c_str()); - initNetwork(Cookie, FSAddr); - - while (Self == NULL) // wait for position etc from server - updateLoadingState(ucstring("Connecting"), true, true); - - displayLoadingState("Load Landscape"); - loadAllZonesAround(); - - displayLoadingState("Ready!"); - -//#ifdef NL_OS_WINDOWS -// playMusic(SBCLIENT_MUSIC_BACKGROUND); -//#endif - LoadedOnline = true; -} - -void initOffline() -{ - if (!LoadedOffline) - { - LoadedOffline = true; -//#ifdef NL_OS_WINDOWS -// playMusic(SBCLIENT_MUSIC_WAIT); -//#endif - - uint32 id = NextEID++; - Login = ucstring("Entity" + toString(id)); - - // Creates the self entity - displayLoadingState("Creating offline entity"); - CVector startPoint = CVector(ConfigFile->getVar("StartPoint").asFloat(0), ConfigFile->getVar("StartPoint").asFloat(1), ConfigFile->getVar("StartPoint").asFloat(2)); - addEntity(id, Login.toUtf8(), CEntity::Self, startPoint, startPoint); - - displayLoadingState("Load Landscape"); - loadAllZonesAround(); - - // Display a local welcome message - addLine(">>>>> Welcome to Snowballs!"); - addLine(">>>>> Press SHIFT-ESC to exit the game."); - - displayLoadingState("Ready!"); - -//#ifdef NL_OS_WINDOWS -// playMusic(SBCLIENT_MUSIC_BACKGROUND); -//#endif - } -} - -void releaseCore() -{ - if (LoadedCore) - { - LoadedCore = false; - // Release configuration callbacks - CConfiguration::dropCallback("OpenGL"); - -#if SBCLIENT_DEV_STEREO - // Release stereo render - Driver->deleteStereoRender(_StereoRender); - _StereoRender = NULL; -#endif /* #if SBCLIENT_DEV_STEREO */ - - // Release the sun - releaseLight(); - // Release the loading state textures - releaseLoadingState(); - // Release the sound -//#ifdef NL_OS_WINDOWS -// releaseSound(); -//#endif - // Release the text context - Driver->deleteTextContext(TextContext); - TextContext = NULL; - // Release the 3d driver - Driver->release(); - delete Driver; - Driver = NULL; - - // Release timing system - CGameTime::init(); - // Release language file - CInternationalization::init(); - // Release the configuration - CConfiguration::release(); - } -} - -void releaseLogin() -{ - if (LoadedLogin) - { - LoadedLogin = false; - } -} - -void releaseIngame() -{ - if (LoadedIngame) - { - LoadedIngame = false; - - // Release the mouse cursor - if (CaptureState) - { - Driver->setCapture(false); - Driver->showCursor(true); - } - - // Release all before quit - - releaseSky(); - releaseLensFlare(); - releaseRadar(); - releaseCommands(); - releaseEntities(); - releaseGraph(); - releaseCompass(); - releaseInterface(); - releaseNetwork(); - releaseAnimation(); - releaseMouseListenerConfig(); - releaseCamera(); - releaseAiming(); - releasePACS(); - releaseLandscape(); - // Release the mouse listener - MouseListener->removeFromServer(Driver->EventServer); - delete MouseListener; - MouseListener = NULL; - - // release bloom effect - CBloomEffect::instance().releaseInstance(); - - Driver->deleteScene(Scene); - Scene = NULL; - } -} - -void releaseOnline() -{ - if (LoadedOnline) - { - LoadedOnline = false; - releaseNetwork(); - deleteAllEntities(); - } -} - -void releaseOffline() -{ - if (LoadedOffline) - { - LoadedOffline = false; - deleteAllEntities(); - } -} - -void loopLogin() -{ -//#ifdef NL_OS_WINDOWS -// playMusic(SBCLIENT_MUSIC_LOGIN); -//#endif - // todo: login screen, move this stuff to a button or something - displayLoadingState("Login"); - if (ConfigFile->getVar("Local").asInt() == 0) - { - // Only attempt to directly log in if we haven't been passed a cookie already. - if(Cookie.empty() || FSAddr.empty()) - { - if (ConfigFile->getVar("UseDirectClient").asInt() == 1) - { - string result; - string LSHost(ConfigFile->getVar("LSHost").asString()); - Login = ConfigFile->getVar("Login").asString(); - string Password = ConfigFile->getVar("Password").asString(); - CHashKeyMD5 hk = getMD5((uint8 *)Password.c_str(), (uint32)Password.size()); - string CPassword = hk.toString(); - nlinfo("The crypted password is %s", CPassword.c_str()); - string Application = ConfigFile->getVar("ClientApplication").asString(); - sint32 sid = ConfigFile->getVar("ShardId").asInt(); - - // 1/ Authenticate - updateLoadingState(ucstring("Authenticate"), false, false); - result = CLoginClient::authenticateBegin(LSHost, Login, CPassword, Application); - if (!result.empty()) goto AuthenticateFail; - while (CLoginClient::authenticateUpdate(result)) - updateLoadingState(ucstring("Authenticate"), false, false); - if (!result.empty()) goto AuthenticateFail; - goto AuthenticateSuccess; - -AuthenticateFail: - nlinfo("*** Authenticate failed '%s' ***", result.c_str()); - for (TLocalTime t = 0; t < 5.000; t += LocalTimeDelta) - updateLoadingState(ucstring("Authenticate failed: ") + ucstring(result), false, false); - NextGameState = GameStateOffline; - return; - -AuthenticateSuccess: - nlinfo("%d Shards are available:", CLoginClient::ShardList.size()); - for (uint i = 0; i < CLoginClient::ShardList.size(); i++) - { - nlinfo(" ShardId %3d: %s(%d online players)", CLoginClient::ShardList[i].Id, CLoginClient::ShardList[i].Name.toUtf8().c_str(), CLoginClient::ShardList[i].NbPlayers); - } - - // 2/ Select shard - updateLoadingState(ucstring("Select shard"), false, false); - result = CLoginClient::selectShardBegin(sid); - if (!result.empty()) goto SelectFail; - while (CLoginClient::selectShardUpdate(result, FSAddr, Cookie)) - updateLoadingState(ucstring("Select shard"), false, false); - if (!result.empty()) goto SelectFail; - goto SelectSuccess; - -SelectFail: - nlinfo("*** Connection to the shard failed '%s' ***", result.c_str()); - for (TLocalTime t = 0; t < 5.000; t += LocalTimeDelta) - updateLoadingState(ucstring("Select shard failed: ") + ucstring(result), false, false); - NextGameState = GameStateOffline; - return; - -SelectSuccess:; - } - } - NextGameState = GameStateOnline; - return; - } - NextGameState = GameStateOffline; - return; -} - -void loopIngame() -{ - while (CurrentGameState == NextGameState) - { - if (!Driver->isActive()) { NextGameState = GameStateExit; return; } - - // call all update functions - // 01. Update Utilities (configuration etc) - CConfiguration::updateUtilities(); // update configuration files - - // 02. Update Time (deltas) - CGameTime::updateTime(); - - // 03. Update Input (keyboard controls, etc) - Driver->EventServer.pump(); // Pump user input messages - MouseListener->update(); - MouseListener->updateCamera(); - - // 04. Update Incoming (network, receive messages) - updateNetwork(); - - // 05. Update Weather (sky, snow, wind, fog, sun) - animateSky(LocalTimeDelta); - - // 06. Update Landscape (async zone loading near entity) - updateLandscape(); // Update the landscape - - // ... Update Animations (TEST) - // ... - - // 07. Update Entities (collisions and actions) - // - Move Other Entities (move//, animations, etc) - // - Update Self Collision (move) - // - Update Self Entity (animations//, etc) - updateEntities(); // Update network messages FIXME_NETWORK_OUTGOING - - // 08. Update Animations (playlists) - Scene->animate(AnimationTime); // Set new animation date - - // 09. Update Camera (depends on entities) - updateCamera(); - - // 10. Update Interface (login, ui, etc) - // ... - - // 11. Update Sound (sound driver) -//#ifdef NL_OS_WINDOWS -// updateSound(); // Update the sound -//#endif - - // 12. Update Outgoing (network, send new position etc) - // ... - - // 13. Update Debug (stuff for dev) - // ... - - // if driver is lost (d3d) do nothing for a while - if (Driver->isLost()) nlSleep(10); - else - { - // call all 3d render thingies - Driver->clearBuffers(CRGBA(127, 0, 0)); // if you see red, there's a problem with bloom or stereo render -#if SBCLIENT_DEV_STEREO - _StereoRender->calculateCameras(Camera.getObjectPtr()); // calculate modified matrices for the current camera - for (uint cameraId = 0; cameraId < _StereoRender->getCameraCount(); ++cameraId) - { - _StereoRender->getCamera(cameraId, Camera.getObjectPtr()); // get the matrix details for this camera -#endif /* #if SBCLIENT_DEV_STEREO */ - - // 01. Render Driver (background color) - CBloomEffect::instance().initBloom(); // start bloom effect (just before the first scene element render) - Driver->clearBuffers(CRGBA(0, 0, 127)); // clear all buffers, if you see this blue there's a problem with scene rendering - - // 02. Render Sky (sky scene) - updateSky(); // Render the sky scene before the main scene - - // 04. Render Scene (entity scene) - Scene->render(); // Render - - // 05. Render Effects (flare) - updateLensFlare(); // Render the lens flare - CBloomEffect::instance().endBloom(); // end the actual bloom effect visible in the scene - - // 06. Render Interface 3D (player names) - CBloomEffect::instance().endInterfacesDisplayBloom(); // end bloom effect system after drawing the 3d interface (z buffer related) - -#if SBCLIENT_DEV_STEREO - _StereoRender->copyBufferToTexture(cameraId); // copy current buffer to the active stereorender texture - } - _StereoRender->restoreCamera(Camera.getObjectPtr()); // restore the camera - _StereoRender->render(); // render everything together in the current mode -#endif /* #if SBCLIENT_DEV_STEREO */ - - // 07. Render Interface 2D (chatboxes etc, optionally does have 3d) - updateCompass(); // Update the compass - updateRadar(); // Update the radar - updateGraph(); // Update the radar - if (ShowCommands) updateCommands(); // Update the commands panel - updateAnimation(); - renderEntitiesNames(); // Render the name on top of the other players - updateInterface(); // Update interface - renderInformation(); - update3dLogo(); - - // 08. Render Debug (stuff for dev) - // ... - - // 09. Render Buffer - Driver->swapBuffers(); - } - - // begin various extra keys stuff ... - - if (Driver->AsyncListener.isKeyDown(KeySHIFT) && Driver->AsyncListener.isKeyPushed(KeyESCAPE)) - { - // Shift Escape -> quit - NextGameState = GameStateExit; - } - else if (Driver->AsyncListener.isKeyPushed(KeyF3)) - { - // F3 -> toggle wireframe/solid - UDriver::TPolygonMode p = Driver->getPolygonMode(); - p = UDriver::TPolygonMode(((int)p+1)%3); - Driver->setPolygonMode(p); - } - else if (Driver->AsyncListener.isKeyPushed(KeyF4)) - { - // F4 -> clear the command(chat) output - clearCommands(); - } - else if (Driver->AsyncListener.isKeyPushed(KeyF5)) - { - // F5 -> display/hide the commands(chat) interface - ShowCommands = !ShowCommands; - } - else if (Driver->AsyncListener.isKeyPushed(KeyF6)) - { - // F6 -> display/hide the radar interface - RadarState =(RadarState + 1) % 3; - } - else if (Driver->AsyncListener.isKeyDown(KeyF7)) - { - // F7 -> radar zoom out - RadarDistance += 50; - } - else if (Driver->AsyncListener.isKeyDown(KeyF8)) - { - // F8 -> radar zoom in - RadarDistance -= 50; - } - else if (Driver->AsyncListener.isKeyPushed(KeyF9)) - { - // F9 -> release/capture the mouse cursor - if (!CaptureState) - { - Driver->setCapture(false); - Driver->showCursor(true); - MouseListener->removeFromServer(Driver->EventServer); - } - else - { - Driver->setCapture(true); - Driver->showCursor(false); - MouseListener->addToServer(Driver->EventServer); - } - CaptureState = !CaptureState; - } - else if (Driver->AsyncListener.isKeyPushed(KeyF10)) - { - // F10 -> switch beteen online and offline - if (isOnline()) NextGameState = GameStateOffline; - else NextGameState = GameStateLogin; - } - else if (Driver->AsyncListener.isKeyPushed(KeyF11)) - { - // F11 -> reset the PACS global position of the self entity(in case of a pacs failure :-\) - if (Self != NULL) - resetEntityPosition(Self->Id); - } - else if (Driver->AsyncListener.isKeyPushed(KeyF12)) - { - // F12 -> take a screenshot - CBitmap btm; - Driver->getBuffer(btm); - string filename = CFile::findNewFile("screenshot.tga"); - COFile fs(filename); - btm.writeTGA(fs,24,false); - nlinfo("Screenshot '%s' saved", filename.c_str()); - } - - // end of various keys - } -} - -void renderInformation() -{ - // Display if we are online or offline - TextContext->setHotSpot(UTextContext::TopRight); - TextContext->setColor(isOnline()?CRGBA(0, 255, 0):CRGBA(255, 0, 0)); - TextContext->setFontSize(18); - TextContext->printfAt(0.99f, 0.99f, isOnline() ? "Online" : "Offline"); - - // Display the frame rate - TextContext->setHotSpot(UTextContext::TopLeft); - TextContext->setColor(CRGBA(255, 255, 255, 255)); - TextContext->setFontSize(14); - TextContext->printfAt(0.01f, 0.99f, "%.2f(%.2f)fps %.3fs", FramesPerSecondSmooth, FramesPerSecond, (float)LocalTimeDelta); - - // one more frame - FpsGraph.addValue(1.0f); - SpfGraph.addOneValue((float)LocalTimeDelta); -} - -// -// Configuration callbacks -// - -void cbGraphicsDriver(CConfigFile::CVar &var) -{ - // -- give ingame warning or something instead =) - NextGameState = GameStateReset; -} - -// -// Loading state procedure -// - -static UTextureFile *NelLogo = NULL; -// static UTextureFile *NevraxLogo = NULL; -static UTextureFile *SnowballsBackground = NULL; -static float ScreenWidth, ScreenHeight; -// The logo 3D objects -static UScene *LogoScene = NULL; -static UInstance Logo = NULL; - -void initLoadingState() -{ - NelLogo = Driver->createTextureFile("nel128.tga"); - // NevraxLogo = Driver->createTextureFile("nevrax.tga"); - SnowballsBackground = Driver->createTextureFile("snowbg.tga"); - uint32 width, height; - Driver->getWindowSize(width, height); - ScreenWidth =(float)width; - ScreenHeight =(float)height; - - // - // Setup the logo scene - // - - LogoScene = Driver->createScene(false); - - CViewport v; - v.init(0.0f, 0.80f, 0.2f, 0.2f); - LogoScene->setViewport(v); - - Logo = LogoScene->createInstance("nel_logo.shape"); - Logo.setPos(0.0f, 3.0f, 0.0f); - Logo.setTransformMode(UTransformable::RotEuler); -} - -void releaseLoadingState() -{ - LogoScene->deleteInstance(Logo); Logo = NULL; - Driver->deleteScene(LogoScene); LogoScene = NULL; - - Driver->deleteTextureFile(NelLogo); NelLogo = NULL; - // Driver->deleteTextureFile(NevraxLogo); NevraxLogo = NULL; - Driver->deleteTextureFile(SnowballsBackground); SnowballsBackground = NULL; -} - -void renderLoadingState(const char *state, bool logo3d) -{ - renderLoadingState(ucstring(state), logo3d); -} -void renderLoadingState(ucstring state, bool logo3d) -{ - if (!Driver) return; - - Driver->clearBuffers(CRGBA(0,0,0)); - - Driver->setMatrixMode2D(CFrustum(0.0f, ScreenWidth, 0.0f, ScreenHeight, 0.0f, 1.0f, false)); - - if (SnowballsBackground != NULL) - { - float imageAspect = 16.0f / 9.0f; // 1.777 - float minTransform = 4.0f / 3.0f; // 1.333 - float screenAspect = ScreenWidth / ScreenHeight; - float transform = screenAspect > imageAspect ? 1.0f : (screenAspect < minTransform ? imageAspect / minTransform : imageAspect / screenAspect); - float newWidth = ScreenWidth * transform; - Driver->drawBitmap((newWidth - ScreenWidth) * -0.5f, 0, newWidth, ScreenHeight, *SnowballsBackground); - } - - /*if (logo3d) update3dLogo(); - else */ if (NelLogo != NULL) Driver->drawBitmap(16, 32 - 42, 128, 128, *NelLogo); - // if (NevraxLogo != NULL) Driver->drawBitmap(ScreenWidth - 128 - 16, 32, 128, 16, *NevraxLogo); - - if (!TextContext) return; - - TextContext->setColor(CRGBA(255, 255, 255)); - TextContext->setHotSpot(UTextContext::MiddleMiddle); - - TextContext->setFontSize(40); - TextContext->printAt(0.5f, 0.5f, ucstring("Welcome to Snowballs!")); - - TextContext->setFontSize(30); - TextContext->printAt(0.5f, 0.2f, state); - - TextContext->setHotSpot(UTextContext::BottomRight); - TextContext->setFontSize(15); -#if (FINAL_VERSION == 1) - TextContext->printAt(0.99f, 0.01f, ucstring("Final Version")); -#else - TextContext->printAt(0.99f, 0.01f, ucstring("(compiled " __DATE__ " " __TIME__ ")")); -#endif - - TextContext->setHotSpot(UTextContext::BottomLeft); - TextContext->setFontSize(15); -#if defined(NL_DEBUG_FAST) - ucstring version = ucstring("DebugFast Version"); -#elif defined(NL_DEBUG) - ucstring version = ucstring("Debug Version"); -#elif defined(NL_RELEASE) - ucstring version = ucstring("Release Version"); -#elif defined(NL_RELEASE_DEBUG) - ucstring version = ucstring("ReleaseDebug Version"); -#else - ucstring version = ucstring("Unknown Version"); -#endif - TextContext->printAt(0.01f, 0.01f, version); -} - -void displayLoadingState(const char *state) -{ - displayLoadingState(ucstring(state)); -} -void displayLoadingState(ucstring state) -{ - CGameTime::updateTime(); - renderLoadingState(state, false); - Driver->swapBuffers(); - //Driver->EventServer.pump(); -} - -void updateLoadingState(const char *state, bool network, bool information) -{ - updateLoadingState(ucstring(state), network, information); -} -void updateLoadingState(ucstring state, bool network, bool information) -{ - CGameTime::updateTime(); // important that time is updated here!!! -//#ifdef NL_OS_WINDOWS -// updateSound(); -//#endif - renderLoadingState(state, true); - if (information) renderInformation(); - if (network) updateNetwork(); - Driver->swapBuffers(); - Driver->EventServer.pump(); -} - -void update3dLogo() -{ - Driver->clearZBuffer(); - static float angle = 0.0; - angle += 2.0f * (float)LocalTimeDelta; - Logo.setRotEuler(0.0f, 0.0f, angle); - LogoScene->animate(AnimationTime); - LogoScene->render(); -} - -void CSnowballsClient::init() -{ - // Sanity check - CGlobals::assertNull(); -} - -bool CSnowballsClient::run() -{ - // Run the game state loop switcher - switchGameState(); - return true; -} - -void CSnowballsClient::release() -{ - // Make sure everything's released - releaseOnline(); - releaseOffline(); - releaseIngame(); - releaseLogin(); - releaseCore(); - CGlobals::assertNull(); -} - -} /* namespace SBCLIENT */ - -void end(); -#ifdef NL_OS_WINDOWS -# ifdef _UNICODE -# define tstring wstring -# else -# define tstring string -# endif -sint WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdline, int nCmdShow) -#else -sint main(int argc, char **argv) -#endif -{ - // must do this to allow deallocation when closing with X - atexit(end); - -#ifdef NL_OS_WINDOWS - - // extract the 2 first param (argv[1] and argv[2]) it must be cookie and addr - - string cmd = cmdline; - string::size_type pos1 = cmd.find_first_not_of (' '); - string::size_type pos2; - if (pos1 != string::npos) - { - pos2 = cmd.find (' ', pos1); - if(pos2 != string::npos) - { - SBCLIENT::Cookie = cmd.substr (pos1, pos2-pos1); - - pos1 = cmd.find_first_not_of (' ', pos2); - if (pos1 != string::npos) - { - pos2 = cmd.find (' ', pos1); - if(pos2 == string::npos) - { - SBCLIENT::FSAddr = cmd.substr (pos1); - } - else if (pos1 != pos2) - { - SBCLIENT::FSAddr = cmd.substr (pos1, pos2-pos1); - } - } - } - } - -#else - - if (argc>=3) - { - SBCLIENT::Cookie = argv[1]; - SBCLIENT::FSAddr = argv[2]; - } - -#endif - - nlinfo ("cookie '%s' addr '%s'", SBCLIENT::Cookie.c_str (), SBCLIENT::FSAddr.c_str()); - - -#if defined(NL_OS_WINDOWS) && !FINAL_VERSION - // ensure paths are ok before powering up nel - { - OutputDebugString(" ******************************** \n"); - OutputDebugString(" * DEVELOPER MODE * \n"); - OutputDebugString(" ******************************** \n\n"); - FILE *f = _tfopen(_T(SBCLIENT_CONFIG_FILE_DEFAULT), _T("r")); - if (!f) - { - OutputDebugString(" ******************************** \n"); - OutputDebugString(" * CHANGING WORKING DIRECTORY * \n"); - OutputDebugString(" ******************************** \n\n"); - char cwd[256]; - _tgetcwd(cwd, 256); - tstring workdir(cwd); - workdir += "\\..\\bin\\"; - _tchdir(workdir.c_str()); - f = _tfopen(_T(SBCLIENT_CONFIG_FILE_DEFAULT), _T("r")); - if (!f) - { - OutputDebugString(" ******************************** \n"); - OutputDebugString(" * DEFAULT CONFIG MISSING * \n"); - OutputDebugString(" ******************************** \n\n"); - return EXIT_FAILURE; - } - } - fclose(f); - } -#endif - - // go nel! - { - // use log.log if NEL_LOG_IN_FILE and SBCLIENT_USE_LOG_LOG defined as 1 - createDebug(NULL, SBCLIENT_USE_LOG_LOG, false); - - #if SBCLIENT_USE_LOG - // create snowballs_client.log - // filedisplayer only deletes the 001 etc - if (SBCLIENT_ERASE_LOG && CFile::isExists(SBCLIENT_LOG_FILE)) - CFile::deleteFile(SBCLIENT_LOG_FILE); - // initialize the log file - SBCLIENT::_FileDisplayer = new CFileDisplayer(); - SBCLIENT::_FileDisplayer->setParam(SBCLIENT_LOG_FILE, SBCLIENT_ERASE_LOG); - DebugLog->addDisplayer(SBCLIENT::_FileDisplayer); - InfoLog->addDisplayer(SBCLIENT::_FileDisplayer); - WarningLog->addDisplayer(SBCLIENT::_FileDisplayer); - AssertLog->addDisplayer(SBCLIENT::_FileDisplayer); - ErrorLog->addDisplayer(SBCLIENT::_FileDisplayer); - #endif - - nlinfo("Welcome to NeL!"); - } - - SBCLIENT::CSnowballsClient::init(); - exit(SBCLIENT::CSnowballsClient::run() ? EXIT_SUCCESS : EXIT_FAILURE); - return EXIT_FAILURE; -} -void end() -{ - SBCLIENT::CSnowballsClient::release(); - nlinfo("See you later!"); - -#if SBCLIENT_USE_LOG - DebugLog->removeDisplayer(SBCLIENT::_FileDisplayer); - InfoLog->removeDisplayer(SBCLIENT::_FileDisplayer); - WarningLog->removeDisplayer(SBCLIENT::_FileDisplayer); - AssertLog->removeDisplayer(SBCLIENT::_FileDisplayer); - ErrorLog->removeDisplayer(SBCLIENT::_FileDisplayer); - delete SBCLIENT::_FileDisplayer; SBCLIENT::_FileDisplayer = NULL; -#endif -} - -// Command to quit the client -NLMISC_COMMAND(sb_quit,"quit the client","") -{ - // check args, if there s not the right number of parameter, return bad - if (args.size() != 0) return false; - - log.displayNL("Exit requested"); - - SBCLIENT::NextGameState = SBCLIENT::GameStateExit; - - return true; -} - -NLMISC_COMMAND(sb_offline, "go offline", "") -{ - if (args.size() != 0) return false; - SBCLIENT::NextGameState = SBCLIENT::GameStateOffline; - return true; -} - -NLMISC_COMMAND(sb_unload, "unload game", "") -{ - if (args.size() != 0) return false; - SBCLIENT::NextGameState = SBCLIENT::GameStateUnload; - return true; -} - -NLMISC_COMMAND(sb_reset, "reset game", "") -{ - if (args.size() != 0) return false; - SBCLIENT::NextGameState = SBCLIENT::GameStateReset; - return true; -} - -NLMISC_COMMAND(sb_login, "go to the login screen", "") -{ - if (args.size() != 0) return false; - SBCLIENT::NextGameState = SBCLIENT::GameStateLogin; - return true; -} - -#if SBCLIENT_DEV_MEMLEAK -// enable memory leak checks, trick to get _CrtSetBreakAlloc in before main -#define DEBUG_ALLOC_HOOK -#if defined(NL_OS_WINDOWS) && defined(NL_DEBUG) -#if defined(DEBUG_ALLOC_HOOK) -int debugAllocHook(int allocType, void *userData, size_t size, int - blockType, long requestNumber, const unsigned char *filename, int - lineNumber); -#endif -class CEnableCrtDebug -{ -public: - CEnableCrtDebug() - { - _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); - _CrtSetBreakAlloc(0); -#if defined(DEBUG_ALLOC_HOOK) - LastSize = 0; - _CrtSetAllocHook(debugAllocHook); -#endif - } -#if defined(DEBUG_ALLOC_HOOK) - size_t LastSize; -#endif -}; -static CEnableCrtDebug _EnableCrtDebug; -#if defined(DEBUG_ALLOC_HOOK) -int debugAllocHook(int allocType, void *userData, size_t size, int - blockType, long requestNumber, const unsigned char *filename, int - lineNumber) -{ - if (allocType == _HOOK_ALLOC) - { - //if (requestNumber == 14806) - // _CrtSetBreakAlloc(14809); - //if (_EnableCrtDebug.LastSize == 4 && size == 40 && requestNumber > 291000 && requestNumber < 292000) - // _CrtDbgBreak(); - //if (_EnableCrtDebug.LastSize == 36 && size == 112 && requestNumber > 300000) - // _CrtDbgBreak(); - _EnableCrtDebug.LastSize = size; - } - return TRUE; -} -#endif -#endif - -// trick to clean up nel memory trash! (todo: unload of loaded dynamic nel libs (nel drivers) in linux) -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef NL_OS_WINDOWS -#include -BOOL CALLBACK EnumerateLoadedModulesProc(PCSTR ModuleName, ULONG ModuleBase, ULONG ModuleSize, PVOID UserContext) -{ - // free nel libraries (cannot call nlwarning etc here, so nlGetProcAddress etc does not work) - HMODULE hModule = GetModuleHandle(ModuleName); - if (GetProcAddress(hModule, NL_MACRO_TO_STR(NLMISC_PURE_LIB_ENTRY_POINT))) - FreeLibrary(hModule); - return TRUE; -} -#endif -struct yy_buffer_state; -extern void cf_switch_to_buffer(yy_buffer_state *new_buffer); -extern yy_buffer_state *cf_create_buffer(FILE *file, int size); -extern void cf_delete_buffer(yy_buffer_state *b); -class CCleanupNeL -{ -public: - CCleanupNeL() : _CfBufferState(NULL) - { - _CfBufferState = cf_create_buffer(NULL, 16384); - cf_switch_to_buffer(_CfBufferState); - } - ~CCleanupNeL() - { -#ifdef NL_OS_WINDOWS - // must unload all other nel modules before killing nel context (or they will crash in static destructors) - EnumerateLoadedModules(GetCurrentProcess(), EnumerateLoadedModulesProc, NULL); // todo: linux version -#endif - - // delete most stuff - NL3D::CParticleSystemShape::releaseInstance(); - NLMISC::CAsyncFileManager::terminate(); - NL3D::CParticleSystemManager::release(); - NLMISC::CBigFile::releaseInstance(); - NLMISC::CClassRegistry::release(); - delete &NLMISC::CObjectArenaAllocator::getDefaultAllocator(); - cf_delete_buffer(_CfBufferState); _CfBufferState = NULL; - -#ifdef NL_OS_WINDOWS - // delete context related stuff (must unload all dynamic nel libs first) - NLMISC::destroyDebug(); - if (NLMISC::INelContext::isContextInitialised()) - { - delete &NLMISC::INelContext::getInstance(); - delete &NLMISC::CInstanceCounterManager::getInstance(); - delete &NLMISC::CCommandRegistry::getInstance(); - } - NLMISC::CLog::releaseProcessName(); -#endif - } -private: - yy_buffer_state *_CfBufferState; -}; -CCleanupNeL _CleanupNeL; -#endif - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include "snowballs_client.h" +#include "snowballs_config.h" + +// STL includes +#include +#include +#include +#include +#if defined(NL_OS_WINDOWS) +# include +# include +#endif + +// NeL includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if SBCLIENT_DEV_STEREO +# include +#endif /* #if SBCLIENT_DEV_STEREO */ + +// Project includes +#include "pacs.h" +#include "radar.h" +#include "graph.h" +#include "camera.h" +#include "compass.h" +#include "commands.h" +#include "entities.h" +#include "network.h" +#include "landscape.h" +#include "animation.h" +#include "interface.h" +#include "lens_flare.h" +#include "mouse_listener.h" +#include "configuration.h" +#include "internationalization.h" +#include "game_time.h" + +#ifdef NL_OS_WINDOWS +#include +#endif + +using namespace std; +using namespace NLMISC; +using namespace NL3D; +using namespace NLNET; + +namespace SBCLIENT { + +/******************************************************************* + * GLOBALS * + *******************************************************************/ + +void CGlobals::assertNull() +{ + // extra verification against stupid typos + nlassert(!Driver); + nlassert(!Scene); + nlassert(!TextContext); + nlassert(!ConfigFile); + nlassert(!Landscape); + nlassert(!MouseListener); +} + +// The 3d driver +NL3D::UDriver *Driver = NULL; // core +// This is the main scene +NL3D::UScene *Scene = NULL; // ingame +// This variable is used to display text on the screen +NL3D::UTextContext *TextContext = NULL; // core +// This class contains all variables that are in the snowballs_client.cfg +NLMISC::CConfigFile *ConfigFile = NULL; // core +NL3D::ULandscape *Landscape = NULL; // ingame +// This class is used to handle mouse/keyboard input for camera movement +C3dMouseListener *MouseListener = NULL; // ingame +//// Log file +//CFileDisplayer FileDisplayer; // main + +// stuff not initialized +// The previous and current frame dates +NLMISC::TLocalTime LocalTime; +NLMISC::TLocalTime LocalTimeDelta; +// NLMISC::TLocalTime ServerTime; +// NLMISC::TLocalTime ServerTimeDelta; +// NLMISC::TGameTime GameTime; +// NLMISC::TGameTime GameTimeDelta; +// NLMISC::TGameCycle GameCycle; +// NLMISC::TGameCycle GameCycleDelta; +NL3D::TGlobalAnimationTime AnimationTime; +NL3D::TAnimationTime AnimationTimeDelta; +float FramesPerSecond; +float FramesPerSecondSmooth; + +// Stuff for connection +ucstring Login; +static string FSAddr, Cookie; + +/******************************************************************* + * SNOWBALLS CLIENT * + *******************************************************************/ + +static CFileDisplayer *_FileDisplayer = NULL; +static const uint8 GameStateLoad = 0, GameStateUnload = 1, GameStateReset = 2, GameStateExit = 3, +GameStateLogin = 4, GameStateOnline = 5, GameStateOffline = 6; + +// true if the commands(chat) interface must be display. This variable is set automatically with the config file +static bool ShowCommands; // ingame +// if true, the mouse can't go out the client window(work only on Windows) +static bool CaptureState = false; // ingame +// Set NextGameState to switch the current game state +static uint8 CurrentGameState = -1, NextGameState = 0; // state +// To know which data has been loaded +static bool LoadedCore = false, LoadedIngame = false, LoadedLogin = false, +LoadedOnline = false, LoadedOffline = false; // state + +#if SBCLIENT_DEV_STEREO +static IStereoRender *_StereoRender = NULL; +#endif /* #if SBCLIENT_DEV_STEREO */ + +// +// Prototypes +// + +void initLoadingState(); +void releaseLoadingState(); +void renderLoadingState(const char *state, bool logo3d); +void updateLoadingState(const char *state, bool network, bool information); +void displayLoadingState(const char *state); +void renderLoadingState(ucstring state, bool logo3d); +void updateLoadingState(ucstring state, bool network, bool information); +void displayLoadingState(ucstring state); +void update3dLogo(); +void renderInformation(); +void switchGameState(); +void loopLogin(); +void loopIngame(); +void initCore(); +void initLogin(); +void initIngame(); +void initOnline(); +void initOffline(); +void releaseCore(); +void releaseLogin(); +void releaseIngame(); +void releaseOnline(); +void releaseOffline(); +void cbGraphicsDriver(CConfigFile::CVar &var); + +// +// Functions +// + +void switchGameState() +{ +SwitchNextGameState: + nlinfo("Switching to the next game state"); + if (CurrentGameState == NextGameState) + { + nlwarning("NextGameState wasn't changed"); + } + else + { + switch(CurrentGameState) + { + case GameStateOnline: + releaseOnline(); // always release online after switch + break; + case GameStateOffline: + releaseOffline(); // always releaes offline after switch + break; + } + switch(NextGameState) + { + case GameStateLoad: + try + { + initCore(); // core is required + } + catch (NLMISC::Exception e) + { +#ifdef NL_OS_WINDOWS + MessageBox(NULL, e.what(), "NeL Exception", MB_OK | MB_ICONSTOP); +#else + printf("%s\n", e.what()); +#endif + return; // exit if driver loading failed + } + break; + case GameStateUnload: + displayLoadingState("Unloading"); + releaseLogin(); // release all + releaseIngame(); + break; + case GameStateReset: + displayLoadingState("Reset"); + releaseLogin(); // release all + releaseIngame(); + releaseCore(); + break; + case GameStateExit: + displayLoadingState("See you later!"); + releaseLogin(); // release all + releaseIngame(); + releaseCore(); + break; + case GameStateLogin: + initCore(); // core is required + initLogin(); // login is required + break; + case GameStateOnline: + initCore(); // core is required + releaseLogin(); //login can be released + initIngame(); // ingame is required + initOnline(); // connection is required + break; + case GameStateOffline: + initCore(); // core is required + releaseLogin(); //login can be released + initIngame(); // ingame is required + initOffline(); // offline entity required + break; + } + } + CurrentGameState = NextGameState; + switch(CurrentGameState) + { + case GameStateLoad: // switch to the default state + NextGameState = GameStateLogin; + break; + case GameStateUnload: // test state, switch back to load for default + NextGameState = GameStateLoad; + break; + case GameStateReset: // used to reset everything + NextGameState = GameStateLoad; + break; + case GameStateExit: // exit the loop + return; + case GameStateLogin: // loop the login screen + loopLogin(); // must loop by itself + break; + case GameStateOnline: // start offline if not online + if (!LoadedOnline) + { + NextGameState = GameStateOffline; + break; + } + case GameStateOffline: // loop ingame + loopIngame(); // must loop by itself + break; + } + goto SwitchNextGameState; +} + +void initCore() +{ + if (!LoadedCore) + { + LoadedCore = true; + // Seed the randomizer + srand(uint(time(0))); + // Load configuration file, set paths, extension remapping + CConfiguration::init(); + // Load language file + CInternationalization::init(); + // Start timing system + CGameTime::init(); + // Set the ShowCommands with the value set in the client config file + ShowCommands = ConfigFile->getVar("ShowCommands").asInt() == 1; + // Create a driver + Driver = UDriver::createDriver(0, ConfigFile->getVar("OpenGL").asInt() == 0); + // Create the window with config file values + Driver->setDisplay(UDriver::CMode(ConfigFile->getVar("ScreenWidth").asInt(), + ConfigFile->getVar("ScreenHeight").asInt(), + ConfigFile->getVar("ScreenDepth").asInt(), + ConfigFile->getVar("ScreenFull").asInt()==0)); + // Set the cache size for the font manager(in bytes) + Driver->setFontManagerMaxMemory(2097152); + // Create a Text context for later text rendering + displayLoadingState("Initialize Text"); + TextContext = Driver->createTextContext(CPath::lookup(ConfigFile->getVar("FontName").asString())); + TextContext->setShaded(true); + TextContext->setKeep800x600Ratio(false); + // You can't call displayLoadingState() before init the loading state system + displayLoadingState("Initialize Loading"); + initLoadingState(); + // Initialize sound for loading screens etc +//#ifdef NL_OS_WINDOWS +// displayLoadingState("Initialize Sound"); +// initSound(); +// playMusic(SBCLIENT_MUSIC_WAIT); +//#endif + // Required for 3d rendering (3d nel logo etc) + displayLoadingState("Initialize Light"); + initLight(); +#if SBCLIENT_DEV_STEREO + displayLoadingState("Initialize Stereo Renderer"); + _StereoRender = Driver->createStereoRender(); + _StereoRender->setMode("AnaglyphRedCyan"); + //_StereoRender->setMode("SideBySideHalf"); + //_StereoRender->setMode("Mono"); +#endif /* #if SBCLIENT_DEV_STEREO */ + + ConfigFile->setCallback("OpenGL", cbGraphicsDriver); + } +} + +void initLogin() +{ + if (!LoadedLogin) + { + LoadedLogin = true; + } +} + +void initIngame() +{ + if (!LoadedIngame) + { + LoadedIngame = true; +//#ifdef NL_OS_WINDOWS +// playMusic(SBCLIENT_MUSIC_WAIT); +//#endif + + // Create a scene + Scene = Driver->createScene(false); + + // initialize bloom effect + CBloomEffect::instance().setDriver(Driver); + CBloomEffect::instance().setScene(Scene); + CBloomEffect::instance().init(ConfigFile->getVar("OpenGL").asInt() == 1); + + // Init the landscape using the previously created UScene + displayLoadingState("Initialize Landscape"); + initLandscape(); + // Init the pacs + displayLoadingState("Initialize PACS "); + initPACS(); + // Init the aiming system + displayLoadingState("Initialize Aiming "); + initAiming(); + // Init the user camera + displayLoadingState("Initialize Camera "); + initCamera(); + // Create a 3D mouse listener + displayLoadingState("Initialize MouseListener "); + MouseListener = new C3dMouseListener(); + MouseListener->addToServer(Driver->EventServer); + MouseListener->setCamera(Camera); + MouseListener->setHotSpot(CVectorD(0,0,0)); + MouseListener->setFrustrum(Camera.getFrustum()); + MouseListener->setMatrix(Camera.getMatrix()); + MouseListener->setSpeed(PlayerSpeed); + initMouseListenerConfig(); + // Init interface + displayLoadingState("Initialize Interface "); + initInterface(); + // Init radar + displayLoadingState("Initialize Radar "); + initRadar(); + // Init compass + displayLoadingState("Initialize Compass "); + initCompass(); + // Init graph + displayLoadingState("Initialize Graph "); + initGraph(); + // Init the command control + displayLoadingState("Initialize Commands "); + initCommands(); + // Init the entities prefs + displayLoadingState("Initialize Entities "); + initEntities(); + // Init animation system + displayLoadingState("Initialize Animation "); + initAnimation(); + // Init the lens flare + displayLoadingState("Initialize LensFlare "); + initLensFlare(); + // Init the sky + displayLoadingState("Initialize Sky "); + initSky(); + + // Init the mouse so it's trapped by the main window. + Driver->showCursor(false); + Driver->setCapture(true); + Driver->setMousePos(0.5f, 0.5f); + } +} + +void initOnline() +{ + if (LoadedOnline) return; +//#ifdef NL_OS_WINDOWS +// playMusic(SBCLIENT_MUSIC_WAIT); +//#endif + + displayLoadingState("Connecting"); + + // connect to the server + nlinfo("Try to connect to FS addr '%s' and identify with the cookie '%s'", FSAddr.c_str(), Cookie.c_str()); + initNetwork(Cookie, FSAddr); + + while (Self == NULL) // wait for position etc from server + updateLoadingState(ucstring("Connecting"), true, true); + + displayLoadingState("Load Landscape"); + loadAllZonesAround(); + + displayLoadingState("Ready!"); + +//#ifdef NL_OS_WINDOWS +// playMusic(SBCLIENT_MUSIC_BACKGROUND); +//#endif + LoadedOnline = true; +} + +void initOffline() +{ + if (!LoadedOffline) + { + LoadedOffline = true; +//#ifdef NL_OS_WINDOWS +// playMusic(SBCLIENT_MUSIC_WAIT); +//#endif + + uint32 id = NextEID++; + Login = ucstring("Entity" + toString(id)); + + // Creates the self entity + displayLoadingState("Creating offline entity"); + CVector startPoint = CVector(ConfigFile->getVar("StartPoint").asFloat(0), ConfigFile->getVar("StartPoint").asFloat(1), ConfigFile->getVar("StartPoint").asFloat(2)); + addEntity(id, Login.toUtf8(), CEntity::Self, startPoint, startPoint); + + displayLoadingState("Load Landscape"); + loadAllZonesAround(); + + // Display a local welcome message + addLine(">>>>> Welcome to Snowballs!"); + addLine(">>>>> Press SHIFT-ESC to exit the game."); + + displayLoadingState("Ready!"); + +//#ifdef NL_OS_WINDOWS +// playMusic(SBCLIENT_MUSIC_BACKGROUND); +//#endif + } +} + +void releaseCore() +{ + if (LoadedCore) + { + LoadedCore = false; + // Release configuration callbacks + CConfiguration::dropCallback("OpenGL"); + +#if SBCLIENT_DEV_STEREO + // Release stereo render + Driver->deleteStereoRender(_StereoRender); + _StereoRender = NULL; +#endif /* #if SBCLIENT_DEV_STEREO */ + + // Release the sun + releaseLight(); + // Release the loading state textures + releaseLoadingState(); + // Release the sound +//#ifdef NL_OS_WINDOWS +// releaseSound(); +//#endif + // Release the text context + Driver->deleteTextContext(TextContext); + TextContext = NULL; + // Release the 3d driver + Driver->release(); + delete Driver; + Driver = NULL; + + // Release timing system + CGameTime::init(); + // Release language file + CInternationalization::init(); + // Release the configuration + CConfiguration::release(); + } +} + +void releaseLogin() +{ + if (LoadedLogin) + { + LoadedLogin = false; + } +} + +void releaseIngame() +{ + if (LoadedIngame) + { + LoadedIngame = false; + + // Release the mouse cursor + if (CaptureState) + { + Driver->setCapture(false); + Driver->showCursor(true); + } + + // Release all before quit + + releaseSky(); + releaseLensFlare(); + releaseRadar(); + releaseCommands(); + releaseEntities(); + releaseGraph(); + releaseCompass(); + releaseInterface(); + releaseNetwork(); + releaseAnimation(); + releaseMouseListenerConfig(); + releaseCamera(); + releaseAiming(); + releasePACS(); + releaseLandscape(); + // Release the mouse listener + MouseListener->removeFromServer(Driver->EventServer); + delete MouseListener; + MouseListener = NULL; + + // release bloom effect + CBloomEffect::instance().releaseInstance(); + + Driver->deleteScene(Scene); + Scene = NULL; + } +} + +void releaseOnline() +{ + if (LoadedOnline) + { + LoadedOnline = false; + releaseNetwork(); + deleteAllEntities(); + } +} + +void releaseOffline() +{ + if (LoadedOffline) + { + LoadedOffline = false; + deleteAllEntities(); + } +} + +void loopLogin() +{ +//#ifdef NL_OS_WINDOWS +// playMusic(SBCLIENT_MUSIC_LOGIN); +//#endif + // todo: login screen, move this stuff to a button or something + displayLoadingState("Login"); + if (ConfigFile->getVar("Local").asInt() == 0) + { + // Only attempt to directly log in if we haven't been passed a cookie already. + if(Cookie.empty() || FSAddr.empty()) + { + if (ConfigFile->getVar("UseDirectClient").asInt() == 1) + { + string result; + string LSHost(ConfigFile->getVar("LSHost").asString()); + Login = ConfigFile->getVar("Login").asString(); + string Password = ConfigFile->getVar("Password").asString(); + CHashKeyMD5 hk = getMD5((uint8 *)Password.c_str(), (uint32)Password.size()); + string CPassword = hk.toString(); + nlinfo("The crypted password is %s", CPassword.c_str()); + string Application = ConfigFile->getVar("ClientApplication").asString(); + sint32 sid = ConfigFile->getVar("ShardId").asInt(); + + // 1/ Authenticate + updateLoadingState(ucstring("Authenticate"), false, false); + result = CLoginClient::authenticateBegin(LSHost, Login, CPassword, Application); + if (!result.empty()) goto AuthenticateFail; + while (CLoginClient::authenticateUpdate(result)) + updateLoadingState(ucstring("Authenticate"), false, false); + if (!result.empty()) goto AuthenticateFail; + goto AuthenticateSuccess; + +AuthenticateFail: + nlinfo("*** Authenticate failed '%s' ***", result.c_str()); + for (TLocalTime t = 0; t < 5.000; t += LocalTimeDelta) + updateLoadingState(ucstring("Authenticate failed: ") + ucstring(result), false, false); + NextGameState = GameStateOffline; + return; + +AuthenticateSuccess: + nlinfo("%d Shards are available:", CLoginClient::ShardList.size()); + for (uint i = 0; i < CLoginClient::ShardList.size(); i++) + { + nlinfo(" ShardId %3d: %s(%d online players)", CLoginClient::ShardList[i].Id, CLoginClient::ShardList[i].Name.toUtf8().c_str(), CLoginClient::ShardList[i].NbPlayers); + } + + // 2/ Select shard + updateLoadingState(ucstring("Select shard"), false, false); + result = CLoginClient::selectShardBegin(sid); + if (!result.empty()) goto SelectFail; + while (CLoginClient::selectShardUpdate(result, FSAddr, Cookie)) + updateLoadingState(ucstring("Select shard"), false, false); + if (!result.empty()) goto SelectFail; + goto SelectSuccess; + +SelectFail: + nlinfo("*** Connection to the shard failed '%s' ***", result.c_str()); + for (TLocalTime t = 0; t < 5.000; t += LocalTimeDelta) + updateLoadingState(ucstring("Select shard failed: ") + ucstring(result), false, false); + NextGameState = GameStateOffline; + return; + +SelectSuccess:; + } + } + NextGameState = GameStateOnline; + return; + } + NextGameState = GameStateOffline; + return; +} + +void loopIngame() +{ + while (CurrentGameState == NextGameState) + { + if (!Driver->isActive()) { NextGameState = GameStateExit; return; } + + // call all update functions + // 01. Update Utilities (configuration etc) + CConfiguration::updateUtilities(); // update configuration files + + // 02. Update Time (deltas) + CGameTime::updateTime(); + + // 03. Update Input (keyboard controls, etc) + Driver->EventServer.pump(); // Pump user input messages + MouseListener->update(); + MouseListener->updateCamera(); + + // 04. Update Incoming (network, receive messages) + updateNetwork(); + + // 05. Update Weather (sky, snow, wind, fog, sun) + animateSky(LocalTimeDelta); + + // 06. Update Landscape (async zone loading near entity) + updateLandscape(); // Update the landscape + + // ... Update Animations (TEST) + // ... + + // 07. Update Entities (collisions and actions) + // - Move Other Entities (move//, animations, etc) + // - Update Self Collision (move) + // - Update Self Entity (animations//, etc) + updateEntities(); // Update network messages FIXME_NETWORK_OUTGOING + + // 08. Update Animations (playlists) + Scene->animate(AnimationTime); // Set new animation date + + // 09. Update Camera (depends on entities) + updateCamera(); + + // 10. Update Interface (login, ui, etc) + // ... + + // 11. Update Sound (sound driver) +//#ifdef NL_OS_WINDOWS +// updateSound(); // Update the sound +//#endif + + // 12. Update Outgoing (network, send new position etc) + // ... + + // 13. Update Debug (stuff for dev) + // ... + + // if driver is lost (d3d) do nothing for a while + if (Driver->isLost()) nlSleep(10); + else + { + // call all 3d render thingies + Driver->clearBuffers(CRGBA(127, 0, 0)); // if you see red, there's a problem with bloom or stereo render +#if SBCLIENT_DEV_STEREO + _StereoRender->calculateCameras(Camera.getObjectPtr()); // calculate modified matrices for the current camera + for (uint cameraId = 0; cameraId < _StereoRender->getCameraCount(); ++cameraId) + { + _StereoRender->getCamera(cameraId, Camera.getObjectPtr()); // get the matrix details for this camera +#endif /* #if SBCLIENT_DEV_STEREO */ + + // 01. Render Driver (background color) + CBloomEffect::instance().initBloom(); // start bloom effect (just before the first scene element render) + Driver->clearBuffers(CRGBA(0, 0, 127)); // clear all buffers, if you see this blue there's a problem with scene rendering + + // 02. Render Sky (sky scene) + updateSky(); // Render the sky scene before the main scene + + // 04. Render Scene (entity scene) + Scene->render(); // Render + + // 05. Render Effects (flare) + updateLensFlare(); // Render the lens flare + CBloomEffect::instance().endBloom(); // end the actual bloom effect visible in the scene + + // 06. Render Interface 3D (player names) + CBloomEffect::instance().endInterfacesDisplayBloom(); // end bloom effect system after drawing the 3d interface (z buffer related) + +#if SBCLIENT_DEV_STEREO + _StereoRender->copyBufferToTexture(cameraId); // copy current buffer to the active stereorender texture + } + _StereoRender->restoreCamera(Camera.getObjectPtr()); // restore the camera + _StereoRender->render(); // render everything together in the current mode +#endif /* #if SBCLIENT_DEV_STEREO */ + + // 07. Render Interface 2D (chatboxes etc, optionally does have 3d) + updateCompass(); // Update the compass + updateRadar(); // Update the radar + updateGraph(); // Update the radar + if (ShowCommands) updateCommands(); // Update the commands panel + updateAnimation(); + renderEntitiesNames(); // Render the name on top of the other players + updateInterface(); // Update interface + renderInformation(); + update3dLogo(); + + // 08. Render Debug (stuff for dev) + // ... + + // 09. Render Buffer + Driver->swapBuffers(); + } + + // begin various extra keys stuff ... + + if (Driver->AsyncListener.isKeyDown(KeySHIFT) && Driver->AsyncListener.isKeyPushed(KeyESCAPE)) + { + // Shift Escape -> quit + NextGameState = GameStateExit; + } + else if (Driver->AsyncListener.isKeyPushed(KeyF3)) + { + // F3 -> toggle wireframe/solid + UDriver::TPolygonMode p = Driver->getPolygonMode(); + p = UDriver::TPolygonMode(((int)p+1)%3); + Driver->setPolygonMode(p); + } + else if (Driver->AsyncListener.isKeyPushed(KeyF4)) + { + // F4 -> clear the command(chat) output + clearCommands(); + } + else if (Driver->AsyncListener.isKeyPushed(KeyF5)) + { + // F5 -> display/hide the commands(chat) interface + ShowCommands = !ShowCommands; + } + else if (Driver->AsyncListener.isKeyPushed(KeyF6)) + { + // F6 -> display/hide the radar interface + RadarState =(RadarState + 1) % 3; + } + else if (Driver->AsyncListener.isKeyDown(KeyF7)) + { + // F7 -> radar zoom out + RadarDistance += 50; + } + else if (Driver->AsyncListener.isKeyDown(KeyF8)) + { + // F8 -> radar zoom in + RadarDistance -= 50; + } + else if (Driver->AsyncListener.isKeyPushed(KeyF9)) + { + // F9 -> release/capture the mouse cursor + if (!CaptureState) + { + Driver->setCapture(false); + Driver->showCursor(true); + MouseListener->removeFromServer(Driver->EventServer); + } + else + { + Driver->setCapture(true); + Driver->showCursor(false); + MouseListener->addToServer(Driver->EventServer); + } + CaptureState = !CaptureState; + } + else if (Driver->AsyncListener.isKeyPushed(KeyF10)) + { + // F10 -> switch beteen online and offline + if (isOnline()) NextGameState = GameStateOffline; + else NextGameState = GameStateLogin; + } + else if (Driver->AsyncListener.isKeyPushed(KeyF11)) + { + // F11 -> reset the PACS global position of the self entity(in case of a pacs failure :-\) + if (Self != NULL) + resetEntityPosition(Self->Id); + } + else if (Driver->AsyncListener.isKeyPushed(KeyF12)) + { + // F12 -> take a screenshot + CBitmap btm; + Driver->getBuffer(btm); + string filename = CFile::findNewFile("screenshot.tga"); + COFile fs(filename); + btm.writeTGA(fs,24,false); + nlinfo("Screenshot '%s' saved", filename.c_str()); + } + + // end of various keys + } +} + +void renderInformation() +{ + // Display if we are online or offline + TextContext->setHotSpot(UTextContext::TopRight); + TextContext->setColor(isOnline()?CRGBA(0, 255, 0):CRGBA(255, 0, 0)); + TextContext->setFontSize(18); + TextContext->printfAt(0.99f, 0.99f, isOnline() ? "Online" : "Offline"); + + // Display the frame rate + TextContext->setHotSpot(UTextContext::TopLeft); + TextContext->setColor(CRGBA(255, 255, 255, 255)); + TextContext->setFontSize(14); + TextContext->printfAt(0.01f, 0.99f, "%.2f(%.2f)fps %.3fs", FramesPerSecondSmooth, FramesPerSecond, (float)LocalTimeDelta); + + // one more frame + FpsGraph.addValue(1.0f); + SpfGraph.addOneValue((float)LocalTimeDelta); +} + +// +// Configuration callbacks +// + +void cbGraphicsDriver(CConfigFile::CVar &var) +{ + // -- give ingame warning or something instead =) + NextGameState = GameStateReset; +} + +// +// Loading state procedure +// + +static UTextureFile *NelLogo = NULL; +// static UTextureFile *NevraxLogo = NULL; +static UTextureFile *SnowballsBackground = NULL; +static float ScreenWidth, ScreenHeight; +// The logo 3D objects +static UScene *LogoScene = NULL; +static UInstance Logo = NULL; + +void initLoadingState() +{ + NelLogo = Driver->createTextureFile("nel128.tga"); + // NevraxLogo = Driver->createTextureFile("nevrax.tga"); + SnowballsBackground = Driver->createTextureFile("snowbg.tga"); + uint32 width, height; + Driver->getWindowSize(width, height); + ScreenWidth =(float)width; + ScreenHeight =(float)height; + + // + // Setup the logo scene + // + + LogoScene = Driver->createScene(false); + + CViewport v; + v.init(0.0f, 0.80f, 0.2f, 0.2f); + LogoScene->setViewport(v); + + Logo = LogoScene->createInstance("nel_logo.shape"); + Logo.setPos(0.0f, 3.0f, 0.0f); + Logo.setTransformMode(UTransformable::RotEuler); +} + +void releaseLoadingState() +{ + LogoScene->deleteInstance(Logo); Logo = NULL; + Driver->deleteScene(LogoScene); LogoScene = NULL; + + Driver->deleteTextureFile(NelLogo); NelLogo = NULL; + // Driver->deleteTextureFile(NevraxLogo); NevraxLogo = NULL; + Driver->deleteTextureFile(SnowballsBackground); SnowballsBackground = NULL; +} + +void renderLoadingState(const char *state, bool logo3d) +{ + renderLoadingState(ucstring(state), logo3d); +} +void renderLoadingState(ucstring state, bool logo3d) +{ + if (!Driver) return; + + Driver->clearBuffers(CRGBA(0,0,0)); + + Driver->setMatrixMode2D(CFrustum(0.0f, ScreenWidth, 0.0f, ScreenHeight, 0.0f, 1.0f, false)); + + if (SnowballsBackground != NULL) + { + float imageAspect = 16.0f / 9.0f; // 1.777 + float minTransform = 4.0f / 3.0f; // 1.333 + float screenAspect = ScreenWidth / ScreenHeight; + float transform = screenAspect > imageAspect ? 1.0f : (screenAspect < minTransform ? imageAspect / minTransform : imageAspect / screenAspect); + float newWidth = ScreenWidth * transform; + Driver->drawBitmap((newWidth - ScreenWidth) * -0.5f, 0, newWidth, ScreenHeight, *SnowballsBackground); + } + + /*if (logo3d) update3dLogo(); + else */ if (NelLogo != NULL) Driver->drawBitmap(16, 32 - 42, 128, 128, *NelLogo); + // if (NevraxLogo != NULL) Driver->drawBitmap(ScreenWidth - 128 - 16, 32, 128, 16, *NevraxLogo); + + if (!TextContext) return; + + TextContext->setColor(CRGBA(255, 255, 255)); + TextContext->setHotSpot(UTextContext::MiddleMiddle); + + TextContext->setFontSize(40); + TextContext->printAt(0.5f, 0.5f, ucstring("Welcome to Snowballs!")); + + TextContext->setFontSize(30); + TextContext->printAt(0.5f, 0.2f, state); + + TextContext->setHotSpot(UTextContext::BottomRight); + TextContext->setFontSize(15); +#if (FINAL_VERSION == 1) + TextContext->printAt(0.99f, 0.01f, ucstring("Final Version")); +#else + TextContext->printAt(0.99f, 0.01f, ucstring("(compiled " __DATE__ " " __TIME__ ")")); +#endif + + TextContext->setHotSpot(UTextContext::BottomLeft); + TextContext->setFontSize(15); +#if defined(NL_DEBUG_FAST) + ucstring version = ucstring("DebugFast Version"); +#elif defined(NL_DEBUG) + ucstring version = ucstring("Debug Version"); +#elif defined(NL_RELEASE) + ucstring version = ucstring("Release Version"); +#elif defined(NL_RELEASE_DEBUG) + ucstring version = ucstring("ReleaseDebug Version"); +#else + ucstring version = ucstring("Unknown Version"); +#endif + TextContext->printAt(0.01f, 0.01f, version); +} + +void displayLoadingState(const char *state) +{ + displayLoadingState(ucstring(state)); +} +void displayLoadingState(ucstring state) +{ + CGameTime::updateTime(); + renderLoadingState(state, false); + Driver->swapBuffers(); + //Driver->EventServer.pump(); +} + +void updateLoadingState(const char *state, bool network, bool information) +{ + updateLoadingState(ucstring(state), network, information); +} +void updateLoadingState(ucstring state, bool network, bool information) +{ + CGameTime::updateTime(); // important that time is updated here!!! +//#ifdef NL_OS_WINDOWS +// updateSound(); +//#endif + renderLoadingState(state, true); + if (information) renderInformation(); + if (network) updateNetwork(); + Driver->swapBuffers(); + Driver->EventServer.pump(); +} + +void update3dLogo() +{ + Driver->clearZBuffer(); + static float angle = 0.0; + angle += 2.0f * (float)LocalTimeDelta; + Logo.setRotEuler(0.0f, 0.0f, angle); + LogoScene->animate(AnimationTime); + LogoScene->render(); +} + +void CSnowballsClient::init() +{ + // Sanity check + CGlobals::assertNull(); +} + +bool CSnowballsClient::run() +{ + // Run the game state loop switcher + switchGameState(); + return true; +} + +void CSnowballsClient::release() +{ + // Make sure everything's released + releaseOnline(); + releaseOffline(); + releaseIngame(); + releaseLogin(); + releaseCore(); + CGlobals::assertNull(); +} + +} /* namespace SBCLIENT */ + +void end(); +#ifdef NL_OS_WINDOWS +# ifdef _UNICODE +# define tstring wstring +# else +# define tstring string +# endif +sint WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdline, int nCmdShow) +#else +sint main(int argc, char **argv) +#endif +{ + // must do this to allow deallocation when closing with X + atexit(end); + +#ifdef NL_OS_WINDOWS + + // extract the 2 first param (argv[1] and argv[2]) it must be cookie and addr + + string cmd = cmdline; + string::size_type pos1 = cmd.find_first_not_of (' '); + string::size_type pos2; + if (pos1 != string::npos) + { + pos2 = cmd.find (' ', pos1); + if(pos2 != string::npos) + { + SBCLIENT::Cookie = cmd.substr (pos1, pos2-pos1); + + pos1 = cmd.find_first_not_of (' ', pos2); + if (pos1 != string::npos) + { + pos2 = cmd.find (' ', pos1); + if(pos2 == string::npos) + { + SBCLIENT::FSAddr = cmd.substr (pos1); + } + else if (pos1 != pos2) + { + SBCLIENT::FSAddr = cmd.substr (pos1, pos2-pos1); + } + } + } + } + +#else + + if (argc>=3) + { + SBCLIENT::Cookie = argv[1]; + SBCLIENT::FSAddr = argv[2]; + } + +#endif + + nlinfo ("cookie '%s' addr '%s'", SBCLIENT::Cookie.c_str (), SBCLIENT::FSAddr.c_str()); + + +#if defined(NL_OS_WINDOWS) && !FINAL_VERSION + // ensure paths are ok before powering up nel + { + OutputDebugString(" ******************************** \n"); + OutputDebugString(" * DEVELOPER MODE * \n"); + OutputDebugString(" ******************************** \n\n"); + FILE *f = _tfopen(_T(SBCLIENT_CONFIG_FILE_DEFAULT), _T("r")); + if (!f) + { + OutputDebugString(" ******************************** \n"); + OutputDebugString(" * CHANGING WORKING DIRECTORY * \n"); + OutputDebugString(" ******************************** \n\n"); + char cwd[256]; + _tgetcwd(cwd, 256); + tstring workdir(cwd); + workdir += "\\..\\bin\\"; + _tchdir(workdir.c_str()); + f = _tfopen(_T(SBCLIENT_CONFIG_FILE_DEFAULT), _T("r")); + if (!f) + { + OutputDebugString(" ******************************** \n"); + OutputDebugString(" * DEFAULT CONFIG MISSING * \n"); + OutputDebugString(" ******************************** \n\n"); + return EXIT_FAILURE; + } + } + fclose(f); + } +#endif + + // go nel! + { + // use log.log if NEL_LOG_IN_FILE and SBCLIENT_USE_LOG_LOG defined as 1 + createDebug(NULL, SBCLIENT_USE_LOG_LOG, false); + + #if SBCLIENT_USE_LOG + // create snowballs_client.log + // filedisplayer only deletes the 001 etc + if (SBCLIENT_ERASE_LOG && CFile::isExists(SBCLIENT_LOG_FILE)) + CFile::deleteFile(SBCLIENT_LOG_FILE); + // initialize the log file + SBCLIENT::_FileDisplayer = new CFileDisplayer(); + SBCLIENT::_FileDisplayer->setParam(SBCLIENT_LOG_FILE, SBCLIENT_ERASE_LOG); + DebugLog->addDisplayer(SBCLIENT::_FileDisplayer); + InfoLog->addDisplayer(SBCLIENT::_FileDisplayer); + WarningLog->addDisplayer(SBCLIENT::_FileDisplayer); + AssertLog->addDisplayer(SBCLIENT::_FileDisplayer); + ErrorLog->addDisplayer(SBCLIENT::_FileDisplayer); + #endif + + nlinfo("Welcome to NeL!"); + } + + SBCLIENT::CSnowballsClient::init(); + exit(SBCLIENT::CSnowballsClient::run() ? EXIT_SUCCESS : EXIT_FAILURE); + return EXIT_FAILURE; +} +void end() +{ + SBCLIENT::CSnowballsClient::release(); + nlinfo("See you later!"); + +#if SBCLIENT_USE_LOG + DebugLog->removeDisplayer(SBCLIENT::_FileDisplayer); + InfoLog->removeDisplayer(SBCLIENT::_FileDisplayer); + WarningLog->removeDisplayer(SBCLIENT::_FileDisplayer); + AssertLog->removeDisplayer(SBCLIENT::_FileDisplayer); + ErrorLog->removeDisplayer(SBCLIENT::_FileDisplayer); + delete SBCLIENT::_FileDisplayer; SBCLIENT::_FileDisplayer = NULL; +#endif +} + +// Command to quit the client +NLMISC_COMMAND(sb_quit,"quit the client","") +{ + // check args, if there s not the right number of parameter, return bad + if (args.size() != 0) return false; + + log.displayNL("Exit requested"); + + SBCLIENT::NextGameState = SBCLIENT::GameStateExit; + + return true; +} + +NLMISC_COMMAND(sb_offline, "go offline", "") +{ + if (args.size() != 0) return false; + SBCLIENT::NextGameState = SBCLIENT::GameStateOffline; + return true; +} + +NLMISC_COMMAND(sb_unload, "unload game", "") +{ + if (args.size() != 0) return false; + SBCLIENT::NextGameState = SBCLIENT::GameStateUnload; + return true; +} + +NLMISC_COMMAND(sb_reset, "reset game", "") +{ + if (args.size() != 0) return false; + SBCLIENT::NextGameState = SBCLIENT::GameStateReset; + return true; +} + +NLMISC_COMMAND(sb_login, "go to the login screen", "") +{ + if (args.size() != 0) return false; + SBCLIENT::NextGameState = SBCLIENT::GameStateLogin; + return true; +} + +#if SBCLIENT_DEV_MEMLEAK +// enable memory leak checks, trick to get _CrtSetBreakAlloc in before main +#define DEBUG_ALLOC_HOOK +#if defined(NL_OS_WINDOWS) && defined(NL_DEBUG) +#if defined(DEBUG_ALLOC_HOOK) +int debugAllocHook(int allocType, void *userData, size_t size, int + blockType, long requestNumber, const unsigned char *filename, int + lineNumber); +#endif +class CEnableCrtDebug +{ +public: + CEnableCrtDebug() + { + _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); + _CrtSetBreakAlloc(0); +#if defined(DEBUG_ALLOC_HOOK) + LastSize = 0; + _CrtSetAllocHook(debugAllocHook); +#endif + } +#if defined(DEBUG_ALLOC_HOOK) + size_t LastSize; +#endif +}; +static CEnableCrtDebug _EnableCrtDebug; +#if defined(DEBUG_ALLOC_HOOK) +int debugAllocHook(int allocType, void *userData, size_t size, int + blockType, long requestNumber, const unsigned char *filename, int + lineNumber) +{ + if (allocType == _HOOK_ALLOC) + { + //if (requestNumber == 14806) + // _CrtSetBreakAlloc(14809); + //if (_EnableCrtDebug.LastSize == 4 && size == 40 && requestNumber > 291000 && requestNumber < 292000) + // _CrtDbgBreak(); + //if (_EnableCrtDebug.LastSize == 36 && size == 112 && requestNumber > 300000) + // _CrtDbgBreak(); + _EnableCrtDebug.LastSize = size; + } + return TRUE; +} +#endif +#endif + +// trick to clean up nel memory trash! (todo: unload of loaded dynamic nel libs (nel drivers) in linux) +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef NL_OS_WINDOWS +#include +BOOL CALLBACK EnumerateLoadedModulesProc(PCSTR ModuleName, ULONG ModuleBase, ULONG ModuleSize, PVOID UserContext) +{ + // free nel libraries (cannot call nlwarning etc here, so nlGetProcAddress etc does not work) + HMODULE hModule = GetModuleHandle(ModuleName); + if (GetProcAddress(hModule, NL_MACRO_TO_STR(NLMISC_PURE_LIB_ENTRY_POINT))) + FreeLibrary(hModule); + return TRUE; +} +#endif +struct yy_buffer_state; +extern void cf_switch_to_buffer(yy_buffer_state *new_buffer); +extern yy_buffer_state *cf_create_buffer(FILE *file, int size); +extern void cf_delete_buffer(yy_buffer_state *b); +class CCleanupNeL +{ +public: + CCleanupNeL() : _CfBufferState(NULL) + { + _CfBufferState = cf_create_buffer(NULL, 16384); + cf_switch_to_buffer(_CfBufferState); + } + ~CCleanupNeL() + { +#ifdef NL_OS_WINDOWS + // must unload all other nel modules before killing nel context (or they will crash in static destructors) + EnumerateLoadedModules(GetCurrentProcess(), EnumerateLoadedModulesProc, NULL); // todo: linux version +#endif + + // delete most stuff + NL3D::CParticleSystemShape::releaseInstance(); + NLMISC::CAsyncFileManager::terminate(); + NL3D::CParticleSystemManager::release(); + NLMISC::CBigFile::releaseInstance(); + NLMISC::CClassRegistry::release(); + delete &NLMISC::CObjectArenaAllocator::getDefaultAllocator(); + cf_delete_buffer(_CfBufferState); _CfBufferState = NULL; + +#ifdef NL_OS_WINDOWS + // delete context related stuff (must unload all dynamic nel libs first) + NLMISC::destroyDebug(); + if (NLMISC::INelContext::isContextInitialised()) + { + delete &NLMISC::INelContext::getInstance(); + delete &NLMISC::CInstanceCounterManager::getInstance(); + delete &NLMISC::CCommandRegistry::getInstance(); + } + NLMISC::CLog::releaseProcessName(); +#endif + } +private: + yy_buffer_state *_CfBufferState; +}; +CCleanupNeL _CleanupNeL; +#endif + +/* end of file */ diff --git a/code/snowballs2/client/src/snowballs_client.h b/code/snowballs2/client/src/snowballs_client.h index 5eac7048f..67116f7e6 100644 --- a/code/snowballs2/client/src/snowballs_client.h +++ b/code/snowballs2/client/src/snowballs_client.h @@ -1,99 +1,99 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef SBCLIENT_SNOWBALLS_CLIENT_H -#define SBCLIENT_SNOWBALLS_CLIENT_H -#include -#include "snowballs_config.h" - -#include - -// STL includes -// ... - -// NeL includes -#include -#include -#include -#include - -// Project includes -// ... - -namespace NLMISC { - class CConfigFile; -} - -namespace NL3D { - class UDriver; - class UScene; - class UTextContext; - class ULandscape; -} - -namespace SBCLIENT { - class C3dMouseListener; - -/******************************************************************* - * GLOBALS * - *******************************************************************/ - -class CGlobals -{ -public: - static void assertNull(); -}; - -extern NL3D::UDriver *Driver; -extern NL3D::UScene *Scene; -extern NL3D::UTextContext *TextContext; -extern NLMISC::CConfigFile *ConfigFile; -extern NL3D::ULandscape *Landscape; -extern C3dMouseListener *MouseListener; - -extern NLMISC::TLocalTime LocalTime; // use for delta only -extern NLMISC::TLocalTime LocalTimeDelta; -// extern NLMISC::TLocalTime ServerTime; // use for delta only -// extern NLMISC::TLocalTime ServerTimeDelta; -// extern NLMISC::TGameTime GameTime; -// extern NLMISC::TGameTime GameTimeDelta; -// extern NLMISC::TGameCycle GameCycle; -// extern NLMISC::TGameCycle GameCycleDelta; -extern NL3D::TGlobalAnimationTime AnimationTime; -extern NL3D::TAnimationTime AnimationTimeDelta; -extern float FramesPerSecond; -extern float FramesPerSecondSmooth; - -// Stuff for connection -extern ucstring Login; - -/******************************************************************* - * SNOWBALLS CLIENT * - *******************************************************************/ - -class CSnowballsClient -{ -public: - static void init(); - static bool run(); - static void release(); -}; - -} /* namespace SBCLIENT */ - -#endif /* #ifndef SBCLIENT_SNOWBALLS_CLIENT_H */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SBCLIENT_SNOWBALLS_CLIENT_H +#define SBCLIENT_SNOWBALLS_CLIENT_H +#include +#include "snowballs_config.h" + +#include + +// STL includes +// ... + +// NeL includes +#include +#include +#include +#include + +// Project includes +// ... + +namespace NLMISC { + class CConfigFile; +} + +namespace NL3D { + class UDriver; + class UScene; + class UTextContext; + class ULandscape; +} + +namespace SBCLIENT { + class C3dMouseListener; + +/******************************************************************* + * GLOBALS * + *******************************************************************/ + +class CGlobals +{ +public: + static void assertNull(); +}; + +extern NL3D::UDriver *Driver; +extern NL3D::UScene *Scene; +extern NL3D::UTextContext *TextContext; +extern NLMISC::CConfigFile *ConfigFile; +extern NL3D::ULandscape *Landscape; +extern C3dMouseListener *MouseListener; + +extern NLMISC::TLocalTime LocalTime; // use for delta only +extern NLMISC::TLocalTime LocalTimeDelta; +// extern NLMISC::TLocalTime ServerTime; // use for delta only +// extern NLMISC::TLocalTime ServerTimeDelta; +// extern NLMISC::TGameTime GameTime; +// extern NLMISC::TGameTime GameTimeDelta; +// extern NLMISC::TGameCycle GameCycle; +// extern NLMISC::TGameCycle GameCycleDelta; +extern NL3D::TGlobalAnimationTime AnimationTime; +extern NL3D::TAnimationTime AnimationTimeDelta; +extern float FramesPerSecond; +extern float FramesPerSecondSmooth; + +// Stuff for connection +extern ucstring Login; + +/******************************************************************* + * SNOWBALLS CLIENT * + *******************************************************************/ + +class CSnowballsClient +{ +public: + static void init(); + static bool run(); + static void release(); +}; + +} /* namespace SBCLIENT */ + +#endif /* #ifndef SBCLIENT_SNOWBALLS_CLIENT_H */ + +/* end of file */ diff --git a/code/snowballs2/client/src/snowballs_config.h b/code/snowballs2/client/src/snowballs_config.h index e245d4348..edd282718 100644 --- a/code/snowballs2/client/src/snowballs_config.h +++ b/code/snowballs2/client/src/snowballs_config.h @@ -1,79 +1,79 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include - - - -// use the default log.log file (not erased on use) -// #define SBCLIENT_USE_LOG_LOG false - - - -// the config file name -// #define SBCLIENT_CONFIG_FILE "snowballs_client.cfg" -// #define SBCLIENT_CONFIG_FILE_DEFAULT "snowballs_client_default.cfg" - -// use snowballs log file -// #define SBCLIENT_USE_LOG 1 - -// snowballs log file name -#define SBCLIENT_LOG_FILE "snowballs_client.log" - -// clear snowballs log before use -#define SBCLIENT_ERASE_LOG true - -// version number -#define SBCLIENT_VERSION "2.1.551" - - - -// temporary dev tags -#define SBCLIENT_DEV_SOUND 0 -#define SBCLIENT_DEV_STEREO 0 -#define SBCLIENT_DEV_MEMLEAK 0 - - - -// some default defines -#if FINAL_VERSION -# if !defined(SBCLIENT_USE_LOG_LOG) -# define SBCLIENT_USE_LOG_LOG false -# endif -# if !defined(SBCLIENT_USE_LOG) -# define SBCLIENT_USE_LOG 0 -# endif -#endif - -#if !defined(SBCLIENT_USE_LOG_LOG) -# define SBCLIENT_USE_LOG_LOG true -#endif -#if !defined (SBCLIENT_USE_LOG) -# define SBCLIENT_USE_LOG 1 -#endif - -// for compatibility with old configuration -#ifndef SBCLIENT_CONFIG_FILE -# ifndef SNOWBALLS_CONFIG -# define SBCLIENT_CONFIG_FILE "snowballs_client.cfg" -# else -# define SBCLIENT_CONFIG_FILE SNOWBALLS_CONFIG "client.cfg" -# endif -#endif - -#ifndef SBCLIENT_CONFIG_FILE_DEFAULT -# define SBCLIENT_CONFIG_FILE_DEFAULT "snowballs_client_default.cfg" +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include + + + +// use the default log.log file (not erased on use) +// #define SBCLIENT_USE_LOG_LOG false + + + +// the config file name +// #define SBCLIENT_CONFIG_FILE "snowballs_client.cfg" +// #define SBCLIENT_CONFIG_FILE_DEFAULT "snowballs_client_default.cfg" + +// use snowballs log file +// #define SBCLIENT_USE_LOG 1 + +// snowballs log file name +#define SBCLIENT_LOG_FILE "snowballs_client.log" + +// clear snowballs log before use +#define SBCLIENT_ERASE_LOG true + +// version number +#define SBCLIENT_VERSION "2.1.551" + + + +// temporary dev tags +#define SBCLIENT_DEV_SOUND 0 +#define SBCLIENT_DEV_STEREO 0 +#define SBCLIENT_DEV_MEMLEAK 0 + + + +// some default defines +#if FINAL_VERSION +# if !defined(SBCLIENT_USE_LOG_LOG) +# define SBCLIENT_USE_LOG_LOG false +# endif +# if !defined(SBCLIENT_USE_LOG) +# define SBCLIENT_USE_LOG 0 +# endif +#endif + +#if !defined(SBCLIENT_USE_LOG_LOG) +# define SBCLIENT_USE_LOG_LOG true +#endif +#if !defined (SBCLIENT_USE_LOG) +# define SBCLIENT_USE_LOG 1 +#endif + +// for compatibility with old configuration +#ifndef SBCLIENT_CONFIG_FILE +# ifndef SNOWBALLS_CONFIG +# define SBCLIENT_CONFIG_FILE "snowballs_client.cfg" +# else +# define SBCLIENT_CONFIG_FILE SNOWBALLS_CONFIG "client.cfg" +# endif +#endif + +#ifndef SBCLIENT_CONFIG_FILE_DEFAULT +# define SBCLIENT_CONFIG_FILE_DEFAULT "snowballs_client_default.cfg" #endif \ No newline at end of file diff --git a/code/snowballs2/client/src/sound.cpp b/code/snowballs2/client/src/sound.cpp index eec9cb950..7ad802e03 100644 --- a/code/snowballs2/client/src/sound.cpp +++ b/code/snowballs2/client/src/sound.cpp @@ -1,245 +1,245 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include - -#include -#include - -#include -#include - -#include -#include -#include - -#include "sound.h" -#include "entities.h" - -// -// Namespaces -// - -using namespace std; -using namespace NLMISC; -using namespace NLSOUND; - -#ifdef SBCLIENT_WITH_SOUND - -//// -//// Variables -//// -// -//UAudioMixer *AudioMixer = NULL; -//TSoundId SoundId; -//const vector *SoundIdArray; -//static bool SoundEnabled; -// -//// -//// Functions -//// -// -//#ifdef NL_OS_WINDOWS -//void initSound2(); -//void releaseSound2(); -//#endif -// -//void cbConfigFileSoundMaxTracks(NLMISC::CConfigFile::CVar &var) -//{ -////#ifdef NL_OS_WINDOWS -//// AudioMixer->changeMaxTrack(var.asInt()); -////#endif -//} -// -//void cbConfigFileSoundEnabled(NLMISC::CConfigFile::CVar &var) -//{ -////#ifdef NL_OS_WINDOWS -//// if (var.asBool() != SoundEnabled) -//// { -//// if (var.asBool()) initSound2(); -//// else releaseSound2(); -//// } -////#endif -//} -// -//void cbConfigFileFail(NLMISC::CConfigFile::CVar &var) -//{ -// //nlwarning("You can't modify the config variable '%s' at runtime for now, please restart the game", var.asString().c_str()); -//} -// -////#ifdef NL_OS_WINDOWS -////void initSound2() -////{ -//// AudioMixer = UAudioMixer::createAudioMixer (); -//// std::string driverName; -//// NLSOUND::UAudioMixer::TDriver driverType; -//// if (!ConfigFile->exists("SoundDriver")) -////#ifdef NL_OS_WINDOWS -//// driverType = NLSOUND::UAudioMixer::DriverFMod; -////#elif defined (NL_OS_UNIX) -//// driverType = NLSOUND::UAudioMixer::DriverOpenAl; -////#else -//// driverType = NLSOUND::UAudioMixer::DriverAuto; -////#endif -//// else -//// { -//// driverName = ConfigFile->getVar("SoundDriver").asString(); -//// if (driverName == "Auto") driverType = NLSOUND::UAudioMixer::DriverAuto; -//// else if (driverName == "FMod") driverType = NLSOUND::UAudioMixer::DriverFMod; -//// else if (driverName == "DSound") driverType = NLSOUND::UAudioMixer::DriverDSound; -//// else if (driverName == "OpenAl") driverType = NLSOUND::UAudioMixer::DriverOpenAl; -//// else nlerror("SoundDriver value '%s' is invalid.", driverName.c_str()); -//// } -//// -//// AudioMixer->init( -//// ConfigFile->exists("SoundMaxTracks") -//// ? ConfigFile->getVar("SoundMaxTracks").asInt() : 32, -//// ConfigFile->exists("SoundUseEax") -//// ? ConfigFile->getVar("SoundUseEax").asBool() : true, -//// ConfigFile->exists("SoundUseADPCM") -//// ? ConfigFile->getVar("SoundUseADPCM").asBool() : true, -//// NULL, false, driverType, -//// ConfigFile->exists("SoundForceSoftware") -//// ? ConfigFile->getVar("SoundForceSoftware").asBool() : true); -//// -//// ConfigFile->setCallback("SoundMaxTracks", cbConfigFileSoundMaxTracks); -//// ConfigFile->setCallback("SoundUseEax", cbConfigFileFail); -//// ConfigFile->setCallback("SoundUseADPCM", cbConfigFileFail); -//// ConfigFile->setCallback("SoundForceSoftware", cbConfigFileFail); -//// ConfigFile->setCallback("SoundDriver", cbConfigFileFail); -//// -//// PlaylistManager = new SBCLIENT::CMusicPlaylistManager(AudioMixer, ConfigFile, "SoundPlaylist"); -//// -//// /* AudioMixer->loadSoundBuffers ("sounds.nss", &SoundIdArray); -//// nlassert( SoundIdArray->size() == 2 ); -//// SoundId = (*SoundIdArray)[0]; -//// // StSoundId = (*SoundIdArray)[1]; */ -//// -//// SoundEnabled = true; -////} -////#endif -// -//void initSound() -//{ -////#ifdef NL_OS_WINDOWS -//// if (ConfigFile->exists("SoundEnabled") ? ConfigFile->getVar("SoundEnabled").asBool() : false) initSound2(); -//// ConfigFile->setCallback("SoundEnabled", cbConfigFileSoundEnabled); -////#endif -//} -// -//void playSound (CEntity &entity, TSoundId id) -//{ -///* entity.Source = AudioMixer->createSource (id); -// entity.Source->setLooping (true); -// entity.Source->play (); -//*/} -// -//void deleteSound (CEntity &entity) -//{ -///* if (entity.Source != NULL) -// { -// if (entity.Source->isPlaying ()) -// entity.Source->stop (); -// -// AudioMixer->removeSource (entity.Source); -// entity.Source = NULL; -// } -//*/} -// -//void updateSound() -//{ -////#ifdef NL_OS_WINDOWS -//// if (SoundEnabled) -//// { -//// PlaylistManager->update(DiffTime); -//// AudioMixer->update(); -//// } -////#endif -//} -// -////#ifdef NL_OS_WINDOWS -////void releaseSound2() -////{ -//// SoundEnabled = false; -//// ConfigFile->setCallback("SoundMaxTracks", NULL); -//// ConfigFile->setCallback("SoundUseEax", NULL); -//// ConfigFile->setCallback("SoundUseADPCM", NULL); -//// ConfigFile->setCallback("SoundForceSoftware", NULL); -//// ConfigFile->setCallback("SoundDriver", NULL); -//// delete PlaylistManager; -//// PlaylistManager = NULL; -//// delete AudioMixer; -//// AudioMixer = NULL; -////} -////#endif -// -//void releaseSound() -//{ -////#ifdef NL_OS_WINDOWS -//// ConfigFile->setCallback("SoundEnabled", NULL); -//// if (SoundEnabled) releaseSound2(); -////#endif -//} -// -////#ifdef NL_OS_WINDOWS -//// -////void playMusic(sint32 playlist, sint32 track) -////{ -//// if (SoundEnabled) -//// PlaylistManager->playMusic(playlist, track); -////} -//// -////void setMusicVolume(sint32 playlist, float volume) -////{ -//// if (SoundEnabled) -//// PlaylistManager->setVolume(playlist, volume); -////} -//// -////NLMISC_COMMAND(music_bg,"background music","") -////{ -//// if (args.size() != 0) return false; -//// playMusic(SBCLIENT_MUSIC_BACKGROUND); -//// return true; -////} -//// -////NLMISC_COMMAND(music_bg_beat,"background music with beat","") -////{ -//// if (args.size() != 0) return false; -//// PlaylistManager->playMusic(SBCLIENT_MUSIC_BACKGROUND_BEAT); -//// return true; -////} -//// -////NLMISC_COMMAND(music_wait,"loading music","") -////{ -//// if (args.size() != 0) return false; -//// PlaylistManager->playMusic(SBCLIENT_MUSIC_WAIT); -//// return true; -////} -//// -////NLMISC_COMMAND(music_login,"login screen music","") -////{ -//// if (args.size() != 0) return false; -//// PlaylistManager->playMusic(SBCLIENT_MUSIC_LOGIN); -//// return true; -////} -//// -////#endif - -#endif // SBCLIENT_WITH_SOUND +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include "sound.h" +#include "entities.h" + +// +// Namespaces +// + +using namespace std; +using namespace NLMISC; +using namespace NLSOUND; + +#ifdef SBCLIENT_WITH_SOUND + +//// +//// Variables +//// +// +//UAudioMixer *AudioMixer = NULL; +//TSoundId SoundId; +//const vector *SoundIdArray; +//static bool SoundEnabled; +// +//// +//// Functions +//// +// +//#ifdef NL_OS_WINDOWS +//void initSound2(); +//void releaseSound2(); +//#endif +// +//void cbConfigFileSoundMaxTracks(NLMISC::CConfigFile::CVar &var) +//{ +////#ifdef NL_OS_WINDOWS +//// AudioMixer->changeMaxTrack(var.asInt()); +////#endif +//} +// +//void cbConfigFileSoundEnabled(NLMISC::CConfigFile::CVar &var) +//{ +////#ifdef NL_OS_WINDOWS +//// if (var.asBool() != SoundEnabled) +//// { +//// if (var.asBool()) initSound2(); +//// else releaseSound2(); +//// } +////#endif +//} +// +//void cbConfigFileFail(NLMISC::CConfigFile::CVar &var) +//{ +// //nlwarning("You can't modify the config variable '%s' at runtime for now, please restart the game", var.asString().c_str()); +//} +// +////#ifdef NL_OS_WINDOWS +////void initSound2() +////{ +//// AudioMixer = UAudioMixer::createAudioMixer (); +//// std::string driverName; +//// NLSOUND::UAudioMixer::TDriver driverType; +//// if (!ConfigFile->exists("SoundDriver")) +////#ifdef NL_OS_WINDOWS +//// driverType = NLSOUND::UAudioMixer::DriverFMod; +////#elif defined (NL_OS_UNIX) +//// driverType = NLSOUND::UAudioMixer::DriverOpenAl; +////#else +//// driverType = NLSOUND::UAudioMixer::DriverAuto; +////#endif +//// else +//// { +//// driverName = ConfigFile->getVar("SoundDriver").asString(); +//// if (driverName == "Auto") driverType = NLSOUND::UAudioMixer::DriverAuto; +//// else if (driverName == "FMod") driverType = NLSOUND::UAudioMixer::DriverFMod; +//// else if (driverName == "DSound") driverType = NLSOUND::UAudioMixer::DriverDSound; +//// else if (driverName == "OpenAl") driverType = NLSOUND::UAudioMixer::DriverOpenAl; +//// else nlerror("SoundDriver value '%s' is invalid.", driverName.c_str()); +//// } +//// +//// AudioMixer->init( +//// ConfigFile->exists("SoundMaxTracks") +//// ? ConfigFile->getVar("SoundMaxTracks").asInt() : 32, +//// ConfigFile->exists("SoundUseEax") +//// ? ConfigFile->getVar("SoundUseEax").asBool() : true, +//// ConfigFile->exists("SoundUseADPCM") +//// ? ConfigFile->getVar("SoundUseADPCM").asBool() : true, +//// NULL, false, driverType, +//// ConfigFile->exists("SoundForceSoftware") +//// ? ConfigFile->getVar("SoundForceSoftware").asBool() : true); +//// +//// ConfigFile->setCallback("SoundMaxTracks", cbConfigFileSoundMaxTracks); +//// ConfigFile->setCallback("SoundUseEax", cbConfigFileFail); +//// ConfigFile->setCallback("SoundUseADPCM", cbConfigFileFail); +//// ConfigFile->setCallback("SoundForceSoftware", cbConfigFileFail); +//// ConfigFile->setCallback("SoundDriver", cbConfigFileFail); +//// +//// PlaylistManager = new SBCLIENT::CMusicPlaylistManager(AudioMixer, ConfigFile, "SoundPlaylist"); +//// +//// /* AudioMixer->loadSoundBuffers ("sounds.nss", &SoundIdArray); +//// nlassert( SoundIdArray->size() == 2 ); +//// SoundId = (*SoundIdArray)[0]; +//// // StSoundId = (*SoundIdArray)[1]; */ +//// +//// SoundEnabled = true; +////} +////#endif +// +//void initSound() +//{ +////#ifdef NL_OS_WINDOWS +//// if (ConfigFile->exists("SoundEnabled") ? ConfigFile->getVar("SoundEnabled").asBool() : false) initSound2(); +//// ConfigFile->setCallback("SoundEnabled", cbConfigFileSoundEnabled); +////#endif +//} +// +//void playSound (CEntity &entity, TSoundId id) +//{ +///* entity.Source = AudioMixer->createSource (id); +// entity.Source->setLooping (true); +// entity.Source->play (); +//*/} +// +//void deleteSound (CEntity &entity) +//{ +///* if (entity.Source != NULL) +// { +// if (entity.Source->isPlaying ()) +// entity.Source->stop (); +// +// AudioMixer->removeSource (entity.Source); +// entity.Source = NULL; +// } +//*/} +// +//void updateSound() +//{ +////#ifdef NL_OS_WINDOWS +//// if (SoundEnabled) +//// { +//// PlaylistManager->update(DiffTime); +//// AudioMixer->update(); +//// } +////#endif +//} +// +////#ifdef NL_OS_WINDOWS +////void releaseSound2() +////{ +//// SoundEnabled = false; +//// ConfigFile->setCallback("SoundMaxTracks", NULL); +//// ConfigFile->setCallback("SoundUseEax", NULL); +//// ConfigFile->setCallback("SoundUseADPCM", NULL); +//// ConfigFile->setCallback("SoundForceSoftware", NULL); +//// ConfigFile->setCallback("SoundDriver", NULL); +//// delete PlaylistManager; +//// PlaylistManager = NULL; +//// delete AudioMixer; +//// AudioMixer = NULL; +////} +////#endif +// +//void releaseSound() +//{ +////#ifdef NL_OS_WINDOWS +//// ConfigFile->setCallback("SoundEnabled", NULL); +//// if (SoundEnabled) releaseSound2(); +////#endif +//} +// +////#ifdef NL_OS_WINDOWS +//// +////void playMusic(sint32 playlist, sint32 track) +////{ +//// if (SoundEnabled) +//// PlaylistManager->playMusic(playlist, track); +////} +//// +////void setMusicVolume(sint32 playlist, float volume) +////{ +//// if (SoundEnabled) +//// PlaylistManager->setVolume(playlist, volume); +////} +//// +////NLMISC_COMMAND(music_bg,"background music","") +////{ +//// if (args.size() != 0) return false; +//// playMusic(SBCLIENT_MUSIC_BACKGROUND); +//// return true; +////} +//// +////NLMISC_COMMAND(music_bg_beat,"background music with beat","") +////{ +//// if (args.size() != 0) return false; +//// PlaylistManager->playMusic(SBCLIENT_MUSIC_BACKGROUND_BEAT); +//// return true; +////} +//// +////NLMISC_COMMAND(music_wait,"loading music","") +////{ +//// if (args.size() != 0) return false; +//// PlaylistManager->playMusic(SBCLIENT_MUSIC_WAIT); +//// return true; +////} +//// +////NLMISC_COMMAND(music_login,"login screen music","") +////{ +//// if (args.size() != 0) return false; +//// PlaylistManager->playMusic(SBCLIENT_MUSIC_LOGIN); +//// return true; +////} +//// +////#endif + +#endif // SBCLIENT_WITH_SOUND diff --git a/code/snowballs2/client/src/sound.h b/code/snowballs2/client/src/sound.h index 7e97e7240..2862d141c 100644 --- a/code/snowballs2/client/src/sound.h +++ b/code/snowballs2/client/src/sound.h @@ -1,69 +1,69 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef SBCLIENT_SOUND_H -#define SBCLIENT_SOUND_H - -// -// Includes -// - -#include -#include - -#include -#include -#include - -#include "snowballs_client.h" -#include "entities.h" - -// -// Defines -// - -//#define SBCLIENT_MUSIC_WAIT (0), (0) -//#define SBCLIENT_MUSIC_LOGIN (1), (0) -//#define SBCLIENT_MUSIC_BACKGROUND (2), (0) -//#define SBCLIENT_MUSIC_BACKGROUND_BEAT (2), (1) - -// -// External variables -// - -//extern NLSOUND::UAudioMixer *AudioMixer; -//extern NLSOUND::TSoundId SoundId; -// -//// -//// External functions -//// -// -//void playMusic(sint32 playlist, sint32 track); -//void setMusicVolume(sint32 playlist, float volume); -// -//void initSound(); -//void updateSound(); -//void releaseSound(); -// -//// Set and play a sound on an entity -//void playSound(CEntity &entity, NLSOUND::TSoundId id); -// -//// Remove the sound system link to the entity -//void deleteSound(CEntity &entity); - -#endif // SBCLIENT_SOUND_H - -/* End of sound.h */ // duh +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SBCLIENT_SOUND_H +#define SBCLIENT_SOUND_H + +// +// Includes +// + +#include +#include + +#include +#include +#include + +#include "snowballs_client.h" +#include "entities.h" + +// +// Defines +// + +//#define SBCLIENT_MUSIC_WAIT (0), (0) +//#define SBCLIENT_MUSIC_LOGIN (1), (0) +//#define SBCLIENT_MUSIC_BACKGROUND (2), (0) +//#define SBCLIENT_MUSIC_BACKGROUND_BEAT (2), (1) + +// +// External variables +// + +//extern NLSOUND::UAudioMixer *AudioMixer; +//extern NLSOUND::TSoundId SoundId; +// +//// +//// External functions +//// +// +//void playMusic(sint32 playlist, sint32 track); +//void setMusicVolume(sint32 playlist, float volume); +// +//void initSound(); +//void updateSound(); +//void releaseSound(); +// +//// Set and play a sound on an entity +//void playSound(CEntity &entity, NLSOUND::TSoundId id); +// +//// Remove the sound system link to the entity +//void deleteSound(CEntity &entity); + +#endif // SBCLIENT_SOUND_H + +/* End of sound.h */ // duh diff --git a/code/snowballs2/server/CMakeLists.txt b/code/snowballs2/server/CMakeLists.txt index ad60b4427..0faeccad0 100644 --- a/code/snowballs2/server/CMakeLists.txt +++ b/code/snowballs2/server/CMakeLists.txt @@ -1,6 +1,6 @@ -ADD_SUBDIRECTORY(chat) -ADD_SUBDIRECTORY(collision) -ADD_SUBDIRECTORY(frontend) -ADD_SUBDIRECTORY(position) - -INSTALL(FILES common.cfg DESTINATION etc/snowballs COMPONENT services) +ADD_SUBDIRECTORY(chat) +ADD_SUBDIRECTORY(collision) +ADD_SUBDIRECTORY(frontend) +ADD_SUBDIRECTORY(position) + +INSTALL(FILES common.cfg DESTINATION etc/snowballs COMPONENT services) diff --git a/code/snowballs2/server/chat/CMakeLists.txt b/code/snowballs2/server/chat/CMakeLists.txt index b80fe1d77..837bb742d 100644 --- a/code/snowballs2/server/chat/CMakeLists.txt +++ b/code/snowballs2/server/chat/CMakeLists.txt @@ -1,3 +1,3 @@ -ADD_SUBDIRECTORY(src) - -INSTALL(FILES chat_service.cfg DESTINATION etc/snowballs COMPONENT services) +ADD_SUBDIRECTORY(src) + +INSTALL(FILES chat_service.cfg DESTINATION etc/snowballs COMPONENT services) diff --git a/code/snowballs2/server/chat/src/CMakeLists.txt b/code/snowballs2/server/chat/src/CMakeLists.txt index 0106c3b1b..425242df7 100644 --- a/code/snowballs2/server/chat/src/CMakeLists.txt +++ b/code/snowballs2/server/chat/src/CMakeLists.txt @@ -1,17 +1,17 @@ -FILE(GLOB SRC *.cpp *.h) - -ADD_EXECUTABLE(snowballs_chat_service WIN32 ${SRC}) - -INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) - -TARGET_LINK_LIBRARIES(snowballs_chat_service - ${LIBXML2_LIBRARIES} - nelmisc - nelnet) - -NL_DEFAULT_PROPS(snowballs_chat_service "Snowballs, Services: Chat") -NL_ADD_RUNTIME_FLAGS(snowballs_chat_service) - -ADD_DEFINITIONS(${LIBXML2_DEFINITIONS}) - -INSTALL(TARGETS snowballs_chat_service RUNTIME DESTINATION sbin COMPONENT services) +FILE(GLOB SRC *.cpp *.h) + +ADD_EXECUTABLE(snowballs_chat_service WIN32 ${SRC}) + +INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) + +TARGET_LINK_LIBRARIES(snowballs_chat_service + ${LIBXML2_LIBRARIES} + nelmisc + nelnet) + +NL_DEFAULT_PROPS(snowballs_chat_service "Snowballs, Services: Chat") +NL_ADD_RUNTIME_FLAGS(snowballs_chat_service) + +ADD_DEFINITIONS(${LIBXML2_DEFINITIONS}) + +INSTALL(TARGETS snowballs_chat_service RUNTIME DESTINATION sbin COMPONENT services) diff --git a/code/snowballs2/server/chat/src/main.cpp b/code/snowballs2/server/chat/src/main.cpp index 37f58eb92..42a13d92a 100644 --- a/code/snowballs2/server/chat/src/main.cpp +++ b/code/snowballs2/server/chat/src/main.cpp @@ -1,99 +1,99 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif // HAVE_CONFIG_H - -#ifndef SNOWBALLS_CONFIG -#define SNOWBALLS_CONFIG "" -#endif // SNOWBALLS_CONFIG - -#ifndef SNOWBALLS_LOGS -#define SNOWBALLS_LOGS "" -#endif // SNOWBALLS_LOGS - -// This include is mandatory to use NeL. It include NeL types. -#include - -#include - -#include - -// We're using the NeL Service framework, and layer 5 -#include - -#ifdef NL_OS_WINDOWS -#include -#endif - -using namespace std; -using namespace NLMISC; -using namespace NLNET; - -/**************************************************************************** - * Function: cbChat - * Callback function called when the Chat Service receive a "CHAT" - * message - ****************************************************************************/ -void cbChat (CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - string message; - - // Extract the incoming message content from the Frontend and print it - msgin.serial( message ); - nldebug( "SB: Received CHAT line: \"%s\"", message.c_str() ); - - // Prepare to send back the message. - CMessage msgout( "CHAT" ); - msgout.serial( message ); - - /* - * Send the message to all the connected Frontend. - */ - CUnifiedNetwork::getInstance ()->send( "FS", msgout ); - - nldebug( "SB: Sent to every front end service CHAT line: \"%s\"", message.c_str() ); -} - - -/**************************************************************************** - * CallbackArray - * - * It define the functions to call when receiving a specific message - ****************************************************************************/ -TUnifiedCallbackItem CallbackArray[] = -{ - { "CHAT", cbChat } -}; - - -/**************************************************************************** - * SNOWBALLS CHAT SERVICE MAIN Function - * - * This call create a main function for the CHAT service: - * - * - based on the base service class "IService", no need to inherit from it - * - having the short name "CHAT" - * - having the long name "chat_service" - * - listening on an automatically allocated port (0) by the naming service - * - and callback actions set to "CallbackArray" - * - ****************************************************************************/ -NLNET_SERVICE_MAIN( IService, "CHAT", "chat_service", 0, CallbackArray, SNOWBALLS_CONFIG, SNOWBALLS_LOGS ) - - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif // HAVE_CONFIG_H + +#ifndef SNOWBALLS_CONFIG +#define SNOWBALLS_CONFIG "" +#endif // SNOWBALLS_CONFIG + +#ifndef SNOWBALLS_LOGS +#define SNOWBALLS_LOGS "" +#endif // SNOWBALLS_LOGS + +// This include is mandatory to use NeL. It include NeL types. +#include + +#include + +#include + +// We're using the NeL Service framework, and layer 5 +#include + +#ifdef NL_OS_WINDOWS +#include +#endif + +using namespace std; +using namespace NLMISC; +using namespace NLNET; + +/**************************************************************************** + * Function: cbChat + * Callback function called when the Chat Service receive a "CHAT" + * message + ****************************************************************************/ +void cbChat (CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + string message; + + // Extract the incoming message content from the Frontend and print it + msgin.serial( message ); + nldebug( "SB: Received CHAT line: \"%s\"", message.c_str() ); + + // Prepare to send back the message. + CMessage msgout( "CHAT" ); + msgout.serial( message ); + + /* + * Send the message to all the connected Frontend. + */ + CUnifiedNetwork::getInstance ()->send( "FS", msgout ); + + nldebug( "SB: Sent to every front end service CHAT line: \"%s\"", message.c_str() ); +} + + +/**************************************************************************** + * CallbackArray + * + * It define the functions to call when receiving a specific message + ****************************************************************************/ +TUnifiedCallbackItem CallbackArray[] = +{ + { "CHAT", cbChat } +}; + + +/**************************************************************************** + * SNOWBALLS CHAT SERVICE MAIN Function + * + * This call create a main function for the CHAT service: + * + * - based on the base service class "IService", no need to inherit from it + * - having the short name "CHAT" + * - having the long name "chat_service" + * - listening on an automatically allocated port (0) by the naming service + * - and callback actions set to "CallbackArray" + * + ****************************************************************************/ +NLNET_SERVICE_MAIN( IService, "CHAT", "chat_service", 0, CallbackArray, SNOWBALLS_CONFIG, SNOWBALLS_LOGS ) + + +/* end of file */ diff --git a/code/snowballs2/server/collision/CMakeLists.txt b/code/snowballs2/server/collision/CMakeLists.txt index 500d3c8dd..e49a978d6 100644 --- a/code/snowballs2/server/collision/CMakeLists.txt +++ b/code/snowballs2/server/collision/CMakeLists.txt @@ -1,3 +1,3 @@ -ADD_SUBDIRECTORY(src) - -INSTALL(FILES collision_service.cfg DESTINATION etc/snowballs COMPONENT services) +ADD_SUBDIRECTORY(src) + +INSTALL(FILES collision_service.cfg DESTINATION etc/snowballs COMPONENT services) diff --git a/code/snowballs2/server/collision/src/CMakeLists.txt b/code/snowballs2/server/collision/src/CMakeLists.txt index bd079b3ad..773bd65d8 100644 --- a/code/snowballs2/server/collision/src/CMakeLists.txt +++ b/code/snowballs2/server/collision/src/CMakeLists.txt @@ -1,19 +1,19 @@ -FILE(GLOB SRC *.cpp *.h) - -ADD_EXECUTABLE(snowballs_collision_service WIN32 ${SRC}) - -INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) - -TARGET_LINK_LIBRARIES(snowballs_collision_service - ${LIBXML2_LIBRARIES} - nelmisc - nelnet - nelpacs - nel3d) - -NL_DEFAULT_PROPS(snowballs_collision_service "Snowballs, Services: Collision") -NL_ADD_RUNTIME_FLAGS(snowballs_collision_service) - -ADD_DEFINITIONS(${LIBXML2_DEFINITIONS}) - -INSTALL(TARGETS snowballs_collision_service RUNTIME DESTINATION sbin COMPONENT services) +FILE(GLOB SRC *.cpp *.h) + +ADD_EXECUTABLE(snowballs_collision_service WIN32 ${SRC}) + +INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) + +TARGET_LINK_LIBRARIES(snowballs_collision_service + ${LIBXML2_LIBRARIES} + nelmisc + nelnet + nelpacs + nel3d) + +NL_DEFAULT_PROPS(snowballs_collision_service "Snowballs, Services: Collision") +NL_ADD_RUNTIME_FLAGS(snowballs_collision_service) + +ADD_DEFINITIONS(${LIBXML2_DEFINITIONS}) + +INSTALL(TARGETS snowballs_collision_service RUNTIME DESTINATION sbin COMPONENT services) diff --git a/code/snowballs2/server/collision/src/collision_service.cpp b/code/snowballs2/server/collision/src/collision_service.cpp index ffde0c725..83808f6c9 100644 --- a/code/snowballs2/server/collision/src/collision_service.cpp +++ b/code/snowballs2/server/collision/src/collision_service.cpp @@ -1,409 +1,409 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "collision_service.h" -#include - -#ifdef NL_OS_WINDOWS -#include -#endif - -using namespace SBSERVICE; -using namespace NLMISC; -using namespace NLNET; -using namespace NLPACS; -using namespace std; - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// VARIABLES /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -CCollisionService::CClientMap CCollisionService::_Clients; -NLPACS::URetrieverBank *CCollisionService::_RetrieverBank; -NLPACS::UGlobalRetriever *CCollisionService::_GlobalRetriever; -NLPACS::UMoveContainer *CCollisionService::_MoveContainer; -CCollisionService::CMovePrimitiveVector CCollisionService::_StaticMovePrimitives; -TTime CCollisionService::_LastTime, CCollisionService::_NewTime, CCollisionService::_DiffTime; -double CCollisionService::_DiffTimeSeconds; -float CCollisionService::_DiffTimeFloat; - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// BASIC FUNCTIONS /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -void CCollisionService::commandStart() -{ - -} - -void CCollisionService::init() -{ - // set down callback - CUnifiedNetwork::getInstance()->setServiceDownCallback("*", cbDown); - - // set the data path - CPath::addSearchPath(ConfigFile.getVar("DataPath").asString(), true, false); - - // init the global retriever, the retriever bank, and the move container - _RetrieverBank = URetrieverBank::createRetrieverBank(ConfigFile.getVar("RetrieverBankName").asString().c_str()); - _GlobalRetriever = UGlobalRetriever::createGlobalRetriever(ConfigFile.getVar("GlobalRetrieverName").asString().c_str(), _RetrieverBank); - _MoveContainer = UMoveContainer::createMoveContainer(_GlobalRetriever, 100, 100, 6.0); - - // some silly snowballs specific code to load static instance groups, redo - CConfigFile::CVar igv = ConfigFile.getVar("InstanceGroups"); - for (uint i = 0; i < igv.size(); ++i) - { - NL3D::UInstanceGroup *ig = NL3D::UInstanceGroup::createInstanceGroup(igv.asString(i)); - if (ig == NULL) nlwarning("Instance group '%s' not found", igv.asString(i).c_str()); - else - { - for (uint i = 0; i < ig->getNumInstance(); ++i) - { - UMovePrimitive *primitive = _MoveContainer->addCollisionablePrimitive(0, 1); - primitive->setPrimitiveType(UMovePrimitive::_2DOrientedCylinder); - primitive->setReactionType(UMovePrimitive::DoNothing); - primitive->setTriggerType(UMovePrimitive::NotATrigger); - primitive->setCollisionMask(2); - primitive->setOcclusionMask(1); - primitive->setObstacle(true); - - string name = ig->getShapeName(i); - float rad; - if (strlwr(name) == "pi_po_igloo_a") rad = 4.5f; - else if (strlwr(name) == "pi_po_snowman_a") rad = 1.0f; - else if (strlwr(name) == "pi_po_pinetree_a") rad = 2.0f; - else if (strlwr(name) == "pi_po_tree_a") rad = 2.0f; - else if (strlwr(name) == "pi_po_pingoo_stat_a") rad = 1.0f; - else if (strlwr(name) == "pi_po_gnu_stat_a") rad = 1.0f; - else - { - rad = 2.0f; - nlwarning ("Instance name '%s' doesn't have a good radius for collision", name.c_str()); - } - - primitive->setRadius(rad); - primitive->setHeight(6.0f); - - primitive->insertInWorldImage(0); - CVector pos = ig->getInstancePos(i); - primitive->setGlobalPosition(CVectorD(pos.x, pos.y, pos.z - 1.5f), 0); - _StaticMovePrimitives.push_back(primitive); - } - } - delete ig; - } - - _NewTime = CTime::getLocalTime(); -} - -bool CCollisionService::update() -{ - _LastTime = _NewTime; - _NewTime = CTime::getLocalTime(); - _DiffTime = _NewTime - _LastTime; - _DiffTimeSeconds = (double)_DiffTime / 1000.0; - _DiffTimeFloat = (float)_DiffTimeSeconds; - - for (CClientMap::iterator it = _Clients.begin(); it != _Clients.end(); it++) - for (CEntityMap::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) - { - CEntity &entity = it2->second; - - if (entity.Moving) - { - // nldebug("entity.Moving"); - CVector movement = entity.NewClientPosition - entity.OldClientPosition; - entity.Distance = movement.norm(); - if (entity.Distance == 0.0f) - { - entity.Moving = false; - entity.Retry = false; - } - CVectorD speed = CVectorD(movement) / _DiffTimeSeconds; - entity.MovePrimitive->move(speed, 0); - } - // else nldebug("!entity.Moving"); - } - - // apparently this thingy does the collision checks - _MoveContainer->evalCollision(_DiffTimeSeconds, 0); - - // check all wrong stuff (use some different way maybe) - for (CClientMap::iterator it = _Clients.begin(); it != _Clients.end(); it++) - for (CEntityMap::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) - { - CEntity &entity = it2->second; - - if (entity.Moving) - { - UGlobalPosition globalPosition; - entity.MovePrimitive->getGlobalPosition(globalPosition, 0); - CVector serverPosition = _GlobalRetriever->getGlobalPosition(globalPosition); - //nlinfo("clientPosition: %f %f %f", entity.NewClientPosition.x, entity.NewClientPosition.y, entity.NewClientPosition.z); - //nlinfo("serverPosition: %f %f %f", serverPosition.x, serverPosition.y, serverPosition.z); - - // Allow the difference between the external client position and the - // local server position to be up to half of the traveled distance - // plus the entity's height or radius, twice (using Retry). - float allowedDifference = entity.Distance * 0.5f; - bool move = false; - if (abs(entity.NewClientPosition.z - serverPosition.z) > 1.0f + allowedDifference) - { - move = true; - } - else - { - // fake server position has same z as client position if ok - serverPosition.z = entity.NewClientPosition.z; - if ((serverPosition - entity.NewClientPosition).norm() > entity.MovePrimitive->getRadius() + allowedDifference) - move = true; - } - - if (move) // Entity moved incorrectly. - { - if (entity.Retry) // If second try. - { - nldebug("entity.Retry"); - msgPosition(it2->first, serverPosition); - } - else nldebug("!entity.Retry"); - entity.Retry = !entity.Retry; // Else the entity gets one more chance. - } - - // The difference to the new position must be from local server position. - entity.OldClientPosition = serverPosition; - } - } - - msgUpdate(); - return true; -} - -void CCollisionService::release() -{ - -} - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// OTHER FUNCTIONS /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -void CCollisionService::sendMessage(CMessage &msgout) -{ - CUnifiedNetwork *instance = CUnifiedNetwork::getInstance(); - for (CClientMap::iterator it = _Clients.begin(); it != _Clients.end(); it++) - CUnifiedNetwork::getInstance()->send(TServiceId(it->first), msgout); -} - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// MESSAGE SENDERS /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -/**************************************************************************** - * Function: msgUpdate - * Send CLS_UPDATE message to registered services - * - * Arguments: - ****************************************************************************/ -void CCollisionService::msgUpdate() -{ - if (!_Clients.size()) return; - - static CMessage msgout("CLS_UPDATE"); - sendMessage(msgout); - //nldebug("Sent CLS_UPDATE to %u services", _Clients.size()); -} - -/**************************************************************************** - * Function: msgPosition - * Send CLS_POSITION message to registered services - * - * Arguments: - * - id: entity id - * - position: new position - ****************************************************************************/ -void CCollisionService::msgPosition(uint32 id, CVector position) -{ - if (!_Clients.size()) return; - - CMessage msgout("CLS_POSITION"); - msgout.serial(id, position); - sendMessage(msgout); - nldebug("Sent CLS_POSITION %u %f %f %f to %u services", id, position.x, position.y, position.z, _Clients.size()); -} - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// MESSAGE CALLBACKS /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -/**************************************************************************** - * Function: cbAdd - * Receives an "ADD" message. - ****************************************************************************/ -void CCollisionService::cbAdd(CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - // Read incoming message - uint32 id; - CVector position; - float radius; - msgin.serial(id, position, radius); - nldebug("Received ADD %u %f %f %f %f", id, position.x, position.y, position.z, radius); - - // Do something with it - CEntity &entity = _Clients[sid.get()][id] = CEntity(); - entity.OldClientPosition = position; - entity.NewClientPosition = position; - entity.MovePrimitive = _MoveContainer->addCollisionablePrimitive(0, 1); - entity.MovePrimitive->setPrimitiveType(UMovePrimitive::_2DOrientedCylinder); - entity.MovePrimitive->setReactionType(UMovePrimitive::Slide); - entity.MovePrimitive->setTriggerType(UMovePrimitive::NotATrigger); - entity.MovePrimitive->setCollisionMask(3); - entity.MovePrimitive->setOcclusionMask(2); - entity.MovePrimitive->setObstacle(true); - entity.MovePrimitive->setRadius(radius); - entity.MovePrimitive->setHeight(1.8f); - entity.MovePrimitive->insertInWorldImage(0); - entity.MovePrimitive->setGlobalPosition(position, 0); -} - -/**************************************************************************** - * Function: cbMove - * Receives a "MOVE" message. - ****************************************************************************/ -void CCollisionService::cbMove(CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - // Read incoming message - uint32 id; - CVector position; - msgin.serial(id, position); - // nldebug("Received MOVE %u %f %f %f", id, position.x, position.y, position.z); - - // Do something with it - CEntity &entity = _Clients[sid.get()][id]; - entity.NewClientPosition = position; - if (entity.OldClientPosition != position) - entity.Moving = true; -} - -/**************************************************************************** - * Function: cbRemove - * Receives a "REMOVE" message. - ****************************************************************************/ -void CCollisionService::cbRemove(CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - // Read incoming message - uint32 id; - msgin.serial(id); - nldebug("Received REMOVE %u", id); - - // Do something with it - if (_Clients[sid.get()].find(id) == _Clients[sid.get()].end()) - { - nlwarning("Unknown entity %u", id); - return; - } - CEntity &entity = _Clients[sid.get()][id]; - _MoveContainer->removePrimitive(entity.MovePrimitive); - _Clients[sid.get()].erase(id); -} - -/**************************************************************************** - * Function: cbRegister - * Receives a "REGISTER" message. - ****************************************************************************/ -void CCollisionService::cbRegister(CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - // Read incoming message - nldebug("Received REGISTER %s %s", serviceName.c_str(), sid.toString().c_str()); - - // Do something with it - _Clients[sid.get()] = CEntityMap(); -} - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// NETWORK CALLBACKS /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -/**************************************************************************** - * Function: cbDown - * Called when a registered service goes down - ****************************************************************************/ -void CCollisionService::cbDown(const string &serviceName, TServiceId sid, void *arg) -{ - CClientMap::iterator it = _Clients.find(sid.get()); - if (it != _Clients.end()) - { - // remove all entities - for (CEntityMap::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) - _MoveContainer->removePrimitive(it2->second.MovePrimitive); - // erase the client - _Clients.erase(it); - } -} - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// SERVICE CONFIGURATION /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -/**************************************************************************** - * CallbackArray - * - * It define the functions to call when receiving a specific message - ****************************************************************************/ -TUnifiedCallbackItem CallbackArray[] = -{ - { "REGISTER", CCollisionService::cbRegister }, - { "ADD", CCollisionService::cbAdd }, - { "MOVE", CCollisionService::cbMove }, - { "REMOVE", CCollisionService::cbRemove }, -}; - -/**************************************************************************** - * SNOWBALLS COLLISION SERVICE MAIN Function - * - * This call create a main function for the world_service: - * - * - based on the service class CCollisionService inherited from IService - * - having the short name "CLS" - * - having the long name "collision_service" - * - listening on an automatically allocated port (0) by the naming service - * - and callback actions set to "CallbackArray" - * - ****************************************************************************/ -NLNET_SERVICE_MAIN(CCollisionService, "CLS", "collision_service", 0, CallbackArray, "", "") - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "collision_service.h" +#include + +#ifdef NL_OS_WINDOWS +#include +#endif + +using namespace SBSERVICE; +using namespace NLMISC; +using namespace NLNET; +using namespace NLPACS; +using namespace std; + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// VARIABLES /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +CCollisionService::CClientMap CCollisionService::_Clients; +NLPACS::URetrieverBank *CCollisionService::_RetrieverBank; +NLPACS::UGlobalRetriever *CCollisionService::_GlobalRetriever; +NLPACS::UMoveContainer *CCollisionService::_MoveContainer; +CCollisionService::CMovePrimitiveVector CCollisionService::_StaticMovePrimitives; +TTime CCollisionService::_LastTime, CCollisionService::_NewTime, CCollisionService::_DiffTime; +double CCollisionService::_DiffTimeSeconds; +float CCollisionService::_DiffTimeFloat; + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// BASIC FUNCTIONS /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +void CCollisionService::commandStart() +{ + +} + +void CCollisionService::init() +{ + // set down callback + CUnifiedNetwork::getInstance()->setServiceDownCallback("*", cbDown); + + // set the data path + CPath::addSearchPath(ConfigFile.getVar("DataPath").asString(), true, false); + + // init the global retriever, the retriever bank, and the move container + _RetrieverBank = URetrieverBank::createRetrieverBank(ConfigFile.getVar("RetrieverBankName").asString().c_str()); + _GlobalRetriever = UGlobalRetriever::createGlobalRetriever(ConfigFile.getVar("GlobalRetrieverName").asString().c_str(), _RetrieverBank); + _MoveContainer = UMoveContainer::createMoveContainer(_GlobalRetriever, 100, 100, 6.0); + + // some silly snowballs specific code to load static instance groups, redo + CConfigFile::CVar igv = ConfigFile.getVar("InstanceGroups"); + for (uint i = 0; i < igv.size(); ++i) + { + NL3D::UInstanceGroup *ig = NL3D::UInstanceGroup::createInstanceGroup(igv.asString(i)); + if (ig == NULL) nlwarning("Instance group '%s' not found", igv.asString(i).c_str()); + else + { + for (uint i = 0; i < ig->getNumInstance(); ++i) + { + UMovePrimitive *primitive = _MoveContainer->addCollisionablePrimitive(0, 1); + primitive->setPrimitiveType(UMovePrimitive::_2DOrientedCylinder); + primitive->setReactionType(UMovePrimitive::DoNothing); + primitive->setTriggerType(UMovePrimitive::NotATrigger); + primitive->setCollisionMask(2); + primitive->setOcclusionMask(1); + primitive->setObstacle(true); + + string name = ig->getShapeName(i); + float rad; + if (strlwr(name) == "pi_po_igloo_a") rad = 4.5f; + else if (strlwr(name) == "pi_po_snowman_a") rad = 1.0f; + else if (strlwr(name) == "pi_po_pinetree_a") rad = 2.0f; + else if (strlwr(name) == "pi_po_tree_a") rad = 2.0f; + else if (strlwr(name) == "pi_po_pingoo_stat_a") rad = 1.0f; + else if (strlwr(name) == "pi_po_gnu_stat_a") rad = 1.0f; + else + { + rad = 2.0f; + nlwarning ("Instance name '%s' doesn't have a good radius for collision", name.c_str()); + } + + primitive->setRadius(rad); + primitive->setHeight(6.0f); + + primitive->insertInWorldImage(0); + CVector pos = ig->getInstancePos(i); + primitive->setGlobalPosition(CVectorD(pos.x, pos.y, pos.z - 1.5f), 0); + _StaticMovePrimitives.push_back(primitive); + } + } + delete ig; + } + + _NewTime = CTime::getLocalTime(); +} + +bool CCollisionService::update() +{ + _LastTime = _NewTime; + _NewTime = CTime::getLocalTime(); + _DiffTime = _NewTime - _LastTime; + _DiffTimeSeconds = (double)_DiffTime / 1000.0; + _DiffTimeFloat = (float)_DiffTimeSeconds; + + for (CClientMap::iterator it = _Clients.begin(); it != _Clients.end(); it++) + for (CEntityMap::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) + { + CEntity &entity = it2->second; + + if (entity.Moving) + { + // nldebug("entity.Moving"); + CVector movement = entity.NewClientPosition - entity.OldClientPosition; + entity.Distance = movement.norm(); + if (entity.Distance == 0.0f) + { + entity.Moving = false; + entity.Retry = false; + } + CVectorD speed = CVectorD(movement) / _DiffTimeSeconds; + entity.MovePrimitive->move(speed, 0); + } + // else nldebug("!entity.Moving"); + } + + // apparently this thingy does the collision checks + _MoveContainer->evalCollision(_DiffTimeSeconds, 0); + + // check all wrong stuff (use some different way maybe) + for (CClientMap::iterator it = _Clients.begin(); it != _Clients.end(); it++) + for (CEntityMap::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) + { + CEntity &entity = it2->second; + + if (entity.Moving) + { + UGlobalPosition globalPosition; + entity.MovePrimitive->getGlobalPosition(globalPosition, 0); + CVector serverPosition = _GlobalRetriever->getGlobalPosition(globalPosition); + //nlinfo("clientPosition: %f %f %f", entity.NewClientPosition.x, entity.NewClientPosition.y, entity.NewClientPosition.z); + //nlinfo("serverPosition: %f %f %f", serverPosition.x, serverPosition.y, serverPosition.z); + + // Allow the difference between the external client position and the + // local server position to be up to half of the traveled distance + // plus the entity's height or radius, twice (using Retry). + float allowedDifference = entity.Distance * 0.5f; + bool move = false; + if (abs(entity.NewClientPosition.z - serverPosition.z) > 1.0f + allowedDifference) + { + move = true; + } + else + { + // fake server position has same z as client position if ok + serverPosition.z = entity.NewClientPosition.z; + if ((serverPosition - entity.NewClientPosition).norm() > entity.MovePrimitive->getRadius() + allowedDifference) + move = true; + } + + if (move) // Entity moved incorrectly. + { + if (entity.Retry) // If second try. + { + nldebug("entity.Retry"); + msgPosition(it2->first, serverPosition); + } + else nldebug("!entity.Retry"); + entity.Retry = !entity.Retry; // Else the entity gets one more chance. + } + + // The difference to the new position must be from local server position. + entity.OldClientPosition = serverPosition; + } + } + + msgUpdate(); + return true; +} + +void CCollisionService::release() +{ + +} + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// OTHER FUNCTIONS /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +void CCollisionService::sendMessage(CMessage &msgout) +{ + CUnifiedNetwork *instance = CUnifiedNetwork::getInstance(); + for (CClientMap::iterator it = _Clients.begin(); it != _Clients.end(); it++) + CUnifiedNetwork::getInstance()->send(TServiceId(it->first), msgout); +} + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// MESSAGE SENDERS /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +/**************************************************************************** + * Function: msgUpdate + * Send CLS_UPDATE message to registered services + * + * Arguments: + ****************************************************************************/ +void CCollisionService::msgUpdate() +{ + if (!_Clients.size()) return; + + static CMessage msgout("CLS_UPDATE"); + sendMessage(msgout); + //nldebug("Sent CLS_UPDATE to %u services", _Clients.size()); +} + +/**************************************************************************** + * Function: msgPosition + * Send CLS_POSITION message to registered services + * + * Arguments: + * - id: entity id + * - position: new position + ****************************************************************************/ +void CCollisionService::msgPosition(uint32 id, CVector position) +{ + if (!_Clients.size()) return; + + CMessage msgout("CLS_POSITION"); + msgout.serial(id, position); + sendMessage(msgout); + nldebug("Sent CLS_POSITION %u %f %f %f to %u services", id, position.x, position.y, position.z, _Clients.size()); +} + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// MESSAGE CALLBACKS /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +/**************************************************************************** + * Function: cbAdd + * Receives an "ADD" message. + ****************************************************************************/ +void CCollisionService::cbAdd(CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + // Read incoming message + uint32 id; + CVector position; + float radius; + msgin.serial(id, position, radius); + nldebug("Received ADD %u %f %f %f %f", id, position.x, position.y, position.z, radius); + + // Do something with it + CEntity &entity = _Clients[sid.get()][id] = CEntity(); + entity.OldClientPosition = position; + entity.NewClientPosition = position; + entity.MovePrimitive = _MoveContainer->addCollisionablePrimitive(0, 1); + entity.MovePrimitive->setPrimitiveType(UMovePrimitive::_2DOrientedCylinder); + entity.MovePrimitive->setReactionType(UMovePrimitive::Slide); + entity.MovePrimitive->setTriggerType(UMovePrimitive::NotATrigger); + entity.MovePrimitive->setCollisionMask(3); + entity.MovePrimitive->setOcclusionMask(2); + entity.MovePrimitive->setObstacle(true); + entity.MovePrimitive->setRadius(radius); + entity.MovePrimitive->setHeight(1.8f); + entity.MovePrimitive->insertInWorldImage(0); + entity.MovePrimitive->setGlobalPosition(position, 0); +} + +/**************************************************************************** + * Function: cbMove + * Receives a "MOVE" message. + ****************************************************************************/ +void CCollisionService::cbMove(CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + // Read incoming message + uint32 id; + CVector position; + msgin.serial(id, position); + // nldebug("Received MOVE %u %f %f %f", id, position.x, position.y, position.z); + + // Do something with it + CEntity &entity = _Clients[sid.get()][id]; + entity.NewClientPosition = position; + if (entity.OldClientPosition != position) + entity.Moving = true; +} + +/**************************************************************************** + * Function: cbRemove + * Receives a "REMOVE" message. + ****************************************************************************/ +void CCollisionService::cbRemove(CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + // Read incoming message + uint32 id; + msgin.serial(id); + nldebug("Received REMOVE %u", id); + + // Do something with it + if (_Clients[sid.get()].find(id) == _Clients[sid.get()].end()) + { + nlwarning("Unknown entity %u", id); + return; + } + CEntity &entity = _Clients[sid.get()][id]; + _MoveContainer->removePrimitive(entity.MovePrimitive); + _Clients[sid.get()].erase(id); +} + +/**************************************************************************** + * Function: cbRegister + * Receives a "REGISTER" message. + ****************************************************************************/ +void CCollisionService::cbRegister(CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + // Read incoming message + nldebug("Received REGISTER %s %s", serviceName.c_str(), sid.toString().c_str()); + + // Do something with it + _Clients[sid.get()] = CEntityMap(); +} + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// NETWORK CALLBACKS /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +/**************************************************************************** + * Function: cbDown + * Called when a registered service goes down + ****************************************************************************/ +void CCollisionService::cbDown(const string &serviceName, TServiceId sid, void *arg) +{ + CClientMap::iterator it = _Clients.find(sid.get()); + if (it != _Clients.end()) + { + // remove all entities + for (CEntityMap::iterator it2 = it->second.begin(); it2 != it->second.end(); it2++) + _MoveContainer->removePrimitive(it2->second.MovePrimitive); + // erase the client + _Clients.erase(it); + } +} + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// SERVICE CONFIGURATION /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +/**************************************************************************** + * CallbackArray + * + * It define the functions to call when receiving a specific message + ****************************************************************************/ +TUnifiedCallbackItem CallbackArray[] = +{ + { "REGISTER", CCollisionService::cbRegister }, + { "ADD", CCollisionService::cbAdd }, + { "MOVE", CCollisionService::cbMove }, + { "REMOVE", CCollisionService::cbRemove }, +}; + +/**************************************************************************** + * SNOWBALLS COLLISION SERVICE MAIN Function + * + * This call create a main function for the world_service: + * + * - based on the service class CCollisionService inherited from IService + * - having the short name "CLS" + * - having the long name "collision_service" + * - listening on an automatically allocated port (0) by the naming service + * - and callback actions set to "CallbackArray" + * + ****************************************************************************/ +NLNET_SERVICE_MAIN(CCollisionService, "CLS", "collision_service", 0, CallbackArray, "", "") + +/* end of file */ diff --git a/code/snowballs2/server/collision/src/collision_service.h b/code/snowballs2/server/collision/src/collision_service.h index 2be3a1154..ac46479ba 100644 --- a/code/snowballs2/server/collision/src/collision_service.h +++ b/code/snowballs2/server/collision/src/collision_service.h @@ -1,96 +1,96 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - - -#ifndef SERVICE_EMPTY_SERVICE_H -#define SERVICE_EMPTY_SERVICE_H - -// This include is mandatory to use NeL. It include NeL types. -#include - -// Some other NeL structures that can be used. -#include -#include -#include - -// The stuff from PACS -#include -#include -#include -#include - -// And we're also using the NeL Service framework, layer 5. -#include - -namespace SBSERVICE { - -class CCollisionService : public NLNET::IService -{ -protected: - struct CEntity - { - CEntity() : OldClientPosition(), NewClientPosition(), MovePrimitive(NULL), Distance(0.0f), Moving(false), Retry(false) { } - NLMISC::CVector OldClientPosition; - NLMISC::CVector NewClientPosition; - NLPACS::UMovePrimitive *MovePrimitive; // ServerPosition - float Distance; - bool Moving; - bool Retry; - }; - typedef std::map CEntityMap; - typedef std::map CClientMap; - typedef std::vector CMovePrimitiveVector; - -private: - // The list of registered services, their entities, and their move primitive - static CClientMap _Clients; - // The retriever bank used in the world - static NLPACS::URetrieverBank *_RetrieverBank; - // The global retriever used for pacs - static NLPACS::UGlobalRetriever *_GlobalRetriever; - // The move container used for dynamic collisions - static NLPACS::UMoveContainer *_MoveContainer; - // The collision primitive for the static entities - static CMovePrimitiveVector _StaticMovePrimitives; - // Time - static NLMISC::TTime _LastTime, _NewTime, _DiffTime; - static double _DiffTimeSeconds; - static float _DiffTimeFloat; - -public: - virtual void commandStart(); - virtual void init(); - virtual bool update(); - virtual void release(); - - static void sendMessage(NLNET::CMessage &msgout); - - static void msgUpdate(); - static void msgPosition(uint32 id, NLMISC::CVector position); - - static void cbAdd(NLNET::CMessage &msgin, const std::string &serviceName, NLNET::TServiceId sid); - static void cbMove(NLNET::CMessage &msgin, const std::string &serviceName, NLNET::TServiceId sid); - static void cbRemove(NLNET::CMessage &msgin, const std::string &serviceName, NLNET::TServiceId sid); - static void cbRegister(NLNET::CMessage &msgin, const std::string &serviceName, NLNET::TServiceId sid); - - static void cbDown(const std::string &serviceName, NLNET::TServiceId sid, void *arg); -}; - -} - -#endif /* SERVICE_EMPTY_SERVICE_H */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef SERVICE_EMPTY_SERVICE_H +#define SERVICE_EMPTY_SERVICE_H + +// This include is mandatory to use NeL. It include NeL types. +#include + +// Some other NeL structures that can be used. +#include +#include +#include + +// The stuff from PACS +#include +#include +#include +#include + +// And we're also using the NeL Service framework, layer 5. +#include + +namespace SBSERVICE { + +class CCollisionService : public NLNET::IService +{ +protected: + struct CEntity + { + CEntity() : OldClientPosition(), NewClientPosition(), MovePrimitive(NULL), Distance(0.0f), Moving(false), Retry(false) { } + NLMISC::CVector OldClientPosition; + NLMISC::CVector NewClientPosition; + NLPACS::UMovePrimitive *MovePrimitive; // ServerPosition + float Distance; + bool Moving; + bool Retry; + }; + typedef std::map CEntityMap; + typedef std::map CClientMap; + typedef std::vector CMovePrimitiveVector; + +private: + // The list of registered services, their entities, and their move primitive + static CClientMap _Clients; + // The retriever bank used in the world + static NLPACS::URetrieverBank *_RetrieverBank; + // The global retriever used for pacs + static NLPACS::UGlobalRetriever *_GlobalRetriever; + // The move container used for dynamic collisions + static NLPACS::UMoveContainer *_MoveContainer; + // The collision primitive for the static entities + static CMovePrimitiveVector _StaticMovePrimitives; + // Time + static NLMISC::TTime _LastTime, _NewTime, _DiffTime; + static double _DiffTimeSeconds; + static float _DiffTimeFloat; + +public: + virtual void commandStart(); + virtual void init(); + virtual bool update(); + virtual void release(); + + static void sendMessage(NLNET::CMessage &msgout); + + static void msgUpdate(); + static void msgPosition(uint32 id, NLMISC::CVector position); + + static void cbAdd(NLNET::CMessage &msgin, const std::string &serviceName, NLNET::TServiceId sid); + static void cbMove(NLNET::CMessage &msgin, const std::string &serviceName, NLNET::TServiceId sid); + static void cbRemove(NLNET::CMessage &msgin, const std::string &serviceName, NLNET::TServiceId sid); + static void cbRegister(NLNET::CMessage &msgin, const std::string &serviceName, NLNET::TServiceId sid); + + static void cbDown(const std::string &serviceName, NLNET::TServiceId sid, void *arg); +}; + +} + +#endif /* SERVICE_EMPTY_SERVICE_H */ + +/* end of file */ diff --git a/code/snowballs2/server/empty/src/empty_service.cpp b/code/snowballs2/server/empty/src/empty_service.cpp index 3be5d0447..cda18fbdb 100644 --- a/code/snowballs2/server/empty/src/empty_service.cpp +++ b/code/snowballs2/server/empty/src/empty_service.cpp @@ -1,209 +1,209 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include "empty_service.h" - -using namespace SBSERVICE; -using namespace NLMISC; -using namespace NLNET; -using namespace std; - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// VARIABLES /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -// ... - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// BASIC FUNCTIONS /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -void CEmptyService::commandStart() -{ - -} - -void CEmptyService::init() -{ - CUnifiedNetwork::getInstance()->setServiceUpCallback("*", cbUp); -} - -bool CEmptyService::update() -{ - msgWater("FS", 0.1f); - return true; -} - -void CEmptyService::release() -{ - -} - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// OTHER FUNCTIONS /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -// ... - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// MESSAGE SENDERS /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -/**************************************************************************** - * Function: msgWater - * Send WATER message to target service - * - * Arguments: - * - service: target service name - * - water: floating point number - ****************************************************************************/ -void CEmptyService::msgWater(const std::string service, float water) -{ - CMessage msgout("WATER"); - msgout.serial(water); - CUnifiedNetwork::getInstance()->send(service, msgout); - nldebug("Sent WATER %f", water); -} - -/**************************************************************************** - * Function: msgFire - * Send FIRE message to target service - * - * Arguments: - * - sid: target service id - * - fire: unicode string - ****************************************************************************/ -void CEmptyService::msgFire(TServiceId sid, ucstring fire) -{ - CMessage msgout("FIRE"); - msgout.serial(fire); - CUnifiedNetwork::getInstance()->send(sid, msgout); - nldebug("Sent FIRE %s", fire.toString().c_str()); -} - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// MESSAGE CALLBACKS /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -/**************************************************************************** - * Function: cbSnow - * Receives a "SNOW" message with a uint32, increases it by one, - * and forwards it to all frontend services. - ****************************************************************************/ -void CEmptyService::cbSnow(CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - // Read incoming message - uint32 snow; - msgin.serial(snow); - nldebug("Received SNOW %u", snow); - - // Do something with it - ++snow; - - // Send a message to all frontends. - CMessage msgout("SNOW"); - msgout.serial(snow); - CUnifiedNetwork::getInstance()->send("FS", msgout); - nldebug("Sent SNOW %u", snow); -} - -/**************************************************************************** - * Function: cbIce - * Receives an "ICE" message with a ucstring, duplicates it, - * and replies the result to the sender. - ****************************************************************************/ -void CEmptyService::cbIce(CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - // Read incoming message - ucstring ice; - msgin.serial(ice); - nldebug("Received ICE %s", ice.toString().c_str()); - - // Do something with it - ice += ice; - - // Send a message to all frontends. - CMessage msgout("ICE"); - msgout.serial(ice); - CUnifiedNetwork::getInstance()->send(sid, msgout); - nldebug("Sent ICE %s", ice.toString().c_str()); -} - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// NETWORK CALLBACKS /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -/**************************************************************************** - * Function: cbUp - * Called when any service comes up - ****************************************************************************/ -void CEmptyService::cbUp(const string &serviceName, TServiceId sid, void *arg) -{ - // Send a message in reply - msgFire(sid, ucstring("BURN")); -} - - -////////////////////////////////////////////////////////////////////////////// -/// /// -/// SERVICE CONFIGURATION /// -/// /// -////////////////////////////////////////////////////////////////////////////// - -/**************************************************************************** - * CallbackArray - * - * It define the initial functions to call when receiving a specific message - ****************************************************************************/ -TUnifiedCallbackItem CallbackArray[] = -{ - { "SNOW", CEmptyService::cbSnow }, - { "ICE", CEmptyService::cbIce } -}; - -/**************************************************************************** - * SNOWBALLS SERVICE MAIN Function - * - * This call create a main function for the world_service: - * - * - based on the service class CEmptyService inherited from IService - * - having the short name "EMPTY" - * - having the long name "empty_service" - * - listening on an automatically allocated port (0) by the naming service - * - and callback actions set to "CallbackArray" - * - ****************************************************************************/ -NLNET_SERVICE_MAIN(CEmptyService, "EMPTY", "empty_service", 0, CallbackArray, "", "") - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include "empty_service.h" + +using namespace SBSERVICE; +using namespace NLMISC; +using namespace NLNET; +using namespace std; + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// VARIABLES /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +// ... + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// BASIC FUNCTIONS /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +void CEmptyService::commandStart() +{ + +} + +void CEmptyService::init() +{ + CUnifiedNetwork::getInstance()->setServiceUpCallback("*", cbUp); +} + +bool CEmptyService::update() +{ + msgWater("FS", 0.1f); + return true; +} + +void CEmptyService::release() +{ + +} + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// OTHER FUNCTIONS /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +// ... + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// MESSAGE SENDERS /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +/**************************************************************************** + * Function: msgWater + * Send WATER message to target service + * + * Arguments: + * - service: target service name + * - water: floating point number + ****************************************************************************/ +void CEmptyService::msgWater(const std::string service, float water) +{ + CMessage msgout("WATER"); + msgout.serial(water); + CUnifiedNetwork::getInstance()->send(service, msgout); + nldebug("Sent WATER %f", water); +} + +/**************************************************************************** + * Function: msgFire + * Send FIRE message to target service + * + * Arguments: + * - sid: target service id + * - fire: unicode string + ****************************************************************************/ +void CEmptyService::msgFire(TServiceId sid, ucstring fire) +{ + CMessage msgout("FIRE"); + msgout.serial(fire); + CUnifiedNetwork::getInstance()->send(sid, msgout); + nldebug("Sent FIRE %s", fire.toString().c_str()); +} + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// MESSAGE CALLBACKS /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +/**************************************************************************** + * Function: cbSnow + * Receives a "SNOW" message with a uint32, increases it by one, + * and forwards it to all frontend services. + ****************************************************************************/ +void CEmptyService::cbSnow(CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + // Read incoming message + uint32 snow; + msgin.serial(snow); + nldebug("Received SNOW %u", snow); + + // Do something with it + ++snow; + + // Send a message to all frontends. + CMessage msgout("SNOW"); + msgout.serial(snow); + CUnifiedNetwork::getInstance()->send("FS", msgout); + nldebug("Sent SNOW %u", snow); +} + +/**************************************************************************** + * Function: cbIce + * Receives an "ICE" message with a ucstring, duplicates it, + * and replies the result to the sender. + ****************************************************************************/ +void CEmptyService::cbIce(CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + // Read incoming message + ucstring ice; + msgin.serial(ice); + nldebug("Received ICE %s", ice.toString().c_str()); + + // Do something with it + ice += ice; + + // Send a message to all frontends. + CMessage msgout("ICE"); + msgout.serial(ice); + CUnifiedNetwork::getInstance()->send(sid, msgout); + nldebug("Sent ICE %s", ice.toString().c_str()); +} + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// NETWORK CALLBACKS /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +/**************************************************************************** + * Function: cbUp + * Called when any service comes up + ****************************************************************************/ +void CEmptyService::cbUp(const string &serviceName, TServiceId sid, void *arg) +{ + // Send a message in reply + msgFire(sid, ucstring("BURN")); +} + + +////////////////////////////////////////////////////////////////////////////// +/// /// +/// SERVICE CONFIGURATION /// +/// /// +////////////////////////////////////////////////////////////////////////////// + +/**************************************************************************** + * CallbackArray + * + * It define the initial functions to call when receiving a specific message + ****************************************************************************/ +TUnifiedCallbackItem CallbackArray[] = +{ + { "SNOW", CEmptyService::cbSnow }, + { "ICE", CEmptyService::cbIce } +}; + +/**************************************************************************** + * SNOWBALLS SERVICE MAIN Function + * + * This call create a main function for the world_service: + * + * - based on the service class CEmptyService inherited from IService + * - having the short name "EMPTY" + * - having the long name "empty_service" + * - listening on an automatically allocated port (0) by the naming service + * - and callback actions set to "CallbackArray" + * + ****************************************************************************/ +NLNET_SERVICE_MAIN(CEmptyService, "EMPTY", "empty_service", 0, CallbackArray, "", "") + +/* end of file */ diff --git a/code/snowballs2/server/empty/src/empty_service.h b/code/snowballs2/server/empty/src/empty_service.h index dabd27d4b..01f2f746f 100644 --- a/code/snowballs2/server/empty/src/empty_service.h +++ b/code/snowballs2/server/empty/src/empty_service.h @@ -1,53 +1,53 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef SERVICE_EMPTY_SERVICE_H -#define SERVICE_EMPTY_SERVICE_H - -// This include is mandatory to use NeL. It include NeL types. -#include - -// Some other NeL structures that can be used. -#include -#include - -// And we're also using the NeL Service framework, layer 5. -#include - -namespace SBSERVICE { - -class CEmptyService : public NLNET::IService -{ -public: - virtual void commandStart(); - virtual void init(); - virtual bool update(); - virtual void release(); - - static void msgWater(const std::string service, float water); - static void msgFire(NLNET::TServiceId sid, ucstring fire); - - static void cbSnow(NLNET::CMessage &msgin, const std::string &serviceName, NLNET::TServiceId sid); - static void cbIce(NLNET::CMessage &msgin, const std::string &serviceName, NLNET::TServiceId sid); - - static void cbUp(const std::string &serviceName, NLNET::TServiceId sid, void *arg); -}; - -} - -#endif /* SERVICE_EMPTY_SERVICE_H */ - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SERVICE_EMPTY_SERVICE_H +#define SERVICE_EMPTY_SERVICE_H + +// This include is mandatory to use NeL. It include NeL types. +#include + +// Some other NeL structures that can be used. +#include +#include + +// And we're also using the NeL Service framework, layer 5. +#include + +namespace SBSERVICE { + +class CEmptyService : public NLNET::IService +{ +public: + virtual void commandStart(); + virtual void init(); + virtual bool update(); + virtual void release(); + + static void msgWater(const std::string service, float water); + static void msgFire(NLNET::TServiceId sid, ucstring fire); + + static void cbSnow(NLNET::CMessage &msgin, const std::string &serviceName, NLNET::TServiceId sid); + static void cbIce(NLNET::CMessage &msgin, const std::string &serviceName, NLNET::TServiceId sid); + + static void cbUp(const std::string &serviceName, NLNET::TServiceId sid, void *arg); +}; + +} + +#endif /* SERVICE_EMPTY_SERVICE_H */ + +/* end of file */ diff --git a/code/snowballs2/server/frontend/CMakeLists.txt b/code/snowballs2/server/frontend/CMakeLists.txt index 3382c430d..2de0f9e48 100644 --- a/code/snowballs2/server/frontend/CMakeLists.txt +++ b/code/snowballs2/server/frontend/CMakeLists.txt @@ -1,3 +1,3 @@ -ADD_SUBDIRECTORY(src) - -INSTALL(FILES frontend_service.cfg DESTINATION etc/snowballs COMPONENT services) +ADD_SUBDIRECTORY(src) + +INSTALL(FILES frontend_service.cfg DESTINATION etc/snowballs COMPONENT services) diff --git a/code/snowballs2/server/frontend/src/CMakeLists.txt b/code/snowballs2/server/frontend/src/CMakeLists.txt index d24c6743e..19d2c7165 100644 --- a/code/snowballs2/server/frontend/src/CMakeLists.txt +++ b/code/snowballs2/server/frontend/src/CMakeLists.txt @@ -1,17 +1,17 @@ -FILE(GLOB SRC *.cpp *.h) - -ADD_EXECUTABLE(snowballs_frontend_service WIN32 ${SRC}) - -INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) - -TARGET_LINK_LIBRARIES(snowballs_frontend_service - ${LIBXML2_LIBRARIES} - nelmisc - nelnet) - -NL_DEFAULT_PROPS(snowballs_frontend_service "Snowballs, Services: Frontend Service") -NL_ADD_RUNTIME_FLAGS(snowballs_frontend_service) - -ADD_DEFINITIONS(${LIBXML2_DEFINITIONS}) - -INSTALL(TARGETS snowballs_frontend_service RUNTIME DESTINATION sbin COMPONENT services) +FILE(GLOB SRC *.cpp *.h) + +ADD_EXECUTABLE(snowballs_frontend_service WIN32 ${SRC}) + +INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR}) + +TARGET_LINK_LIBRARIES(snowballs_frontend_service + ${LIBXML2_LIBRARIES} + nelmisc + nelnet) + +NL_DEFAULT_PROPS(snowballs_frontend_service "Snowballs, Services: Frontend Service") +NL_ADD_RUNTIME_FLAGS(snowballs_frontend_service) + +ADD_DEFINITIONS(${LIBXML2_DEFINITIONS}) + +INSTALL(TARGETS snowballs_frontend_service RUNTIME DESTINATION sbin COMPONENT services) diff --git a/code/snowballs2/server/frontend/src/main.cpp b/code/snowballs2/server/frontend/src/main.cpp index 74ccdc50f..7b3470cbe 100644 --- a/code/snowballs2/server/frontend/src/main.cpp +++ b/code/snowballs2/server/frontend/src/main.cpp @@ -1,709 +1,709 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif // HAVE_CONFIG_H - -#ifndef SNOWBALLS_CONFIG -#define SNOWBALLS_CONFIG "" -#endif // SNOWBALLS_CONFIG - -#ifndef SNOWBALLS_LOGS -#define SNOWBALLS_LOGS "" -#endif // SNOWBALLS_LOGS - -// This include is mandatory to use NeL. It include NeL types. -#include - -#include - -// We're using the NeL Service framework and layer 5 -#include -#include - -#include -#include - -#ifdef NL_OS_WINDOWS -#include -#endif - -using namespace NLMISC; -using namespace NLNET; -using namespace std; - -CCallbackServer *Clients = 0; - -//TSockId clientfrom; - -/* - * Keep a list of the players connected to that Frontend. Only map Id - * to a Connection - */ - -struct CPlayer -{ - enum PlayerState - { - IDENTIFYING, - ONLINE - }; - CPlayer(uint32 Id, TSockId Con) : id(Id), con(Con), State(IDENTIFYING) { } - uint32 id; - TSockId con; - PlayerState State; -}; - -typedef map _pmap; - -_pmap localPlayers; - - -/**************************************************************************** - * cbChatClient - * - * Receive chat messages from a client and send it to the Chat Service. - ****************************************************************************/ -void cbChatClient ( CMessage& msgin, TSockId from, CCallbackNetBase& clientcb ) -{ - string message; - - // Input from the client is stored. - msgin.serial (message); - - // Prepare the message to send to the CHAT service - CMessage msgout ("CHAT"); - msgout.serial (message); - - /* - * The incomming message from the client is sent to the CHAT service - * under the "CHAT" identification. - */ - CUnifiedNetwork::getInstance ()->send( "CHAT", msgout ); - - nldebug("SB: Received CHAT message \"%s\" from client \"%s\"", message.c_str(), clientcb.hostAddress(from).asString().c_str()); -} - - -/**************************************************************************** - * cdChatService - * - * Receive chat messages from the Chat Service to send it to all the clients. - ****************************************************************************/ -void cbChatService (CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - string message; - - // Input: process the reply of the chat service - msgin.serial (message); - - // Output: send the reply to the client - CMessage msgout ("CHAT"); - msgout.serial (message); - - // Send the message to all connected clients - Clients->send (msgout, InvalidSockId); - - nldebug( "SB: Sent chat message \"%s\" to all clients", message.c_str()); -} - - -/**************************************************************************** - * cbPosClient - * - * Receive position messages from a client and send it to the Position Service. - ****************************************************************************/ -void cbPosClient ( CMessage& msgin, TSockId from, CCallbackNetBase& clientcb ) -{ - uint32 id; - CVector pos; - float angle; - uint32 state; - - // Input from the client is stored. - msgin.serial( id ); - msgin.serial( pos ); - msgin.serial( angle ); - msgin.serial( state ); - - // Prepare the message to send to the Position service - CMessage msgout ("ENTITY_POS"); - msgout.serial( id ); - msgout.serial( pos ); - msgout.serial( angle ); - msgout.serial( state ); - - /* - * The incomming message from the client is sent to the Position service - * under the "POS" identification. - */ - CUnifiedNetwork::getInstance ()->send( "POS", msgout ); - - //nldebug( "SB: Received ENTITY_POS from the client"); -} - - -/**************************************************************************** - * cbPosService - * - * Receive position messages from the Position Service to send it to all the - * clients. - ****************************************************************************/ -void cbPosService (CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - uint32 id; - CVector pos; - float angle; - uint32 state; - - // Input: process the reply of the position service - msgin.serial( id ); - msgin.serial( pos ); - msgin.serial( angle ); - msgin.serial( state ); - - // Output: send the reply to the client - CMessage msgout( "ENTITY_POS" ); - msgout.serial( id ); - msgout.serial( pos ); - msgout.serial( angle ); - msgout.serial( state ); - - // Send the message to all connected clients - Clients->send(msgout, InvalidSockId); - - //nldebug( "SB: Sent ENTITY_POS message to all the connected clients"); -} - -/**************************************************************************** - * cbTeleportService - * - * Test - ****************************************************************************/ -void cbTeleportService (CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - uint32 id; - CVector position; - msgin.serial(id); - msgin.serial(position); - CMessage msgout("ENTITY_TP"); - msgout.serial(id); - msgout.serial(position); - Clients->send(msgout, InvalidSockId); - nldebug("SB: Sent ENTITY_TP message to all the connected clients"); -} - - -/**************************************************************************** - * cbAddClient - * - * Receive an ADD_ENTITY message from a client and send it to the Position - * Service. - ****************************************************************************/ -void cbAddClient ( CMessage& msgin, TSockId from, CCallbackNetBase& clientcb ) -{ - uint32 id; - string name; - uint8 race; - CVector start(1840.0f + ((float)(rand() % 100) / 10.0f), -970.0f + ((float)(rand() % 100) / 10.0f), -23.0f); // kaetemi_todo: from config - - // Input from the client is stored. - msgin.serial(id); - msgin.serial(name); - msgin.serial(race); - - - if(from->appId() != 0) - { - CPlayer *p = (CPlayer *)(uint)from->appId(); - if(id == p->id) - p->State = CPlayer::ONLINE; - } - - // Prepare the message to send to the Position service - CMessage msgout("ADD_ENTITY"); - msgout.serial(id); - msgout.serial(name); - msgout.serial(race); - msgout.serial(start); - - /* - * The incoming message from the client is sent to the Position service - * under the "POS" identification. - */ - CUnifiedNetwork::getInstance()->send("POS", msgout); - - nldebug("SB: Received ADD_ENTITY from the client"); - - // kaetemi_todo: from config - msgout = CMessage("CHAT"); - std::string chat_msg(std::string(">>>> Welcome to Snowballs, ") + name + std::string("!")); - msgout.serial(chat_msg); - Clients->send(msgout, from); -} - - -/**************************************************************************** - * cdAddService - * - * Receive an ADD_ENTITY messages from the Position Service to send it to all - * the clients. - ****************************************************************************/ -void cbAddService (CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - bool all; - uint32 to; - uint32 id; - string name; - uint8 race; - CVector start; - - // Input: process the reply of the position service - msgin.serial( all ); - msgin.serial( to ); - msgin.serial( id ); - msgin.serial( name ); - msgin.serial( race ); - msgin.serial( start ); - - // Output: prepare the reply to the clients - CMessage msgout( "ADD_ENTITY" ); - msgout.serial( id ); - msgout.serial( name ); - msgout.serial( race ); - msgout.serial( start ); - - if ( all == true ) - { - // Send the message to all connected clients - Clients->send(msgout, InvalidSockId ); - - nldebug( "SB: Sent ADD_ENTITY message to all the connected clients"); - } - else - { - // Send the message about a former connected client to the new client - _pmap::iterator ItPlayer; - ItPlayer = localPlayers.find(to); - if ( ItPlayer == localPlayers.end() ) - { - nlwarning( "New player id %u not found !", to ); - } - else - { - TSockId conToClient = ((*ItPlayer).second).con; - Clients->send( msgout, conToClient ); - - nldebug( "SB: Sent ADD_ENTITY about all the connected clients to the new client."); - } - } - -} - - -/**************************************************************************** - * cbRemoveClient - * - * Receive an REMOVE_ENTITY message from a client and send it to the Position - * Service. - ****************************************************************************/ -void cbRemoveClient ( CMessage& msgin, TSockId from, CCallbackNetBase& clientcb ) -{ - uint32 id; - - // Input from the client is stored. - msgin.serial( id ); - - // Prepare the message to send to the Position service - CMessage msgout( "REMOVE_ENTITY" ); - msgout.serial( id ); - - /* - * The incomming message from the client is sent to the Position service - * under the "POS" identification. - */ - CUnifiedNetwork::getInstance ()->send( "POS", msgout ); - - nldebug( "SB: Received REMOVE_ENTITY from the client"); -} - - -/**************************************************************************** - * cdRemoveService - * - * Receive an REMOVE_ENTITY messages from the Position Service to send it to all - * the clients. - ****************************************************************************/ -void cbRemoveService (CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - uint32 id; - - // Input: process the reply of the position service - msgin.serial( id ); - - // Output: send the reply to the client - CMessage msgout( "REMOVE_ENTITY" ); - msgout.serial( id ); - - // Send the message to all connected clients - Clients->send( msgout, InvalidSockId ); - - nldebug( "SB: Sent REMOVE_ENTITY message to all the connected clients"); -} - - -/**************************************************************************** - * cdSnowballService - * - * Receive an SNOWBALL messages from the Position Service to send it to all - * the clients. - ****************************************************************************/ -void cbSnowballService (CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - uint32 id, - playerId; - CVector start, - target; - float speed, - explosionRadius; - - // Input: process the reply of the position service - msgin.serial( id ); - msgin.serial( playerId ); - msgin.serial( start ); - msgin.serial( target ); - msgin.serial( speed ); - msgin.serial( explosionRadius ); - - // Output: send the reply to the client - CMessage msgout( "SNOWBALL" ); - msgout.serial( id ); - msgout.serial( playerId ); - msgout.serial( start ); - msgout.serial( target ); - msgout.serial( speed ); - msgout.serial( explosionRadius ); - - // Send the message to all connected clients - Clients->send( msgout, InvalidSockId ); - - nldebug( "SB: Sent SNOWBALL message to all the connected clients"); -} - - -/**************************************************************************** - * cbSnowballClient - * - * Receive an SNOWBALL message from a client and send it to the Position - * Service. - ****************************************************************************/ -void cbSnowballClient ( CMessage& msgin, TSockId from, CCallbackNetBase& clientcb ) -{ - uint32 playerId; - CVector start, - target; - float speed, - explosionRadius; - - // Input from the client is stored. - msgin.serial( playerId ); - msgin.serial( start ); - msgin.serial( target ); - msgin.serial( speed ); - msgin.serial( explosionRadius ); - - // Prepare the message to send to the Position service - CMessage msgout( "SNOWBALL" ); - msgout.serial( playerId ); - msgout.serial( start ); - msgout.serial( target ); - msgout.serial( speed ); - msgout.serial( explosionRadius ); - - /* - * The incomming message from the client is sent to the Position service - * under the "POS" identification. - */ - CUnifiedNetwork::getInstance ()->send( "POS", msgout ); - - nldebug( "SB: Received SNOWBALL from the client"); -} - - -/**************************************************************************** - * cdHitService - * - * Receive an HIT messages from the Position Service to send it to all - * the clients. - ****************************************************************************/ -void cbHitService (CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - uint32 snowballId, - victimId; - bool direct; - - // Input: process the reply of the position service - msgin.serial( snowballId ); - msgin.serial( victimId ); - msgin.serial( direct ); - - // Output: send the reply to the client - CMessage msgout( "HIT" ); - msgout.serial( snowballId ); - msgout.serial( victimId ); - msgout.serial( direct ); - - // Send the message to all connected clients - Clients->send( msgout, InvalidSockId); - - nldebug( "SB: Sent HIT message to all the connected clients"); -} - - -/** - * Contains all callbacks from client - */ -TCallbackItem ClientCallbackArray[] = -{ - { "ADD_ENTITY", cbAddClient }, - { "ENTITY_POS", cbPosClient }, - { "CHAT", cbChatClient }, - { "REMOVE_ENTITY", cbRemoveClient }, - { "SNOWBALL", cbSnowballClient }, -}; - - -/** - * Contains *all* callbacks from the shard - */ -TUnifiedCallbackItem CallbackArray[] = -{ - { "CHAT", cbChatService }, - { "ADD_ENTITY", cbAddService }, - { "ENTITY_POS", cbPosService }, - { "ENTITY_TP", cbTeleportService }, - { "REMOVE_ENTITY", cbRemoveService }, - { "SNOWBALL", cbSnowballService }, - { "HIT", cbHitService }, -}; - - -/**************************************************************************** - * Connection callback for the Chat service - ****************************************************************************/ -void onReconnectChat (const std::string &serviceName, TServiceId sid, void *arg) -{ - nldebug( "SB: Chat Service reconnected" ); -} - - -/**************************************************************************** - * Disconnection callback for the Chat service - ****************************************************************************/ -void onDisconnectChat (const std::string &serviceName, TServiceId sid, void *arg) -{ - /* Note: messages already forwarded should get no reply, but it may occure - * (e.g. if the server reconnects before the forwarding of a message and - * the reconnection callbacks is called after that). Then onReconnectChat() - * may send messagess that have already been sent and the front-end may get - * the same message twice. This is partially handled in cbChatService. - */ - - nldebug( "SB: Chat Service disconnecting: messages will be delayed until reconnection" ); -} - - -/**************************************************************************** - * Connection callback for the Position service - ****************************************************************************/ -void onReconnectPosition (const std::string &serviceName, TServiceId sid, void *arg) -{ - nldebug( "SB: Position Service reconnected" ); -} - - -/**************************************************************************** - * Disconnection callback for the Position service - ****************************************************************************/ -void onDisconnectPosition (const std::string &serviceName, TServiceId sid, void *arg) -{ - /* Note: messages already forwarded should get no reply, but it may occure - * (e.g. if the server reconnects before the forwarding of a message and - * the reconnection callbacks is called after that). Then onReconnectChat() - * may send messagess that have already been sent and the front-end may get - * the same message twice. This is partially handled in cbPositionService. - */ - - nldebug( "SB: Position Service disconnecting: messages will be delayed until reconnection" ); -} - - -/**************************************************************************** - * Connection callback for a client - ****************************************************************************/ -void onConnectionClient (TSockId from, const CLoginCookie &cookie) -{ - uint32 id; - - id = cookie.getUserId(); - - nlinfo( "The client with unique Id %u is connected", id ); - - // Add new client to the list of player managed by this FrontEnd - pair<_pmap::iterator, bool> player = localPlayers.insert( make_pair( id, CPlayer( id, from ))); - - // store the player info in appId - - _pmap::iterator it = player.first; - CPlayer *p = &((*it).second); - from->setAppId((uint64)(uintptr_t)p); - - // Output: send the IDENTIFICATION number to the new connected client - CMessage msgout( "IDENTIFICATION" ); - msgout.serial( id ); - - // Send the message to connected client "from" - Clients->send( msgout, from ); - - nldebug( "SB: Sent IDENTIFICATION message to the new client"); -} - - -/**************************************************************************** - * Disconnection callback for a client - ****************************************************************************/ -void onDisconnectClient ( TSockId from, void *arg ) -{ - uint32 id; - - uint64 i = from->appId(); - - if(i == 0) - return; - - CPlayer *p = (CPlayer *)(uint)i; - id = p->id; - - nlinfo( "A client with unique Id %u has disconnected", id ); - - // tell the login system that this client is disconnected - CLoginServer::clientDisconnected ( id ); - - // remove the player from the local player list - localPlayers.erase( id ); - - // don't send remove messages for entities that haven't been created. - if(p->State == CPlayer::ONLINE) - { - // Output: send the REMOVE_ENTITY to the position manager. - CMessage msgout( "REMOVE_ENTITY" ); - msgout.serial( id ); - - // Send the message to the position manager - CUnifiedNetwork::getInstance ()->send( "POS", msgout); - nldebug( "SB: Sent REMOVE_ENTITY message to the position manager."); - } - -} - - -/**************************************************************************** - * CFrontEndService - ****************************************************************************/ -class CFrontEndService : public IService -{ -public: - - // Initialisation - void init() - { - - // Create the server where the client must connect into - // In a real game, it should be an UDP server with specific protocol to manage packet lost and so on. - - Clients = new CCallbackServer (); - nlassert (Clients != 0); - - // Set the callbacks for that connection (comming from the Chat service) - Clients->addCallbackArray (ClientCallbackArray, sizeof(ClientCallbackArray)/sizeof(ClientCallbackArray[0])); - - // Set the callbacks for the client disconnection of the Frontend - Clients->setDisconnectionCallback (onDisconnectClient, 0); - - Clients->init (37000); - - // Connect the frontend to the login system - CLoginServer::init( *Clients, onConnectionClient); - - /* - * Set the callback function when the Chat service reconnect to the - * frontend - */ - CUnifiedNetwork::getInstance ()->setServiceUpCallback ("CHAT", onReconnectChat, 0); - - /* - * Set the callback function when the Chat service disconnect from - * frontend - */ - CUnifiedNetwork::getInstance ()->setServiceDownCallback ("CHAT", onDisconnectChat, 0); - - /* - * Set the callback function when the Position service reconnect to the - * frontend - */ - CUnifiedNetwork::getInstance ()->setServiceUpCallback ("POS", onReconnectPosition, 0); - - /* - * Set the callback function when the Position service disconnect from - * frontend - */ - CUnifiedNetwork::getInstance ()->setServiceDownCallback ("POS", onDisconnectPosition, 0); - } - - bool update() - { - // Manage messages from clients - Clients->update (); - - // we want to continue - return true; - } - - void release() - { - delete Clients; - Clients = NULL; - } -}; - - -/**************************************************************************** - * SNOWBALLS FRONTEND SERVICE MAIN Function - * - * This call create a main function for a service: - * - * - based on the "CFrontEndService" class - * - having the short name "FS" - * - having the long name "frontend_service" - * - listening on the port "0" (dynamically determined) - * - and shard callback set to "CallbackArray" - * - ****************************************************************************/ -NLNET_SERVICE_MAIN (CFrontEndService, "FS", "frontend_service", 0, CallbackArray, SNOWBALLS_CONFIG, SNOWBALLS_LOGS) - - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif // HAVE_CONFIG_H + +#ifndef SNOWBALLS_CONFIG +#define SNOWBALLS_CONFIG "" +#endif // SNOWBALLS_CONFIG + +#ifndef SNOWBALLS_LOGS +#define SNOWBALLS_LOGS "" +#endif // SNOWBALLS_LOGS + +// This include is mandatory to use NeL. It include NeL types. +#include + +#include + +// We're using the NeL Service framework and layer 5 +#include +#include + +#include +#include + +#ifdef NL_OS_WINDOWS +#include +#endif + +using namespace NLMISC; +using namespace NLNET; +using namespace std; + +CCallbackServer *Clients = 0; + +//TSockId clientfrom; + +/* + * Keep a list of the players connected to that Frontend. Only map Id + * to a Connection + */ + +struct CPlayer +{ + enum PlayerState + { + IDENTIFYING, + ONLINE + }; + CPlayer(uint32 Id, TSockId Con) : id(Id), con(Con), State(IDENTIFYING) { } + uint32 id; + TSockId con; + PlayerState State; +}; + +typedef map _pmap; + +_pmap localPlayers; + + +/**************************************************************************** + * cbChatClient + * + * Receive chat messages from a client and send it to the Chat Service. + ****************************************************************************/ +void cbChatClient ( CMessage& msgin, TSockId from, CCallbackNetBase& clientcb ) +{ + string message; + + // Input from the client is stored. + msgin.serial (message); + + // Prepare the message to send to the CHAT service + CMessage msgout ("CHAT"); + msgout.serial (message); + + /* + * The incomming message from the client is sent to the CHAT service + * under the "CHAT" identification. + */ + CUnifiedNetwork::getInstance ()->send( "CHAT", msgout ); + + nldebug("SB: Received CHAT message \"%s\" from client \"%s\"", message.c_str(), clientcb.hostAddress(from).asString().c_str()); +} + + +/**************************************************************************** + * cdChatService + * + * Receive chat messages from the Chat Service to send it to all the clients. + ****************************************************************************/ +void cbChatService (CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + string message; + + // Input: process the reply of the chat service + msgin.serial (message); + + // Output: send the reply to the client + CMessage msgout ("CHAT"); + msgout.serial (message); + + // Send the message to all connected clients + Clients->send (msgout, InvalidSockId); + + nldebug( "SB: Sent chat message \"%s\" to all clients", message.c_str()); +} + + +/**************************************************************************** + * cbPosClient + * + * Receive position messages from a client and send it to the Position Service. + ****************************************************************************/ +void cbPosClient ( CMessage& msgin, TSockId from, CCallbackNetBase& clientcb ) +{ + uint32 id; + CVector pos; + float angle; + uint32 state; + + // Input from the client is stored. + msgin.serial( id ); + msgin.serial( pos ); + msgin.serial( angle ); + msgin.serial( state ); + + // Prepare the message to send to the Position service + CMessage msgout ("ENTITY_POS"); + msgout.serial( id ); + msgout.serial( pos ); + msgout.serial( angle ); + msgout.serial( state ); + + /* + * The incomming message from the client is sent to the Position service + * under the "POS" identification. + */ + CUnifiedNetwork::getInstance ()->send( "POS", msgout ); + + //nldebug( "SB: Received ENTITY_POS from the client"); +} + + +/**************************************************************************** + * cbPosService + * + * Receive position messages from the Position Service to send it to all the + * clients. + ****************************************************************************/ +void cbPosService (CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + uint32 id; + CVector pos; + float angle; + uint32 state; + + // Input: process the reply of the position service + msgin.serial( id ); + msgin.serial( pos ); + msgin.serial( angle ); + msgin.serial( state ); + + // Output: send the reply to the client + CMessage msgout( "ENTITY_POS" ); + msgout.serial( id ); + msgout.serial( pos ); + msgout.serial( angle ); + msgout.serial( state ); + + // Send the message to all connected clients + Clients->send(msgout, InvalidSockId); + + //nldebug( "SB: Sent ENTITY_POS message to all the connected clients"); +} + +/**************************************************************************** + * cbTeleportService + * + * Test + ****************************************************************************/ +void cbTeleportService (CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + uint32 id; + CVector position; + msgin.serial(id); + msgin.serial(position); + CMessage msgout("ENTITY_TP"); + msgout.serial(id); + msgout.serial(position); + Clients->send(msgout, InvalidSockId); + nldebug("SB: Sent ENTITY_TP message to all the connected clients"); +} + + +/**************************************************************************** + * cbAddClient + * + * Receive an ADD_ENTITY message from a client and send it to the Position + * Service. + ****************************************************************************/ +void cbAddClient ( CMessage& msgin, TSockId from, CCallbackNetBase& clientcb ) +{ + uint32 id; + string name; + uint8 race; + CVector start(1840.0f + ((float)(rand() % 100) / 10.0f), -970.0f + ((float)(rand() % 100) / 10.0f), -23.0f); // kaetemi_todo: from config + + // Input from the client is stored. + msgin.serial(id); + msgin.serial(name); + msgin.serial(race); + + + if(from->appId() != 0) + { + CPlayer *p = (CPlayer *)(uint)from->appId(); + if(id == p->id) + p->State = CPlayer::ONLINE; + } + + // Prepare the message to send to the Position service + CMessage msgout("ADD_ENTITY"); + msgout.serial(id); + msgout.serial(name); + msgout.serial(race); + msgout.serial(start); + + /* + * The incoming message from the client is sent to the Position service + * under the "POS" identification. + */ + CUnifiedNetwork::getInstance()->send("POS", msgout); + + nldebug("SB: Received ADD_ENTITY from the client"); + + // kaetemi_todo: from config + msgout = CMessage("CHAT"); + std::string chat_msg(std::string(">>>> Welcome to Snowballs, ") + name + std::string("!")); + msgout.serial(chat_msg); + Clients->send(msgout, from); +} + + +/**************************************************************************** + * cdAddService + * + * Receive an ADD_ENTITY messages from the Position Service to send it to all + * the clients. + ****************************************************************************/ +void cbAddService (CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + bool all; + uint32 to; + uint32 id; + string name; + uint8 race; + CVector start; + + // Input: process the reply of the position service + msgin.serial( all ); + msgin.serial( to ); + msgin.serial( id ); + msgin.serial( name ); + msgin.serial( race ); + msgin.serial( start ); + + // Output: prepare the reply to the clients + CMessage msgout( "ADD_ENTITY" ); + msgout.serial( id ); + msgout.serial( name ); + msgout.serial( race ); + msgout.serial( start ); + + if ( all == true ) + { + // Send the message to all connected clients + Clients->send(msgout, InvalidSockId ); + + nldebug( "SB: Sent ADD_ENTITY message to all the connected clients"); + } + else + { + // Send the message about a former connected client to the new client + _pmap::iterator ItPlayer; + ItPlayer = localPlayers.find(to); + if ( ItPlayer == localPlayers.end() ) + { + nlwarning( "New player id %u not found !", to ); + } + else + { + TSockId conToClient = ((*ItPlayer).second).con; + Clients->send( msgout, conToClient ); + + nldebug( "SB: Sent ADD_ENTITY about all the connected clients to the new client."); + } + } + +} + + +/**************************************************************************** + * cbRemoveClient + * + * Receive an REMOVE_ENTITY message from a client and send it to the Position + * Service. + ****************************************************************************/ +void cbRemoveClient ( CMessage& msgin, TSockId from, CCallbackNetBase& clientcb ) +{ + uint32 id; + + // Input from the client is stored. + msgin.serial( id ); + + // Prepare the message to send to the Position service + CMessage msgout( "REMOVE_ENTITY" ); + msgout.serial( id ); + + /* + * The incomming message from the client is sent to the Position service + * under the "POS" identification. + */ + CUnifiedNetwork::getInstance ()->send( "POS", msgout ); + + nldebug( "SB: Received REMOVE_ENTITY from the client"); +} + + +/**************************************************************************** + * cdRemoveService + * + * Receive an REMOVE_ENTITY messages from the Position Service to send it to all + * the clients. + ****************************************************************************/ +void cbRemoveService (CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + uint32 id; + + // Input: process the reply of the position service + msgin.serial( id ); + + // Output: send the reply to the client + CMessage msgout( "REMOVE_ENTITY" ); + msgout.serial( id ); + + // Send the message to all connected clients + Clients->send( msgout, InvalidSockId ); + + nldebug( "SB: Sent REMOVE_ENTITY message to all the connected clients"); +} + + +/**************************************************************************** + * cdSnowballService + * + * Receive an SNOWBALL messages from the Position Service to send it to all + * the clients. + ****************************************************************************/ +void cbSnowballService (CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + uint32 id, + playerId; + CVector start, + target; + float speed, + explosionRadius; + + // Input: process the reply of the position service + msgin.serial( id ); + msgin.serial( playerId ); + msgin.serial( start ); + msgin.serial( target ); + msgin.serial( speed ); + msgin.serial( explosionRadius ); + + // Output: send the reply to the client + CMessage msgout( "SNOWBALL" ); + msgout.serial( id ); + msgout.serial( playerId ); + msgout.serial( start ); + msgout.serial( target ); + msgout.serial( speed ); + msgout.serial( explosionRadius ); + + // Send the message to all connected clients + Clients->send( msgout, InvalidSockId ); + + nldebug( "SB: Sent SNOWBALL message to all the connected clients"); +} + + +/**************************************************************************** + * cbSnowballClient + * + * Receive an SNOWBALL message from a client and send it to the Position + * Service. + ****************************************************************************/ +void cbSnowballClient ( CMessage& msgin, TSockId from, CCallbackNetBase& clientcb ) +{ + uint32 playerId; + CVector start, + target; + float speed, + explosionRadius; + + // Input from the client is stored. + msgin.serial( playerId ); + msgin.serial( start ); + msgin.serial( target ); + msgin.serial( speed ); + msgin.serial( explosionRadius ); + + // Prepare the message to send to the Position service + CMessage msgout( "SNOWBALL" ); + msgout.serial( playerId ); + msgout.serial( start ); + msgout.serial( target ); + msgout.serial( speed ); + msgout.serial( explosionRadius ); + + /* + * The incomming message from the client is sent to the Position service + * under the "POS" identification. + */ + CUnifiedNetwork::getInstance ()->send( "POS", msgout ); + + nldebug( "SB: Received SNOWBALL from the client"); +} + + +/**************************************************************************** + * cdHitService + * + * Receive an HIT messages from the Position Service to send it to all + * the clients. + ****************************************************************************/ +void cbHitService (CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + uint32 snowballId, + victimId; + bool direct; + + // Input: process the reply of the position service + msgin.serial( snowballId ); + msgin.serial( victimId ); + msgin.serial( direct ); + + // Output: send the reply to the client + CMessage msgout( "HIT" ); + msgout.serial( snowballId ); + msgout.serial( victimId ); + msgout.serial( direct ); + + // Send the message to all connected clients + Clients->send( msgout, InvalidSockId); + + nldebug( "SB: Sent HIT message to all the connected clients"); +} + + +/** + * Contains all callbacks from client + */ +TCallbackItem ClientCallbackArray[] = +{ + { "ADD_ENTITY", cbAddClient }, + { "ENTITY_POS", cbPosClient }, + { "CHAT", cbChatClient }, + { "REMOVE_ENTITY", cbRemoveClient }, + { "SNOWBALL", cbSnowballClient }, +}; + + +/** + * Contains *all* callbacks from the shard + */ +TUnifiedCallbackItem CallbackArray[] = +{ + { "CHAT", cbChatService }, + { "ADD_ENTITY", cbAddService }, + { "ENTITY_POS", cbPosService }, + { "ENTITY_TP", cbTeleportService }, + { "REMOVE_ENTITY", cbRemoveService }, + { "SNOWBALL", cbSnowballService }, + { "HIT", cbHitService }, +}; + + +/**************************************************************************** + * Connection callback for the Chat service + ****************************************************************************/ +void onReconnectChat (const std::string &serviceName, TServiceId sid, void *arg) +{ + nldebug( "SB: Chat Service reconnected" ); +} + + +/**************************************************************************** + * Disconnection callback for the Chat service + ****************************************************************************/ +void onDisconnectChat (const std::string &serviceName, TServiceId sid, void *arg) +{ + /* Note: messages already forwarded should get no reply, but it may occure + * (e.g. if the server reconnects before the forwarding of a message and + * the reconnection callbacks is called after that). Then onReconnectChat() + * may send messagess that have already been sent and the front-end may get + * the same message twice. This is partially handled in cbChatService. + */ + + nldebug( "SB: Chat Service disconnecting: messages will be delayed until reconnection" ); +} + + +/**************************************************************************** + * Connection callback for the Position service + ****************************************************************************/ +void onReconnectPosition (const std::string &serviceName, TServiceId sid, void *arg) +{ + nldebug( "SB: Position Service reconnected" ); +} + + +/**************************************************************************** + * Disconnection callback for the Position service + ****************************************************************************/ +void onDisconnectPosition (const std::string &serviceName, TServiceId sid, void *arg) +{ + /* Note: messages already forwarded should get no reply, but it may occure + * (e.g. if the server reconnects before the forwarding of a message and + * the reconnection callbacks is called after that). Then onReconnectChat() + * may send messagess that have already been sent and the front-end may get + * the same message twice. This is partially handled in cbPositionService. + */ + + nldebug( "SB: Position Service disconnecting: messages will be delayed until reconnection" ); +} + + +/**************************************************************************** + * Connection callback for a client + ****************************************************************************/ +void onConnectionClient (TSockId from, const CLoginCookie &cookie) +{ + uint32 id; + + id = cookie.getUserId(); + + nlinfo( "The client with unique Id %u is connected", id ); + + // Add new client to the list of player managed by this FrontEnd + pair<_pmap::iterator, bool> player = localPlayers.insert( make_pair( id, CPlayer( id, from ))); + + // store the player info in appId + + _pmap::iterator it = player.first; + CPlayer *p = &((*it).second); + from->setAppId((uint64)(uintptr_t)p); + + // Output: send the IDENTIFICATION number to the new connected client + CMessage msgout( "IDENTIFICATION" ); + msgout.serial( id ); + + // Send the message to connected client "from" + Clients->send( msgout, from ); + + nldebug( "SB: Sent IDENTIFICATION message to the new client"); +} + + +/**************************************************************************** + * Disconnection callback for a client + ****************************************************************************/ +void onDisconnectClient ( TSockId from, void *arg ) +{ + uint32 id; + + uint64 i = from->appId(); + + if(i == 0) + return; + + CPlayer *p = (CPlayer *)(uint)i; + id = p->id; + + nlinfo( "A client with unique Id %u has disconnected", id ); + + // tell the login system that this client is disconnected + CLoginServer::clientDisconnected ( id ); + + // remove the player from the local player list + localPlayers.erase( id ); + + // don't send remove messages for entities that haven't been created. + if(p->State == CPlayer::ONLINE) + { + // Output: send the REMOVE_ENTITY to the position manager. + CMessage msgout( "REMOVE_ENTITY" ); + msgout.serial( id ); + + // Send the message to the position manager + CUnifiedNetwork::getInstance ()->send( "POS", msgout); + nldebug( "SB: Sent REMOVE_ENTITY message to the position manager."); + } + +} + + +/**************************************************************************** + * CFrontEndService + ****************************************************************************/ +class CFrontEndService : public IService +{ +public: + + // Initialisation + void init() + { + + // Create the server where the client must connect into + // In a real game, it should be an UDP server with specific protocol to manage packet lost and so on. + + Clients = new CCallbackServer (); + nlassert (Clients != 0); + + // Set the callbacks for that connection (comming from the Chat service) + Clients->addCallbackArray (ClientCallbackArray, sizeof(ClientCallbackArray)/sizeof(ClientCallbackArray[0])); + + // Set the callbacks for the client disconnection of the Frontend + Clients->setDisconnectionCallback (onDisconnectClient, 0); + + Clients->init (37000); + + // Connect the frontend to the login system + CLoginServer::init( *Clients, onConnectionClient); + + /* + * Set the callback function when the Chat service reconnect to the + * frontend + */ + CUnifiedNetwork::getInstance ()->setServiceUpCallback ("CHAT", onReconnectChat, 0); + + /* + * Set the callback function when the Chat service disconnect from + * frontend + */ + CUnifiedNetwork::getInstance ()->setServiceDownCallback ("CHAT", onDisconnectChat, 0); + + /* + * Set the callback function when the Position service reconnect to the + * frontend + */ + CUnifiedNetwork::getInstance ()->setServiceUpCallback ("POS", onReconnectPosition, 0); + + /* + * Set the callback function when the Position service disconnect from + * frontend + */ + CUnifiedNetwork::getInstance ()->setServiceDownCallback ("POS", onDisconnectPosition, 0); + } + + bool update() + { + // Manage messages from clients + Clients->update (); + + // we want to continue + return true; + } + + void release() + { + delete Clients; + Clients = NULL; + } +}; + + +/**************************************************************************** + * SNOWBALLS FRONTEND SERVICE MAIN Function + * + * This call create a main function for a service: + * + * - based on the "CFrontEndService" class + * - having the short name "FS" + * - having the long name "frontend_service" + * - listening on the port "0" (dynamically determined) + * - and shard callback set to "CallbackArray" + * + ****************************************************************************/ +NLNET_SERVICE_MAIN (CFrontEndService, "FS", "frontend_service", 0, CallbackArray, SNOWBALLS_CONFIG, SNOWBALLS_LOGS) + + +/* end of file */ diff --git a/code/snowballs2/server/position/CMakeLists.txt b/code/snowballs2/server/position/CMakeLists.txt index d2f2fd740..8c9dbbdf2 100644 --- a/code/snowballs2/server/position/CMakeLists.txt +++ b/code/snowballs2/server/position/CMakeLists.txt @@ -1,3 +1,3 @@ -ADD_SUBDIRECTORY(src) - -INSTALL(FILES position_service.cfg DESTINATION etc/snowballs COMPONENT services) +ADD_SUBDIRECTORY(src) + +INSTALL(FILES position_service.cfg DESTINATION etc/snowballs COMPONENT services) diff --git a/code/snowballs2/server/position/src/CMakeLists.txt b/code/snowballs2/server/position/src/CMakeLists.txt index 52231fdf2..3c4b04529 100644 --- a/code/snowballs2/server/position/src/CMakeLists.txt +++ b/code/snowballs2/server/position/src/CMakeLists.txt @@ -1,12 +1,12 @@ -FILE(GLOB SRC *.cpp *.h) - -ADD_EXECUTABLE(snowballs_position_service WIN32 ${SRC}) - -TARGET_LINK_LIBRARIES(snowballs_position_service - nelmisc - nelnet) - -NL_DEFAULT_PROPS(snowballs_position_service "Snowballs, Services: Position Service") -NL_ADD_RUNTIME_FLAGS(snowballs_position_service) - -INSTALL(TARGETS snowballs_position_service RUNTIME DESTINATION sbin COMPONENT services) +FILE(GLOB SRC *.cpp *.h) + +ADD_EXECUTABLE(snowballs_position_service WIN32 ${SRC}) + +TARGET_LINK_LIBRARIES(snowballs_position_service + nelmisc + nelnet) + +NL_DEFAULT_PROPS(snowballs_position_service "Snowballs, Services: Position Service") +NL_ADD_RUNTIME_FLAGS(snowballs_position_service) + +INSTALL(TARGETS snowballs_position_service RUNTIME DESTINATION sbin COMPONENT services) diff --git a/code/snowballs2/server/position/src/main.cpp b/code/snowballs2/server/position/src/main.cpp index 44a94d560..98eca639b 100644 --- a/code/snowballs2/server/position/src/main.cpp +++ b/code/snowballs2/server/position/src/main.cpp @@ -1,615 +1,615 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif // HAVE_CONFIG_H - -#ifndef SNOWBALLS_CONFIG -#define SNOWBALLS_CONFIG "" -#endif // SNOWBALLS_CONFIG - -#ifndef SNOWBALLS_LOGS -#define SNOWBALLS_LOGS "" -#endif // SNOWBALLS_LOGS - -// This include is mandatory to use NeL. It include NeL types. -#include - -#include - -#include - -// We're using the NeL Service framework, and layer 5 -#include - -#include -#include - -#include "physics.h" - -#ifdef NL_OS_WINDOWS -#include -#endif - -using namespace NLMISC; -using namespace NLNET; -using namespace std; - - -#define PLAYER_RADIUS 1.0f -#define SNOWBALL_RADIUS 0.1f -#define START_SNOW_ID 2000000000 -#define THROW_ANIM_OFFSET 1000 - - - - -// Define information used for all connected players to the shard. -struct _player -{ - _player( uint32 Id, string Name, uint8 Race, CVector Position ) : - id( Id ), name( Name ), race( Race ), position( Position ) { } - uint32 id; - string name; - uint8 race; - CVector position; -}; - -// List of all the players connected to the shard. -typedef map _pmap; -_pmap playerList; - -// Define informations used for the snowballs management -struct _snowball -{ - _snowball( uint32 Id, uint32 Owner, CTrajectory Traj, float ExplosionRadius ) : - id( Id ), owner( Owner ), traj( Traj ), explosionRadius( ExplosionRadius ) { } - uint32 id; - uint32 owner; - CTrajectory traj; - float explosionRadius; -}; - -// List of all the games snowballs -list<_snowball> snoList; - - - - -class CCLSClient -{ -private: - struct _entity - { - _entity() { } - _entity(CVector position, float radius) - : Position(position), Radius(radius) { } - CVector Position; - float Radius; - }; - - static map adds; - static map positions; - static map moves; - static map radiuses; - static map removes; -public: - static void cbUpdate(CMessage &msgin, const std::string &serviceName, TServiceId sid) - { - // nldebug("Received CLS_UPDATE, %s %s", serviceName.c_str(), sid.toString().c_str()); - - for (map::iterator it = adds.begin(); it != adds.end(); it++) - { - CMessage msgout("ADD"); - msgout.serial((uint32 &)it->first); - msgout.serial(it->second.Position); - msgout.serial(it->second.Radius); - CUnifiedNetwork::getInstance()->send(sid, msgout); - } - adds.clear(); - - for (map::iterator it = positions.begin(); it != positions.end(); it++) - { - CMessage msgout("POSITION"); - msgout.serial((uint32 &)it->first); - msgout.serial((NLMISC::CVector &)it->second); - CUnifiedNetwork::getInstance()->send(sid, msgout); - } - positions.clear(); - - for (map::iterator it = moves.begin(); it != moves.end(); it++) - { - CMessage msgout("MOVE"); - msgout.serial((uint32 &)it->first); - msgout.serial((NLMISC::CVector &)it->second); - CUnifiedNetwork::getInstance()->send(sid, msgout); - } - moves.clear(); - - for (map::iterator it = radiuses.begin(); it != radiuses.end(); it++) - { - CMessage msgout("RADIUS"); - msgout.serial((uint32 &)it->first); - msgout.serial((float &)it->second); - CUnifiedNetwork::getInstance()->send(sid, msgout); - } - radiuses.clear(); - - for (map::iterator it = removes.begin(); it != removes.end(); it++) - { - CMessage msgout("REMOVE"); - msgout.serial((uint32 &)it->first); - CUnifiedNetwork::getInstance()->send(sid, msgout); - } - removes.clear(); - } - - static void cbPosition(CMessage &msgin, const std::string &serviceName, TServiceId sid) - { - - } - - static void addEntity(uint32 id, CVector position, float radius) - { - adds[id] = _entity(position, radius); - } - - static void removeEntity(uint32 id) - { - if (positions.find(id) != positions.end()) positions.erase(id); - if (moves.find(id) != moves.end()) moves.erase(id); - if (radiuses.find(id) != radiuses.end()) radiuses.erase(id); - if (adds.find(id) == adds.end()) removes[id] = 1; - else adds.erase(id); - } - - static void movePosition(uint32 id, CVector position) - { - moves[id] = position; - } - - static void setPosition(uint32 id, CVector position) - { - if (moves.find(id) != moves.end()) moves.erase(id); - if (adds.find(id) == adds.end()) positions[id] = position; - else adds[id].Position = position; - } - - static void setRadius(uint32 id, float radius) - { - if (adds.find(id) == adds.end()) radiuses[id] = radius; - else adds[id].Radius = radius; - } - - static void msgRegister(TServiceId sid) - { - CMessage msgout("REGISTER"); - CUnifiedNetwork::getInstance()->send(sid, msgout); - } - - static void clear() - { - adds.clear(); - positions.clear(); - moves.clear(); - radiuses.clear(); - removes.clear(); - } -}; -map CCLSClient::adds; -map CCLSClient::positions; -map CCLSClient::moves; -map CCLSClient::radiuses; -map CCLSClient::removes; - -class CCLSClientPOS : public CCLSClient -{ -public: - static void cbPosition(CMessage &msgin, const std::string &serviceName, TServiceId sid) - { - // temp - uint32 id; - CVector position; - msgin.serial(id); - msgin.serial(position); - nldebug("Received CLS_POSITION, %s %s", serviceName.c_str(), sid.toString().c_str()); - - // Update position information in the player list - _pmap::iterator ItPlayer; - ItPlayer = playerList.find( id ); - if ( ItPlayer == playerList.end() ) - { - nlwarning( "Player id %u not found !", id ); - } - else - { - ((*ItPlayer).second).position = position; - //nldebug( "SB: Player position updated" ); - } - - CMessage msgout("ENTITY_TP"); - msgout.serial(id); - msgout.serial(position); - CUnifiedNetwork::getInstance()->send("FS", msgout); - } - - /**************************************************************************** - * Connection callback for the collision service - ****************************************************************************/ - static void cbCollisionServiceUp(const std::string &serviceName, TServiceId sid, void *arg) - { - nldebug("SB: Collision Service UP, %s %s", serviceName.c_str(), sid.toString().c_str()); - clear(); - msgRegister(sid); - for (_pmap::iterator it = playerList.begin(); it != playerList.end(); it++) - addEntity(it->second.id, it->second.position, 1.0f); - } -}; - - - - - - - -/**************************************************************************** - * Function: cbAddEntity - * Callback function called when the Position Service receive a - * "ADD_ENTITY" message - ****************************************************************************/ -void cbAddEntity (CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - bool all; - uint32 id; - string name; - uint8 race; - CVector startPoint; - - // Extract the incomming message content from the Frontend and print it - msgin.serial( id ); - msgin.serial( name ); - msgin.serial( race ); - msgin.serial( startPoint ); - nldebug( "SB: Received ADD_ENTITY line." ); - - // Prepare to send back the message. - all = true; - CMessage msgout( "ADD_ENTITY" ); - msgout.serial( all ); - msgout.serial( id ); - msgout.serial( id ); - msgout.serial( name ); - msgout.serial( race ); - msgout.serial( startPoint ); - - /* - * Send the message to all the connected Frontend. If we decide to send - * it back to the sender, that last argument should be 'from' inteed of '0' - */ - CUnifiedNetwork::getInstance ()->send( "FS", msgout ); - - CCLSClientPOS::addEntity(id, startPoint, /* 10.0f, */ 1.0f); - - nldebug( "SB: Send back ADD_ENTITY line." ); - - // Send ADD_ENTITY message about all already connected client to the new one. - all = false; - _pmap::iterator ItPlayer; - for (ItPlayer = playerList.begin(); ItPlayer != playerList.end(); ++ItPlayer) - { - CMessage msgout( "ADD_ENTITY" ); - msgout.serial( all ); - msgout.serial( id ); - msgout.serial( ((*ItPlayer).second).id ); - msgout.serial( ((*ItPlayer).second).name ); - msgout.serial( ((*ItPlayer).second).race ); - msgout.serial( ((*ItPlayer).second).position ); - - CUnifiedNetwork::getInstance ()->send( sid, msgout); - } - - nldebug( "SB: Send ADD_ENTITY line about all already connected clients to the new one." ); - - // ADD the current added entity in the player list. - playerList.insert( make_pair( id, _player( id, name, race, startPoint ) )); -} - - -/**************************************************************************** - * Function: cbPosition - * Callback function called when the Position Service receive a - * "ENTITY_POS" message - ****************************************************************************/ -void cbPosition (CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - uint32 id; - CVector pos; - float angle; - uint32 state; - - // Extract the incomming message content from the Frontend and print it - msgin.serial( id ); - msgin.serial( pos ); - msgin.serial( angle ); - msgin.serial( state ); - //nldebug( "SB: Received ENTITY_POS line." ); - - // Update position information in the player list - _pmap::iterator ItPlayer; - ItPlayer = playerList.find( id ); - if ( ItPlayer == playerList.end() ) - { - nlwarning( "Player id %u not found !", id ); - } - else - { - ((*ItPlayer).second).position = pos; - //nldebug( "SB: Player position updated" ); - } - - // Prepare to send back the message. - CMessage msgout( "ENTITY_POS" ); - msgout.serial( id ); - msgout.serial( pos ); - msgout.serial( angle ); - msgout.serial( state ); - - /* - * Send the message to all the connected Frontend. - */ - CUnifiedNetwork::getInstance ()->send( "FS", msgout ); - - CCLSClientPOS::movePosition(id, pos); - - //nldebug( "SB: Send back ENTITY_POS line." ); -} - - -/**************************************************************************** - * Function: cbRemoveEntity - * Callback function called when the Position Service receive a - * "REMOVE_ENTITY" message - ****************************************************************************/ -void cbRemoveEntity (CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - uint32 id; - - // Extract the incomming message content from the Frontend and print it - msgin.serial( id ); - nldebug( "SB: Received REMOVE_ENTITY line." ); - - // Prepare to send back the message. - CMessage msgout( "REMOVE_ENTITY" ); - msgout.serial( id ); - - /* - * Send the message to all the connected Frontend. - */ - CUnifiedNetwork::getInstance ()->send( "FS", msgout ); - - // Remove player form the player list. - playerList.erase( id ); - - CCLSClientPOS::removeEntity(id); - - nldebug( "SB: Send back REMOVE_ENTITY line. %d players left ...", - playerList.size() ); -} - - -/**************************************************************************** - * Function: cbSnowball - * Callback function called when the Position Service receive a - * "SNOWBALL" message - ****************************************************************************/ -void cbSnowball (CMessage &msgin, const std::string &serviceName, TServiceId sid) -{ - static uint32 snowballId = START_SNOW_ID; - - uint32 playerId; - CVector start, - target; - float speed, - explosionRadius; - - // Extract the incomming message content from the Frontend and print it - msgin.serial( playerId ); - msgin.serial( start ); - msgin.serial( target ); - msgin.serial( speed ); - msgin.serial( explosionRadius ); - nldebug( "SB: Received SNOWBALL line." ); - - // Store new snowballs informations - CTrajectory traj; - traj.init( start, target, speed, CTime::getLocalTime() + THROW_ANIM_OFFSET ); - _snowball snowball = _snowball( snowballId, playerId, traj, explosionRadius ); - snoList.push_front( snowball ); - - // Prepare to send back the message. - CMessage msgout( "SNOWBALL" ); - msgout.serial( snowballId ); - msgout.serial( playerId ); - msgout.serial( start ); - msgout.serial( target ); - msgout.serial( speed ); - msgout.serial( explosionRadius ); - - snowballId++; - - /* - * Send the message to all the connected Frontend. - */ - CUnifiedNetwork::getInstance ()->send( "FS", msgout ); - - nldebug( "SB: Send back SNOWBALL line." ); -} - - -/**************************************************************************** - * CallbackArray - * - * It define the functions to call when receiving a specific message - ****************************************************************************/ -TUnifiedCallbackItem CallbackArray[] = -{ - { "ADD_ENTITY", cbAddEntity }, - { "ENTITY_POS", cbPosition }, - { "REMOVE_ENTITY", cbRemoveEntity }, - { "SNOWBALL", cbSnowball }, - { "CLS_UPDATE", CCLSClientPOS::cbUpdate }, - { "CLS_POSITION", CCLSClientPOS::cbPosition } -}; - - -/**************************************************************************** - * Function: SendHITMsg - * Send HIT message to all clients - * - * Arguments: - * - snowball: snowball id - * - victim: player touched by the snowball - * - direct: define if the hit is direct or by the explosion - * area - ****************************************************************************/ -void SendHITMsg ( uint32 snowball, uint32 victim, bool direct ) -{ - CMessage msgout( "HIT" ); - - msgout.serial( snowball ); - msgout.serial( victim ); - msgout.serial( direct ); - - CUnifiedNetwork::getInstance ()->send( "FS", msgout ); -} - -/**************************************************************************** - * CPositionService - ****************************************************************************/ -class CPositionService : public IService -{ -public: - - void init() - { - CUnifiedNetwork::getInstance()->setServiceUpCallback("CLS", CCLSClientPOS::cbCollisionServiceUp, 0); - } - - // Update fonction, called at every frames - bool update() - { - //_snowball snowball; - CVector snoPos; - float distance; - bool removeSnowball; - - // Get the Current time - TTime currentTime = CTime::getLocalTime(); - list<_snowball>::iterator ItSnowball; - - // Check collision of snowballs with players - ItSnowball = snoList.begin(); - while ( ItSnowball != snoList.end() ) - { - removeSnowball = false; - - list<_snowball>::iterator ItSb = ItSnowball++; - _snowball snowball = (*ItSb); - - // Test collision (direct and explosion with players) - _pmap::iterator ItPlayer; - for (ItPlayer = playerList.begin(); ItPlayer != playerList.end(); ++ItPlayer) - { - _player player = (*ItPlayer).second; - - /* - * Snowballs can't touch the guy which throw it, Like that - * players could not kill them self (intentionally or not :-) - */ - if ( player.id == snowball.owner ) - { - continue; - } - - // Get the current snowball position - snoPos = snowball.traj.eval( currentTime ); - - // Test direct collision with players - distance = (player.position - snoPos).norm(); - if ( distance < ( PLAYER_RADIUS + SNOWBALL_RADIUS ) ) - { - nldebug( "SB: HIT on player %u by player %u.", - player.id, snowball.owner ); - - // Send HIT message - SendHITMsg( snowball.id, player.id, true ); - - // Flag the snowball to be removed from the list - removeSnowball = true; - } - - // Snowballs touch his stop Position - if ( snowball.traj.getStopTime() < currentTime ) - { - // Test for explosion victims - distance = (player.position - snoPos).norm(); - if ( distance < ( PLAYER_RADIUS + snowball.explosionRadius ) ) - { - nldebug( "SB: Explosion hit on player %u by player %u.", - player.id, snowball.owner ); - - // Send HIT message - SendHITMsg( snowball.id, player.id, false ); - } - - // Flag the snowball to be removed from the list - removeSnowball = true; - } - } - - - // Removed if flaged snowball - if ( removeSnowball ) - { - snoList.erase( ItSb ); - nldebug( "SB: Removed outdated SNOWBALL id %u.", snowball.id ); - } - - } - - return true; - } - -}; - - -/**************************************************************************** - * SNOWBALLS POSITION SERVICE MAIN Function - * - * This call create a main function for the POSITION service: - * - * - based on the base service class "IService", no need to inherit from it - * - having the short name "POSITION" - * - having the long name "position_service" - * - listening on an automatically allocated port (0) by the naming service - * - and callback actions set to "CallbackArray" - * - ****************************************************************************/ -NLNET_SERVICE_MAIN( CPositionService, "POS", "position_service", 0, CallbackArray, SNOWBALLS_CONFIG, SNOWBALLS_LOGS ) - - -/* end of file */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif // HAVE_CONFIG_H + +#ifndef SNOWBALLS_CONFIG +#define SNOWBALLS_CONFIG "" +#endif // SNOWBALLS_CONFIG + +#ifndef SNOWBALLS_LOGS +#define SNOWBALLS_LOGS "" +#endif // SNOWBALLS_LOGS + +// This include is mandatory to use NeL. It include NeL types. +#include + +#include + +#include + +// We're using the NeL Service framework, and layer 5 +#include + +#include +#include + +#include "physics.h" + +#ifdef NL_OS_WINDOWS +#include +#endif + +using namespace NLMISC; +using namespace NLNET; +using namespace std; + + +#define PLAYER_RADIUS 1.0f +#define SNOWBALL_RADIUS 0.1f +#define START_SNOW_ID 2000000000 +#define THROW_ANIM_OFFSET 1000 + + + + +// Define information used for all connected players to the shard. +struct _player +{ + _player( uint32 Id, string Name, uint8 Race, CVector Position ) : + id( Id ), name( Name ), race( Race ), position( Position ) { } + uint32 id; + string name; + uint8 race; + CVector position; +}; + +// List of all the players connected to the shard. +typedef map _pmap; +_pmap playerList; + +// Define informations used for the snowballs management +struct _snowball +{ + _snowball( uint32 Id, uint32 Owner, CTrajectory Traj, float ExplosionRadius ) : + id( Id ), owner( Owner ), traj( Traj ), explosionRadius( ExplosionRadius ) { } + uint32 id; + uint32 owner; + CTrajectory traj; + float explosionRadius; +}; + +// List of all the games snowballs +list<_snowball> snoList; + + + + +class CCLSClient +{ +private: + struct _entity + { + _entity() { } + _entity(CVector position, float radius) + : Position(position), Radius(radius) { } + CVector Position; + float Radius; + }; + + static map adds; + static map positions; + static map moves; + static map radiuses; + static map removes; +public: + static void cbUpdate(CMessage &msgin, const std::string &serviceName, TServiceId sid) + { + // nldebug("Received CLS_UPDATE, %s %s", serviceName.c_str(), sid.toString().c_str()); + + for (map::iterator it = adds.begin(); it != adds.end(); it++) + { + CMessage msgout("ADD"); + msgout.serial((uint32 &)it->first); + msgout.serial(it->second.Position); + msgout.serial(it->second.Radius); + CUnifiedNetwork::getInstance()->send(sid, msgout); + } + adds.clear(); + + for (map::iterator it = positions.begin(); it != positions.end(); it++) + { + CMessage msgout("POSITION"); + msgout.serial((uint32 &)it->first); + msgout.serial((NLMISC::CVector &)it->second); + CUnifiedNetwork::getInstance()->send(sid, msgout); + } + positions.clear(); + + for (map::iterator it = moves.begin(); it != moves.end(); it++) + { + CMessage msgout("MOVE"); + msgout.serial((uint32 &)it->first); + msgout.serial((NLMISC::CVector &)it->second); + CUnifiedNetwork::getInstance()->send(sid, msgout); + } + moves.clear(); + + for (map::iterator it = radiuses.begin(); it != radiuses.end(); it++) + { + CMessage msgout("RADIUS"); + msgout.serial((uint32 &)it->first); + msgout.serial((float &)it->second); + CUnifiedNetwork::getInstance()->send(sid, msgout); + } + radiuses.clear(); + + for (map::iterator it = removes.begin(); it != removes.end(); it++) + { + CMessage msgout("REMOVE"); + msgout.serial((uint32 &)it->first); + CUnifiedNetwork::getInstance()->send(sid, msgout); + } + removes.clear(); + } + + static void cbPosition(CMessage &msgin, const std::string &serviceName, TServiceId sid) + { + + } + + static void addEntity(uint32 id, CVector position, float radius) + { + adds[id] = _entity(position, radius); + } + + static void removeEntity(uint32 id) + { + if (positions.find(id) != positions.end()) positions.erase(id); + if (moves.find(id) != moves.end()) moves.erase(id); + if (radiuses.find(id) != radiuses.end()) radiuses.erase(id); + if (adds.find(id) == adds.end()) removes[id] = 1; + else adds.erase(id); + } + + static void movePosition(uint32 id, CVector position) + { + moves[id] = position; + } + + static void setPosition(uint32 id, CVector position) + { + if (moves.find(id) != moves.end()) moves.erase(id); + if (adds.find(id) == adds.end()) positions[id] = position; + else adds[id].Position = position; + } + + static void setRadius(uint32 id, float radius) + { + if (adds.find(id) == adds.end()) radiuses[id] = radius; + else adds[id].Radius = radius; + } + + static void msgRegister(TServiceId sid) + { + CMessage msgout("REGISTER"); + CUnifiedNetwork::getInstance()->send(sid, msgout); + } + + static void clear() + { + adds.clear(); + positions.clear(); + moves.clear(); + radiuses.clear(); + removes.clear(); + } +}; +map CCLSClient::adds; +map CCLSClient::positions; +map CCLSClient::moves; +map CCLSClient::radiuses; +map CCLSClient::removes; + +class CCLSClientPOS : public CCLSClient +{ +public: + static void cbPosition(CMessage &msgin, const std::string &serviceName, TServiceId sid) + { + // temp + uint32 id; + CVector position; + msgin.serial(id); + msgin.serial(position); + nldebug("Received CLS_POSITION, %s %s", serviceName.c_str(), sid.toString().c_str()); + + // Update position information in the player list + _pmap::iterator ItPlayer; + ItPlayer = playerList.find( id ); + if ( ItPlayer == playerList.end() ) + { + nlwarning( "Player id %u not found !", id ); + } + else + { + ((*ItPlayer).second).position = position; + //nldebug( "SB: Player position updated" ); + } + + CMessage msgout("ENTITY_TP"); + msgout.serial(id); + msgout.serial(position); + CUnifiedNetwork::getInstance()->send("FS", msgout); + } + + /**************************************************************************** + * Connection callback for the collision service + ****************************************************************************/ + static void cbCollisionServiceUp(const std::string &serviceName, TServiceId sid, void *arg) + { + nldebug("SB: Collision Service UP, %s %s", serviceName.c_str(), sid.toString().c_str()); + clear(); + msgRegister(sid); + for (_pmap::iterator it = playerList.begin(); it != playerList.end(); it++) + addEntity(it->second.id, it->second.position, 1.0f); + } +}; + + + + + + + +/**************************************************************************** + * Function: cbAddEntity + * Callback function called when the Position Service receive a + * "ADD_ENTITY" message + ****************************************************************************/ +void cbAddEntity (CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + bool all; + uint32 id; + string name; + uint8 race; + CVector startPoint; + + // Extract the incomming message content from the Frontend and print it + msgin.serial( id ); + msgin.serial( name ); + msgin.serial( race ); + msgin.serial( startPoint ); + nldebug( "SB: Received ADD_ENTITY line." ); + + // Prepare to send back the message. + all = true; + CMessage msgout( "ADD_ENTITY" ); + msgout.serial( all ); + msgout.serial( id ); + msgout.serial( id ); + msgout.serial( name ); + msgout.serial( race ); + msgout.serial( startPoint ); + + /* + * Send the message to all the connected Frontend. If we decide to send + * it back to the sender, that last argument should be 'from' inteed of '0' + */ + CUnifiedNetwork::getInstance ()->send( "FS", msgout ); + + CCLSClientPOS::addEntity(id, startPoint, /* 10.0f, */ 1.0f); + + nldebug( "SB: Send back ADD_ENTITY line." ); + + // Send ADD_ENTITY message about all already connected client to the new one. + all = false; + _pmap::iterator ItPlayer; + for (ItPlayer = playerList.begin(); ItPlayer != playerList.end(); ++ItPlayer) + { + CMessage msgout( "ADD_ENTITY" ); + msgout.serial( all ); + msgout.serial( id ); + msgout.serial( ((*ItPlayer).second).id ); + msgout.serial( ((*ItPlayer).second).name ); + msgout.serial( ((*ItPlayer).second).race ); + msgout.serial( ((*ItPlayer).second).position ); + + CUnifiedNetwork::getInstance ()->send( sid, msgout); + } + + nldebug( "SB: Send ADD_ENTITY line about all already connected clients to the new one." ); + + // ADD the current added entity in the player list. + playerList.insert( make_pair( id, _player( id, name, race, startPoint ) )); +} + + +/**************************************************************************** + * Function: cbPosition + * Callback function called when the Position Service receive a + * "ENTITY_POS" message + ****************************************************************************/ +void cbPosition (CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + uint32 id; + CVector pos; + float angle; + uint32 state; + + // Extract the incomming message content from the Frontend and print it + msgin.serial( id ); + msgin.serial( pos ); + msgin.serial( angle ); + msgin.serial( state ); + //nldebug( "SB: Received ENTITY_POS line." ); + + // Update position information in the player list + _pmap::iterator ItPlayer; + ItPlayer = playerList.find( id ); + if ( ItPlayer == playerList.end() ) + { + nlwarning( "Player id %u not found !", id ); + } + else + { + ((*ItPlayer).second).position = pos; + //nldebug( "SB: Player position updated" ); + } + + // Prepare to send back the message. + CMessage msgout( "ENTITY_POS" ); + msgout.serial( id ); + msgout.serial( pos ); + msgout.serial( angle ); + msgout.serial( state ); + + /* + * Send the message to all the connected Frontend. + */ + CUnifiedNetwork::getInstance ()->send( "FS", msgout ); + + CCLSClientPOS::movePosition(id, pos); + + //nldebug( "SB: Send back ENTITY_POS line." ); +} + + +/**************************************************************************** + * Function: cbRemoveEntity + * Callback function called when the Position Service receive a + * "REMOVE_ENTITY" message + ****************************************************************************/ +void cbRemoveEntity (CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + uint32 id; + + // Extract the incomming message content from the Frontend and print it + msgin.serial( id ); + nldebug( "SB: Received REMOVE_ENTITY line." ); + + // Prepare to send back the message. + CMessage msgout( "REMOVE_ENTITY" ); + msgout.serial( id ); + + /* + * Send the message to all the connected Frontend. + */ + CUnifiedNetwork::getInstance ()->send( "FS", msgout ); + + // Remove player form the player list. + playerList.erase( id ); + + CCLSClientPOS::removeEntity(id); + + nldebug( "SB: Send back REMOVE_ENTITY line. %d players left ...", + playerList.size() ); +} + + +/**************************************************************************** + * Function: cbSnowball + * Callback function called when the Position Service receive a + * "SNOWBALL" message + ****************************************************************************/ +void cbSnowball (CMessage &msgin, const std::string &serviceName, TServiceId sid) +{ + static uint32 snowballId = START_SNOW_ID; + + uint32 playerId; + CVector start, + target; + float speed, + explosionRadius; + + // Extract the incomming message content from the Frontend and print it + msgin.serial( playerId ); + msgin.serial( start ); + msgin.serial( target ); + msgin.serial( speed ); + msgin.serial( explosionRadius ); + nldebug( "SB: Received SNOWBALL line." ); + + // Store new snowballs informations + CTrajectory traj; + traj.init( start, target, speed, CTime::getLocalTime() + THROW_ANIM_OFFSET ); + _snowball snowball = _snowball( snowballId, playerId, traj, explosionRadius ); + snoList.push_front( snowball ); + + // Prepare to send back the message. + CMessage msgout( "SNOWBALL" ); + msgout.serial( snowballId ); + msgout.serial( playerId ); + msgout.serial( start ); + msgout.serial( target ); + msgout.serial( speed ); + msgout.serial( explosionRadius ); + + snowballId++; + + /* + * Send the message to all the connected Frontend. + */ + CUnifiedNetwork::getInstance ()->send( "FS", msgout ); + + nldebug( "SB: Send back SNOWBALL line." ); +} + + +/**************************************************************************** + * CallbackArray + * + * It define the functions to call when receiving a specific message + ****************************************************************************/ +TUnifiedCallbackItem CallbackArray[] = +{ + { "ADD_ENTITY", cbAddEntity }, + { "ENTITY_POS", cbPosition }, + { "REMOVE_ENTITY", cbRemoveEntity }, + { "SNOWBALL", cbSnowball }, + { "CLS_UPDATE", CCLSClientPOS::cbUpdate }, + { "CLS_POSITION", CCLSClientPOS::cbPosition } +}; + + +/**************************************************************************** + * Function: SendHITMsg + * Send HIT message to all clients + * + * Arguments: + * - snowball: snowball id + * - victim: player touched by the snowball + * - direct: define if the hit is direct or by the explosion + * area + ****************************************************************************/ +void SendHITMsg ( uint32 snowball, uint32 victim, bool direct ) +{ + CMessage msgout( "HIT" ); + + msgout.serial( snowball ); + msgout.serial( victim ); + msgout.serial( direct ); + + CUnifiedNetwork::getInstance ()->send( "FS", msgout ); +} + +/**************************************************************************** + * CPositionService + ****************************************************************************/ +class CPositionService : public IService +{ +public: + + void init() + { + CUnifiedNetwork::getInstance()->setServiceUpCallback("CLS", CCLSClientPOS::cbCollisionServiceUp, 0); + } + + // Update fonction, called at every frames + bool update() + { + //_snowball snowball; + CVector snoPos; + float distance; + bool removeSnowball; + + // Get the Current time + TTime currentTime = CTime::getLocalTime(); + list<_snowball>::iterator ItSnowball; + + // Check collision of snowballs with players + ItSnowball = snoList.begin(); + while ( ItSnowball != snoList.end() ) + { + removeSnowball = false; + + list<_snowball>::iterator ItSb = ItSnowball++; + _snowball snowball = (*ItSb); + + // Test collision (direct and explosion with players) + _pmap::iterator ItPlayer; + for (ItPlayer = playerList.begin(); ItPlayer != playerList.end(); ++ItPlayer) + { + _player player = (*ItPlayer).second; + + /* + * Snowballs can't touch the guy which throw it, Like that + * players could not kill them self (intentionally or not :-) + */ + if ( player.id == snowball.owner ) + { + continue; + } + + // Get the current snowball position + snoPos = snowball.traj.eval( currentTime ); + + // Test direct collision with players + distance = (player.position - snoPos).norm(); + if ( distance < ( PLAYER_RADIUS + SNOWBALL_RADIUS ) ) + { + nldebug( "SB: HIT on player %u by player %u.", + player.id, snowball.owner ); + + // Send HIT message + SendHITMsg( snowball.id, player.id, true ); + + // Flag the snowball to be removed from the list + removeSnowball = true; + } + + // Snowballs touch his stop Position + if ( snowball.traj.getStopTime() < currentTime ) + { + // Test for explosion victims + distance = (player.position - snoPos).norm(); + if ( distance < ( PLAYER_RADIUS + snowball.explosionRadius ) ) + { + nldebug( "SB: Explosion hit on player %u by player %u.", + player.id, snowball.owner ); + + // Send HIT message + SendHITMsg( snowball.id, player.id, false ); + } + + // Flag the snowball to be removed from the list + removeSnowball = true; + } + } + + + // Removed if flaged snowball + if ( removeSnowball ) + { + snoList.erase( ItSb ); + nldebug( "SB: Removed outdated SNOWBALL id %u.", snowball.id ); + } + + } + + return true; + } + +}; + + +/**************************************************************************** + * SNOWBALLS POSITION SERVICE MAIN Function + * + * This call create a main function for the POSITION service: + * + * - based on the base service class "IService", no need to inherit from it + * - having the short name "POSITION" + * - having the long name "position_service" + * - listening on an automatically allocated port (0) by the naming service + * - and callback actions set to "CallbackArray" + * + ****************************************************************************/ +NLNET_SERVICE_MAIN( CPositionService, "POS", "position_service", 0, CallbackArray, SNOWBALLS_CONFIG, SNOWBALLS_LOGS ) + + +/* end of file */ diff --git a/code/snowballs2/server/position/src/physics.cpp b/code/snowballs2/server/position/src/physics.cpp index ac32ceaa4..2bfb7bd77 100644 --- a/code/snowballs2/server/position/src/physics.cpp +++ b/code/snowballs2/server/position/src/physics.cpp @@ -1,46 +1,46 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// -// Includes -// - -#include "physics.h" - -// -// Namespaces -// - -using namespace std; -using namespace NLMISC; - -CVector CTrajectory::eval(NLMISC::TTime t) const -{ - float ft = (float)(t-_StartTime)/(float)(_StopTime-_StartTime); - ft = min(ft, 1.0f); - CVector res = _EndPosition*ft + _StartPosition*(1.0f-ft); - res.z += 0.3f*_Distance*_Distance/90.0f*(float)sin(Pi*ft); - return res; -} - -CVector CTrajectory::evalSpeed(NLMISC::TTime t) const -{ - float ft = (float)(t-_StartTime)/(float)(_StopTime-_StartTime); - ft = min(ft, 1.0f); - CVector res = (_EndPosition-_StartPosition).normed()*_Speed; - res.z += 0.3f*_Distance*_Distance/90.0f*(float)Pi*(float)cos(Pi*ft); - return res; -} +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// +// Includes +// + +#include "physics.h" + +// +// Namespaces +// + +using namespace std; +using namespace NLMISC; + +CVector CTrajectory::eval(NLMISC::TTime t) const +{ + float ft = (float)(t-_StartTime)/(float)(_StopTime-_StartTime); + ft = min(ft, 1.0f); + CVector res = _EndPosition*ft + _StartPosition*(1.0f-ft); + res.z += 0.3f*_Distance*_Distance/90.0f*(float)sin(Pi*ft); + return res; +} + +CVector CTrajectory::evalSpeed(NLMISC::TTime t) const +{ + float ft = (float)(t-_StartTime)/(float)(_StopTime-_StartTime); + ft = min(ft, 1.0f); + CVector res = (_EndPosition-_StartPosition).normed()*_Speed; + res.z += 0.3f*_Distance*_Distance/90.0f*(float)Pi*(float)cos(Pi*ft); + return res; +} diff --git a/code/snowballs2/server/position/src/physics.h b/code/snowballs2/server/position/src/physics.h index fcaeef0e2..e857fe25f 100644 --- a/code/snowballs2/server/position/src/physics.h +++ b/code/snowballs2/server/position/src/physics.h @@ -1,63 +1,63 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#ifndef PHYSICS_H -#define PHYSICS_H - -// -// Includes -// - -#include -#include - -// -// External classes -// - -class CTrajectory -{ - NLMISC::CVector _StartPosition; - NLMISC::CVector _EndPosition; - float _Speed; - NLMISC::TTime _StartTime; - NLMISC::TTime _StopTime; - float _Distance; - -public: - void init(const NLMISC::CVector &position, const NLMISC::CVector &target, float speed, NLMISC::TTime startTime) - { - _StartPosition = position; - _EndPosition = target; - _Speed = speed; - _StartTime = startTime; - _Distance = (_EndPosition-_StartPosition).norm(); - _StopTime = (NLMISC::TTime)(_Distance/_Speed*1000.0+_StartTime); - } - -// void compute(const NLMISC::CVector &position, const NLMISC::CVector &target, float speed, NLMISC::TTime startTime); - - NLMISC::CVector eval(NLMISC::TTime t) const; - NLMISC::CVector evalSpeed(NLMISC::TTime t) const; - - NLMISC::TTime getStartTime() const { return _StartTime; } - NLMISC::CVector getStartPosition() const { return _StartPosition; } - NLMISC::TTime getStopTime() const { return _StopTime; } -}; - -#endif // PHYSICS_H - -/* End of physics.h */ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef PHYSICS_H +#define PHYSICS_H + +// +// Includes +// + +#include +#include + +// +// External classes +// + +class CTrajectory +{ + NLMISC::CVector _StartPosition; + NLMISC::CVector _EndPosition; + float _Speed; + NLMISC::TTime _StartTime; + NLMISC::TTime _StopTime; + float _Distance; + +public: + void init(const NLMISC::CVector &position, const NLMISC::CVector &target, float speed, NLMISC::TTime startTime) + { + _StartPosition = position; + _EndPosition = target; + _Speed = speed; + _StartTime = startTime; + _Distance = (_EndPosition-_StartPosition).norm(); + _StopTime = (NLMISC::TTime)(_Distance/_Speed*1000.0+_StartTime); + } + +// void compute(const NLMISC::CVector &position, const NLMISC::CVector &target, float speed, NLMISC::TTime startTime); + + NLMISC::CVector eval(NLMISC::TTime t) const; + NLMISC::CVector evalSpeed(NLMISC::TTime t) const; + + NLMISC::TTime getStartTime() const { return _StartTime; } + NLMISC::CVector getStartPosition() const { return _StartPosition; } + NLMISC::TTime getStopTime() const { return _StopTime; } +}; + +#endif // PHYSICS_H + +/* End of physics.h */ diff --git a/code/tool/bin2c/bin2c.cpp b/code/tool/bin2c/bin2c.cpp index 5ecc433db..7f8538d9b 100644 --- a/code/tool/bin2c/bin2c.cpp +++ b/code/tool/bin2c/bin2c.cpp @@ -1,95 +1,95 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// bin2c.cpp : Defines the entry point for the console application. -// - -#include -#include -#include - -int main(int argc, char* argv[]) -{ - if (argc<2) - { - printf ("bin2c [filename.bin] [filename.c]\n"); - } - else - { - char sDir[256]; - char sPath[256]; - char sName[256]; - char sExt[256]; - _splitpath (argv[1], sDir, sPath, sName, sExt); - - char sOutput[256]; - if (argc>2) - strcpy (sOutput, argv[2]); - else - { - _makepath (sOutput, sDir, sPath, sName, ".cpp"); - } - - FILE *pIn=fopen( argv[1], "rb"); - if (pIn==NULL) - printf ("Can't open %s.", argv[1]); - else - { - FILE *pOut=fopen( sOutput, "w"); - if (pOut==NULL) - printf ("Can't open %s.", sOutput); - else - { - fprintf (pOut, - "/**\n" - " * Generated by bin2c.exe\n" - " * binfile: %s\n" - " */\n" - "\n" - "extern const unsigned char %s[];\n" - "extern const unsigned int %sSize;\n\n" - "static const unsigned char %s[] =\n" - "{\n", argv[1], sName, sName, sName); - - unsigned int size=0; - int i; - while (1) - { - fprintf (pOut, "\t"); - for (i=0; i<8; i++) - { - int c=fgetc (pIn); - if (c==EOF) - break; - fprintf (pOut, "0x%02x, ", c); - size++; - } - fprintf (pOut, "\n"); - if (i!=8) - break; - } - fprintf (pOut, "};\n\n"); - - fprintf (pOut, "static const unsigned int %sSize = %d;\n\n", sName, size); - - fclose (pOut); - fclose (pIn); - } - } - } - - return 0; -} +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// bin2c.cpp : Defines the entry point for the console application. +// + +#include +#include +#include + +int main(int argc, char* argv[]) +{ + if (argc<2) + { + printf ("bin2c [filename.bin] [filename.c]\n"); + } + else + { + char sDir[256]; + char sPath[256]; + char sName[256]; + char sExt[256]; + _splitpath (argv[1], sDir, sPath, sName, sExt); + + char sOutput[256]; + if (argc>2) + strcpy (sOutput, argv[2]); + else + { + _makepath (sOutput, sDir, sPath, sName, ".cpp"); + } + + FILE *pIn=fopen( argv[1], "rb"); + if (pIn==NULL) + printf ("Can't open %s.", argv[1]); + else + { + FILE *pOut=fopen( sOutput, "w"); + if (pOut==NULL) + printf ("Can't open %s.", sOutput); + else + { + fprintf (pOut, + "/**\n" + " * Generated by bin2c.exe\n" + " * binfile: %s\n" + " */\n" + "\n" + "extern const unsigned char %s[];\n" + "extern const unsigned int %sSize;\n\n" + "static const unsigned char %s[] =\n" + "{\n", argv[1], sName, sName, sName); + + unsigned int size=0; + int i; + while (1) + { + fprintf (pOut, "\t"); + for (i=0; i<8; i++) + { + int c=fgetc (pIn); + if (c==EOF) + break; + fprintf (pOut, "0x%02x, ", c); + size++; + } + fprintf (pOut, "\n"); + if (i!=8) + break; + } + fprintf (pOut, "};\n\n"); + + fprintf (pOut, "static const unsigned int %sSize = %d;\n\n", sName, size); + + fclose (pOut); + fclose (pIn); + } + } + } + + return 0; +} diff --git a/code/tool/crash/crash.cpp b/code/tool/crash/crash.cpp index b5d529e5a..71f83794f 100644 --- a/code/tool/crash/crash.cpp +++ b/code/tool/crash/crash.cpp @@ -1,27 +1,27 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// crash.cpp : Defines the entry point for the console application. -// - -#include - -int main(int argc, char* argv[]) -{ - *(int*)0 = 0; - return 0; -} - +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// crash.cpp : Defines the entry point for the console application. +// + +#include + +int main(int argc, char* argv[]) +{ + *(int*)0 = 0; + return 0; +} + diff --git a/code/tool/increment_version/increment_version.cpp b/code/tool/increment_version/increment_version.cpp index 1f90023f4..d24127a6c 100644 --- a/code/tool/increment_version/increment_version.cpp +++ b/code/tool/increment_version/increment_version.cpp @@ -1,135 +1,135 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include -#include -#include - - -#include -#include - -using namespace std; -using namespace NLMISC; - - - -//----------------------------------------------- -// main -// -//----------------------------------------------- -sint main( sint argc, char ** argv ) -{ - if( argc < 4 ) - { - printf("\n"); - printf("Increment the version number in a version file\n\n"); - printf("INCREMENT_VERSION \n"); - return 1; - } - - // open the version file - ifstream input(argv[1], ios::in); - if( !input.is_open() ) - { - nlwarning("can't open the file %s",argv[1]); - return 1; - } - - // open the output file - string outputFilename = string(argv[1]) + ".out"; - FILE * output = fopen(outputFilename.c_str(),"w"); - if( output == NULL ) - { - nlwarning("can't open the output file %s",outputFilename.c_str()); - return 1; - } - - bool motifFound = false; - bool versionNumberFound = false; - - while( !input.eof() ) - { - // read a line - string line; - getline(input,line,'\n'); - - // search the version motif - string::size_type idx = line.find(argv[2]); - - // if motif not found - if( idx == string::npos ) - { - // we write the line in output and continue to the next line - fprintf(output,"%s\n",line.c_str()); - } - // if motif found - else - { - motifFound = true; - - // search the main version number - idx = line.find(argv[3]); - if( idx == string::npos ) - { - fprintf(output,"%s\n",line.c_str()); - continue; - } - - versionNumberFound = true; - - // get old build version number - string::size_type oldBuildVersionStartIdx = line.rfind(".") + 1; - string::size_type oldBuildVersionEndIdx = line.find_first_of(" \"\t",oldBuildVersionStartIdx) - 1; - if( oldBuildVersionEndIdx == string::npos) - { - oldBuildVersionEndIdx = line.size() - 1; - } - string oldBuildVersionStr = line.substr( oldBuildVersionStartIdx, oldBuildVersionEndIdx - oldBuildVersionStartIdx + 1 ); - sint oldBuildVersion = atoi( oldBuildVersionStr.c_str() ); - - // increment build version - sint32 buildVersion = oldBuildVersion + 1; - string buildVersionStr = toString(buildVersion); - printf("%d\n",buildVersion); - - // replace build version in line - line.replace( oldBuildVersionStartIdx, oldBuildVersionStr.size(), buildVersionStr.c_str(), buildVersionStr.size() ); - - // we write the line in output and continue to the next line - fprintf(output,"%s\n",line.c_str()); - } - } - input.close(); - fclose(output); - - if( !motifFound ) - { - nlwarning("version motif %s not found\n",argv[2]); - return 1; - } - else - { - if( !versionNumberFound ) - { - nlwarning("version number %s not found\n",argv[3]); - return 1; - } - } - - return 0; -} - +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include +#include + + +#include +#include + +using namespace std; +using namespace NLMISC; + + + +//----------------------------------------------- +// main +// +//----------------------------------------------- +sint main( sint argc, char ** argv ) +{ + if( argc < 4 ) + { + printf("\n"); + printf("Increment the version number in a version file\n\n"); + printf("INCREMENT_VERSION \n"); + return 1; + } + + // open the version file + ifstream input(argv[1], ios::in); + if( !input.is_open() ) + { + nlwarning("can't open the file %s",argv[1]); + return 1; + } + + // open the output file + string outputFilename = string(argv[1]) + ".out"; + FILE * output = fopen(outputFilename.c_str(),"w"); + if( output == NULL ) + { + nlwarning("can't open the output file %s",outputFilename.c_str()); + return 1; + } + + bool motifFound = false; + bool versionNumberFound = false; + + while( !input.eof() ) + { + // read a line + string line; + getline(input,line,'\n'); + + // search the version motif + string::size_type idx = line.find(argv[2]); + + // if motif not found + if( idx == string::npos ) + { + // we write the line in output and continue to the next line + fprintf(output,"%s\n",line.c_str()); + } + // if motif found + else + { + motifFound = true; + + // search the main version number + idx = line.find(argv[3]); + if( idx == string::npos ) + { + fprintf(output,"%s\n",line.c_str()); + continue; + } + + versionNumberFound = true; + + // get old build version number + string::size_type oldBuildVersionStartIdx = line.rfind(".") + 1; + string::size_type oldBuildVersionEndIdx = line.find_first_of(" \"\t",oldBuildVersionStartIdx) - 1; + if( oldBuildVersionEndIdx == string::npos) + { + oldBuildVersionEndIdx = line.size() - 1; + } + string oldBuildVersionStr = line.substr( oldBuildVersionStartIdx, oldBuildVersionEndIdx - oldBuildVersionStartIdx + 1 ); + sint oldBuildVersion = atoi( oldBuildVersionStr.c_str() ); + + // increment build version + sint32 buildVersion = oldBuildVersion + 1; + string buildVersionStr = toString(buildVersion); + printf("%d\n",buildVersion); + + // replace build version in line + line.replace( oldBuildVersionStartIdx, oldBuildVersionStr.size(), buildVersionStr.c_str(), buildVersionStr.size() ); + + // we write the line in output and continue to the next line + fprintf(output,"%s\n",line.c_str()); + } + } + input.close(); + fclose(output); + + if( !motifFound ) + { + nlwarning("version motif %s not found\n",argv[2]); + return 1; + } + else + { + if( !versionNumberFound ) + { + nlwarning("version number %s not found\n",argv[3]); + return 1; + } + } + + return 0; +} + diff --git a/code/tool/mkdir_date/mkdir_date.cpp b/code/tool/mkdir_date/mkdir_date.cpp index f3f10b553..6a8ef9a20 100644 --- a/code/tool/mkdir_date/mkdir_date.cpp +++ b/code/tool/mkdir_date/mkdir_date.cpp @@ -1,50 +1,50 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// mkdir_date.cpp : Defines the entry point for the console application. -// - -#include -#include -#include - -int main(int argc, char* argv[]) -{ - // Help - if (argc<2) - { - printf ("mkdir_date [directory]"); - return 0; - } - - // Get the time - time_t aclock; - time(&aclock); - - // Get time information - const struct tm *timeptr=localtime(&aclock); - - // Format the string - char date[512]; - strftime( date, sizeof(date), "%Y %m %d %Hh%M", timeptr); - - // Name of the directory - char directory[512]; - sprintf (directory, "%s %s", argv[1], date); - - // Create a directory - return _mkdir( directory )==0; -} +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// mkdir_date.cpp : Defines the entry point for the console application. +// + +#include +#include +#include + +int main(int argc, char* argv[]) +{ + // Help + if (argc<2) + { + printf ("mkdir_date [directory]"); + return 0; + } + + // Get the time + time_t aclock; + time(&aclock); + + // Get time information + const struct tm *timeptr=localtime(&aclock); + + // Format the string + char date[512]; + strftime( date, sizeof(date), "%Y %m %d %Hh%M", timeptr); + + // Name of the directory + char directory[512]; + sprintf (directory, "%s %s", argv[1], date); + + // Create a directory + return _mkdir( directory )==0; +} diff --git a/code/tool/open_file/open_file.cpp b/code/tool/open_file/open_file.cpp index 5e66fa485..ee5b77656 100644 --- a/code/tool/open_file/open_file.cpp +++ b/code/tool/open_file/open_file.cpp @@ -1,100 +1,100 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// openhtml.cpp : Defines the entry point for the application. -// - -#include -#include -#include - -LONG GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata) -{ - HKEY hkey; - LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey); - - if (retval == ERROR_SUCCESS) - { - long datasize = MAX_PATH; - TCHAR data[MAX_PATH]; - RegQueryValue(hkey, NULL, data, &datasize); - lstrcpy(retdata,data); - RegCloseKey(hkey); - } - - return retval; -} - -bool OpenFile (LPCTSTR filename, LPCTSTR ext, int showcmd) -{ - TCHAR key[MAX_PATH + MAX_PATH]; - - // First try ShellExecute() - HINSTANCE result = ShellExecute(NULL, "open", filename, NULL,NULL, showcmd); - - // If it failed, get the .htm regkey and lookup the program - if ((UINT)result <= HINSTANCE_ERROR) - { - if (GetRegKey(HKEY_CLASSES_ROOT, ext, key) == ERROR_SUCCESS) - { - lstrcat(key, "\\shell\\open\\command"); - - if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS) - { - TCHAR *pos; - pos = strstr(key, "\"%1\""); - if (pos == NULL) { // No quotes found - pos = strstr(key, "%1"); // Check for %1, without quotes - if (pos == NULL) // No parameter at all... - pos = key+lstrlen(key)-1; - else - *pos = '\0'; // Remove the parameter - } - else - *pos = '\0'; // Remove the parameter - - lstrcat(pos, " "); - lstrcat(pos, filename); - int res = WinExec(key,showcmd); - return (res>31); - } - } - } - else - return true; - - return false; -} - -int APIENTRY WinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpCmdLine, - int nCmdShow) -{ - // TODO: Place code here. - if (strcmp (lpCmdLine, "")==0) - { - MessageBox (NULL, "Open a file with the default application.\nUsage: open_file [filepath]", "Open file", MB_OK|MB_ICONINFORMATION); - } - else - { - char ext[512]; - _splitpath (lpCmdLine, NULL, NULL, NULL, ext); - OpenFile(lpCmdLine, ext, SW_SHOW); - } - - return 0; -} +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// openhtml.cpp : Defines the entry point for the application. +// + +#include +#include +#include + +LONG GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata) +{ + HKEY hkey; + LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey); + + if (retval == ERROR_SUCCESS) + { + long datasize = MAX_PATH; + TCHAR data[MAX_PATH]; + RegQueryValue(hkey, NULL, data, &datasize); + lstrcpy(retdata,data); + RegCloseKey(hkey); + } + + return retval; +} + +bool OpenFile (LPCTSTR filename, LPCTSTR ext, int showcmd) +{ + TCHAR key[MAX_PATH + MAX_PATH]; + + // First try ShellExecute() + HINSTANCE result = ShellExecute(NULL, "open", filename, NULL,NULL, showcmd); + + // If it failed, get the .htm regkey and lookup the program + if ((UINT)result <= HINSTANCE_ERROR) + { + if (GetRegKey(HKEY_CLASSES_ROOT, ext, key) == ERROR_SUCCESS) + { + lstrcat(key, "\\shell\\open\\command"); + + if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS) + { + TCHAR *pos; + pos = strstr(key, "\"%1\""); + if (pos == NULL) { // No quotes found + pos = strstr(key, "%1"); // Check for %1, without quotes + if (pos == NULL) // No parameter at all... + pos = key+lstrlen(key)-1; + else + *pos = '\0'; // Remove the parameter + } + else + *pos = '\0'; // Remove the parameter + + lstrcat(pos, " "); + lstrcat(pos, filename); + int res = WinExec(key,showcmd); + return (res>31); + } + } + } + else + return true; + + return false; +} + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + // TODO: Place code here. + if (strcmp (lpCmdLine, "")==0) + { + MessageBox (NULL, "Open a file with the default application.\nUsage: open_file [filepath]", "Open file", MB_OK|MB_ICONINFORMATION); + } + else + { + char ext[512]; + _splitpath (lpCmdLine, NULL, NULL, NULL, ext); + OpenFile(lpCmdLine, ext, SW_SHOW); + } + + return 0; +} diff --git a/code/tool/path_content_diff/path_content_diff.cpp b/code/tool/path_content_diff/path_content_diff.cpp index 0033c2377..c2df4b946 100644 --- a/code/tool/path_content_diff/path_content_diff.cpp +++ b/code/tool/path_content_diff/path_content_diff.cpp @@ -1,220 +1,220 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -#include -#include -#include - -#include - -using namespace std; -using namespace NLMISC; - - -//----------------------------------------------- -// main -// -//----------------------------------------------- -int main( int argc, char ** argv ) -{ - if( argc < 3 || argc > 4 ) - { - printf("Build a listing of the diff of two path contents and copy new files in \n"); - printf("usage: path_content []\n"); - return EXIT_FAILURE; - } - - string DestPath; - if( argc == 4 ) - { - DestPath = CPath::standardizeDosPath(argv[3]); - if(CFile::isExists(DestPath)) - { - if(!CFile::isDirectory(DestPath)) - { - printf("'%s' is not a directory\n", DestPath.c_str()); - return EXIT_FAILURE; - } - } - else - { - if (!CFile::createDirectory(DestPath)) - { - printf("Can't create directory: '%s'\n", DestPath.c_str()); - return EXIT_FAILURE; - } - } - } - - // content of new path - string newPath(argv[2]); - vector newPathContent; - CPath::getPathContent(newPath, true, false, true, newPathContent); - - string outputFileName = CFile::findNewFile("path_content_diff.txt"); - FILE *output = fopen (outputFileName.c_str(), "wt"); - if( output == NULL ) - { - nlwarning("Can't open output file %s",outputFileName.c_str()); - return EXIT_FAILURE; - } - - // add ref path in search paths - string refPath(argv[1]); - CPath::addSearchPath(refPath, true, false); - - map refSHAMap; - CIFile refSHAFile; - if( refSHAFile.open(refPath +".sha1key") ) - { - // load the map of SHA hash key for the ref files - refSHAFile.serialCont( refSHAMap ); - refSHAFile.close(); - } - else - { - // build the map of SHA hash key for the ref files - string extension; - vector refPathContent; - CPath::getFileList(extension, refPathContent); - vector::const_iterator itFile; - for( itFile = refPathContent.begin(); itFile != refPathContent.end(); ++itFile ) - { - refSHAMap.insert( make_pair(*itFile,getSHA1(*itFile)) ); - } - COFile refSHAFile(refPath + ".sha1key"); - refSHAFile.serialCont( refSHAMap ); - } - - - // build the map of SHA hash key for new files - map newSHAMap; - vector::const_iterator itFile; - for( itFile = newPathContent.begin(); itFile != newPathContent.end(); ++itFile ) - { - newSHAMap.insert( make_pair(*itFile,getSHA1(*itFile)) ); - } - -// display (debug) - map::iterator itSHA; - /* - for( itSHA = refSHAMap.begin(); itSHA != refSHAMap.end(); ++itSHA ) - { - nlinfo("(ref) %s : %s",(*itSHA).first.c_str(),(*itSHA).second.toString().c_str()); - } - for( itSHA = newSHAMap.begin(); itSHA != newSHAMap.end(); ++itSHA ) - { - nlinfo("(new) %s : %s",(*itSHA).first.c_str(),(*itSHA).second.toString().c_str()); - } - */ -// - - uint32 LastDisplay = 0, curFile = 0; - - // get the list of new or modified files - vector differentFiles; - for( itFile = newPathContent.begin(); itFile != newPathContent.end(); ++itFile ) - { - string newFileName = *itFile; - string newFileNameShort = CFile::getFilename(newFileName); - - curFile++; - - if (CTime::getSecondsSince1970() > LastDisplay + 5) - { - printf("%d on %d files, %d left\n", curFile, newPathContent.size(), newPathContent.size() - curFile); - LastDisplay = CTime::getSecondsSince1970(); - } - - if( CFile::getExtension(newFileNameShort) == "bnp" ) - { - nlwarning ("BNP PROBLEM: %s is a big file, content of big files is not managed", newFileName.c_str()); - nlwarning ("The must *not* contains .bnp files"); - } - - bool keepIt = false; - - string refFileName = CPath::lookup(strlwr(newFileNameShort), false, false, false); - if( refFileName.empty() ) - { - keepIt = true; - nlinfo ("new file : %s",newFileNameShort.c_str()); - } - else - { - itSHA = refSHAMap.find( newFileNameShort ); - CHashKey refSHA; - if( itSHA != refSHAMap.end() ) - { - refSHA = (*itSHA).second; - } - - itSHA = newSHAMap.find( newFileName ); - CHashKey newSHA; - if( itSHA != newSHAMap.end() ) - { - newSHA = (*itSHA).second; - } - - if( !(refSHA==newSHA) ) - { - keepIt = true; - nlinfo("file : %s , key : %s(%s), size : %d(%d)",newFileNameShort.c_str(), newSHA.toString().c_str(),refSHA.toString().c_str(),CFile::getFileSize(newFileName),CFile::getFileSize(refFileName)); - } - - /* - uint32 refModificationDate = CFile::getFileModificationDate( refFileName ); - uint32 newModificationDate = CFile::getFileModificationDate( newFileName ); - - if( newModificationDate > refModificationDate ) - { - keepIt = true; - nlinfo ("DATE CHANGED: %s", newFileName.c_str()); - } - else - { - // same date, must be same size - uint32 refSize = CFile::getFileSize( refFileName ); - uint32 newSize = CFile::getFileSize( newFileName ); - if( refSize != newSize ) - { - nlwarning ("DATE PROBLEM: file '%s' have the same date but not the same size than '%s'", newFileName.c_str(), refFileName.c_str()); - } - } - */ - } - - if( keepIt ) - { - differentFiles.push_back( newFileName ); - - //uint32 newCreationDate = CFile::getFileCreationDate( newFileName ); - //string outputLine = newFileName + "\t\t"+toString(newSize) + "\t" + toString(newModificationDate) + "\t" + toString(newCreationDate) + "\n"; - string outputLine = newFileName + "\n"; - fprintf (output, outputLine.c_str()); - - if( !DestPath.empty() ) - { - string systemStr = "copy /Y " + CPath::standardizeDosPath(newFileName) + " " + DestPath; - //nlinfo("System call '%s'",systemStr.c_str()); - system( systemStr.c_str() ); - } - } - } - - return EXIT_SUCCESS; -} - +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#include +#include +#include + +#include + +using namespace std; +using namespace NLMISC; + + +//----------------------------------------------- +// main +// +//----------------------------------------------- +int main( int argc, char ** argv ) +{ + if( argc < 3 || argc > 4 ) + { + printf("Build a listing of the diff of two path contents and copy new files in \n"); + printf("usage: path_content []\n"); + return EXIT_FAILURE; + } + + string DestPath; + if( argc == 4 ) + { + DestPath = CPath::standardizeDosPath(argv[3]); + if(CFile::isExists(DestPath)) + { + if(!CFile::isDirectory(DestPath)) + { + printf("'%s' is not a directory\n", DestPath.c_str()); + return EXIT_FAILURE; + } + } + else + { + if (!CFile::createDirectory(DestPath)) + { + printf("Can't create directory: '%s'\n", DestPath.c_str()); + return EXIT_FAILURE; + } + } + } + + // content of new path + string newPath(argv[2]); + vector newPathContent; + CPath::getPathContent(newPath, true, false, true, newPathContent); + + string outputFileName = CFile::findNewFile("path_content_diff.txt"); + FILE *output = fopen (outputFileName.c_str(), "wt"); + if( output == NULL ) + { + nlwarning("Can't open output file %s",outputFileName.c_str()); + return EXIT_FAILURE; + } + + // add ref path in search paths + string refPath(argv[1]); + CPath::addSearchPath(refPath, true, false); + + map refSHAMap; + CIFile refSHAFile; + if( refSHAFile.open(refPath +".sha1key") ) + { + // load the map of SHA hash key for the ref files + refSHAFile.serialCont( refSHAMap ); + refSHAFile.close(); + } + else + { + // build the map of SHA hash key for the ref files + string extension; + vector refPathContent; + CPath::getFileList(extension, refPathContent); + vector::const_iterator itFile; + for( itFile = refPathContent.begin(); itFile != refPathContent.end(); ++itFile ) + { + refSHAMap.insert( make_pair(*itFile,getSHA1(*itFile)) ); + } + COFile refSHAFile(refPath + ".sha1key"); + refSHAFile.serialCont( refSHAMap ); + } + + + // build the map of SHA hash key for new files + map newSHAMap; + vector::const_iterator itFile; + for( itFile = newPathContent.begin(); itFile != newPathContent.end(); ++itFile ) + { + newSHAMap.insert( make_pair(*itFile,getSHA1(*itFile)) ); + } + +// display (debug) + map::iterator itSHA; + /* + for( itSHA = refSHAMap.begin(); itSHA != refSHAMap.end(); ++itSHA ) + { + nlinfo("(ref) %s : %s",(*itSHA).first.c_str(),(*itSHA).second.toString().c_str()); + } + for( itSHA = newSHAMap.begin(); itSHA != newSHAMap.end(); ++itSHA ) + { + nlinfo("(new) %s : %s",(*itSHA).first.c_str(),(*itSHA).second.toString().c_str()); + } + */ +// + + uint32 LastDisplay = 0, curFile = 0; + + // get the list of new or modified files + vector differentFiles; + for( itFile = newPathContent.begin(); itFile != newPathContent.end(); ++itFile ) + { + string newFileName = *itFile; + string newFileNameShort = CFile::getFilename(newFileName); + + curFile++; + + if (CTime::getSecondsSince1970() > LastDisplay + 5) + { + printf("%d on %d files, %d left\n", curFile, newPathContent.size(), newPathContent.size() - curFile); + LastDisplay = CTime::getSecondsSince1970(); + } + + if( CFile::getExtension(newFileNameShort) == "bnp" ) + { + nlwarning ("BNP PROBLEM: %s is a big file, content of big files is not managed", newFileName.c_str()); + nlwarning ("The must *not* contains .bnp files"); + } + + bool keepIt = false; + + string refFileName = CPath::lookup(strlwr(newFileNameShort), false, false, false); + if( refFileName.empty() ) + { + keepIt = true; + nlinfo ("new file : %s",newFileNameShort.c_str()); + } + else + { + itSHA = refSHAMap.find( newFileNameShort ); + CHashKey refSHA; + if( itSHA != refSHAMap.end() ) + { + refSHA = (*itSHA).second; + } + + itSHA = newSHAMap.find( newFileName ); + CHashKey newSHA; + if( itSHA != newSHAMap.end() ) + { + newSHA = (*itSHA).second; + } + + if( !(refSHA==newSHA) ) + { + keepIt = true; + nlinfo("file : %s , key : %s(%s), size : %d(%d)",newFileNameShort.c_str(), newSHA.toString().c_str(),refSHA.toString().c_str(),CFile::getFileSize(newFileName),CFile::getFileSize(refFileName)); + } + + /* + uint32 refModificationDate = CFile::getFileModificationDate( refFileName ); + uint32 newModificationDate = CFile::getFileModificationDate( newFileName ); + + if( newModificationDate > refModificationDate ) + { + keepIt = true; + nlinfo ("DATE CHANGED: %s", newFileName.c_str()); + } + else + { + // same date, must be same size + uint32 refSize = CFile::getFileSize( refFileName ); + uint32 newSize = CFile::getFileSize( newFileName ); + if( refSize != newSize ) + { + nlwarning ("DATE PROBLEM: file '%s' have the same date but not the same size than '%s'", newFileName.c_str(), refFileName.c_str()); + } + } + */ + } + + if( keepIt ) + { + differentFiles.push_back( newFileName ); + + //uint32 newCreationDate = CFile::getFileCreationDate( newFileName ); + //string outputLine = newFileName + "\t\t"+toString(newSize) + "\t" + toString(newModificationDate) + "\t" + toString(newCreationDate) + "\n"; + string outputLine = newFileName + "\n"; + fprintf (output, outputLine.c_str()); + + if( !DestPath.empty() ) + { + string systemStr = "copy /Y " + CPath::standardizeDosPath(newFileName) + " " + DestPath; + //nlinfo("System call '%s'",systemStr.c_str()); + system( systemStr.c_str() ); + } + } + } + + return EXIT_SUCCESS; +} + diff --git a/code/tool/ren_date/ren_date.cpp b/code/tool/ren_date/ren_date.cpp index af168abda..c0d957247 100644 --- a/code/tool/ren_date/ren_date.cpp +++ b/code/tool/ren_date/ren_date.cpp @@ -1,79 +1,79 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// mkdir_date.cpp : Defines the entry point for the console application. -// - -#include -#include -#include -#include - -int main(int argc, char* argv[]) -{ - // Help - bool keepExt = false; - bool help = ( (argc<3) || (argc>4) ); - if (argc == 4) - { - if (strcmp (argv[3], "-keepExt") == 0) - keepExt = true; - else - help = true; - } - - if (help) - { - printf ("ren_date [old_name] [new_base_name] [-keepExt]"); - return 0; - } - - // Get the time - time_t aclock; - time(&aclock); - - // Get time information - const struct tm *timeptr=localtime(&aclock); - - // Extension - char ext[512]; - - // Empty string - strcpy (ext, ""); - - // Keep the extension - if (keepExt) - { - // Get the extension - char *point = strrchr (argv[2], '.'); - if (point) - { - strcpy (ext, point); - *point = 0; - } - } - - // Format the string - char date[512]; - strftime( date, sizeof(date), "%Y %m %d %Hh%M", timeptr); - - // Name of the directory - char directory[512]; - sprintf (directory, "%s %s%s", argv[2], date, ext); - - // Create a directory - return rename ( argv[1], directory )==0; -} +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// mkdir_date.cpp : Defines the entry point for the console application. +// + +#include +#include +#include +#include + +int main(int argc, char* argv[]) +{ + // Help + bool keepExt = false; + bool help = ( (argc<3) || (argc>4) ); + if (argc == 4) + { + if (strcmp (argv[3], "-keepExt") == 0) + keepExt = true; + else + help = true; + } + + if (help) + { + printf ("ren_date [old_name] [new_base_name] [-keepExt]"); + return 0; + } + + // Get the time + time_t aclock; + time(&aclock); + + // Get time information + const struct tm *timeptr=localtime(&aclock); + + // Extension + char ext[512]; + + // Empty string + strcpy (ext, ""); + + // Keep the extension + if (keepExt) + { + // Get the extension + char *point = strrchr (argv[2], '.'); + if (point) + { + strcpy (ext, point); + *point = 0; + } + } + + // Format the string + char date[512]; + strftime( date, sizeof(date), "%Y %m %d %Hh%M", timeptr); + + // Name of the directory + char directory[512]; + sprintf (directory, "%s %s%s", argv[2], date, ext); + + // Create a directory + return rename ( argv[1], directory )==0; +} diff --git a/code/tool/resswap/ResSwap.cpp b/code/tool/resswap/ResSwap.cpp index 7060b2066..d221ff5da 100644 --- a/code/tool/resswap/ResSwap.cpp +++ b/code/tool/resswap/ResSwap.cpp @@ -1,50 +1,50 @@ -// NeL - MMORPG Framework -// Copyright (C) 2010 Winch Gate Property Limited -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as -// published by the Free Software Foundation, either version 3 of the -// License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -// ResSwap.cpp : Defines the entry point for the application. -// - -#include - -int APIENTRY WinMain(HINSTANCE hInstance, - HINSTANCE hPrevInstance, - LPSTR lpCmdLine, - int nCmdShow) -{ - DEVMODE bkupMode, devMode; - devMode.dmSize= sizeof(DEVMODE); - devMode.dmDriverExtra= 0; - EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode); - devMode.dmFields= DM_BITSPERPEL; - - bkupMode= devMode; - - if(devMode.dmBitsPerPel==16) - { - devMode.dmBitsPerPel=32; - } - else - { - devMode.dmBitsPerPel=16; - } - ChangeDisplaySettings(&devMode, 0); - ChangeDisplaySettings(&bkupMode, 0); - - return 0; -} - - - +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +// ResSwap.cpp : Defines the entry point for the application. +// + +#include + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + DEVMODE bkupMode, devMode; + devMode.dmSize= sizeof(DEVMODE); + devMode.dmDriverExtra= 0; + EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &devMode); + devMode.dmFields= DM_BITSPERPEL; + + bkupMode= devMode; + + if(devMode.dmBitsPerPel==16) + { + devMode.dmBitsPerPel=32; + } + else + { + devMode.dmBitsPerPel=16; + } + ChangeDisplaySettings(&devMode, 0); + ChangeDisplaySettings(&bkupMode, 0); + + return 0; +} + + + diff --git a/code/tool/visual_studio_macros/nevrax_macros_howto.txt b/code/tool/visual_studio_macros/nevrax_macros_howto.txt index f1ddf3f34..54c8ecd81 100644 --- a/code/tool/visual_studio_macros/nevrax_macros_howto.txt +++ b/code/tool/visual_studio_macros/nevrax_macros_howto.txt @@ -1,149 +1,149 @@ -Mode d'emploi des macros Nevrax -02/08/00 cado@nevrax.com -$Id: nevrax_macros_howto.txt,v 1.10 2001/05/22 12:08:47 cado Exp $ ----------- - -Dernière mise à jour : 22/05/2001 - -1. Nouveautés du 22/05/2001 ---------------------------- - -- NevraxNewClass: Pour faire en sorte que le répertoire des -fichiers include soit le même que celui des fichiers source, -spécifier une chaîne vide pour le répertoire des fichiers -include (boite de dialogue n°4) - -- Il existe maintenant un fichier nevrax_macros_ryzom.dsm. -La seule différence avec nevrax_macros.dsm est que le nom -du projet généré dans l'en-tête des fichiers n'est pas -NEL mais RYZOM. - -- (Windows 2000 uniquement) La macro NevraxToggleHCPP -recherche désormais le fichier .h dans les trois -répertoires suivants si le fichier .cpp fait partie de NeL : - R:\code\nel\include\nel\ - R:\code\nel\include_private\nel\ - Le répertoire du fichier .cpp -La recherche du .cpp correspondant à un .h appartenant à -NeL se fait dans : - R:\code\nel\src\ - Le répertoire du fichier .h - -Si le fichier ne fait pas partie de nel, la recherche ne -se fait que dans le même répertoire que le fichier de -départ. - - -1. Nouveauté du 14/12/2000 --------------------------- -- La macro NevraxNewClass stocke les répertoires des sources -et des include dans le fichier de configuration -R:\code\tool\VisualStudioMacros\nevrax_new_class.cfg -(sauf si vous utilisez nevrax_macros_98.dsm). -IMPORTANT: -Avant de lancer la macro, il faut rajouter les répertoires -par défaut (par exemple R:\code\nel\src et -R:\code\nel\include\nel) dans le fichier de config, à la -main. - - -2. Nouveautés du 18/09/2000 --------------------------- -- La macro NevraxNewClass stocke votre nom dans un fichier -(R:\code\tool\VisualStudioMacros\nevrax_new_class.cfg) -(sauf si vous utilisez nevrax_macros_98.dsm). -- Lorsque vous spécifiez un répertoire de travail (ex: misc, -net), la macro définit le namespace correspondant, commençant -par RKn dans les fichiers .h et .cpp. -- Lorsque vous spécifiez un répertoire de travail (ex: misc, -net), les fichiers .h et .cpp sont ajoutés dans le projet du -même nom même si ce n'est pas le projet actif. - - -3. Note du 13/09/2000 ---------------------- - -Dans ce document, remplacez nevrax_macros.dsm par -nevrax_macros_98.dsm si la macro NevraxNewClass de -nevrax_macros.dsm génère une erreur en instanciant -un objet ActiveX Automation "FileSystemObject". -Ce problème a été constaté sous Windows 98, pas -sous Windows 2000. -Dans la version 98, il n'y a pas de test d'existence -des fichiers et répertoires, et votre nom n'est pas -stocké dans un fichier. - - -4. Nouveautés du 07/09/2000 ---------------------------- - -- La macro NevraxNewClass vous demande et mémorise votre nom, pour -l'insérer dans le champ \name de Doxygen. -- La macro NevraxNewClass teste l'existence des répertoires et des -fichiers : elle vérifie que les fichiers .h et .cpp n'existent pas -déjà, que les répertoires des fichiers include et source existent -bien, et vous informe quand le fichier .h de l'éventuelle classe de -base n'existe pas. - - -5. Installation ---------------- - -a. Dans Visual Studio, menu Tools, Macros, -Options>>, Loaded Files, -Browse, R:\code\tool\VisualStudioMacros\nevrax_macros.dsm, -Close - -b. (Facultatif) Raccourci clavier : Menu Tools, Macros, choisir -nevrax_macros dans la liste Macro File, sélectionner NevraxToggleHCPP, -Options>>, Keystrokes, dans "Press new shortcut key" taper la -combinaison Ctrl+< (touche Ctrl et touche <). Dans Current keys, on -voit s'afficher Ctrl+< ; Close - -c. (Facultatif) Bouton supplémentaire : Menu Tools, Macros, -sélectionner NevraxNewClass (du fichier nevrax_macros), Options>>, -oolbars, glisser-déposer NevraxNewClass sur une barre d'outil de Visual -Studio, choisir une image pour le bouton (par exemple le petit crayon -jaune), OK, Close. - - -6. Utilisation --------------- - -- NevraxToggleHCPP (raccourci-clavier "Ctrl-<" installé en 1.b. ci-dessus) - Cette macro sert à passer d'un .h à un .cpp et vice-versa. - Elle est compatible avec l'arborescence de NeL. - -- NevraxNewClass (bouton installé en 1.c. ci-dessus) - Cette macro est un assistant de création de classe, adaptée pour - NeL. Elle doit être utilisée quand un projet C++ est ouvert. - Les étapes : - 1. Choix du nom de la classe. Ex: CMaClasse - 2. Confirmation du nom des fichiers .h et .cpp à créer. Ex: Pour - CMaClasse, la macro propose ma_classe. - 3. Confirmation du répertoire des sources .cpp. Par défaut : - R:\code\nel\src - Pour le répertoire courant du projet, entrer un point (.) - 4. Confirmation du répertoire des includes .h. Par défaut : - R:\code\nel\include\nel - Pour le répertoire courant du projet, entrer un point (.) - 5. Choix ou confirmation du répertoire de travail. Celui-ci doit - être tapé une fois par session de Visual Studio, après il est - mémorisé. Exs: misc ou system ou 3d ou ia ou network ou database - Les répertoires ainsi formés (ex: R:\code\nel\src\misc et - R:\code\nel\include\nel\misc) doivent déjà exister, sans - quoi Visual Studio déclenchera une "unknown error" lors de la - sauvegarde du fichier. - Pour le répertoire courant du projet, ne rien entrer. - 6. Choix ou confirmation du nom du programmeur. Comme dans l'étape - précédente, on le tape une seule fois par session de Visual - Studio. - 7. Choix d'une classe de base (si la nouvelle classe doit être - dérivée d'une classe parente) (ex: CBaseClass) ou NO BASE CLASS. - 8. Si vous avez entré une classe de base, vous devez entrer le - nom du fichier include de cette classe. Ex: nel/misc/base_class - N'oubliez pas le chemin d'accès (comme dans l'exemple ci-dessus). - Remarque : - Le bouton Annuler fonctionne seulement dans les étapes 1,2,6,7,8 - (merci VBScript !). Si vous vous trompez en 3,4 ou 5, cliquez sur - Annuler dans l'étape 6. +Mode d'emploi des macros Nevrax +02/08/00 cado@nevrax.com +$Id: nevrax_macros_howto.txt,v 1.10 2001/05/22 12:08:47 cado Exp $ +---------- + +Dernière mise à jour : 22/05/2001 + +1. Nouveautés du 22/05/2001 +--------------------------- + +- NevraxNewClass: Pour faire en sorte que le répertoire des +fichiers include soit le même que celui des fichiers source, +spécifier une chaîne vide pour le répertoire des fichiers +include (boite de dialogue n°4) + +- Il existe maintenant un fichier nevrax_macros_ryzom.dsm. +La seule différence avec nevrax_macros.dsm est que le nom +du projet généré dans l'en-tête des fichiers n'est pas +NEL mais RYZOM. + +- (Windows 2000 uniquement) La macro NevraxToggleHCPP +recherche désormais le fichier .h dans les trois +répertoires suivants si le fichier .cpp fait partie de NeL : + R:\code\nel\include\nel\ + R:\code\nel\include_private\nel\ + Le répertoire du fichier .cpp +La recherche du .cpp correspondant à un .h appartenant à +NeL se fait dans : + R:\code\nel\src\ + Le répertoire du fichier .h + +Si le fichier ne fait pas partie de nel, la recherche ne +se fait que dans le même répertoire que le fichier de +départ. + + +1. Nouveauté du 14/12/2000 +-------------------------- +- La macro NevraxNewClass stocke les répertoires des sources +et des include dans le fichier de configuration +R:\code\tool\VisualStudioMacros\nevrax_new_class.cfg +(sauf si vous utilisez nevrax_macros_98.dsm). +IMPORTANT: +Avant de lancer la macro, il faut rajouter les répertoires +par défaut (par exemple R:\code\nel\src et +R:\code\nel\include\nel) dans le fichier de config, à la +main. + + +2. Nouveautés du 18/09/2000 +-------------------------- +- La macro NevraxNewClass stocke votre nom dans un fichier +(R:\code\tool\VisualStudioMacros\nevrax_new_class.cfg) +(sauf si vous utilisez nevrax_macros_98.dsm). +- Lorsque vous spécifiez un répertoire de travail (ex: misc, +net), la macro définit le namespace correspondant, commençant +par RKn dans les fichiers .h et .cpp. +- Lorsque vous spécifiez un répertoire de travail (ex: misc, +net), les fichiers .h et .cpp sont ajoutés dans le projet du +même nom même si ce n'est pas le projet actif. + + +3. Note du 13/09/2000 +--------------------- + +Dans ce document, remplacez nevrax_macros.dsm par +nevrax_macros_98.dsm si la macro NevraxNewClass de +nevrax_macros.dsm génère une erreur en instanciant +un objet ActiveX Automation "FileSystemObject". +Ce problème a été constaté sous Windows 98, pas +sous Windows 2000. +Dans la version 98, il n'y a pas de test d'existence +des fichiers et répertoires, et votre nom n'est pas +stocké dans un fichier. + + +4. Nouveautés du 07/09/2000 +--------------------------- + +- La macro NevraxNewClass vous demande et mémorise votre nom, pour +l'insérer dans le champ \name de Doxygen. +- La macro NevraxNewClass teste l'existence des répertoires et des +fichiers : elle vérifie que les fichiers .h et .cpp n'existent pas +déjà, que les répertoires des fichiers include et source existent +bien, et vous informe quand le fichier .h de l'éventuelle classe de +base n'existe pas. + + +5. Installation +--------------- + +a. Dans Visual Studio, menu Tools, Macros, +Options>>, Loaded Files, +Browse, R:\code\tool\VisualStudioMacros\nevrax_macros.dsm, +Close + +b. (Facultatif) Raccourci clavier : Menu Tools, Macros, choisir +nevrax_macros dans la liste Macro File, sélectionner NevraxToggleHCPP, +Options>>, Keystrokes, dans "Press new shortcut key" taper la +combinaison Ctrl+< (touche Ctrl et touche <). Dans Current keys, on +voit s'afficher Ctrl+< ; Close + +c. (Facultatif) Bouton supplémentaire : Menu Tools, Macros, +sélectionner NevraxNewClass (du fichier nevrax_macros), Options>>, +oolbars, glisser-déposer NevraxNewClass sur une barre d'outil de Visual +Studio, choisir une image pour le bouton (par exemple le petit crayon +jaune), OK, Close. + + +6. Utilisation +-------------- + +- NevraxToggleHCPP (raccourci-clavier "Ctrl-<" installé en 1.b. ci-dessus) + Cette macro sert à passer d'un .h à un .cpp et vice-versa. + Elle est compatible avec l'arborescence de NeL. + +- NevraxNewClass (bouton installé en 1.c. ci-dessus) + Cette macro est un assistant de création de classe, adaptée pour + NeL. Elle doit être utilisée quand un projet C++ est ouvert. + Les étapes : + 1. Choix du nom de la classe. Ex: CMaClasse + 2. Confirmation du nom des fichiers .h et .cpp à créer. Ex: Pour + CMaClasse, la macro propose ma_classe. + 3. Confirmation du répertoire des sources .cpp. Par défaut : + R:\code\nel\src + Pour le répertoire courant du projet, entrer un point (.) + 4. Confirmation du répertoire des includes .h. Par défaut : + R:\code\nel\include\nel + Pour le répertoire courant du projet, entrer un point (.) + 5. Choix ou confirmation du répertoire de travail. Celui-ci doit + être tapé une fois par session de Visual Studio, après il est + mémorisé. Exs: misc ou system ou 3d ou ia ou network ou database + Les répertoires ainsi formés (ex: R:\code\nel\src\misc et + R:\code\nel\include\nel\misc) doivent déjà exister, sans + quoi Visual Studio déclenchera une "unknown error" lors de la + sauvegarde du fichier. + Pour le répertoire courant du projet, ne rien entrer. + 6. Choix ou confirmation du nom du programmeur. Comme dans l'étape + précédente, on le tape une seule fois par session de Visual + Studio. + 7. Choix d'une classe de base (si la nouvelle classe doit être + dérivée d'une classe parente) (ex: CBaseClass) ou NO BASE CLASS. + 8. Si vous avez entré une classe de base, vous devez entrer le + nom du fichier include de cette classe. Ex: nel/misc/base_class + N'oubliez pas le chemin d'accès (comme dans l'exemple ci-dessus). + Remarque : + Le bouton Annuler fonctionne seulement dans les étapes 1,2,6,7,8 + (merci VBScript !). Si vous vous trompez en 3,4 ou 5, cliquez sur + Annuler dans l'étape 6.
    "; - if ( c == keyColumn ) - s += key; // key should be a substr of toString( c ) - else - { - if ( lightMode ) - s += "\""; - else - s += columnToString( c ); - } - s += "
    "; + if ( c == keyColumn ) + s += key; // key should be a substr of toString( c ) + else + { + if ( lightMode ) + s += "\""; + else + s += columnToString( c ); + } + s += "