mirror of
https://github.com/godotengine/godot-docs.git
synced 2026-01-05 22:09:56 +03:00
Fix invalid indentation in various files
This commit is contained in:
@@ -173,7 +173,7 @@ Distro-specific one-liners
|
||||
"pkgconfig(xcursor)" \
|
||||
"pkgconfig(xinerama)" \
|
||||
"pkgconfig(xi)" \
|
||||
"pkgconfig(xrandr)"
|
||||
"pkgconfig(xrandr)"
|
||||
|
||||
.. tab:: NetBSD
|
||||
|
||||
|
||||
@@ -193,7 +193,7 @@ Example `SCsub` with custom flags:
|
||||
|
||||
env_tts = env.Clone()
|
||||
env_tts.add_source_files(env.modules_sources, "*.cpp")
|
||||
# Append CCFLAGS flags for both C and C++ code.
|
||||
# Append CCFLAGS flags for both C and C++ code.
|
||||
env_tts.Append(CCFLAGS=['-O2'])
|
||||
# If you need to, you can:
|
||||
# - Append CFLAGS for C code only.
|
||||
|
||||
@@ -47,71 +47,71 @@ Therefore, playback state must be self-contained in AudioStreamPlayback.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
/* audiostream_mytone.h */
|
||||
/* audiostream_mytone.h */
|
||||
|
||||
#include "core/reference.h"
|
||||
#include "core/resource.h"
|
||||
#include "servers/audio/audio_stream.h"
|
||||
#include "core/reference.h"
|
||||
#include "core/resource.h"
|
||||
#include "servers/audio/audio_stream.h"
|
||||
|
||||
class AudioStreamMyTone : public AudioStream {
|
||||
GDCLASS(AudioStreamMyTone, AudioStream)
|
||||
class AudioStreamMyTone : public AudioStream {
|
||||
GDCLASS(AudioStreamMyTone, AudioStream)
|
||||
|
||||
private:
|
||||
friend class AudioStreamPlaybackMyTone;
|
||||
uint64_t pos;
|
||||
int mix_rate;
|
||||
bool stereo;
|
||||
int hz;
|
||||
private:
|
||||
friend class AudioStreamPlaybackMyTone;
|
||||
uint64_t pos;
|
||||
int mix_rate;
|
||||
bool stereo;
|
||||
int hz;
|
||||
|
||||
public:
|
||||
void reset();
|
||||
void set_position(uint64_t pos);
|
||||
virtual Ref<AudioStreamPlayback> instance_playback();
|
||||
virtual String get_stream_name() const;
|
||||
void gen_tone(int16_t *pcm_buf, int size);
|
||||
virtual float get_length() const { return 0; } // if supported, otherwise return 0
|
||||
AudioStreamMyTone();
|
||||
public:
|
||||
void reset();
|
||||
void set_position(uint64_t pos);
|
||||
virtual Ref<AudioStreamPlayback> instance_playback();
|
||||
virtual String get_stream_name() const;
|
||||
void gen_tone(int16_t *pcm_buf, int size);
|
||||
virtual float get_length() const { return 0; } // if supported, otherwise return 0
|
||||
AudioStreamMyTone();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
};
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
};
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
/* audiostream_mytone.cpp */
|
||||
/* audiostream_mytone.cpp */
|
||||
|
||||
#include "audiostream_mytone.h"
|
||||
#include "audiostream_mytone.h"
|
||||
|
||||
AudioStreamMyTone::AudioStreamMyTone()
|
||||
: mix_rate(44100), stereo(false), hz(639) {
|
||||
}
|
||||
AudioStreamMyTone::AudioStreamMyTone()
|
||||
: mix_rate(44100), stereo(false), hz(639) {
|
||||
}
|
||||
|
||||
Ref<AudioStreamPlayback> AudioStreamMyTone::instance_playback() {
|
||||
Ref<AudioStreamPlaybackMyTone> talking_tree;
|
||||
talking_tree.instantiate();
|
||||
talking_tree->base = Ref<AudioStreamMyTone>(this);
|
||||
return talking_tree;
|
||||
}
|
||||
Ref<AudioStreamPlayback> AudioStreamMyTone::instance_playback() {
|
||||
Ref<AudioStreamPlaybackMyTone> talking_tree;
|
||||
talking_tree.instantiate();
|
||||
talking_tree->base = Ref<AudioStreamMyTone>(this);
|
||||
return talking_tree;
|
||||
}
|
||||
|
||||
String AudioStreamMyTone::get_stream_name() const {
|
||||
return "MyTone";
|
||||
}
|
||||
void AudioStreamMyTone::reset() {
|
||||
set_position(0);
|
||||
}
|
||||
void AudioStreamMyTone::set_position(uint64_t p) {
|
||||
pos = p;
|
||||
}
|
||||
void AudioStreamMyTone::gen_tone(int16_t *pcm_buf, int size) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
pcm_buf[i] = 32767.0 * sin(2.0 * Math_PI * double(pos + i) / (double(mix_rate) / double(hz)));
|
||||
}
|
||||
pos += size;
|
||||
}
|
||||
void AudioStreamMyTone::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("reset"), &AudioStreamMyTone::reset);
|
||||
ClassDB::bind_method(D_METHOD("get_stream_name"), &AudioStreamMyTone::get_stream_name);
|
||||
}
|
||||
String AudioStreamMyTone::get_stream_name() const {
|
||||
return "MyTone";
|
||||
}
|
||||
void AudioStreamMyTone::reset() {
|
||||
set_position(0);
|
||||
}
|
||||
void AudioStreamMyTone::set_position(uint64_t p) {
|
||||
pos = p;
|
||||
}
|
||||
void AudioStreamMyTone::gen_tone(int16_t *pcm_buf, int size) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
pcm_buf[i] = 32767.0 * sin(2.0 * Math_PI * double(pos + i) / (double(mix_rate) / double(hz)));
|
||||
}
|
||||
pos += size;
|
||||
}
|
||||
void AudioStreamMyTone::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("reset"), &AudioStreamMyTone::reset);
|
||||
ClassDB::bind_method(D_METHOD("get_stream_name"), &AudioStreamMyTone::get_stream_name);
|
||||
}
|
||||
|
||||
References:
|
||||
~~~~~~~~~~~
|
||||
@@ -128,105 +128,105 @@ Since AudioStreamPlayback is controlled by the audio thread, i/o and dynamic mem
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
/* audiostreamplayer_mytone.h */
|
||||
/* audiostreamplayer_mytone.h */
|
||||
|
||||
#include "core/reference.h"
|
||||
#include "core/resource.h"
|
||||
#include "servers/audio/audio_stream.h"
|
||||
#include "core/reference.h"
|
||||
#include "core/resource.h"
|
||||
#include "servers/audio/audio_stream.h"
|
||||
|
||||
class AudioStreamPlaybackMyTone : public AudioStreamPlayback {
|
||||
GDCLASS(AudioStreamPlaybackMyTone, AudioStreamPlayback)
|
||||
friend class AudioStreamMyTone;
|
||||
class AudioStreamPlaybackMyTone : public AudioStreamPlayback {
|
||||
GDCLASS(AudioStreamPlaybackMyTone, AudioStreamPlayback)
|
||||
friend class AudioStreamMyTone;
|
||||
|
||||
private:
|
||||
enum {
|
||||
PCM_BUFFER_SIZE = 4096
|
||||
};
|
||||
enum {
|
||||
MIX_FRAC_BITS = 13,
|
||||
MIX_FRAC_LEN = (1 << MIX_FRAC_BITS),
|
||||
MIX_FRAC_MASK = MIX_FRAC_LEN - 1,
|
||||
};
|
||||
void *pcm_buffer;
|
||||
Ref<AudioStreamMyTone> base;
|
||||
bool active;
|
||||
private:
|
||||
enum {
|
||||
PCM_BUFFER_SIZE = 4096
|
||||
};
|
||||
enum {
|
||||
MIX_FRAC_BITS = 13,
|
||||
MIX_FRAC_LEN = (1 << MIX_FRAC_BITS),
|
||||
MIX_FRAC_MASK = MIX_FRAC_LEN - 1,
|
||||
};
|
||||
void *pcm_buffer;
|
||||
Ref<AudioStreamMyTone> base;
|
||||
bool active;
|
||||
|
||||
public:
|
||||
virtual void start(float p_from_pos = 0.0);
|
||||
virtual void stop();
|
||||
virtual bool is_playing() const;
|
||||
virtual int get_loop_count() const; // times it looped
|
||||
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);
|
||||
virtual float get_length() const; // if supported, otherwise return 0
|
||||
AudioStreamPlaybackMyTone();
|
||||
~AudioStreamPlaybackMyTone();
|
||||
};
|
||||
public:
|
||||
virtual void start(float p_from_pos = 0.0);
|
||||
virtual void stop();
|
||||
virtual bool is_playing() const;
|
||||
virtual int get_loop_count() const; // times it looped
|
||||
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);
|
||||
virtual float get_length() const; // if supported, otherwise return 0
|
||||
AudioStreamPlaybackMyTone();
|
||||
~AudioStreamPlaybackMyTone();
|
||||
};
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
/* audiostreamplayer_mytone.cpp */
|
||||
/* audiostreamplayer_mytone.cpp */
|
||||
|
||||
#include "audiostreamplayer_mytone.h"
|
||||
#include "audiostreamplayer_mytone.h"
|
||||
|
||||
#include "core/math/math_funcs.h"
|
||||
#include "core/print_string.h"
|
||||
#include "core/math/math_funcs.h"
|
||||
#include "core/print_string.h"
|
||||
|
||||
AudioStreamPlaybackMyTone::AudioStreamPlaybackMyTone()
|
||||
: active(false) {
|
||||
AudioServer::get_singleton()->lock();
|
||||
pcm_buffer = AudioServer::get_singleton()->audio_data_alloc(PCM_BUFFER_SIZE);
|
||||
zeromem(pcm_buffer, PCM_BUFFER_SIZE);
|
||||
AudioServer::get_singleton()->unlock();
|
||||
}
|
||||
AudioStreamPlaybackMyTone::~AudioStreamPlaybackMyTone() {
|
||||
if(pcm_buffer) {
|
||||
AudioServer::get_singleton()->audio_data_free(pcm_buffer);
|
||||
pcm_buffer = NULL;
|
||||
}
|
||||
}
|
||||
void AudioStreamPlaybackMyTone::stop() {
|
||||
active = false;
|
||||
base->reset();
|
||||
}
|
||||
void AudioStreamPlaybackMyTone::start(float p_from_pos) {
|
||||
seek(p_from_pos);
|
||||
active = true;
|
||||
}
|
||||
void AudioStreamPlaybackMyTone::seek(float p_time) {
|
||||
float max = get_length();
|
||||
if (p_time < 0) {
|
||||
p_time = 0;
|
||||
}
|
||||
base->set_position(uint64_t(p_time * base->mix_rate) << MIX_FRAC_BITS);
|
||||
}
|
||||
void AudioStreamPlaybackMyTone::mix(AudioFrame *p_buffer, float p_rate, int p_frames) {
|
||||
ERR_FAIL_COND(!active);
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
zeromem(pcm_buffer, PCM_BUFFER_SIZE);
|
||||
int16_t *buf = (int16_t *)pcm_buffer;
|
||||
base->gen_tone(buf, p_frames);
|
||||
AudioStreamPlaybackMyTone::AudioStreamPlaybackMyTone()
|
||||
: active(false) {
|
||||
AudioServer::get_singleton()->lock();
|
||||
pcm_buffer = AudioServer::get_singleton()->audio_data_alloc(PCM_BUFFER_SIZE);
|
||||
zeromem(pcm_buffer, PCM_BUFFER_SIZE);
|
||||
AudioServer::get_singleton()->unlock();
|
||||
}
|
||||
AudioStreamPlaybackMyTone::~AudioStreamPlaybackMyTone() {
|
||||
if(pcm_buffer) {
|
||||
AudioServer::get_singleton()->audio_data_free(pcm_buffer);
|
||||
pcm_buffer = NULL;
|
||||
}
|
||||
}
|
||||
void AudioStreamPlaybackMyTone::stop() {
|
||||
active = false;
|
||||
base->reset();
|
||||
}
|
||||
void AudioStreamPlaybackMyTone::start(float p_from_pos) {
|
||||
seek(p_from_pos);
|
||||
active = true;
|
||||
}
|
||||
void AudioStreamPlaybackMyTone::seek(float p_time) {
|
||||
float max = get_length();
|
||||
if (p_time < 0) {
|
||||
p_time = 0;
|
||||
}
|
||||
base->set_position(uint64_t(p_time * base->mix_rate) << MIX_FRAC_BITS);
|
||||
}
|
||||
void AudioStreamPlaybackMyTone::mix(AudioFrame *p_buffer, float p_rate, int p_frames) {
|
||||
ERR_FAIL_COND(!active);
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
zeromem(pcm_buffer, PCM_BUFFER_SIZE);
|
||||
int16_t *buf = (int16_t *)pcm_buffer;
|
||||
base->gen_tone(buf, p_frames);
|
||||
|
||||
for(int i = 0; i < p_frames; i++) {
|
||||
float sample = float(buf[i]) / 32767.0;
|
||||
p_buffer[i] = AudioFrame(sample, sample);
|
||||
}
|
||||
}
|
||||
int AudioStreamPlaybackMyTone::get_loop_count() const {
|
||||
return 0;
|
||||
}
|
||||
float AudioStreamPlaybackMyTone::get_playback_position() const {
|
||||
return 0.0;
|
||||
}
|
||||
float AudioStreamPlaybackMyTone::get_length() const {
|
||||
return 0.0;
|
||||
}
|
||||
bool AudioStreamPlaybackMyTone::is_playing() const {
|
||||
return active;
|
||||
}
|
||||
for(int i = 0; i < p_frames; i++) {
|
||||
float sample = float(buf[i]) / 32767.0;
|
||||
p_buffer[i] = AudioFrame(sample, sample);
|
||||
}
|
||||
}
|
||||
int AudioStreamPlaybackMyTone::get_loop_count() const {
|
||||
return 0;
|
||||
}
|
||||
float AudioStreamPlaybackMyTone::get_playback_position() const {
|
||||
return 0.0;
|
||||
}
|
||||
float AudioStreamPlaybackMyTone::get_length() const {
|
||||
return 0.0;
|
||||
}
|
||||
bool AudioStreamPlaybackMyTone::is_playing() const {
|
||||
return active;
|
||||
}
|
||||
|
||||
Resampling
|
||||
~~~~~~~~~~
|
||||
@@ -240,109 +240,109 @@ query AudioFrames and ``get_stream_sampling_rate`` to query current mix rate.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "core/reference.h"
|
||||
#include "core/resource.h"
|
||||
#include "servers/audio/audio_stream.h"
|
||||
#include "core/reference.h"
|
||||
#include "core/resource.h"
|
||||
#include "servers/audio/audio_stream.h"
|
||||
|
||||
class AudioStreamMyToneResampled;
|
||||
class AudioStreamMyToneResampled;
|
||||
|
||||
class AudioStreamPlaybackResampledMyTone : public AudioStreamPlaybackResampled {
|
||||
GDCLASS(AudioStreamPlaybackResampledMyTone, AudioStreamPlaybackResampled)
|
||||
friend class AudioStreamMyToneResampled;
|
||||
class AudioStreamPlaybackResampledMyTone : public AudioStreamPlaybackResampled {
|
||||
GDCLASS(AudioStreamPlaybackResampledMyTone, AudioStreamPlaybackResampled)
|
||||
friend class AudioStreamMyToneResampled;
|
||||
|
||||
private:
|
||||
enum {
|
||||
PCM_BUFFER_SIZE = 4096
|
||||
};
|
||||
enum {
|
||||
MIX_FRAC_BITS = 13,
|
||||
MIX_FRAC_LEN = (1 << MIX_FRAC_BITS),
|
||||
MIX_FRAC_MASK = MIX_FRAC_LEN - 1,
|
||||
};
|
||||
void *pcm_buffer;
|
||||
Ref<AudioStreamMyToneResampled> base;
|
||||
bool active;
|
||||
private:
|
||||
enum {
|
||||
PCM_BUFFER_SIZE = 4096
|
||||
};
|
||||
enum {
|
||||
MIX_FRAC_BITS = 13,
|
||||
MIX_FRAC_LEN = (1 << MIX_FRAC_BITS),
|
||||
MIX_FRAC_MASK = MIX_FRAC_LEN - 1,
|
||||
};
|
||||
void *pcm_buffer;
|
||||
Ref<AudioStreamMyToneResampled> base;
|
||||
bool active;
|
||||
|
||||
protected:
|
||||
virtual void _mix_internal(AudioFrame *p_buffer, int p_frames);
|
||||
protected:
|
||||
virtual void _mix_internal(AudioFrame *p_buffer, int p_frames);
|
||||
|
||||
public:
|
||||
virtual void start(float p_from_pos = 0.0);
|
||||
virtual void stop();
|
||||
virtual bool is_playing() const;
|
||||
virtual int get_loop_count() const; // times it looped
|
||||
virtual float get_playback_position() const;
|
||||
virtual void seek(float p_time);
|
||||
virtual float get_length() const; // if supported, otherwise return 0
|
||||
virtual float get_stream_sampling_rate();
|
||||
AudioStreamPlaybackResampledMyTone();
|
||||
~AudioStreamPlaybackResampledMyTone();
|
||||
};
|
||||
public:
|
||||
virtual void start(float p_from_pos = 0.0);
|
||||
virtual void stop();
|
||||
virtual bool is_playing() const;
|
||||
virtual int get_loop_count() const; // times it looped
|
||||
virtual float get_playback_position() const;
|
||||
virtual void seek(float p_time);
|
||||
virtual float get_length() const; // if supported, otherwise return 0
|
||||
virtual float get_stream_sampling_rate();
|
||||
AudioStreamPlaybackResampledMyTone();
|
||||
~AudioStreamPlaybackResampledMyTone();
|
||||
};
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "mytone_audiostream_resampled.h"
|
||||
#include "mytone_audiostream_resampled.h"
|
||||
|
||||
#include "core/math/math_funcs.h"
|
||||
#include "core/print_string.h"
|
||||
#include "core/math/math_funcs.h"
|
||||
#include "core/print_string.h"
|
||||
|
||||
AudioStreamPlaybackResampledMyTone::AudioStreamPlaybackResampledMyTone()
|
||||
: active(false) {
|
||||
AudioServer::get_singleton()->lock();
|
||||
pcm_buffer = AudioServer::get_singleton()->audio_data_alloc(PCM_BUFFER_SIZE);
|
||||
zeromem(pcm_buffer, PCM_BUFFER_SIZE);
|
||||
AudioServer::get_singleton()->unlock();
|
||||
}
|
||||
AudioStreamPlaybackResampledMyTone::~AudioStreamPlaybackResampledMyTone() {
|
||||
if (pcm_buffer) {
|
||||
AudioServer::get_singleton()->audio_data_free(pcm_buffer);
|
||||
pcm_buffer = NULL;
|
||||
}
|
||||
}
|
||||
void AudioStreamPlaybackResampledMyTone::stop() {
|
||||
active = false;
|
||||
base->reset();
|
||||
}
|
||||
void AudioStreamPlaybackResampledMyTone::start(float p_from_pos) {
|
||||
seek(p_from_pos);
|
||||
active = true;
|
||||
}
|
||||
void AudioStreamPlaybackResampledMyTone::seek(float p_time) {
|
||||
float max = get_length();
|
||||
if (p_time < 0) {
|
||||
p_time = 0;
|
||||
}
|
||||
base->set_position(uint64_t(p_time * base->mix_rate) << MIX_FRAC_BITS);
|
||||
}
|
||||
void AudioStreamPlaybackResampledMyTone::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
||||
ERR_FAIL_COND(!active);
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
zeromem(pcm_buffer, PCM_BUFFER_SIZE);
|
||||
int16_t *buf = (int16_t *)pcm_buffer;
|
||||
base->gen_tone(buf, p_frames);
|
||||
AudioStreamPlaybackResampledMyTone::AudioStreamPlaybackResampledMyTone()
|
||||
: active(false) {
|
||||
AudioServer::get_singleton()->lock();
|
||||
pcm_buffer = AudioServer::get_singleton()->audio_data_alloc(PCM_BUFFER_SIZE);
|
||||
zeromem(pcm_buffer, PCM_BUFFER_SIZE);
|
||||
AudioServer::get_singleton()->unlock();
|
||||
}
|
||||
AudioStreamPlaybackResampledMyTone::~AudioStreamPlaybackResampledMyTone() {
|
||||
if (pcm_buffer) {
|
||||
AudioServer::get_singleton()->audio_data_free(pcm_buffer);
|
||||
pcm_buffer = NULL;
|
||||
}
|
||||
}
|
||||
void AudioStreamPlaybackResampledMyTone::stop() {
|
||||
active = false;
|
||||
base->reset();
|
||||
}
|
||||
void AudioStreamPlaybackResampledMyTone::start(float p_from_pos) {
|
||||
seek(p_from_pos);
|
||||
active = true;
|
||||
}
|
||||
void AudioStreamPlaybackResampledMyTone::seek(float p_time) {
|
||||
float max = get_length();
|
||||
if (p_time < 0) {
|
||||
p_time = 0;
|
||||
}
|
||||
base->set_position(uint64_t(p_time * base->mix_rate) << MIX_FRAC_BITS);
|
||||
}
|
||||
void AudioStreamPlaybackResampledMyTone::_mix_internal(AudioFrame *p_buffer, int p_frames) {
|
||||
ERR_FAIL_COND(!active);
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
zeromem(pcm_buffer, PCM_BUFFER_SIZE);
|
||||
int16_t *buf = (int16_t *)pcm_buffer;
|
||||
base->gen_tone(buf, p_frames);
|
||||
|
||||
for(int i = 0; i < p_frames; i++) {
|
||||
float sample = float(buf[i]) / 32767.0;
|
||||
p_buffer[i] = AudioFrame(sample, sample);
|
||||
}
|
||||
}
|
||||
float AudioStreamPlaybackResampledMyTone::get_stream_sampling_rate() {
|
||||
return float(base->mix_rate);
|
||||
}
|
||||
int AudioStreamPlaybackResampledMyTone::get_loop_count() const {
|
||||
return 0;
|
||||
}
|
||||
float AudioStreamPlaybackResampledMyTone::get_playback_position() const {
|
||||
return 0.0;
|
||||
}
|
||||
float AudioStreamPlaybackResampledMyTone::get_length() const {
|
||||
return 0.0;
|
||||
}
|
||||
bool AudioStreamPlaybackResampledMyTone::is_playing() const {
|
||||
return active;
|
||||
}
|
||||
for(int i = 0; i < p_frames; i++) {
|
||||
float sample = float(buf[i]) / 32767.0;
|
||||
p_buffer[i] = AudioFrame(sample, sample);
|
||||
}
|
||||
}
|
||||
float AudioStreamPlaybackResampledMyTone::get_stream_sampling_rate() {
|
||||
return float(base->mix_rate);
|
||||
}
|
||||
int AudioStreamPlaybackResampledMyTone::get_loop_count() const {
|
||||
return 0;
|
||||
}
|
||||
float AudioStreamPlaybackResampledMyTone::get_playback_position() const {
|
||||
return 0.0;
|
||||
}
|
||||
float AudioStreamPlaybackResampledMyTone::get_length() const {
|
||||
return 0.0;
|
||||
}
|
||||
bool AudioStreamPlaybackResampledMyTone::is_playing() const {
|
||||
return active;
|
||||
}
|
||||
|
||||
References:
|
||||
~~~~~~~~~~~
|
||||
|
||||
@@ -40,231 +40,231 @@ an initialization state and a cleanup procedure.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#ifndef HILBERT_HOTEL_H
|
||||
#define HILBERT_HOTEL_H
|
||||
#ifndef HILBERT_HOTEL_H
|
||||
#define HILBERT_HOTEL_H
|
||||
|
||||
#include "core/object/object.h"
|
||||
#include "core/os/thread.h"
|
||||
#include "core/os/mutex.h"
|
||||
#include "core/templates/list.h"
|
||||
#include "core/templates/rid.h"
|
||||
#include "core/templates/set.h"
|
||||
#include "core/variant/variant.h"
|
||||
#include "core/object/object.h"
|
||||
#include "core/os/thread.h"
|
||||
#include "core/os/mutex.h"
|
||||
#include "core/templates/list.h"
|
||||
#include "core/templates/rid.h"
|
||||
#include "core/templates/set.h"
|
||||
#include "core/variant/variant.h"
|
||||
|
||||
class HilbertHotel : public Object {
|
||||
GDCLASS(HilbertHotel, Object);
|
||||
class HilbertHotel : public Object {
|
||||
GDCLASS(HilbertHotel, Object);
|
||||
|
||||
static HilbertHotel *singleton;
|
||||
static void thread_func(void *p_udata);
|
||||
static HilbertHotel *singleton;
|
||||
static void thread_func(void *p_udata);
|
||||
|
||||
private:
|
||||
bool thread_exited;
|
||||
mutable bool exit_thread;
|
||||
Thread *thread;
|
||||
Mutex *mutex;
|
||||
private:
|
||||
bool thread_exited;
|
||||
mutable bool exit_thread;
|
||||
Thread *thread;
|
||||
Mutex *mutex;
|
||||
|
||||
public:
|
||||
static HilbertHotel *get_singleton();
|
||||
Error init();
|
||||
void lock();
|
||||
void unlock();
|
||||
void finish();
|
||||
public:
|
||||
static HilbertHotel *get_singleton();
|
||||
Error init();
|
||||
void lock();
|
||||
void unlock();
|
||||
void finish();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
private:
|
||||
uint64_t counter;
|
||||
RID_Owner<InfiniteBus> bus_owner;
|
||||
// https://github.com/godotengine/godot/blob/master/core/templates/rid.h
|
||||
Set<RID> buses;
|
||||
void _emit_occupy_room(uint64_t room, RID rid);
|
||||
private:
|
||||
uint64_t counter;
|
||||
RID_Owner<InfiniteBus> bus_owner;
|
||||
// https://github.com/godotengine/godot/blob/master/core/templates/rid.h
|
||||
Set<RID> buses;
|
||||
void _emit_occupy_room(uint64_t room, RID rid);
|
||||
|
||||
public:
|
||||
RID create_bus();
|
||||
Variant get_bus_info(RID id);
|
||||
bool empty();
|
||||
bool delete_bus(RID id);
|
||||
void clear();
|
||||
void register_rooms();
|
||||
HilbertHotel();
|
||||
};
|
||||
public:
|
||||
RID create_bus();
|
||||
Variant get_bus_info(RID id);
|
||||
bool empty();
|
||||
bool delete_bus(RID id);
|
||||
void clear();
|
||||
void register_rooms();
|
||||
HilbertHotel();
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
#include "hilbert_hotel.h"
|
||||
#include "hilbert_hotel.h"
|
||||
|
||||
#include "core/variant/dictionary.h"
|
||||
#include "core/os/os.h"
|
||||
#include "core/variant/dictionary.h"
|
||||
#include "core/os/os.h"
|
||||
|
||||
#include "prime_225.h"
|
||||
#include "prime_225.h"
|
||||
|
||||
void HilbertHotel::thread_func(void *p_udata) {
|
||||
void HilbertHotel::thread_func(void *p_udata) {
|
||||
|
||||
HilbertHotel *ac = (HilbertHotel *) p_udata;
|
||||
uint64_t msdelay = 1000;
|
||||
HilbertHotel *ac = (HilbertHotel *) p_udata;
|
||||
uint64_t msdelay = 1000;
|
||||
|
||||
while (!ac->exit_thread) {
|
||||
if (!ac->empty()) {
|
||||
ac->lock();
|
||||
ac->register_rooms();
|
||||
ac->unlock();
|
||||
}
|
||||
OS::get_singleton()->delay_usec(msdelay * 1000);
|
||||
}
|
||||
}
|
||||
while (!ac->exit_thread) {
|
||||
if (!ac->empty()) {
|
||||
ac->lock();
|
||||
ac->register_rooms();
|
||||
ac->unlock();
|
||||
}
|
||||
OS::get_singleton()->delay_usec(msdelay * 1000);
|
||||
}
|
||||
}
|
||||
|
||||
Error HilbertHotel::init() {
|
||||
thread_exited = false;
|
||||
counter = 0;
|
||||
mutex = Mutex::create();
|
||||
thread = Thread::create(HilbertHotel::thread_func, this);
|
||||
return OK;
|
||||
}
|
||||
Error HilbertHotel::init() {
|
||||
thread_exited = false;
|
||||
counter = 0;
|
||||
mutex = Mutex::create();
|
||||
thread = Thread::create(HilbertHotel::thread_func, this);
|
||||
return OK;
|
||||
}
|
||||
|
||||
HilbertHotel *HilbertHotel::singleton = NULL;
|
||||
HilbertHotel *HilbertHotel::singleton = NULL;
|
||||
|
||||
HilbertHotel *HilbertHotel::get_singleton() {
|
||||
return singleton;
|
||||
}
|
||||
HilbertHotel *HilbertHotel::get_singleton() {
|
||||
return singleton;
|
||||
}
|
||||
|
||||
void HilbertHotel::register_rooms() {
|
||||
for (Set<RID>::Element *e = buses.front(); e; e = e->next()) {
|
||||
auto bus = bus_owner.getornull(e->get());
|
||||
void HilbertHotel::register_rooms() {
|
||||
for (Set<RID>::Element *e = buses.front(); e; e = e->next()) {
|
||||
auto bus = bus_owner.getornull(e->get());
|
||||
|
||||
if (bus) {
|
||||
uint64_t room = bus->next_room();
|
||||
_emit_occupy_room(room, bus->get_self());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bus) {
|
||||
uint64_t room = bus->next_room();
|
||||
_emit_occupy_room(room, bus->get_self());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HilbertHotel::unlock() {
|
||||
if (!thread || !mutex) {
|
||||
return;
|
||||
}
|
||||
void HilbertHotel::unlock() {
|
||||
if (!thread || !mutex) {
|
||||
return;
|
||||
}
|
||||
|
||||
mutex->unlock();
|
||||
}
|
||||
mutex->unlock();
|
||||
}
|
||||
|
||||
void HilbertHotel::lock() {
|
||||
if (!thread || !mutex) {
|
||||
return;
|
||||
}
|
||||
void HilbertHotel::lock() {
|
||||
if (!thread || !mutex) {
|
||||
return;
|
||||
}
|
||||
|
||||
mutex->lock();
|
||||
}
|
||||
mutex->lock();
|
||||
}
|
||||
|
||||
void HilbertHotel::_emit_occupy_room(uint64_t room, RID rid) {
|
||||
_HilbertHotel::get_singleton()->_occupy_room(room, rid);
|
||||
}
|
||||
void HilbertHotel::_emit_occupy_room(uint64_t room, RID rid) {
|
||||
_HilbertHotel::get_singleton()->_occupy_room(room, rid);
|
||||
}
|
||||
|
||||
Variant HilbertHotel::get_bus_info(RID id) {
|
||||
InfiniteBus *bus = bus_owner.getornull(id);
|
||||
Variant HilbertHotel::get_bus_info(RID id) {
|
||||
InfiniteBus *bus = bus_owner.getornull(id);
|
||||
|
||||
if (bus) {
|
||||
Dictionary d;
|
||||
d["prime"] = bus->get_bus_num();
|
||||
d["current_room"] = bus->get_current_room();
|
||||
return d;
|
||||
}
|
||||
if (bus) {
|
||||
Dictionary d;
|
||||
d["prime"] = bus->get_bus_num();
|
||||
d["current_room"] = bus->get_current_room();
|
||||
return d;
|
||||
}
|
||||
|
||||
return Variant();
|
||||
}
|
||||
return Variant();
|
||||
}
|
||||
|
||||
void HilbertHotel::finish() {
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
void HilbertHotel::finish() {
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
exit_thread = true;
|
||||
Thread::wait_to_finish(thread);
|
||||
exit_thread = true;
|
||||
Thread::wait_to_finish(thread);
|
||||
|
||||
memdelete(thread);
|
||||
memdelete(thread);
|
||||
|
||||
if (mutex) {
|
||||
memdelete(mutex);
|
||||
}
|
||||
if (mutex) {
|
||||
memdelete(mutex);
|
||||
}
|
||||
|
||||
thread = NULL;
|
||||
}
|
||||
thread = NULL;
|
||||
}
|
||||
|
||||
RID HilbertHotel::create_bus() {
|
||||
lock();
|
||||
InfiniteBus *ptr = memnew(InfiniteBus(PRIME[counter++]));
|
||||
RID ret = bus_owner.make_rid(ptr);
|
||||
ptr->set_self(ret);
|
||||
buses.insert(ret);
|
||||
unlock();
|
||||
RID HilbertHotel::create_bus() {
|
||||
lock();
|
||||
InfiniteBus *ptr = memnew(InfiniteBus(PRIME[counter++]));
|
||||
RID ret = bus_owner.make_rid(ptr);
|
||||
ptr->set_self(ret);
|
||||
buses.insert(ret);
|
||||
unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// https://github.com/godotengine/godot/blob/master/core/templates/rid.h
|
||||
bool HilbertHotel::delete_bus(RID id) {
|
||||
if (bus_owner.owns(id)) {
|
||||
lock();
|
||||
InfiniteBus *b = bus_owner.get(id);
|
||||
bus_owner.free(id);
|
||||
buses.erase(id);
|
||||
memdelete(b);
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
// https://github.com/godotengine/godot/blob/master/core/templates/rid.h
|
||||
bool HilbertHotel::delete_bus(RID id) {
|
||||
if (bus_owner.owns(id)) {
|
||||
lock();
|
||||
InfiniteBus *b = bus_owner.get(id);
|
||||
bus_owner.free(id);
|
||||
buses.erase(id);
|
||||
memdelete(b);
|
||||
unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void HilbertHotel::clear() {
|
||||
for (Set<RID>::Element *e = buses.front(); e; e = e->next()) {
|
||||
delete_bus(e->get());
|
||||
}
|
||||
}
|
||||
void HilbertHotel::clear() {
|
||||
for (Set<RID>::Element *e = buses.front(); e; e = e->next()) {
|
||||
delete_bus(e->get());
|
||||
}
|
||||
}
|
||||
|
||||
bool HilbertHotel::empty() {
|
||||
return buses.size() <= 0;
|
||||
}
|
||||
bool HilbertHotel::empty() {
|
||||
return buses.size() <= 0;
|
||||
}
|
||||
|
||||
void HilbertHotel::_bind_methods() {
|
||||
}
|
||||
void HilbertHotel::_bind_methods() {
|
||||
}
|
||||
|
||||
HilbertHotel::HilbertHotel() {
|
||||
singleton = this;
|
||||
}
|
||||
HilbertHotel::HilbertHotel() {
|
||||
singleton = this;
|
||||
}
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
/* prime_225.h */
|
||||
/* prime_225.h */
|
||||
|
||||
const uint64_t PRIME[225] = {
|
||||
2,3,5,7,11,13,17,19,23,
|
||||
29,31,37,41,43,47,53,59,61,
|
||||
67,71,73,79,83,89,97,101,103,
|
||||
107,109,113,127,131,137,139,149,151,
|
||||
157,163,167,173,179,181,191,193,197,
|
||||
199,211,223,227,229,233,239,241,251,
|
||||
257,263,269,271,277,281,283,293,307,
|
||||
311,313,317,331,337,347,349,353,359,
|
||||
367,373,379,383,389,397,401,409,419,
|
||||
421,431,433,439,443,449,457,461,463,
|
||||
467,479,487,491,499,503,509,521,523,
|
||||
541,547,557,563,569,571,577,587,593,
|
||||
599,601,607,613,617,619,631,641,643,
|
||||
647,653,659,661,673,677,683,691,701,
|
||||
709,719,727,733,739,743,751,757,761,
|
||||
769,773,787,797,809,811,821,823,827,
|
||||
829,839,853,857,859,863,877,881,883,
|
||||
887,907,911,919,929,937,941,947,953,
|
||||
967,971,977,983,991,997,1009,1013,1019,
|
||||
1021,1031,1033,1039,1049,1051,1061,1063,1069,
|
||||
1087,1091,1093,1097,1103,1109,1117,1123,1129,
|
||||
1151,1153,1163,1171,1181,1187,1193,1201,1213,
|
||||
1217,1223,1229,1231,1237,1249,1259,1277,1279,
|
||||
1283,1289,1291,1297,1301,1303,1307,1319,1321,
|
||||
1327,1361,1367,1373,1381,1399,1409,1423,1427
|
||||
};
|
||||
const uint64_t PRIME[225] = {
|
||||
2,3,5,7,11,13,17,19,23,
|
||||
29,31,37,41,43,47,53,59,61,
|
||||
67,71,73,79,83,89,97,101,103,
|
||||
107,109,113,127,131,137,139,149,151,
|
||||
157,163,167,173,179,181,191,193,197,
|
||||
199,211,223,227,229,233,239,241,251,
|
||||
257,263,269,271,277,281,283,293,307,
|
||||
311,313,317,331,337,347,349,353,359,
|
||||
367,373,379,383,389,397,401,409,419,
|
||||
421,431,433,439,443,449,457,461,463,
|
||||
467,479,487,491,499,503,509,521,523,
|
||||
541,547,557,563,569,571,577,587,593,
|
||||
599,601,607,613,617,619,631,641,643,
|
||||
647,653,659,661,673,677,683,691,701,
|
||||
709,719,727,733,739,743,751,757,761,
|
||||
769,773,787,797,809,811,821,823,827,
|
||||
829,839,853,857,859,863,877,881,883,
|
||||
887,907,911,919,929,937,941,947,953,
|
||||
967,971,977,983,991,997,1009,1013,1019,
|
||||
1021,1031,1033,1039,1049,1051,1061,1063,1069,
|
||||
1087,1091,1093,1097,1103,1109,1117,1123,1129,
|
||||
1151,1153,1163,1171,1181,1187,1193,1201,1213,
|
||||
1217,1223,1229,1231,1237,1249,1259,1277,1279,
|
||||
1283,1289,1291,1297,1301,1303,1307,1319,1321,
|
||||
1327,1361,1367,1373,1381,1399,1409,1423,1427
|
||||
};
|
||||
|
||||
Custom managed resource data
|
||||
----------------------------
|
||||
@@ -276,37 +276,37 @@ object-oriented C code.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
class InfiniteBus : public RID_Data {
|
||||
RID self;
|
||||
class InfiniteBus : public RID_Data {
|
||||
RID self;
|
||||
|
||||
private:
|
||||
uint64_t prime_num;
|
||||
uint64_t num;
|
||||
private:
|
||||
uint64_t prime_num;
|
||||
uint64_t num;
|
||||
|
||||
public:
|
||||
uint64_t next_room() {
|
||||
return prime_num * num++;
|
||||
}
|
||||
public:
|
||||
uint64_t next_room() {
|
||||
return prime_num * num++;
|
||||
}
|
||||
|
||||
uint64_t get_bus_num() const {
|
||||
return prime_num;
|
||||
}
|
||||
uint64_t get_bus_num() const {
|
||||
return prime_num;
|
||||
}
|
||||
|
||||
uint64_t get_current_room() const {
|
||||
return prime_num * num;
|
||||
}
|
||||
uint64_t get_current_room() const {
|
||||
return prime_num * num;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ void set_self(const RID &p_self) {
|
||||
self = p_self;
|
||||
}
|
||||
_FORCE_INLINE_ void set_self(const RID &p_self) {
|
||||
self = p_self;
|
||||
}
|
||||
|
||||
_FORCE_INLINE_ RID get_self() const {
|
||||
return self;
|
||||
}
|
||||
_FORCE_INLINE_ RID get_self() const {
|
||||
return self;
|
||||
}
|
||||
|
||||
InfiniteBus(uint64_t prime) : prime_num(prime), num(1) {};
|
||||
~InfiniteBus() {};
|
||||
}
|
||||
InfiniteBus(uint64_t prime) : prime_num(prime), num(1) {};
|
||||
~InfiniteBus() {};
|
||||
}
|
||||
|
||||
References
|
||||
~~~~~~~~~~~
|
||||
@@ -330,44 +330,44 @@ is used to register the dummy class in GDScript.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
/* register_types.cpp */
|
||||
/* register_types.cpp */
|
||||
|
||||
#include "register_types.h"
|
||||
#include "register_types.h"
|
||||
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/config/engine.h"
|
||||
#include "core/object/class_db.h"
|
||||
#include "core/config/engine.h"
|
||||
|
||||
#include "hilbert_hotel.h"
|
||||
#include "hilbert_hotel.h"
|
||||
|
||||
static HilbertHotel *hilbert_hotel = NULL;
|
||||
static _HilbertHotel *_hilbert_hotel = NULL;
|
||||
static HilbertHotel *hilbert_hotel = NULL;
|
||||
static _HilbertHotel *_hilbert_hotel = NULL;
|
||||
|
||||
void register_hilbert_hotel_types() {
|
||||
hilbert_hotel = memnew(HilbertHotel);
|
||||
hilbert_hotel->init();
|
||||
_hilbert_hotel = memnew(_HilbertHotel);
|
||||
ClassDB::register_class<_HilbertHotel>();
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("HilbertHotel", _HilbertHotel::get_singleton()));
|
||||
}
|
||||
void register_hilbert_hotel_types() {
|
||||
hilbert_hotel = memnew(HilbertHotel);
|
||||
hilbert_hotel->init();
|
||||
_hilbert_hotel = memnew(_HilbertHotel);
|
||||
ClassDB::register_class<_HilbertHotel>();
|
||||
Engine::get_singleton()->add_singleton(Engine::Singleton("HilbertHotel", _HilbertHotel::get_singleton()));
|
||||
}
|
||||
|
||||
void unregister_hilbert_hotel_types() {
|
||||
if (hilbert_hotel) {
|
||||
hilbert_hotel->finish();
|
||||
memdelete(hilbert_hotel);
|
||||
}
|
||||
void unregister_hilbert_hotel_types() {
|
||||
if (hilbert_hotel) {
|
||||
hilbert_hotel->finish();
|
||||
memdelete(hilbert_hotel);
|
||||
}
|
||||
|
||||
if (_hilbert_hotel) {
|
||||
memdelete(_hilbert_hotel);
|
||||
}
|
||||
}
|
||||
if (_hilbert_hotel) {
|
||||
memdelete(_hilbert_hotel);
|
||||
}
|
||||
}
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
/* register_types.h */
|
||||
/* register_types.h */
|
||||
|
||||
/* Yes, the word in the middle must be the same as the module folder name */
|
||||
void register_hilbert_hotel_types();
|
||||
void unregister_hilbert_hotel_types();
|
||||
/* Yes, the word in the middle must be the same as the module folder name */
|
||||
void register_hilbert_hotel_types();
|
||||
void unregister_hilbert_hotel_types();
|
||||
|
||||
- `servers/register_server_types.cpp <https://github.com/godotengine/godot/blob/master/servers/register_server_types.cpp>`__
|
||||
|
||||
@@ -378,9 +378,9 @@ The dummy class binds singleton methods to GDScript. In most cases, the dummy cl
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
Variant _HilbertHotel::get_bus_info(RID id) {
|
||||
return HilbertHotel::get_singleton()->get_bus_info(id);
|
||||
}
|
||||
Variant _HilbertHotel::get_bus_info(RID id) {
|
||||
return HilbertHotel::get_singleton()->get_bus_info(id);
|
||||
}
|
||||
|
||||
Binding Signals
|
||||
|
||||
@@ -388,75 +388,75 @@ It is possible to emit signals to GDScript by calling the GDScript dummy object.
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
void HilbertHotel::_emit_occupy_room(uint64_t room, RID rid) {
|
||||
_HilbertHotel::get_singleton()->_occupy_room(room, rid);
|
||||
}
|
||||
void HilbertHotel::_emit_occupy_room(uint64_t room, RID rid) {
|
||||
_HilbertHotel::get_singleton()->_occupy_room(room, rid);
|
||||
}
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
class _HilbertHotel : public Object {
|
||||
GDCLASS(_HilbertHotel, Object);
|
||||
class _HilbertHotel : public Object {
|
||||
GDCLASS(_HilbertHotel, Object);
|
||||
|
||||
friend class HilbertHotel;
|
||||
static _HilbertHotel *singleton;
|
||||
friend class HilbertHotel;
|
||||
static _HilbertHotel *singleton;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
||||
private:
|
||||
void _occupy_room(int room_number, RID bus);
|
||||
private:
|
||||
void _occupy_room(int room_number, RID bus);
|
||||
|
||||
public:
|
||||
RID create_bus();
|
||||
void connect_signals();
|
||||
bool delete_bus(RID id);
|
||||
static _HilbertHotel *get_singleton();
|
||||
Variant get_bus_info(RID id);
|
||||
public:
|
||||
RID create_bus();
|
||||
void connect_signals();
|
||||
bool delete_bus(RID id);
|
||||
static _HilbertHotel *get_singleton();
|
||||
Variant get_bus_info(RID id);
|
||||
|
||||
_HilbertHotel();
|
||||
~_HilbertHotel();
|
||||
};
|
||||
_HilbertHotel();
|
||||
~_HilbertHotel();
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
_HilbertHotel *_HilbertHotel::singleton = NULL;
|
||||
_HilbertHotel *_HilbertHotel::get_singleton() { return singleton; }
|
||||
_HilbertHotel *_HilbertHotel::singleton = NULL;
|
||||
_HilbertHotel *_HilbertHotel::get_singleton() { return singleton; }
|
||||
|
||||
RID _HilbertHotel::create_bus() {
|
||||
return HilbertHotel::get_singleton()->create_bus();
|
||||
}
|
||||
RID _HilbertHotel::create_bus() {
|
||||
return HilbertHotel::get_singleton()->create_bus();
|
||||
}
|
||||
|
||||
bool _HilbertHotel::delete_bus(RID rid) {
|
||||
return HilbertHotel::get_singleton()->delete_bus(rid);
|
||||
}
|
||||
bool _HilbertHotel::delete_bus(RID rid) {
|
||||
return HilbertHotel::get_singleton()->delete_bus(rid);
|
||||
}
|
||||
|
||||
void _HilbertHotel::_occupy_room(int room_number, RID bus) {
|
||||
emit_signal("occupy_room", room_number, bus);
|
||||
}
|
||||
void _HilbertHotel::_occupy_room(int room_number, RID bus) {
|
||||
emit_signal("occupy_room", room_number, bus);
|
||||
}
|
||||
|
||||
Variant _HilbertHotel::get_bus_info(RID id) {
|
||||
return HilbertHotel::get_singleton()->get_bus_info(id);
|
||||
}
|
||||
Variant _HilbertHotel::get_bus_info(RID id) {
|
||||
return HilbertHotel::get_singleton()->get_bus_info(id);
|
||||
}
|
||||
|
||||
void _HilbertHotel::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_bus_info", "r_id"), &_HilbertHotel::get_bus_info);
|
||||
ClassDB::bind_method(D_METHOD("create_bus"), &_HilbertHotel::create_bus);
|
||||
ClassDB::bind_method(D_METHOD("delete_bus"), &_HilbertHotel::delete_bus);
|
||||
ADD_SIGNAL(MethodInfo("occupy_room", PropertyInfo(Variant::INT, "room_number"), PropertyInfo(Variant::_RID, "r_id")));
|
||||
}
|
||||
void _HilbertHotel::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_bus_info", "r_id"), &_HilbertHotel::get_bus_info);
|
||||
ClassDB::bind_method(D_METHOD("create_bus"), &_HilbertHotel::create_bus);
|
||||
ClassDB::bind_method(D_METHOD("delete_bus"), &_HilbertHotel::delete_bus);
|
||||
ADD_SIGNAL(MethodInfo("occupy_room", PropertyInfo(Variant::INT, "room_number"), PropertyInfo(Variant::_RID, "r_id")));
|
||||
}
|
||||
|
||||
void _HilbertHotel::connect_signals() {
|
||||
HilbertHotel::get_singleton()->connect("occupy_room", _HilbertHotel::get_singleton(), "_occupy_room");
|
||||
}
|
||||
void _HilbertHotel::connect_signals() {
|
||||
HilbertHotel::get_singleton()->connect("occupy_room", _HilbertHotel::get_singleton(), "_occupy_room");
|
||||
}
|
||||
|
||||
_HilbertHotel::_HilbertHotel() {
|
||||
singleton = this;
|
||||
}
|
||||
_HilbertHotel::_HilbertHotel() {
|
||||
singleton = this;
|
||||
}
|
||||
|
||||
_HilbertHotel::~_HilbertHotel() {
|
||||
}
|
||||
_HilbertHotel::~_HilbertHotel() {
|
||||
}
|
||||
|
||||
MessageQueue
|
||||
------------
|
||||
|
||||
@@ -135,16 +135,16 @@ These files should contain the following:
|
||||
#include "summator.h"
|
||||
|
||||
void initialize_summator_module(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
ClassDB::register_class<Summator>();
|
||||
}
|
||||
|
||||
void uninitialize_summator_module(ModuleInitializationLevel p_level) {
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
|
||||
return;
|
||||
}
|
||||
// Nothing to do here in this example.
|
||||
}
|
||||
|
||||
|
||||
@@ -65,12 +65,12 @@ read and handle data serialization.
|
||||
#include "core/io/resource_loader.h"
|
||||
|
||||
class ResourceFormatLoaderJson : public ResourceFormatLoader {
|
||||
GDCLASS(ResourceFormatLoaderJson, ResourceFormatLoader);
|
||||
GDCLASS(ResourceFormatLoaderJson, ResourceFormatLoader);
|
||||
public:
|
||||
virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL);
|
||||
virtual void get_recognized_extensions(List<String> *r_extensions) const;
|
||||
virtual bool handles_type(const String &p_type) const;
|
||||
virtual String get_resource_type(const String &p_path) const;
|
||||
virtual RES load(const String &p_path, const String &p_original_path, Error *r_error = NULL);
|
||||
virtual void get_recognized_extensions(List<String> *r_extensions) const;
|
||||
virtual bool handles_type(const String &p_type) const;
|
||||
virtual String get_resource_type(const String &p_path) const;
|
||||
};
|
||||
#endif // RESOURCE_LOADER_JSON_H
|
||||
|
||||
@@ -84,25 +84,25 @@ read and handle data serialization.
|
||||
|
||||
RES ResourceFormatLoaderJson::load(const String &p_path, const String &p_original_path, Error *r_error) {
|
||||
Ref<JsonResource> json = memnew(JsonResource);
|
||||
if (r_error) {
|
||||
*r_error = OK;
|
||||
}
|
||||
Error err = json->load_file(p_path);
|
||||
return json;
|
||||
if (r_error) {
|
||||
*r_error = OK;
|
||||
}
|
||||
Error err = json->load_file(p_path);
|
||||
return json;
|
||||
}
|
||||
|
||||
void ResourceFormatLoaderJson::get_recognized_extensions(List<String> *r_extensions) const {
|
||||
if (!r_extensions->find("json")) {
|
||||
r_extensions->push_back("json");
|
||||
}
|
||||
if (!r_extensions->find("json")) {
|
||||
r_extensions->push_back("json");
|
||||
}
|
||||
}
|
||||
|
||||
String ResourceFormatLoaderJson::get_resource_type(const String &p_path) const {
|
||||
return "Resource";
|
||||
return "Resource";
|
||||
}
|
||||
|
||||
bool ResourceFormatLoaderJson::handles_type(const String &p_type) const {
|
||||
return ClassDB::is_parent_class(p_type, "Resource");
|
||||
return ClassDB::is_parent_class(p_type, "Resource");
|
||||
}
|
||||
|
||||
Creating a ResourceFormatSaver
|
||||
@@ -121,11 +121,11 @@ If you'd like to be able to edit and save a resource, you can implement a
|
||||
#include "core/io/resource_saver.h"
|
||||
|
||||
class ResourceFormatSaverJson : public ResourceFormatSaver {
|
||||
GDCLASS(ResourceFormatSaverJson, ResourceFormatSaver);
|
||||
GDCLASS(ResourceFormatSaverJson, ResourceFormatSaver);
|
||||
public:
|
||||
virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
|
||||
virtual bool recognize(const RES &p_resource) const;
|
||||
virtual void get_recognized_extensions(const RES &p_resource, List<String> *r_extensions) const;
|
||||
virtual Error save(const String &p_path, const RES &p_resource, uint32_t p_flags = 0);
|
||||
virtual bool recognize(const RES &p_resource) const;
|
||||
virtual void get_recognized_extensions(const RES &p_resource, List<String> *r_extensions) const;
|
||||
};
|
||||
#endif // RESOURCE_SAVER_JSON_H
|
||||
|
||||
@@ -139,19 +139,19 @@ If you'd like to be able to edit and save a resource, you can implement a
|
||||
#include "scene/resources/resource_format_text.h"
|
||||
|
||||
Error ResourceFormatSaverJson::save(const String &p_path, const RES &p_resource, uint32_t p_flags) {
|
||||
Ref<JsonResource> json = memnew(JsonResource);
|
||||
Error error = json->save_file(p_path, p_resource);
|
||||
return error;
|
||||
Ref<JsonResource> json = memnew(JsonResource);
|
||||
Error error = json->save_file(p_path, p_resource);
|
||||
return error;
|
||||
}
|
||||
|
||||
bool ResourceFormatSaverJson::recognize(const RES &p_resource) const {
|
||||
return Object::cast_to<JsonResource>(*p_resource) != NULL;
|
||||
return Object::cast_to<JsonResource>(*p_resource) != NULL;
|
||||
}
|
||||
|
||||
void ResourceFormatSaverJson::get_recognized_extensions(const RES &p_resource, List<String> *r_extensions) const {
|
||||
if (Object::cast_to<JsonResource>(*p_resource)) {
|
||||
r_extensions->push_back("json");
|
||||
}
|
||||
if (Object::cast_to<JsonResource>(*p_resource)) {
|
||||
r_extensions->push_back("json");
|
||||
}
|
||||
}
|
||||
|
||||
Creating custom data types
|
||||
@@ -174,25 +174,25 @@ Here is an example of creating a custom datatype:
|
||||
#include "core/variant_parser.h"
|
||||
|
||||
class JsonResource : public Resource {
|
||||
GDCLASS(JsonResource, Resource);
|
||||
GDCLASS(JsonResource, Resource);
|
||||
|
||||
protected:
|
||||
static void _bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_dict", "dict"), &JsonResource::set_dict);
|
||||
ClassDB::bind_method(D_METHOD("get_dict"), &JsonResource::get_dict);
|
||||
static void _bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_dict", "dict"), &JsonResource::set_dict);
|
||||
ClassDB::bind_method(D_METHOD("get_dict"), &JsonResource::get_dict);
|
||||
|
||||
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "content"), "set_dict", "get_dict");
|
||||
}
|
||||
ADD_PROPERTY(PropertyInfo(Variant::DICTIONARY, "content"), "set_dict", "get_dict");
|
||||
}
|
||||
|
||||
private:
|
||||
Dictionary content;
|
||||
Dictionary content;
|
||||
|
||||
public:
|
||||
Error load_file(const String &p_path);
|
||||
Error save_file(const String &p_path, const RES &p_resource);
|
||||
Error load_file(const String &p_path);
|
||||
Error save_file(const String &p_path, const RES &p_resource);
|
||||
|
||||
void set_dict(const Dictionary &p_dict);
|
||||
Dictionary get_dict();
|
||||
void set_dict(const Dictionary &p_dict);
|
||||
Dictionary get_dict();
|
||||
};
|
||||
#endif // RESOURCE_JSON_H
|
||||
|
||||
@@ -203,59 +203,59 @@ Here is an example of creating a custom datatype:
|
||||
#include "resource_json.h"
|
||||
|
||||
Error JsonResource::load_file(const String &p_path) {
|
||||
Error error;
|
||||
FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &error);
|
||||
if (error != OK) {
|
||||
if (file) {
|
||||
file->close();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
Error error;
|
||||
FileAccess *file = FileAccess::open(p_path, FileAccess::READ, &error);
|
||||
if (error != OK) {
|
||||
if (file) {
|
||||
file->close();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
String json_string = String("");
|
||||
while (!file->eof_reached()) {
|
||||
json_string += file->get_line();
|
||||
}
|
||||
file->close();
|
||||
String json_string = String("");
|
||||
while (!file->eof_reached()) {
|
||||
json_string += file->get_line();
|
||||
}
|
||||
file->close();
|
||||
|
||||
String error_string;
|
||||
int error_line;
|
||||
JSON json;
|
||||
Variant result;
|
||||
error = json.parse(json_string, result, error_string, error_line);
|
||||
if (error != OK) {
|
||||
file->close();
|
||||
return error;
|
||||
}
|
||||
String error_string;
|
||||
int error_line;
|
||||
JSON json;
|
||||
Variant result;
|
||||
error = json.parse(json_string, result, error_string, error_line);
|
||||
if (error != OK) {
|
||||
file->close();
|
||||
return error;
|
||||
}
|
||||
|
||||
content = Dictionary(result);
|
||||
return OK;
|
||||
content = Dictionary(result);
|
||||
return OK;
|
||||
}
|
||||
|
||||
Error JsonResource::save_file(const String &p_path, const RES &p_resource) {
|
||||
Error error;
|
||||
FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &error);
|
||||
if (error != OK) {
|
||||
if (file) {
|
||||
file->close();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
Error error;
|
||||
FileAccess *file = FileAccess::open(p_path, FileAccess::WRITE, &error);
|
||||
if (error != OK) {
|
||||
if (file) {
|
||||
file->close();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
Ref<JsonResource> json_ref = p_resource.get_ref_ptr();
|
||||
JSON json;
|
||||
Ref<JsonResource> json_ref = p_resource.get_ref_ptr();
|
||||
JSON json;
|
||||
|
||||
file->store_string(json.print(json_ref->get_dict(), " "));
|
||||
file->close();
|
||||
return OK;
|
||||
file->store_string(json.print(json_ref->get_dict(), " "));
|
||||
file->close();
|
||||
return OK;
|
||||
}
|
||||
|
||||
void JsonResource::set_dict(const Dictionary &p_dict) {
|
||||
content = p_dict;
|
||||
content = p_dict;
|
||||
}
|
||||
|
||||
Dictionary JsonResource::get_dict() {
|
||||
return content;
|
||||
return content;
|
||||
}
|
||||
|
||||
Considerations
|
||||
@@ -277,25 +277,25 @@ calls into ``std::istream``.
|
||||
class GodotFileInStreamBuf : public std::streambuf {
|
||||
|
||||
public:
|
||||
GodotFileInStreamBuf(FileAccess *fa) {
|
||||
_file = fa;
|
||||
}
|
||||
int underflow() {
|
||||
if (_file->eof_reached()) {
|
||||
return EOF;
|
||||
} else {
|
||||
size_t pos = _file->get_position();
|
||||
uint8_t ret = _file->get_8();
|
||||
_file->seek(pos); // Required since get_8() advances the read head.
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
int uflow() {
|
||||
return _file->eof_reached() ? EOF : _file->get_8();
|
||||
}
|
||||
GodotFileInStreamBuf(FileAccess *fa) {
|
||||
_file = fa;
|
||||
}
|
||||
int underflow() {
|
||||
if (_file->eof_reached()) {
|
||||
return EOF;
|
||||
} else {
|
||||
size_t pos = _file->get_position();
|
||||
uint8_t ret = _file->get_8();
|
||||
_file->seek(pos); // Required since get_8() advances the read head.
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
int uflow() {
|
||||
return _file->eof_reached() ? EOF : _file->get_8();
|
||||
}
|
||||
|
||||
private:
|
||||
FileAccess *_file;
|
||||
FileAccess *_file;
|
||||
};
|
||||
|
||||
|
||||
@@ -335,21 +335,21 @@ when ``load`` is called.
|
||||
static Ref<ResourceFormatSaverJson> json_saver;
|
||||
|
||||
void register_json_types() {
|
||||
ClassDB::register_class<JsonResource>();
|
||||
ClassDB::register_class<JsonResource>();
|
||||
|
||||
json_loader.instantiate();
|
||||
ResourceLoader::add_resource_format_loader(json_loader);
|
||||
json_loader.instantiate();
|
||||
ResourceLoader::add_resource_format_loader(json_loader);
|
||||
|
||||
json_saver.instantiate();
|
||||
ResourceSaver::add_resource_format_saver(json_saver);
|
||||
json_saver.instantiate();
|
||||
ResourceSaver::add_resource_format_saver(json_saver);
|
||||
}
|
||||
|
||||
void unregister_json_types() {
|
||||
ResourceLoader::remove_resource_format_loader(json_loader);
|
||||
json_loader.unref();
|
||||
ResourceLoader::remove_resource_format_loader(json_loader);
|
||||
json_loader.unref();
|
||||
|
||||
ResourceSaver::remove_resource_format_saver(json_saver);
|
||||
json_saver.unref();
|
||||
ResourceSaver::remove_resource_format_saver(json_saver);
|
||||
json_saver.unref();
|
||||
}
|
||||
|
||||
References
|
||||
|
||||
@@ -86,7 +86,7 @@ Comment out the lines ``var velocity = Vector2.UP.rotated(rotation) * speed`` an
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
#var velocity = Vector2.UP.rotated(rotation) * speed
|
||||
|
||||
|
||||
#position += velocity * delta
|
||||
|
||||
.. code-tab:: csharp C#
|
||||
|
||||
@@ -25,9 +25,9 @@ Once enabled, you have access to all the turbulence properties.
|
||||
|
||||
.. warning::
|
||||
|
||||
Turbulence makes use of 3D noise, which has a high performance cost on the GPU.
|
||||
Only enable turbulence on a few particle systems on screen at most.
|
||||
Using turbulence is not recommended when targeting mobile/web platforms.
|
||||
Turbulence makes use of 3D noise, which has a high performance cost on the GPU.
|
||||
Only enable turbulence on a few particle systems on screen at most.
|
||||
Using turbulence is not recommended when targeting mobile/web platforms.
|
||||
|
||||
Noise properties
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -47,7 +47,7 @@ Finally, once you have added all your vertices call ``surface_end()`` to signal
|
||||
that you have finished generating the surface. You can call ``surface_begin()``
|
||||
and ``surface_end()`` multiple times to generate multiple surfaces for the mesh.
|
||||
|
||||
The example code below draws a single triangle in the ``_ready()`` function.
|
||||
The example code below draws a single triangle in the ``_ready()`` function.
|
||||
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript GDScript
|
||||
@@ -57,7 +57,7 @@ The example code below draws a single triangle in the ``_ready()`` function.
|
||||
func _ready():
|
||||
# Begin draw.
|
||||
mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)
|
||||
|
||||
|
||||
# Prepare attributes for add_vertex.
|
||||
mesh.surface_set_normal(Vector3(0, 0, 1))
|
||||
mesh.surface_set_uv(Vector2(0, 0))
|
||||
@@ -92,7 +92,7 @@ ImmediateMesh. If you want to recreate the mesh from scratch each frame, call
|
||||
|
||||
# Begin draw.
|
||||
mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)
|
||||
|
||||
|
||||
# Draw mesh.
|
||||
|
||||
# End drawing.
|
||||
|
||||
@@ -18,7 +18,7 @@ will detect suffixes in object names and will perform actions automatically.
|
||||
.. warning::
|
||||
|
||||
All the suffixes described below can be used with ``-``, ``$``, and ``_`` and are
|
||||
**case-insensitive**.
|
||||
**case-insensitive**.
|
||||
|
||||
Remove nodes (-noimp)
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
@@ -27,7 +27,7 @@ Obstacles and navigation mesh
|
||||
|
||||
For navigation mesh baking obstacles can be used to discard parts of all other source geometry inside the obstacle shape.
|
||||
|
||||
This can be used to stop navigation meshes being baked in unwanted places,
|
||||
This can be used to stop navigation meshes being baked in unwanted places,
|
||||
e.g. inside "solid" geometry like thick walls or on top of other geometry that should not be included for gameplay like roofs.
|
||||
|
||||
.. figure:: img/nav_mesh_obstacles_discard.webp
|
||||
@@ -47,7 +47,7 @@ For more details on the navigation mesh baking see :ref:`doc_navigation_using_na
|
||||
The property ``affect_navigation_mesh`` makes the obstacle contribute to the navigation mesh baking.
|
||||
It will be parsed or unparsed like all other node objects in a navigation mesh baking process.
|
||||
|
||||
The ``carve_navigation_mesh`` property makes the shape unaffected by offsets of the baking,
|
||||
The ``carve_navigation_mesh`` property makes the shape unaffected by offsets of the baking,
|
||||
e.g. the offset added by the navigation mesh ``agent_radius``.
|
||||
It will basically act as a stencil and cut into the already offset navigation mesh surface.
|
||||
It will still be affected by further postprocessing of the baking process like edge simplification.
|
||||
@@ -61,45 +61,45 @@ Obstacles are not involved in the source geometry parsing so adding them just be
|
||||
.. tabs::
|
||||
.. code-tab:: gdscript 2D GDScript
|
||||
|
||||
var obstacle_outline = PackedVector2Array([
|
||||
Vector2(-50, -50),
|
||||
Vector2(50, -50),
|
||||
Vector2(50, 50),
|
||||
Vector2(-50, 50)
|
||||
])
|
||||
var obstacle_outline = PackedVector2Array([
|
||||
Vector2(-50, -50),
|
||||
Vector2(50, -50),
|
||||
Vector2(50, 50),
|
||||
Vector2(-50, 50)
|
||||
])
|
||||
|
||||
var navigation_mesh = NavigationPolygon.new()
|
||||
var source_geometry = NavigationMeshSourceGeometryData2D.new()
|
||||
var navigation_mesh = NavigationPolygon.new()
|
||||
var source_geometry = NavigationMeshSourceGeometryData2D.new()
|
||||
|
||||
NavigationServer2D.parse_source_geometry_data(navigation_mesh, source_geometry, $MyTestRootNode)
|
||||
NavigationServer2D.parse_source_geometry_data(navigation_mesh, source_geometry, $MyTestRootNode)
|
||||
|
||||
var obstacle_carve: bool = true
|
||||
var obstacle_carve: bool = true
|
||||
|
||||
source_geometry.add_projected_obstruction(obstacle_outline, obstacle_carve)
|
||||
source_geometry.add_projected_obstruction(obstacle_outline, obstacle_carve)
|
||||
|
||||
NavigationServer2D.bake_from_source_geometry_data(navigation_mesh, source_geometry)
|
||||
NavigationServer2D.bake_from_source_geometry_data(navigation_mesh, source_geometry)
|
||||
|
||||
.. code-tab:: gdscript 3D GDScript
|
||||
|
||||
var obstacle_outline = PackedVector3Array([
|
||||
Vector3(-5, 0, -5),
|
||||
Vector3(5, 0, -5),
|
||||
Vector3(5, 0, 5),
|
||||
Vector3(-5, 0, 5)
|
||||
])
|
||||
var obstacle_outline = PackedVector3Array([
|
||||
Vector3(-5, 0, -5),
|
||||
Vector3(5, 0, -5),
|
||||
Vector3(5, 0, 5),
|
||||
Vector3(-5, 0, 5)
|
||||
])
|
||||
|
||||
var navigation_mesh = NavigationMesh.new()
|
||||
var source_geometry = NavigationMeshSourceGeometryData3D.new()
|
||||
var navigation_mesh = NavigationMesh.new()
|
||||
var source_geometry = NavigationMeshSourceGeometryData3D.new()
|
||||
|
||||
NavigationServer3D.parse_source_geometry_data(navigation_mesh, source_geometry, $MyTestRootNode)
|
||||
NavigationServer3D.parse_source_geometry_data(navigation_mesh, source_geometry, $MyTestRootNode)
|
||||
|
||||
var obstacle_elevation: float = $MyTestObstacleNode.global_position.y
|
||||
var obstacle_height: float = 50.0
|
||||
var obstacle_carve: bool = true
|
||||
var obstacle_elevation: float = $MyTestObstacleNode.global_position.y
|
||||
var obstacle_height: float = 50.0
|
||||
var obstacle_carve: bool = true
|
||||
|
||||
source_geometry.add_projected_obstruction(obstacle_outline, obstacle_elevation, obstacle_height, obstacle_carve)
|
||||
source_geometry.add_projected_obstruction(obstacle_outline, obstacle_elevation, obstacle_height, obstacle_carve)
|
||||
|
||||
NavigationServer3D.bake_from_source_geometry_data(navigation_mesh, source_geometry)
|
||||
NavigationServer3D.bake_from_source_geometry_data(navigation_mesh, source_geometry)
|
||||
|
||||
Obstacles and agent avoidance
|
||||
-----------------------------
|
||||
|
||||
@@ -362,7 +362,7 @@ Example use of ``updateSubscription``:
|
||||
::
|
||||
|
||||
payment.updateSubscription(_active_subscription_purchase.purchase_token, \
|
||||
"new_sub_sku", SubscriptionProrationMode.IMMEDIATE_WITH_TIME_PRORATION)
|
||||
"new_sub_sku", SubscriptionProrationMode.IMMEDIATE_WITH_TIME_PRORATION)
|
||||
|
||||
|
||||
The ``confirmPriceChange()`` function can be used to launch price change confirmation flow
|
||||
|
||||
@@ -208,7 +208,7 @@ angle add a setter ``set(new_speed)`` which is executed with the input from the
|
||||
|
||||
|
||||
func _process(delta):
|
||||
rotation += PI * delta * speed
|
||||
rotation += PI * delta * speed
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
@@ -263,7 +263,7 @@ not be called.
|
||||
set(new_resource):
|
||||
resource = new_resource
|
||||
_on_resource_set()
|
||||
|
||||
|
||||
# This will only be called when you create, delete, or paste a resource.
|
||||
# You will not get an update when tweaking properties of it.
|
||||
func _on_resource_set():
|
||||
|
||||
@@ -151,40 +151,40 @@ use these as the base for creating other templates:
|
||||
|
||||
.. code-tab:: gdscript GDScript
|
||||
|
||||
# meta-description: Base template for Node with default Godot cycle methods
|
||||
# meta-description: Base template for Node with default Godot cycle methods
|
||||
|
||||
extends _BASE_
|
||||
extends _BASE_
|
||||
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
func _ready() -> void:
|
||||
pass # Replace with function body.
|
||||
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
||||
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
// meta-description: Base template for Node with default Godot cycle methods
|
||||
// meta-description: Base template for Node with default Godot cycle methods
|
||||
|
||||
using _BINDINGS_NAMESPACE_;
|
||||
using System;
|
||||
using _BINDINGS_NAMESPACE_;
|
||||
using System;
|
||||
|
||||
public partial class _CLASS_ : _BASE_
|
||||
{
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready()
|
||||
{
|
||||
}
|
||||
public partial class _CLASS_ : _BASE_
|
||||
{
|
||||
// Called when the node enters the scene tree for the first time.
|
||||
public override void _Ready()
|
||||
{
|
||||
}
|
||||
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
}
|
||||
}
|
||||
// Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
public override void _Process(double delta)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
The Godot editor provides a set of useful built-in node-specific templates, such as
|
||||
``basic_movement`` for both :ref:`CharacterBody2D <class_CharacterBody2D>` and
|
||||
|
||||
@@ -327,17 +327,17 @@ Iterating using the C-style for loop in C-derived languages can be quite complex
|
||||
[..]
|
||||
|
||||
for (int i = 0; i < 50; i++) {
|
||||
printf("Value: %c Index: %d\n", strings[i], i);
|
||||
}
|
||||
printf("Value: %c Index: %d\n", strings[i], i);
|
||||
}
|
||||
|
||||
// Even in STL:
|
||||
std::list<std::string> strings;
|
||||
|
||||
|
||||
[..]
|
||||
|
||||
for (std::string::const_iterator it = strings.begin(); it != strings.end(); it++) {
|
||||
std::cout << *it << std::endl;
|
||||
}
|
||||
for (std::string::const_iterator it = strings.begin(); it != strings.end(); it++) {
|
||||
std::cout << *it << std::endl;
|
||||
}
|
||||
|
||||
Because of this, GDScript makes the opinionated decision to have a for-in loop over iterables instead:
|
||||
|
||||
|
||||
@@ -1573,7 +1573,7 @@ is best to use ``for i in array.size()``.
|
||||
::
|
||||
|
||||
for i in array.size():
|
||||
array[i] = "Hello World"
|
||||
array[i] = "Hello World"
|
||||
|
||||
|
||||
The loop variable is local to the for-loop and assigning to it will not change
|
||||
|
||||
@@ -106,18 +106,18 @@ Tree order
|
||||
----------
|
||||
|
||||
Most node operations in Godot, such as drawing 2D, processing, or getting
|
||||
notifications are done in *tree order*, or top to bottom as seen in the
|
||||
notifications are done in *tree order*, or top to bottom as seen in the
|
||||
editor (also known as pre-order traversal):
|
||||
|
||||
.. image:: img/toptobottom.webp
|
||||
|
||||
For example, the top node in a scene has its ``_process()`` function
|
||||
called first, then the node below it has its ``_process()`` function called,
|
||||
For example, the top node in a scene has its ``_process()`` function
|
||||
called first, then the node below it has its ``_process()`` function called,
|
||||
then the node below that and so on.
|
||||
|
||||
An important exception is the ``_ready()`` function: each parent node has its
|
||||
``_ready()`` function called only after all its child nodes have their
|
||||
``_ready()`` functions called, so that the parent knows its children are
|
||||
``_ready()`` function called only after all its child nodes have their
|
||||
``_ready()`` functions called, so that the parent knows its children are
|
||||
completely ready to be accessed. This is also known as post-order traversal.
|
||||
In the above image, ``NameLabel`` would be notified first (but only after its
|
||||
children, if it had any!), followed by ``Name``, etc., and ``Panel`` would be
|
||||
@@ -137,7 +137,7 @@ with the priorities "0, 1, 2, 3" would be called in that order from left to righ
|
||||
#. Every node of the newly added scene will receive the "enter_tree"
|
||||
notification ( ``_enter_tree()`` callback in GDScript) in
|
||||
top-to-bottom order (pre-order traversal).
|
||||
#. Every node will receive the "ready" notification ( ``_ready()``
|
||||
#. Every node will receive the "ready" notification ( ``_ready()``
|
||||
callback in GDScript) for convenience, once all its children have
|
||||
received the "ready" notification (post-order traversal).
|
||||
#. When a scene (or part of it) is removed, they receive the "exit
|
||||
@@ -176,7 +176,7 @@ function
|
||||
var next_scene = preload("res://levels/level2.tscn")
|
||||
|
||||
func _my_level_was_completed():
|
||||
get_tree().change_scene_to_packed(next_scene)
|
||||
get_tree().change_scene_to_packed(next_scene)
|
||||
|
||||
.. code-tab:: csharp
|
||||
|
||||
|
||||
@@ -192,9 +192,9 @@ submatrix of the larger matrix is used.
|
||||
|
||||
.. code-block:: glsl
|
||||
|
||||
mat3 basis = mat3(MODEL_MATRIX);
|
||||
mat4 m4 = mat4(basis);
|
||||
mat2 m2 = mat2(m4);
|
||||
mat3 basis = mat3(MODEL_MATRIX);
|
||||
mat4 m4 = mat4(basis);
|
||||
mat2 m2 = mat2(m4);
|
||||
|
||||
Swizzling
|
||||
~~~~~~~~~
|
||||
|
||||
Reference in New Issue
Block a user