Merge pull request #52036 from reduz/native-extension-argument-pointers
Implement NativeExtension pointer arguments
This commit is contained in:
commit
aa3c3a9ebb
|
@ -558,6 +558,7 @@ void register_global_constants() {
|
|||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_NODE_PATH_VALID_TYPES);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_SAVE_FILE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_OBJECTID);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_INT_IS_POINTER);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_ARRAY_TYPE);
|
||||
BIND_CORE_ENUM_CONSTANT(PROPERTY_HINT_MAX);
|
||||
|
||||
|
|
|
@ -31,7 +31,14 @@
|
|||
#include "doc_data.h"
|
||||
|
||||
void DocData::return_doc_from_retinfo(DocData::MethodDoc &p_method, const PropertyInfo &p_retinfo) {
|
||||
if (p_retinfo.type == Variant::INT && p_retinfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
|
||||
if (p_retinfo.type == Variant::INT && p_retinfo.hint == PROPERTY_HINT_INT_IS_POINTER) {
|
||||
p_method.return_type = p_retinfo.hint_string;
|
||||
if (p_method.return_type == "") {
|
||||
p_method.return_type = "void*";
|
||||
} else {
|
||||
p_method.return_type += "*";
|
||||
}
|
||||
} else if (p_retinfo.type == Variant::INT && p_retinfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
|
||||
p_method.return_enum = p_retinfo.class_name;
|
||||
if (p_method.return_enum.begins_with("_")) { //proxy class
|
||||
p_method.return_enum = p_method.return_enum.substr(1, p_method.return_enum.length());
|
||||
|
@ -55,7 +62,14 @@ void DocData::return_doc_from_retinfo(DocData::MethodDoc &p_method, const Proper
|
|||
void DocData::argument_doc_from_arginfo(DocData::ArgumentDoc &p_argument, const PropertyInfo &p_arginfo) {
|
||||
p_argument.name = p_arginfo.name;
|
||||
|
||||
if (p_arginfo.type == Variant::INT && p_arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
|
||||
if (p_arginfo.type == Variant::INT && p_arginfo.hint == PROPERTY_HINT_INT_IS_POINTER) {
|
||||
p_argument.type = p_arginfo.hint_string;
|
||||
if (p_argument.type == "") {
|
||||
p_argument.type = "void*";
|
||||
} else {
|
||||
p_argument.type += "*";
|
||||
}
|
||||
} else if (p_arginfo.type == Variant::INT && p_arginfo.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
|
||||
p_argument.enumeration = p_arginfo.class_name;
|
||||
if (p_argument.enumeration.begins_with("_")) { //proxy class
|
||||
p_argument.enumeration = p_argument.enumeration.substr(1, p_argument.enumeration.length());
|
||||
|
|
|
@ -39,6 +39,13 @@
|
|||
#ifdef TOOLS_ENABLED
|
||||
|
||||
static String get_type_name(const PropertyInfo &p_info) {
|
||||
if (p_info.type == Variant::INT && (p_info.hint == PROPERTY_HINT_INT_IS_POINTER)) {
|
||||
if (p_info.hint_string == "") {
|
||||
return "void*";
|
||||
} else {
|
||||
return p_info.hint_string + "*";
|
||||
}
|
||||
}
|
||||
if (p_info.type == Variant::INT && (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM)) {
|
||||
return String("enum::") + String(p_info.class_name);
|
||||
}
|
||||
|
@ -831,6 +838,20 @@ Dictionary NativeExtensionAPIDump::generate_extension_api() {
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
Array native_structures;
|
||||
|
||||
{
|
||||
Dictionary d;
|
||||
d["name"] = "AudioFrame";
|
||||
d["format"] = "float left,float right";
|
||||
|
||||
native_structures.push_back(d);
|
||||
}
|
||||
|
||||
api_dump["native_structures"] = native_structures;
|
||||
}
|
||||
|
||||
return api_dump;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ proto = """
|
|||
#define GDVIRTUAL$VER($RET m_name $ARG) \\
|
||||
StringName _gdvirtual_##m_name##_sn = #m_name;\\
|
||||
GDNativeExtensionClassCallVirtual _gdvirtual_##m_name = (_get_extension() && _get_extension()->get_virtual) ? _get_extension()->get_virtual(_get_extension()->class_userdata, #m_name) : (GDNativeExtensionClassCallVirtual) nullptr;\\
|
||||
bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
|
||||
_FORCE_INLINE_ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
|
||||
ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
|
||||
if (script_instance) {\\
|
||||
Callable::CallError ce; \\
|
||||
|
@ -23,7 +23,7 @@ bool _gdvirtual_##m_name##_call($CALLARGS) $CONST { \\
|
|||
\\
|
||||
return false;\\
|
||||
}\\
|
||||
bool _gdvirtual_##m_name##_overriden() const { \\
|
||||
_FORCE_INLINE_ bool _gdvirtual_##m_name##_overriden() const { \\
|
||||
ScriptInstance *script_instance = ((Object*)(this))->get_script_instance();\\
|
||||
if (script_instance) {\\
|
||||
return script_instance->has_method(_gdvirtual_##m_name##_sn);\\
|
||||
|
@ -42,7 +42,6 @@ _FORCE_INLINE_ static MethodInfo _gdvirtual_##m_name##_get_method_info() { \\
|
|||
return method_info;\\
|
||||
}
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
|
|
|
@ -97,6 +97,7 @@ enum PropertyHint {
|
|||
PROPERTY_HINT_SAVE_FILE, ///< a file path must be passed, hint_text (optionally) is a filter "*.png,*.wav,*.doc,". This opens a save dialog
|
||||
PROPERTY_HINT_INT_IS_OBJECTID,
|
||||
PROPERTY_HINT_ARRAY_TYPE,
|
||||
PROPERTY_HINT_INT_IS_POINTER,
|
||||
PROPERTY_HINT_MAX,
|
||||
// When updating PropertyHint, also sync the hardcoded list in VisualScriptEditorVariableEdit
|
||||
};
|
||||
|
|
|
@ -191,6 +191,7 @@ struct PtrToArg<ObjectID> {
|
|||
|
||||
// This is for the special cases used by Variant.
|
||||
|
||||
// No EncodeT because direct pointer conversion not possible.
|
||||
#define MAKE_VECARG(m_type) \
|
||||
template <> \
|
||||
struct PtrToArg<Vector<m_type>> { \
|
||||
|
@ -236,6 +237,7 @@ struct PtrToArg<ObjectID> {
|
|||
} \
|
||||
}
|
||||
|
||||
// No EncodeT because direct pointer conversion not possible.
|
||||
#define MAKE_VECARG_ALT(m_type, m_type_alt) \
|
||||
template <> \
|
||||
struct PtrToArg<Vector<m_type_alt>> { \
|
||||
|
@ -285,6 +287,7 @@ MAKE_VECARG_ALT(String, StringName);
|
|||
|
||||
// For stuff that gets converted to Array vectors.
|
||||
|
||||
// No EncodeT because direct pointer conversion not possible.
|
||||
#define MAKE_VECARR(m_type) \
|
||||
template <> \
|
||||
struct PtrToArg<Vector<m_type>> { \
|
||||
|
@ -325,6 +328,7 @@ MAKE_VECARR(Variant);
|
|||
MAKE_VECARR(RID);
|
||||
MAKE_VECARR(Plane);
|
||||
|
||||
// No EncodeT because direct pointer conversion not possible.
|
||||
#define MAKE_DVECARR(m_type) \
|
||||
template <> \
|
||||
struct PtrToArg<Vector<m_type>> { \
|
||||
|
@ -372,6 +376,7 @@ MAKE_VECARR(Plane);
|
|||
|
||||
// Special case for IPAddress.
|
||||
|
||||
// No EncodeT because direct pointer conversion not possible.
|
||||
#define MAKE_STRINGCONV_BY_REFERENCE(m_type) \
|
||||
template <> \
|
||||
struct PtrToArg<m_type> { \
|
||||
|
@ -395,6 +400,7 @@ MAKE_VECARR(Plane);
|
|||
|
||||
MAKE_STRINGCONV_BY_REFERENCE(IPAddress);
|
||||
|
||||
// No EncodeT because direct pointer conversion not possible.
|
||||
template <>
|
||||
struct PtrToArg<Vector<Face3>> {
|
||||
_FORCE_INLINE_ static Vector<Face3> convert(const void *p_ptr) {
|
||||
|
@ -429,6 +435,7 @@ struct PtrToArg<Vector<Face3>> {
|
|||
}
|
||||
};
|
||||
|
||||
// No EncodeT because direct pointer conversion not possible.
|
||||
template <>
|
||||
struct PtrToArg<const Vector<Face3> &> {
|
||||
_FORCE_INLINE_ static Vector<Face3> convert(const void *p_ptr) {
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/*************************************************************************/
|
||||
/* native_ptr.h */
|
||||
/*************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/*************************************************************************/
|
||||
/* Copyright (c) 2007-2021 Juan Linietsky, Ariel Manzur. */
|
||||
/* Copyright (c) 2014-2021 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. */
|
||||
/*************************************************************************/
|
||||
|
||||
#ifndef NATIVE_PTR_H
|
||||
#define NATIVE_PTR_H
|
||||
|
||||
#include "core/math/audio_frame.h"
|
||||
#include "core/variant/method_ptrcall.h"
|
||||
#include "core/variant/type_info.h"
|
||||
|
||||
template <class T>
|
||||
struct GDNativeConstPtr {
|
||||
const T *data = nullptr;
|
||||
GDNativeConstPtr(const T *p_assign) { data = p_assign; }
|
||||
static const char *get_name() { return "const void"; }
|
||||
operator const T *() const { return data; }
|
||||
operator Variant() const { return uint64_t(data); }
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct GDNativePtr {
|
||||
T *data = nullptr;
|
||||
GDNativePtr(T *p_assign) { data = p_assign; }
|
||||
static const char *get_name() { return "void"; }
|
||||
operator T *() const { return data; }
|
||||
operator Variant() const { return uint64_t(data); }
|
||||
};
|
||||
|
||||
#define GDVIRTUAL_NATIVE_PTR(m_type) \
|
||||
template <> \
|
||||
struct GDNativeConstPtr<m_type> { \
|
||||
const m_type *data = nullptr; \
|
||||
GDNativeConstPtr(const m_type *p_assign) { data = p_assign; } \
|
||||
static const char *get_name() { return "const " #m_type; } \
|
||||
operator const m_type *() const { return data; } \
|
||||
operator Variant() const { return uint64_t(data); } \
|
||||
}; \
|
||||
template <> \
|
||||
struct GDNativePtr<m_type> { \
|
||||
m_type *data = nullptr; \
|
||||
GDNativePtr(m_type *p_assign) { data = p_assign; } \
|
||||
static const char *get_name() { return #m_type; } \
|
||||
operator m_type *() const { return data; } \
|
||||
operator Variant() const { return uint64_t(data); } \
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct GetTypeInfo<GDNativeConstPtr<T>> {
|
||||
static const Variant::Type VARIANT_TYPE = Variant::NIL;
|
||||
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
|
||||
static inline PropertyInfo get_class_info() {
|
||||
return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDNativeConstPtr<T>::get_name());
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct GetTypeInfo<GDNativePtr<T>> {
|
||||
static const Variant::Type VARIANT_TYPE = Variant::NIL;
|
||||
static const GodotTypeInfo::Metadata METADATA = GodotTypeInfo::METADATA_NONE;
|
||||
static inline PropertyInfo get_class_info() {
|
||||
return PropertyInfo(Variant::INT, String(), PROPERTY_HINT_INT_IS_POINTER, GDNativePtr<T>::get_name());
|
||||
}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
struct PtrToArg<GDNativeConstPtr<T>> {
|
||||
_FORCE_INLINE_ static GDNativeConstPtr<T> convert(const void *p_ptr) {
|
||||
return GDNativeConstPtr<T>(reinterpret_cast<const T *>(p_ptr));
|
||||
}
|
||||
typedef const T *EncodeT;
|
||||
_FORCE_INLINE_ static void encode(GDNativeConstPtr<T> p_val, void *p_ptr) {
|
||||
*((const T **)p_ptr) = p_val.data;
|
||||
}
|
||||
};
|
||||
template <class T>
|
||||
struct PtrToArg<GDNativePtr<T>> {
|
||||
_FORCE_INLINE_ static GDNativePtr<T> convert(const void *p_ptr) {
|
||||
return GDNativePtr<T>(reinterpret_cast<const T *>(p_ptr));
|
||||
}
|
||||
typedef T *EncodeT;
|
||||
_FORCE_INLINE_ static void encode(GDNativePtr<T> p_val, void *p_ptr) {
|
||||
*((T **)p_ptr) = p_val.data;
|
||||
}
|
||||
};
|
||||
|
||||
GDVIRTUAL_NATIVE_PTR(AudioFrame)
|
||||
GDVIRTUAL_NATIVE_PTR(bool)
|
||||
GDVIRTUAL_NATIVE_PTR(char)
|
||||
GDVIRTUAL_NATIVE_PTR(char16_t)
|
||||
GDVIRTUAL_NATIVE_PTR(char32_t)
|
||||
GDVIRTUAL_NATIVE_PTR(wchar_t)
|
||||
GDVIRTUAL_NATIVE_PTR(uint8_t)
|
||||
GDVIRTUAL_NATIVE_PTR(int8_t)
|
||||
GDVIRTUAL_NATIVE_PTR(uint16_t)
|
||||
GDVIRTUAL_NATIVE_PTR(int16_t)
|
||||
GDVIRTUAL_NATIVE_PTR(uint32_t)
|
||||
GDVIRTUAL_NATIVE_PTR(int32_t)
|
||||
GDVIRTUAL_NATIVE_PTR(int64_t)
|
||||
GDVIRTUAL_NATIVE_PTR(uint64_t)
|
||||
GDVIRTUAL_NATIVE_PTR(float)
|
||||
GDVIRTUAL_NATIVE_PTR(double)
|
||||
|
||||
#endif // NATIVE_PTR_H
|
|
@ -2351,9 +2351,11 @@
|
|||
</constant>
|
||||
<constant name="PROPERTY_HINT_INT_IS_OBJECTID" value="38" enum="PropertyHint">
|
||||
</constant>
|
||||
<constant name="PROPERTY_HINT_INT_IS_POINTER" value="40" enum="PropertyHint">
|
||||
</constant>
|
||||
<constant name="PROPERTY_HINT_ARRAY_TYPE" value="39" enum="PropertyHint">
|
||||
</constant>
|
||||
<constant name="PROPERTY_HINT_MAX" value="40" enum="PropertyHint">
|
||||
<constant name="PROPERTY_HINT_MAX" value="41" enum="PropertyHint">
|
||||
</constant>
|
||||
<constant name="PROPERTY_USAGE_NONE" value="0" enum="PropertyUsageFlags">
|
||||
</constant>
|
||||
|
|
|
@ -13,6 +13,21 @@
|
|||
<link title="Audio Spectrum Demo">https://godotengine.org/asset-library/asset/528</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="_get_length" qualifiers="virtual const">
|
||||
<return type="float" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_get_stream_name" qualifiers="virtual const">
|
||||
<return type="String" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_instance_playback" qualifiers="virtual const">
|
||||
<return type="AudioStreamPlayback" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="get_length" qualifiers="const">
|
||||
<return type="float" />
|
||||
<description>
|
||||
|
|
|
@ -10,6 +10,46 @@
|
|||
<link title="Audio Generator Demo">https://godotengine.org/asset-library/asset/526</link>
|
||||
</tutorials>
|
||||
<methods>
|
||||
<method name="_get_loop_count" qualifiers="virtual const">
|
||||
<return type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_get_playback_position" qualifiers="virtual const">
|
||||
<return type="float" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_is_playing" qualifiers="virtual const">
|
||||
<return type="bool" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_mix" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="buffer" type="AudioFrame*" />
|
||||
<argument index="1" name="rate_scale" type="float" />
|
||||
<argument index="2" name="frames" type="int" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_seek" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="position" type="float" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_start" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<argument index="0" name="from_pos" type="float" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
<method name="_stop" qualifiers="virtual">
|
||||
<return type="void" />
|
||||
<description>
|
||||
</description>
|
||||
</method>
|
||||
</methods>
|
||||
<constants>
|
||||
</constants>
|
||||
|
|
|
@ -1007,6 +1007,8 @@ def format_table(f, data, remove_empty_columns=False): # type: (TextIO, Iterabl
|
|||
|
||||
|
||||
def make_type(klass, state): # type: (str, State) -> str
|
||||
if klass.find("*") != -1: # Pointer, ignore
|
||||
return klass
|
||||
link_type = klass
|
||||
if link_type.endswith("[]"): # Typed array, strip [] to link to contained type.
|
||||
link_type = link_type[:-2]
|
||||
|
|
|
@ -170,7 +170,7 @@ void EditorHelp::_add_type(const String &p_type, const String &p_enum) {
|
|||
if (t.is_empty()) {
|
||||
t = "void";
|
||||
}
|
||||
bool can_ref = (t != "void") || !p_enum.is_empty();
|
||||
bool can_ref = (t != "void" && t.find("*") == -1) || !p_enum.is_empty();
|
||||
|
||||
if (!p_enum.is_empty()) {
|
||||
if (p_enum.get_slice_count(".") > 1) {
|
||||
|
@ -632,8 +632,8 @@ void EditorHelp::_update_doc() {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
// Ignore undocumented private.
|
||||
if (cd.methods[i].name.begins_with("_") && cd.methods[i].description.is_empty()) {
|
||||
// Ignore undocumented non virtual private.
|
||||
if (cd.methods[i].name.begins_with("_") && cd.methods[i].description.is_empty() && cd.methods[i].qualifiers.find("virtual") == -1) {
|
||||
continue;
|
||||
}
|
||||
methods.push_back(cd.methods[i]);
|
||||
|
|
|
@ -272,8 +272,12 @@ void AudioStreamPlayer2D::set_stream(Ref<AudioStream> p_stream) {
|
|||
}
|
||||
|
||||
if (p_stream.is_valid()) {
|
||||
stream = p_stream;
|
||||
stream_playback = p_stream->instance_playback();
|
||||
if (stream_playback.is_valid()) {
|
||||
stream = p_stream;
|
||||
} else {
|
||||
stream.unref();
|
||||
}
|
||||
}
|
||||
|
||||
AudioServer::get_singleton()->unlock();
|
||||
|
|
|
@ -624,8 +624,12 @@ void AudioStreamPlayer3D::set_stream(Ref<AudioStream> p_stream) {
|
|||
}
|
||||
|
||||
if (p_stream.is_valid()) {
|
||||
stream = p_stream;
|
||||
stream_playback = p_stream->instance_playback();
|
||||
if (stream_playback.is_valid()) {
|
||||
stream = p_stream;
|
||||
} else {
|
||||
stream.unref();
|
||||
}
|
||||
}
|
||||
|
||||
AudioServer::get_singleton()->unlock();
|
||||
|
|
|
@ -202,8 +202,12 @@ void AudioStreamPlayer::set_stream(Ref<AudioStream> p_stream) {
|
|||
}
|
||||
|
||||
if (p_stream.is_valid()) {
|
||||
stream = p_stream;
|
||||
stream_playback = p_stream->instance_playback();
|
||||
if (stream_playback.is_valid()) {
|
||||
stream = p_stream;
|
||||
} else {
|
||||
stream.unref();
|
||||
}
|
||||
}
|
||||
|
||||
AudioServer::get_singleton()->unlock();
|
||||
|
|
|
@ -33,6 +33,63 @@
|
|||
#include "core/config/project_settings.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
void AudioStreamPlayback::start(float p_from_pos) {
|
||||
if (GDVIRTUAL_CALL(_start, p_from_pos)) {
|
||||
return;
|
||||
}
|
||||
ERR_FAIL_MSG("AudioStreamPlayback::start unimplemented!");
|
||||
}
|
||||
void AudioStreamPlayback::stop() {
|
||||
if (GDVIRTUAL_CALL(_stop)) {
|
||||
return;
|
||||
}
|
||||
ERR_FAIL_MSG("AudioStreamPlayback::stop unimplemented!");
|
||||
}
|
||||
bool AudioStreamPlayback::is_playing() const {
|
||||
bool ret;
|
||||
if (GDVIRTUAL_CALL(_is_playing, ret)) {
|
||||
return ret;
|
||||
}
|
||||
ERR_FAIL_V_MSG(false, "AudioStreamPlayback::is_playing unimplemented!");
|
||||
}
|
||||
|
||||
int AudioStreamPlayback::get_loop_count() const {
|
||||
int ret;
|
||||
if (GDVIRTUAL_CALL(_get_loop_count, ret)) {
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
float AudioStreamPlayback::get_playback_position() const {
|
||||
float ret;
|
||||
if (GDVIRTUAL_CALL(_get_playback_position, ret)) {
|
||||
return ret;
|
||||
}
|
||||
ERR_FAIL_V_MSG(0, "AudioStreamPlayback::get_playback_position unimplemented!");
|
||||
}
|
||||
void AudioStreamPlayback::seek(float p_time) {
|
||||
if (GDVIRTUAL_CALL(_seek, p_time)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioStreamPlayback::mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) {
|
||||
if (GDVIRTUAL_CALL(_mix, p_buffer, p_rate_scale, p_frames)) {
|
||||
return;
|
||||
}
|
||||
WARN_PRINT_ONCE("AudioStreamPlayback::mix unimplemented!");
|
||||
}
|
||||
|
||||
void AudioStreamPlayback::_bind_methods() {
|
||||
GDVIRTUAL_BIND(_start, "from_pos")
|
||||
GDVIRTUAL_BIND(_stop)
|
||||
GDVIRTUAL_BIND(_is_playing)
|
||||
GDVIRTUAL_BIND(_get_loop_count)
|
||||
GDVIRTUAL_BIND(_get_playback_position)
|
||||
GDVIRTUAL_BIND(_seek, "position")
|
||||
GDVIRTUAL_BIND(_mix, "buffer", "rate_scale", "frames");
|
||||
}
|
||||
//////////////////////////////
|
||||
|
||||
void AudioStreamPlaybackResampled::_begin_resample() {
|
||||
|
@ -92,8 +149,34 @@ void AudioStreamPlaybackResampled::mix(AudioFrame *p_buffer, float p_rate_scale,
|
|||
|
||||
////////////////////////////////
|
||||
|
||||
Ref<AudioStreamPlayback> AudioStream::instance_playback() {
|
||||
Ref<AudioStreamPlayback> ret;
|
||||
if (GDVIRTUAL_CALL(_instance_playback, ret)) {
|
||||
return ret;
|
||||
}
|
||||
ERR_FAIL_V_MSG(Ref<AudioStreamPlayback>(), "Method must be implemented!");
|
||||
}
|
||||
String AudioStream::get_stream_name() const {
|
||||
String ret;
|
||||
if (GDVIRTUAL_CALL(_get_stream_name, ret)) {
|
||||
return ret;
|
||||
}
|
||||
return String();
|
||||
}
|
||||
|
||||
float AudioStream::get_length() const {
|
||||
float ret;
|
||||
if (GDVIRTUAL_CALL(_get_length, ret)) {
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioStream::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_length"), &AudioStream::get_length);
|
||||
GDVIRTUAL_BIND(_instance_playback);
|
||||
GDVIRTUAL_BIND(_get_stream_name);
|
||||
GDVIRTUAL_BIND(_get_length);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
|
@ -358,3 +441,4 @@ void AudioStreamPlaybackRandomPitch::mix(AudioFrame *p_buffer, float p_rate_scal
|
|||
AudioStreamPlaybackRandomPitch::~AudioStreamPlaybackRandomPitch() {
|
||||
random_pitch->playbacks.erase(this);
|
||||
}
|
||||
/////////////////////////////////////////////
|
||||
|
|
|
@ -36,20 +36,33 @@
|
|||
#include "servers/audio/audio_filter_sw.h"
|
||||
#include "servers/audio_server.h"
|
||||
|
||||
#include "core/object/gdvirtual.gen.inc"
|
||||
#include "core/object/script_language.h"
|
||||
#include "core/variant/native_ptr.h"
|
||||
|
||||
class AudioStreamPlayback : public RefCounted {
|
||||
GDCLASS(AudioStreamPlayback, RefCounted);
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
GDVIRTUAL1(_start, float)
|
||||
GDVIRTUAL0(_stop)
|
||||
GDVIRTUAL0RC(bool, _is_playing)
|
||||
GDVIRTUAL0RC(int, _get_loop_count)
|
||||
GDVIRTUAL0RC(float, _get_playback_position)
|
||||
GDVIRTUAL1(_seek, float)
|
||||
GDVIRTUAL3(_mix, GDNativePtr<AudioFrame>, float, int)
|
||||
public:
|
||||
virtual void start(float p_from_pos = 0.0) = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual bool is_playing() const = 0;
|
||||
virtual void start(float p_from_pos = 0.0);
|
||||
virtual void stop();
|
||||
virtual bool is_playing() const;
|
||||
|
||||
virtual int get_loop_count() const = 0; //times it looped
|
||||
virtual int get_loop_count() const; //times it looped
|
||||
|
||||
virtual float get_playback_position() const = 0;
|
||||
virtual void seek(float p_time) = 0;
|
||||
virtual float get_playback_position() const;
|
||||
virtual void seek(float p_time);
|
||||
|
||||
virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames) = 0;
|
||||
virtual void mix(AudioFrame *p_buffer, float p_rate_scale, int p_frames);
|
||||
};
|
||||
|
||||
class AudioStreamPlaybackResampled : public AudioStreamPlayback {
|
||||
|
@ -84,11 +97,15 @@ class AudioStream : public Resource {
|
|||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
public:
|
||||
virtual Ref<AudioStreamPlayback> instance_playback() = 0;
|
||||
virtual String get_stream_name() const = 0;
|
||||
GDVIRTUAL0RC(Ref<AudioStreamPlayback>, _instance_playback)
|
||||
GDVIRTUAL0RC(String, _get_stream_name)
|
||||
GDVIRTUAL0RC(float, _get_length)
|
||||
|
||||
virtual float get_length() const = 0; //if supported, otherwise return 0
|
||||
public:
|
||||
virtual Ref<AudioStreamPlayback> instance_playback();
|
||||
virtual String get_stream_name() const;
|
||||
|
||||
virtual float get_length() const;
|
||||
};
|
||||
|
||||
// Microphone
|
||||
|
|
|
@ -140,8 +140,8 @@ void register_server_types() {
|
|||
GDREGISTER_VIRTUAL_CLASS(XRInterface);
|
||||
GDREGISTER_CLASS(XRPositionalTracker);
|
||||
|
||||
GDREGISTER_VIRTUAL_CLASS(AudioStream);
|
||||
GDREGISTER_VIRTUAL_CLASS(AudioStreamPlayback);
|
||||
GDREGISTER_CLASS(AudioStream);
|
||||
GDREGISTER_CLASS(AudioStreamPlayback);
|
||||
GDREGISTER_VIRTUAL_CLASS(AudioStreamPlaybackResampled);
|
||||
GDREGISTER_CLASS(AudioStreamMicrophone);
|
||||
GDREGISTER_CLASS(AudioStreamRandomPitch);
|
||||
|
|
Loading…
Reference in New Issue