rapid-router 5.4.1__py2.py3-none-any.whl → 7.6.8__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- example_project/rapid_router_test_settings.py +164 -0
- example_project/settings.py +152 -0
- example_project/urls.py +15 -0
- example_project/{example_project/wsgi.py → wsgi.py} +2 -1
- game/__init__.py +1 -1
- game/admin.py +43 -4
- game/app_settings.py +3 -7
- game/character.py +26 -18
- game/decor.py +172 -97
- game/end_to_end_tests/base_game_test.py +44 -33
- game/end_to_end_tests/editor_page.py +17 -2
- game/end_to_end_tests/game_page.py +127 -45
- game/end_to_end_tests/selenium_test_case.py +1 -20
- game/end_to_end_tests/test_cow_crashes.py +3 -5
- game/end_to_end_tests/test_language_dropdown.py +14 -0
- game/end_to_end_tests/test_level_editor.py +290 -0
- game/end_to_end_tests/test_level_failures.py +1 -1
- game/end_to_end_tests/test_level_selection.py +79 -0
- game/end_to_end_tests/test_play_through.py +240 -102
- game/end_to_end_tests/test_python_levels.py +44 -13
- game/end_to_end_tests/test_saving_workspace.py +22 -0
- game/forms.py +9 -2
- game/level_management.py +38 -29
- game/messages.py +1218 -203
- game/migrations/0001_squashed_0025_levels_ordering_pt1.py +19 -1
- game/migrations/0026_levels_pt2.py +13 -2
- game/migrations/0032_cannot_turn_left_level.py +13 -2
- game/migrations/0033_recursion_level.py +13 -2
- game/migrations/0034_joes_level.py +13 -2
- game/migrations/0035_disable_route_score_level_70.py +0 -2
- game/migrations/0036_level_score_73.py +0 -2
- game/migrations/0037_level_score_79.py +0 -2
- game/migrations/0038_level_score_40.py +0 -1
- game/migrations/0042_level_score_73.py +0 -2
- game/migrations/0048_add_cow_field_and_blocks.py +0 -2
- game/migrations/0049_level_score_34.py +0 -2
- game/migrations/0050_level_score_40.py +0 -2
- game/migrations/0051_level_score_49.py +0 -1
- game/migrations/0076_level_locked_for_class.py +19 -0
- game/migrations/0077_alter_level_next_level.py +52 -0
- game/migrations/0078_add_block_types.py +23 -0
- game/migrations/0079_populate_block_type_add_cow_blocks.py +60 -0
- game/migrations/0080_level_disable_algorithm_score.py +18 -0
- game/migrations/0081_first_12_levels_no_algo_score.py +29 -0
- game/migrations/0082_level_43_solution.py +16 -0
- game/migrations/0083_add_cows_to_existing_levels.py +195 -0
- game/migrations/0084_alter_block_block_type.py +18 -0
- game/migrations/0085_add_new_blocks.py +53 -0
- game/migrations/0086_loop_levels.py +482 -0
- game/migrations/0087_workspace_python_view_enabled.py +18 -0
- game/migrations/0088_rename_episodes.py +35 -0
- game/migrations/0089_episodes_in_development.py +30 -0
- game/migrations/0090_add_missing_model_solutions.py +144 -0
- game/migrations/0091_disable_algo_score_if_no_model_solution.py +46 -0
- game/migrations/0092_disable_algo_score_in_custom_levels.py +28 -0
- game/migrations/0093_alter_level_character_name.py +18 -0
- game/migrations/0094_add_hint_lesson_subtitle_to_levels.py +28 -0
- game/migrations/0095_level_commands.py +18 -0
- game/migrations/0096_alter_level_commands.py +18 -0
- game/migrations/0097_add_python_den_levels.py +1515 -0
- game/migrations/0098_add_episode_link_fields.py +44 -0
- game/migrations/0099_python_episodes_links.py +103 -0
- game/migrations/0100_reorder_python_levels.py +179 -0
- game/migrations/0101_rename_episodes.py +45 -0
- game/migrations/0102_reoder_episodes_13_14.py +136 -0
- game/migrations/0103_level_1015_solution.py +26 -0
- game/migrations/0104_remove_level_direct_drive.py +17 -0
- game/migrations/0105_delete_invalid_attempts.py +18 -0
- game/migrations/0106_fields_to_snake_case.py +48 -0
- game/migrations/0107_rename_worksheet_link_episode_student_worksheet_link.py +18 -0
- game/migrations/0108_episode_indy_worksheet_link.py +18 -0
- game/migrations/0109_create_episodes_23_and_24.py +99 -0
- game/migrations/0110_remove_episode_indy_worksheet_link_and_more.py +100 -0
- game/migrations/0111_create_worksheets.py +149 -0
- game/migrations/0112_worksheet_locked_classes.py +21 -0
- game/migrations/0113_level_needs_approval.py +18 -0
- game/migrations/0114_default_and_non_student_levels_no_approval.py +31 -0
- game/migrations/0115_level_level__default_does_not_need_approval.py +22 -0
- game/migrations/0116_update_worksheet_video_links.py +68 -0
- game/migrations/0117_update_solutions_to_if_else.py +61 -0
- game/models.py +157 -16
- game/permissions.py +34 -19
- game/python_den_urls.py +26 -0
- game/random_road.py +43 -127
- game/serializers.py +12 -17
- game/static/django_reverse_js/js/reverse.js +171 -0
- game/static/game/css/LilitaOne-Regular.ttf +0 -0
- game/static/game/css/backgrounds.css +14 -10
- game/static/game/css/dataTables.custom.css +4 -2
- game/static/game/css/dataTables.jqueryui.css +561 -320
- game/static/game/css/editor.css +47 -0
- game/static/game/css/game.css +43 -49
- game/static/game/css/game_screen.css +116 -53
- game/static/game/css/jquery.dataTables.css +455 -251
- game/static/game/css/level_editor.css +10 -1
- game/static/game/css/level_selection.css +32 -3
- game/static/game/css/level_share.css +6 -5
- game/static/game/css/skulpt/codemirror.css +1 -0
- game/static/game/image/Python_Den_hero_student.png +0 -0
- game/static/game/image/Python_levels_page.svg +1954 -0
- game/static/game/image/characters/front_view/Electric_van.svg +448 -0
- game/static/game/image/characters/top_view/Electric_van.svg +448 -0
- game/static/game/image/characters/top_view/Sleigh.svg +436 -0
- game/static/game/image/decor/city/solar_panel.svg +1200 -0
- game/static/game/image/decor/farm/solar_panel.svg +86 -0
- game/static/game/image/decor/grass/solar_panel.svg +86 -0
- game/static/game/image/decor/snow/barn.svg +1788 -0
- game/static/game/image/decor/snow/cfc.svg +1050 -147
- game/static/game/image/decor/snow/crops.svg +7370 -0
- game/static/game/image/decor/snow/hospital.svg +1220 -0
- game/static/game/image/decor/snow/house1.svg +971 -0
- game/static/game/image/decor/snow/house2.svg +1574 -0
- game/static/game/image/decor/snow/school.svg +1071 -0
- game/static/game/image/decor/snow/shop.svg +3211 -0
- game/static/game/image/decor/snow/solar_panel.svg +173 -0
- game/static/game/image/electric_van.svg +448 -0
- game/static/game/image/icons/add_house.svg +26 -0
- game/static/game/image/icons/delete_house.svg +26 -0
- game/static/game/image/icons/description.svg +1 -0
- game/static/game/image/icons/hint.svg +1 -0
- game/static/game/image/icons/if_else.svg +3 -0
- game/static/game/image/icons/python.svg +1 -1
- game/static/game/image/if_else_example.png +0 -0
- game/static/game/image/pigeon.svg +684 -0
- game/static/game/image/python_den_header.svg +19 -0
- game/static/game/js/animation.js +84 -28
- game/static/game/js/blockly/msg/js/bg.js +52 -1
- game/static/game/js/blockly/msg/js/ca.js +52 -1
- game/static/game/js/blockly/msg/js/en-gb.js +52 -1
- game/static/game/js/blockly/msg/js/en.js +52 -1
- game/static/game/js/blockly/msg/js/es.js +52 -1
- game/static/game/js/blockly/msg/js/fr.js +52 -1
- game/static/game/js/blockly/msg/js/hi.js +52 -1
- game/static/game/js/blockly/msg/js/it.js +52 -1
- game/static/game/js/blockly/msg/js/pl.js +52 -1
- game/static/game/js/blockly/msg/js/pt-br.js +52 -1
- game/static/game/js/blockly/msg/js/ru.js +52 -1
- game/static/game/js/blockly/msg/js/ur.js +52 -1
- game/static/game/js/blocklyCompiler.js +550 -392
- game/static/game/js/blocklyControl.js +335 -302
- game/static/game/js/blocklyCustomBlocks.js +691 -458
- game/static/game/js/blocklyCustomisations.js +3 -1
- game/static/game/js/button.js +12 -0
- game/static/game/js/cow.js +15 -130
- game/static/game/js/drawing.js +313 -201
- game/static/game/js/editor.js +23 -0
- game/static/game/js/game.js +148 -139
- game/static/game/js/jquery.dataTables.min.js +3 -159
- game/static/game/js/level_editor.js +823 -448
- game/static/game/js/level_moderation.js +33 -2
- game/static/game/js/level_selection.js +62 -25
- game/static/game/js/loadLanguages.js +21 -0
- game/static/game/js/map.js +106 -36
- game/static/game/js/model.js +55 -107
- game/static/game/js/pathFinder.js +73 -72
- game/static/game/js/program.js +184 -193
- game/static/game/js/pythonControl.js +14 -1
- game/static/game/js/scoreboard.js +0 -37
- game/static/game/js/scoreboardSharedLevels.js +48 -0
- game/static/game/js/sharing.js +22 -10
- game/static/game/js/skulpt/codemirror.js +5 -4
- game/static/game/js/skulpt/skulpt-stdlib.js +1 -1
- game/static/game/js/sound.js +52 -5
- game/static/game/js/van.js +0 -7
- game/static/game/raphael_image/characters/top_view/Electric_van.svg +448 -0
- game/static/game/raphael_image/characters/top_view/Sleigh.svg +436 -0
- game/static/game/raphael_image/decor/city/solar_panel.svg +1200 -0
- game/static/game/raphael_image/decor/farm/solar_panel.svg +86 -0
- game/static/game/raphael_image/decor/grass/solar_panel.svg +86 -0
- game/static/game/raphael_image/decor/snow/barn.svg +1788 -0
- game/static/game/raphael_image/decor/snow/cfc.svg +1050 -147
- game/static/game/raphael_image/decor/snow/crops.svg +7370 -0
- game/static/game/raphael_image/decor/snow/hospital.svg +1220 -0
- game/static/game/raphael_image/decor/snow/house1.svg +971 -0
- game/static/game/raphael_image/decor/snow/house2.svg +1574 -0
- game/static/game/raphael_image/decor/snow/school.svg +1071 -0
- game/static/game/raphael_image/decor/snow/shop.svg +3211 -0
- game/static/game/raphael_image/decor/snow/solar_panel.svg +173 -0
- game/static/game/raphael_image/pigeon.svg +685 -0
- game/static/game/raphael_image/sleigh_wreckage.svg +430 -0
- game/static/game/sass/game.scss +22 -6
- game/static/game/sound/clown_horn.mp3 +0 -0
- game/static/game/sound/clown_horn.ogg +0 -0
- game/static/game/sound/electric_van_starting.mp3 +0 -0
- game/static/game/sound/electric_van_starting.ogg +0 -0
- game/static/game/sound/pigeon.mp3 +0 -0
- game/static/game/sound/pigeon.ogg +0 -0
- game/static/game/sound/sleigh_bells.mp3 +0 -0
- game/static/game/sound/sleigh_bells.ogg +0 -0
- game/static/game/sound/sleigh_crash.mp3 +0 -0
- game/static/game/sound/sleigh_crash.ogg +0 -0
- game/templates/game/base.html +35 -15
- game/templates/game/basenonav.html +23 -17
- game/templates/game/game.html +236 -111
- game/templates/game/level_editor.html +353 -275
- game/templates/game/level_moderation.html +19 -6
- game/templates/game/level_selection.html +75 -62
- game/templates/game/python_den_level_selection.html +291 -0
- game/templates/game/python_den_worksheet.html +101 -0
- game/templates/game/scoreboard.html +88 -65
- game/tests/test_level_editor.py +210 -35
- game/tests/test_level_moderation.py +6 -20
- game/tests/test_level_selection.py +332 -11
- game/tests/test_python_den_worksheet.py +85 -0
- game/tests/test_scoreboard.py +258 -66
- game/tests/utils/level.py +43 -3
- game/tests/utils/teacher.py +2 -2
- game/theme.py +21 -21
- game/urls.py +125 -78
- game/views/language_code_conversions.py +90 -0
- game/views/level.py +201 -63
- game/views/level_editor.py +109 -48
- game/views/level_moderation.py +29 -6
- game/views/level_selection.py +179 -56
- game/views/level_solutions.py +600 -106
- game/views/scoreboard.py +181 -66
- game/views/worksheet.py +25 -0
- rapid_router-7.6.8.dist-info/METADATA +174 -0
- {rapid_router-5.4.1.dist-info → rapid_router-7.6.8.dist-info}/RECORD +222 -242
- {rapid_router-5.4.1.dist-info → rapid_router-7.6.8.dist-info}/WHEEL +1 -1
- rapid_router-7.6.8.dist-info/licenses/LICENSE.md +3 -0
- example_project/example_project/__init__.py +0 -1
- example_project/example_project/settings.py +0 -54
- example_project/example_project/urls.py +0 -16
- example_project/manage.py +0 -10
- game/autoconfig.py +0 -59
- game/csp_config.py +0 -23
- game/locale/ar_SA/LC_MESSAGES/django.mo +0 -0
- game/locale/ar_SA/LC_MESSAGES/django.po +0 -405
- game/locale/ar_SA/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/ar_SA/LC_MESSAGES/djangojs.po +0 -743
- game/locale/bg_BG/LC_MESSAGES/django.mo +0 -0
- game/locale/bg_BG/LC_MESSAGES/django.po +0 -405
- game/locale/bg_BG/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/bg_BG/LC_MESSAGES/djangojs.po +0 -739
- game/locale/ca_ES/LC_MESSAGES/django.mo +0 -0
- game/locale/ca_ES/LC_MESSAGES/django.po +0 -405
- game/locale/ca_ES/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/ca_ES/LC_MESSAGES/djangojs.po +0 -740
- game/locale/cs_CZ/LC_MESSAGES/django.mo +0 -0
- game/locale/cs_CZ/LC_MESSAGES/django.po +0 -405
- game/locale/cs_CZ/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/cs_CZ/LC_MESSAGES/djangojs.po +0 -741
- game/locale/cy_GB/LC_MESSAGES/django.mo +0 -0
- game/locale/cy_GB/LC_MESSAGES/django.po +0 -405
- game/locale/cy_GB/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/cy_GB/LC_MESSAGES/djangojs.po +0 -743
- game/locale/de_DE/LC_MESSAGES/django.mo +0 -0
- game/locale/de_DE/LC_MESSAGES/django.po +0 -405
- game/locale/de_DE/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/de_DE/LC_MESSAGES/djangojs.po +0 -739
- game/locale/el_GR/LC_MESSAGES/django.mo +0 -0
- game/locale/el_GR/LC_MESSAGES/django.po +0 -405
- game/locale/el_GR/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/el_GR/LC_MESSAGES/djangojs.po +0 -739
- game/locale/en_GB/LC_MESSAGES/django.mo +0 -0
- game/locale/en_GB/LC_MESSAGES/django.po +0 -405
- game/locale/en_GB/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/en_GB/LC_MESSAGES/djangojs.po +0 -739
- game/locale/es_ES/LC_MESSAGES/django.mo +0 -0
- game/locale/es_ES/LC_MESSAGES/django.po +0 -405
- game/locale/es_ES/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/es_ES/LC_MESSAGES/djangojs.po +0 -739
- game/locale/fi_FI/LC_MESSAGES/django.mo +0 -0
- game/locale/fi_FI/LC_MESSAGES/django.po +0 -405
- game/locale/fi_FI/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/fi_FI/LC_MESSAGES/djangojs.po +0 -739
- game/locale/fr_FR/LC_MESSAGES/django.mo +0 -0
- game/locale/fr_FR/LC_MESSAGES/django.po +0 -405
- game/locale/fr_FR/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/fr_FR/LC_MESSAGES/djangojs.po +0 -739
- game/locale/gu_IN/LC_MESSAGES/django.mo +0 -0
- game/locale/gu_IN/LC_MESSAGES/django.po +0 -405
- game/locale/gu_IN/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/gu_IN/LC_MESSAGES/djangojs.po +0 -739
- game/locale/hi_IN/LC_MESSAGES/django.mo +0 -0
- game/locale/hi_IN/LC_MESSAGES/django.po +0 -405
- game/locale/hi_IN/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/hi_IN/LC_MESSAGES/djangojs.po +0 -739
- game/locale/id_ID/LC_MESSAGES/django.mo +0 -0
- game/locale/id_ID/LC_MESSAGES/django.po +0 -405
- game/locale/id_ID/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/id_ID/LC_MESSAGES/djangojs.po +0 -738
- game/locale/it_IT/LC_MESSAGES/django.mo +0 -0
- game/locale/it_IT/LC_MESSAGES/django.po +0 -405
- game/locale/it_IT/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/it_IT/LC_MESSAGES/djangojs.po +0 -739
- game/locale/ja_JP/LC_MESSAGES/django.mo +0 -0
- game/locale/ja_JP/LC_MESSAGES/django.po +0 -405
- game/locale/ja_JP/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/ja_JP/LC_MESSAGES/djangojs.po +0 -738
- game/locale/lol_US/LC_MESSAGES/django.mo +0 -0
- game/locale/lol_US/LC_MESSAGES/django.po +0 -405
- game/locale/lol_US/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/lol_US/LC_MESSAGES/djangojs.po +0 -739
- game/locale/nb_NO/LC_MESSAGES/django.mo +0 -0
- game/locale/nb_NO/LC_MESSAGES/django.po +0 -405
- game/locale/nb_NO/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/nb_NO/LC_MESSAGES/djangojs.po +0 -739
- game/locale/nl_NL/LC_MESSAGES/django.mo +0 -0
- game/locale/nl_NL/LC_MESSAGES/django.po +0 -405
- game/locale/nl_NL/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/nl_NL/LC_MESSAGES/djangojs.po +0 -739
- game/locale/pl_PL/LC_MESSAGES/django.mo +0 -0
- game/locale/pl_PL/LC_MESSAGES/django.po +0 -405
- game/locale/pl_PL/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/pl_PL/LC_MESSAGES/djangojs.po +0 -741
- game/locale/pt_BR/LC_MESSAGES/django.mo +0 -0
- game/locale/pt_BR/LC_MESSAGES/django.po +0 -405
- game/locale/pt_BR/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/pt_BR/LC_MESSAGES/djangojs.po +0 -739
- game/locale/pt_PT/LC_MESSAGES/django.mo +0 -0
- game/locale/pt_PT/LC_MESSAGES/django.po +0 -405
- game/locale/pt_PT/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/pt_PT/LC_MESSAGES/djangojs.po +0 -739
- game/locale/ro_RO/LC_MESSAGES/django.mo +0 -0
- game/locale/ro_RO/LC_MESSAGES/django.po +0 -405
- game/locale/ro_RO/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/ro_RO/LC_MESSAGES/djangojs.po +0 -740
- game/locale/ru_RU/LC_MESSAGES/django.mo +0 -0
- game/locale/ru_RU/LC_MESSAGES/django.po +0 -405
- game/locale/ru_RU/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/ru_RU/LC_MESSAGES/djangojs.po +0 -741
- game/locale/sv_SE/LC_MESSAGES/django.mo +0 -0
- game/locale/sv_SE/LC_MESSAGES/django.po +0 -405
- game/locale/sv_SE/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/sv_SE/LC_MESSAGES/djangojs.po +0 -739
- game/locale/tl_PH/LC_MESSAGES/django.mo +0 -0
- game/locale/tl_PH/LC_MESSAGES/django.po +0 -405
- game/locale/tl_PH/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/tl_PH/LC_MESSAGES/djangojs.po +0 -739
- game/locale/tlh_AA/LC_MESSAGES/django.mo +0 -0
- game/locale/tlh_AA/LC_MESSAGES/django.po +0 -405
- game/locale/tlh_AA/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/tlh_AA/LC_MESSAGES/djangojs.po +0 -739
- game/locale/tr_TR/LC_MESSAGES/django.mo +0 -0
- game/locale/tr_TR/LC_MESSAGES/django.po +0 -405
- game/locale/tr_TR/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/tr_TR/LC_MESSAGES/djangojs.po +0 -740
- game/locale/ur_IN/LC_MESSAGES/django.mo +0 -0
- game/locale/ur_IN/LC_MESSAGES/django.po +0 -405
- game/locale/ur_IN/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/ur_IN/LC_MESSAGES/djangojs.po +0 -739
- game/locale/ur_PK/LC_MESSAGES/django.mo +0 -0
- game/locale/ur_PK/LC_MESSAGES/django.po +0 -405
- game/locale/ur_PK/LC_MESSAGES/djangojs.mo +0 -0
- game/locale/ur_PK/LC_MESSAGES/djangojs.po +0 -739
- game/static/game/image/actions/go.svg +0 -18
- game/static/game/image/icons/destination.svg +0 -9
- game/static/game/js/pqselect.min.js +0 -9
- game/static/game/js/widget-scroller.js +0 -906
- rapid_router-5.4.1.dist-info/LICENSE.md +0 -577
- rapid_router-5.4.1.dist-info/METADATA +0 -24
- {rapid_router-5.4.1.dist-info → rapid_router-7.6.8.dist-info}/top_level.txt +0 -0
|
@@ -8,6 +8,8 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
8
8
|
/* Constants */
|
|
9
9
|
/*************/
|
|
10
10
|
|
|
11
|
+
const TAB_PANE_WIDTH = 500;
|
|
12
|
+
|
|
11
13
|
var LIGHT_RED_URL = ocargo.Drawing.raphaelImageDir + 'trafficLight_red.svg';
|
|
12
14
|
var LIGHT_GREEN_URL = ocargo.Drawing.raphaelImageDir + 'trafficLight_green.svg';
|
|
13
15
|
|
|
@@ -36,21 +38,37 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
36
38
|
'#8F7C00' // Khaki
|
|
37
39
|
];
|
|
38
40
|
|
|
39
|
-
var ADD_ROAD_IMG_URL = ocargo.Drawing.imageDir + "icons/add_road.svg";
|
|
40
|
-
var DELETE_ROAD_IMG_URL = ocargo.Drawing.imageDir + "icons/delete_road.svg";
|
|
41
|
-
var MARK_START_IMG_URL = ocargo.Drawing.imageDir + "icons/origin.svg";
|
|
42
|
-
var MARK_END_IMG_URL = ocargo.Drawing.imageDir + "icons/destination.svg";
|
|
43
|
-
|
|
44
41
|
var VALID_LIGHT_COLOUR = '#87E34D';
|
|
45
42
|
var INVALID_LIGHT_COLOUR = '#E35F4D';
|
|
46
43
|
|
|
47
44
|
var paper = $('#paper'); // May as well cache this
|
|
48
45
|
|
|
49
46
|
var modes = {
|
|
50
|
-
ADD_ROAD_MODE: {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
ADD_ROAD_MODE: {
|
|
48
|
+
name: gettext('Add road'),
|
|
49
|
+
url: ocargo.Drawing.imageDir + 'icons/add_road.svg',
|
|
50
|
+
id: 'add_road',
|
|
51
|
+
},
|
|
52
|
+
DELETE_ROAD_MODE: {
|
|
53
|
+
name: gettext('Delete road'),
|
|
54
|
+
url: ocargo.Drawing.imageDir + 'icons/delete_road.svg',
|
|
55
|
+
id: 'delete_road',
|
|
56
|
+
},
|
|
57
|
+
MARK_ORIGIN_MODE: {
|
|
58
|
+
name: gettext('Mark start'),
|
|
59
|
+
url: ocargo.Drawing.imageDir + 'icons/origin.svg',
|
|
60
|
+
id: 'start',
|
|
61
|
+
},
|
|
62
|
+
ADD_HOUSE_MODE: {
|
|
63
|
+
name: gettext('Add house'),
|
|
64
|
+
url: ocargo.Drawing.imageDir + 'icons/add_house.svg',
|
|
65
|
+
id: 'add_house',
|
|
66
|
+
},
|
|
67
|
+
DELETE_HOUSE_MODE: {
|
|
68
|
+
name: gettext('Delete house'),
|
|
69
|
+
url: ocargo.Drawing.imageDir + 'icons/delete_house.svg',
|
|
70
|
+
id: 'delete_house',
|
|
71
|
+
}
|
|
54
72
|
};
|
|
55
73
|
|
|
56
74
|
/*********/
|
|
@@ -67,8 +85,9 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
67
85
|
var trafficLights = [];
|
|
68
86
|
var cows = [];
|
|
69
87
|
var originNode = null;
|
|
70
|
-
var
|
|
88
|
+
var houseNodes = [];
|
|
71
89
|
var currentTheme = THEMES.grass;
|
|
90
|
+
var needsApproval = false;
|
|
72
91
|
|
|
73
92
|
// Reference to the Raphael elements for each square
|
|
74
93
|
var grid;
|
|
@@ -173,6 +192,8 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
173
192
|
tabs.character = new ocargo.Tab($('#character_radio'), $('#character_radio + label'), $('#character_pane'));
|
|
174
193
|
tabs.blocks = new ocargo.Tab($('#blocks_radio'), $('#blocks_radio + label'), $('#blocks_pane'));
|
|
175
194
|
tabs.random = new ocargo.Tab($('#random_radio'), $('#random_radio + label'), $('#random_pane'));
|
|
195
|
+
tabs.description = new ocargo.Tab($('#description_radio'), $('#description_radio + label'), $('#description_pane'));
|
|
196
|
+
tabs.hint = new ocargo.Tab($('#hint_radio'), $('#hint_radio + label'), $('#hint_pane'));
|
|
176
197
|
tabs.load = new ocargo.Tab($('#load_radio'), $('#load_radio + label'), $('#load_pane'));
|
|
177
198
|
tabs.save = new ocargo.Tab($('#save_radio'), $('#save_radio + label'), $('#save_pane'));
|
|
178
199
|
tabs.share = new ocargo.Tab($('#share_radio'), $('#share_radio + label'), $('#share_pane'));
|
|
@@ -186,6 +207,8 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
186
207
|
setupCharacterTab();
|
|
187
208
|
setupBlocksTab();
|
|
188
209
|
setupRandomTab();
|
|
210
|
+
setupDescriptionTab();
|
|
211
|
+
setupHintTab();
|
|
189
212
|
setupLoadTab();
|
|
190
213
|
setupSaveTab();
|
|
191
214
|
setupShareTab();
|
|
@@ -235,6 +258,10 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
235
258
|
function changeCurrentToolDisplay(mode){
|
|
236
259
|
$('#currentToolText').text(mode.name);
|
|
237
260
|
$('#currentToolIcon').attr("src", mode.url);
|
|
261
|
+
Object.values(modes).forEach((element) => {
|
|
262
|
+
$(`#${element.id}`).addClass('unselected');
|
|
263
|
+
});
|
|
264
|
+
$(`#${mode.id}`).removeClass('unselected');
|
|
238
265
|
}
|
|
239
266
|
|
|
240
267
|
function setupMapTab() {
|
|
@@ -254,11 +281,6 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
254
281
|
changeCurrentToolDisplay(modes.MARK_ORIGIN_MODE);
|
|
255
282
|
});
|
|
256
283
|
|
|
257
|
-
$('#end').click(function() {
|
|
258
|
-
mode = modes.MARK_DESTINATION_MODE;
|
|
259
|
-
changeCurrentToolDisplay(modes.MARK_DESTINATION_MODE);
|
|
260
|
-
});
|
|
261
|
-
|
|
262
284
|
$('#add_road').click(function() {
|
|
263
285
|
mode = modes.ADD_ROAD_MODE;
|
|
264
286
|
changeCurrentToolDisplay(modes.ADD_ROAD_MODE);
|
|
@@ -269,6 +291,16 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
269
291
|
changeCurrentToolDisplay(modes.DELETE_ROAD_MODE);
|
|
270
292
|
});
|
|
271
293
|
|
|
294
|
+
$('#add_house').click(function() {
|
|
295
|
+
mode = modes.ADD_HOUSE_MODE;
|
|
296
|
+
changeCurrentToolDisplay(modes.ADD_HOUSE_MODE);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
$('#delete_house').click(function() {
|
|
300
|
+
mode = modes.DELETE_HOUSE_MODE;
|
|
301
|
+
changeCurrentToolDisplay(modes.DELETE_HOUSE_MODE);
|
|
302
|
+
});
|
|
303
|
+
|
|
272
304
|
if(DEVELOPER) {
|
|
273
305
|
$('#djangoText').click(function() {
|
|
274
306
|
ocargo.Drawing.startPopup('Django level migration',
|
|
@@ -293,122 +325,27 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
293
325
|
}
|
|
294
326
|
});
|
|
295
327
|
|
|
296
|
-
$('.decor_button').
|
|
297
|
-
new InternalDecor(e.target.id);
|
|
298
|
-
});
|
|
328
|
+
$('.decor_button').mousedown(handleDraggableDecorMouseDown);
|
|
299
329
|
|
|
300
|
-
$('#trafficLightRed').
|
|
301
|
-
|
|
302
|
-
"startingState": ocargo.TrafficLight.RED,
|
|
303
|
-
"sourceCoordinate": null, "direction": null});
|
|
330
|
+
$('#trafficLightRed').mousedown(function(e) {
|
|
331
|
+
handleDraggableTrafficLightsMouseDown(e, ocargo.TrafficLight.RED);
|
|
304
332
|
});
|
|
305
333
|
|
|
306
|
-
$('#trafficLightGreen').
|
|
307
|
-
|
|
308
|
-
"startingState": ocargo.TrafficLight.GREEN,
|
|
309
|
-
"sourceCoordinate": null, "direction": null});
|
|
334
|
+
$('#trafficLightGreen').mousedown(function(e) {
|
|
335
|
+
handleDraggableTrafficLightsMouseDown(e, ocargo.TrafficLight.GREEN);
|
|
310
336
|
});
|
|
311
337
|
|
|
312
338
|
if(COW_LEVELS_ENABLED) {
|
|
313
|
-
$('#cow').click(function () {
|
|
314
|
-
new InternalCow({group: cowGroups[$('#cow_group_select').val()]});
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
//"Advanced" button
|
|
318
|
-
$('#advanced_cow_options_button').on('click', function () {
|
|
319
|
-
$(this).toggleClass('cow_navigation_button_pressed');
|
|
320
|
-
|
|
321
|
-
var showIconSrc = "/static/game/image/icons/show.svg";
|
|
322
|
-
var hideIconSrc = "/static/game/image/icons/hide_button.svg";
|
|
323
|
-
var advancedButtonIcon = $('#advanced_cow_options_button_icon');
|
|
324
|
-
var iconSrc = (advancedButtonIcon.attr("src") === showIconSrc) ? hideIconSrc : showIconSrc;
|
|
325
|
-
advancedButtonIcon.attr("src", iconSrc);
|
|
326
|
-
|
|
327
|
-
var advancedDivHidden = $('#cow_advanced_div').css('display') === 'none';
|
|
328
|
-
|
|
329
|
-
$('#cow_advanced_div').slideToggle(1000);
|
|
330
|
-
|
|
331
|
-
//Only scroll down if advanced options were previously hidden
|
|
332
|
-
if (advancedDivHidden) {
|
|
333
|
-
$('#tab_panes_wrapper').animate({scrollTop: $('#tab_panes_wrapper')[0].scrollHeight},
|
|
334
|
-
1500,
|
|
335
|
-
"swing");
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
// Set up cow type selector and listener
|
|
340
|
-
$('#cow_type_select').append($('<option>', {value: ocargo.Cow.WHITE})
|
|
341
|
-
.text(gettext('White')));
|
|
342
|
-
$('#cow_type_select').append($('<option>', {value: ocargo.Cow.BROWN})
|
|
343
|
-
.text(gettext('Brown')));
|
|
344
|
-
$('#cow_type_select').on('change', function () {
|
|
345
|
-
var selectedGroupId = $('#cow_group_select').val();
|
|
346
|
-
var selectedType = $('#cow_type_select').val();
|
|
347
|
-
cowGroups[selectedGroupId].type = selectedType;
|
|
348
|
-
var newUrl = ocargo.Drawing.raphaelImageDir + ocargo.Drawing.cowUrl(selectedType);
|
|
349
|
-
$('#cow').attr('src', newUrl);
|
|
350
|
-
|
|
351
|
-
for(var i = cows.length - 1; i >= 0; i--) {
|
|
352
|
-
if(cows[i].data.group.id === selectedGroupId) {
|
|
353
|
-
cows[i].image.attr({src: newUrl})
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
});
|
|
358
|
-
|
|
359
|
-
//Min & max spinners
|
|
360
|
-
var minSpinner = $('#min_cows_spinner').spinner({
|
|
361
|
-
min: 1,
|
|
362
|
-
max: 1
|
|
363
|
-
}).val(1);
|
|
364
|
-
minSpinner.on('spinstop', function () {
|
|
365
|
-
$('#max_cows_spinner').spinner('option', 'min', $('#min_cows_spinner').val());
|
|
366
|
-
cowGroups[$('#cow_group_select').val()].minCows = $('#min_cows_spinner').val();
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
var maxSpinner = $('#max_cows_spinner').spinner({
|
|
370
|
-
min: 1,
|
|
371
|
-
max: 1
|
|
372
|
-
}).val(1);
|
|
373
|
-
maxSpinner.on('spinstop', function () {
|
|
374
|
-
$('#min_cows_spinner').spinner('option', 'max', $('#max_cows_spinner').val());
|
|
375
|
-
cowGroups[$('#cow_group_select').val()].maxCows = $('#max_cows_spinner').val();
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
//Group select element (has to be initialised after the min and max spinners are created)
|
|
379
|
-
$('#cow_group_select').on('change', function () {
|
|
380
|
-
$('#cow_group_select').css('background-color', cowGroups[this.value].color);
|
|
381
|
-
//Set max values of min & max spinners
|
|
382
|
-
var groupId = this.value;
|
|
383
|
-
var noOfValidCowsInGroup = 0;
|
|
384
|
-
for (var i = 0; i < cows.length; i++) {
|
|
385
|
-
if (cows[i].valid && cows[i].data.group.id === groupId) {
|
|
386
|
-
noOfValidCowsInGroup++;
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
// Set cow type
|
|
391
|
-
$('#cow_type_select').val(cowGroups[this.value].type).change();
|
|
392
|
-
|
|
393
|
-
var minMaxValue = Math.max(1, cowGroups[this.value].maxCows);
|
|
394
|
-
$('#min_cows_spinner').spinner('option', 'max', minMaxValue);
|
|
395
|
-
var maxMinValue = Math.max(1, cowGroups[this.value].minCows);
|
|
396
|
-
$('#max_cows_spinner').spinner('option', 'min', maxMinValue);
|
|
397
|
-
$('#max_cows_spinner').spinner('option', 'max', Math.max(1, noOfValidCowsInGroup));
|
|
398
|
-
|
|
399
|
-
//Set min & max values
|
|
400
|
-
$('#min_cows_spinner').val(cowGroups[this.value].minCows);
|
|
401
|
-
$('#max_cows_spinner').val(cowGroups[this.value].maxCows);
|
|
402
|
-
});
|
|
403
|
-
|
|
404
339
|
if (Object.keys(cowGroups).length == 0) {
|
|
405
340
|
addCowGroup();
|
|
406
341
|
}
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
342
|
+
$('#cow').mouseover(function(e) {
|
|
343
|
+
e.target.style.cursor = "pointer";
|
|
344
|
+
})
|
|
345
|
+
$('#cow').mousedown(function(e) {
|
|
346
|
+
handleDraggableCowMouseDown(e, "group1")
|
|
347
|
+
});
|
|
410
348
|
}
|
|
411
|
-
|
|
412
349
|
}
|
|
413
350
|
|
|
414
351
|
function setupCharacterTab() {
|
|
@@ -479,7 +416,8 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
479
416
|
|
|
480
417
|
for (var i = 0; i < BLOCKS.length; i++) {
|
|
481
418
|
var type = BLOCKS[i];
|
|
482
|
-
|
|
419
|
+
let usePigeons = type === "cow_crossing" && currentTheme == THEMES.city
|
|
420
|
+
var block = usePigeons ? Blockly.mainWorkspace.newBlock("pigeon_crossing_IMAGE_ONLY") : Blockly.mainWorkspace.newBlock(type);
|
|
483
421
|
block.initSvg();
|
|
484
422
|
block.render();
|
|
485
423
|
|
|
@@ -545,6 +483,18 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
545
483
|
});
|
|
546
484
|
}
|
|
547
485
|
|
|
486
|
+
function setupDescriptionTab() {
|
|
487
|
+
tabs.description.setOnChange(function() {
|
|
488
|
+
transitionTab(tabs.description);
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
function setupHintTab() {
|
|
493
|
+
tabs.hint.setOnChange(function() {
|
|
494
|
+
transitionTab(tabs.hint);
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
|
|
548
498
|
function goToMapTab() {
|
|
549
499
|
tabs.map.select();
|
|
550
500
|
}
|
|
@@ -682,17 +632,27 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
682
632
|
return;
|
|
683
633
|
}
|
|
684
634
|
|
|
685
|
-
|
|
635
|
+
const nameInput = $('#levelNameInput')
|
|
636
|
+
const newName = nameInput.val();
|
|
686
637
|
if (!newName || newName === "") {
|
|
687
|
-
|
|
638
|
+
ocargo.Drawing.startPopup(
|
|
639
|
+
"Oh no!",
|
|
640
|
+
"No level title!",
|
|
641
|
+
"Sorry, you need to specify a title for your" +
|
|
642
|
+
" level to be saved.",
|
|
643
|
+
);
|
|
688
644
|
return;
|
|
689
645
|
}
|
|
690
646
|
|
|
691
|
-
|
|
692
|
-
|
|
647
|
+
const regex = /^[\w ]*$/;
|
|
648
|
+
const validString = regex.exec(nameInput.val());
|
|
693
649
|
if (!validString) {
|
|
694
|
-
ocargo.Drawing.startPopup(
|
|
695
|
-
|
|
650
|
+
ocargo.Drawing.startPopup(
|
|
651
|
+
"Oh no!",
|
|
652
|
+
"You used some invalid characters.",
|
|
653
|
+
"Try saving your level again using only" +
|
|
654
|
+
" letters and numbers."
|
|
655
|
+
);
|
|
696
656
|
return;
|
|
697
657
|
}
|
|
698
658
|
|
|
@@ -701,31 +661,37 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
701
661
|
}
|
|
702
662
|
|
|
703
663
|
// Test to see if we already have the level saved
|
|
704
|
-
|
|
705
|
-
|
|
664
|
+
const table = $("#saveLevelTable");
|
|
665
|
+
let existingId = -1;
|
|
706
666
|
|
|
707
|
-
for (
|
|
708
|
-
|
|
709
|
-
|
|
667
|
+
for (let i = 0; i < table[0].rows.length; i++) {
|
|
668
|
+
const row = table[0].rows[i];
|
|
669
|
+
const existingName = row.cells[0].innerHTML;
|
|
710
670
|
if (existingName === newName) {
|
|
711
671
|
existingId = row.getAttribute('value');
|
|
712
672
|
break;
|
|
713
673
|
}
|
|
714
674
|
}
|
|
715
675
|
|
|
716
|
-
if (existingId
|
|
676
|
+
if (existingId !== -1) {
|
|
717
677
|
if (!saveState.isCurrentLevel(existingId)) {
|
|
718
|
-
|
|
678
|
+
const onYes = function(){
|
|
719
679
|
saveLevelLocal(existingId);
|
|
720
|
-
$("#
|
|
680
|
+
$("#myModal").hide()
|
|
681
|
+
$("#ocargo-modal").hide()
|
|
721
682
|
};
|
|
722
|
-
|
|
723
|
-
$("#
|
|
683
|
+
const onNo = function(){
|
|
684
|
+
$("#myModal").hide()
|
|
685
|
+
$("#ocargo-modal").hide()
|
|
724
686
|
};
|
|
725
|
-
ocargo.Drawing.startYesNoPopup(
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
}
|
|
687
|
+
ocargo.Drawing.startYesNoPopup(
|
|
688
|
+
"Overwriting",
|
|
689
|
+
"Warning",
|
|
690
|
+
`Level ${newName} already exists. Are
|
|
691
|
+
you sure you want to overwrite it?`,
|
|
692
|
+
onYes,
|
|
693
|
+
onNo
|
|
694
|
+
);
|
|
729
695
|
} else {
|
|
730
696
|
saveLevelLocal(existingId);
|
|
731
697
|
}
|
|
@@ -766,7 +732,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
766
732
|
}
|
|
767
733
|
|
|
768
734
|
function setupShareTab() {
|
|
769
|
-
//
|
|
735
|
+
// Set up the behaviour for when the tab is selected
|
|
770
736
|
tabs.share.setOnChange(function() {
|
|
771
737
|
if (!isIndependentStudent() || !isLoggedIn("share") || !canShare() || !isLevelOwned()) {
|
|
772
738
|
restorePreviousTab();
|
|
@@ -797,25 +763,28 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
797
763
|
interpolate(
|
|
798
764
|
gettext('In %(map_icon)s%(map_label)s menu, click %(mark_start_icon)s%(mark_start_label)s and select a ' +
|
|
799
765
|
'square for your road to start from. The starting point can only be placed on dead ends. You need a ' +
|
|
800
|
-
'road first before adding a starting point. Make sure you use %(
|
|
801
|
-
'select
|
|
766
|
+
'road first before adding a starting point. Make sure you use %(add_house_icon)s%(add_house_label)s to ' +
|
|
767
|
+
'select houses for delivery. Setting a fuel level means the route will need to be short enough for the ' +
|
|
802
768
|
'fuel not to run out.'
|
|
803
769
|
), {
|
|
804
770
|
map_icon: ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/map.svg', 'popupIcon'),
|
|
805
771
|
map_label: '<b>' + gettext('Map') + '</b>',
|
|
806
772
|
mark_start_icon: ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/origin.svg', 'popupIcon'),
|
|
807
773
|
mark_start_label: '<b>' + gettext('Mark start') + '</b>',
|
|
808
|
-
|
|
809
|
-
|
|
774
|
+
add_house_icon: ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/add_house.svg', 'popupIcon'),
|
|
775
|
+
add_house_label: '<b>' + gettext('Add house') + '</b>'
|
|
810
776
|
},
|
|
811
777
|
true
|
|
812
778
|
),
|
|
813
779
|
interpolate(
|
|
814
780
|
gettext('To remove road, click the %(delete_road_icon)s%(delete_road_label)s button and select a section ' +
|
|
815
|
-
'to get rid of.'
|
|
781
|
+
'to get rid of. To remove a house for delivery, click the %(delete_house_icon)s%(delete_house_label)s button' +
|
|
782
|
+
'and select a house to get rid of.'
|
|
816
783
|
), {
|
|
817
784
|
delete_road_icon: ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/delete_road.svg', 'popupIcon'),
|
|
818
|
-
delete_road_label: '<b>' + gettext('Delete road') + '</b>'
|
|
785
|
+
delete_road_label: '<b>' + gettext('Delete road') + '</b>',
|
|
786
|
+
delete_house_icon: ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/delete_house.svg', 'popupIcon'),
|
|
787
|
+
delete_house_label: '<b>' + gettext('Delete house') + '</b>'
|
|
819
788
|
},
|
|
820
789
|
true
|
|
821
790
|
),
|
|
@@ -942,7 +911,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
942
911
|
var color = COW_GROUP_COLOR_PALETTE[(currentCowGroupId - 1) % COW_GROUP_COLOR_PALETTE.length];
|
|
943
912
|
var style = 'background-color: ' + color;
|
|
944
913
|
var value = 'group' + currentCowGroupId++;
|
|
945
|
-
var type = ocargo.Cow.WHITE;
|
|
914
|
+
var type = currentTheme == THEMES.city ? ocargo.Cow.PIGEON : ocargo.Cow.WHITE;
|
|
946
915
|
|
|
947
916
|
cowGroups[value] = {
|
|
948
917
|
id: value,
|
|
@@ -1045,8 +1014,8 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1045
1014
|
var windowWidth = $(window).width();
|
|
1046
1015
|
var windowHeight = $(window).height();
|
|
1047
1016
|
|
|
1048
|
-
var paperRightEdge =
|
|
1049
|
-
var paperBottomEdge =
|
|
1017
|
+
var paperRightEdge = EXTENDED_PAPER_WIDTH + $('#tools').width();
|
|
1018
|
+
var paperBottomEdge = EXTENDED_PAPER_HEIGHT;
|
|
1050
1019
|
|
|
1051
1020
|
var bottom = 50;
|
|
1052
1021
|
if(windowHeight > paperBottomEdge) {
|
|
@@ -1093,7 +1062,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1093
1062
|
} else {
|
|
1094
1063
|
closeTrashcan();
|
|
1095
1064
|
}
|
|
1096
|
-
|
|
1065
|
+
}
|
|
1097
1066
|
|
|
1098
1067
|
function openTrashcan() {
|
|
1099
1068
|
$('#trashcanLidOpen').css('display', 'block');
|
|
@@ -1116,8 +1085,8 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1116
1085
|
return originNode && originNode.coordinate.equals(coordinate);
|
|
1117
1086
|
}
|
|
1118
1087
|
|
|
1119
|
-
function
|
|
1120
|
-
return
|
|
1088
|
+
function isHouseCoordinate(coordinate) {
|
|
1089
|
+
return houseNodes.includes(ocargo.Node.findNodeByCoordinate(coordinate, nodes));
|
|
1121
1090
|
}
|
|
1122
1091
|
|
|
1123
1092
|
function isCoordinateOnGrid(coordinate) {
|
|
@@ -1182,7 +1151,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1182
1151
|
nodes = [];
|
|
1183
1152
|
strikeStart = null;
|
|
1184
1153
|
originNode = null;
|
|
1185
|
-
|
|
1154
|
+
houseNodes = [];
|
|
1186
1155
|
|
|
1187
1156
|
cowGroups = {};
|
|
1188
1157
|
currentCowGroupId = 1;
|
|
@@ -1238,7 +1207,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1238
1207
|
mark(coordinate, 'red', 0.7, true);
|
|
1239
1208
|
}
|
|
1240
1209
|
|
|
1241
|
-
function
|
|
1210
|
+
function markAsHouse(coordinate) {
|
|
1242
1211
|
mark(coordinate, 'blue', 0.7, true);
|
|
1243
1212
|
}
|
|
1244
1213
|
|
|
@@ -1258,8 +1227,8 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1258
1227
|
if (cows) {
|
|
1259
1228
|
for (var i = 0; i < cows.length; i++) {
|
|
1260
1229
|
var internalCow = cows[i];
|
|
1261
|
-
if (internalCow.
|
|
1262
|
-
mark(internalCow.
|
|
1230
|
+
if (internalCow.coordinate) {
|
|
1231
|
+
mark(internalCow.coordinate, internalCow.data.group.color, 0.3, true);
|
|
1263
1232
|
}
|
|
1264
1233
|
}
|
|
1265
1234
|
}
|
|
@@ -1278,8 +1247,10 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1278
1247
|
if (originNode) {
|
|
1279
1248
|
markAsOrigin(originNode.coordinate);
|
|
1280
1249
|
}
|
|
1281
|
-
if (
|
|
1282
|
-
|
|
1250
|
+
if (houseNodes.length > 0) {
|
|
1251
|
+
for (let i = 0; i < houseNodes.length; i++) {
|
|
1252
|
+
markAsHouse(houseNodes[i].coordinate);
|
|
1253
|
+
}
|
|
1283
1254
|
}
|
|
1284
1255
|
|
|
1285
1256
|
bringTrafficLightsToFront();
|
|
@@ -1358,10 +1329,11 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1358
1329
|
var prevStart = originNode.coordinate;
|
|
1359
1330
|
markAsBackground(prevStart);
|
|
1360
1331
|
}
|
|
1361
|
-
// Check if same as
|
|
1362
|
-
if (
|
|
1363
|
-
|
|
1332
|
+
// Check if same as a house node
|
|
1333
|
+
if (isHouseCoordinate(coordMap)) {
|
|
1334
|
+
houseNodes.splice(houseNodes.indexOf(ocargo.Node.findNodeByCoordinate(coordMap, nodes)), 1)
|
|
1364
1335
|
}
|
|
1336
|
+
|
|
1365
1337
|
markAsOrigin(coordMap);
|
|
1366
1338
|
var newStartIndex = ocargo.Node.findNodeIndexByCoordinate(coordMap, nodes);
|
|
1367
1339
|
|
|
@@ -1370,20 +1342,22 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1370
1342
|
nodes[newStartIndex] = nodes[0];
|
|
1371
1343
|
nodes[0] = temp;
|
|
1372
1344
|
originNode = nodes[0];
|
|
1373
|
-
} else if (mode === modes.
|
|
1374
|
-
if (destinationNode) {
|
|
1375
|
-
var prevEnd = destinationNode.coordinate;
|
|
1376
|
-
markAsBackground(prevEnd);
|
|
1377
|
-
}
|
|
1345
|
+
} else if (mode === modes.ADD_HOUSE_MODE && existingNode) {
|
|
1378
1346
|
// Check if same as starting node
|
|
1379
1347
|
if (isOriginCoordinate(coordMap)) {
|
|
1380
1348
|
originNode = null;
|
|
1381
1349
|
}
|
|
1382
|
-
|
|
1350
|
+
|
|
1351
|
+
markAsHouse(coordMap);
|
|
1383
1352
|
var newEnd = ocargo.Node.findNodeIndexByCoordinate(coordMap, nodes);
|
|
1384
|
-
|
|
1353
|
+
houseNodes.push(nodes[newEnd]);
|
|
1385
1354
|
|
|
1386
|
-
}
|
|
1355
|
+
} else if (mode === modes.DELETE_HOUSE_MODE && existingNode) {
|
|
1356
|
+
if (isHouseCoordinate(coordMap)) {
|
|
1357
|
+
houseNodes.splice(houseNodes.indexOf(ocargo.Node.findNodeByCoordinate(coordMap, nodes)), 1);
|
|
1358
|
+
markAsBackground(coordMap);
|
|
1359
|
+
}
|
|
1360
|
+
} else if (mode === modes.ADD_ROAD_MODE || mode === modes.DELETE_ROAD_MODE) {
|
|
1387
1361
|
strikeStart = coordMap;
|
|
1388
1362
|
markAsSelected(coordMap);
|
|
1389
1363
|
}
|
|
@@ -1405,17 +1379,19 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1405
1379
|
if (mode === modes.ADD_ROAD_MODE || mode === modes.DELETE_ROAD_MODE) {
|
|
1406
1380
|
if (strikeStart !== null) {
|
|
1407
1381
|
markTentativeRoad(coordMap);
|
|
1408
|
-
} else if (!isOriginCoordinate(coordMap) && !
|
|
1382
|
+
} else if (!isOriginCoordinate(coordMap) && !isHouseCoordinate(coordMap)) {
|
|
1409
1383
|
markAsHighlighted(coordMap);
|
|
1410
1384
|
}
|
|
1411
|
-
} else if (mode === modes.MARK_ORIGIN_MODE || mode === modes.
|
|
1385
|
+
} else if (mode === modes.MARK_ORIGIN_MODE || mode === modes.ADD_HOUSE_MODE || mode === modes.DELETE_HOUSE_MODE) {
|
|
1412
1386
|
var node = ocargo.Node.findNodeByCoordinate(coordMap, nodes);
|
|
1413
|
-
if (node &&
|
|
1414
|
-
if (mode === modes.
|
|
1387
|
+
if (node && originNode !== node && !houseNodes.includes(node)) {
|
|
1388
|
+
if (mode === modes.ADD_HOUSE_MODE) {
|
|
1415
1389
|
mark(coordMap, 'blue', 0.3, true);
|
|
1416
|
-
} else if (canPlaceCFC(node)) {
|
|
1390
|
+
} else if (mode === modes.MARK_ORIGIN_MODE && canPlaceCFC(node)) {
|
|
1417
1391
|
mark(coordMap, 'red', 0.5, true);
|
|
1418
1392
|
}
|
|
1393
|
+
} else if (node && houseNodes.includes(node) && mode === modes.DELETE_HOUSE_MODE) {
|
|
1394
|
+
mark(coordMap, 'blue', 0.3, true);
|
|
1419
1395
|
}
|
|
1420
1396
|
}
|
|
1421
1397
|
};
|
|
@@ -1429,14 +1405,17 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1429
1405
|
var coordPaper = getCoordinateFromBBox(getBBox);
|
|
1430
1406
|
var coordMap = ocargo.Drawing.translate(coordPaper);
|
|
1431
1407
|
|
|
1432
|
-
if (mode === modes.MARK_ORIGIN_MODE || mode === modes.
|
|
1408
|
+
if (mode === modes.MARK_ORIGIN_MODE || mode === modes.ADD_HOUSE_MODE || mode === modes.DELETE_HOUSE_MODE) {
|
|
1433
1409
|
var node = ocargo.Node.findNodeByCoordinate(coordMap, nodes);
|
|
1434
|
-
if (node &&
|
|
1410
|
+
if (node && originNode !== node && !houseNodes.includes(node)) {
|
|
1435
1411
|
markAsBackground(coordMap);
|
|
1436
1412
|
markCowNodes();
|
|
1413
|
+
} else if (node && houseNodes.includes(node)) {
|
|
1414
|
+
markAsHouse(coordMap);
|
|
1415
|
+
markCowNodes();
|
|
1437
1416
|
}
|
|
1438
1417
|
} else if (mode === modes.ADD_ROAD_MODE || mode === modes.DELETE_ROAD_MODE) {
|
|
1439
|
-
if (!isOriginCoordinate(coordMap) && !
|
|
1418
|
+
if (!isOriginCoordinate(coordMap) && !isHouseCoordinate(coordMap)) {
|
|
1440
1419
|
markAsBackground(coordMap);
|
|
1441
1420
|
markCowNodes();
|
|
1442
1421
|
}
|
|
@@ -1492,6 +1471,23 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1492
1471
|
};
|
|
1493
1472
|
}
|
|
1494
1473
|
|
|
1474
|
+
function draggedObjectOnGrid(e, dragged_object) {
|
|
1475
|
+
// object location is relative to the whole page, so need to factor in paper and padding size, grid canvas scroll amount, width of toolbar, etc.
|
|
1476
|
+
return e.pageX >= (TAB_PANE_WIDTH + PAPER_PADDING)
|
|
1477
|
+
&& (e.pageY + paper.scrollTop() + dragged_object.height / 2) <= (PAPER_HEIGHT + PAPER_PADDING)
|
|
1478
|
+
&& (e.pageX + paper.scrollLeft() + dragged_object.width / 2) <= (TAB_PANE_WIDTH + PAPER_WIDTH + PAPER_PADDING)
|
|
1479
|
+
}
|
|
1480
|
+
|
|
1481
|
+
function getAbsCoordinates(e) {
|
|
1482
|
+
const absX = (e.pageX + paper.scrollLeft() - TAB_PANE_WIDTH) / GRID_SPACE_SIZE;
|
|
1483
|
+
const absY = (e.pageY + paper.scrollTop()) / GRID_SPACE_SIZE;
|
|
1484
|
+
return [absX, absY];
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
function draggedCursorOverGrid(absX, absY) {
|
|
1488
|
+
return absY <= SEMI_EXTENDED_PAPER_HEIGHT / 100 && absX <= EXTENDED_PAPER_WIDTH / 100 && absX >= 0
|
|
1489
|
+
}
|
|
1490
|
+
|
|
1495
1491
|
function setupDecorListeners(decor) {
|
|
1496
1492
|
var image = decor.image;
|
|
1497
1493
|
|
|
@@ -1517,14 +1513,14 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1517
1513
|
// Stop it being dragged off the edge of the page
|
|
1518
1514
|
if (paperX < 0) {
|
|
1519
1515
|
paperX = 0;
|
|
1520
|
-
} else if (paperX + imageWidth >
|
|
1521
|
-
paperX =
|
|
1516
|
+
} else if (paperX + imageWidth > EXTENDED_PAPER_WIDTH) {
|
|
1517
|
+
paperX = EXTENDED_PAPER_WIDTH - imageWidth;
|
|
1522
1518
|
}
|
|
1523
1519
|
|
|
1524
1520
|
if (paperY < 0) {
|
|
1525
1521
|
paperY = 0;
|
|
1526
|
-
} else if (paperY + imageHeight >
|
|
1527
|
-
paperY =
|
|
1522
|
+
} else if (paperY + imageHeight > EXTENDED_PAPER_HEIGHT) {
|
|
1523
|
+
paperY = EXTENDED_PAPER_HEIGHT - imageHeight;
|
|
1528
1524
|
}
|
|
1529
1525
|
|
|
1530
1526
|
image.transform('t' + paperX + ',' + paperY);
|
|
@@ -1547,8 +1543,17 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1547
1543
|
originX = paperX;
|
|
1548
1544
|
originY = paperY;
|
|
1549
1545
|
|
|
1550
|
-
if(trashcanOpen) {
|
|
1546
|
+
if (trashcanOpen) {
|
|
1551
1547
|
decor.destroy();
|
|
1548
|
+
} else {
|
|
1549
|
+
if (paperWidth < paperX + imageWidth) {
|
|
1550
|
+
originX = paperWidth - imageWidth;
|
|
1551
|
+
}
|
|
1552
|
+
if (paperHeight < paperY + imageHeight) {
|
|
1553
|
+
originY = paperHeight - imageHeight;
|
|
1554
|
+
}
|
|
1555
|
+
|
|
1556
|
+
image.transform('t' + originX + ',' + originY);
|
|
1552
1557
|
}
|
|
1553
1558
|
|
|
1554
1559
|
closeTrashcan();
|
|
@@ -1558,6 +1563,47 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1558
1563
|
addReleaseListeners(image.node);
|
|
1559
1564
|
}
|
|
1560
1565
|
|
|
1566
|
+
function handleDraggableDecorMouseDown(e){
|
|
1567
|
+
e.preventDefault();
|
|
1568
|
+
|
|
1569
|
+
window.dragged_decor = {};
|
|
1570
|
+
dragged_decor.pageX0 = e.pageX;
|
|
1571
|
+
dragged_decor.pageY0 = e.pageY;
|
|
1572
|
+
dragged_decor.elem = this;
|
|
1573
|
+
dragged_decor.offset0 = $(this).offset();
|
|
1574
|
+
dragged_decor.width = parseInt(currentTheme.decor[this.id].width);
|
|
1575
|
+
dragged_decor.height = parseInt(currentTheme.decor[this.id].height);
|
|
1576
|
+
dragged_decor.parent = this.parentElement;
|
|
1577
|
+
|
|
1578
|
+
const clone = $(this).clone(true);
|
|
1579
|
+
|
|
1580
|
+
function handleDraggableDecorDragging(e){
|
|
1581
|
+
const left = dragged_decor.offset0.left + (e.pageX - dragged_decor.pageX0);
|
|
1582
|
+
const top = dragged_decor.offset0.top + (e.pageY - dragged_decor.pageY0);
|
|
1583
|
+
$(dragged_decor.elem).offset({top: top, left: left});
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
function handleDraggableDecorMouseUp(e){
|
|
1587
|
+
if (dragged_decor.elem.id !== null) {
|
|
1588
|
+
if (draggedObjectOnGrid(e, dragged_decor)) {
|
|
1589
|
+
let decorObject = new InternalDecor(dragged_decor.elem.id);
|
|
1590
|
+
decorObject.setPosition(e.pageX + paper.scrollLeft() - TAB_PANE_WIDTH - dragged_decor.width / 2, e.pageY + paper.scrollTop() - dragged_decor.height / 2);
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
$(document)
|
|
1595
|
+
.off('mousemove', handleDraggableDecorDragging)
|
|
1596
|
+
.off('mouseup mouseleave', handleDraggableDecorMouseUp);
|
|
1597
|
+
|
|
1598
|
+
$(dragged_decor.elem).remove();
|
|
1599
|
+
$(clone).appendTo(dragged_decor.parent);
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1602
|
+
$(document)
|
|
1603
|
+
.on('mouseup mouseleave', handleDraggableDecorMouseUp)
|
|
1604
|
+
.on('mousemove', handleDraggableDecorDragging);
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1561
1607
|
function setupCowListeners(cow) {
|
|
1562
1608
|
var image = cow.image;
|
|
1563
1609
|
|
|
@@ -1598,61 +1644,27 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1598
1644
|
// Stop it being dragged off the edge of the page
|
|
1599
1645
|
if (paperX < 0) {
|
|
1600
1646
|
paperX = 0;
|
|
1601
|
-
} else if (paperX + imageWidth >
|
|
1602
|
-
paperX =
|
|
1647
|
+
} else if (paperX + imageWidth > EXTENDED_PAPER_WIDTH) {
|
|
1648
|
+
paperX = EXTENDED_PAPER_WIDTH - imageWidth;
|
|
1603
1649
|
}
|
|
1604
1650
|
if (paperY < 0) {
|
|
1605
1651
|
paperY = 0;
|
|
1606
|
-
} else if (paperY + imageHeight >
|
|
1607
|
-
paperY =
|
|
1652
|
+
} else if (paperY + imageHeight > EXTENDED_PAPER_HEIGHT) {
|
|
1653
|
+
paperY = EXTENDED_PAPER_HEIGHT - imageHeight;
|
|
1608
1654
|
}
|
|
1609
1655
|
|
|
1610
1656
|
// And perform the updatee
|
|
1611
1657
|
image.transform('t' + paperX + ',' + paperY );
|
|
1612
1658
|
|
|
1613
1659
|
//Unmark the squares the cow previously occupied
|
|
1614
|
-
|
|
1615
|
-
markAsBackground(controlledCoord);
|
|
1616
|
-
}
|
|
1617
|
-
if(cows) {
|
|
1618
|
-
for( var i = 0; i < cows.length; i++){
|
|
1619
|
-
var internalCow = cows[i];
|
|
1620
|
-
if(internalCow !== cow && internalCow.controlledNode) {
|
|
1621
|
-
mark(internalCow.controlledNode.coordinate, internalCow.data.group.color, 0.3, true);
|
|
1622
|
-
}
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
if (originNode) {
|
|
1626
|
-
markAsOrigin(originNode.coordinate);
|
|
1627
|
-
}
|
|
1628
|
-
if (destinationNode) {
|
|
1629
|
-
markAsDestination(destinationNode.coordinate);
|
|
1630
|
-
}
|
|
1660
|
+
unmarkOldCowSquare(controlledCoord, cow);
|
|
1631
1661
|
|
|
1632
1662
|
// Now calculate the source coordinate
|
|
1633
1663
|
var box = image.getBBox();
|
|
1634
1664
|
var absX = (box.x + box.width/2) / GRID_SPACE_SIZE;
|
|
1635
1665
|
var absY = (box.y + box.height/2) / GRID_SPACE_SIZE;
|
|
1636
1666
|
|
|
1637
|
-
|
|
1638
|
-
var y = GRID_HEIGHT - Math.min(Math.max(0, Math.floor(absY)), GRID_HEIGHT - 1) - 1;
|
|
1639
|
-
controlledCoord = new ocargo.Coordinate(x,y);
|
|
1640
|
-
|
|
1641
|
-
// If source node is not on grid remove it
|
|
1642
|
-
if (!isCoordinateOnGrid(controlledCoord)) {
|
|
1643
|
-
controlledCoord = null;
|
|
1644
|
-
}
|
|
1645
|
-
|
|
1646
|
-
if (controlledCoord) {
|
|
1647
|
-
var colour;
|
|
1648
|
-
if(isValidPlacement(controlledCoord)) {
|
|
1649
|
-
colour = VALID_LIGHT_COLOUR;
|
|
1650
|
-
} else {
|
|
1651
|
-
colour = INVALID_LIGHT_COLOUR;
|
|
1652
|
-
}
|
|
1653
|
-
|
|
1654
|
-
mark(controlledCoord, colour, 0.7, false);
|
|
1655
|
-
}
|
|
1667
|
+
controlledCoord = markNewCowSquare(absX, absY, controlledCoord, cow);
|
|
1656
1668
|
|
|
1657
1669
|
// Deal with trashcan
|
|
1658
1670
|
var paperAbsX = paperX - paper.scrollLeft() + imageWidth/2;
|
|
@@ -1669,6 +1681,8 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1669
1681
|
}
|
|
1670
1682
|
|
|
1671
1683
|
function onDragStart(x, y) {
|
|
1684
|
+
// cow shouldn't be in the cow group during dragging
|
|
1685
|
+
removeCowFromCowList(cow);
|
|
1672
1686
|
var bBox = image.getBBox();
|
|
1673
1687
|
imageWidth = bBox.width;
|
|
1674
1688
|
imageHeight = bBox.height;
|
|
@@ -1684,56 +1698,62 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1684
1698
|
}
|
|
1685
1699
|
|
|
1686
1700
|
function onDragEnd() {
|
|
1687
|
-
//Unmark previously occupied square
|
|
1688
|
-
if(cow.controlledNode) {
|
|
1689
|
-
markAsBackground(cow.controlledNode.coordinate);
|
|
1690
|
-
}
|
|
1691
|
-
|
|
1692
|
-
// Mark squares currently occupied
|
|
1693
|
-
if (controlledCoord) {
|
|
1694
|
-
mark(controlledCoord, cow.data.group.color, 0.3, true);
|
|
1695
|
-
}
|
|
1696
|
-
if (originNode) {
|
|
1697
|
-
markAsOrigin(originNode.coordinate);
|
|
1698
|
-
}
|
|
1699
|
-
if (destinationNode) {
|
|
1700
|
-
markAsDestination(destinationNode.coordinate);
|
|
1701
|
-
}
|
|
1702
1701
|
|
|
1703
|
-
if(trashcanOpen) {
|
|
1702
|
+
if (trashcanOpen) {
|
|
1704
1703
|
cow.destroy();
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
var controlledNode = ocargo.Node.findNodeByCoordinate(controlledCoord, nodes);
|
|
1708
|
-
cow.controlledNode = controlledNode;
|
|
1709
|
-
cow.valid = true;
|
|
1710
|
-
drawing.setCowImagePosition(controlledCoord, image, controlledNode);
|
|
1704
|
+
unmarkOldCowSquare(controlledCoord, cow);
|
|
1705
|
+
closeTrashcan();
|
|
1711
1706
|
} else {
|
|
1712
|
-
cow
|
|
1713
|
-
cow
|
|
1714
|
-
|
|
1715
|
-
|
|
1707
|
+
setCowMarkingsOnMouseUp(controlledCoord, cow);
|
|
1708
|
+
cows.push(cow);
|
|
1709
|
+
cow.coordinate = controlledCoord;
|
|
1710
|
+
cow.valid = isValidDraggedCowPlacement(controlledCoord, cow);
|
|
1711
|
+
if (cow.isOnRoad()) {
|
|
1712
|
+
const controlledNode = ocargo.Node.findNodeByCoordinate(controlledCoord, nodes);
|
|
1713
|
+
drawing.setCowImagePosition(controlledCoord, image, controlledNode);
|
|
1714
|
+
}
|
|
1715
|
+
else {
|
|
1716
|
+
var cowX = paperX;
|
|
1717
|
+
var cowY = paperY;
|
|
1716
1718
|
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1719
|
+
if (paperWidth < paperX + imageWidth) {
|
|
1720
|
+
cowX = paperWidth - imageWidth
|
|
1721
|
+
}
|
|
1720
1722
|
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
if (otherCow.controlledNode == controlledNode && cow != otherCow)
|
|
1728
|
-
return false;
|
|
1723
|
+
if (paperHeight < paperY + imageHeight) {
|
|
1724
|
+
cowY = paperHeight - imageHeight
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1727
|
+
image.transform('t' + cowX + ',' + cowY);
|
|
1728
|
+
}
|
|
1729
1729
|
}
|
|
1730
|
-
|
|
1730
|
+
|
|
1731
|
+
adjustCowGroupMinMaxFields(cow);
|
|
1732
|
+
image.attr({'cursor':'pointer'});
|
|
1731
1733
|
}
|
|
1732
1734
|
|
|
1733
1735
|
image.drag(onDragMove, onDragStart, onDragEnd);
|
|
1734
1736
|
addReleaseListeners(image.node);
|
|
1735
1737
|
}
|
|
1736
1738
|
|
|
1739
|
+
function removeCowFromCowList(cow) {
|
|
1740
|
+
var index = cows.indexOf(cow);
|
|
1741
|
+
if (index > -1) {
|
|
1742
|
+
cows.splice(index, 1);
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
function isValidDraggedCowPlacement(controlledCoord, cow){
|
|
1747
|
+
if (isOriginCoordinate(controlledCoord) || isHouseCoordinate(controlledCoord))
|
|
1748
|
+
return false;
|
|
1749
|
+
for (var i=0; i < cows.length; i++) {
|
|
1750
|
+
var otherCow = cows[i];
|
|
1751
|
+
if (cow != otherCow && otherCow.coordinate && otherCow.coordinate.equals(controlledCoord))
|
|
1752
|
+
return false;
|
|
1753
|
+
}
|
|
1754
|
+
return true;
|
|
1755
|
+
}
|
|
1756
|
+
|
|
1737
1757
|
function adjustCowGroupMinMaxFields(draggedCow) {
|
|
1738
1758
|
var draggedCowGroupId = draggedCow.data.group.id;
|
|
1739
1759
|
|
|
@@ -1750,6 +1770,131 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1750
1770
|
$('#cow_group_select').val(draggedCowGroupId).change();
|
|
1751
1771
|
}
|
|
1752
1772
|
|
|
1773
|
+
function unmarkOldCowSquare(controlledCoord, cow = "undefined") {
|
|
1774
|
+
if (controlledCoord) {
|
|
1775
|
+
markAsBackground(controlledCoord);
|
|
1776
|
+
}
|
|
1777
|
+
if (originNode) {
|
|
1778
|
+
markAsOrigin(originNode.coordinate);
|
|
1779
|
+
}
|
|
1780
|
+
if (houseNodes.length > 0) {
|
|
1781
|
+
for (let i = 0; i < houseNodes.length; i++){
|
|
1782
|
+
markAsHouse(houseNodes[i].coordinate);
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
function setCowMarkingsOnMouseUp(controlledCoord, cow) {
|
|
1788
|
+
if (cow.isOnRoad()) {
|
|
1789
|
+
markAsBackground(cow.coordinate);
|
|
1790
|
+
}
|
|
1791
|
+
if (controlledCoord) {
|
|
1792
|
+
mark(controlledCoord, cow.data.group.color, 0.3, true);
|
|
1793
|
+
}
|
|
1794
|
+
if (originNode) {
|
|
1795
|
+
markAsOrigin(originNode.coordinate);
|
|
1796
|
+
}
|
|
1797
|
+
if (houseNodes.length > 0) {
|
|
1798
|
+
for (let i = 0; i < houseNodes.length; i++) {
|
|
1799
|
+
markAsHouse(houseNodes[i].coordinate);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
function markNewCowSquare(absX, absY, controlledCoord, cow = "undefined") {
|
|
1805
|
+
const x = Math.min(Math.max(0, Math.floor(absX)), GRID_WIDTH - 1);
|
|
1806
|
+
const y = GRID_HEIGHT - Math.min(Math.max(0, Math.floor(absY)), GRID_HEIGHT - 1) - 1;
|
|
1807
|
+
controlledCoord = new ocargo.Coordinate(x,y);
|
|
1808
|
+
|
|
1809
|
+
// If source node is not on grid remove it
|
|
1810
|
+
if (!isCoordinateOnGrid(controlledCoord)) {
|
|
1811
|
+
controlledCoord = null;
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
// mark square valid or invalid
|
|
1815
|
+
if (controlledCoord) {
|
|
1816
|
+
let colour;
|
|
1817
|
+
if(isValidDraggedCowPlacement(controlledCoord, cow)) {
|
|
1818
|
+
colour = VALID_LIGHT_COLOUR;
|
|
1819
|
+
} else {
|
|
1820
|
+
colour = INVALID_LIGHT_COLOUR;
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
mark(controlledCoord, colour, 0.7, false);
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
return controlledCoord;
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
function handleDraggableCowMouseDown(e, cowGroup){
|
|
1830
|
+
e.preventDefault();
|
|
1831
|
+
|
|
1832
|
+
window.dragged_cow = {};
|
|
1833
|
+
dragged_cow.pageX0 = e.pageX;
|
|
1834
|
+
dragged_cow.pageY0 = e.pageY;
|
|
1835
|
+
dragged_cow.elem = e.target;
|
|
1836
|
+
dragged_cow.offset0 = $(e.target).offset();
|
|
1837
|
+
dragged_cow.parent = e.target.parentElement;
|
|
1838
|
+
dragged_cow.group = cowGroups[cowGroup];
|
|
1839
|
+
dragged_cow.width = COW_WIDTH;
|
|
1840
|
+
dragged_cow.height = COW_HEIGHT;
|
|
1841
|
+
|
|
1842
|
+
const clone = $(e.target).clone(true);
|
|
1843
|
+
let controlledCoord;
|
|
1844
|
+
|
|
1845
|
+
function handleDraggableCowDragging(e){
|
|
1846
|
+
e.target.style.cursor = "pointer";
|
|
1847
|
+
|
|
1848
|
+
const left = dragged_cow.offset0.left + (e.pageX - dragged_cow.pageX0);
|
|
1849
|
+
const top = dragged_cow.offset0.top + (e.pageY - dragged_cow.pageY0);
|
|
1850
|
+
$(dragged_cow.elem).offset({top: top, left: left});
|
|
1851
|
+
|
|
1852
|
+
unmarkOldCowSquare(controlledCoord);
|
|
1853
|
+
|
|
1854
|
+
const [absX, absY] = getAbsCoordinates(e);
|
|
1855
|
+
if (draggedCursorOverGrid(absX, absY)) {
|
|
1856
|
+
controlledCoord = markNewCowSquare(absX, absY, controlledCoord);
|
|
1857
|
+
}
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
function handleDraggableCowMouseUp(e){
|
|
1861
|
+
let internalCow = new InternalCow({group: cowGroups["group1"]});
|
|
1862
|
+
let image = internalCow.image;
|
|
1863
|
+
internalCow.coordinate = controlledCoord;
|
|
1864
|
+
internalCow.valid = isValidDraggedCowPlacement(controlledCoord, internalCow);
|
|
1865
|
+
|
|
1866
|
+
if (internalCow.isOnRoad()) {
|
|
1867
|
+
const controlledNode = ocargo.Node.findNodeByCoordinate(controlledCoord, nodes);
|
|
1868
|
+
drawing.setCowImagePosition(controlledCoord, image, controlledNode);
|
|
1869
|
+
} else {
|
|
1870
|
+
const cowX = e.pageX + paper.scrollLeft() - TAB_PANE_WIDTH - dragged_cow.width / 2;
|
|
1871
|
+
const cowY = e.pageY + paper.scrollTop() - dragged_cow.height / 2;
|
|
1872
|
+
|
|
1873
|
+
if (draggedObjectOnGrid(e, dragged_cow)) {
|
|
1874
|
+
image.transform('t' + cowX + ',' + cowY);
|
|
1875
|
+
} else {
|
|
1876
|
+
internalCow.destroy();
|
|
1877
|
+
}
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
if (!trashcanOpen) {
|
|
1881
|
+
setCowMarkingsOnMouseUp(controlledCoord, internalCow);
|
|
1882
|
+
adjustCowGroupMinMaxFields(internalCow);
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
$(document)
|
|
1886
|
+
.off('mousemove', handleDraggableCowDragging)
|
|
1887
|
+
.off('mouseup mouseleave', handleDraggableCowMouseUp);
|
|
1888
|
+
|
|
1889
|
+
$(dragged_cow.elem).remove();
|
|
1890
|
+
$(clone).appendTo(dragged_cow.parent);
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
$(document)
|
|
1894
|
+
.on('mouseup mouseleave', handleDraggableCowMouseUp)
|
|
1895
|
+
.on('mousemove', handleDraggableCowDragging);
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1753
1898
|
|
|
1754
1899
|
function setupTrafficLightListeners(trafficLight) {
|
|
1755
1900
|
var image = trafficLight.image;
|
|
@@ -1801,34 +1946,20 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1801
1946
|
// Stop it being dragged off the edge of the page
|
|
1802
1947
|
if (paperX < 0) {
|
|
1803
1948
|
paperX = 0;
|
|
1804
|
-
} else if (paperX + imageWidth >
|
|
1805
|
-
paperX =
|
|
1949
|
+
} else if (paperX + imageWidth > EXTENDED_PAPER_WIDTH) {
|
|
1950
|
+
paperX = EXTENDED_PAPER_WIDTH - imageWidth;
|
|
1806
1951
|
}
|
|
1807
1952
|
if (paperY < 0) {
|
|
1808
1953
|
paperY = 0;
|
|
1809
|
-
} else if (paperY + imageHeight >
|
|
1810
|
-
paperY =
|
|
1954
|
+
} else if (paperY + imageHeight > EXTENDED_PAPER_HEIGHT) {
|
|
1955
|
+
paperY = EXTENDED_PAPER_HEIGHT - imageHeight;
|
|
1811
1956
|
}
|
|
1812
1957
|
|
|
1813
|
-
// And perform the
|
|
1958
|
+
// And perform the update
|
|
1814
1959
|
image.transform('t' + paperX + ',' + paperY + 'r' + rotation + 's' + scaling);
|
|
1815
1960
|
|
|
1816
1961
|
// Unmark the squares the light previously occupied
|
|
1817
|
-
|
|
1818
|
-
markAsBackground(sourceCoord);
|
|
1819
|
-
}
|
|
1820
|
-
if (controlledCoord) {
|
|
1821
|
-
markAsBackground(controlledCoord);
|
|
1822
|
-
}
|
|
1823
|
-
|
|
1824
|
-
markCowNodes();
|
|
1825
|
-
|
|
1826
|
-
if (originNode) {
|
|
1827
|
-
markAsOrigin(originNode.coordinate);
|
|
1828
|
-
}
|
|
1829
|
-
if (destinationNode) {
|
|
1830
|
-
markAsDestination(destinationNode.coordinate);
|
|
1831
|
-
}
|
|
1962
|
+
unmarkOldTrafficLightSquare(sourceCoord, controlledCoord);
|
|
1832
1963
|
|
|
1833
1964
|
// Now calculate the source coordinate
|
|
1834
1965
|
var box = image.getBBox();
|
|
@@ -1850,48 +1981,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1850
1981
|
break;
|
|
1851
1982
|
}
|
|
1852
1983
|
|
|
1853
|
-
|
|
1854
|
-
var y = GRID_HEIGHT - Math.min(Math.max(0, Math.floor(absY)), GRID_HEIGHT - 1) - 1;
|
|
1855
|
-
sourceCoord = new ocargo.Coordinate(x,y);
|
|
1856
|
-
|
|
1857
|
-
// Find controlled position in map coordinates
|
|
1858
|
-
switch(rotation) {
|
|
1859
|
-
case 0:
|
|
1860
|
-
controlledCoord = new ocargo.Coordinate(sourceCoord.x, sourceCoord.y + 1);
|
|
1861
|
-
break;
|
|
1862
|
-
case 90:
|
|
1863
|
-
controlledCoord = new ocargo.Coordinate(sourceCoord.x + 1, sourceCoord.y);
|
|
1864
|
-
break;
|
|
1865
|
-
case 180:
|
|
1866
|
-
controlledCoord = new ocargo.Coordinate(sourceCoord.x, sourceCoord.y - 1);
|
|
1867
|
-
break;
|
|
1868
|
-
case 270:
|
|
1869
|
-
controlledCoord = new ocargo.Coordinate(sourceCoord.x - 1, sourceCoord.y);
|
|
1870
|
-
break;
|
|
1871
|
-
}
|
|
1872
|
-
|
|
1873
|
-
// If controlled node is not on grid, remove it
|
|
1874
|
-
if (!isCoordinateOnGrid(controlledCoord)) {
|
|
1875
|
-
controlledCoord = null;
|
|
1876
|
-
}
|
|
1877
|
-
|
|
1878
|
-
// If source node is not on grid remove it
|
|
1879
|
-
if (!isCoordinateOnGrid(sourceCoord)) {
|
|
1880
|
-
sourceCoord = null;
|
|
1881
|
-
}
|
|
1882
|
-
|
|
1883
|
-
if (sourceCoord && controlledCoord) {
|
|
1884
|
-
var colour;
|
|
1885
|
-
if(isValidPlacement(sourceCoord, controlledCoord)) {
|
|
1886
|
-
colour = VALID_LIGHT_COLOUR;
|
|
1887
|
-
drawing.setTrafficLightImagePosition(sourceCoord, controlledCoord, image);
|
|
1888
|
-
} else {
|
|
1889
|
-
colour = INVALID_LIGHT_COLOUR;
|
|
1890
|
-
}
|
|
1891
|
-
|
|
1892
|
-
mark(controlledCoord, colour, 0.7, false);
|
|
1893
|
-
mark(sourceCoord, colour, 0.7, false);
|
|
1894
|
-
}
|
|
1984
|
+
[sourceCoord, controlledCoord] = markNewTrafficLightSquare(absX, absY, isValidTrafficLightPlacement, sourceCoord, controlledCoord, rotation, image);
|
|
1895
1985
|
|
|
1896
1986
|
// Deal with trashcan
|
|
1897
1987
|
var paperAbsX = paperX - paper.scrollLeft() + imageWidth/2;
|
|
@@ -1931,31 +2021,29 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1931
2021
|
|
|
1932
2022
|
function onDragEnd() {
|
|
1933
2023
|
// Unmark squares currently occupied
|
|
1934
|
-
|
|
1935
|
-
markAsBackground(sourceCoord);
|
|
1936
|
-
}
|
|
1937
|
-
if (controlledCoord) {
|
|
1938
|
-
markAsBackground(controlledCoord);
|
|
1939
|
-
}
|
|
1940
|
-
|
|
1941
|
-
markCowNodes();
|
|
1942
|
-
|
|
1943
|
-
if (originNode) {
|
|
1944
|
-
markAsOrigin(originNode.coordinate);
|
|
1945
|
-
}
|
|
1946
|
-
if (destinationNode) {
|
|
1947
|
-
markAsDestination(destinationNode.coordinate);
|
|
1948
|
-
}
|
|
2024
|
+
unmarkOldTrafficLightSquare(sourceCoord, controlledCoord);
|
|
1949
2025
|
|
|
1950
2026
|
if(trashcanOpen) {
|
|
1951
2027
|
trafficLight.destroy();
|
|
1952
|
-
} else if(
|
|
2028
|
+
} else if(isValidTrafficLightPlacement(sourceCoord, controlledCoord)) {
|
|
1953
2029
|
// Add back to the list of traffic lights if on valid nodes
|
|
1954
2030
|
trafficLight.sourceNode = ocargo.Node.findNodeByCoordinate(sourceCoord, nodes);
|
|
1955
2031
|
trafficLight.controlledNode = ocargo.Node.findNodeByCoordinate(controlledCoord, nodes);
|
|
1956
2032
|
trafficLight.valid = true;
|
|
1957
2033
|
|
|
1958
2034
|
drawing.setTrafficLightImagePosition(sourceCoord, controlledCoord, image);
|
|
2035
|
+
} else {
|
|
2036
|
+
var trafficLightX = paperX;
|
|
2037
|
+
var trafficLightY = paperY;
|
|
2038
|
+
|
|
2039
|
+
if (paperWidth < paperX + imageWidth) {
|
|
2040
|
+
trafficLightX = paperWidth - imageWidth
|
|
2041
|
+
image.transform('t' + trafficLightX + ',' + trafficLightY + 'r' + rotation + 's' + scaling);
|
|
2042
|
+
}
|
|
2043
|
+
if (paperHeight < paperY + imageHeight) {
|
|
2044
|
+
trafficLightY = paperHeight - imageHeight
|
|
2045
|
+
image.transform('t' + trafficLightX + ',' + trafficLightY + 'r' + rotation + 's' + scaling);
|
|
2046
|
+
}
|
|
1959
2047
|
}
|
|
1960
2048
|
|
|
1961
2049
|
image.attr({'cursor':'pointer'});
|
|
@@ -1986,41 +2074,177 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
1986
2074
|
}
|
|
1987
2075
|
return "0,0";
|
|
1988
2076
|
}
|
|
2077
|
+
}
|
|
1989
2078
|
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
2079
|
+
function isValidTrafficLightPlacement(sourceCoord, controlledCoord) {
|
|
2080
|
+
var sourceNode = ocargo.Node.findNodeByCoordinate(sourceCoord, nodes);
|
|
2081
|
+
var controlledNode = ocargo.Node.findNodeByCoordinate(controlledCoord, nodes);
|
|
1993
2082
|
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
}
|
|
2083
|
+
// Test if two connected nodes exist
|
|
2084
|
+
var connected = false;
|
|
2085
|
+
if (sourceNode && controlledNode) {
|
|
2086
|
+
for (var i = 0; i < sourceNode.connectedNodes.length; i++) {
|
|
2087
|
+
if (sourceNode.connectedNodes[i] === controlledNode) {
|
|
2088
|
+
connected = true;
|
|
2089
|
+
break;
|
|
2002
2090
|
}
|
|
2003
2091
|
}
|
|
2092
|
+
}
|
|
2004
2093
|
|
|
2005
|
-
|
|
2094
|
+
if(!connected) {
|
|
2095
|
+
return false;
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
// Test it's not already occupied
|
|
2099
|
+
for(var i = 0; i < trafficLights.length; i++) {
|
|
2100
|
+
var tl = trafficLights[i];
|
|
2101
|
+
if(tl.valid &&
|
|
2102
|
+
((tl.sourceNode === sourceNode && tl.controlledNode === controlledNode) ||
|
|
2103
|
+
(tl.sourceNode === controlledNode && tl.controlledNode === sourceNode))) {
|
|
2006
2104
|
return false;
|
|
2007
2105
|
}
|
|
2106
|
+
}
|
|
2107
|
+
return true;
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
function unmarkOldTrafficLightSquare(sourceCoord, controlledCoord) {
|
|
2111
|
+
// Unmark the squares the light previously occupied
|
|
2112
|
+
if (sourceCoord) {
|
|
2113
|
+
markAsBackground(sourceCoord);
|
|
2114
|
+
}
|
|
2115
|
+
if (controlledCoord) {
|
|
2116
|
+
markAsBackground(controlledCoord);
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
markCowNodes();
|
|
2120
|
+
|
|
2121
|
+
if (originNode) {
|
|
2122
|
+
markAsOrigin(originNode.coordinate);
|
|
2123
|
+
}
|
|
2124
|
+
if (houseNodes.length > 0) {
|
|
2125
|
+
for (let i = 0; i < houseNodes.length; i++) {
|
|
2126
|
+
markAsHouse(houseNodes[i].coordinate);
|
|
2127
|
+
}
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2131
|
+
function markNewTrafficLightSquare(absX, absY, validityCheckFunction, sourceCoord, controlledCoord, rotation, image = "undefined") {
|
|
2132
|
+
var x = Math.min(Math.max(0, Math.floor(absX)), GRID_WIDTH - 1);
|
|
2133
|
+
var y = GRID_HEIGHT - Math.min(Math.max(0, Math.floor(absY)), GRID_HEIGHT - 1) - 1;
|
|
2134
|
+
sourceCoord = new ocargo.Coordinate(x,y);
|
|
2135
|
+
|
|
2136
|
+
// Find controlled position in map coordinates
|
|
2137
|
+
switch(rotation) {
|
|
2138
|
+
case 0:
|
|
2139
|
+
controlledCoord = new ocargo.Coordinate(sourceCoord.x, sourceCoord.y + 1);
|
|
2140
|
+
break;
|
|
2141
|
+
case 90:
|
|
2142
|
+
controlledCoord = new ocargo.Coordinate(sourceCoord.x + 1, sourceCoord.y);
|
|
2143
|
+
break;
|
|
2144
|
+
case 180:
|
|
2145
|
+
controlledCoord = new ocargo.Coordinate(sourceCoord.x, sourceCoord.y - 1);
|
|
2146
|
+
break;
|
|
2147
|
+
case 270:
|
|
2148
|
+
controlledCoord = new ocargo.Coordinate(sourceCoord.x - 1, sourceCoord.y);
|
|
2149
|
+
break;
|
|
2150
|
+
}
|
|
2008
2151
|
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2152
|
+
// If controlled node is not on grid, remove it
|
|
2153
|
+
if (!isCoordinateOnGrid(controlledCoord)) {
|
|
2154
|
+
controlledCoord = null;
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
// If source node is not on grid remove it
|
|
2158
|
+
if (!isCoordinateOnGrid(sourceCoord)) {
|
|
2159
|
+
sourceCoord = null;
|
|
2160
|
+
}
|
|
2161
|
+
|
|
2162
|
+
if (sourceCoord && controlledCoord) {
|
|
2163
|
+
var colour;
|
|
2164
|
+
if(validityCheckFunction(sourceCoord, controlledCoord)) {
|
|
2165
|
+
colour = VALID_LIGHT_COLOUR;
|
|
2166
|
+
if (image !== "undefined") {
|
|
2167
|
+
drawing.setTrafficLightImagePosition(sourceCoord, controlledCoord, image);
|
|
2016
2168
|
}
|
|
2169
|
+
} else {
|
|
2170
|
+
colour = INVALID_LIGHT_COLOUR;
|
|
2017
2171
|
}
|
|
2018
|
-
|
|
2172
|
+
|
|
2173
|
+
mark(controlledCoord, colour, 0.7, false);
|
|
2174
|
+
mark(sourceCoord, colour, 0.7, false);
|
|
2019
2175
|
}
|
|
2020
2176
|
|
|
2021
|
-
|
|
2177
|
+
return [sourceCoord, controlledCoord];
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
function handleDraggableTrafficLightsMouseDown(e, startingState){
|
|
2181
|
+
e.preventDefault();
|
|
2182
|
+
|
|
2183
|
+
window.dragged_light = {};
|
|
2184
|
+
dragged_light.pageX0 = e.pageX;
|
|
2185
|
+
dragged_light.pageY0 = e.pageY;
|
|
2186
|
+
dragged_light.elem = e.target;
|
|
2187
|
+
dragged_light.offset0 = $(e.target).offset();
|
|
2188
|
+
dragged_light.width = TRAFFIC_LIGHT_WIDTH;
|
|
2189
|
+
dragged_light.height = TRAFFIC_LIGHT_HEIGHT;
|
|
2190
|
+
dragged_light.parent = e.target.parentElement;
|
|
2191
|
+
|
|
2192
|
+
const clone = $(e.target).clone(true);
|
|
2193
|
+
|
|
2194
|
+
let sourceCoord;
|
|
2195
|
+
let controlledCoord;
|
|
2196
|
+
|
|
2197
|
+
function handleDraggableTrafficLightsDragging(e){
|
|
2198
|
+
const left = dragged_light.offset0.left + (e.pageX - dragged_light.pageX0);
|
|
2199
|
+
const top = dragged_light.offset0.top + (e.pageY - dragged_light.pageY0);
|
|
2200
|
+
$(dragged_light.elem).offset({top: top, left: left});
|
|
2022
2201
|
|
|
2202
|
+
unmarkOldTrafficLightSquare(sourceCoord, controlledCoord);
|
|
2203
|
+
|
|
2204
|
+
const [absX, absY] = getAbsCoordinates(e);
|
|
2205
|
+
if (draggedCursorOverGrid(absX, absY)) {
|
|
2206
|
+
[sourceCoord, controlledCoord] = markNewTrafficLightSquare(absX, absY, isValidTrafficLightPlacement, sourceCoord, controlledCoord, 0);
|
|
2207
|
+
}
|
|
2023
2208
|
}
|
|
2209
|
+
|
|
2210
|
+
function handleDraggableTrafficLightsMouseUp(e){
|
|
2211
|
+
let internalTrafficLight = new InternalTrafficLight({"redDuration": 3, "greenDuration": 3, "startTime": 0, "startingState": startingState, "sourceCoordinate": null, "direction": null});
|
|
2212
|
+
let image = internalTrafficLight.image;
|
|
2213
|
+
|
|
2214
|
+
const lightX = e.pageX + paper.scrollLeft() - TAB_PANE_WIDTH - dragged_light.width;
|
|
2215
|
+
const lightY = e.pageY + paper.scrollTop() - dragged_light.width / 2;
|
|
2216
|
+
|
|
2217
|
+
unmarkOldTrafficLightSquare(sourceCoord, controlledCoord);
|
|
2218
|
+
|
|
2219
|
+
if (isValidTrafficLightPlacement(sourceCoord, controlledCoord)) {
|
|
2220
|
+
internalTrafficLight.sourceNode = ocargo.Node.findNodeByCoordinate(sourceCoord, nodes);
|
|
2221
|
+
internalTrafficLight.controlledNode = ocargo.Node.findNodeByCoordinate(controlledCoord, nodes);
|
|
2222
|
+
internalTrafficLight.valid = true;
|
|
2223
|
+
|
|
2224
|
+
drawing.setTrafficLightImagePosition(sourceCoord, controlledCoord, image);
|
|
2225
|
+
} else {
|
|
2226
|
+
internalTrafficLight.sourceCoord = null;
|
|
2227
|
+
internalTrafficLight.controlledCoord = null;
|
|
2228
|
+
internalTrafficLight.valid = false;
|
|
2229
|
+
|
|
2230
|
+
if (draggedObjectOnGrid(e, dragged_light)) {
|
|
2231
|
+
image.transform('t' + lightX + ',' + lightY + ' s-1,1');
|
|
2232
|
+
} else {
|
|
2233
|
+
internalTrafficLight.destroy();
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2237
|
+
$(document)
|
|
2238
|
+
.off('mousemove', handleDraggableTrafficLightsDragging)
|
|
2239
|
+
.off('mouseup mouseleave', handleDraggableTrafficLightsMouseUp);
|
|
2240
|
+
|
|
2241
|
+
$(dragged_light.elem).remove();
|
|
2242
|
+
$(clone).appendTo(dragged_light.parent);
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
$(document)
|
|
2246
|
+
.on('mouseup mouseleave', handleDraggableTrafficLightsMouseUp)
|
|
2247
|
+
.on('mousemove', handleDraggableTrafficLightsDragging);
|
|
2024
2248
|
}
|
|
2025
2249
|
|
|
2026
2250
|
/********************************/
|
|
@@ -2039,14 +2263,14 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2039
2263
|
}
|
|
2040
2264
|
nodes.splice(nodes.indexOf(node), 1);
|
|
2041
2265
|
|
|
2042
|
-
// Check if start or
|
|
2266
|
+
// Check if start or house node
|
|
2043
2267
|
if (isOriginCoordinate(coord)) {
|
|
2044
2268
|
markAsBackground(originNode.coordinate);
|
|
2045
2269
|
originNode = null;
|
|
2046
2270
|
}
|
|
2047
|
-
if (
|
|
2048
|
-
markAsBackground(
|
|
2049
|
-
|
|
2271
|
+
if (isHouseCoordinate(coord)) {
|
|
2272
|
+
markAsBackground(houseNodes[houseNodes.indexOf(coord)]);
|
|
2273
|
+
houseNodes.splice(houseNodes.indexOf(ocargo.Node.findNodeByCoordinate(coordMap, nodes)), 1);
|
|
2050
2274
|
}
|
|
2051
2275
|
|
|
2052
2276
|
// Check if any traffic lights present
|
|
@@ -2153,6 +2377,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2153
2377
|
|
|
2154
2378
|
function setTheme(theme) {
|
|
2155
2379
|
currentTheme = theme;
|
|
2380
|
+
let newType = currentTheme == THEMES.city ? ocargo.Cow.PIGEON : ocargo.Cow.WHITE;
|
|
2156
2381
|
|
|
2157
2382
|
for (var x = 0; x < GRID_WIDTH; x++) {
|
|
2158
2383
|
for (var y = 0; y < GRID_HEIGHT; y++) {
|
|
@@ -2169,6 +2394,36 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2169
2394
|
});
|
|
2170
2395
|
|
|
2171
2396
|
$('#paper').css({'background-color': theme.background});
|
|
2397
|
+
|
|
2398
|
+
const animalSource = theme == THEMES.city ? "/static/game/image/pigeon.svg" : "/static/game/image/Clarice.svg";
|
|
2399
|
+
|
|
2400
|
+
$('#cow').each(function(index, element) {
|
|
2401
|
+
element.src = animalSource;
|
|
2402
|
+
})
|
|
2403
|
+
|
|
2404
|
+
$('#animals_label').each(function(index, element) {
|
|
2405
|
+
element.innerHTML = theme == THEMES.city ? "Pigeons" : "Cows";
|
|
2406
|
+
})
|
|
2407
|
+
|
|
2408
|
+
for (let [key, value] of Object.entries(cowGroups)) {
|
|
2409
|
+
value["type"] = theme == THEMES.city ? ocargo.Cow.PIGEON : ocargo.Cow.WHITE;
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2412
|
+
for (let i = 0; i < cows.length; i++) {
|
|
2413
|
+
cows[i].updateTheme();
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
const pigeonHTML = `<svg class="block_image"><g transform="translate(10,0)" <path="" class="blocklyPathDark" fill="#496684" d="m 0,0 H 111.34375 v 30 H 0 V 20 c 0,-10 -8,8 -8,-7.5 s 8,2.5 8,-7.5 z
|
|
2417
|
+
"><path class="blocklyPath" stroke="none" fill="#5b80a5" d="m 0,0 H 111.34375 v 30 H 0 V 20 c 0,-10 -8,8 -8,-7.5 s 8,2.5 8,-7.5 z
|
|
2418
|
+
"></path><path class="blocklyPathLight" stroke="#8ca6c0" d="m 0.5,0.5 H 110.84375 M 110.84375,0.5 M 0.5,29.5 V 18.5 m -7.36,-0.5 q -1.52,-5.5 0,-11 m 7.36,1 V 0.5 H 1
|
|
2419
|
+
"></path><text class="blocklyText" y="12.5" transform="translate(10,5)">pigeons</text><g transform="translate(71.34375,5)"><image height="20px" width="30px" xlink:href="/static/game/image/pigeon.svg" alt=""></image></g></g></svg>`;
|
|
2420
|
+
|
|
2421
|
+
const cowHTML = `<svg class="block_image"><g transform="translate(10,0)" <path="" class="blocklyPathDark" fill="#496684" d="m 0,0 H 93.40625 v 30 H 0 V 20 c 0,-10 -8,8 -8,-7.5 s 8,2.5 8,-7.5 z
|
|
2422
|
+
"><path class="blocklyPath" stroke="none" fill="#5b80a5" d="m 0,0 H 93.40625 v 30 H 0 V 20 c 0,-10 -8,8 -8,-7.5 s 8,2.5 8,-7.5 z
|
|
2423
|
+
"></path><path class="blocklyPathLight" stroke="#8ca6c0" d="m 0.5,0.5 H 92.90625 M 92.90625,0.5 M 0.5,29.5 V 18.5 m -7.36,-0.5 q -1.52,-5.5 0,-11 m 7.36,1 V 0.5 H 1
|
|
2424
|
+
"></path><text class="blocklyText" y="12.5" transform="translate(10,5)">cows</text><g transform="translate(53.40625,5)"><image height="20px" width="30px" xlink:href="/static/game/image/Clarice.svg" alt=""></image></g></g></svg>`;
|
|
2425
|
+
|
|
2426
|
+
$("#cow_crossing_image").html(newType == ocargo.Cow.PIGEON ? pigeonHTML : cowHTML);
|
|
2172
2427
|
}
|
|
2173
2428
|
|
|
2174
2429
|
function sortNodes(nodes) {
|
|
@@ -2235,7 +2490,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2235
2490
|
type: cowGroups[groupId].type}; //editor can only add white cow for now
|
|
2236
2491
|
}
|
|
2237
2492
|
|
|
2238
|
-
var coordinates = cows[i].
|
|
2493
|
+
var coordinates = cows[i].coordinate;
|
|
2239
2494
|
var strCoordinates = {'x':coordinates.x, 'y':coordinates.y};
|
|
2240
2495
|
cowGroupData[groupId].potentialCoordinates.push(strCoordinates);
|
|
2241
2496
|
}
|
|
@@ -2270,9 +2525,10 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2270
2525
|
state.decor = ocargo.utils.sortObjects(state.decor, "z");
|
|
2271
2526
|
|
|
2272
2527
|
// Destination and origin data
|
|
2273
|
-
if (
|
|
2274
|
-
|
|
2275
|
-
|
|
2528
|
+
if (houseNodes.length > 0) {
|
|
2529
|
+
state.destinations = JSON.stringify(houseNodes.map(function (houseNode) {
|
|
2530
|
+
return [houseNode.coordinate.x, houseNode.coordinate.y]
|
|
2531
|
+
}));
|
|
2276
2532
|
}
|
|
2277
2533
|
if (originNode) {
|
|
2278
2534
|
var originCoord = originNode.coordinate;
|
|
@@ -2286,19 +2542,83 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2286
2542
|
|
|
2287
2543
|
// Language data
|
|
2288
2544
|
var language = $('#language_select').val();
|
|
2289
|
-
state.
|
|
2290
|
-
state.
|
|
2291
|
-
state.
|
|
2545
|
+
state.blockly_enabled = language === 'blockly' || language === 'both' || language === 'blocklyWithPythonView';
|
|
2546
|
+
state.python_view_enabled = language === 'blocklyWithPythonView';
|
|
2547
|
+
state.python_enabled = language === 'python' || language === 'both';
|
|
2548
|
+
|
|
2549
|
+
const regex = /^[\w.?!', ]*$/;
|
|
2550
|
+
const subtitleValue = $('#subtitle').val();
|
|
2551
|
+
const descriptionValue = $('#description').val();
|
|
2552
|
+
const hintValue = $('#hint').val();
|
|
2553
|
+
|
|
2554
|
+
// Description and hint data
|
|
2555
|
+
if (subtitleValue.length > 0) {
|
|
2556
|
+
if (regex.exec(subtitleValue)) {
|
|
2557
|
+
state.subtitle = subtitleValue;
|
|
2558
|
+
}
|
|
2559
|
+
else {
|
|
2560
|
+
ocargo.Drawing.startPopup(
|
|
2561
|
+
"Oh no!",
|
|
2562
|
+
"You used some invalid characters for your level subtitle.",
|
|
2563
|
+
"Try saving your level again using only" +
|
|
2564
|
+
" letters, numbers and standard punctuation."
|
|
2565
|
+
);
|
|
2566
|
+
return
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
2569
|
+
|
|
2570
|
+
if (descriptionValue.length > 0) {
|
|
2571
|
+
if (regex.exec(descriptionValue)) {
|
|
2572
|
+
state.lesson = descriptionValue;
|
|
2573
|
+
}
|
|
2574
|
+
else {
|
|
2575
|
+
ocargo.Drawing.startPopup(
|
|
2576
|
+
"Oh no!",
|
|
2577
|
+
"You used some invalid characters for your level description.",
|
|
2578
|
+
"Try saving your level again using only" +
|
|
2579
|
+
" letters and numbers and standard punctuation."
|
|
2580
|
+
);
|
|
2581
|
+
return
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
if (hintValue.length > 0) {
|
|
2586
|
+
if (regex.exec(hintValue)) {
|
|
2587
|
+
state.hint = hintValue;
|
|
2588
|
+
}
|
|
2589
|
+
else {
|
|
2590
|
+
ocargo.Drawing.startPopup(
|
|
2591
|
+
"Oh no!",
|
|
2592
|
+
"You used some invalid characters for your level hint.",
|
|
2593
|
+
"Try saving your level again using only" +
|
|
2594
|
+
" letters and numbers and standard punctuation."
|
|
2595
|
+
);
|
|
2596
|
+
return
|
|
2597
|
+
}
|
|
2598
|
+
}
|
|
2292
2599
|
|
|
2293
2600
|
// Other data
|
|
2294
2601
|
state.theme = currentTheme.id;
|
|
2295
2602
|
state.character = $('#character_select').val();
|
|
2603
|
+
state.disable_algorithm_score = true;
|
|
2296
2604
|
|
|
2297
2605
|
return state;
|
|
2298
2606
|
}
|
|
2299
2607
|
|
|
2300
2608
|
function restoreState(state) {
|
|
2301
|
-
|
|
2609
|
+
console.log("restoring state");
|
|
2610
|
+
|
|
2611
|
+
// Get character id from saved character name
|
|
2612
|
+
var characterName = state.character_name;
|
|
2613
|
+
if (characterName) {
|
|
2614
|
+
var characterId = null;
|
|
2615
|
+
for (var id in CHARACTERS) {
|
|
2616
|
+
if (characterName == CHARACTERS[id].name) {
|
|
2617
|
+
characterId = id;
|
|
2618
|
+
break;
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
}
|
|
2302
2622
|
clear();
|
|
2303
2623
|
|
|
2304
2624
|
// Load node data
|
|
@@ -2310,41 +2630,15 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2310
2630
|
new InternalTrafficLight(trafficLightData[i]);
|
|
2311
2631
|
}
|
|
2312
2632
|
|
|
2313
|
-
if(COW_LEVELS_ENABLED) {
|
|
2314
|
-
var cowGroupData = JSON.parse(state.cows);
|
|
2315
|
-
for (var i = 0; i < cowGroupData.length; i++) {
|
|
2316
|
-
// Add new group to group select element
|
|
2317
|
-
if (i >= Object.keys(cowGroups).length) {
|
|
2318
|
-
addCowGroup();
|
|
2319
|
-
}
|
|
2320
|
-
var cowGroupId = Object.keys(cowGroups)[i];
|
|
2321
|
-
cowGroups[cowGroupId].minCows = cowGroupData[i].minCows;
|
|
2322
|
-
cowGroups[cowGroupId].maxCows = cowGroupData[i].maxCows;
|
|
2323
|
-
cowGroups[cowGroupId].type = cowGroupData[i].type;
|
|
2324
|
-
|
|
2325
|
-
if (cowGroupData[i].potentialCoordinates != null) {
|
|
2326
|
-
for (var j = 0; j < cowGroupData[i].potentialCoordinates.length; j++) {
|
|
2327
|
-
var cowData = {
|
|
2328
|
-
coordinates: [cowGroupData[i].potentialCoordinates[j]],
|
|
2329
|
-
group: cowGroups[cowGroupId]
|
|
2330
|
-
};
|
|
2331
|
-
new InternalCow(cowData);
|
|
2332
|
-
}
|
|
2333
|
-
}
|
|
2334
|
-
}
|
|
2335
|
-
|
|
2336
|
-
// Trigger change listener on cow group select box to set initial min/max values
|
|
2337
|
-
$('#cow_group_select').change();
|
|
2338
|
-
|
|
2339
|
-
markCowNodes();
|
|
2340
|
-
}
|
|
2341
|
-
|
|
2342
2633
|
// Load in destination and origin nodes
|
|
2343
|
-
// TODO needs to be fixed in the long term with multiple destinations
|
|
2344
2634
|
if (state.destinations) {
|
|
2345
|
-
var
|
|
2346
|
-
var
|
|
2347
|
-
|
|
2635
|
+
var houses = JSON.parse(state.destinations);
|
|
2636
|
+
var houseCoordinates = houses.map(function (house) {
|
|
2637
|
+
return new ocargo.Coordinate(house[0], house[1]);
|
|
2638
|
+
})
|
|
2639
|
+
houseNodes = houseCoordinates.map(function (houseCoord) {
|
|
2640
|
+
return ocargo.Node.findNodeByCoordinate(houseCoord, nodes);
|
|
2641
|
+
})
|
|
2348
2642
|
}
|
|
2349
2643
|
|
|
2350
2644
|
if (state.origin) {
|
|
@@ -2354,7 +2648,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2354
2648
|
}
|
|
2355
2649
|
|
|
2356
2650
|
// Load in character
|
|
2357
|
-
$('#character_select').val(
|
|
2651
|
+
$('#character_select').val(characterId);
|
|
2358
2652
|
$('#character_select').change();
|
|
2359
2653
|
|
|
2360
2654
|
drawAll();
|
|
@@ -2383,6 +2677,36 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2383
2677
|
PAPER_HEIGHT - currentTheme.decor[decor[i].decorName].height - decor[i].y + PAPER_PADDING);
|
|
2384
2678
|
}
|
|
2385
2679
|
|
|
2680
|
+
//Load in cow data
|
|
2681
|
+
if(COW_LEVELS_ENABLED) {
|
|
2682
|
+
var cowGroupData = JSON.parse(state.cows);
|
|
2683
|
+
for (var i = 0; i < cowGroupData.length; i++) {
|
|
2684
|
+
// Add new group to group select element
|
|
2685
|
+
if (i >= Object.keys(cowGroups).length) {
|
|
2686
|
+
addCowGroup();
|
|
2687
|
+
}
|
|
2688
|
+
var cowGroupId = Object.keys(cowGroups)[i];
|
|
2689
|
+
cowGroups[cowGroupId].minCows = cowGroupData[i].minCows;
|
|
2690
|
+
cowGroups[cowGroupId].maxCows = cowGroupData[i].maxCows;
|
|
2691
|
+
cowGroups[cowGroupId].type = cowGroupData[i].type;
|
|
2692
|
+
|
|
2693
|
+
if (cowGroupData[i].potentialCoordinates != null) {
|
|
2694
|
+
for (var j = 0; j < cowGroupData[i].potentialCoordinates.length; j++) {
|
|
2695
|
+
var cowData = {
|
|
2696
|
+
coordinates: [cowGroupData[i].potentialCoordinates[j]],
|
|
2697
|
+
group: cowGroups[cowGroupId]
|
|
2698
|
+
};
|
|
2699
|
+
new InternalCow(cowData);
|
|
2700
|
+
}
|
|
2701
|
+
}
|
|
2702
|
+
}
|
|
2703
|
+
|
|
2704
|
+
// Trigger change listener on cow group select box to set initial min/max values
|
|
2705
|
+
$('#cow_group_select').change();
|
|
2706
|
+
|
|
2707
|
+
markCowNodes();
|
|
2708
|
+
}
|
|
2709
|
+
|
|
2386
2710
|
// Load in block data
|
|
2387
2711
|
if(state.blocks) {
|
|
2388
2712
|
for(var i = 0; i < BLOCKS.length; i++) {
|
|
@@ -2401,20 +2725,29 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2401
2725
|
}
|
|
2402
2726
|
|
|
2403
2727
|
// Load in language data
|
|
2404
|
-
var languageSelect = $('#
|
|
2405
|
-
if(state.
|
|
2728
|
+
var languageSelect = $('#language_select');
|
|
2729
|
+
if (state.blockly_enabled && state.python_view_enabled){
|
|
2730
|
+
languageSelect.val('blocklyWithPythonView');
|
|
2731
|
+
} else if(state.blockly_enabled && state.python_enabled) {
|
|
2406
2732
|
languageSelect.val('both');
|
|
2407
|
-
} else if(state.
|
|
2733
|
+
} else if(state.python_enabled) {
|
|
2408
2734
|
languageSelect.val('python');
|
|
2409
2735
|
} else {
|
|
2410
2736
|
languageSelect.val('blockly');
|
|
2411
2737
|
}
|
|
2412
2738
|
languageSelect.change();
|
|
2413
2739
|
|
|
2740
|
+
// Load in description and hint data
|
|
2741
|
+
$('#subtitle').val(state.subtitle);
|
|
2742
|
+
$('#description').val(state.lesson);
|
|
2743
|
+
$('#hint').val(state.hint);
|
|
2744
|
+
|
|
2414
2745
|
// Other data
|
|
2415
2746
|
if(state.max_fuel) {
|
|
2416
2747
|
$('#max_fuel').val(state.max_fuel);
|
|
2417
2748
|
}
|
|
2749
|
+
|
|
2750
|
+
needsApproval = state.needs_approval;
|
|
2418
2751
|
}
|
|
2419
2752
|
|
|
2420
2753
|
function loadLevel(levelID) {
|
|
@@ -2455,28 +2788,42 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2455
2788
|
return false;
|
|
2456
2789
|
}
|
|
2457
2790
|
// Check to see if start and end nodes have been marked
|
|
2458
|
-
if (!originNode
|
|
2459
|
-
var
|
|
2460
|
-
gettext('In %(map_icon)s
|
|
2461
|
-
'
|
|
2791
|
+
if (!originNode) {
|
|
2792
|
+
var noStart = interpolate(
|
|
2793
|
+
gettext('In %(map_icon)s%(map_label)s menu, click on %(mark_start_icon)s%(mark_start_label)s ' +
|
|
2794
|
+
'and then select the square where you want the road to start.'
|
|
2462
2795
|
), {
|
|
2463
2796
|
map_icon: ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/map.svg', 'popupIcon'),
|
|
2464
2797
|
map_label: '<b>' + gettext('Map') + '</b>',
|
|
2465
2798
|
mark_start_icon: ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/origin.svg', 'popupIcon'),
|
|
2466
2799
|
mark_start_label: '<b>' + gettext('Mark start') + '</b>',
|
|
2467
|
-
mark_end_icon: ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/destination.svg', 'popupIcon'),
|
|
2468
|
-
mark_end_label: '<b>' + gettext('Mark end') + '</b>'
|
|
2469
2800
|
},
|
|
2470
2801
|
true
|
|
2471
2802
|
);
|
|
2472
|
-
ocargo.Drawing.startPopup(gettext('Oh no!'), gettext('You forgot to mark the start
|
|
2803
|
+
ocargo.Drawing.startPopup(gettext('Oh no!'), gettext('You forgot to mark the start point.'), noStart);
|
|
2473
2804
|
return false;
|
|
2474
2805
|
}
|
|
2475
2806
|
|
|
2476
|
-
|
|
2477
|
-
|
|
2807
|
+
if (houseNodes.length === 0) {
|
|
2808
|
+
var noHouses = interpolate(
|
|
2809
|
+
gettext('In %(map_icon)s%(map_label)s menu, click on %(add_house_icon)s%(add_house_label)s ' +
|
|
2810
|
+
'and then select the square(s) where you want to add houses for delivery.'
|
|
2811
|
+
), {
|
|
2812
|
+
map_icon: ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/map.svg', 'popupIcon'),
|
|
2813
|
+
map_label: '<b>' + gettext('Map') + '</b>',
|
|
2814
|
+
add_house_icon: ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/add_house.svg', 'popupIcon'),
|
|
2815
|
+
add_house_label: '<b>' + gettext('Add house') + '</b>'
|
|
2816
|
+
},
|
|
2817
|
+
true
|
|
2818
|
+
);
|
|
2819
|
+
ocargo.Drawing.startPopup(gettext('Oh no!'), gettext('You forgot to mark the houses.'), noHouses);
|
|
2820
|
+
return false;
|
|
2821
|
+
}
|
|
2822
|
+
|
|
2823
|
+
// Check to see if path exists from start to each house
|
|
2824
|
+
if (!areDestinationsReachable(originNode, houseNodes, nodes)) {
|
|
2478
2825
|
ocargo.Drawing.startPopup(gettext('Something is wrong...'),
|
|
2479
|
-
gettext('There is no way to get from the start to
|
|
2826
|
+
gettext('There is no way to get from the start to all of your houses.'),
|
|
2480
2827
|
gettext('Edit your level to allow the driver to get to the end.'));
|
|
2481
2828
|
return false;
|
|
2482
2829
|
}
|
|
@@ -2509,10 +2856,13 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2509
2856
|
|
|
2510
2857
|
function canShare() {
|
|
2511
2858
|
if (!saveState.isSaved()) {
|
|
2512
|
-
ocargo.Drawing.startPopup(
|
|
2859
|
+
ocargo.Drawing.startPopup("Sharing", "", "Please save your level before continuing!");
|
|
2513
2860
|
return false;
|
|
2514
2861
|
} else if (hasLevelChangedSinceSave()) {
|
|
2515
|
-
ocargo.Drawing.startPopup(
|
|
2862
|
+
ocargo.Drawing.startPopup("Sharing", "", "Please save your latest changes!");
|
|
2863
|
+
return false;
|
|
2864
|
+
} else if (needsApproval) {
|
|
2865
|
+
ocargo.Drawing.startPopup("Sharing", "", "Your teacher hasn't approved your level so you can't share it yet. Please let your teacher know they need to approve it first.")
|
|
2516
2866
|
return false;
|
|
2517
2867
|
}
|
|
2518
2868
|
return true;
|
|
@@ -2546,7 +2896,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2546
2896
|
|
|
2547
2897
|
notLoggedInMessages.push(interpolate(gettext('You can log in as a %(student_login_url)s, '
|
|
2548
2898
|
+ '%(teacher_login_url)s or %(independent_login_url)s.'), {
|
|
2549
|
-
student_login_url: '<a href="' + Urls.
|
|
2899
|
+
student_login_url: '<a href="' + Urls.student_login_access_code() + '">' + pgettext('login_url', 'student') + '</a>',
|
|
2550
2900
|
teacher_login_url: '<a href="' + Urls.teacher_login() + '">' + pgettext('login_url', 'teacher') + '</a>',
|
|
2551
2901
|
independent_login_url: '<a href="' + Urls.independent_student_login() + '">'
|
|
2552
2902
|
+ pgettext('login_url', 'independent student') + '</a>'
|
|
@@ -2575,7 +2925,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2575
2925
|
// you can copy and paste into a Django migration file
|
|
2576
2926
|
var state = extractState();
|
|
2577
2927
|
|
|
2578
|
-
var boolFields = ["
|
|
2928
|
+
var boolFields = ["python_enabled", "blockly_enabled", 'fuel_gauge'];
|
|
2579
2929
|
var stringFields = ['path', 'traffic_lights', 'cows', 'origin', 'destinations'];
|
|
2580
2930
|
var otherFields = ['max_fuel'];
|
|
2581
2931
|
|
|
@@ -2626,9 +2976,8 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2626
2976
|
if (!this.valid) {
|
|
2627
2977
|
throw "Error: cannot create actual cow from invalid internal cow!";
|
|
2628
2978
|
}
|
|
2629
|
-
|
|
2630
2979
|
// Where the cow is placed.
|
|
2631
|
-
var coordinates = this.
|
|
2980
|
+
var coordinates = this.coordinate;
|
|
2632
2981
|
var strCoordinates= {'x':coordinates.x, 'y':coordinates.y};
|
|
2633
2982
|
|
|
2634
2983
|
return { "coordinates": [strCoordinates],
|
|
@@ -2650,17 +2999,50 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2650
2999
|
|
|
2651
3000
|
};
|
|
2652
3001
|
|
|
3002
|
+
this.isOnRoad = function() {
|
|
3003
|
+
return this.coordinate && ocargo.Node.findNodeByCoordinate(this.coordinate, nodes);
|
|
3004
|
+
}
|
|
3005
|
+
|
|
3006
|
+
this.updateTheme = function() {
|
|
3007
|
+
let newType = currentTheme == THEMES.city ? ocargo.Cow.PIGEON : ocargo.Cow.WHITE;
|
|
3008
|
+
let transformDimensions = this["image"]["_"]["transform"][0]
|
|
3009
|
+
let rotateDimensions = this["image"]["_"]["transform"][1]
|
|
3010
|
+
let x = transformDimensions[1]
|
|
3011
|
+
let y = transformDimensions[2]
|
|
3012
|
+
let r = 0;
|
|
3013
|
+
if (rotateDimensions) {
|
|
3014
|
+
r = rotateDimensions[1];
|
|
3015
|
+
}
|
|
3016
|
+
|
|
3017
|
+
this.image.remove();
|
|
3018
|
+
|
|
3019
|
+
this.image = drawing.createCowImage(newType);
|
|
3020
|
+
if (this.isOnRoad()) {
|
|
3021
|
+
let controlledNode = ocargo.Node.findNodeByCoordinate(coordinates, nodes);
|
|
3022
|
+
drawing.setCowImagePosition(this.coordinate, this.image, controlledNode);
|
|
3023
|
+
} else {
|
|
3024
|
+
this.image.transform("t" + x + "," + y + " r" + r);
|
|
3025
|
+
}
|
|
3026
|
+
|
|
3027
|
+
setupCowListeners(this);
|
|
3028
|
+
}
|
|
3029
|
+
|
|
2653
3030
|
this.image = drawing.createCowImage(data.group.type);
|
|
2654
3031
|
this.valid = false;
|
|
2655
3032
|
|
|
2656
|
-
|
|
2657
3033
|
if ( data.coordinates && data.coordinates.length > 0 ) {
|
|
2658
|
-
|
|
2659
|
-
this.
|
|
3034
|
+
this.coordinate = new ocargo.Coordinate(data.coordinates[0].x, data.coordinates[0].y);
|
|
3035
|
+
this.valid = isValidDraggedCowPlacement(this.coordinate, this);
|
|
2660
3036
|
|
|
2661
|
-
if (this.
|
|
2662
|
-
this.
|
|
2663
|
-
drawing.setCowImagePosition(
|
|
3037
|
+
if (this.isOnRoad()) {
|
|
3038
|
+
const controlledNode = ocargo.Node.findNodeByCoordinate(this.coordinate, nodes);
|
|
3039
|
+
drawing.setCowImagePosition(this.coordinate, this.image, controlledNode);
|
|
3040
|
+
} else {
|
|
3041
|
+
const box = this.image.getBBox();
|
|
3042
|
+
// calculate position of the image
|
|
3043
|
+
const paperX = (this.coordinate.x + 1) * GRID_SPACE_SIZE - box.width/2;
|
|
3044
|
+
const paperY = (GRID_HEIGHT - this.coordinate.y) * GRID_SPACE_SIZE - box.height/2;
|
|
3045
|
+
this.image.transform('t' + paperX + ',' + paperY );
|
|
2664
3046
|
}
|
|
2665
3047
|
} else {
|
|
2666
3048
|
this.image.transform('...t' + (-paper.scrollLeft()) + ',' + paper.scrollTop());
|
|
@@ -2668,6 +3050,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2668
3050
|
|
|
2669
3051
|
setupCowListeners(this);
|
|
2670
3052
|
this.image.attr({'cursor':'pointer'});
|
|
3053
|
+
this.image.attr({'position': 'absolute'});
|
|
2671
3054
|
cows.push(this);
|
|
2672
3055
|
|
|
2673
3056
|
}
|
|
@@ -2797,7 +3180,7 @@ ocargo.LevelEditor = function(levelId) {
|
|
|
2797
3180
|
/******************/
|
|
2798
3181
|
|
|
2799
3182
|
$(function() {
|
|
2800
|
-
|
|
3183
|
+
new ocargo.LevelEditor(LEVEL);
|
|
2801
3184
|
var subtitle = interpolate(
|
|
2802
3185
|
gettext('Click %(help_icon)s%(help_label)s for clues on getting started.'), {
|
|
2803
3186
|
help_icon: ocargo.jsElements.image(ocargo.Drawing.imageDir + 'icons/help.svg', 'popupHelp'),
|
|
@@ -2808,24 +3191,16 @@ $(function() {
|
|
|
2808
3191
|
if (LEVEL === null){
|
|
2809
3192
|
ocargo.Drawing.startPopup(gettext('Welcome to the Level editor!'), subtitle, '');
|
|
2810
3193
|
} else {
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
};
|
|
2815
|
-
|
|
2816
|
-
var optionBFunc = function(){
|
|
2817
|
-
window.location.replace("/rapidrouter/custom/"+LEVEL+"/");
|
|
2818
|
-
};
|
|
3194
|
+
let buttons = '';
|
|
3195
|
+
buttons += ocargo.button.dismissButtonHtml("edit_button", "Edit");
|
|
3196
|
+
buttons += ocargo.button.redirectButtonHtml("play_button", Urls.levels() + "custom/" + LEVEL, "Play");
|
|
2819
3197
|
|
|
2820
|
-
ocargo.Drawing.
|
|
3198
|
+
ocargo.Drawing.startPopup(
|
|
2821
3199
|
gettext('Welcome back!'),
|
|
2822
3200
|
gettext('Would you like to edit or play with your design?'),
|
|
2823
3201
|
'',
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
"Edit",
|
|
2827
|
-
"Play",
|
|
2828
|
-
''
|
|
3202
|
+
false,
|
|
3203
|
+
buttons,
|
|
2829
3204
|
);
|
|
2830
3205
|
}
|
|
2831
3206
|
|