made it acutally work in godot, and made it draw a texture

This commit is contained in:
Rhys Tumelty
2026-08-23 20:59:48 +01:00
parent 427c64ef5d
commit 27693a8fbf
15 changed files with 163 additions and 98 deletions

2
.gitignore vendored
View File

@@ -53,3 +53,5 @@ CMakeUserPresets.json
# stupid godot developers using SCons
build/
godot/

View File

@@ -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

View File

@@ -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"

View File

@@ -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"

View File

@@ -0,0 +1 @@
uid://vgmwthvwcljf

View File

@@ -2,5 +2,4 @@ extends Node
func _ready() -> void:
var example := ExampleClass.new()
example.print_type(example)
$UDPVideoStream.begin("localhost:1000")

1
project/example.gd.uid Normal file
View File

@@ -0,0 +1 @@
uid://bkwk40ybs8kgm

View File

@@ -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]

View File

@@ -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

View File

@@ -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"

View File

@@ -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()));
}

View File

@@ -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;
};

View File

@@ -5,7 +5,7 @@
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/godot.hpp>
#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);

View File

@@ -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<RDTextureFormat> 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<PackedByteArray> data;
data.push_back(byte_array);
Ref<RDTextureView> 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));
}
}

View File

@@ -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<Texture2DRD> 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;
};