From 27693a8fbfca154af10fa5bbd8da79f0786780a9 Mon Sep 17 00:00:00 2001 From: Rhys Tumelty Date: Sun, 23 Aug 2026 20:59:48 +0100 Subject: [PATCH] made it acutally work in godot, and made it draw a texture --- .gitignore | 2 + CMakeLists.txt | 4 +- project/bin/example.gdextension | 57 ------------------ project/bin/gdvapi.gdextension | 6 ++ project/bin/gdvapi.gdextension.uid | 1 + project/example.gd | 3 +- project/example.gd.uid | 1 + project/example.tscn | 8 ++- project/icon.svg.import | 6 ++ project/project.godot | 7 ++- src/example_class.cpp | 9 --- src/example_class.h | 20 ------ src/register_types.cpp | 8 +-- src/udpvideostream_class.cpp | 97 ++++++++++++++++++++++++++++++ src/udpvideostream_class.h | 32 ++++++++++ 15 files changed, 163 insertions(+), 98 deletions(-) delete mode 100644 project/bin/example.gdextension create mode 100644 project/bin/gdvapi.gdextension create mode 100644 project/bin/gdvapi.gdextension.uid create mode 100644 project/example.gd.uid delete mode 100644 src/example_class.cpp delete mode 100644 src/example_class.h create mode 100644 src/udpvideostream_class.cpp create mode 100644 src/udpvideostream_class.h diff --git a/.gitignore b/.gitignore index b35ce1a..cae99a7 100644 --- a/.gitignore +++ b/.gitignore @@ -53,3 +53,5 @@ CMakeUserPresets.json # stupid godot developers using SCons build/ + +godot/ diff --git a/CMakeLists.txt b/CMakeLists.txt index f5ff069..1a66068 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -55,8 +55,8 @@ target_sources(${LIBNAME} PRIVATE src/register_types.cpp src/register_types.h - src/example_class.cpp - src/example_class.h + src/udpvideostream_class.cpp + src/udpvideostream_class.h ) # Fetch a list of the xml files to use for documentation and add to our target diff --git a/project/bin/example.gdextension b/project/bin/example.gdextension deleted file mode 100644 index 8be121f..0000000 --- a/project/bin/example.gdextension +++ /dev/null @@ -1,57 +0,0 @@ -[configuration] - -entry_symbol = "example_library_init" -compatibility_minimum = "4.1" -reloadable = false - -[libraries] -; Relative paths ensure that our GDExtension can be placed anywhere in the project directory. -macos.single.debug = "./macos/libEXTENSION-NAME.macos.template_debug.dylib" -macos.double.debug = "./macos/libEXTENSION-NAME.macos.template_debug.double.dylib" -macos.single.release = "./macos/libEXTENSION-NAME.macos.template_release.dylib" -macos.double.release = "./macos/libEXTENSION-NAME.macos.template_release.double.dylib" - -ios.arm64.single.debug = "./ios/libEXTENSION-NAME.ios.template_debug.arm64.dylib" -ios.arm64.double.debug = "./ios/libEXTENSION-NAME.ios.template_debug.arm64.double.dylib" -ios.arm64.single.release = "./ios/libEXTENSION-NAME.ios.template_release.arm64.dylib" -ios.arm64.double.release = "./ios/libEXTENSION-NAME.ios.template_release.arm64.double.dylib" - -windows.x86_32.single.debug = "./windows/EXTENSION-NAME.windows.template_debug.x86_32.dll" -windows.x86_32.double.debug = "./windows/EXTENSION-NAME.windows.template_debug.x86_32.double.dll" -windows.x86_32.single.release = "./windows/EXTENSION-NAME.windows.template_release.x86_32.dll" -windows.x86_32.double.release = "./windows/EXTENSION-NAME.windows.template_release.x86_32.double.dll" - -windows.x86_64.single.debug = "./windows/EXTENSION-NAME.windows.template_debug.x86_64.dll" -windows.x86_64.double.debug = "./windows/EXTENSION-NAME.windows.template_debug.x86_64.double.dll" -windows.x86_64.single.release = "./windows/EXTENSION-NAME.windows.template_release.x86_64.dll" -windows.x86_64.double.release = "./windows/EXTENSION-NAME.windows.template_release.x86_64.double.dll" - -linux.x86_64.single.debug = "./linux/libEXTENSION-NAME.linux.template_debug.x86_64.so" -linux.x86_64.double.debug = "./linux/libEXTENSION-NAME.linux.template_debug.x86_64.double.so" -linux.x86_64.single.release = "./linux/libEXTENSION-NAME.linux.template_release.x86_64.so" -linux.x86_64.double.release = "./linux/libEXTENSION-NAME.linux.template_release.x86_64.double.so" - -linux.arm64.single.debug = "./linux/libEXTENSION-NAME.linux.template_debug.arm64.so" -linux.arm64.double.debug = "./linux/libEXTENSION-NAME.linux.template_debug.arm64.double.so" -linux.arm64.single.release = "./linux/libEXTENSION-NAME.linux.template_release.arm64.so" -linux.arm64.double.release = "./linux/libEXTENSION-NAME.linux.template_release.arm64.double.so" - -linux.rv64.single.debug = "./linux/libEXTENSION-NAME.linux.template_debug.rv64.so" -linux.rv64.double.debug = "./linux/libEXTENSION-NAME.linux.template_debug.rv64.double.so" -linux.rv64.single.release = "./linux/libEXTENSION-NAME.linux.template_release.rv64.so" -linux.rv64.double.release = "./linux/libEXTENSION-NAME.linux.template_release.rv64.double.so" - -android.x86_64.single.debug = "./android/libEXTENSION-NAME.android.template_debug.x86_64.so" -android.x86_64.double.debug = "./android/libEXTENSION-NAME.android.template_debug.x86_64.double.so" -android.x86_64.single.release = "./android/libEXTENSION-NAME.android.template_release.x86_64.so" -android.x86_64.double.release = "./android/libEXTENSION-NAME.android.template_release.x86_64.double.so" - -android.arm64.single.debug = "./android/libEXTENSION-NAME.android.template_debug.arm64.so" -android.arm64.double.debug = "./android/libEXTENSION-NAME.android.template_debug.arm64.double.so" -android.arm64.single.release = "./android/libEXTENSION-NAME.android.template_release.arm64.so" -android.arm64.double.release = "./android/libEXTENSION-NAME.android.template_release.arm64.double.so" - -web.wasm32.single.debug = "./web/libEXTENSION-NAME.web.template_debug.wasm32.nothreads.wasm" -web.wasm32.double.debug = "./web/libEXTENSION-NAME.web.template_debug.wasm32.double.nothreads.wasm" -web.wasm32.single.release = "./web/libEXTENSION-NAME.web.template_release.wasm32.nothreads.wasm" -web.wasm32.double.release = "./web/libEXTENSION-NAME.web.template_release.wasm32.double.nothreads.wasm" diff --git a/project/bin/gdvapi.gdextension b/project/bin/gdvapi.gdextension new file mode 100644 index 0000000..93c793f --- /dev/null +++ b/project/bin/gdvapi.gdextension @@ -0,0 +1,6 @@ +[configuration] +entry_symbol = "gdvapi_library_init" +compatibility_minimum = "4.7" + +[libraries] +linux.x86_64 = "res://bin/linux/gdvapi.linux.template_debug.x86_64.so" diff --git a/project/bin/gdvapi.gdextension.uid b/project/bin/gdvapi.gdextension.uid new file mode 100644 index 0000000..37ac7cf --- /dev/null +++ b/project/bin/gdvapi.gdextension.uid @@ -0,0 +1 @@ +uid://vgmwthvwcljf diff --git a/project/example.gd b/project/example.gd index 02cfc52..5157869 100644 --- a/project/example.gd +++ b/project/example.gd @@ -2,5 +2,4 @@ extends Node func _ready() -> void: - var example := ExampleClass.new() - example.print_type(example) + $UDPVideoStream.begin("localhost:1000") diff --git a/project/example.gd.uid b/project/example.gd.uid new file mode 100644 index 0000000..31d5b6a --- /dev/null +++ b/project/example.gd.uid @@ -0,0 +1 @@ +uid://bkwk40ybs8kgm diff --git a/project/example.tscn b/project/example.tscn index 8fea2ee..3fd2d94 100644 --- a/project/example.tscn +++ b/project/example.tscn @@ -1,6 +1,8 @@ -[gd_scene load_steps=2 format=3 uid="uid://dh0oj81pufivs"] +[gd_scene format=3 uid="uid://dh0oj81pufivs"] -[ext_resource type="Script" path="res://example.gd" id="1_jdh55"] +[ext_resource type="Script" uid="uid://bkwk40ybs8kgm" path="res://example.gd" id="1_jdh55"] -[node name="Node" type="Node"] +[node name="Node" type="Node" unique_id=2080300232] script = ExtResource("1_jdh55") + +[node name="UDPVideoStream" type="UDPVideoStream" parent="." unique_id=270982386] diff --git a/project/icon.svg.import b/project/icon.svg.import index c8d2b12..800518c 100644 --- a/project/icon.svg.import +++ b/project/icon.svg.import @@ -18,6 +18,8 @@ dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.cte compress/mode=0 compress/high_quality=false compress/lossy_quality=0.7 +compress/uastc_level=0 +compress/rdo_quality_loss=0.0 compress/hdr_compression=1 compress/normal_map=0 compress/channel_pack=0 @@ -25,6 +27,10 @@ mipmaps/generate=false mipmaps/limit=-1 roughness/mode=0 roughness/src_normal="" +process/channel_remap/red=0 +process/channel_remap/green=1 +process/channel_remap/blue=2 +process/channel_remap/alpha=3 process/fix_alpha_border=true process/premult_alpha=false process/normal_map_invert_y=false diff --git a/project/project.godot b/project/project.godot index 9c5c174..c22533f 100644 --- a/project/project.godot +++ b/project/project.godot @@ -8,8 +8,13 @@ config_version=5 +[animation] + +compatibility/default_parent_skeleton_in_mesh_instance_3d=true + [application] config/name="godot cpp template" -config/features=PackedStringArray("4.1", "Forward Plus") +run/main_scene="uid://dh0oj81pufivs" +config/features=PackedStringArray("4.7", "Forward Plus") config/icon="res://icon.svg" diff --git a/src/example_class.cpp b/src/example_class.cpp deleted file mode 100644 index 177f9b5..0000000 --- a/src/example_class.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "example_class.h" - -void ExampleClass::_bind_methods() { - godot::ClassDB::bind_method(D_METHOD("print_type", "variant"), &ExampleClass::print_type); -} - -void ExampleClass::print_type(const Variant &p_variant) const { - print_line(vformat("Type: %d", p_variant.get_type())); -} diff --git a/src/example_class.h b/src/example_class.h deleted file mode 100644 index 76c6d55..0000000 --- a/src/example_class.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include "godot_cpp/classes/ref_counted.hpp" -#include "godot_cpp/classes/wrapped.hpp" -#include "godot_cpp/variant/variant.hpp" - -using namespace godot; - -class ExampleClass : public RefCounted { - GDCLASS(ExampleClass, RefCounted) - -protected: - static void _bind_methods(); - -public: - ExampleClass() = default; - ~ExampleClass() override = default; - - void print_type(const Variant &p_variant) const; -}; diff --git a/src/register_types.cpp b/src/register_types.cpp index 2760920..74f574a 100644 --- a/src/register_types.cpp +++ b/src/register_types.cpp @@ -5,7 +5,7 @@ #include #include -#include "example_class.h" +#include "udpvideostream_class.h" using namespace godot; @@ -14,7 +14,7 @@ void initialize_gdextension_types(ModuleInitializationLevel p_level) if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) { return; } - GDREGISTER_CLASS(ExampleClass); + GDREGISTER_CLASS(UDPVideoStream); } void uninitialize_gdextension_types(ModuleInitializationLevel p_level) { @@ -26,7 +26,7 @@ void uninitialize_gdextension_types(ModuleInitializationLevel p_level) { extern "C" { // Initialization - GDExtensionBool GDE_EXPORT example_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) + GDExtensionBool GDE_EXPORT gdvapi_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) { GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization); init_obj.register_initializer(initialize_gdextension_types); @@ -35,4 +35,4 @@ extern "C" return init_obj.init(); } -} \ No newline at end of file +} diff --git a/src/udpvideostream_class.cpp b/src/udpvideostream_class.cpp new file mode 100644 index 0000000..ec3e43e --- /dev/null +++ b/src/udpvideostream_class.cpp @@ -0,0 +1,97 @@ +#include "udpvideostream_class.h" +#include "godot_cpp/classes/rendering_server.hpp" +#include "godot_cpp/classes/rendering_device.hpp" +#include "godot_cpp/classes/rd_texture_format.hpp" +#include "godot_cpp/classes/rd_texture_view.hpp" + + +using namespace godot; + +void UDPVideoStream::_bind_methods() { + godot::ClassDB::bind_method(D_METHOD("begin", "variant"), &UDPVideoStream::begin); +} + +void UDPVideoStream::begin(const Variant &source) const { + print_line(vformat("[gdvapi] begin stream at %s", source.stringify())); +} + +UDPVideoStream::~UDPVideoStream() { + cleanup(); +} + +void UDPVideoStream::_notification(int p_what) { + switch (p_what) { + case NOTIFICATION_POST_ENTER_TREE: { + texture_init(); + } break; + + case NOTIFICATION_EXIT_TREE: { + cleanup(); + } break; + } +} + + +void UDPVideoStream::texture_init() { + RenderingDevice *rd = RenderingServer::get_singleton()->get_rendering_device(); + if (!rd) { + UtilityFunctions::printerr("Vulkan RenderingDevice is not available!"); + return; + } + + int width = 256; + int height = 256; + + Ref format; + format.instantiate(); + format->set_texture_type(RenderingDevice::TEXTURE_TYPE_2D); + format->set_format(RenderingDevice::DATA_FORMAT_R8G8B8A8_UNORM); + format->set_width(width); + format->set_height(height); + format->set_depth(1); + format->set_array_layers(1); + format->set_mipmaps(1); + format->set_usage_bits(RenderingDevice::TEXTURE_USAGE_SAMPLING_BIT | + RenderingDevice::TEXTURE_USAGE_CAN_UPDATE_BIT); + + PackedByteArray byte_array; + byte_array.resize(width * height * 4); + for (int i = 0; i < byte_array.size(); i += 4) { + byte_array[i] = 0; + byte_array[i + 1] = 0; + byte_array[i + 2] = 255; + byte_array[i + 3] = 255; + } + + TypedArray data; + data.push_back(byte_array); + + Ref view; + view.instantiate(); + + texture_rd_rid = rd->texture_create(format, view, data); + + if (texture_rd_rid.is_valid()) { + godot_texture.instantiate(); + godot_texture->set_texture_rd_rid(texture_rd_rid); + + queue_redraw(); + } +} + +void UDPVideoStream::cleanup() { + RenderingDevice *rd = RenderingServer::get_singleton()->get_rendering_device(); + + godot_texture.unref(); + + if (rd && texture_rd_rid.is_valid()) { + rd->free_rid(texture_rd_rid); + texture_rd_rid = RID(); + } +} + +void UDPVideoStream::_draw() { + if (godot_texture.is_valid() && godot_texture->get_texture_rd_rid().is_valid()) { + draw_texture(godot_texture, Point2(0, 0)); + } +} diff --git a/src/udpvideostream_class.h b/src/udpvideostream_class.h new file mode 100644 index 0000000..0e605be --- /dev/null +++ b/src/udpvideostream_class.h @@ -0,0 +1,32 @@ +#pragma once + +#include "godot_cpp/classes/control.hpp" +#include "godot_cpp/classes/wrapped.hpp" +#include "godot_cpp/variant/variant.hpp" +#include "godot_cpp/classes/rendering_device.hpp" +#include "godot_cpp/classes/texture2drd.hpp" + +using namespace godot; + +class UDPVideoStream : public Control { + GDCLASS(UDPVideoStream, Control) + +private: + RID texture_rd_rid; + Ref godot_texture; + + void cleanup(); + void texture_init(); + +protected: + static void _bind_methods(); + +public: + UDPVideoStream() = default; + ~UDPVideoStream() override; + + void begin(const Variant &source) const; + + void _notification(int p_what); + virtual void _draw() override; +};