summaryrefslogtreecommitdiffstats
path: root/platform/web
diff options
context:
space:
mode:
Diffstat (limited to 'platform/web')
-rw-r--r--platform/web/SCsub2
-rw-r--r--platform/web/audio_driver_web.cpp20
-rw-r--r--platform/web/audio_driver_web.h1
-rw-r--r--platform/web/detect.py1
-rw-r--r--platform/web/godot_audio.h1
-rw-r--r--platform/web/js/libs/library_godot_audio.js37
-rw-r--r--platform/web/js/libs/library_godot_input.js1
-rw-r--r--platform/web/js/libs/library_godot_javascript_singleton.js16
-rw-r--r--platform/web/web_main.cpp4
9 files changed, 68 insertions, 15 deletions
diff --git a/platform/web/SCsub b/platform/web/SCsub
index 3d36a888d6..e81f2ec516 100644
--- a/platform/web/SCsub
+++ b/platform/web/SCsub
@@ -71,8 +71,6 @@ if env["dlink_enabled"]:
sys_env.Append(LINKFLAGS=["-s", "MAIN_MODULE=1"])
sys_env.Append(LINKFLAGS=["-s", "EXPORT_ALL=1"])
sys_env.Append(LINKFLAGS=["-s", "WARN_ON_UNDEFINED_SYMBOLS=0"])
- # Force exporting the standard library (printf, malloc, etc.)
- sys_env["ENV"]["EMCC_FORCE_STDLIBS"] = "libc,libc++,libc++abi"
sys_env["CCFLAGS"].remove("-fvisibility=hidden")
sys_env["LINKFLAGS"].remove("-fvisibility=hidden")
diff --git a/platform/web/audio_driver_web.cpp b/platform/web/audio_driver_web.cpp
index dd986e650c..22487d2756 100644
--- a/platform/web/audio_driver_web.cpp
+++ b/platform/web/audio_driver_web.cpp
@@ -33,6 +33,8 @@
#include "godot_audio.h"
#include "core/config/project_settings.h"
+#include "core/object/object.h"
+#include "scene/main/node.h"
#include "servers/audio/audio_stream.h"
#include <emscripten.h>
@@ -51,6 +53,21 @@ void AudioDriverWeb::_latency_update_callback(float p_latency) {
AudioDriverWeb::audio_context.output_latency = p_latency;
}
+void AudioDriverWeb::_sample_playback_finished_callback(const char *p_playback_object_id) {
+ const ObjectID playback_id = ObjectID(String::to_int(p_playback_object_id));
+
+ Object *playback_object = ObjectDB::get_instance(playback_id);
+ if (playback_object == nullptr) {
+ return;
+ }
+ Ref<AudioSamplePlayback> playback = Object::cast_to<AudioSamplePlayback>(playback_object);
+ if (playback.is_null()) {
+ return;
+ }
+
+ AudioServer::get_singleton()->stop_sample_playback(playback);
+}
+
void AudioDriverWeb::_audio_driver_process(int p_from, int p_samples) {
int32_t *stream_buffer = reinterpret_cast<int32_t *>(output_rb);
const int max_samples = memarr_len(output_rb);
@@ -132,6 +149,9 @@ Error AudioDriverWeb::init() {
if (!input_rb) {
return ERR_OUT_OF_MEMORY;
}
+
+ godot_audio_sample_set_finished_callback(&_sample_playback_finished_callback);
+
return OK;
}
diff --git a/platform/web/audio_driver_web.h b/platform/web/audio_driver_web.h
index 298ad90fae..46c5ce4de1 100644
--- a/platform/web/audio_driver_web.h
+++ b/platform/web/audio_driver_web.h
@@ -58,6 +58,7 @@ private:
WASM_EXPORT static void _state_change_callback(int p_state);
WASM_EXPORT static void _latency_update_callback(float p_latency);
+ WASM_EXPORT static void _sample_playback_finished_callback(const char *p_playback_object_id);
static AudioDriverWeb *singleton;
diff --git a/platform/web/detect.py b/platform/web/detect.py
index cb4dac1125..79485ea28a 100644
--- a/platform/web/detect.py
+++ b/platform/web/detect.py
@@ -78,6 +78,7 @@ def get_flags():
# -Os reduces file size by around 5 MiB over -O3. -Oz only saves about
# 100 KiB over -Os, which does not justify the negative impact on
# run-time performance.
+ # Note that this overrides the "auto" behavior for target/dev_build.
"optimize": "size",
}
diff --git a/platform/web/godot_audio.h b/platform/web/godot_audio.h
index 8bebbcf7de..dd5bec00cf 100644
--- a/platform/web/godot_audio.h
+++ b/platform/web/godot_audio.h
@@ -57,6 +57,7 @@ extern void godot_audio_sample_set_pause(const char *p_playback_object_id, bool
extern int godot_audio_sample_is_active(const char *p_playback_object_id);
extern void godot_audio_sample_update_pitch_scale(const char *p_playback_object_id, float p_pitch_scale);
extern void godot_audio_sample_set_volumes_linear(const char *p_playback_object_id, int *p_buses_buf, int p_buses_size, float *p_volumes_buf, int p_volumes_size);
+extern void godot_audio_sample_set_finished_callback(void (*p_callback)(const char *));
extern void godot_audio_sample_bus_set_count(int p_count);
extern void godot_audio_sample_bus_remove(int p_index);
diff --git a/platform/web/js/libs/library_godot_audio.js b/platform/web/js/libs/library_godot_audio.js
index 4bca13d2d6..0b16b07261 100644
--- a/platform/web/js/libs/library_godot_audio.js
+++ b/platform/web/js/libs/library_godot_audio.js
@@ -142,7 +142,7 @@ class Sample {
* @returns {void}
*/
clear() {
- this.audioBuffer = null;
+ this.setAudioBuffer(null);
GodotAudio.Sample.delete(this.id);
}
@@ -432,7 +432,7 @@ class SampleNode {
/** @type {number} */
this._playbackRate = 44100;
/** @type {LoopMode} */
- this.loopMode = 'disabled';
+ this.loopMode = options.loopMode ?? this.getSample().loopMode ?? 'disabled';
/** @type {number} */
this._pitchScale = 1;
/** @type {number} */
@@ -445,7 +445,6 @@ class SampleNode {
this._onended = null;
this.setPlaybackRate(options.playbackRate ?? 44100);
- this.loopMode = options.loopMode ?? this.getSample().loopMode ?? 'disabled';
this._source.buffer = this.getSample().getAudioBuffer();
this._addEndedListener();
@@ -688,9 +687,15 @@ class SampleNode {
}
switch (self.getSample().loopMode) {
- case 'disabled':
+ case 'disabled': {
+ const id = this.id;
self.stop();
- break;
+ if (GodotAudio.sampleFinishedCallback != null) {
+ const idCharPtr = GodotRuntime.allocString(id);
+ GodotAudio.sampleFinishedCallback(idCharPtr);
+ GodotRuntime.free(idCharPtr);
+ }
+ } break;
case 'forward':
case 'backward':
self.restart();
@@ -777,8 +782,7 @@ class Bus {
*/
static move(fromIndex, toIndex) {
const movedBus = GodotAudio.Bus.getBus(fromIndex);
- let buses = GodotAudio.buses;
- buses = buses.filter((_, i) => i !== fromIndex);
+ const buses = GodotAudio.buses.filter((_, i) => i !== fromIndex);
// Inserts at index.
buses.splice(toIndex - 1, 0, movedBus);
GodotAudio.buses = buses;
@@ -1092,6 +1096,12 @@ const _GodotAudio = {
busSolo: null,
Bus,
+ /**
+ * Callback to signal that a sample has finished.
+ * @type {(playbackObjectIdPtr: number) => void | null}
+ */
+ sampleFinishedCallback: null,
+
/** @type {AudioContext} */
ctx: null,
input: null,
@@ -1369,7 +1379,7 @@ const _GodotAudio = {
*/
set_sample_bus_volume_db: function (busIndex, volumeDb) {
const bus = GodotAudio.Bus.getBus(busIndex);
- bus.volumeDb = volumeDb;
+ bus.setVolumeDb(volumeDb);
},
/**
@@ -1766,6 +1776,17 @@ const _GodotAudio = {
godot_audio_sample_bus_set_mute: function (bus, enable) {
GodotAudio.set_sample_bus_mute(bus, Boolean(enable));
},
+
+ godot_audio_sample_set_finished_callback__proxy: 'sync',
+ godot_audio_sample_set_finished_callback__sig: 'vi',
+ /**
+ * Sets the finished callback
+ * @param {Number} callbackPtr Finished callback pointer
+ * @returns {void}
+ */
+ godot_audio_sample_set_finished_callback: function (callbackPtr) {
+ GodotAudio.sampleFinishedCallback = GodotRuntime.get_func(callbackPtr);
+ },
};
autoAddDeps(_GodotAudio, '$GodotAudio');
diff --git a/platform/web/js/libs/library_godot_input.js b/platform/web/js/libs/library_godot_input.js
index 7ea89d553f..6e3b97023d 100644
--- a/platform/web/js/libs/library_godot_input.js
+++ b/platform/web/js/libs/library_godot_input.js
@@ -112,6 +112,7 @@ const GodotIME = {
ime.style.top = '0px';
ime.style.width = '100%';
ime.style.height = '40px';
+ ime.style.pointerEvents = 'none';
ime.style.display = 'none';
ime.contentEditable = 'true';
diff --git a/platform/web/js/libs/library_godot_javascript_singleton.js b/platform/web/js/libs/library_godot_javascript_singleton.js
index b17fde1544..6bb69bca95 100644
--- a/platform/web/js/libs/library_godot_javascript_singleton.js
+++ b/platform/web/js/libs/library_godot_javascript_singleton.js
@@ -81,11 +81,16 @@ const GodotJSWrapper = {
case 0:
return null;
case 1:
- return !!GodotRuntime.getHeapValue(val, 'i64');
- case 2:
- return GodotRuntime.getHeapValue(val, 'i64');
+ return Boolean(GodotRuntime.getHeapValue(val, 'i64'));
+ case 2: {
+ // `heap_value` may be a bigint.
+ const heap_value = GodotRuntime.getHeapValue(val, 'i64');
+ return heap_value >= Number.MIN_SAFE_INTEGER && heap_value <= Number.MAX_SAFE_INTEGER
+ ? Number(heap_value)
+ : heap_value;
+ }
case 3:
- return GodotRuntime.getHeapValue(val, 'double');
+ return Number(GodotRuntime.getHeapValue(val, 'double'));
case 4:
return GodotRuntime.parseString(GodotRuntime.getHeapValue(val, '*'));
case 24: // OBJECT
@@ -110,6 +115,9 @@ const GodotJSWrapper = {
}
GodotRuntime.setHeapValue(p_exchange, p_val, 'double');
return 3; // FLOAT
+ } else if (type === 'bigint') {
+ GodotRuntime.setHeapValue(p_exchange, p_val, 'i64');
+ return 2; // INT
} else if (type === 'string') {
const c_str = GodotRuntime.allocString(p_val);
GodotRuntime.setHeapValue(p_exchange, c_str, '*');
diff --git a/platform/web/web_main.cpp b/platform/web/web_main.cpp
index 04513f6d57..d0c3bd7c0e 100644
--- a/platform/web/web_main.cpp
+++ b/platform/web/web_main.cpp
@@ -35,6 +35,8 @@
#include "core/config/engine.h"
#include "core/io/resource_loader.h"
#include "main/main.h"
+#include "scene/main/scene_tree.h"
+#include "scene/main/window.h" // SceneTree only forward declares it.
#include <emscripten/emscripten.h>
#include <stdlib.h>
@@ -130,7 +132,7 @@ extern EMSCRIPTEN_KEEPALIVE int godot_web_main(int argc, char *argv[]) {
if (Engine::get_singleton()->is_project_manager_hint() && FileAccess::exists("/tmp/preload.zip")) {
PackedStringArray ps;
ps.push_back("/tmp/preload.zip");
- os->get_main_loop()->emit_signal(SNAME("files_dropped"), ps, -1);
+ SceneTree::get_singleton()->get_root()->emit_signal(SNAME("files_dropped"), ps);
}
#endif
emscripten_set_main_loop(main_loop_callback, -1, false);