doc: Complete documentation for VideoStreams
Also quick clean up of the matching C++ files.
This commit is contained in:
parent
55cc46a052
commit
bb6c0d3e8b
16 changed files with 43 additions and 73 deletions
|
@ -4,7 +4,8 @@
|
||||||
Control for playing video streams.
|
Control for playing video streams.
|
||||||
</brief_description>
|
</brief_description>
|
||||||
<description>
|
<description>
|
||||||
Control node for playing video streams. Supported formats are [url=https://www.webmproject.org/]WebM[/url] and [url=https://www.theora.org/]Ogg Theora[/url].
|
Control node for playing video streams using [VideoStream] resources.
|
||||||
|
Supported video formats are [url=https://www.webmproject.org/]WebM[/url] ([VideoStreamWebm]), [url=https://www.theora.org/]Ogg Theora[/url] ([VideoStreamTheora]), and any format exposed via a GDNative plugin using [VideoStreamGDNative].
|
||||||
</description>
|
</description>
|
||||||
<tutorials>
|
<tutorials>
|
||||||
</tutorials>
|
</tutorials>
|
||||||
|
@ -61,7 +62,7 @@
|
||||||
Audio bus to use for sound playback.
|
Audio bus to use for sound playback.
|
||||||
</member>
|
</member>
|
||||||
<member name="expand" type="bool" setter="set_expand" getter="has_expand" default="true">
|
<member name="expand" type="bool" setter="set_expand" getter="has_expand" default="true">
|
||||||
If [code]true[/code], the video scales to the control size.
|
If [code]true[/code], the video scales to the control size. Otherwise, the control minimum size will be automatically adjusted to match the video stream's dimensions.
|
||||||
</member>
|
</member>
|
||||||
<member name="paused" type="bool" setter="set_paused" getter="is_paused" default="false">
|
<member name="paused" type="bool" setter="set_paused" getter="is_paused" default="false">
|
||||||
If [code]true[/code], the video is paused.
|
If [code]true[/code], the video is paused.
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
Base resource for video streams.
|
Base resource for video streams.
|
||||||
</brief_description>
|
</brief_description>
|
||||||
<description>
|
<description>
|
||||||
|
Base resource type for all video streams. Classes that derive from [VideoStream] can all be used as resource types to play back videos in [VideoPlayer].
|
||||||
</description>
|
</description>
|
||||||
<tutorials>
|
<tutorials>
|
||||||
</tutorials>
|
</tutorials>
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<class name="VideoStreamGDNative" inherits="VideoStream" category="Core" version="3.2">
|
<class name="VideoStreamGDNative" inherits="VideoStream" category="Core" version="3.2">
|
||||||
<brief_description>
|
<brief_description>
|
||||||
|
[VideoStream] resource for for video formats implemented via GDNative.
|
||||||
</brief_description>
|
</brief_description>
|
||||||
<description>
|
<description>
|
||||||
|
[VideoStream] resource for for video formats implemented via GDNative.
|
||||||
|
It can be used via [url=https://github.com/KidRigger/godot-videodecoder]godot-videodecoder[/url] which uses the [url=https://ffmpeg.org]FFmpeg[/url] library.
|
||||||
</description>
|
</description>
|
||||||
<tutorials>
|
<tutorials>
|
||||||
</tutorials>
|
</tutorials>
|
||||||
|
@ -11,6 +14,7 @@
|
||||||
<return type="String">
|
<return type="String">
|
||||||
</return>
|
</return>
|
||||||
<description>
|
<description>
|
||||||
|
Returns the video file handled by this [VideoStreamGDNative].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="set_file">
|
<method name="set_file">
|
||||||
|
@ -19,6 +23,7 @@
|
||||||
<argument index="0" name="file" type="String">
|
<argument index="0" name="file" type="String">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
|
Sets the video file that this [VideoStreamGDNative] resource handles. The supported extensions depend on the GDNative plugins used to expose video formats.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
</methods>
|
</methods>
|
||||||
|
|
|
@ -73,7 +73,7 @@ public:
|
||||||
class AudioStreamOGGVorbis : public AudioStream {
|
class AudioStreamOGGVorbis : public AudioStream {
|
||||||
|
|
||||||
GDCLASS(AudioStreamOGGVorbis, AudioStream);
|
GDCLASS(AudioStreamOGGVorbis, AudioStream);
|
||||||
OBJ_SAVE_TYPE(AudioStream) //children are all saved as AudioStream, so they can be exchanged
|
OBJ_SAVE_TYPE(AudioStream); // Saves derived classes with common type so they can be interchanged.
|
||||||
RES_BASE_EXTENSION("oggstr");
|
RES_BASE_EXTENSION("oggstr");
|
||||||
|
|
||||||
friend class AudioStreamPlaybackOGGVorbis;
|
friend class AudioStreamPlaybackOGGVorbis;
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<class name="VideoStreamTheora" inherits="VideoStream" category="Core" version="3.2">
|
<class name="VideoStreamTheora" inherits="VideoStream" category="Core" version="3.2">
|
||||||
<brief_description>
|
<brief_description>
|
||||||
|
[VideoStream] resource for Ogg Theora videos.
|
||||||
</brief_description>
|
</brief_description>
|
||||||
<description>
|
<description>
|
||||||
|
[VideoStream] resource handling the [url=https://www.theora.org/]Ogg Theora[/url] video format with [code].ogv[/code] extension.
|
||||||
</description>
|
</description>
|
||||||
<tutorials>
|
<tutorials>
|
||||||
</tutorials>
|
</tutorials>
|
||||||
|
@ -11,6 +13,7 @@
|
||||||
<return type="String">
|
<return type="String">
|
||||||
</return>
|
</return>
|
||||||
<description>
|
<description>
|
||||||
|
Returns the Ogg Theora video file handled by this [VideoStreamTheora].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="set_file">
|
<method name="set_file">
|
||||||
|
@ -19,6 +22,7 @@
|
||||||
<argument index="0" name="file" type="String">
|
<argument index="0" name="file" type="String">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
|
Sets the Ogg Theora video file that this [VideoStreamTheora] resource handles. The [code]file[/code] name should have the [code].o[/code] extension.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
</methods>
|
</methods>
|
||||||
|
|
|
@ -147,7 +147,6 @@ void VideoStreamPlaybackTheora::clear() {
|
||||||
thread = NULL;
|
thread = NULL;
|
||||||
ring_buffer.clear();
|
ring_buffer.clear();
|
||||||
#endif
|
#endif
|
||||||
//file_name = "";
|
|
||||||
|
|
||||||
theora_p = 0;
|
theora_p = 0;
|
||||||
vorbis_p = 0;
|
vorbis_p = 0;
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" ?>
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
<class name="VideoStreamWebm" inherits="VideoStream" category="Core" version="3.2">
|
<class name="VideoStreamWebm" inherits="VideoStream" category="Core" version="3.2">
|
||||||
<brief_description>
|
<brief_description>
|
||||||
|
[VideoStream] resource for WebM videos.
|
||||||
</brief_description>
|
</brief_description>
|
||||||
<description>
|
<description>
|
||||||
|
[VideoStream] resource handling the [url=https://www.webmproject.org/]WebM[/url] video format with [code].webm[/code] extension.
|
||||||
</description>
|
</description>
|
||||||
<tutorials>
|
<tutorials>
|
||||||
</tutorials>
|
</tutorials>
|
||||||
|
@ -11,6 +13,7 @@
|
||||||
<return type="String">
|
<return type="String">
|
||||||
</return>
|
</return>
|
||||||
<description>
|
<description>
|
||||||
|
Returns the WebM video file handled by this [VideoStreamWebm].
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="set_file">
|
<method name="set_file">
|
||||||
|
@ -19,6 +22,7 @@
|
||||||
<argument index="0" name="file" type="String">
|
<argument index="0" name="file" type="String">
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
|
Sets the WebM video file that this [VideoStreamWebm] resource handles. The [code]file[/code] name should have the [code].webm[/code] extension.
|
||||||
</description>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
</methods>
|
</methods>
|
||||||
|
|
|
@ -30,21 +30,22 @@
|
||||||
|
|
||||||
#include "video_stream_webm.h"
|
#include "video_stream_webm.h"
|
||||||
|
|
||||||
#include "OpusVorbisDecoder.hpp"
|
|
||||||
#include "VPXDecoder.hpp"
|
|
||||||
#include <vpx/vpx_image.h>
|
|
||||||
|
|
||||||
#include "mkvparser/mkvparser.h"
|
|
||||||
|
|
||||||
#include "core/os/file_access.h"
|
#include "core/os/file_access.h"
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "core/project_settings.h"
|
#include "core/project_settings.h"
|
||||||
|
#include "servers/audio_server.h"
|
||||||
|
|
||||||
#include "thirdparty/misc/yuv2rgb.h"
|
#include "thirdparty/misc/yuv2rgb.h"
|
||||||
|
|
||||||
#include "servers/audio_server.h"
|
// libsimplewebm
|
||||||
|
#include <OpusVorbisDecoder.hpp>
|
||||||
|
#include <VPXDecoder.hpp>
|
||||||
|
|
||||||
#include <string.h>
|
// libvpx
|
||||||
|
#include <vpx/vpx_image.h>
|
||||||
|
|
||||||
|
// libwebm
|
||||||
|
#include <mkvparser/mkvparser.h>
|
||||||
|
|
||||||
class MkvReader : public mkvparser::IMkvReader {
|
class MkvReader : public mkvparser::IMkvReader {
|
||||||
|
|
||||||
|
@ -335,22 +336,22 @@ void VideoStreamPlaybackWebm::update(float p_delta) {
|
||||||
} else if (image.chromaShiftW == 1 && image.chromaShiftH == 1) {
|
} else if (image.chromaShiftW == 1 && image.chromaShiftH == 1) {
|
||||||
|
|
||||||
yuv420_2_rgb8888(w.ptr(), image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2);
|
yuv420_2_rgb8888(w.ptr(), image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2);
|
||||||
// libyuv::I420ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
//libyuv::I420ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
||||||
converted = true;
|
converted = true;
|
||||||
} else if (image.chromaShiftW == 1 && image.chromaShiftH == 0) {
|
} else if (image.chromaShiftW == 1 && image.chromaShiftH == 0) {
|
||||||
|
|
||||||
yuv422_2_rgb8888(w.ptr(), image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2);
|
yuv422_2_rgb8888(w.ptr(), image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2);
|
||||||
// libyuv::I422ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
//libyuv::I422ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
||||||
converted = true;
|
converted = true;
|
||||||
} else if (image.chromaShiftW == 0 && image.chromaShiftH == 0) {
|
} else if (image.chromaShiftW == 0 && image.chromaShiftH == 0) {
|
||||||
|
|
||||||
yuv444_2_rgb8888(w.ptr(), image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2);
|
yuv444_2_rgb8888(w.ptr(), image.planes[0], image.planes[1], image.planes[2], image.w, image.h, image.linesize[0], image.linesize[1], image.w << 2);
|
||||||
// libyuv::I444ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
//libyuv::I444ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
||||||
converted = true;
|
converted = true;
|
||||||
} else if (image.chromaShiftW == 2 && image.chromaShiftH == 0) {
|
} else if (image.chromaShiftW == 2 && image.chromaShiftH == 0) {
|
||||||
|
|
||||||
// libyuv::I411ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2], image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
//libyuv::I411ToARGB(image.planes[0], image.linesize[0], image.planes[2], image.linesize[2] image.planes[1], image.linesize[1], w.ptr(), image.w << 2, image.w, image.h);
|
||||||
// converted = true;
|
//converted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (converted) {
|
if (converted) {
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "audio_stream_sample.h"
|
#include "audio_stream_sample.h"
|
||||||
|
|
||||||
#include "core/io/marshalls.h"
|
#include "core/io/marshalls.h"
|
||||||
#include "core/os/file_access.h"
|
#include "core/os/file_access.h"
|
||||||
|
|
||||||
|
@ -656,8 +657,8 @@ AudioStreamSample::AudioStreamSample() {
|
||||||
data = NULL;
|
data = NULL;
|
||||||
data_bytes = 0;
|
data_bytes = 0;
|
||||||
}
|
}
|
||||||
AudioStreamSample::~AudioStreamSample() {
|
|
||||||
|
|
||||||
|
AudioStreamSample::~AudioStreamSample() {
|
||||||
if (data) {
|
if (data) {
|
||||||
AudioServer::get_singleton()->audio_data_free(data);
|
AudioServer::get_singleton()->audio_data_free(data);
|
||||||
data = NULL;
|
data = NULL;
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#ifndef AUDIOSTREAMSAMPLE_H
|
#ifndef AUDIO_STREAM_SAMPLE_H
|
||||||
#define AUDIOSTREAMSAMPLE_H
|
#define AUDIO_STREAM_SAMPLE_H
|
||||||
|
|
||||||
#include "servers/audio/audio_stream.h"
|
#include "servers/audio/audio_stream.h"
|
||||||
|
|
||||||
|
@ -153,4 +153,4 @@ public:
|
||||||
VARIANT_ENUM_CAST(AudioStreamSample::Format)
|
VARIANT_ENUM_CAST(AudioStreamSample::Format)
|
||||||
VARIANT_ENUM_CAST(AudioStreamSample::LoopMode)
|
VARIANT_ENUM_CAST(AudioStreamSample::LoopMode)
|
||||||
|
|
||||||
#endif // AUDIOSTREAMSample_H
|
#endif // AUDIO_STREAM_SAMPLE_H
|
||||||
|
|
|
@ -42,7 +42,7 @@ class Material : public Resource {
|
||||||
|
|
||||||
GDCLASS(Material, Resource);
|
GDCLASS(Material, Resource);
|
||||||
RES_BASE_EXTENSION("material")
|
RES_BASE_EXTENSION("material")
|
||||||
OBJ_SAVE_TYPE(Material)
|
OBJ_SAVE_TYPE(Material);
|
||||||
|
|
||||||
RID material;
|
RID material;
|
||||||
Ref<Material> next_pass;
|
Ref<Material> next_pass;
|
||||||
|
|
|
@ -45,7 +45,8 @@
|
||||||
class Texture : public Resource {
|
class Texture : public Resource {
|
||||||
|
|
||||||
GDCLASS(Texture, Resource);
|
GDCLASS(Texture, Resource);
|
||||||
OBJ_SAVE_TYPE(Texture); //children are all saved as Texture, so they can be exchanged
|
OBJ_SAVE_TYPE(Texture); // Saves derived classes with common type so they can be interchanged.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
/*************************************************************************/
|
|
||||||
/* video_stream.cpp */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* This file is part of: */
|
|
||||||
/* GODOT ENGINE */
|
|
||||||
/* https://godotengine.org */
|
|
||||||
/*************************************************************************/
|
|
||||||
/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
|
|
||||||
/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
|
|
||||||
/* */
|
|
||||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
|
||||||
/* a copy of this software and associated documentation files (the */
|
|
||||||
/* "Software"), to deal in the Software without restriction, including */
|
|
||||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
|
||||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
|
||||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
|
||||||
/* the following conditions: */
|
|
||||||
/* */
|
|
||||||
/* The above copyright notice and this permission notice shall be */
|
|
||||||
/* included in all copies or substantial portions of the Software. */
|
|
||||||
/* */
|
|
||||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
|
||||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
|
||||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
|
|
||||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
|
||||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
|
||||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
|
||||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
|
||||||
/*************************************************************************/
|
|
||||||
|
|
||||||
#include "video_stream.h"
|
|
||||||
|
|
||||||
void VideoStreamPlayback::_bind_methods(){
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
VideoStreamPlayback::VideoStreamPlayback(){
|
|
||||||
|
|
||||||
};
|
|
|
@ -37,9 +37,6 @@ class VideoStreamPlayback : public Resource {
|
||||||
|
|
||||||
GDCLASS(VideoStreamPlayback, Resource);
|
GDCLASS(VideoStreamPlayback, Resource);
|
||||||
|
|
||||||
protected:
|
|
||||||
static void _bind_methods();
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef int (*AudioMixCallback)(void *p_udata, const float *p_data, int p_frames);
|
typedef int (*AudioMixCallback)(void *p_udata, const float *p_data, int p_frames);
|
||||||
|
|
||||||
|
@ -61,28 +58,22 @@ public:
|
||||||
|
|
||||||
virtual void set_audio_track(int p_idx) = 0;
|
virtual void set_audio_track(int p_idx) = 0;
|
||||||
|
|
||||||
//virtual int mix(int16_t* p_buffer,int p_frames)=0;
|
|
||||||
|
|
||||||
virtual Ref<Texture> get_texture() const = 0;
|
virtual Ref<Texture> get_texture() const = 0;
|
||||||
virtual void update(float p_delta) = 0;
|
virtual void update(float p_delta) = 0;
|
||||||
|
|
||||||
virtual void set_mix_callback(AudioMixCallback p_callback, void *p_userdata) = 0;
|
virtual void set_mix_callback(AudioMixCallback p_callback, void *p_userdata) = 0;
|
||||||
virtual int get_channels() const = 0;
|
virtual int get_channels() const = 0;
|
||||||
virtual int get_mix_rate() const = 0;
|
virtual int get_mix_rate() const = 0;
|
||||||
|
|
||||||
VideoStreamPlayback();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class VideoStream : public Resource {
|
class VideoStream : public Resource {
|
||||||
|
|
||||||
GDCLASS(VideoStream, Resource);
|
GDCLASS(VideoStream, Resource);
|
||||||
OBJ_SAVE_TYPE(VideoStream); //children are all saved as AudioStream, so they can be exchanged
|
OBJ_SAVE_TYPE(VideoStream); // Saves derived classes with common type so they can be interchanged.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual void set_audio_track(int p_track) = 0;
|
virtual void set_audio_track(int p_track) = 0;
|
||||||
virtual Ref<VideoStreamPlayback> instance_playback() = 0;
|
virtual Ref<VideoStreamPlayback> instance_playback() = 0;
|
||||||
|
|
||||||
VideoStream() {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
/*************************************************************************/
|
/*************************************************************************/
|
||||||
|
|
||||||
#include "audio_stream.h"
|
#include "audio_stream.h"
|
||||||
|
|
||||||
#include "core/os/os.h"
|
#include "core/os/os.h"
|
||||||
#include "core/project_settings.h"
|
#include "core/project_settings.h"
|
||||||
|
|
||||||
|
|
|
@ -82,7 +82,7 @@ public:
|
||||||
class AudioStream : public Resource {
|
class AudioStream : public Resource {
|
||||||
|
|
||||||
GDCLASS(AudioStream, Resource);
|
GDCLASS(AudioStream, Resource);
|
||||||
OBJ_SAVE_TYPE(AudioStream) //children are all saved as AudioStream, so they can be exchanged
|
OBJ_SAVE_TYPE(AudioStream); // Saves derived classes with common type so they can be interchanged.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
Loading…
Reference in a new issue