diff options
author | Daniel Weipert <git@mail.dweipert.de> | 2024-05-18 15:49:24 +0200 |
---|---|---|
committer | Daniel Weipert <git@mail.dweipert.de> | 2024-05-18 15:49:24 +0200 |
commit | 9155752f861ae43e3534cdfa833d8c644cb0e5d3 (patch) | |
tree | fb1a0b115c1b23099796b56b30a04cb6fd1864d2 | |
parent | 3e94dd0704d7b4005f17c1086796afdbbe36b1f5 (diff) |
save/load
-rw-r--r-- | Objects/BuilderObject.gd | 8 | ||||
-rw-r--r-- | Start.tscn | 6 | ||||
-rw-r--r-- | Tray.gd | 45 | ||||
-rw-r--r-- | Tray.tscn | 15 | ||||
-rw-r--r-- | app.html | 217 | ||||
-rw-r--r-- | export_presets.cfg | 2 | ||||
-rw-r--r-- | project.godot | 4 |
7 files changed, 287 insertions, 10 deletions
diff --git a/Objects/BuilderObject.gd b/Objects/BuilderObject.gd index 91465bc..fde2660 100644 --- a/Objects/BuilderObject.gd +++ b/Objects/BuilderObject.gd @@ -30,7 +30,7 @@ func _process(_delta): func _on_area_2d_input_event(_viewport, event: InputEvent, _shape_idx): if event.is_action_pressed("drag_start"): drag_start() - if event.is_action_released("drag_start"): + if is_dragging and event.is_action_released("drag_start"): drag_end() @@ -79,6 +79,6 @@ func _on_area_2d_area_entered(_area): func _on_area_2d_area_exited(_area): - #if $Area2D.get_overlapping_areas().size() == 0: - is_colliding = false - modulate = Color("fff") + if $Area2D.get_overlapping_areas().size() == 0: + is_colliding = false + modulate = Color("fff") @@ -1,7 +1,6 @@ -[gd_scene load_steps=5 format=3 uid="uid://bdyngwtm3rowr"] +[gd_scene load_steps=4 format=3 uid="uid://bdyngwtm3rowr"] [ext_resource type="Script" path="res://Start.gd" id="1_k0odd"] -[ext_resource type="PackedScene" uid="uid://p0ay1mp7v772" path="res://Objects/BuilderObject.tscn" id="3_skats"] [ext_resource type="PackedScene" uid="uid://3vuctgbcjqi7" path="res://Tray.tscn" id="3_u4wpj"] [ext_resource type="Texture2D" uid="uid://djasmoqj87h1r" path="res://icon.svg" id="4_kyq1e"] @@ -39,9 +38,6 @@ texture = ExtResource("4_kyq1e") [node name="DropTarget" type="Node2D" parent="Map"] unique_name_in_owner = true -[node name="BuilderObject" parent="Map/DropTarget" instance=ExtResource("3_skats")] -position = Vector2(155, 109) - [node name="Viewport" type="Node2D" parent="."] unique_name_in_owner = true @@ -4,9 +4,15 @@ extends Control var TrayItemScene = preload("res://TrayItem.tscn") var is_open = true +var _on_data_loaded_callback = null func _ready(): + if OS.get_name() == "Web": + _on_data_loaded_callback = JavaScriptBridge.create_callback(load_save) + var callbacks = JavaScriptBridge.get_interface("godotCallbacks") + callbacks.dataLoaded = _on_data_loaded_callback + for i in range(5): add_item() @@ -55,3 +61,42 @@ func _on_button_pressed(): close() else: open() + + +func _on_save_pressed(): + if OS.get_name() == "Web": + var to_save = [] + var objects = get_tree().current_scene.get_node("%DropTarget").get_children() + for obj in objects: + to_save.append({ + "position": { + "x": obj.position.x, + "y": obj.position.y, + }, + "rotation": obj.rotation, + "object": "BuilderObject", + }) + + JavaScriptBridge.download_buffer( + JSON.stringify(to_save).to_utf8_buffer(), + "CityBuilder-save.json", + "application/json" + ) + + +func _on_load_pressed(): + if OS.get_name() == "Web": + JavaScriptBridge.eval("openLoadDialog()") + + +func load_save(data: Array): + var current_objects = get_tree().current_scene.get_node("%DropTarget").get_children() + for obj in current_objects: + obj.queue_free() + + var objects = JSON.parse_string(data[0]) + for obj in objects: + var scene = load("res://Objects/" + obj.object + ".tscn").instantiate() + scene.position = Vector2(obj.position.x, obj.position.y) + scene.rotation = obj.rotation + get_tree().current_scene.get_node("%DropTarget").add_child(scene) @@ -38,6 +38,19 @@ layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 3 +[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"] +layout_mode = 2 + +[node name="Save" type="Button" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Save" + +[node name="Load" type="Button" parent="VBoxContainer/HBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 3 +text = "Load" + [node name="Control" type="Control" parent="."] layout_mode = 2 size_flags_horizontal = 0 @@ -60,4 +73,6 @@ collision_mask = 3 [node name="CollisionShape2D" type="CollisionShape2D" parent="TrayCollision"] [connection signal="resized" from="." to="." method="_on_resized"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/Save" to="." method="_on_save_pressed"] +[connection signal="pressed" from="VBoxContainer/HBoxContainer/Load" to="." method="_on_load_pressed"] [connection signal="pressed" from="Control/Button" to="." method="_on_button_pressed"] diff --git a/app.html b/app.html new file mode 100644 index 0000000..078d27d --- /dev/null +++ b/app.html @@ -0,0 +1,217 @@ +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"> + <title>$GODOT_PROJECT_NAME</title> + <style> + html, body, #canvas { + margin: 0; + padding: 0; + border: 0; + } + + body { + color: white; + background-color: black; + overflow: hidden; + touch-action: none; + } + + #canvas { + display: block; + } + + #canvas:focus { + outline: none; + } + + #status, #status-splash, #status-progress { + position: absolute; + left: 0; + right: 0; + } + + #status, #status-splash { + top: 0; + bottom: 0; + } + + #status { + background-color: #242424; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + visibility: hidden; + } + + #status-splash { + max-height: 100%; + max-width: 100%; + margin: auto; + } + + #status-progress, #status-notice { + display: none; + } + + #status-progress { + bottom: 10%; + width: 50%; + margin: 0 auto; + } + + #status-notice { + background-color: #5b3943; + border-radius: 0.5rem; + border: 1px solid #9b3943; + color: #e0e0e0; + font-family: 'Noto Sans', 'Droid Sans', Arial, sans-serif; + line-height: 1.3; + margin: 0 2rem; + overflow: hidden; + padding: 1rem; + text-align: center; + z-index: 1; + } + </style> + $GODOT_HEAD_INCLUDE + <script> + var godotCallbacks = { + dataLoaded: null + } + + function openLoadDialog() { + var input = document.createElement('input'); + input.setAttribute('type', 'file'); + input.setAttribute('accept', '.json'); + input.click(); + + input.addEventListener('change', (event) => { + var file = event.target.files[0]; + var reader = new FileReader(); + + reader.readAsText(file); + + reader.onloadend = () => { + if (godotCallbacks.dataLoaded) { + godotCallbacks.dataLoaded(reader.result); + } + } + }); + } + </script> + </head> + <body> + <canvas id="canvas"> + Your browser does not support the canvas tag. + </canvas> + + <noscript> + Your browser does not support JavaScript. + </noscript> + + <div id="status"> + <img id="status-splash" src="$GODOT_SPLASH" alt=""> + <progress id="status-progress"></progress> + <div id="status-notice"></div> + </div> + + <script src="$GODOT_URL"></script> + <script> + const GODOT_CONFIG = $GODOT_CONFIG; + // const GODOT_THREADS_ENABLED = $GODOT_THREADS_ENABLED; + const GODOT_THREADS_ENABLED = 'yes'; + const engine = new Engine(GODOT_CONFIG); + + (function () { + const statusOverlay = document.getElementById('status'); + const statusProgress = document.getElementById('status-progress'); + const statusNotice = document.getElementById('status-notice'); + + let initializing = true; + let statusMode = ''; + + function setStatusMode(mode) { + if (statusMode === mode || !initializing) { + return; + } + if (mode === 'hidden') { + statusOverlay.remove(); + initializing = false; + return; + } + statusOverlay.style.visibility = 'visible'; + statusProgress.style.display = mode === 'progress' ? 'block' : 'none'; + statusNotice.style.display = mode === 'notice' ? 'block' : 'none'; + statusMode = mode; + } + + function setStatusNotice(text) { + while (statusNotice.lastChild) { + statusNotice.removeChild(statusNotice.lastChild); + } + const lines = text.split('\n'); + lines.forEach((line) => { + statusNotice.appendChild(document.createTextNode(line)); + statusNotice.appendChild(document.createElement('br')); + }); + } + + function displayFailureNotice(err) { + const msg = err.message || err; + console.error(msg); + setStatusNotice(msg); + setStatusMode('notice'); + initializing = false; + } + + const missing = Engine.getMissingFeatures({ + threads: GODOT_THREADS_ENABLED, + }); + + if (missing.length !== 0) { + if (GODOT_CONFIG['serviceWorker'] && GODOT_CONFIG['ensureCrossOriginIsolationHeaders'] && 'serviceWorker' in navigator) { + // There's a chance that installing the service worker would fix the issue + Promise.race([ + navigator.serviceWorker.getRegistration().then((registration) => { + if (registration != null) { + return Promise.reject(new Error('Service worker already exists.')); + } + return registration; + }).then(() => engine.installServiceWorker()), + // For some reason, `getRegistration()` can stall + new Promise((resolve) => { + setTimeout(() => resolve(), 2000); + }), + ]).catch((err) => { + console.error('Error while registering service worker:', err); + }).then(() => { + window.location.reload(); + }); + } else { + // Display the message as usual + const missingMsg = 'Error\nThe following features required to run Godot projects on the Web are missing:\n'; + displayFailureNotice(missingMsg + missing.join('\n')); + } + } else { + setStatusMode('progress'); + engine.startGame({ + 'onProgress': function (current, total) { + if (current > 0 && total > 0) { + statusProgress.value = current; + statusProgress.max = total; + } else { + statusProgress.removeAttribute('value'); + statusProgress.removeAttribute('max'); + } + }, + }).then(() => { + setStatusMode('hidden'); + }, displayFailureNotice); + } + }()); + </script> + </body> +</html> diff --git a/export_presets.cfg b/export_presets.cfg index 542cb18..4deecb9 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -22,7 +22,7 @@ variant/extensions_support=false vram_texture_compression/for_desktop=true vram_texture_compression/for_mobile=false html/export_icon=true -html/custom_html_shell="" +html/custom_html_shell="res://app.html" html/head_include="" html/canvas_resize_policy=2 html/focus_canvas_on_start=true diff --git a/project.godot b/project.godot index 2f94abc..a703fc6 100644 --- a/project.godot +++ b/project.godot @@ -15,6 +15,10 @@ run/main_scene="res://Start.tscn" config/features=PackedStringArray("4.2", "GL Compatibility") config/icon="res://icon.svg" +[audio] + +driver/mix_rate.web=44100 + [input] drag_start={ |