diff --git a/SConstruct b/SConstruct index 91efbd8..fb8e654 100644 --- a/SConstruct +++ b/SConstruct @@ -8,11 +8,9 @@ VariantDir('build/src','extension/src', duplicate=False) VariantDir('build/T5Integration','extension/T5Integration', duplicate=False) env = SConscript('godot-cpp/SConstruct') -env['CXXFLAGS'].remove('/std:c++17') -env.Append(CXXFLAGS=['/std:c++20']) tilt_five_headers_path = 'extension/TiltFiveNDK/include' -tilt_five_library_path = 'extension/TiltFiveNDK/lib/' + { 'windows' : 'win/x86_64', 'linux' : 'linux/x86_64'}[env["platform"]] -tilt_five_library = 'TiltFiveNative.dll.if' +tilt_five_library_path = 'extension/TiltFiveNDK/lib/' + { 'windows' : 'win/x86_64', 'linux' : 'linux/x86_64', 'android' : 'android/arm64-v8a'}[env["platform"]] +tilt_five_library = {'windows' : 'TiltFiveNative.dll.if', 'linux' : 'libTiltFiveNative.so', 'android' : 'libTiltFiveNative.so'}[env["platform"]] # For the reference: # - CCFLAGS are compilation flags shared between C and C++ @@ -31,16 +29,39 @@ env.Append(LIBPATH=[tilt_five_library_path]) env.Append(LIBS=[tilt_five_library]) if env['platform'] == 'windows': + env['t5_shared_lib'] = 'TiltFiveNative.dll' + env['CXXFLAGS'].remove('/std:c++17') + env.Append(CXXFLAGS=['/std:c++20']) env.Append(CXXFLAGS=['/Zc:__cplusplus']) library = env.SharedLibrary( 'build/bin/libgdtiltfive{}{}'.format(env['suffix'], env['SHLIBSUFFIX']), source=sources, ) +elif env['platform'] == 'linux': + env['t5_shared_lib'] = 'libTiltFiveNative.so' + env['CXXFLAGS'].remove('-std=c++17') + env.Append(CXXFLAGS=['-std=c++20']) + env.Append(RPATH=env.Literal('\\$$ORIGIN' )) + library = env.SharedLibrary( + 'build/bin/libgdtiltfive{}{}'.format(env['suffix'], env['SHLIBSUFFIX']), + source=sources, + ) +elif env['platform'] == 'android': + env['t5_shared_lib'] = 'libTiltFiveNative.so' + env['CXXFLAGS'].remove('-std=c++17') + env.Append(CXXFLAGS=['-std=c++20']) + env.Append(CXXFLAGS=['-stdlib=libc++']) + env.Append(CCFLAGS=['-fPIC']) + env.Append(RPATH=env.Literal('\\$$ORIGIN' )) + library = env.SharedLibrary( + 'build/bin/libgdtiltfive{}{}'.format(env['suffix'], env['SHLIBSUFFIX']), + source=sources, + ) f1 = env.Command('example.gd/addons/tiltfive/bin/libgdtiltfive{}{}'.format(env['suffix'], env['SHLIBSUFFIX']), library, Copy('$TARGET', '$SOURCE') ) -f2 = env.Command('example.gd/addons/tiltfive/bin/TiltFiveNative.dll', tilt_five_library_path + '/TiltFiveNative.dll', Copy('$TARGET', '$SOURCE') ) +f2 = env.Command('example.gd/addons/tiltfive/bin/{}'.format(env['t5_shared_lib']), tilt_five_library_path + '/{}'.format(env['t5_shared_lib']), Copy('$TARGET', '$SOURCE') ) f3 = env.Command('example.csharp/addons/tiltfive/bin/libgdtiltfive{}{}'.format(env['suffix'], env['SHLIBSUFFIX']), library, Copy('$TARGET', '$SOURCE') ) -f4 = env.Command('example.csharp/addons/tiltfive/bin/TiltFiveNative.dll', tilt_five_library_path + '/TiltFiveNative.dll', Copy('$TARGET', '$SOURCE') ) +f4 = env.Command('example.csharp/addons/tiltfive/bin/{}'.format(env['t5_shared_lib']), tilt_five_library_path + '/{}'.format(env['t5_shared_lib']), Copy('$TARGET', '$SOURCE') ) env.Alias('example', [f1, f2, f3, f4]) diff --git a/example.gd/addons/tiltfive/tiltfive.gdextension b/example.gd/addons/tiltfive/tiltfive.gdextension index 96362ae..aa4e9e7 100644 --- a/example.gd/addons/tiltfive/tiltfive.gdextension +++ b/example.gd/addons/tiltfive/tiltfive.gdextension @@ -10,6 +10,9 @@ T5Gameboard = "res://addons/tiltfive/assets/board.svg" windows.x86_64.debug = "res://addons/tiltfive/bin/libgdtiltfive.windows.template_debug.x86_64.dll" windows.x86_64.release = "res://addons/tiltfive/bin/libgdtiltfive.windows.template_release.x86_64.dll" +linux.x86_64.debug = "res://addons/tiltfive/bin/libgdtiltfive.linux.template_debug.x86_64.so" +linux.x86_64.release = "res://addons/tiltfive/bin/libgdtiltfive.linux.template_release.x86_64.so" + [dependencies] @@ -19,4 +22,10 @@ windows.x86_64.debug = { windows.x86_64.release = { "res://addons/tiltfive/bin/TiltFiveNative.dll" : "" } +linux.x86_64.debug = { + "res://addons/tiltfive/bin/libTiltFiveNative.so" : "" +} +linux.x86_64.release = { + "res://addons/tiltfive/bin/libTiltFiveNative.so" : "" +} diff --git a/extension/T5Integration/Glasses.cpp b/extension/T5Integration/Glasses.cpp index a56c195..4ad4687 100644 --- a/extension/T5Integration/Glasses.cpp +++ b/extension/T5Integration/Glasses.cpp @@ -2,6 +2,8 @@ #include #include #include +#include + using TaskSystem::task_sleep; using TaskSystem::run_in_foreground; @@ -28,7 +30,9 @@ namespace T5Integration { _scheduler = ObjectRegistry::scheduler(); _math = ObjectRegistry::math(); - _state.reset(GlassesState::UNAVAILABLE, true); + _state.reset(GlassesState::UNAVAILABLE); + _previous_event_state.reset(GlassesState::UNAVAILABLE); + _previous_update_state.reset(GlassesState::UNAVAILABLE); set_swap_chain_size(1); } @@ -178,6 +182,9 @@ namespace T5Integration { while (_glasses_handle && _state.is_current(GlassesState::SUSTAIN_CONNECTION)) { T5_ConnectionState connectionState; + GlassesFlags _previous_monitor_state; + + _previous_monitor_state.sync_from(_state); { std::lock_guard lock(g_t5_exclusivity_group_1); @@ -264,15 +271,16 @@ namespace T5Integration { } } - if (_state.any_changed(GlassesState::READY | GlassesState::GRAPHICS_INIT)) { + if (_state.any_changed(_previous_monitor_state, GlassesState::READY | GlassesState::GRAPHICS_INIT)) { if (_state.is_current(GlassesState::READY | GlassesState::GRAPHICS_INIT)) _state.set(GlassesState::CONNECTED); else _state.clear(GlassesState::CONNECTED); } - if (_state.is_current(GlassesState::READY) && !_state.is_current(GlassesState::TRACKING_WANDS)) { - _state.set(GlassesState::TRACKING_WANDS); - _scheduler->add_task(monitor_wands()); + if (_state.is_current(GlassesState::READY)) { + if(_state.set_and_was_toggled(GlassesState::TRACKING_WANDS)) { + _scheduler->add_task(monitor_wands()); + } } co_await task_sleep( @@ -427,7 +435,6 @@ namespace T5Integration { } void Glasses::disconnect() { - if (_state.is_current(GlassesState::READY)) { T5_Result result; { @@ -442,6 +449,18 @@ namespace T5Integration { on_glasses_released(); } + void Glasses::start_display() { + if(_state.set_and_was_toggled(GlassesState::DISPLAY_STARTED)) { + on_start_display(); + } + } + + void Glasses::stop_display() { + if(_state.clear_and_was_toggled(GlassesState::DISPLAY_STARTED)) { + on_stop_display(); + } + } + bool Glasses::initialize_graphics() { auto service = ObjectRegistry::service(); @@ -573,26 +592,15 @@ namespace T5Integration { bool Glasses::update_connection() { - static GlassesFlags::FlagType prev_changes = 0; - static GlassesFlags::FlagType prev_current = 0; - auto changes = _state.get_changes(); - auto current_state = _state.get_current(); - - // if(changes != prev_changes || current_state != prev_current) { - // log_message("Glasses::update_connection changes ", changes, " Current ", current_state); - // prev_changes = changes; - // prev_current = current_state; - // } - - if((changes & GlassesState::CONNECTED) == GlassesState::CONNECTED) { - if(current_state & GlassesState::CONNECTED) { - on_glasses_reserved(); - } else { + if(_state.became_set(_previous_update_state, GlassesState::CONNECTED)) { + on_glasses_reserved(); + } + if(_state.became_clear(_previous_update_state, GlassesState::CONNECTED)) { + stop_display(); on_glasses_dropped(); - - } } + _previous_update_state.sync_from(_state); return true; } @@ -605,48 +613,34 @@ namespace T5Integration { void Glasses::get_events(int index, std::vector& out_events) { - static GlassesFlags::FlagType prev_changes = 0; - static GlassesFlags::FlagType prev_current = 0; - - auto changes = _state.get_changes(); - auto current_state = _state.get_current(); - - // if(changes != prev_changes || current_state != prev_current) { - // log_message("T5Service::get_events ", changes, " Current ", current_state); - // prev_changes = changes; - // prev_current = current_state; - // } - if((changes & GlassesState::CREATED) == GlassesState::CREATED) { - if(current_state & GlassesState::CREATED) { - out_events.push_back(GlassesEvent(index, GlassesEvent::E_ADDED)); - - } else { - out_events.push_back(GlassesEvent(index, GlassesEvent::E_LOST)); - } + if(_state.became_set(_previous_event_state, GlassesState::CREATED)) { + out_events.push_back(GlassesEvent(index, GlassesEvent::E_ADDED)); + } + if(_state.became_clear(_previous_event_state, GlassesState::CREATED)) { + out_events.push_back(GlassesEvent(index, GlassesEvent::E_LOST)); } - if((changes & GlassesState::UNAVAILABLE) == GlassesState::UNAVAILABLE) { - if(current_state & GlassesState::UNAVAILABLE) { + + if(_state.became_set(_previous_event_state, GlassesState::UNAVAILABLE)) { out_events.push_back(GlassesEvent(index, GlassesEvent::E_UNAVAILABLE)); - } else { + } + if(_state.became_clear(_previous_event_state, GlassesState::UNAVAILABLE)) { out_events.push_back(GlassesEvent(index, GlassesEvent::E_AVAILABLE)); - } } - if((changes & GlassesState::CONNECTED) == GlassesState::CONNECTED) { - if(current_state & GlassesState::CONNECTED) { + + if(_state.became_set(_previous_event_state, GlassesState::CONNECTED)) { out_events.push_back(GlassesEvent(index, GlassesEvent::E_CONNECTED)); - } else { + } + if(_state.became_clear(_previous_event_state, GlassesState::CONNECTED)) { out_events.push_back(GlassesEvent(index, GlassesEvent::E_DISCONNECTED)); - - } } - if((changes & GlassesState::TRACKING) == GlassesState::TRACKING) { - out_events.push_back(GlassesEvent(index, current_state & GlassesState::TRACKING ? GlassesEvent::E_TRACKING : GlassesEvent::E_NOT_TRACKING)); + + if(_state.became_set(_previous_event_state, GlassesState::TRACKING)) { + out_events.push_back(GlassesEvent(index, GlassesEvent::E_TRACKING)); } - if((changes & GlassesState::ERROR) == GlassesState::ERROR) { - // There is currently no way to recover from the error state - out_events.push_back(GlassesEvent(index, current_state & GlassesState::ERROR ? GlassesEvent::E_STOPPED_ON_ERROR : GlassesEvent::E_AVAILABLE)); + if(_state.became_clear(_previous_event_state, GlassesState::TRACKING)) { + out_events.push_back(GlassesEvent(index, GlassesEvent::E_NOT_TRACKING)); } - _state.reset_changes(); - } + _previous_event_state.sync_from(_state); + } } \ No newline at end of file diff --git a/extension/T5Integration/Glasses.h b/extension/T5Integration/Glasses.h index add02ad..837f54f 100644 --- a/extension/T5Integration/Glasses.h +++ b/extension/T5Integration/Glasses.h @@ -17,16 +17,17 @@ using TaskSystem::Scheduler; float const g_default_fov = 48.0f; namespace GlassesState { - const uint16_t READY = 0x00000001; //000000001 - const uint16_t GRAPHICS_INIT = 0x00000002; //000000010 - const uint16_t SUSTAIN_CONNECTION = 0x00000004; //000000100 - - const uint16_t CREATED = 0x00000008; //000001000 - const uint16_t UNAVAILABLE = 0x00000010; //000010000 - const uint16_t TRACKING = 0x00000020; //000100000 - const uint16_t CONNECTED = 0x00000040; //001000000 - const uint16_t TRACKING_WANDS = 0x00000080; //010000000 - const uint16_t ERROR = 0x00000100; //100000000 + const uint16_t READY = 0x00000001; //0000000001 + const uint16_t GRAPHICS_INIT = 0x00000002; //0000000010 + const uint16_t SUSTAIN_CONNECTION = 0x00000004; //0000000100 + + const uint16_t CREATED = 0x00000008; //0000001000 + const uint16_t UNAVAILABLE = 0x00000010; //0000010000 + const uint16_t TRACKING = 0x00000020; //0000100000 + const uint16_t CONNECTED = 0x00000040; //0001000000 + const uint16_t TRACKING_WANDS = 0x00000080; //0010000000 + const uint16_t ERROR = 0x00000100; //0100000000 + const uint16_t DISPLAY_STARTED = 0x00000200; //1000000000 } struct GlassesEvent { @@ -82,10 +83,13 @@ class Glasses bool is_available(); bool is_tracking(); - bool allocate_handle(T5_Context context); + bool allocate_handle(T5_Context context); void destroy_handle(); void connect(const std::string_view application_name); void disconnect(); + void start_display(); + void stop_display(); + float get_ipd(); float get_fov(); @@ -128,6 +132,8 @@ class Glasses void set_swap_chain_texture_pair(int swap_chain_idx, intptr_t left_eye_handle, intptr_t right_eye_handle); void set_swap_chain_texture_array(int swap_chain_idx, intptr_t array_handle); + virtual void on_start_display() {} + virtual void on_stop_display() {} virtual void on_glasses_reserved() {} virtual void on_glasses_released() {} virtual void on_glasses_dropped() {} @@ -172,6 +178,8 @@ class Glasses float _ipd = 0.059f; GlassesFlags _state; + GlassesFlags _previous_event_state; + GlassesFlags _previous_update_state; bool _is_upside_down_texture = false; diff --git a/extension/T5Integration/Logging.h b/extension/T5Integration/Logging.h index 094b40c..86bb7d1 100644 --- a/extension/T5Integration/Logging.h +++ b/extension/T5Integration/Logging.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include namespace T5Integration { @@ -58,6 +59,10 @@ void log_message(T var1, Types... var2) { #define LOG_TOGGLE(INIT, TEST, MSG1, MSG2) { static bool toggle ## __LINE__ = (INIT); T5Integration::log_toggle((TEST), toggle ## __LINE__, MSG1, MSG2); } #endif +#ifndef LOG_MESSAGE +#define LOG_MESSAGE(...) T5Integration::log_message(__func__, ":", __LINE__, " ", __VA_ARGS__) +#endif + #ifndef LOG_ERROR #define LOG_ERROR(message) T5Integration::log_error((message), __func__, __FILE__, __LINE__) #endif diff --git a/extension/T5Integration/StateFlags.h b/extension/T5Integration/StateFlags.h index dfd3dc9..97f864b 100644 --- a/extension/T5Integration/StateFlags.h +++ b/extension/T5Integration/StateFlags.h @@ -16,14 +16,15 @@ class StateFlags return _current.load(); } - FlagType get_changes() const + void set(FlagType state) { - return (_current.load() ^ _previous); + _current.fetch_or(state); } - void set(FlagType state) + bool set_and_was_toggled(FlagType state) { - _current.fetch_or(state); + T old = _current.fetch_or(state); + return (old & state) != state; } void clear(FlagType state) @@ -31,18 +32,20 @@ class StateFlags _current.fetch_and(~state); } - void clear_all(bool clear_changes = true) + bool clear_and_was_toggled(FlagType state) + { + T old = _current.fetch_and(~state); + return (old & state) == state; + } + + void clear_all() { _current.store(0); - if(clear_changes) - _previous = 0; } - void reset(FlagType state, bool clear_changes = false) + void reset(FlagType state) { _current.store(state); - if(clear_changes) - _previous = state; } bool is_current(FlagType state) const @@ -60,25 +63,25 @@ class StateFlags return (_current.load() & state) != state; } - bool any_changed(FlagType state) const + bool any_changed(const StateFlags& from, FlagType query_state) const { - return ((_current.load() ^ _previous) & state) != 0; + return ((_current.load() ^ from._current.load()) & query_state) != 0; } - bool became_set(FlagType state) const { - return (_current.load() & state) == state && (_previous & state) != state; + bool became_set(const StateFlags& from, FlagType query_state) const { + return (_current.load() & query_state) == query_state && + (from._current.load() & query_state) != query_state; } - bool became_clear(FlagType state) const { - return (_current.load() & state) != state && (_previous & state) == state; + bool became_clear(const StateFlags& from, FlagType query_state) const { + return (_current.load() & query_state) != query_state && + (from._current.load() & query_state) == query_state; } - void reset_changes() - { - _previous = _current; + void sync_from(const StateFlags& from) { + _current.store(from._current.load()); } private: std::atomic _current; - FlagType _previous; }; diff --git a/extension/T5Integration/T5Service.cpp b/extension/T5Integration/T5Service.cpp index 7ae438b..9348f86 100644 --- a/extension/T5Integration/T5Service.cpp +++ b/extension/T5Integration/T5Service.cpp @@ -12,61 +12,63 @@ T5Service::T5Service() { _graphics_api = T5_GraphicsApi::kT5_GraphicsApi_None; _scheduler = ObjectRegistry::scheduler(); - _state.clear_all(true); + _state.clear_all(); + _previous_event_state.clear_all(); } T5Service::~T5Service() { - stop_service(); } bool T5Service::start_service(const std::string_view application_id, std::string_view application_version, uint8_t sdk_type) { - if(_state.is_any_current(T5ServiceState::RUNNING | T5ServiceState::STARTING)) + if(_state.is_current(T5ServiceState::RUNNING)) return true; - if(_graphics_api == T5_GraphicsApi::kT5_GraphicsApi_None) { - LOG_ERROR("TiltFive graphics api is not set"); - return false; - } + if(_state.set_and_was_toggled(T5ServiceState::STARTING)) + { + if(_graphics_api == T5_GraphicsApi::kT5_GraphicsApi_None) { + LOG_ERROR("TiltFive graphics api is not set"); + return false; + } - T5_ClientInfo clientInfo; - clientInfo.applicationId = application_id.data(); - clientInfo.applicationVersion = application_version.data(); - clientInfo.sdkType = sdk_type; - - auto result = t5CreateContext(&_context, &clientInfo, nullptr); + T5_ClientInfo clientInfo; + clientInfo.applicationId = application_id.data(); + clientInfo.applicationVersion = application_version.data(); + clientInfo.sdkType = sdk_type; + + auto result = t5CreateContext(&_context, &clientInfo, nullptr); - if(result != T5_SUCCESS) { - LOG_T5_ERROR(result); - return false; - } - - _state.set(T5ServiceState::STARTING); + if(result != T5_SUCCESS) { + LOG_T5_ERROR(result); + return false; + } - _scheduler->start(); - _scheduler->add_task(startup_checks()); + _state.set(T5ServiceState::STARTING); + _scheduler->start(); + _scheduler->add_task(startup_checks()); + } return true; } void T5Service::stop_service() { - if(_state.is_not_current(T5ServiceState::RUNNING)) - return; - - _state.clear(T5ServiceState::RUNNING); - - _scheduler->stop(); - for(int i = 0; i < _glasses_list.size(); i++) { - _glasses_list[i]->disconnect(); - _glasses_list[i]->destroy_handle(); - } - _glasses_list.clear(); + if( _state.clear_and_was_toggled(T5ServiceState::RUNNING) || + _state.clear_and_was_toggled(T5ServiceState::STARTING)) + { + _scheduler->stop(); + for(int i = 0; i < _glasses_list.size(); i++) { + _glasses_list[i]->stop_display(); + _glasses_list[i]->disconnect(); + _glasses_list[i]->destroy_handle(); + } + _glasses_list.clear(); - if(_context) - { - std::lock_guard lock(g_t5_exclusivity_group_1); - t5DestroyContext(&_context); + if(_context) + { + std::lock_guard lock(g_t5_exclusivity_group_1); + t5DestroyContext(&_context); + } + _context = nullptr; } - _context = nullptr; } std::optional T5Service::find_glasses_idx(const std::string_view glasses_id) { @@ -200,7 +202,6 @@ CotaskPtr T5Service::query_glasses_list() { break; parsed_id_list.emplace_back(str_view.substr(0, pos)); str_view.remove_prefix(pos + 1); - } co_await run_in_foreground; @@ -270,23 +271,19 @@ void T5Service::update_tracking() { } void T5Service::get_service_events(std::vector& out_events) { - - auto changes = _state.get_changes(); - auto current_state = _state.get_current(); - - if(_state.became_set(T5ServiceState::T5_UNAVAILABLE)) { + if(_state.became_set(_previous_event_state, T5ServiceState::T5_UNAVAILABLE)) { out_events.push_back(T5ServiceEvent(T5ServiceEvent::E_T5_UNAVAILABLE)); } - if(_state.became_set(T5ServiceState::T5_INCOMPATIBLE_VERSION)) { + if(_state.became_set(_previous_event_state, T5ServiceState::T5_INCOMPATIBLE_VERSION)) { out_events.push_back(T5ServiceEvent(T5ServiceEvent::E_T5_INCOMPATIBLE_VERSION)); } - if(_state.became_set(T5ServiceState::RUNNING)) { + if(_state.became_set(_previous_event_state, T5ServiceState::RUNNING)) { out_events.push_back(T5ServiceEvent(T5ServiceEvent::E_RUNNING)); } - if(_state.became_clear(T5ServiceState::RUNNING)) { + if(_state.became_clear(_previous_event_state, T5ServiceState::RUNNING)) { out_events.push_back(T5ServiceEvent(T5ServiceEvent::E_STOPPED)); } - _state.reset_changes(); + _previous_event_state.sync_from(_state); } void T5Service::get_glasses_events(std::vector& out_events) { diff --git a/extension/T5Integration/T5Service.h b/extension/T5Integration/T5Service.h index 69269b1..db992ce 100644 --- a/extension/T5Integration/T5Service.h +++ b/extension/T5Integration/T5Service.h @@ -111,6 +111,7 @@ class T5Service { std::vector _glasses_list; T5ServiceFlags _state; + T5ServiceFlags _previous_event_state; std::chrono::milliseconds _poll_rate_for_monitoring = 2s; std::chrono::milliseconds _poll_rate_for_retry = 100ms; diff --git a/extension/T5Integration/Wand.cpp b/extension/T5Integration/Wand.cpp index d385528..e84c28e 100644 --- a/extension/T5Integration/Wand.cpp +++ b/extension/T5Integration/Wand.cpp @@ -151,8 +151,8 @@ void WandService::monitor_wands(std::stop_token s_token) { if(event.type != kT5_WandStreamEventType_Desync) { std::lock_guard lock(_list_access); - auto opt_wand_ptr = find_wand(_wand_list, event.wandId); - auto wand = opt_wand_ptr ? opt_wand_ptr.value() : &_wand_list.emplace_back(); + auto wand_ptr = find_wand(_wand_list, event.wandId); + auto wand = wand_ptr ? wand_ptr : &_wand_list.emplace_back(); wand->update_from_stream_event(event); } else { diff --git a/extension/T5Integration/Wand.h b/extension/T5Integration/Wand.h index 8a23762..e872f39 100644 --- a/extension/T5Integration/Wand.h +++ b/extension/T5Integration/Wand.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include #include @@ -81,15 +82,15 @@ class WandService { T5_Result _last_wand_error; }; -inline std::optional find_wand(const WandList& list, T5_WandHandle handle) { +inline Wand* find_wand(WandList& list, T5_WandHandle handle) { auto it = std::find_if(list.begin(), list.end(), [handle](auto& test_wand) { return test_wand._handle == handle; }); if(it != list.end()) - return it._Ptr; - return std::nullopt; + return std::addressof(*it); + return nullptr; } } // T5Integration \ No newline at end of file diff --git a/extension/src/GodotT5Glasses.cpp b/extension/src/GodotT5Glasses.cpp index d7aab3a..339258b 100644 --- a/extension/src/GodotT5Glasses.cpp +++ b/extension/src/GodotT5Glasses.cpp @@ -97,11 +97,12 @@ void GodotT5Glasses::on_glasses_reserved() { XRServer *xr_server = XRServer::get_singleton(); ERR_FAIL_NULL(xr_server); - auto tracker_name = std::format("/user/{}/head", get_id()); + char buffer[64]; + ERR_FAIL_COND(snprintf(buffer, 64, "/user/%s/head", get_id().c_str()) > 64); _head.instantiate(); _head->set_tracker_type(XRServer::TRACKER_HEAD); - _head->set_tracker_name(tracker_name.c_str()); + _head->set_tracker_name(buffer); _head->set_tracker_desc("Players head"); xr_server->add_tracker(_head); } @@ -166,11 +167,12 @@ void GodotT5Glasses::add_tracker() { Ref positional_tracker; positional_tracker.instantiate(); - auto tracker_name = std::format("/user/{}/wand_{}", get_id(), new_id); + char buffer[64]; + ERR_FAIL_COND(snprintf(buffer, 64, "/user/%s/wand_%d", get_id().c_str(), new_id) > 64); - positional_tracker->set_tracker_type(XRServer::TRACKER_CONTROLLER); - positional_tracker->set_tracker_name(tracker_name.c_str()); - positional_tracker->set_tracker_desc(tracker_name.c_str()); + positional_tracker->set_tracker_type(XRServer::TRACKER_CONTROLLER); + positional_tracker->set_tracker_name(buffer); + positional_tracker->set_tracker_desc("Tracks wand"); _wand_trackers.push_back(positional_tracker); } diff --git a/extension/src/OpenGLGlasses.cpp b/extension/src/OpenGLGlasses.cpp index 8c2d588..1dc1727 100644 --- a/extension/src/OpenGLGlasses.cpp +++ b/extension/src/OpenGLGlasses.cpp @@ -20,7 +20,8 @@ OpenGLGlasses::OpenGLGlasses(std::string_view id) void OpenGLGlasses::SwapChainTextures::allocate_textures(int width, int height) { auto render_server = RenderingServer::get_singleton(); - deallocate_textures(); + if(is_allocated) + deallocate_textures(); Ref dummy_image = Image::create(width, height, false, godot::Image::FORMAT_RGBA8); godot::Color bg(0,0,0); @@ -32,10 +33,13 @@ void OpenGLGlasses::SwapChainTextures::allocate_textures(int width, int height) render_tex.instantiate(); render_tex->create_from_images(image_arr); + + is_allocated = true; } void OpenGLGlasses::SwapChainTextures::deallocate_textures() { render_tex.unref(); + is_allocated = false; } void OpenGLGlasses::allocate_textures() { @@ -58,18 +62,11 @@ void OpenGLGlasses::deallocate_textures() { } } -void OpenGLGlasses::on_glasses_reserved() { - GodotT5Glasses::on_glasses_reserved(); +void OpenGLGlasses::on_start_display() { allocate_textures(); } -void OpenGLGlasses::on_glasses_released() { - GodotT5Glasses::on_glasses_released(); - deallocate_textures(); -} - -void OpenGLGlasses::on_glasses_dropped() { - GodotT5Glasses::on_glasses_dropped(); +void OpenGLGlasses::on_stop_display() { deallocate_textures(); } diff --git a/extension/src/OpenGLGlasses.h b/extension/src/OpenGLGlasses.h index 7d90345..586f7a1 100644 --- a/extension/src/OpenGLGlasses.h +++ b/extension/src/OpenGLGlasses.h @@ -16,6 +16,7 @@ namespace GodotT5Integration { void allocate_textures(int width, int height); void deallocate_textures(); + bool is_allocated = false; Ref render_tex; }; @@ -30,9 +31,8 @@ namespace GodotT5Integration { void allocate_textures(); void deallocate_textures(); - virtual void on_glasses_reserved() override; - virtual void on_glasses_released() override; - virtual void on_glasses_dropped() override; + virtual void on_start_display() override; + virtual void on_stop_display() override; private: diff --git a/extension/src/TiltFiveXRInterface.cpp b/extension/src/TiltFiveXRInterface.cpp index 6191922..d9c590d 100644 --- a/extension/src/TiltFiveXRInterface.cpp +++ b/extension/src/TiltFiveXRInterface.cpp @@ -205,6 +205,7 @@ void TiltFiveXRInterface::_start_display(TiltFiveXRInterface::GlassesIndexEntry& WARN_PRINT("Glasses need to be reserved to display viewport"); return; } + glasses->start_display(); entry.viewport_id = viewport->get_instance_id(); entry.gameboard_id = gameboard->get_instance_id(); @@ -220,11 +221,13 @@ void TiltFiveXRInterface::stop_display(const StringName glasses_id) { void TiltFiveXRInterface::_stop_display(GlassesIndexEntry& entry) { + auto glasses = entry.glasses.lock(); auto viewport = Object::cast_to(ObjectDB::get_instance(entry.viewport_id)); if(viewport) { viewport->set_use_xr(false); viewport->set_update_mode(godot::SubViewport::UpdateMode::UPDATE_DISABLED); } + glasses->stop_display(); entry.viewport_id = ObjectID(); entry.gameboard_id = ObjectID(); } diff --git a/extension/src/VulkanGlasses.cpp b/extension/src/VulkanGlasses.cpp index fc869f6..3411bf1 100644 --- a/extension/src/VulkanGlasses.cpp +++ b/extension/src/VulkanGlasses.cpp @@ -23,10 +23,10 @@ VulkanGlasses::VulkanGlasses(std::string_view id) } void VulkanGlasses::SwapChainTextures::allocate_textures(int width, int height) { - deallocate_textures(); + if(is_allocated) + deallocate_textures(); auto render_server = RenderingServer::get_singleton(); - auto service = T5Integration::ObjectRegistry::service(); auto render_device = render_server->get_rendering_device(); Ref texture_format_render; @@ -54,11 +54,15 @@ void VulkanGlasses::SwapChainTextures::allocate_textures(int width, int height) left_tex_handle = render_device->get_driver_resource(RenderingDevice::DRIVER_RESOURCE_VULKAN_IMAGE_VIEW, left_eye_tex, 0); right_tex_handle = render_device->get_driver_resource(RenderingDevice::DRIVER_RESOURCE_VULKAN_IMAGE_VIEW, right_eye_tex, 0); + + is_allocated = true; } void VulkanGlasses::SwapChainTextures::deallocate_textures() { + if(!is_allocated) + return; + auto render_server = RenderingServer::get_singleton(); - auto service = T5Integration::ObjectRegistry::service(); auto render_device = render_server->get_rendering_device(); if(right_eye_tex.is_valid()) @@ -67,6 +71,11 @@ void VulkanGlasses::SwapChainTextures::deallocate_textures() { render_device->free_rid(left_eye_tex); if(render_tex.is_valid()) render_device->free_rid(render_tex); + + left_tex_handle = 0; + right_tex_handle = 0; + + is_allocated = false; } void VulkanGlasses::allocate_textures() { @@ -95,18 +104,11 @@ void VulkanGlasses::deallocate_textures() { } } -void VulkanGlasses::on_glasses_reserved() { - GodotT5Glasses::on_glasses_reserved(); +void VulkanGlasses::on_start_display() { allocate_textures(); } -void VulkanGlasses::on_glasses_released() { - GodotT5Glasses::on_glasses_released(); - deallocate_textures(); -} - -void VulkanGlasses::on_glasses_dropped() { - GodotT5Glasses::on_glasses_dropped(); +void VulkanGlasses::on_stop_display() { deallocate_textures(); } diff --git a/extension/src/VulkanGlasses.h b/extension/src/VulkanGlasses.h index 376aa82..f74f2c2 100644 --- a/extension/src/VulkanGlasses.h +++ b/extension/src/VulkanGlasses.h @@ -12,6 +12,7 @@ namespace GodotT5Integration { void allocate_textures(int width, int height); void deallocate_textures(); + bool is_allocated = false; RID render_tex; RID left_eye_tex; RID right_eye_tex; @@ -31,10 +32,8 @@ namespace GodotT5Integration { void allocate_textures(); void deallocate_textures(); - virtual void on_glasses_reserved() override; - virtual void on_glasses_released() override; - virtual void on_glasses_dropped() override; - + virtual void on_start_display() override; + virtual void on_stop_display() override; private: