diff --git a/README.md b/README.md
index aa9d9dc..fe027eb 100644
--- a/README.md
+++ b/README.md
@@ -1,50 +1,44 @@
# TiltFiveGodot4
-TiltFiveGodot4 is **GDExtension** for the Godot 4 engine to connect to the [Tilt Five](https://www.tiltfive.com/)
-system. It extends Godot's **XRInterface** and has functions to connect glasses and signals for connection events.
-
-This extension is in an Alpha state and needs that latest Godot 4.1 to run. It currently needs the OpenGL renderer
-Vulkan support is coming.
+TiltFiveGodot4 is **GDExtension** for the Godot 4 engine to connect to the [Tilt Five](https://www.tiltfive.com/) system. It extends Godot's **XRInterface** and adds T5 Nodes to handle the creation of the XR rigs in the scene.
## Platforms
-Currently only Windows 10/11 is supported. Tilt Five Linux and Android support are recent additions and and support
-for those platforms will investigated.
+| | Renderer Forward+ | Renderer Mobile | Renderer Compatibility |
+| - | - | - | - |
+| Windows |✅| ✅ | ✅ |
+| Linux1 | ✓ |✓ | ✓ |
+| Android | | ❌ | |
+
+1. [Experimental Version](https://github.com/patrickdown/TiltFiveGodot4/releases/tag/1.1.0-linux-experimental3)
+
+## Usage
+
+TiltFiveGodot4 is available in the Godot Asset Library.
+
+Installable [Releases can also be found here](https://github.com/GodotVR/TiltFiveGodot4/releases).
+- Use `gdtiltfive_gdscript.zip` for gdscript projects
+- Use `gdtiltfive_csharp.zip` for C# projects
+
+Please refer to this [documentation](https://patrickdown.github.io/godot/tilt-five-godot-4.html) for installation.
## Build
### Prerequisites
+This extension requires a C++20 capable compiler.
+
Things you will need to know how to do.
* Use [scons](https://scons.org/)
* [Build GDExtensions](https://docs.godotengine.org/en/stable/tutorials/scripting/gdextension/gdextension_cpp_example.html)
### Building the extension
-Scons should be run from an environment that has the Microsoft x64 development tools setup.
-
-> `scons target=[template_debug | template_release]` Build the shared library. Result is in `build\bin`
-
-> `scons example target=[template_debug | template_release]` Copy build products to the `example.gd\addons\tilt-five\bin`
-
-## Starting with a new project
-
-To use this plugin in your own project:
-- Copy the `addons/tiltfive` folder into your project
-- Open Project->Project Settings
- - Click on the Plugins tab
- - Make sure the Tilt Five plugin is enabled
- - You may need to restart Godot
-- In the main scene add a T5Manager node
-- In the main scene add a T5Gameboard node
-- On the T5Manager node set the start location to the T5Gameboard node
-- Add lights and other items to your scene
+To build the plugin invoke `scons` from the root directory of the project. The build product will in `build\bin`. Invoking `scons example` will build the product and copy the binaries to the `example.gd\addons\tilt-five\bin` and `example.csharp\addons\tilt-five\bin` directories.
-Running should now show your scene on the Tilt Five system
+## Using the build products
-## Dependencies
+When built with the `example` option the `addons\tilt-five` directory can be copied from the `example.gd` or `example.csharp` directories into the root directory of a new Godot project.
-- Uses the godot-cpp headers
-- Uses the Tilt Five NDK
diff --git a/example.csharp/addons/tiltfive/T5Interface.cs b/example.csharp/addons/tiltfive/T5Interface.cs
index ccf62aa..30e1527 100644
--- a/example.csharp/addons/tiltfive/T5Interface.cs
+++ b/example.csharp/addons/tiltfive/T5Interface.cs
@@ -51,6 +51,7 @@ public override void _EnterTree()
xrInterface.Set("application_id", T5ProjectSettings.ApplicationID);
xrInterface.Set("application_version", T5ProjectSettings.ApplicationVersion);
xrInterface.Set("trigger_click_threshold", T5ProjectSettings.TriggerClickThreshhold);
+ xrInterface.Set("debug_logging", T5ProjectSettings.IsDebugLogging);
XRServer.AddInterface(xrInterface as XRInterface);
@@ -118,26 +119,14 @@ void _OnGlassesEvent(String glassesID, int eventNum)
switch ((GlassesEventType)eventNum)
{
- case GlassesEventType.E_GLASSES_ADDED:
- {
- GD.Print(glassesID, " E_GLASSES_ADDED");
- break;
- }
- case GlassesEventType.E_GLASSES_LOST:
- {
- GD.Print(glassesID, " E_GLASSES_LOST");
- break;
- }
case GlassesEventType.E_GLASSES_AVAILABLE:
{
- GD.Print(glassesID, " E_GLASSES_AVAILABLE");
xrRigState.available = true;
ProcessGlasses();
break;
}
case GlassesEventType.E_GLASSES_UNAVAILABLE:
{
- GD.Print(glassesID, " E_GLASSES_UNAVAILABLE");
xrRigState.available = false;
if(xrRigState.attemptingToReserve)
{
@@ -148,8 +137,6 @@ void _OnGlassesEvent(String glassesID, int eventNum)
}
case GlassesEventType.E_GLASSES_RESERVED:
{
- GD.Print(glassesID, " E_GLASSES_RESERVED");
-
xrRigState.reserved = true;
xrRigState.attemptingToReserve = false;
@@ -170,8 +157,6 @@ void _OnGlassesEvent(String glassesID, int eventNum)
}
case GlassesEventType.E_GLASSES_DROPPED:
{
- GD.Print(glassesID, " E_DROPPED");
-
xrRigState.reserved = false;
xrRigState.attemptingToReserve = false;
@@ -187,7 +172,6 @@ void _OnGlassesEvent(String glassesID, int eventNum)
}
case GlassesEventType.E_GLASSES_TRACKING:
{
- GD.Print(glassesID, " E_GLASSES_TRACKING");
var gbt = xrInterface.Call("get_gameboard_type", glassesID).As();
if(xrRigState.gameboardType != gbt)
{
@@ -201,16 +185,8 @@ void _OnGlassesEvent(String glassesID, int eventNum)
}
break;
}
- case GlassesEventType.E_GLASSES_NOT_TRACKING:
- {
- GD.Print(glassesID, " E_GLASSES_NOT_TRACKING");
- break;
- }
- default:
- {
- GD.PrintErr(glassesID, " unknown event");
- break;
- }
+ // This is the only set of events that needs to be handled
+ default: break;
}
}
diff --git a/example.csharp/addons/tiltfive/T5ProjectSettings.cs b/example.csharp/addons/tiltfive/T5ProjectSettings.cs
index 6dc0f0f..12c5a10 100644
--- a/example.csharp/addons/tiltfive/T5ProjectSettings.cs
+++ b/example.csharp/addons/tiltfive/T5ProjectSettings.cs
@@ -29,6 +29,7 @@ public static void setup_properties() {
if (!isInitialized) {
DefineProjectSetting("xr/tilt_five/default_display_name", Variant.Type.String, PropertyHint.None, "", "");
DefineProjectSetting("xr/tilt_five/trigger_click_threshhold", Variant.Type.Float, PropertyHint.Range, "0,1,0.01", 0.3);
+ DefineProjectSetting("xr/tilt_five/debug_logging", Variant.Type.Bool, PropertyHint.None, "", false);
isInitialized = true;
}
@@ -69,5 +70,10 @@ public static float TriggerClickThreshhold
{
get { setup_properties(); return (float)ProjectSettings.GetSettingWithOverride("xr/tilt_five/trigger_click_threshhold").AsDouble(); }
}
+
+ public static bool IsDebugLogging
+ {
+ get { setup_properties(); return ProjectSettings.GetSettingWithOverride("xr/tilt_five/debug_logging").AsBool(); }
+ }
}
diff --git a/example.gd/addons/tiltfive/T5Interface.gd b/example.gd/addons/tiltfive/T5Interface.gd
index d24088d..3f7e5df 100644
--- a/example.gd/addons/tiltfive/T5Interface.gd
+++ b/example.gd/addons/tiltfive/T5Interface.gd
@@ -1,5 +1,5 @@
extends Node
-## It will instantiate the TileFive interface and register it with the XRServer.
+## It will instantiate the TiltFive interface and register it with the XRServer.
##
## This script should be configured be automatically added as an autoload script
## when the plugin is enabled. This
@@ -26,19 +26,14 @@ var t5_manager : T5ManagerBase:
func get_tilt_five_xr_interface() -> TiltFiveXRInterface:
return tilt_five_xr_interface
-
-func get_setting_or_default(name : String, default):
- var val = ProjectSettings.get_setting_with_override(name)
- if not val:
- val = default
- return val
-
+
func _enter_tree():
- tilt_five_xr_interface = TiltFiveXRInterface.new();
+ tilt_five_xr_interface = TiltFiveXRInterface.new()
if tilt_five_xr_interface:
tilt_five_xr_interface.application_id = T5ProjectSettings.application_id
tilt_five_xr_interface.application_version = T5ProjectSettings.application_version
tilt_five_xr_interface.trigger_click_threshold = T5ProjectSettings.trigger_click_threshhold
+ tilt_five_xr_interface.debug_logging = T5ProjectSettings.is_debug_logging
XRServer.add_interface(tilt_five_xr_interface)
tilt_five_xr_interface.glasses_event.connect(_on_glasses_event)
@@ -83,7 +78,7 @@ func _on_service_event(event_num):
t5_manager.service_unvailable()
TiltFiveXRInterface.E_SERVICE_T5_INCOMPATIBLE_VERSION:
t5_manager.service_incorrect_version()
-
+
func _on_glasses_event(glasses_id, event_num):
var xr_rig_state = id_to_state.get(glasses_id) as XRRigState
if not xr_rig_state:
@@ -91,19 +86,16 @@ func _on_glasses_event(glasses_id, event_num):
id_to_state[glasses_id] = xr_rig_state
match event_num:
TiltFiveXRInterface.E_GLASSES_AVAILABLE:
- print_verbose(glasses_id, " E_AVAILABLE")
xr_rig_state.available = true
_process_glasses()
TiltFiveXRInterface.E_GLASSES_UNAVAILABLE:
- print_verbose(glasses_id, " E_UNAVAILABLE")
xr_rig_state.available = false
if xr_rig_state.attempting_to_reserve:
xr_rig_state.attempting_to_reserve = false
_process_glasses()
TiltFiveXRInterface.E_GLASSES_RESERVED:
- print_verbose(glasses_id, " E_RESERVED")
xr_rig_state.reserved = true
xr_rig_state.attempting_to_reserve = false
@@ -116,7 +108,6 @@ func _on_glasses_event(glasses_id, event_num):
tilt_five_xr_interface.release_glasses(glasses_id)
TiltFiveXRInterface.E_GLASSES_DROPPED:
- print_verbose(glasses_id, " E_DROPPED")
xr_rig_state.reserved = false
var xr_rig = xr_rig_state.xr_rig
@@ -132,10 +123,6 @@ func _on_glasses_event(glasses_id, event_num):
xr_rig._gameboard_type = gbt
xr_rig._gameboard_size = tilt_five_xr_interface.get_gameboard_extents(gbt)
t5_manager.set_gameboard_type(xr_rig, gbt)
- print_verbose(glasses_id, " E_TRACKING, Gameboard size = ", )
-
- TiltFiveXRInterface.E_GLASSES_NOT_TRACKING:
- print_verbose(glasses_id, " E_NOT_TRACKING")
-
+
_:
- print_verbose(glasses_id, " - unknown event: ", event_num)
+ pass # These are the only events that need to be handled
diff --git a/example.gd/addons/tiltfive/T5ProjectSettings.gd b/example.gd/addons/tiltfive/T5ProjectSettings.gd
index 47c1c1e..48140e8 100644
--- a/example.gd/addons/tiltfive/T5ProjectSettings.gd
+++ b/example.gd/addons/tiltfive/T5ProjectSettings.gd
@@ -29,6 +29,7 @@ static func setup_properties():
if not _initialized:
_define_project_setting("xr/tilt_five/default_display_name", TYPE_STRING)
_define_project_setting("xr/tilt_five/trigger_click_threshhold", TYPE_FLOAT, PROPERTY_HINT_RANGE, "0,1,0.01", 0.3)
+ _define_project_setting("xr/tilt_five/debug_logging", TYPE_BOOL, PROPERTY_HINT_NONE, "", false)
_initialized = true
static var application_id : String:
@@ -57,4 +58,8 @@ static var trigger_click_threshhold : float:
get:
setup_properties()
return ProjectSettings.get_setting_with_override("xr/tilt_five/trigger_click_threshhold")
-
+
+static var is_debug_logging : bool:
+ get:
+ setup_properties()
+ return ProjectSettings.get_setting_with_override("xr/tilt_five/debug_logging")
diff --git a/extension/T5Integration/Logging.h b/extension/T5Integration/Logging.h
index c4df568..3e22072 100644
--- a/extension/T5Integration/Logging.h
+++ b/extension/T5Integration/Logging.h
@@ -1,5 +1,6 @@
#pragma once
#include
+#include
#include
#include
@@ -12,6 +13,13 @@ class Logger {
virtual void log_error(const char* message, const char* func_name, const char* file_name, int line_num) = 0;
virtual void log_warning(const char* message, const char* func_name, const char* file_name, int line_num) = 0;
virtual void log_string(const char* message) = 0;
+ void set_debug(bool is_debug_) {
+ is_debug = is_debug_;
+ }
+ bool get_debug() { return is_debug; }
+
+private:
+ bool is_debug = false;
};
class DefaultLogger : public Logger {
diff --git a/extension/src/GodotT5Service.cpp b/extension/src/GodotT5Service.cpp
index 5857d9c..33eb3b7 100644
--- a/extension/src/GodotT5Service.cpp
+++ b/extension/src/GodotT5Service.cpp
@@ -100,12 +100,15 @@ void GodotT5Logger::log_error(const char* message, const char* func_name, const
}
void GodotT5Logger::log_warning(const char* message, const char* func_name, const char* file_name, int line_num) {
- godot::_err_print_error(func_name, file_name, line_num, "TiltFiveXRInterface", message, true, false);
+ godot::_err_print_error(func_name, file_name, line_num, "TiltFiveXRInterface", message, true, true);
}
void GodotT5Logger::log_string(const char* message) {
Variant v_msg = message;
- UtilityFunctions::print_verbose(v_msg);
+ if (get_debug())
+ UtilityFunctions::print(v_msg);
+ else
+ UtilityFunctions::print_verbose(v_msg);
}
GodotT5Service::Ptr GodotT5ObjectRegistry::service() {
@@ -135,15 +138,15 @@ T5Integration::T5Math::Ptr GodotT5ObjectRegistry::get_math() {
return math;
}
+GodotT5Logger::Ptr g_logger;
+
T5Integration::Logger::Ptr GodotT5ObjectRegistry::get_logger() {
- GodotT5Logger::Ptr logger;
- if (_logger.expired()) {
- logger = std::make_shared();
- _logger = logger;
- } else {
- logger = std::static_pointer_cast(_logger.lock());
+ if (!g_logger) {
+ g_logger = std::make_shared();
+ _logger = g_logger;
}
- return logger;
+
+ return g_logger;
}
} //namespace GodotT5Integration
\ No newline at end of file
diff --git a/extension/src/TiltFiveXRInterface.cpp b/extension/src/TiltFiveXRInterface.cpp
index 1be8611..f40d36b 100644
--- a/extension/src/TiltFiveXRInterface.cpp
+++ b/extension/src/TiltFiveXRInterface.cpp
@@ -1,4 +1,5 @@
#include "TiltFiveXRInterface.h"
+#include
#include
#include
#include
@@ -34,6 +35,10 @@ void TiltFiveXRInterface::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_trigger_click_threshold"), &TiltFiveXRInterface::get_trigger_click_threshold);
ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "trigger_click_threshold"), "set_trigger_click_threshold", "get_trigger_click_threshold");
+ ClassDB::bind_method(D_METHOD("set_debug_logging", "debug_logging"), &TiltFiveXRInterface::set_debug_logging);
+ ClassDB::bind_method(D_METHOD("get_debug_logging"), &TiltFiveXRInterface::get_debug_logging);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_logging"), "set_debug_logging", "get_debug_logging");
+
// Signals.
ADD_SIGNAL(MethodInfo("service_event", PropertyInfo(Variant::INT, "event")));
ADD_SIGNAL(MethodInfo("glasses_event", PropertyInfo(Variant::STRING, "glasses_id"), PropertyInfo(Variant::INT, "event")));
@@ -90,6 +95,14 @@ void TiltFiveXRInterface::set_trigger_click_threshold(float threshold) {
}
}
+bool TiltFiveXRInterface::get_debug_logging() {
+ return GodotT5ObjectRegistry::logger()->get_debug();
+}
+
+void TiltFiveXRInterface::set_debug_logging(bool is_debug) {
+ GodotT5ObjectRegistry::logger()->set_debug(is_debug);
+}
+
TiltFiveXRInterface::GlassesIndexEntry* TiltFiveXRInterface::lookup_glasses_entry(StringName glasses_id) {
for (auto& entry : _glasses_index) {
if (glasses_id == entry.id) {
@@ -448,6 +461,66 @@ PackedStringArray TiltFiveXRInterface::_get_suggested_pose_names(const StringNam
return tracker_names;
}
+void TiltFiveXRInterface::log_service_events() {
+ if (get_debug_logging() || OS::get_singleton()->is_stdout_verbose()) {
+ for (auto& event : _service_events) {
+ switch (event.event) {
+ case T5ServiceEvent::E_RUNNING:
+ LOG_MESSAGE("Tilt Five Running");
+ break;
+ case T5ServiceEvent::E_STOPPED:
+ LOG_MESSAGE("Tilt Five Stopped");
+ break;
+ case T5ServiceEvent::E_T5_UNAVAILABLE:
+ LOG_MESSAGE("Tilt Five Unavailable");
+ break;
+ case T5ServiceEvent::E_T5_INCOMPATIBLE_VERSION:
+ LOG_MESSAGE("Tilt Five Incompatible Version");
+ break;
+ }
+ }
+ }
+}
+
+void TiltFiveXRInterface::log_glasses_events() {
+ if (get_debug_logging() || OS::get_singleton()->is_stdout_verbose()) {
+ for (auto& event : _glasses_events) {
+ auto glasses = t5_service->get_glasses(event.glasses_num);
+ if (!glasses)
+ continue;
+ switch (event.event) {
+ case GlassesEventType::E_GLASSES_ADDED:
+ LOG_MESSAGE(glasses->get_id(), " Added");
+ break;
+ case GlassesEventType::E_GLASSES_LOST:
+ LOG_MESSAGE(glasses->get_id(), " Lost");
+ break;
+ case GlassesEventType::E_GLASSES_AVAILABLE:
+ LOG_MESSAGE(glasses->get_id(), " Available to use");
+ break;
+ case GlassesEventType::E_GLASSES_UNAVAILABLE:
+ LOG_MESSAGE(glasses->get_id(), " Unavailable to use");
+ break;
+ case GlassesEventType::E_GLASSES_RESERVED:
+ LOG_MESSAGE(glasses->get_id(), " Reserved for application");
+ break;
+ case GlassesEventType::E_GLASSES_DROPPED:
+ LOG_MESSAGE(glasses->get_id(), " Reservation dropped");
+ break;
+ case GlassesEventType::E_GLASSES_TRACKING:
+ LOG_MESSAGE(glasses->get_id(), " Tracking pose");
+ break;
+ case GlassesEventType::E_GLASSES_NOT_TRACKING:
+ LOG_MESSAGE(glasses->get_id(), " Not tracking pose");
+ break;
+ case GlassesEventType::E_GLASSES_STOPPED_ON_ERROR:
+ LOG_MESSAGE(glasses->get_id(), " Stopped with unknown error");
+ break;
+ }
+ }
+ }
+}
+
void TiltFiveXRInterface::_process() {
if (!t5_service)
return;
@@ -457,12 +530,14 @@ void TiltFiveXRInterface::_process() {
_service_events.clear();
t5_service->get_service_events(_service_events);
+ log_service_events();
for (int i = 0; i < _service_events.size(); i++) {
emit_signal("service_event", _service_events[i].event);
}
_glasses_events.clear();
t5_service->get_glasses_events(_glasses_events);
+ log_glasses_events();
for (int i = 0; i < _glasses_events.size(); i++) {
auto glasses_idx = _glasses_events[i].glasses_num;
switch (_glasses_events[i].event) {
@@ -523,6 +598,9 @@ int32_t TiltFiveXRInterface::_get_camera_feed_id() const {
}
TiltFiveXRInterface::TiltFiveXRInterface() {
+#ifdef DEV_ENABLED
+ UtilityFunctions::print("Tilt Five DEV_BUILD");
+#endif
}
TiltFiveXRInterface::~TiltFiveXRInterface() {
diff --git a/extension/src/TiltFiveXRInterface.h b/extension/src/TiltFiveXRInterface.h
index 0aefcf3..98b9ef8 100644
--- a/extension/src/TiltFiveXRInterface.h
+++ b/extension/src/TiltFiveXRInterface.h
@@ -92,6 +92,9 @@ class TiltFiveXRInterface : public XRInterfaceExtension {
float get_trigger_click_threshold();
void set_trigger_click_threshold(float threshold);
+ bool get_debug_logging();
+ void set_debug_logging(bool is_debug);
+
// Functions.
void reserve_glasses(const StringName glasses_id, const String display_name);
@@ -153,12 +156,16 @@ class TiltFiveXRInterface : public XRInterfaceExtension {
GlassesIndexEntry *lookup_glasses_by_viewport(RID render_target);
private:
+ void log_service_events();
+ void log_glasses_events();
+
bool _initialised = false;
XRServer *xr_server = nullptr;
String application_id;
String application_version;
float _trigger_click_threshold = 0.5;
+ bool _is_debug_logging = false;
std::vector _glasses_index;
std::vector _glasses_events;