summaryrefslogtreecommitdiff
path: root/servers
diff options
context:
space:
mode:
Diffstat (limited to 'servers')
-rw-r--r--servers/SCsub20
-rw-r--r--servers/audio/SCsub6
-rw-r--r--servers/audio/audio_driver_dummy.cpp12
-rw-r--r--servers/audio/audio_driver_dummy.h10
-rw-r--r--servers/audio/audio_effect.cpp6
-rw-r--r--servers/audio/audio_effect.h26
-rw-r--r--servers/audio/audio_filter_sw.cpp6
-rw-r--r--servers/audio/audio_filter_sw.h4
-rw-r--r--servers/audio/audio_mixer_sw.cpp1222
-rw-r--r--servers/audio/audio_mixer_sw.h264
-rw-r--r--servers/audio/audio_rb_resampler.cpp2
-rw-r--r--servers/audio/audio_rb_resampler.h2
-rw-r--r--servers/audio/audio_server_sw.cpp1028
-rw-r--r--servers/audio/audio_server_sw.h286
-rw-r--r--servers/audio/audio_stream.cpp (renamed from servers/spatial_sound_server.cpp)60
-rw-r--r--servers/audio/audio_stream.h (renamed from servers/spatial_sound_2d_server.cpp)79
-rw-r--r--servers/audio/effects/SCsub7
-rw-r--r--servers/audio/effects/audio_effect_amplify.cpp50
-rw-r--r--servers/audio/effects/audio_effect_amplify.h40
-rw-r--r--servers/audio/effects/audio_effect_chorus.cpp365
-rw-r--r--servers/audio/effects/audio_effect_chorus.h115
-rw-r--r--servers/audio/effects/audio_effect_compressor.cpp227
-rw-r--r--servers/audio/effects/audio_effect_compressor.h70
-rw-r--r--servers/audio/effects/audio_effect_delay.cpp326
-rw-r--r--servers/audio/effects/audio_effect_delay.h112
-rw-r--r--servers/audio/effects/audio_effect_distortion.cpp171
-rw-r--r--servers/audio/effects/audio_effect_distortion.h69
-rw-r--r--servers/audio/effects/audio_effect_eq.cpp122
-rw-r--r--servers/audio/effects/audio_effect_eq.h72
-rw-r--r--servers/audio/effects/audio_effect_filter.cpp151
-rw-r--r--servers/audio/effects/audio_effect_filter.h125
-rw-r--r--servers/audio/effects/audio_effect_limiter.cpp124
-rw-r--r--servers/audio/effects/audio_effect_limiter.h58
-rw-r--r--servers/audio/effects/audio_effect_panner.cpp47
-rw-r--r--servers/audio/effects/audio_effect_panner.h40
-rw-r--r--servers/audio/effects/audio_effect_phaser.cpp148
-rw-r--r--servers/audio/effects/audio_effect_phaser.h81
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.cpp298
-rw-r--r--servers/audio/effects/audio_effect_pitch_shift.h89
-rw-r--r--servers/audio/effects/audio_effect_reverb.cpp182
-rw-r--r--servers/audio/effects/audio_effect_reverb.h76
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.cpp135
-rw-r--r--servers/audio/effects/audio_effect_stereo_enhance.h62
-rw-r--r--servers/audio/effects/eq.cpp219
-rw-r--r--servers/audio/effects/eq.h106
-rw-r--r--servers/audio/effects/reverb.cpp364
-rw-r--r--servers/audio/effects/reverb.h111
-rw-r--r--servers/audio/reverb_sw.cpp118
-rw-r--r--servers/audio/reverb_sw.h2
-rw-r--r--servers/audio/sample_manager_sw.cpp320
-rw-r--r--servers/audio/sample_manager_sw.h129
-rw-r--r--servers/audio/voice_rb_sw.h2
-rw-r--r--servers/audio_server.cpp1235
-rw-r--r--servers/audio_server.h411
-rw-r--r--servers/physics/SCsub4
-rw-r--r--servers/physics/area_pair_sw.cpp12
-rw-r--r--servers/physics/area_pair_sw.h10
-rw-r--r--servers/physics/area_sw.cpp18
-rw-r--r--servers/physics/area_sw.h32
-rw-r--r--servers/physics/body_pair_sw.cpp44
-rw-r--r--servers/physics/body_pair_sw.h10
-rw-r--r--servers/physics/body_sw.cpp138
-rw-r--r--servers/physics/body_sw.h69
-rw-r--r--servers/physics/broad_phase_basic.cpp10
-rw-r--r--servers/physics/broad_phase_basic.h8
-rw-r--r--servers/physics/broad_phase_octree.cpp10
-rw-r--r--servers/physics/broad_phase_octree.h6
-rw-r--r--servers/physics/broad_phase_sw.cpp2
-rw-r--r--servers/physics/broad_phase_sw.h8
-rw-r--r--servers/physics/collision_object_sw.cpp10
-rw-r--r--servers/physics/collision_object_sw.h8
-rw-r--r--servers/physics/collision_solver_sat.cpp70
-rw-r--r--servers/physics/collision_solver_sat.h4
-rw-r--r--servers/physics/collision_solver_sw.cpp32
-rw-r--r--servers/physics/collision_solver_sw.h8
-rw-r--r--servers/physics/constraint_sw.h8
-rw-r--r--servers/physics/gjk_epa.cpp2
-rw-r--r--servers/physics/gjk_epa.h2
-rw-r--r--servers/physics/joints/SCsub4
-rw-r--r--servers/physics/joints/cone_twist_joint_sw.cpp20
-rw-r--r--servers/physics/joints/cone_twist_joint_sw.h10
-rw-r--r--servers/physics/joints/generic_6dof_joint_sw.cpp99
-rw-r--r--servers/physics/joints/generic_6dof_joint_sw.h10
-rw-r--r--servers/physics/joints/hinge_joint_sw.cpp44
-rw-r--r--servers/physics/joints/hinge_joint_sw.h10
-rw-r--r--servers/physics/joints/jacobian_entry_sw.h12
-rw-r--r--servers/physics/joints/pin_joint_sw.cpp22
-rw-r--r--servers/physics/joints/pin_joint_sw.h10
-rw-r--r--servers/physics/joints/slider_joint_sw.cpp20
-rw-r--r--servers/physics/joints/slider_joint_sw.h10
-rw-r--r--servers/physics/joints_sw.h2
-rw-r--r--servers/physics/physics_server_sw.cpp63
-rw-r--r--servers/physics/physics_server_sw.h37
-rw-r--r--servers/physics/shape_sw.cpp214
-rw-r--r--servers/physics/shape_sw.h89
-rw-r--r--servers/physics/space_sw.cpp48
-rw-r--r--servers/physics/space_sw.h23
-rw-r--r--servers/physics/step_sw.cpp12
-rw-r--r--servers/physics/step_sw.h10
-rw-r--r--servers/physics_2d/SCsub4
-rw-r--r--servers/physics_2d/area_2d_sw.cpp20
-rw-r--r--servers/physics_2d/area_2d_sw.h34
-rw-r--r--servers/physics_2d/area_pair_2d_sw.cpp10
-rw-r--r--servers/physics_2d/area_pair_2d_sw.h10
-rw-r--r--servers/physics_2d/body_2d_sw.cpp79
-rw-r--r--servers/physics_2d/body_2d_sw.h34
-rw-r--r--servers/physics_2d/body_pair_2d_sw.cpp24
-rw-r--r--servers/physics_2d/body_pair_2d_sw.h10
-rw-r--r--servers/physics_2d/broad_phase_2d_basic.cpp4
-rw-r--r--servers/physics_2d/broad_phase_2d_basic.h2
-rw-r--r--servers/physics_2d/broad_phase_2d_hash_grid.cpp30
-rw-r--r--servers/physics_2d/broad_phase_2d_hash_grid.h2
-rw-r--r--servers/physics_2d/broad_phase_2d_sw.cpp2
-rw-r--r--servers/physics_2d/broad_phase_2d_sw.h2
-rw-r--r--servers/physics_2d/collision_object_2d_sw.cpp10
-rw-r--r--servers/physics_2d/collision_object_2d_sw.h26
-rw-r--r--servers/physics_2d/collision_solver_2d_sat.cpp90
-rw-r--r--servers/physics_2d/collision_solver_2d_sat.h4
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.cpp32
-rw-r--r--servers/physics_2d/collision_solver_2d_sw.h10
-rw-r--r--servers/physics_2d/constraint_2d_sw.h8
-rw-r--r--servers/physics_2d/joints_2d_sw.cpp32
-rw-r--r--servers/physics_2d/joints_2d_sw.h20
-rw-r--r--servers/physics_2d/physics_2d_server_sw.cpp76
-rw-r--r--servers/physics_2d/physics_2d_server_sw.h48
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.cpp22
-rw-r--r--servers/physics_2d/physics_2d_server_wrap_mt.h48
-rw-r--r--servers/physics_2d/shape_2d_sw.cpp90
-rw-r--r--servers/physics_2d/shape_2d_sw.h88
-rw-r--r--servers/physics_2d/space_2d_sw.cpp132
-rw-r--r--servers/physics_2d/space_2d_sw.h23
-rw-r--r--servers/physics_2d/step_2d_sw.cpp12
-rw-r--r--servers/physics_2d/step_2d_sw.h10
-rw-r--r--servers/physics_2d_server.cpp334
-rw-r--r--servers/physics_2d_server.h56
-rw-r--r--servers/physics_server.cpp359
-rw-r--r--servers/physics_server.h22
-rw-r--r--servers/register_server_types.cpp106
-rw-r--r--servers/register_server_types.h2
-rw-r--r--servers/server_wrap_mt_common.h2
-rw-r--r--servers/spatial_sound/SCsub5
-rw-r--r--servers/spatial_sound/spatial_sound_server_sw.cpp1071
-rw-r--r--servers/spatial_sound/spatial_sound_server_sw.h266
-rw-r--r--servers/spatial_sound_2d/SCsub5
-rw-r--r--servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp1042
-rw-r--r--servers/spatial_sound_2d/spatial_sound_2d_server_sw.h265
-rw-r--r--servers/spatial_sound_2d_server.h164
-rw-r--r--servers/spatial_sound_server.h168
-rw-r--r--servers/visual/SCsub4
-rw-r--r--servers/visual/particle_system_sw.cpp412
-rw-r--r--servers/visual/particle_system_sw.h131
-rw-r--r--servers/visual/rasterizer.cpp124
-rw-r--r--servers/visual/rasterizer.h1084
-rw-r--r--servers/visual/rasterizer_dummy.cpp1961
-rw-r--r--servers/visual/rasterizer_dummy.h791
-rw-r--r--servers/visual/shader_language.cpp4618
-rw-r--r--servers/visual/shader_language.h438
-rw-r--r--servers/visual/shader_types.cpp182
-rw-r--r--servers/visual/shader_types.h27
-rw-r--r--servers/visual/visual_server_canvas.cpp1270
-rw-r--r--servers/visual/visual_server_canvas.h217
-rw-r--r--servers/visual/visual_server_global.cpp10
-rw-r--r--servers/visual/visual_server_global.h26
-rw-r--r--servers/visual/visual_server_light_baker.cpp6
-rw-r--r--servers/visual/visual_server_light_baker.h29
-rw-r--r--servers/visual/visual_server_raster.cpp318
-rw-r--r--servers/visual/visual_server_raster.h964
-rw-r--r--servers/visual/visual_server_scene.cpp3629
-rw-r--r--servers/visual/visual_server_scene.h589
-rw-r--r--servers/visual/visual_server_viewport.cpp568
-rw-r--r--servers/visual/visual_server_viewport.h150
-rw-r--r--servers/visual/visual_server_wrap_mt.cpp212
-rw-r--r--servers/visual/visual_server_wrap_mt.h739
-rw-r--r--servers/visual_server.cpp1716
-rw-r--r--servers/visual_server.h908
175 files changed, 20739 insertions, 16005 deletions
diff --git a/servers/SCsub b/servers/SCsub
index d861847101..eefa6278c4 100644
--- a/servers/SCsub
+++ b/servers/SCsub
@@ -1,17 +1,19 @@
+#!/usr/bin/env python
+
Import('env')
-env.servers_sources=[]
-env.add_source_files(env.servers_sources,"*.cpp")
+env.servers_sources = []
+env.add_source_files(env.servers_sources, "*.cpp")
Export('env')
-SConscript('physics/SCsub');
-SConscript('physics_2d/SCsub');
-SConscript('visual/SCsub');
-SConscript('audio/SCsub');
-SConscript('spatial_sound/SCsub');
-SConscript('spatial_sound_2d/SCsub');
+SConscript('physics/SCsub')
+SConscript('physics_2d/SCsub')
+SConscript('visual/SCsub')
+SConscript('audio/SCsub')
+SConscript('spatial_sound/SCsub')
+SConscript('spatial_sound_2d/SCsub')
-lib = env.Library("servers",env.servers_sources)
+lib = env.Library("servers", env.servers_sources)
env.Prepend(LIBS=[lib])
diff --git a/servers/audio/SCsub b/servers/audio/SCsub
index d31af2c1c4..afaffcfe93 100644
--- a/servers/audio/SCsub
+++ b/servers/audio/SCsub
@@ -1,5 +1,9 @@
+#!/usr/bin/env python
+
Import('env')
-env.add_source_files(env.servers_sources,"*.cpp")
+env.add_source_files(env.servers_sources, "*.cpp")
Export('env')
+
+SConscript("effects/SCsub")
diff --git a/servers/audio/audio_driver_dummy.cpp b/servers/audio/audio_driver_dummy.cpp
index d0695451b9..6c12957851 100644
--- a/servers/audio/audio_driver_dummy.cpp
+++ b/servers/audio/audio_driver_dummy.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "audio_driver_dummy.h"
-#include "globals.h"
+#include "global_config.h"
#include "os/os.h"
@@ -43,7 +43,7 @@ Error AudioDriverDummy::init() {
mix_rate = 44100;
- output_format = OUTPUT_STEREO;
+ speaker_mode = SPEAKER_MODE_STEREO;
channels = 2;
int latency = GLOBAL_DEF("audio/output_latency",25);
@@ -97,16 +97,18 @@ int AudioDriverDummy::get_mix_rate() const {
return mix_rate;
};
-AudioDriverSW::OutputFormat AudioDriverDummy::get_output_format() const {
+AudioDriver::SpeakerMode AudioDriverDummy::get_speaker_mode() const {
- return output_format;
+ return speaker_mode;
};
+
void AudioDriverDummy::lock() {
if (!thread || !mutex)
return;
mutex->lock();
};
+
void AudioDriverDummy::unlock() {
if (!thread || !mutex)
diff --git a/servers/audio/audio_driver_dummy.h b/servers/audio/audio_driver_dummy.h
index 9421574f93..78ec41ea09 100644
--- a/servers/audio/audio_driver_dummy.h
+++ b/servers/audio/audio_driver_dummy.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,13 +29,13 @@
#ifndef AUDIO_DRIVER_DUMMY_H
#define AUDIO_DRIVER_DUMMY_H
-#include "servers/audio/audio_server_sw.h"
+#include "servers/audio_server.h"
#include "core/os/thread.h"
#include "core/os/mutex.h"
-class AudioDriverDummy : public AudioDriverSW {
+class AudioDriverDummy : public AudioDriver {
Thread* thread;
Mutex* mutex;
@@ -46,7 +46,7 @@ class AudioDriverDummy : public AudioDriverSW {
int buffer_size;
unsigned int mix_rate;
- OutputFormat output_format;
+ SpeakerMode speaker_mode;
int channels;
@@ -64,7 +64,7 @@ public:
virtual Error init();
virtual void start();
virtual int get_mix_rate() const;
- virtual OutputFormat get_output_format() const;
+ virtual SpeakerMode get_speaker_mode() const;
virtual void lock();
virtual void unlock();
virtual void finish();
diff --git a/servers/audio/audio_effect.cpp b/servers/audio/audio_effect.cpp
new file mode 100644
index 0000000000..372c0cbc13
--- /dev/null
+++ b/servers/audio/audio_effect.cpp
@@ -0,0 +1,6 @@
+#include "audio_effect.h"
+
+AudioEffect::AudioEffect()
+{
+
+}
diff --git a/servers/audio/audio_effect.h b/servers/audio/audio_effect.h
new file mode 100644
index 0000000000..02eb258f99
--- /dev/null
+++ b/servers/audio/audio_effect.h
@@ -0,0 +1,26 @@
+#ifndef AUDIOEFFECT_H
+#define AUDIOEFFECT_H
+
+#include "audio_frame.h"
+#include "resource.h"
+
+
+class AudioEffectInstance : public Reference {
+ GDCLASS(AudioEffectInstance,Reference)
+
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count)=0;
+
+};
+
+
+class AudioEffect : public Resource {
+ GDCLASS(AudioEffect,Resource)
+public:
+
+ virtual Ref<AudioEffectInstance> instance()=0;
+ AudioEffect();
+};
+
+#endif // AUDIOEFFECT_H
diff --git a/servers/audio/audio_filter_sw.cpp b/servers/audio/audio_filter_sw.cpp
index 3fb8e8f734..e97eb75d04 100644
--- a/servers/audio/audio_filter_sw.cpp
+++ b/servers/audio/audio_filter_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -142,9 +142,9 @@ void AudioFilterSW::prepare_coefficients(Coeffs *p_coeffs) {
//this one is extra tricky
double hicutoff=resonance;
double centercutoff = (cutoff+resonance)/2.0;
- double bandwidth=(Math::log(centercutoff)-Math::log(hicutoff))/Math::log(2);
+ double bandwidth=(Math::log(centercutoff)-Math::log(hicutoff))/Math::log((double)2);
omega=2.0*Math_PI*centercutoff/sampling_rate;
- alpha = Math::sin(omega)*Math::sinh( Math::log(2)/2 * bandwidth * omega/Math::sin(omega) );
+ alpha = Math::sin(omega)*Math::sinh( Math::log((double)2)/2 * bandwidth * omega/Math::sin(omega) );
a0=1+alpha;
p_coeffs->b0 = alpha;
diff --git a/servers/audio/audio_filter_sw.h b/servers/audio/audio_filter_sw.h
index d4d225ce29..b711944ca8 100644
--- a/servers/audio/audio_filter_sw.h
+++ b/servers/audio/audio_filter_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -65,7 +65,7 @@ public:
void set_filter(AudioFilterSW * p_filter);
void process(float *p_samples,int p_amount, int p_stride=1);
void update_coeffs();
- inline void process_one(float& p_sample);
+ _ALWAYS_INLINE_ void process_one(float& p_sample);
Processor();
};
diff --git a/servers/audio/audio_mixer_sw.cpp b/servers/audio/audio_mixer_sw.cpp
deleted file mode 100644
index 17f8c36c9a..0000000000
--- a/servers/audio/audio_mixer_sw.cpp
+++ /dev/null
@@ -1,1222 +0,0 @@
-/*************************************************************************/
-/* audio_mixer_sw.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 "audio_mixer_sw.h"
-#include "print_string.h"
-#include "os/os.h"
-//TODO implement FAST_AUDIO macro
-
-#ifdef FAST_AUDIO
-#define NO_REVERB
-#endif
-
-template<class Depth,bool is_stereo,bool is_ima_adpcm,bool use_filter,bool use_fx,AudioMixerSW::InterpolationType type,AudioMixerSW::MixChannels mix_mode>
-void AudioMixerSW::do_resample(const Depth* p_src, int32_t *p_dst, ResamplerState *p_state) {
-
- // this function will be compiled branchless by any decent compiler
-
- int32_t final,final_r,next,next_r;
- int32_t *reverb_dst = p_state->reverb_buffer;
- while (p_state->amount--) {
-
- int32_t pos=p_state->pos >> MIX_FRAC_BITS;
- if (is_stereo && !is_ima_adpcm)
- pos<<=1;
-
- if (is_ima_adpcm) {
-
- int sample_pos = pos + p_state->ima_adpcm[0].window_ofs;
-
- while(sample_pos>p_state->ima_adpcm[0].last_nibble) {
-
-
- static const int16_t _ima_adpcm_step_table[89] = {
- 7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
- 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
- 50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
- 130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
- 337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
- 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
- 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
- 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
- 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
- };
-
- static const int8_t _ima_adpcm_index_table[16] = {
- -1, -1, -1, -1, 2, 4, 6, 8,
- -1, -1, -1, -1, 2, 4, 6, 8
- };
-
- for(int i=0;i<(is_stereo?2:1);i++) {
-
-
- int16_t nibble,diff,step;
-
- p_state->ima_adpcm[i].last_nibble++;
- const uint8_t *src_ptr=p_state->ima_adpcm[i].ptr;
-
-
- uint8_t nbb = src_ptr[ (p_state->ima_adpcm[i].last_nibble>>1) * (is_stereo?2:1) + i ];
- nibble = (p_state->ima_adpcm[i].last_nibble&1)?(nbb>>4):(nbb&0xF);
- step=_ima_adpcm_step_table[p_state->ima_adpcm[i].step_index];
-
-
- p_state->ima_adpcm[i].step_index += _ima_adpcm_index_table[nibble];
- if (p_state->ima_adpcm[i].step_index<0)
- p_state->ima_adpcm[i].step_index=0;
- if (p_state->ima_adpcm[i].step_index>88)
- p_state->ima_adpcm[i].step_index=88;
-
- diff = step >> 3 ;
- if (nibble & 1)
- diff += step >> 2 ;
- if (nibble & 2)
- diff += step >> 1 ;
- if (nibble & 4)
- diff += step ;
- if (nibble & 8)
- diff = -diff ;
-
- p_state->ima_adpcm[i].predictor+=diff;
- if (p_state->ima_adpcm[i].predictor<-0x8000)
- p_state->ima_adpcm[i].predictor=-0x8000;
- else if (p_state->ima_adpcm[i].predictor>0x7FFF)
- p_state->ima_adpcm[i].predictor=0x7FFF;
-
-
- /* store loop if there */
- if (p_state->ima_adpcm[i].last_nibble==p_state->ima_adpcm[i].loop_pos) {
-
- p_state->ima_adpcm[i].loop_step_index = p_state->ima_adpcm[i].step_index;
- p_state->ima_adpcm[i].loop_predictor = p_state->ima_adpcm[i].predictor;
- }
-
- //printf("%i - %i - pred %i\n",int(p_state->ima_adpcm[i].last_nibble),int(nibble),int(p_state->ima_adpcm[i].predictor));
-
- }
-
- }
-
- final=p_state->ima_adpcm[0].predictor;
- if (is_stereo) {
- final_r=p_state->ima_adpcm[1].predictor;
- }
-
- } else {
- final=p_src[pos];
- if (is_stereo)
- final_r=p_src[pos+1];
-
- if (sizeof(Depth)==1) { /* conditions will not exist anymore when compiled! */
- final<<=8;
- if (is_stereo)
- final_r<<=8;
- }
-
- if (type==INTERPOLATION_LINEAR) {
-
- if (is_stereo) {
-
- next=p_src[pos+2];
- next_r=p_src[pos+3];
- } else {
- next=p_src[pos+1];
- }
-
- if (sizeof(Depth)==1) {
- next<<=8;
- if (is_stereo)
- next_r<<=8;
- }
-
- int32_t frac=int32_t(p_state->pos&MIX_FRAC_MASK);
-
- final=final+((next-final)*frac >> MIX_FRAC_BITS);
- if (is_stereo)
- final_r=final_r+((next_r-final_r)*frac >> MIX_FRAC_BITS);
- }
- }
-
- if (use_filter) {
-
- Channel::Mix::Filter *f = p_state->filter_l;
- float finalf=final;
- float pre = finalf;
- finalf = ((finalf*p_state->coefs.b0) + (f->hb[0]*p_state->coefs.b1) + (f->hb[1]*p_state->coefs.b2) + (f->ha[0]*p_state->coefs.a1) + (f->ha[1]*p_state->coefs.a2)
- );
-
- f->ha[1]=f->ha[0];
- f->hb[1]=f->hb[0];
- f->hb[0]=pre;
- f->ha[0]=finalf;
-
- final=Math::fast_ftoi(finalf);
-
- if (is_stereo) {
-
- f = p_state->filter_r;
- finalf=final_r;
- pre = finalf;
- finalf = ((finalf*p_state->coefs.b0) + (f->hb[0]*p_state->coefs.b1) + (f->hb[1]*p_state->coefs.b2) + (f->ha[0]*p_state->coefs.a1) + (f->ha[1]*p_state->coefs.a2)
- );
- f->ha[1]=f->ha[0];
- f->hb[1]=f->hb[0];
- f->hb[0]=pre;
- f->ha[0]=finalf;
-
- final_r=Math::fast_ftoi(finalf);
-
- }
-
- p_state->coefs.b0+=p_state->coefs_inc.b0;
- p_state->coefs.b1+=p_state->coefs_inc.b1;
- p_state->coefs.b2+=p_state->coefs_inc.b2;
- p_state->coefs.a1+=p_state->coefs_inc.a1;
- p_state->coefs.a2+=p_state->coefs_inc.a2;
- }
-
- if (!is_stereo) {
- final_r=final; //copy to right channel if stereo
- }
-
- //convert back to 24 bits and mix to buffers
-
- if (mix_mode==MIX_STEREO) {
- *p_dst++ +=(final*(p_state->vol[0]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24;
- *p_dst++ +=(final_r*(p_state->vol[1]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24;
-
- p_state->vol[0]+=p_state->vol_inc[0];
- p_state->vol[1]+=p_state->vol_inc[1];
-
- if (use_fx) {
- *reverb_dst++ +=(final*(p_state->reverb_vol[0]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24;
- *reverb_dst++ +=(final_r*(p_state->reverb_vol[1]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24;
- p_state->reverb_vol[0]+=p_state->reverb_vol_inc[0];
- p_state->reverb_vol[1]+=p_state->reverb_vol_inc[1];
- }
-
-
- } else if (mix_mode==MIX_QUAD) {
-
- *p_dst++ +=(final*(p_state->vol[0]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24;
- *p_dst++ +=(final_r*(p_state->vol[1]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24;
-
- *p_dst++ +=(final*(p_state->vol[2]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24;
- *p_dst++ +=(final_r*(p_state->vol[3]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24;
-
- p_state->vol[0]+=p_state->vol_inc[0];
- p_state->vol[1]+=p_state->vol_inc[1];
- p_state->vol[2]+=p_state->vol_inc[2];
- p_state->vol[3]+=p_state->vol_inc[3];
-
- if (use_fx) {
- *reverb_dst++ +=(final*(p_state->reverb_vol[0]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24;
- *reverb_dst++ +=(final_r*(p_state->reverb_vol[1]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24;
- *reverb_dst++ +=(final*(p_state->reverb_vol[2]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24;
- *reverb_dst++ +=(final_r*(p_state->reverb_vol[3]>>MIX_VOLRAMP_FRAC_BITS))>>MIX_VOL_MOVE_TO_24;
- p_state->reverb_vol[0]+=p_state->reverb_vol_inc[0];
- p_state->reverb_vol[1]+=p_state->reverb_vol_inc[1];
- p_state->reverb_vol[2]+=p_state->reverb_vol_inc[2];
- p_state->reverb_vol[3]+=p_state->reverb_vol_inc[3];
- }
- }
-
- p_state->pos+=p_state->increment;
- }
-}
-
-
-void AudioMixerSW::mix_channel(Channel& c) {
-
-
- if (!sample_manager->is_sample(c.sample)) {
- // sample is gone!
- c.active=false;
- return;
- }
-
-
- /* some 64-bit fixed point precaches */
-
- int64_t loop_begin_fp=((int64_t)sample_manager->sample_get_loop_begin(c.sample) << MIX_FRAC_BITS);
- int64_t loop_end_fp=((int64_t)sample_manager->sample_get_loop_end(c.sample) << MIX_FRAC_BITS);
- int64_t length_fp=((int64_t)sample_manager->sample_get_length(c.sample) << MIX_FRAC_BITS);
- int64_t begin_limit=(sample_manager->sample_get_loop_format(c.sample)!=AS::SAMPLE_LOOP_NONE)?loop_begin_fp:0;
- int64_t end_limit=(sample_manager->sample_get_loop_format(c.sample)!=AS::SAMPLE_LOOP_NONE)?loop_end_fp:length_fp;
- bool is_stereo=sample_manager->sample_is_stereo(c.sample);
-
- int32_t todo=mix_chunk_size;
-// int mixed=0;
- bool use_filter=false;
-
- ResamplerState rstate;
-
- /* compute voume ramps, increment, etc */
-
-
-
- for(int i=0;i<mix_channels;i++) {
- c.mix.old_vol[i]=c.mix.vol[i];
- c.mix.old_reverb_vol[i]=c.mix.reverb_vol[i];
- c.mix.old_chorus_vol[i]=c.mix.chorus_vol[i];
- }
-
- float vol = c.vol*channel_nrg;
-
- float reverb_vol = c.reverb_send*channel_nrg;
- float chorus_vol = c.chorus_send*channel_nrg;
-
- if (mix_channels==2) {
- //stereo pan
- float pan = c.pan * 0.5 + 0.5;
- float panv[2]={
- (1.0 - pan)*(1<<MIX_VOL_FRAC_BITS),
- (pan)*(1<<MIX_VOL_FRAC_BITS)
- };
-
- for(int i=0;i<2;i++) {
-
- c.mix.vol[i]=Math::fast_ftoi(vol*panv[i]);
- c.mix.reverb_vol[i]=Math::fast_ftoi(reverb_vol*panv[i]);
- c.mix.chorus_vol[i]=Math::fast_ftoi(chorus_vol*panv[i]);
- }
-
- } else {
- //qudra pan
- float panx = c.pan * 0.5 + 0.5;
- float pany = c.depth * 0.5 + 0.5;
- // with this model every speaker plays at 0.25 energy at the center.. i'm not sure if it's correct but it seems to be balanced
- float panv[4]={
- (1.0-pany)*(1.0-panx)*(1<<MIX_VOL_FRAC_BITS),
- (1.0-pany)*( panx)*(1<<MIX_VOL_FRAC_BITS),
- ( pany)*(1.0-panx)*(1<<MIX_VOL_FRAC_BITS),
- ( pany)*( panx)*(1<<MIX_VOL_FRAC_BITS)
- };
-
- for(int i=0;i<4;i++) {
-
- c.mix.vol[i]=Math::fast_ftoi(vol*panv[i]);
- c.mix.reverb_vol[i]=Math::fast_ftoi(reverb_vol*panv[i]);
- c.mix.chorus_vol[i]=Math::fast_ftoi(chorus_vol*panv[i]);
- }
-
- }
-
- if (c.first_mix) { // avoid ramp up
-
- for(int i=0;i<mix_channels;i++) {
- c.mix.old_vol[i]=c.mix.vol[i];
- c.mix.old_reverb_vol[i]=c.mix.reverb_vol[i];
- c.mix.old_chorus_vol[i]=c.mix.chorus_vol[i];
- }
-
- c.first_mix=false;
- }
-
-
-
- Channel::Filter::Coefs filter_coefs;
- Channel::Filter::Coefs filter_inc;
-
- if (c.filter.type!=AudioMixer::FILTER_NONE) {
-
- filter_coefs=c.filter.old_coefs;
- filter_inc.b0=(c.filter.coefs.b0-filter_coefs.b0)/(1<<mix_chunk_bits);
- filter_inc.b1=(c.filter.coefs.b1-filter_coefs.b1)/(1<<mix_chunk_bits);
- filter_inc.b2=(c.filter.coefs.b2-filter_coefs.b2)/(1<<mix_chunk_bits);
- filter_inc.a1=(c.filter.coefs.a1-filter_coefs.a1)/(1<<mix_chunk_bits);
- filter_inc.a2=(c.filter.coefs.a2-filter_coefs.a2)/(1<<mix_chunk_bits);
- use_filter=true;
- }
-
- if (c.mix.increment>0)
- c.mix.increment=((int64_t)c.speed<<MIX_FRAC_BITS)/mix_rate;
- else
- c.mix.increment=-((int64_t)c.speed<<MIX_FRAC_BITS)/mix_rate;
-
- //volume ramp
-
-
- for(int i=0;i<mix_channels;i++) {
- rstate.vol_inc[i]=((c.mix.vol[i]-c.mix.old_vol[i])<<MIX_VOLRAMP_FRAC_BITS)>>mix_chunk_bits;
- rstate.vol[i]=c.mix.old_vol[i]<<MIX_VOLRAMP_FRAC_BITS;
- rstate.reverb_vol_inc[i]=((c.mix.reverb_vol[i]-c.mix.old_reverb_vol[i])<<MIX_VOLRAMP_FRAC_BITS)>>mix_chunk_bits;
- rstate.reverb_vol[i]=c.mix.old_reverb_vol[i]<<MIX_VOLRAMP_FRAC_BITS;
- rstate.chorus_vol_inc[i]=((c.mix.chorus_vol[i]-c.mix.old_chorus_vol[i])<<MIX_VOLRAMP_FRAC_BITS)>>mix_chunk_bits;
- rstate.chorus_vol[i]=c.mix.old_chorus_vol[i]<<MIX_VOLRAMP_FRAC_BITS;
- }
-
-
- //looping
-
- AS::SampleLoopFormat loop_format=sample_manager->sample_get_loop_format(c.sample);
- AS::SampleFormat format=sample_manager->sample_get_format(c.sample);
-
- bool use_fx=false;
-
- if (fx_enabled) {
-
- for(int i=0;i<mix_channels;i++) {
- if (c.mix.old_reverb_vol[i] || c.mix.reverb_vol[i] || c.mix.old_chorus_vol[i] || c.mix.chorus_vol[i] ) {
- use_fx=true;
- break;
- }
- }
- }
-
- /* audio data */
-
- const void *data=sample_manager->sample_get_data_ptr(c.sample);
- int32_t *dst_buff=mix_buffer;
-
-#ifndef NO_REVERB
- rstate.reverb_buffer=reverb_state[c.reverb_room].buffer;
-#endif
-
- /* @TODO validar loops al registrar? */
-
- rstate.coefs=filter_coefs;
- rstate.coefs_inc=filter_inc;
- rstate.filter_l=&c.mix.filter_l;
- rstate.filter_r=&c.mix.filter_r;
-
- if (format==AS::SAMPLE_FORMAT_IMA_ADPCM) {
-
- rstate.ima_adpcm=c.mix.ima_adpcm;
- if (loop_format!=AS::SAMPLE_LOOP_NONE) {
- c.mix.ima_adpcm[0].loop_pos=loop_begin_fp>>MIX_FRAC_BITS;
- c.mix.ima_adpcm[1].loop_pos=loop_begin_fp>>MIX_FRAC_BITS;
- loop_format=AS::SAMPLE_LOOP_FORWARD;
- }
- }
-
- while (todo>0) {
-
- int64_t limit=0;
- int32_t target=0,aux=0;
-
- /** LOOP CHECKING **/
-
- if ( c.mix.increment < 0 ) {
- /* going backwards */
-
- if ( loop_format!=AS::SAMPLE_LOOP_NONE && c.mix.offset < loop_begin_fp ) {
- /* loopstart reached */
- if ( loop_format==AS::SAMPLE_LOOP_PING_PONG ) {
- /* bounce ping pong */
- c.mix.offset= loop_begin_fp + ( loop_begin_fp-c.mix.offset );
- c.mix.increment=-c.mix.increment;
- } else {
- /* go to loop-end */
- c.mix.offset=loop_end_fp-(loop_begin_fp-c.mix.offset);
- }
- } else {
- /* check for sample not reaching begining */
- if(c.mix.offset < 0) {
-
- c.active=false;
- break;
- }
- }
- } else {
- /* going forward */
- if( loop_format!=AS::SAMPLE_LOOP_NONE && c.mix.offset >= loop_end_fp ) {
- /* loopend reached */
-
- if ( loop_format==AS::SAMPLE_LOOP_PING_PONG ) {
- /* bounce ping pong */
- c.mix.offset=loop_end_fp-(c.mix.offset-loop_end_fp);
- c.mix.increment=-c.mix.increment;
- } else {
- /* go to loop-begin */
-
- if (format==AS::SAMPLE_FORMAT_IMA_ADPCM) {
- for(int i=0;i<2;i++) {
- c.mix.ima_adpcm[i].step_index=c.mix.ima_adpcm[i].loop_step_index;
- c.mix.ima_adpcm[i].predictor=c.mix.ima_adpcm[i].loop_predictor;
- c.mix.ima_adpcm[i].last_nibble=loop_begin_fp>>MIX_FRAC_BITS;
- }
- c.mix.offset=loop_begin_fp;
- } else {
- c.mix.offset=loop_begin_fp+(c.mix.offset-loop_end_fp);
- }
-
- }
- } else {
- /* no loop, check for end of sample */
- if(c.mix.offset >= length_fp) {
-
- c.active=false;
- break;
- }
- }
- }
-
- /** MIXCOUNT COMPUTING **/
-
- /* next possible limit (looppoints or sample begin/end */
- limit=(c.mix.increment < 0) ?begin_limit:end_limit;
-
- /* compute what is shorter, the todo or the limit? */
- aux=(limit-c.mix.offset)/c.mix.increment+1;
- target=(aux<todo)?aux:todo; /* mix target is the shorter buffer */
-
- /* check just in case */
- if ( target<=0 ) {
- c.active=false;
- break;
- }
-
- todo-=target;
-
- int32_t offset=c.mix.offset&mix_chunk_mask; /* strip integer */
- c.mix.offset-=offset;
-
- rstate.increment=c.mix.increment;
- rstate.amount=target;
- rstate.pos=offset;
-
-/* Macros to call the resample function for all possibilities, creating a dedicated-non branchy function call for each thanks to template magic*/
-
-#define CALL_RESAMPLE_FUNC( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\
- do_resample<m_depth,m_stereo,m_ima_adpcm, m_use_filter,m_use_fx,m_interp, m_mode>(\
- src_ptr,\
- dst_buff,&rstate);
-
-
-#define CALL_RESAMPLE_INTERP( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\
- if(m_interp==INTERPOLATION_RAW) {\
- CALL_RESAMPLE_FUNC(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,INTERPOLATION_RAW,m_mode);\
- } else if(m_interp==INTERPOLATION_LINEAR) {\
- CALL_RESAMPLE_FUNC(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,INTERPOLATION_LINEAR,m_mode);\
- } else if(m_interp==INTERPOLATION_CUBIC) {\
- CALL_RESAMPLE_FUNC(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,INTERPOLATION_CUBIC,m_mode);\
- }\
-
-#define CALL_RESAMPLE_FX( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\
- if(m_use_fx) {\
- CALL_RESAMPLE_INTERP(m_depth,m_stereo, m_ima_adpcm,m_use_filter,true,m_interp, m_mode);\
- } else {\
- CALL_RESAMPLE_INTERP(m_depth,m_stereo, m_ima_adpcm,m_use_filter,false,m_interp, m_mode);\
- }\
-
-
-#define CALL_RESAMPLE_FILTER( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\
- if(m_use_filter) {\
- CALL_RESAMPLE_FX(m_depth,m_stereo, m_ima_adpcm,true,m_use_fx,m_interp, m_mode);\
- } else {\
- CALL_RESAMPLE_FX(m_depth,m_stereo, m_ima_adpcm,false,m_use_fx,m_interp, m_mode);\
- }\
-
-#define CALL_RESAMPLE_STEREO( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\
- if(m_stereo) {\
- CALL_RESAMPLE_FILTER(m_depth,true,m_ima_adpcm, m_use_filter,m_use_fx,m_interp, m_mode);\
- } else {\
- CALL_RESAMPLE_FILTER(m_depth,false,m_ima_adpcm,m_use_filter,m_use_fx,m_interp, m_mode);\
- }\
-
-#define CALL_RESAMPLE_MODE( m_depth, m_stereo, m_ima_adpcm, m_use_filter, m_use_fx, m_interp, m_mode)\
- if(m_mode==MIX_STEREO) {\
- CALL_RESAMPLE_STEREO(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,m_interp, MIX_STEREO);\
- } else {\
- CALL_RESAMPLE_STEREO(m_depth,m_stereo, m_ima_adpcm,m_use_filter,m_use_fx,m_interp, MIX_QUAD);\
- }\
-
-
-
-
- if (format==AS::SAMPLE_FORMAT_PCM8) {
-
- int8_t *src_ptr = &((int8_t*)data)[(c.mix.offset >> MIX_FRAC_BITS)<<(is_stereo?1:0) ];
- CALL_RESAMPLE_MODE(int8_t,is_stereo,false,use_filter,use_fx,interpolation_type,mix_channels);
-
- } else if (format==AS::SAMPLE_FORMAT_PCM16) {
- int16_t *src_ptr = &((int16_t*)data)[(c.mix.offset >> MIX_FRAC_BITS)<<(is_stereo?1:0) ];
- CALL_RESAMPLE_MODE(int16_t,is_stereo,false,use_filter,use_fx,interpolation_type,mix_channels);
-
- } else if (format==AS::SAMPLE_FORMAT_IMA_ADPCM) {
- for(int i=0;i<2;i++) {
- c.mix.ima_adpcm[i].window_ofs=c.mix.offset>>MIX_FRAC_BITS;
- c.mix.ima_adpcm[i].ptr=(const uint8_t*)data;
- }
- int8_t *src_ptr = NULL;
- CALL_RESAMPLE_MODE(int8_t,is_stereo,true,use_filter,use_fx,interpolation_type,mix_channels);
-
- }
-
- c.mix.offset+=rstate.pos;
- dst_buff+=target*mix_channels;
- rstate.reverb_buffer+=target*mix_channels;
- }
-
- c.filter.old_coefs=c.filter.coefs;
-}
-
-void AudioMixerSW::mix_chunk() {
-
- ERR_FAIL_COND(mix_chunk_left);
-
- inside_mix=true;
-
- // emit tick in usecs
- for (int i=0;i<mix_chunk_size*mix_channels;i++) {
-
- mix_buffer[i]=0;
- }
-#ifndef NO_REVERB
- for(int i=0;i<max_reverbs;i++)
- reverb_state[i].used_in_chunk=false;
-#endif
-
-
- audio_mixer_chunk_call(mix_chunk_size);
-
- int ac=0;
- for (int i=0;i<MAX_CHANNELS;i++) {
-
- if (!channels[i].active)
- continue;
- ac++;
-
- /* process volume */
- Channel&c=channels[i];
-#ifndef NO_REVERB
- bool has_reverb = c.reverb_send>CMP_EPSILON && fx_enabled;
- if (has_reverb || c.had_prev_reverb) {
-
- if (!reverb_state[c.reverb_room].used_in_chunk) {
- //zero the room
- int32_t *buff = reverb_state[c.reverb_room].buffer;
- int len = mix_chunk_size*mix_channels;
- for (int j=0;j<len;j++) {
-
- buff[j]=0; // buffer in use, clear it for appending
- }
- reverb_state[c.reverb_room].used_in_chunk=true;
- }
- }
-#else
- bool has_reverb = false;
-#endif
- bool has_chorus = c.chorus_send>CMP_EPSILON && fx_enabled;
-
-
- mix_channel(c);
-
- c.had_prev_reverb=has_reverb;
- c.had_prev_chorus=has_chorus;
-
- }
-
- //process reverb
-#ifndef NO_REVERB
- if (fx_enabled) {
-
-
- for(int i=0;i<max_reverbs;i++) {
-
- if (!reverb_state[i].enabled && !reverb_state[i].used_in_chunk)
- continue; //this reverb is not in use
-
- int32_t *src=NULL;
-
- if (reverb_state[i].used_in_chunk)
- src=reverb_state[i].buffer;
- else
- src=zero_buffer;
-
- bool in_use=false;
-
- int passes=mix_channels/2;
-
- for(int j=0;j<passes;j++) {
-
- if (reverb_state[i].reverb[j].process((int*)&src[j*2],(int*)&mix_buffer[j*2],mix_chunk_size,passes))
- in_use=true;
- }
-
- if (in_use) {
- reverb_state[i].enabled=true;
- reverb_state[i].frames_idle=0;
- //copy data over
-
- } else {
- reverb_state[i].frames_idle+=mix_chunk_size;
- if (false) { // go idle because too many frames passed
- //disable this reverb, as nothing important happened on it
- reverb_state[i].enabled=false;
- reverb_state[i].frames_idle=0;
- }
- }
-
- }
- }
-#endif
- mix_chunk_left=mix_chunk_size;
- inside_mix=false;
-}
-
-int AudioMixerSW::mix(int32_t *p_buffer,int p_frames) {
-
- int todo=p_frames;
- int mixes=0;
-
- while(todo) {
-
-
- if (!mix_chunk_left) {
-
- if (step_callback)
- step_callback(step_udata);
- mix_chunk();
- mixes++;
- }
-
- int to_mix=MIN(mix_chunk_left,todo);
- int from=mix_chunk_size-mix_chunk_left;
-
- for (int i=0;i<to_mix*2;i++) {
-
- (*p_buffer++)=mix_buffer[from*2+i];
- }
-
- mix_chunk_left-=to_mix;
- todo-=to_mix;
- }
-
- return mixes;
-}
-
-uint64_t AudioMixerSW::get_step_usecs() const {
-
- double mct = (1<<mix_chunk_bits)/double(mix_rate);
- return mct*1000000.0;
-}
-
-int AudioMixerSW::_get_channel(ChannelID p_channel) const {
-
- if (p_channel<0) {
- return -1;
- }
-
- int idx=p_channel%MAX_CHANNELS;
- int check=p_channel/MAX_CHANNELS;
- ERR_FAIL_INDEX_V(idx,MAX_CHANNELS,-1);
- if (channels[idx].check!=check) {
- return -1;
- }
- if (!channels[idx].active) {
- return -1;
- }
-
- return idx;
-}
-
-AudioMixer::ChannelID AudioMixerSW::channel_alloc(RID p_sample) {
-
- ERR_FAIL_COND_V( !sample_manager->is_sample(p_sample), INVALID_CHANNEL );
-
-
- int index=-1;
- for (int i=0;i<MAX_CHANNELS;i++) {
-
- if (!channels[i].active) {
- index=i;
- break;
- }
- }
-
- if (index==-1)
- return INVALID_CHANNEL;
-
- Channel &c=channels[index];
-
- // init variables
- c.sample=p_sample;
- c.vol=1;
- c.pan=0;
- c.depth=0;
- c.height=0;
- c.chorus_send=0;
- c.reverb_send=0;
- c.reverb_room=REVERB_HALL;
- c.positional=false;
- c.filter.type=FILTER_NONE;
- c.speed=sample_manager->sample_get_mix_rate(p_sample);
- c.active=true;
- c.check=channel_id_count++;
- c.first_mix=true;
-
- // init mix variables
-
- c.mix.offset=0;
- c.mix.increment=1;
- //zero everything when this errors
- for(int i=0;i<4;i++) {
- c.mix.vol[i]=0;
- c.mix.reverb_vol[i]=0;
- c.mix.chorus_vol[i]=0;
-
- c.mix.old_vol[i]=0;
- c.mix.old_reverb_vol[i]=0;
- c.mix.old_chorus_vol[i]=0;
- }
-
- c.had_prev_chorus=false;
- c.had_prev_reverb=false;
- c.had_prev_vol=false;
-
-
- if (sample_manager->sample_get_format(c.sample)==AudioServer::SAMPLE_FORMAT_IMA_ADPCM) {
-
- for(int i=0;i<2;i++) {
- c.mix.ima_adpcm[i].step_index=0;
- c.mix.ima_adpcm[i].predictor=0;
- c.mix.ima_adpcm[i].loop_step_index=0;
- c.mix.ima_adpcm[i].loop_predictor=0;
- c.mix.ima_adpcm[i].last_nibble=-1;
- c.mix.ima_adpcm[i].loop_pos=0x7FFFFFFF;
- c.mix.ima_adpcm[i].window_ofs=0;
- c.mix.ima_adpcm[i].ptr=NULL;
- }
- }
-
- ChannelID ret_id = index+c.check*MAX_CHANNELS;
-
- return ret_id;
-
-}
-
-void AudioMixerSW::channel_set_volume(ChannelID p_channel, float p_gain) {
-
- if (p_gain>3) // avoid gain going too high
- p_gain=3;
- if (p_gain<0)
- p_gain=0;
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return;
- Channel &c = channels[chan];
-
- //Math::exp( p_db * 0.11512925464970228420089957273422 );
- c.vol=p_gain;
-
-}
-
-void AudioMixerSW::channel_set_pan(ChannelID p_channel, float p_pan, float p_depth,float p_height) {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return;
- Channel &c = channels[chan];
-
- c.pan=p_pan;
- c.depth=p_depth;
- c.height=p_height;
-
-}
-void AudioMixerSW::channel_set_filter(ChannelID p_channel, FilterType p_type, float p_cutoff, float p_resonance, float p_gain) {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return;
-
- Channel &c = channels[chan];
-
- if (c.filter.type==p_type && c.filter.cutoff==p_cutoff && c.filter.resonance==p_resonance && c.filter.gain==p_gain)
- return; //bye
-
-
- bool type_changed = p_type!=c.filter.type;
-
- c.filter.type=p_type;
- c.filter.cutoff=p_cutoff;
- c.filter.resonance=p_resonance;
- c.filter.gain=p_gain;
-
-
- AudioFilterSW filter;
- switch(p_type) {
- case FILTER_NONE: {
-
- return; //do nothing else
- } break;
- case FILTER_LOWPASS: {
- filter.set_mode(AudioFilterSW::LOWPASS);
- } break;
- case FILTER_BANDPASS: {
- filter.set_mode(AudioFilterSW::BANDPASS);
- } break;
- case FILTER_HIPASS: {
- filter.set_mode(AudioFilterSW::HIGHPASS);
- } break;
- case FILTER_NOTCH: {
- filter.set_mode(AudioFilterSW::NOTCH);
- } break;
- case FILTER_PEAK: {
- filter.set_mode(AudioFilterSW::PEAK);
- } break;
- case FILTER_BANDLIMIT: {
- filter.set_mode(AudioFilterSW::BANDLIMIT);
- } break;
- case FILTER_LOW_SHELF: {
- filter.set_mode(AudioFilterSW::LOWSHELF);
- } break;
- case FILTER_HIGH_SHELF: {
- filter.set_mode(AudioFilterSW::HIGHSHELF);
- } break;
- }
-
- filter.set_cutoff(p_cutoff);
- filter.set_resonance(p_resonance);
- filter.set_gain(p_gain);
- filter.set_sampling_rate(mix_rate);
- filter.set_stages(1);
-
- AudioFilterSW::Coeffs coefs;
- filter.prepare_coefficients(&coefs);
-
- if (!type_changed)
- c.filter.old_coefs=c.filter.coefs;
-
- c.filter.coefs.b0=coefs.b0;
- c.filter.coefs.b1=coefs.b1;
- c.filter.coefs.b2=coefs.b2;
- c.filter.coefs.a1=coefs.a1;
- c.filter.coefs.a2=coefs.a2;
-
-
- if (type_changed) {
- //type changed reset filter
- c.filter.old_coefs=c.filter.coefs;
- c.mix.filter_l.ha[0]=0;
- c.mix.filter_l.ha[1]=0;
- c.mix.filter_l.hb[0]=0;
- c.mix.filter_l.hb[1]=0;
- c.mix.filter_r.ha[0]=0;
- c.mix.filter_r.ha[1]=0;
- c.mix.filter_r.hb[0]=0;
- c.mix.filter_r.hb[1]=0;
- }
-
-
-}
-void AudioMixerSW::channel_set_chorus(ChannelID p_channel, float p_chorus ) {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return;
-
- Channel &c = channels[chan];
- c.chorus_send=p_chorus;
-
-}
-void AudioMixerSW::channel_set_reverb(ChannelID p_channel, ReverbRoomType p_room_type, float p_reverb) {
-
- ERR_FAIL_INDEX(p_room_type,MAX_REVERBS);
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return;
-
- Channel &c = channels[chan];
- c.reverb_room=p_room_type;
- c.reverb_send=p_reverb;
-
-}
-
-void AudioMixerSW::channel_set_mix_rate(ChannelID p_channel, int p_mix_rate) {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return;
-
- Channel &c = channels[chan];
- c.speed=p_mix_rate;
-
-}
-void AudioMixerSW::channel_set_positional(ChannelID p_channel, bool p_positional) {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return;
-
- Channel &c = channels[chan];
- c.positional=p_positional;
-}
-
-float AudioMixerSW::channel_get_volume(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return 0;
-
- const Channel &c = channels[chan];
- //Math::log( c.vol ) * 8.6858896380650365530225783783321;
- return c.vol;
-}
-
-float AudioMixerSW::channel_get_pan(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return 0;
-
- const Channel &c = channels[chan];
- return c.pan;
-}
-float AudioMixerSW::channel_get_pan_depth(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return 0;
-
- const Channel &c = channels[chan];
- return c.depth;
-}
-float AudioMixerSW::channel_get_pan_height(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return 0;
-
- const Channel &c = channels[chan];
- return c.height;
-
-}
-AudioMixer::FilterType AudioMixerSW::channel_get_filter_type(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return FILTER_NONE;
-
- const Channel &c = channels[chan];
- return c.filter.type;
-}
-float AudioMixerSW::channel_get_filter_cutoff(ChannelID p_channel) const {
-
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return 0;
-
- const Channel &c = channels[chan];
- return c.filter.cutoff;
-
-}
-float AudioMixerSW::channel_get_filter_resonance(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return 0;
-
- const Channel &c = channels[chan];
- return c.filter.resonance;
-
-}
-
-float AudioMixerSW::channel_get_filter_gain(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return 0;
-
- const Channel &c = channels[chan];
- return c.filter.gain;
-}
-
-
-float AudioMixerSW::channel_get_chorus(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return 0;
-
- const Channel &c = channels[chan];
- return c.chorus_send;
-
-}
-AudioMixer::ReverbRoomType AudioMixerSW::channel_get_reverb_type(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return REVERB_HALL;
-
- const Channel &c = channels[chan];
- return c.reverb_room;
-
-}
-float AudioMixerSW::channel_get_reverb(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return 0;
-
- const Channel &c = channels[chan];
- return c.reverb_send;
-}
-
-int AudioMixerSW::channel_get_mix_rate(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return 0;
-
- const Channel &c = channels[chan];
- return c.speed;
-}
-bool AudioMixerSW::channel_is_positional(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return false;
-
- const Channel &c = channels[chan];
- return c.positional;
-}
-
-bool AudioMixerSW::channel_is_valid(ChannelID p_channel) const {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return false;
- return channels[chan].active;
-}
-
-
-void AudioMixerSW::channel_free(ChannelID p_channel) {
-
- int chan = _get_channel(p_channel);
- if (chan<0 || chan >=MAX_CHANNELS)
- return;
-
- Channel &c=channels[chan];
-
- if (!c.active)
- return;
-
- bool has_vol=false;
-
- for(int i=0;i<mix_channels;i++) {
-
- if (c.mix.vol[i])
- has_vol=true;
- if (c.mix.reverb_vol[i])
- has_vol=true;
- if (c.mix.chorus_vol[i])
- has_vol=true;
- }
- if (c.active && has_vol && inside_mix) {
- // drive voice to zero, and run a chunk, the VRAMP will fade it good
- c.vol=0;
- c.reverb_send=0;
- c.chorus_send=0;
- mix_channel(c);
- }
- /* @TODO RAMP DOWN ON STOP */
- c.active=false;
-}
-
-
-
-AudioMixerSW::AudioMixerSW(SampleManagerSW *p_sample_manager,int p_desired_latency_ms,int p_mix_rate,MixChannels p_mix_channels,bool p_use_fx,InterpolationType p_interp,MixStepCallback p_step_callback,void *p_step_udata) {
-
- if (OS::get_singleton()->is_stdout_verbose()) {
- print_line("AudioServerSW Params: ");
- print_line(" -mix chans: "+itos(p_mix_channels));
- print_line(" -mix rate: "+itos(p_mix_rate));
- print_line(" -latency: "+itos(p_desired_latency_ms));
- print_line(" -fx: "+itos(p_use_fx));
- print_line(" -interp: "+itos(p_interp));
- }
- sample_manager=p_sample_manager;
- mix_channels=p_mix_channels;
- mix_rate=p_mix_rate;
- step_callback=p_step_callback;
- step_udata=p_step_udata;
-
-
- mix_chunk_bits=nearest_shift( p_desired_latency_ms * p_mix_rate / 1000 );
-
- mix_chunk_size=(1<<mix_chunk_bits);
- mix_chunk_mask=mix_chunk_size-1;
- mix_buffer = memnew_arr(int32_t,mix_chunk_size*mix_channels);
-#ifndef NO_REVERB
- zero_buffer = memnew_arr(int32_t,mix_chunk_size*mix_channels);
- for(int i=0;i<mix_chunk_size*mix_channels;i++)
- zero_buffer[i]=0; //zero buffer is zero...
-
- max_reverbs=MAX_REVERBS;
- int reverberators=mix_channels/2;
-
- reverb_state = memnew_arr(ReverbState,max_reverbs);
- for(int i=0;i<max_reverbs;i++) {
- reverb_state[i].enabled=false;
- reverb_state[i].reverb = memnew_arr(ReverbSW,reverberators);
- reverb_state[i].buffer = memnew_arr(int32_t,mix_chunk_size*mix_channels);
- reverb_state[i].frames_idle=0;
- for(int j=0;j<reverberators;j++) {
- static ReverbSW::ReverbMode modes[MAX_REVERBS]={ReverbSW::REVERB_MODE_STUDIO_SMALL,ReverbSW::REVERB_MODE_STUDIO_MEDIUM,ReverbSW::REVERB_MODE_STUDIO_LARGE,ReverbSW::REVERB_MODE_HALL};
- reverb_state[i].reverb[j].set_mix_rate(p_mix_rate);
- reverb_state[i].reverb[j].set_mode(modes[i]);
- }
-
- }
- fx_enabled=p_use_fx;
-#else
- fx_enabled=false;
-#endif
- mix_chunk_left=0;
-
- interpolation_type=p_interp;
- channel_id_count=1;
- inside_mix=false;
- channel_nrg=1.0;
-
-}
-
-void AudioMixerSW::set_mixer_volume(float p_volume) {
-
- channel_nrg=p_volume;
-}
-
-AudioMixerSW::~AudioMixerSW() {
-
- memdelete_arr(mix_buffer);
-
-#ifndef NO_REVERB
- memdelete_arr(zero_buffer);
- for(int i=0;i<max_reverbs;i++) {
- memdelete_arr(reverb_state[i].reverb);
- memdelete_arr(reverb_state[i].buffer);
- }
- memdelete_arr(reverb_state);
-#endif
-
-
-}
diff --git a/servers/audio/audio_mixer_sw.h b/servers/audio/audio_mixer_sw.h
deleted file mode 100644
index e924b518cc..0000000000
--- a/servers/audio/audio_mixer_sw.h
+++ /dev/null
@@ -1,264 +0,0 @@
-/*************************************************************************/
-/* audio_mixer_sw.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 AUDIO_MIXER_SW_H
-#define AUDIO_MIXER_SW_H
-
-#include "servers/audio_server.h"
-#include "servers/audio/sample_manager_sw.h"
-#include "servers/audio/audio_filter_sw.h"
-#include "servers/audio/reverb_sw.h"
-
-class AudioMixerSW : public AudioMixer {
-public:
-
- enum InterpolationType {
-
- INTERPOLATION_RAW,
- INTERPOLATION_LINEAR,
- INTERPOLATION_CUBIC
- };
-
- enum MixChannels {
-
- MIX_STEREO=2,
- MIX_QUAD=4
- };
-
- typedef void (*MixStepCallback)(void*);
-
-private:
- SampleManagerSW *sample_manager;
-
- enum {
-
- MAX_CHANNELS=64,
- // fixed point defs
-
- MIX_FRAC_BITS=13,
- MIX_FRAC_LEN=(1<<MIX_FRAC_BITS),
- MIX_FRAC_MASK=MIX_FRAC_LEN-1,
- MIX_VOL_FRAC_BITS=12,
- MIX_VOLRAMP_FRAC_BITS=16,
- MIX_VOLRAMP_FRAC_LEN=(1<<MIX_VOLRAMP_FRAC_BITS),
- MIX_VOLRAMP_FRAC_MASK=MIX_VOLRAMP_FRAC_LEN-1,
- MIX_FILTER_FRAC_BITS=16,
- MIX_FILTER_RAMP_FRAC_BITS=8,
- MIX_VOL_MOVE_TO_24=4
- };
-
-
- struct Channel {
-
- RID sample;
- struct Mix {
- int64_t offset;
- int32_t increment;
-
- int32_t vol[4];
- int32_t reverb_vol[4];
- int32_t chorus_vol[4];
-
- int32_t old_vol[4];
- int32_t old_reverb_vol[4];
- int32_t old_chorus_vol[4];
-
-
- struct Filter { //history (stereo)
- float ha[2],hb[2];
- } filter_l,filter_r;
-
- struct IMA_ADPCM_State {
-
- int16_t step_index;
- int32_t predictor;
- /* values at loop point */
- int16_t loop_step_index;
- int32_t loop_predictor;
- int32_t last_nibble;
- int32_t loop_pos;
- int32_t window_ofs;
- const uint8_t *ptr;
- } ima_adpcm[2];
-
- } mix;
-
- float vol;
- float pan;
- float depth;
- float height;
-
- float chorus_send;
- ReverbRoomType reverb_room;
- float reverb_send;
- int speed;
- int check;
- bool positional;
-
- bool had_prev_reverb;
- bool had_prev_chorus;
- bool had_prev_vol;
-
- struct Filter {
-
- bool dirty;
-
- FilterType type;
- float cutoff;
- float resonance;
- float gain;
-
- struct Coefs {
-
- float a1,a2,b0,b1,b2; // fixed point coefficients
- } coefs,old_coefs;
-
- } filter;
-
- bool first_mix;
- bool active;
- Channel() { active=false; check=-1; first_mix=false; filter.dirty=true; filter.type=FILTER_NONE; filter.cutoff=8000; filter.resonance=0; filter.gain=0; }
- };
-
- Channel channels[MAX_CHANNELS];
-
- uint32_t mix_rate;
- bool fx_enabled;
- InterpolationType interpolation_type;
-
- int mix_chunk_bits;
- int mix_chunk_size;
- int mix_chunk_mask;
-
- int32_t *mix_buffer;
- int32_t *zero_buffer; // fx feed when no input was mixed
-
- struct ResamplerState {
-
- uint32_t amount;
- int32_t increment;
-
-
- int32_t pos;
-
-
- int32_t vol[4];
- int32_t reverb_vol[4];
- int32_t chorus_vol[4];
-
- int32_t vol_inc[4];
- int32_t reverb_vol_inc[4];
- int32_t chorus_vol_inc[4];
-
-
-
- Channel::Mix::Filter *filter_l;
- Channel::Mix::Filter *filter_r;
- Channel::Filter::Coefs coefs;
- Channel::Filter::Coefs coefs_inc;
-
- Channel::Mix::IMA_ADPCM_State *ima_adpcm;
-
- int32_t *reverb_buffer;
- };
-
-
-
- template<class Depth,bool is_stereo,bool use_filter,bool is_ima_adpcm,bool use_fx,InterpolationType type,MixChannels>
- _FORCE_INLINE_ void do_resample(const Depth* p_src, int32_t *p_dst, ResamplerState *p_state);
-
- MixChannels mix_channels;
-
- void mix_channel(Channel& p_channel);
- int mix_chunk_left;
- void mix_chunk();
-
- float channel_nrg;
- int channel_id_count;
- bool inside_mix;
- MixStepCallback step_callback;
- void *step_udata;
- _FORCE_INLINE_ int _get_channel(ChannelID p_channel) const;
-
- int max_reverbs;
- struct ReverbState {
-
- bool used_in_chunk;
- bool enabled;
- ReverbSW *reverb;
- int frames_idle;
- int32_t *buffer; //reverb is sent here
- ReverbState() { enabled=false; frames_idle=0; used_in_chunk=false; }
- };
-
- ReverbState *reverb_state;
-
-
-public:
-
-
- virtual ChannelID channel_alloc(RID p_sample);
-
- virtual void channel_set_volume(ChannelID p_channel, float p_gain);
- virtual void channel_set_pan(ChannelID p_channel, float p_pan, float p_depth=0,float height=0); //pan and depth go from -1 to 1
- virtual void channel_set_filter(ChannelID p_channel, FilterType p_type, float p_cutoff, float p_resonance, float p_gain=1.0);
- virtual void channel_set_chorus(ChannelID p_channel, float p_chorus );
- virtual void channel_set_reverb(ChannelID p_channel, ReverbRoomType p_room_type, float p_reverb);
- virtual void channel_set_mix_rate(ChannelID p_channel, int p_mix_rate);
- virtual void channel_set_positional(ChannelID p_channel, bool p_positional);
-
- virtual float channel_get_volume(ChannelID p_channel) const;
- virtual float channel_get_pan(ChannelID p_channel) const; //pan and depth go from -1 to 1
- virtual float channel_get_pan_depth(ChannelID p_channel) const; //pan and depth go from -1 to 1
- virtual float channel_get_pan_height(ChannelID p_channel) const; //pan and depth go from -1 to 1
- virtual FilterType channel_get_filter_type(ChannelID p_channel) const;
- virtual float channel_get_filter_cutoff(ChannelID p_channel) const;
- virtual float channel_get_filter_resonance(ChannelID p_channel) const;
- virtual float channel_get_filter_gain(ChannelID p_channel) const;
-
- virtual float channel_get_chorus(ChannelID p_channel) const;
- virtual ReverbRoomType channel_get_reverb_type(ChannelID p_channel) const;
- virtual float channel_get_reverb(ChannelID p_channel) const;
-
- virtual int channel_get_mix_rate(ChannelID p_channel) const;
- virtual bool channel_is_positional(ChannelID p_channel) const;
-
- virtual bool channel_is_valid(ChannelID p_channel) const;
-
- virtual void channel_free(ChannelID p_channel);
-
- int mix(int32_t *p_buffer,int p_frames); //return amount of mixsteps
- uint64_t get_step_usecs() const;
-
- virtual void set_mixer_volume(float p_volume);
-
- AudioMixerSW(SampleManagerSW *p_sample_manager,int p_desired_latency_ms,int p_mix_rate,MixChannels p_mix_channels,bool p_use_fx=true,InterpolationType p_interp=INTERPOLATION_LINEAR,MixStepCallback p_step_callback=NULL,void *p_callback_udata=NULL);
- ~AudioMixerSW();
-};
-
-#endif // AUDIO_MIXER_SW_H
diff --git a/servers/audio/audio_rb_resampler.cpp b/servers/audio/audio_rb_resampler.cpp
index aa4fca3a62..28f0007b5b 100644
--- a/servers/audio/audio_rb_resampler.cpp
+++ b/servers/audio/audio_rb_resampler.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_rb_resampler.h b/servers/audio/audio_rb_resampler.h
index 22643e4e82..e97e275b68 100644
--- a/servers/audio/audio_rb_resampler.h
+++ b/servers/audio/audio_rb_resampler.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/audio_server_sw.cpp b/servers/audio/audio_server_sw.cpp
deleted file mode 100644
index 853714be2a..0000000000
--- a/servers/audio/audio_server_sw.cpp
+++ /dev/null
@@ -1,1028 +0,0 @@
-/*************************************************************************/
-/* audio_server_sw.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 "audio_server_sw.h"
-#include "globals.h"
-#include "os/os.h"
-
-struct _AudioDriverLock {
-
- _AudioDriverLock() { if (AudioDriverSW::get_singleton()) AudioDriverSW::get_singleton()->lock(); }
- ~_AudioDriverLock() { if (AudioDriverSW::get_singleton()) AudioDriverSW::get_singleton()->unlock(); }
-
-};
-
-#define AUDIO_LOCK _AudioDriverLock _adlock;
-
-AudioMixer *AudioServerSW::get_mixer() {
-
- return mixer;
-}
-
-/* CALLBACKS */
-
-void AudioServerSW::audio_mixer_chunk_callback(int p_frames) {
-/*
- for(List<Stream*>::Element *E=event_streams.front();E;E=E->next()) {
-
- if (E->get()->active)
- E->get()->audio_stream->mix(NULL,p_frames);
- }
-*/
-}
-
-void AudioServerSW::_mixer_callback(void *p_udata) {
-
- AudioServerSW *self = (AudioServerSW*)p_udata;
- for(List<Stream*>::Element *E=self->active_audio_streams.front();E;E=E->next()) {
-
- if (!E->get()->active)
- continue;
-
- EventStream *es=E->get()->event_stream;
- if (!es)
- continue;
-
- es->update(self->mixer_step_usecs);
- }
-
-}
-
-void AudioServerSW::driver_process_chunk(int p_frames,int32_t *p_buffer) {
-
-
-
- int samples=p_frames*internal_buffer_channels;
-
- for(int i=0;i<samples;i++) {
- internal_buffer[i]=0;
- }
-
- while(voice_rb.commands_left()) {
-
- VoiceRBSW::Command cmd = voice_rb.pop_command();
-
- if (cmd.type==VoiceRBSW::Command::CMD_CHANGE_ALL_FX_VOLUMES) {
-
- SelfList<Voice>*al = active_list.first();
- while(al) {
-
- Voice *v=al->self();
- if (v->channel!=AudioMixer::INVALID_CHANNEL) {
- mixer->channel_set_volume(v->channel,v->volume*fx_volume_scale);
- }
- al=al->next();
- }
-
- continue;
- }
- if (!voice_owner.owns(cmd.voice))
- continue;
-
-
- Voice *v = voice_owner.get(cmd.voice);
-
- switch(cmd.type) {
- case VoiceRBSW::Command::CMD_NONE: {
-
-
- } break;
- case VoiceRBSW::Command::CMD_PLAY: {
-
- if (v->channel!=AudioMixer::INVALID_CHANNEL)
- mixer->channel_free(v->channel);
-
- RID sample = cmd.play.sample;
- if (!sample_manager->is_sample(sample))
- continue;
-
- v->channel=mixer->channel_alloc(sample);
- v->volume=1.0;
- mixer->channel_set_volume(v->channel,fx_volume_scale);
- if (v->channel==AudioMixer::INVALID_CHANNEL) {
-#ifdef AUDIO_DEBUG
- WARN_PRINT("AUDIO: all channels used, failed to allocate voice");
-#endif
- v->active=false;
- break; // no voices left?
- }
-
- v->active=true; // this kind of ensures it works
- if (!v->active_item.in_list())
- active_list.add(&v->active_item);
-
- } break;
- case VoiceRBSW::Command::CMD_STOP: {
-
- if (v->channel!=AudioMixer::INVALID_CHANNEL) {
- mixer->channel_free(v->channel);
- if (v->active_item.in_list()) {
- active_list.remove(&v->active_item);
- }
- }
- v->active=false;
- } break;
- case VoiceRBSW::Command::CMD_SET_VOLUME: {
-
-
- if (v->channel!=AudioMixer::INVALID_CHANNEL) {
- v->volume=cmd.volume.volume;
- mixer->channel_set_volume(v->channel,cmd.volume.volume*fx_volume_scale);
- }
-
- } break;
- case VoiceRBSW::Command::CMD_SET_PAN: {
-
- if (v->channel!=AudioMixer::INVALID_CHANNEL)
- mixer->channel_set_pan(v->channel,cmd.pan.pan,cmd.pan.depth,cmd.pan.height);
-
- } break;
- case VoiceRBSW::Command::CMD_SET_FILTER: {
-
-
- if (v->channel!=AudioMixer::INVALID_CHANNEL)
- mixer->channel_set_filter(v->channel,(AudioMixer::FilterType)cmd.filter.type,cmd.filter.cutoff,cmd.filter.resonance,cmd.filter.gain);
- } break;
- case VoiceRBSW::Command::CMD_SET_CHORUS: {
-
- if (v->channel!=AudioMixer::INVALID_CHANNEL)
- mixer->channel_set_chorus(v->channel,cmd.chorus.send);
-
- } break;
- case VoiceRBSW::Command::CMD_SET_REVERB: {
-
- if (v->channel!=AudioMixer::INVALID_CHANNEL)
- mixer->channel_set_reverb(v->channel,(AudioMixer::ReverbRoomType)cmd.reverb.room,cmd.reverb.send);
-
- } break;
- case VoiceRBSW::Command::CMD_SET_MIX_RATE: {
-
- if (v->channel!=AudioMixer::INVALID_CHANNEL)
- mixer->channel_set_mix_rate(v->channel,cmd.mix_rate.mix_rate);
-
- } break;
- case VoiceRBSW::Command::CMD_SET_POSITIONAL: {
-
- if (v->channel!=AudioMixer::INVALID_CHANNEL)
- mixer->channel_set_positional(v->channel,cmd.positional.positional);
-
- } break;
- default: {}
-
- }
- }
-
- mixer->mix(internal_buffer,p_frames);
- //uint64_t stepsize=mixer->get_step_usecs();
-
-
- for(List<Stream*>::Element *E=active_audio_streams.front();E;E=E->next()) {
-
- ERR_CONTINUE(!E->get()->active); // bug?
-
-
- AudioStream *as=E->get()->audio_stream;
- if (!as)
- continue;
-
- int channels=as->get_channel_count();
- if (channels==0)
- continue; // does not want mix
- if (!as->mix(stream_buffer,p_frames))
- continue; //nothing was mixed!!
-
- int32_t stream_vol_scale=(stream_volume*stream_volume_scale*E->get()->volume_scale)*(1<<STREAM_SCALE_BITS);
-
-#define STRSCALE(m_val) (((m_val>>STREAM_SCALE_BITS)*stream_vol_scale)>>8)
- switch(internal_buffer_channels) {
-
- case 2: {
-
- switch(channels) {
- case 1: {
-
- for(int i=0;i<p_frames;i++) {
-
- internal_buffer[(i<<1)+0]+=STRSCALE(stream_buffer[i]);
- internal_buffer[(i<<1)+1]+=STRSCALE(stream_buffer[i]);
- }
- } break;
- case 2: {
-
- for(int i=0;i<p_frames*2;i++) {
-
- internal_buffer[i]+=STRSCALE(stream_buffer[i]);
- }
- } break;
- case 4: {
-
- for(int i=0;i<p_frames;i++) {
-
- internal_buffer[(i<<2)+0]+=STRSCALE((stream_buffer[(i<<2)+0]+stream_buffer[(i<<2)+2])>>1);
- internal_buffer[(i<<2)+1]+=STRSCALE((stream_buffer[(i<<2)+1]+stream_buffer[(i<<2)+3])>>1);
- }
- } break;
-
- } break;
-
- } break;
- case 4: {
-
- switch(channels) {
- case 1: {
-
- for(int i=0;i<p_frames;i++) {
-
- internal_buffer[(i<<2)+0]+=STRSCALE(stream_buffer[i]);
- internal_buffer[(i<<2)+1]+=STRSCALE(stream_buffer[i]);
- internal_buffer[(i<<2)+2]+=STRSCALE(stream_buffer[i]);
- internal_buffer[(i<<2)+3]+=STRSCALE(stream_buffer[i]);
- }
- } break;
- case 2: {
-
- for(int i=0;i<p_frames*2;i++) {
-
- internal_buffer[(i<<2)+0]+=STRSCALE(stream_buffer[(i<<1)+0]);
- internal_buffer[(i<<2)+1]+=STRSCALE(stream_buffer[(i<<1)+1]);
- internal_buffer[(i<<2)+2]+=STRSCALE(stream_buffer[(i<<1)+0]);
- internal_buffer[(i<<2)+3]+=STRSCALE(stream_buffer[(i<<1)+1]);
- }
- } break;
- case 4: {
-
- for(int i=0;i<p_frames*4;i++) {
- internal_buffer[i]+=STRSCALE(stream_buffer[i]);
- }
- } break;
-
- } break;
-
- } break;
- case 6: {
-
-
- } break;
- }
-
-#undef STRSCALE
- }
-
- SelfList<Voice> *activeE=active_list.first();
- while(activeE) {
-
- SelfList<Voice> *activeN=activeE->next();
- if (activeE->self()->channel==AudioMixer::INVALID_CHANNEL || !mixer->channel_is_valid(activeE->self()->channel)) {
-
- active_list.remove(activeE);
- activeE->self()->active=false;
-
- }
- activeE=activeN;
- }
-
- uint32_t peak=0;
- for(int i=0;i<samples;i++) {
- //clamp to (1<<24) using branchless code
- int32_t in = internal_buffer[i];
-#ifdef DEBUG_ENABLED
- {
- int mask = (in >> (32 - 1));
- uint32_t p = (in + mask) ^ mask;
- if (p>peak)
- peak=p;
- }
-#endif
- int32_t lo = -0x800000, hi=0x7FFFFF;
- lo-=in;
- hi-=in;
- in += (lo & ((lo < 0) - 1)) + (hi & ((hi > 0) - 1));
- p_buffer[i]=in<<8;
- }
-
- if (peak>max_peak)
- max_peak=peak;
-}
-
-void AudioServerSW::driver_process(int p_frames,int32_t *p_buffer) {
-
-
- _output_delay=p_frames/double(AudioDriverSW::get_singleton()->get_mix_rate());
- //process in chunks to make sure to never process more than INTERNAL_BUFFER_SIZE
- int todo=p_frames;
- while(todo) {
-
- int tomix=MIN(todo,INTERNAL_BUFFER_SIZE);
- driver_process_chunk(tomix,p_buffer);
- p_buffer+=tomix;
- todo-=tomix;
- }
-
-
-}
-
-/* SAMPLE API */
-
-RID AudioServerSW::sample_create(SampleFormat p_format, bool p_stereo, int p_length) {
-
- AUDIO_LOCK
-
- return sample_manager->sample_create(p_format,p_stereo,p_length);
-}
-
-void AudioServerSW::sample_set_description(RID p_sample, const String& p_description) {
-
- AUDIO_LOCK
- sample_manager->sample_set_description(p_sample,p_description);
-}
-String AudioServerSW::sample_get_description(RID p_sample) const {
-
- AUDIO_LOCK
- return sample_manager->sample_get_description(p_sample);
-}
-
-AS::SampleFormat AudioServerSW::sample_get_format(RID p_sample) const {
- //AUDIO_LOCK
- return sample_manager->sample_get_format(p_sample);
-}
-bool AudioServerSW::sample_is_stereo(RID p_sample) const {
- //AUDIO_LOCK
- return sample_manager->sample_is_stereo(p_sample);
-}
-int AudioServerSW::sample_get_length(RID p_sample) const {
- ///AUDIO_LOCK
- return sample_manager->sample_get_length(p_sample);
-}
-
-const void* AudioServerSW::sample_get_data_ptr(RID p_sample) const {
- ///AUDIO_LOCK
- return sample_manager->sample_get_data_ptr(p_sample);
-}
-
-void AudioServerSW::sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer) {
- AUDIO_LOCK
- sample_manager->sample_set_data(p_sample,p_buffer);
-}
-DVector<uint8_t> AudioServerSW::sample_get_data(RID p_sample) const {
- AUDIO_LOCK
- return sample_manager->sample_get_data(p_sample);
-}
-
-void AudioServerSW::sample_set_mix_rate(RID p_sample,int p_rate) {
- AUDIO_LOCK
- sample_manager->sample_set_mix_rate(p_sample,p_rate);
-}
-int AudioServerSW::sample_get_mix_rate(RID p_sample) const {
- AUDIO_LOCK
- return sample_manager->sample_get_mix_rate(p_sample);
-}
-
-void AudioServerSW::sample_set_loop_format(RID p_sample,SampleLoopFormat p_format) {
- AUDIO_LOCK
- sample_manager->sample_set_loop_format(p_sample,p_format);
-}
-AS::SampleLoopFormat AudioServerSW::sample_get_loop_format(RID p_sample) const {
- AUDIO_LOCK
- return sample_manager->sample_get_loop_format(p_sample);
-}
-
-void AudioServerSW::sample_set_loop_begin(RID p_sample,int p_pos) {
- AUDIO_LOCK
- sample_manager->sample_set_loop_begin(p_sample,p_pos);
-}
-int AudioServerSW::sample_get_loop_begin(RID p_sample) const {
- AUDIO_LOCK
- return sample_manager->sample_get_loop_begin(p_sample);
-}
-
-void AudioServerSW::sample_set_loop_end(RID p_sample,int p_pos) {
- AUDIO_LOCK
- sample_manager->sample_set_loop_end(p_sample,p_pos);
-}
-int AudioServerSW::sample_get_loop_end(RID p_sample) const {
- AUDIO_LOCK
- return sample_manager->sample_get_loop_end(p_sample);
-}
-
-/* VOICE API */
-
-RID AudioServerSW::voice_create() {
-
- Voice * v = memnew( Voice );
- v->channel=AudioMixer::INVALID_CHANNEL;
-
- AUDIO_LOCK
- return voice_owner.make_rid(v);
-
-}
-void AudioServerSW::voice_play(RID p_voice, RID p_sample) {
-
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND(!v);
- v->active=true; // force actvive (will be disabled later i gues..)
-
- //stop old, start new
- VoiceRBSW::Command cmd;
- cmd.type=VoiceRBSW::Command::CMD_PLAY;
- cmd.voice=p_voice;
- cmd.play.sample=p_sample;
- voice_rb.push_command(cmd);
-
-}
-
-void AudioServerSW::voice_set_volume(RID p_voice, float p_volume) {
-
- VoiceRBSW::Command cmd;
- cmd.type=VoiceRBSW::Command::CMD_SET_VOLUME;
- cmd.voice=p_voice;
- cmd.volume.volume=p_volume;
- voice_rb.push_command(cmd);
-
-}
-void AudioServerSW::voice_set_pan(RID p_voice, float p_pan, float p_depth,float p_height) {
-
- VoiceRBSW::Command cmd;
- cmd.type=VoiceRBSW::Command::CMD_SET_PAN;
- cmd.voice=p_voice;
- cmd.pan.pan=p_pan;
- cmd.pan.depth=p_depth;
- cmd.pan.height=p_height;
- voice_rb.push_command(cmd);
-
-}
-void AudioServerSW::voice_set_filter(RID p_voice, FilterType p_type, float p_cutoff, float p_resonance,float p_gain) {
-
- VoiceRBSW::Command cmd;
- cmd.type=VoiceRBSW::Command::CMD_SET_FILTER;
- cmd.voice=p_voice;
- cmd.filter.type=p_type;
- cmd.filter.cutoff=p_cutoff;
- cmd.filter.resonance=p_resonance;
- cmd.filter.gain=p_gain;
- voice_rb.push_command(cmd);
-
-}
-void AudioServerSW::voice_set_chorus(RID p_voice, float p_chorus ) {
-
- VoiceRBSW::Command cmd;
- cmd.type=VoiceRBSW::Command::CMD_SET_CHORUS;
- cmd.voice=p_voice;
- cmd.chorus.send=p_chorus;
- voice_rb.push_command(cmd);
-
-}
-void AudioServerSW::voice_set_reverb(RID p_voice, ReverbRoomType p_room_type, float p_reverb) {
-
- VoiceRBSW::Command cmd;
- cmd.type=VoiceRBSW::Command::CMD_SET_REVERB;
- cmd.voice=p_voice;
- cmd.reverb.room=p_room_type;
- cmd.reverb.send=p_reverb;
-
- voice_rb.push_command(cmd);
-
-}
-void AudioServerSW::voice_set_mix_rate(RID p_voice, int p_mix_rate) {
-
- VoiceRBSW::Command cmd;
- cmd.type=VoiceRBSW::Command::CMD_SET_MIX_RATE;
- cmd.voice=p_voice;
- cmd.mix_rate.mix_rate=p_mix_rate;
- voice_rb.push_command(cmd);
-
-}
-void AudioServerSW::voice_set_positional(RID p_voice, bool p_positional) {
-
- VoiceRBSW::Command cmd;
- cmd.type=VoiceRBSW::Command::CMD_SET_POSITIONAL;
- cmd.voice=p_voice;
- cmd.positional.positional=p_positional;
- voice_rb.push_command(cmd);
-
-}
-
-float AudioServerSW::voice_get_volume(RID p_voice) const {
-
- AUDIO_LOCK
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND_V(!v, 0);
-
- return mixer->channel_get_volume( v->channel );
-
-}
-float AudioServerSW::voice_get_pan(RID p_voice) const {
-
- AUDIO_LOCK
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND_V(!v, 0);
-
- return mixer->channel_get_pan( v->channel );
-
-}
-float AudioServerSW::voice_get_pan_depth(RID p_voice) const {
-
- AUDIO_LOCK
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND_V(!v, 0);
-
- return mixer->channel_get_pan_depth( v->channel );
-
-}
-float AudioServerSW::voice_get_pan_height(RID p_voice) const {
-
- AUDIO_LOCK
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND_V(!v, 0);
-
- return mixer->channel_get_pan_height( v->channel );
-
-}
-AS::FilterType AudioServerSW::voice_get_filter_type(RID p_voice) const {
-
- AUDIO_LOCK
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND_V(!v, AS::FILTER_NONE);
-
- return (AS::FilterType)mixer->channel_get_filter_type(v->channel);
-
-}
-float AudioServerSW::voice_get_filter_cutoff(RID p_voice) const {
-
- AUDIO_LOCK
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND_V(!v, 0);
-
- return mixer->channel_get_filter_cutoff( v->channel );
-
-}
-float AudioServerSW::voice_get_filter_resonance(RID p_voice) const {
-
- AUDIO_LOCK
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND_V(!v, 0);
-
- return mixer->channel_get_filter_resonance( v->channel );
-
-}
-float AudioServerSW::voice_get_chorus(RID p_voice) const {
-
- AUDIO_LOCK
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND_V(!v, 0);
-
- return mixer->channel_get_chorus( v->channel );
-
-}
-AS::ReverbRoomType AudioServerSW::voice_get_reverb_type(RID p_voice) const {
-
- AUDIO_LOCK
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND_V(!v, REVERB_SMALL);
-
- return (AS::ReverbRoomType)mixer->channel_get_reverb_type( v->channel );
-
-}
-float AudioServerSW::voice_get_reverb(RID p_voice) const {
-
- AUDIO_LOCK
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND_V(!v, 0);
-
- return mixer->channel_get_reverb( v->channel );
-
-}
-
-int AudioServerSW::voice_get_mix_rate(RID p_voice) const {
-
- AUDIO_LOCK
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND_V(!v, 0);
-
- return mixer->channel_get_mix_rate( v->channel );
-
-}
-bool AudioServerSW::voice_is_positional(RID p_voice) const {
-
- AUDIO_LOCK
- Voice *v = voice_owner.get( p_voice );
- ERR_FAIL_COND_V(!v, 0);
-
- return mixer->channel_is_positional( v->channel );
-
-}
-
-void AudioServerSW::voice_stop(RID p_voice) {
-
- VoiceRBSW::Command cmd;
- cmd.type=VoiceRBSW::Command::CMD_STOP;
- cmd.voice=p_voice;
- voice_rb.push_command(cmd);
-
- //return mixer->channel_free( v->channel );
-
-}
-
-bool AudioServerSW::voice_is_active(RID p_voice) const {
-
- Voice *v = voice_owner.get(p_voice);
- ERR_FAIL_COND_V(!v,false);
- return v->active;
-
-}
-
-/* STREAM API */
-
-RID AudioServerSW::audio_stream_create(AudioStream *p_stream) {
-
- AUDIO_LOCK
- Stream *s = memnew(Stream);
- s->audio_stream=p_stream;
- s->event_stream=NULL;
- s->active=false;
- s->E=NULL;
- s->volume_scale=1.0;
- p_stream->set_mix_rate(AudioDriverSW::get_singleton()->get_mix_rate());
-
- return stream_owner.make_rid(s);
-}
-
-RID AudioServerSW::event_stream_create(EventStream *p_stream) {
-
- AUDIO_LOCK
- Stream *s = memnew(Stream);
- s->audio_stream=NULL;
- s->event_stream=p_stream;
- s->active=false;
- s->E=NULL;
- s->volume_scale=1.0;
- //p_stream->set_mix_rate(AudioDriverSW::get_singleton()->get_mix_rate());
-
- return stream_owner.make_rid(s);
-
-
-}
-
-
-void AudioServerSW::stream_set_active(RID p_stream, bool p_active) {
-
-
- Stream *s = stream_owner.get(p_stream);
- ERR_FAIL_COND(!s);
- _THREAD_SAFE_METHOD_
-
- if (s->active==p_active)
- return;
- AUDIO_LOCK;
- s->active=p_active;
- if (p_active)
- s->E=active_audio_streams.push_back(s);
- else {
- active_audio_streams.erase(s->E);
- s->E=NULL;
- }
-
-
-}
-
-bool AudioServerSW::stream_is_active(RID p_stream) const {
-
- Stream *s = stream_owner.get(p_stream);
- ERR_FAIL_COND_V(!s,false);
- return s->active;
-}
-
-void AudioServerSW::stream_set_volume_scale(RID p_stream, float p_scale) {
-
- Stream *s = stream_owner.get(p_stream);
- ERR_FAIL_COND(!s);
- s->volume_scale=p_scale;
-
-}
-
-float AudioServerSW::stream_set_volume_scale(RID p_stream) const {
-
- Stream *s = stream_owner.get(p_stream);
- ERR_FAIL_COND_V(!s,0);
- return s->volume_scale;
-
-}
-
-
-void AudioServerSW::free(RID p_id) {
-
- if(voice_owner.owns(p_id)) {
-
- Voice *v = voice_owner.get(p_id);
- AUDIO_LOCK
- mixer->channel_free( v->channel );
- voice_owner.free(p_id);
- memdelete(v);
-
- } else if (stream_owner.owns(p_id)) {
-
-
- Stream *s=stream_owner.get(p_id);
-
- if (s->active) {
- stream_set_active(p_id,false);
- }
-
- memdelete(s);
- stream_owner.free(p_id);
-
- } else if (sample_manager->is_sample(p_id)) {
-
- AUDIO_LOCK
- sample_manager->free(p_id);
- }
-
-}
-
-void AudioServerSW::_thread_func(void *self) {
-
- Thread::set_name("AudioServerSW");
-
- AudioServerSW *as=(AudioServerSW *)self;
-
- while (!as->exit_update_thread) {
- as->_update_streams(true);
- OS::get_singleton()->delay_usec(5000);
- }
-
-}
-
-void AudioServerSW::init() {
-
- int latency = GLOBAL_DEF("audio/mixer_latency",10);
- internal_buffer_channels=2; // read from driver
- internal_buffer = memnew_arr(int32_t,INTERNAL_BUFFER_SIZE*internal_buffer_channels);
- stream_buffer = memnew_arr(int32_t,INTERNAL_BUFFER_SIZE*4); //max 4 channels
- AudioMixerSW::MixChannels mix_chans = AudioMixerSW::MIX_STEREO;
-
- switch(AudioDriverSW::get_singleton()->get_output_format()) {
-
- case AudioDriverSW::OUTPUT_MONO:
- case AudioDriverSW::OUTPUT_STEREO:
- mix_chans=AudioMixerSW::MIX_STEREO;
- break;
- case AudioDriverSW::OUTPUT_QUAD:
- case AudioDriverSW::OUTPUT_5_1:
- mix_chans=AudioMixerSW::MIX_QUAD;
- break;
- }
-
- mixer = memnew( AudioMixerSW( sample_manager, latency, AudioDriverSW::get_singleton()->get_mix_rate(),mix_chans,mixer_use_fx,mixer_interp,_mixer_callback,this ) );
- mixer_step_usecs=mixer->get_step_usecs();
-
- _output_delay=0;
-
- stream_volume=0.3;
- // start the audio driver
- if (AudioDriverSW::get_singleton())
- AudioDriverSW::get_singleton()->start();
-
-#ifndef NO_THREADS
- exit_update_thread=false;
- thread = Thread::create(_thread_func,this);
-#endif
-
-}
-
-void AudioServerSW::finish() {
-
-#ifndef NO_THREADS
- exit_update_thread=true;
- Thread::wait_to_finish(thread);
- memdelete(thread);
-#endif
-
- if (AudioDriverSW::get_singleton())
- AudioDriverSW::get_singleton()->finish();
-
- memdelete_arr(internal_buffer);
- memdelete_arr(stream_buffer);
- memdelete(mixer);
-
-}
-
-void AudioServerSW::_update_streams(bool p_thread) {
-
- _THREAD_SAFE_METHOD_
- for(List<Stream*>::Element *E=active_audio_streams.front();E;) { //stream might be removed durnig this callback
-
- List<Stream*>::Element *N=E->next();
-
- if (E->get()->audio_stream && p_thread == E->get()->audio_stream->can_update_mt())
- E->get()->audio_stream->update();
-
- E=N;
- }
-
-}
-
-void AudioServerSW::update() {
-
- _update_streams(false);
-#ifdef NO_THREADS
-
- _update_streams(true);
-#endif
-}
-
-
-void AudioServerSW::lock() {
-
- AudioDriverSW::get_singleton()->lock();
-}
-
-void AudioServerSW::unlock() {
- AudioDriverSW::get_singleton()->unlock();
-
-}
-
-int AudioServerSW::get_default_mix_rate() const {
-
- return AudioDriverSW::get_singleton()->get_mix_rate();
-}
-int AudioServerSW::get_default_channel_count() const {
- return internal_buffer_channels;
-}
-
-void AudioServerSW::set_mixer_params(AudioMixerSW::InterpolationType p_interp, bool p_use_fx) {
-
- mixer_interp=p_interp;
- mixer_use_fx=p_use_fx;
-}
-
-void AudioServerSW::set_stream_global_volume_scale(float p_volume) {
-
- stream_volume_scale=p_volume;
-}
-
-float AudioServerSW::get_stream_global_volume_scale() const {
-
- return stream_volume_scale;
-
-
-}
-
-void AudioServerSW::set_fx_global_volume_scale(float p_volume) {
-
- fx_volume_scale=p_volume;
- //mixer->set_mixer_volume(fx_volume_scale);
- VoiceRBSW::Command cmd;
- cmd.type=VoiceRBSW::Command::CMD_CHANGE_ALL_FX_VOLUMES;
- cmd.voice=RID();
- cmd.volume.volume=p_volume;
- voice_rb.push_command(cmd);
-
-}
-
-
-float AudioServerSW::get_fx_global_volume_scale() const {
-
- return fx_volume_scale;
-}
-
-void AudioServerSW::set_event_voice_global_volume_scale(float p_volume) {
-
- event_voice_volume_scale=p_volume;
- //mixer->set_mixer_volume(event_voice_volume_scale);
-}
-
-
-float AudioServerSW::get_event_voice_global_volume_scale() const {
-
- return event_voice_volume_scale;
-}
-
-double AudioServerSW::get_output_delay() const {
-
- return _output_delay+AudioDriverSW::get_singleton()->get_latency();
-}
-
-double AudioServerSW::get_mix_time() const {
-
- return AudioDriverSW::get_singleton()->get_mix_time();
-}
-
-uint32_t AudioServerSW::read_output_peak() const {
-
- uint32_t val = max_peak;
- uint32_t *p = (uint32_t*)&max_peak;
- *p=0;
- return val;
-}
-
-AudioServerSW::AudioServerSW(SampleManagerSW *p_sample_manager) {
-
- sample_manager=p_sample_manager;
- String interp = GLOBAL_DEF("audio/mixer_interp","linear");
- Globals::get_singleton()->set_custom_property_info("audio/mixer_interp",PropertyInfo(Variant::STRING,"audio/mixer_interp",PROPERTY_HINT_ENUM,"raw,linear,cubic"));
- if (interp=="raw")
- mixer_interp=AudioMixerSW::INTERPOLATION_RAW;
- else if (interp=="cubic")
- mixer_interp=AudioMixerSW::INTERPOLATION_CUBIC;
- else
- mixer_interp=AudioMixerSW::INTERPOLATION_LINEAR;
- mixer_use_fx = GLOBAL_DEF("audio/use_chorus_reverb",true);
- stream_volume_scale=GLOBAL_DEF("audio/stream_volume_scale",1.0);
- fx_volume_scale=GLOBAL_DEF("audio/fx_volume_scale",1.0);
- event_voice_volume_scale=GLOBAL_DEF("audio/event_voice_volume_scale",0.5);
- max_peak=0;
-
-
-}
-
-AudioServerSW::~AudioServerSW() {
-
-}
-
-
-AudioDriverSW *AudioDriverSW::singleton=NULL;
-AudioDriverSW *AudioDriverSW::get_singleton() {
-
- return singleton;
-}
-
-void AudioDriverSW::set_singleton() {
-
- singleton=this;
-}
-
-void AudioDriverSW::audio_server_process(int p_frames,int32_t *p_buffer,bool p_update_mix_time) {
-
- AudioServerSW * audio_server = static_cast<AudioServerSW*>(AudioServer::get_singleton());
- if (p_update_mix_time)
- update_mix_time(p_frames);
- audio_server->driver_process(p_frames,p_buffer);
-}
-
-void AudioDriverSW::update_mix_time(int p_frames) {
-
- _mix_amount+=p_frames;
- _last_mix_time=OS::get_singleton()->get_ticks_usec();
-}
-
-double AudioDriverSW::get_mix_time() const {
-
- double total = (OS::get_singleton()->get_ticks_usec() - _last_mix_time) / 1000000.0;
- total+=_mix_amount/(double)get_mix_rate();
- return total;
-
-}
-
-
-AudioDriverSW::AudioDriverSW() {
-
- _last_mix_time=0;
- _mix_amount=0;
-}
-
-
-AudioDriverSW *AudioDriverManagerSW::drivers[MAX_DRIVERS];
-int AudioDriverManagerSW::driver_count=0;
-
-
-
-void AudioDriverManagerSW::add_driver(AudioDriverSW *p_driver) {
-
- ERR_FAIL_COND(driver_count>=MAX_DRIVERS);
- drivers[driver_count++]=p_driver;
-}
-
-int AudioDriverManagerSW::get_driver_count() {
-
- return driver_count;
-}
-AudioDriverSW *AudioDriverManagerSW::get_driver(int p_driver) {
-
- ERR_FAIL_INDEX_V(p_driver,driver_count,NULL);
- return drivers[p_driver];
-}
-
diff --git a/servers/audio/audio_server_sw.h b/servers/audio/audio_server_sw.h
deleted file mode 100644
index fda952fa94..0000000000
--- a/servers/audio/audio_server_sw.h
+++ /dev/null
@@ -1,286 +0,0 @@
-/*************************************************************************/
-/* audio_server_sw.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 AUDIO_SERVER_SW_H
-#define AUDIO_SERVER_SW_H
-
-#include "servers/audio_server.h"
-#include "servers/audio/audio_mixer_sw.h"
-#include "servers/audio/voice_rb_sw.h"
-#include "self_list.h"
-#include "os/thread_safe.h"
-#include "os/thread.h"
-class AudioServerSW : public AudioServer {
-
- OBJ_TYPE( AudioServerSW, AudioServer );
-
- _THREAD_SAFE_CLASS_
-
- enum {
- INTERNAL_BUFFER_SIZE=4096,
- STREAM_SCALE_BITS=12
-
- };
-
- SampleManagerSW *sample_manager;
- AudioMixerSW *mixer;
-
- virtual AudioMixer *get_mixer();
- virtual void audio_mixer_chunk_callback(int p_frames);
-
- struct Voice {
-
- float volume;
- volatile bool active;
- SelfList<Voice> active_item;
- AudioMixer::ChannelID channel;
-
-
- Voice () : active_item(this) { channel=AudioMixer::INVALID_CHANNEL; active=false;}
- };
-
- mutable RID_Owner<Voice> voice_owner;
- SelfList<Voice>::List active_list;
-
- struct Stream {
- bool active;
- List<Stream*>::Element *E;
- AudioStream *audio_stream;
- EventStream *event_stream;
- float volume_scale;
- };
-
- List<Stream*> active_audio_streams;
-
- //List<Stream*> event_streams;
-
- int32_t * internal_buffer;
- int internal_buffer_channels;
- int32_t * stream_buffer;
-
- mutable RID_Owner<Stream> stream_owner;
-
- float stream_volume;
- float stream_volume_scale;
- float fx_volume_scale;
- float event_voice_volume_scale;
- float peak_left,peak_right;
- uint32_t max_peak;
-
- double _output_delay;
-
- VoiceRBSW voice_rb;
-
- bool exit_update_thread;
- Thread *thread;
- static void _thread_func(void *self);
-
- void _update_streams(bool p_thread);
- void driver_process_chunk(int p_frames,int32_t *p_buffer);
-
- AudioMixerSW::InterpolationType mixer_interp;
- bool mixer_use_fx;
- uint64_t mixer_step_usecs;
-
- static void _mixer_callback(void *p_udata);
-friend class AudioDriverSW;
- void driver_process(int p_frames,int32_t *p_buffer);
-public:
-
-
- /* SAMPLE API */
-
- virtual RID sample_create(SampleFormat p_format, bool p_stereo, int p_length);
-
- virtual void sample_set_description(RID p_sample, const String& p_description);
- virtual String sample_get_description(RID p_sample) const;
-
- virtual SampleFormat sample_get_format(RID p_sample) const;
- virtual bool sample_is_stereo(RID p_sample) const;
- virtual int sample_get_length(RID p_sample) const;
- const void* sample_get_data_ptr(RID p_sample) const;
-
- virtual void sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer);
- virtual DVector<uint8_t> sample_get_data(RID p_sample) const;
-
- virtual void sample_set_mix_rate(RID p_sample,int p_rate);
- virtual int sample_get_mix_rate(RID p_sample) const;
-
- virtual void sample_set_loop_format(RID p_sample,SampleLoopFormat p_format);
- virtual SampleLoopFormat sample_get_loop_format(RID p_sample) const;
-
- virtual void sample_set_loop_begin(RID p_sample,int p_pos);
- virtual int sample_get_loop_begin(RID p_sample) const;
-
- virtual void sample_set_loop_end(RID p_sample,int p_pos);
- virtual int sample_get_loop_end(RID p_sample) const;
-
- /* VOICE API */
-
- virtual RID voice_create();
-
- virtual void voice_play(RID p_voice, RID p_sample);
-
- virtual void voice_set_volume(RID p_voice, float p_volume);
- virtual void voice_set_pan(RID p_voice, float p_pan, float p_depth=0,float height=0); //pan and depth go from -1 to 1
- virtual void voice_set_filter(RID p_voice, FilterType p_type, float p_cutoff, float p_resonance,float p_gain=0);
- virtual void voice_set_chorus(RID p_voice, float p_chorus );
- virtual void voice_set_reverb(RID p_voice, ReverbRoomType p_room_type, float p_reverb);
- virtual void voice_set_mix_rate(RID p_voice, int p_mix_rate);
- virtual void voice_set_positional(RID p_voice, bool p_positional);
-
- virtual float voice_get_volume(RID p_voice) const;
- virtual float voice_get_pan(RID p_voice) const; //pan and depth go from -1 to 1
- virtual float voice_get_pan_depth(RID p_voice) const; //pan and depth go from -1 to 1
- virtual float voice_get_pan_height(RID p_voice) const; //pan and depth go from -1 to 1
- virtual FilterType voice_get_filter_type(RID p_voice) const;
- virtual float voice_get_filter_cutoff(RID p_voice) const;
- virtual float voice_get_filter_resonance(RID p_voice) const;
- virtual float voice_get_chorus(RID p_voice) const;
- virtual ReverbRoomType voice_get_reverb_type(RID p_voice) const;
- virtual float voice_get_reverb(RID p_voice) const;
-
- virtual int voice_get_mix_rate(RID p_voice) const;
- virtual bool voice_is_positional(RID p_voice) const;
-
- virtual void voice_stop(RID p_voice);
- virtual bool voice_is_active(RID p_voice) const;
-
- /* STREAM API */
-
- virtual RID audio_stream_create(AudioStream *p_stream);
- virtual RID event_stream_create(EventStream *p_stream);
-
- virtual void stream_set_active(RID p_stream, bool p_active);
- virtual bool stream_is_active(RID p_stream) const;
-
- virtual void stream_set_volume_scale(RID p_stream, float p_scale);
- virtual float stream_set_volume_scale(RID p_stream) const;
-
- virtual void free(RID p_id);
-
- virtual void init();
- virtual void finish();
- virtual void update();
-
- virtual void lock();
- virtual void unlock();
- virtual int get_default_channel_count() const;
- virtual int get_default_mix_rate() const;
-
- void set_mixer_params(AudioMixerSW::InterpolationType p_interp, bool p_use_fx);
-
- virtual void set_stream_global_volume_scale(float p_volume);
- virtual void set_fx_global_volume_scale(float p_volume);
- virtual void set_event_voice_global_volume_scale(float p_volume);
-
-
- virtual float get_stream_global_volume_scale() const;
- virtual float get_fx_global_volume_scale() const;
- virtual float get_event_voice_global_volume_scale() const;
-
- virtual uint32_t read_output_peak() const;
-
- virtual double get_mix_time() const; //useful for video -> audio sync
-
- virtual double get_output_delay() const;
-
-
- AudioServerSW(SampleManagerSW *p_sample_manager);
- ~AudioServerSW();
-
-};
-
-
-class AudioDriverSW {
-
-
- static AudioDriverSW *singleton;
- uint64_t _last_mix_time;
- uint64_t _mix_amount;
-
-
-protected:
-
- void audio_server_process(int p_frames,int32_t *p_buffer,bool p_update_mix_time=true);
- void update_mix_time(int p_frames);
-
-public:
-
-
- double get_mix_time() const; //useful for video -> audio sync
-
- enum OutputFormat {
-
- OUTPUT_MONO,
- OUTPUT_STEREO,
- OUTPUT_QUAD,
- OUTPUT_5_1
- };
-
- static AudioDriverSW *get_singleton();
- void set_singleton();
-
- virtual const char* get_name() const=0;
-
- virtual Error init()=0;
- virtual void start()=0;
- virtual int get_mix_rate() const =0;
- virtual OutputFormat get_output_format() const=0;
- virtual void lock()=0;
- virtual void unlock()=0;
- virtual void finish()=0;
-
- virtual float get_latency() { return 0; }
-
-
-
-
- AudioDriverSW();
- virtual ~AudioDriverSW() {};
-};
-
-
-
-class AudioDriverManagerSW {
-
- enum {
-
- MAX_DRIVERS=10
- };
-
- static AudioDriverSW *drivers[MAX_DRIVERS];
- static int driver_count;
-public:
-
- static void add_driver(AudioDriverSW *p_driver);
- static int get_driver_count();
- static AudioDriverSW *get_driver(int p_driver);
-};
-
-#endif // AUDIO_SERVER_SW_H
diff --git a/servers/spatial_sound_server.cpp b/servers/audio/audio_stream.cpp
index 5f93c55a91..f4214838a1 100644
--- a/servers/spatial_sound_server.cpp
+++ b/servers/audio/audio_stream.cpp
@@ -1,11 +1,11 @@
/*************************************************************************/
-/* spatial_sound_server.cpp */
+/* audio_stream.cpp */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,19 +26,61 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "spatial_sound_server.h"
+#include "audio_stream.h"
-SpatialSoundServer *SpatialSoundServer::singleton=NULL;
+//////////////////////////////
-SpatialSoundServer *SpatialSoundServer::get_singleton() {
- return singleton;
+void AudioStreamPlaybackResampled::_begin_resample() {
+
+ //clear cubic interpolation history
+ internal_buffer[0]=AudioFrame(0.0,0.0);
+ internal_buffer[1]=AudioFrame(0.0,0.0);
+ internal_buffer[2]=AudioFrame(0.0,0.0);
+ internal_buffer[3]=AudioFrame(0.0,0.0);
+ //mix buffer
+ _mix_internal(internal_buffer+4,INTERNAL_BUFFER_LEN);
+ mix_offset=0;
}
+void AudioStreamPlaybackResampled::mix(AudioFrame* p_buffer,float p_rate_scale,int p_frames) {
+
+ float target_rate = AudioServer::get_singleton()->get_mix_rate() * p_rate_scale;
+
+ uint64_t mix_increment = uint64_t((get_stream_sampling_rate() / double(target_rate)) * double( FP_LEN ));
+
+ for(int i=0;i<p_frames;i++) {
+
+
+
+ uint32_t idx = CUBIC_INTERP_HISTORY + uint32_t(mix_offset >> FP_BITS);
+ //standard cubic interpolation (great quality/performance ratio)
+ //this used to be moved to a LUT for greater performance, but nowadays CPU speed is generally faster than memory.
+ float mu = (mix_offset&FP_MASK)/float(FP_LEN);
+ AudioFrame y0 = internal_buffer[idx-3];
+ AudioFrame y1 = internal_buffer[idx-2];
+ AudioFrame y2 = internal_buffer[idx-1];
+ AudioFrame y3 = internal_buffer[idx-0];
+
+ float mu2 = mu*mu;
+ AudioFrame a0 = y3 - y2 - y0 + y1;
+ AudioFrame a1 = y0 - y1 - a0;
+ AudioFrame a2 = y2 - y0;
+ AudioFrame a3 = y1;
+
+ p_buffer[i] = (a0*mu*mu2 + a1*mu2 + a2*mu + a3);
+
+ mix_offset+=mix_increment;
-SpatialSoundServer::SpatialSoundServer() {
+ while ( (mix_offset >> FP_BITS) >= INTERNAL_BUFFER_LEN ) {
- ERR_FAIL_COND(singleton!=NULL);
- singleton=this;
+ internal_buffer[0]=internal_buffer[INTERNAL_BUFFER_LEN+0];
+ internal_buffer[1]=internal_buffer[INTERNAL_BUFFER_LEN+1];
+ internal_buffer[2]=internal_buffer[INTERNAL_BUFFER_LEN+2];
+ internal_buffer[3]=internal_buffer[INTERNAL_BUFFER_LEN+3];
+ _mix_internal(internal_buffer+4,INTERNAL_BUFFER_LEN);
+ mix_offset-=(INTERNAL_BUFFER_LEN<<FP_BITS);
+ }
+ }
}
diff --git a/servers/spatial_sound_2d_server.cpp b/servers/audio/audio_stream.h
index cfe40a0937..d08fedb084 100644
--- a/servers/spatial_sound_2d_server.cpp
+++ b/servers/audio/audio_stream.h
@@ -1,11 +1,11 @@
/*************************************************************************/
-/* spatial_sound_2d_server.cpp */
+/* audio_stream.h */
/*************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,19 +26,76 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "spatial_sound_2d_server.h"
+#ifndef AUDIO_STREAM_H
+#define AUDIO_STREAM_H
-SpatialSound2DServer *SpatialSound2DServer::singleton=NULL;
+#include "resource.h"
+#include "servers/audio_server.h"
+class AudioStreamPlayback : public Reference {
-SpatialSound2DServer *SpatialSound2DServer::get_singleton() {
+ GDCLASS( AudioStreamPlayback, Reference )
- return singleton;
-}
+public:
+ virtual void start(float p_from_pos=0.0)=0;
+ virtual void stop()=0;
+ virtual bool is_playing() const=0;
-SpatialSound2DServer::SpatialSound2DServer() {
+ virtual int get_loop_count() const=0; //times it looped
- ERR_FAIL_COND(singleton!=NULL);
- singleton=this;
-}
+ virtual float get_pos() const=0;
+ virtual void seek_pos(float p_time)=0;
+
+ virtual void mix(AudioFrame* p_bufer,float p_rate_scale,int p_frames)=0;
+
+ virtual float get_length() const=0; //if supported, otherwise return 0
+
+
+};
+
+class AudioStreamPlaybackResampled : public AudioStreamPlayback {
+
+ GDCLASS( AudioStreamPlaybackResampled, AudioStreamPlayback )
+
+
+
+ enum {
+ FP_BITS=16, //fixed point used for resampling
+ FP_LEN=(1<<FP_BITS),
+ FP_MASK=FP_LEN-1,
+ INTERNAL_BUFFER_LEN=256,
+ CUBIC_INTERP_HISTORY=4
+ };
+
+ AudioFrame internal_buffer[INTERNAL_BUFFER_LEN+CUBIC_INTERP_HISTORY];
+ uint64_t mix_offset;
+
+protected:
+ void _begin_resample();
+ virtual void _mix_internal(AudioFrame* p_bufer,int p_frames)=0;
+ virtual float get_stream_sampling_rate()=0;
+
+public:
+
+ virtual void mix(AudioFrame* p_bufer,float p_rate_scale,int p_frames);
+
+ AudioStreamPlaybackResampled() { mix_offset=0; }
+};
+
+class AudioStream : public Resource {
+
+ GDCLASS( AudioStream, Resource )
+ OBJ_SAVE_TYPE( AudioStream ) //children are all saved as AudioStream, so they can be exchanged
+
+
+public:
+
+ virtual Ref<AudioStreamPlayback> instance_playback()=0;
+ virtual String get_stream_name() const=0;
+
+
+};
+
+
+#endif // AUDIO_STREAM_H
diff --git a/servers/audio/effects/SCsub b/servers/audio/effects/SCsub
new file mode 100644
index 0000000000..ccc76e823f
--- /dev/null
+++ b/servers/audio/effects/SCsub
@@ -0,0 +1,7 @@
+#!/usr/bin/env python
+
+Import('env')
+
+env.add_source_files(env.servers_sources, "*.cpp")
+
+Export('env')
diff --git a/servers/audio/effects/audio_effect_amplify.cpp b/servers/audio/effects/audio_effect_amplify.cpp
new file mode 100644
index 0000000000..fde33dfe63
--- /dev/null
+++ b/servers/audio/effects/audio_effect_amplify.cpp
@@ -0,0 +1,50 @@
+#include "audio_effect_amplify.h"
+
+
+void AudioEffectAmplifyInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+
+ //multiply volume interpolating to avoid clicks if this changes
+ float volume_db = base->volume_db;
+ float vol = Math::db2linear(mix_volume_db);
+ float vol_inc = (Math::db2linear(volume_db) - vol)/float(p_frame_count);
+
+ for(int i=0;i<p_frame_count;i++) {
+ p_dst_frames[i]=p_src_frames[i]*vol;
+ vol+=vol_inc;
+ }
+ //set volume for next mix
+ mix_volume_db = volume_db;
+
+}
+
+
+Ref<AudioEffectInstance> AudioEffectAmplify::instance() {
+ Ref<AudioEffectAmplifyInstance> ins;
+ ins.instance();
+ ins->base=Ref<AudioEffectAmplify>(this);
+ ins->mix_volume_db=volume_db;
+ return ins;
+}
+
+void AudioEffectAmplify::set_volume_db(float p_volume) {
+ volume_db=p_volume;
+}
+
+float AudioEffectAmplify::get_volume_db() const {
+
+ return volume_db;
+}
+
+void AudioEffectAmplify::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_volume_db","volume"),&AudioEffectAmplify::set_volume_db);
+ ClassDB::bind_method(D_METHOD("get_volume_db"),&AudioEffectAmplify::get_volume_db);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"volume_db",PROPERTY_HINT_RANGE,"-80,24,0.01"),"set_volume_db","get_volume_db");
+}
+
+AudioEffectAmplify::AudioEffectAmplify()
+{
+ volume_db=0;
+}
diff --git a/servers/audio/effects/audio_effect_amplify.h b/servers/audio/effects/audio_effect_amplify.h
new file mode 100644
index 0000000000..921054e2cd
--- /dev/null
+++ b/servers/audio/effects/audio_effect_amplify.h
@@ -0,0 +1,40 @@
+#ifndef AUDIOEFFECTAMPLIFY_H
+#define AUDIOEFFECTAMPLIFY_H
+
+#include "servers/audio/audio_effect.h"
+
+class AudioEffectAmplify;
+
+class AudioEffectAmplifyInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectAmplifyInstance,AudioEffectInstance)
+friend class AudioEffectAmplify;
+ Ref<AudioEffectAmplify> base;
+
+ float mix_volume_db;
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+};
+
+
+class AudioEffectAmplify : public AudioEffect {
+ GDCLASS(AudioEffectAmplify,AudioEffect)
+
+friend class AudioEffectAmplifyInstance;
+ float volume_db;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+
+ Ref<AudioEffectInstance> instance();
+ void set_volume_db(float p_volume);
+ float get_volume_db() const;
+
+ AudioEffectAmplify();
+};
+
+#endif // AUDIOEFFECTAMPLIFY_H
diff --git a/servers/audio/effects/audio_effect_chorus.cpp b/servers/audio/effects/audio_effect_chorus.cpp
new file mode 100644
index 0000000000..b33aabf24b
--- /dev/null
+++ b/servers/audio/effects/audio_effect_chorus.cpp
@@ -0,0 +1,365 @@
+#include "audio_effect_chorus.h"
+#include "servers/audio_server.h"
+#include "math_funcs.h"
+
+void AudioEffectChorusInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+ int todo = p_frame_count;
+
+ while(todo) {
+
+ int to_mix = MIN(todo,256); //can't mix too much
+
+ _process_chunk(p_src_frames,p_dst_frames,to_mix);
+
+ p_src_frames+=to_mix;
+ p_dst_frames+=to_mix;
+
+ todo-=to_mix;
+ }
+}
+
+void AudioEffectChorusInstance::_process_chunk(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+
+ //fill ringbuffer
+ for(int i=0;i<p_frame_count;i++) {
+ audio_buffer[(buffer_pos+i)&buffer_mask]=p_src_frames[i];
+ p_dst_frames[i]=p_src_frames[i]*base->dry;
+ }
+
+ float mix_rate = AudioServer::get_singleton()->get_mix_rate();
+
+ /* process voices */
+ for (int vc=0;vc<base->voice_count;vc++) {
+
+ AudioEffectChorus::Voice &v=base->voice[vc];
+
+
+ double time_to_mix=(float)p_frame_count/mix_rate;
+ double cycles_to_mix=time_to_mix*v.rate;
+
+ unsigned int local_rb_pos=buffer_pos;
+ AudioFrame *dst_buff=p_dst_frames;
+ AudioFrame *rb_buff=audio_buffer.ptr();
+
+ double delay_msec=v.delay;
+ unsigned int delay_frames=Math::fast_ftoi((delay_msec/1000.0)*mix_rate);
+ float max_depth_frames=(v.depth/1000.0)*mix_rate;
+
+ uint64_t local_cycles=cycles[vc];
+ uint64_t increment=llrint(cycles_to_mix/(double)p_frame_count*(double)(1<<AudioEffectChorus::CYCLES_FRAC));
+
+ //check the LFO doesnt read ahead of the write pos
+ if ((((int)max_depth_frames)+10)>delay_frames) { //10 as some threshold to avoid precision stuff
+ delay_frames+=(int)max_depth_frames-delay_frames;
+ delay_frames+=10; //threshold to avoid precision stuff
+
+ }
+
+
+
+ //low pass filter
+ if (v.cutoff==0)
+ continue;
+ float auxlp=expf(-2.0*Math_PI*v.cutoff/mix_rate);
+ float c1=1.0-auxlp;
+ float c2=auxlp;
+ AudioFrame h=filter_h[vc];
+ if (v.cutoff>=AudioEffectChorus::MS_CUTOFF_MAX) {
+ c1=1.0; c2=0.0;
+ }
+
+ //vol modifier
+
+ AudioFrame vol_modifier=AudioFrame(base->wet,base->wet) * Math::db2linear(v.level);
+ vol_modifier.l*=CLAMP( 1.0 - v.pan, 0, 1);
+ vol_modifier.r*=CLAMP( 1.0 + v.pan, 0, 1);
+
+
+
+ for (int i=0;i<p_frame_count;i++) {
+
+ /** COMPUTE WAVEFORM **/
+
+ float phase=(float)(local_cycles&AudioEffectChorus::CYCLES_MASK)/(float)(1<<AudioEffectChorus::CYCLES_FRAC);
+
+ float wave_delay=sinf(phase*2.0*Math_PI)*max_depth_frames;
+
+ int wave_delay_frames=lrint(floor(wave_delay));
+ float wave_delay_frac=wave_delay-(float)wave_delay_frames;
+
+ /** COMPUTE RINGBUFFER POS**/
+
+ unsigned int rb_source=local_rb_pos;
+ rb_source-=delay_frames;
+
+ rb_source-=wave_delay_frames;
+
+ /** READ FROM RINGBUFFER, LINEARLY INTERPOLATE */
+
+ AudioFrame val=rb_buff[rb_source&buffer_mask];
+ AudioFrame val_next=rb_buff[(rb_source-1)&buffer_mask];
+
+ val+=(val_next-val)*wave_delay_frac;
+
+ val=val*c1+h*c2;
+ h=val;
+
+ /** MIX VALUE TO OUTPUT **/
+
+ dst_buff[i]+=val*vol_modifier;
+
+ local_cycles+=increment;
+ local_rb_pos++;
+
+ }
+
+ filter_h[vc]=h;
+ cycles[vc]+=Math::fast_ftoi(cycles_to_mix*(double)(1<<AudioEffectChorus::CYCLES_FRAC));
+ }
+
+ buffer_pos+=p_frame_count;
+}
+
+
+Ref<AudioEffectInstance> AudioEffectChorus::instance() {
+
+ Ref<AudioEffectChorusInstance> ins;
+ ins.instance();
+ ins->base=Ref<AudioEffectChorus>(this);
+ for(int i=0;i<4;i++) {
+ ins->filter_h[i]=AudioFrame(0,0);
+ ins->cycles[i]=0;
+ }
+
+ float ring_buffer_max_size=AudioEffectChorus::MAX_DELAY_MS+AudioEffectChorus::MAX_DEPTH_MS+AudioEffectChorus::MAX_WIDTH_MS;
+
+ ring_buffer_max_size*=2; //just to avoid complications
+ ring_buffer_max_size/=1000.0;//convert to seconds
+ ring_buffer_max_size*=AudioServer::get_singleton()->get_mix_rate();
+
+ int ringbuff_size=ring_buffer_max_size;
+
+ int bits=0;
+
+ while(ringbuff_size>0) {
+ bits++;
+ ringbuff_size/=2;
+ }
+
+ ringbuff_size=1<<bits;
+ ins->buffer_mask=ringbuff_size-1;
+ ins->buffer_pos=0;
+ ins->audio_buffer.resize(ringbuff_size);
+ for(int i=0;i<ringbuff_size;i++) {
+ ins->audio_buffer[i]=AudioFrame(0,0);
+ }
+
+ return ins;
+}
+
+void AudioEffectChorus::set_voice_count(int p_voices) {
+
+ ERR_FAIL_COND(p_voices<1 || p_voices>=MAX_VOICES);
+ voice_count=p_voices;
+ _change_notify();
+}
+
+
+int AudioEffectChorus::get_voice_count() const{
+
+ return voice_count;
+}
+
+void AudioEffectChorus::set_voice_delay_ms(int p_voice,float p_delay_ms){
+
+ ERR_FAIL_INDEX(p_voice,MAX_VOICES);
+
+ voice[p_voice].delay=p_delay_ms;
+
+}
+float AudioEffectChorus::get_voice_delay_ms(int p_voice) const{
+
+ ERR_FAIL_INDEX_V(p_voice,MAX_VOICES,0);
+ return voice[p_voice].delay;
+}
+
+void AudioEffectChorus::set_voice_rate_hz(int p_voice,float p_rate_hz){
+ ERR_FAIL_INDEX(p_voice,MAX_VOICES);
+
+ voice[p_voice].rate=p_rate_hz;
+}
+float AudioEffectChorus::get_voice_rate_hz(int p_voice) const{
+
+ ERR_FAIL_INDEX_V(p_voice,MAX_VOICES,0);
+
+ return voice[p_voice].rate;
+}
+
+void AudioEffectChorus::set_voice_depth_ms(int p_voice,float p_depth_ms){
+
+ ERR_FAIL_INDEX(p_voice,MAX_VOICES);
+
+ voice[p_voice].depth=p_depth_ms;
+}
+float AudioEffectChorus::get_voice_depth_ms(int p_voice) const{
+
+ ERR_FAIL_INDEX_V(p_voice,MAX_VOICES,0);
+
+ return voice[p_voice].depth;
+}
+
+void AudioEffectChorus::set_voice_level_db(int p_voice,float p_level_db){
+
+ ERR_FAIL_INDEX(p_voice,MAX_VOICES);
+
+ voice[p_voice].level=p_level_db;
+}
+float AudioEffectChorus::get_voice_level_db(int p_voice) const{
+
+ ERR_FAIL_INDEX_V(p_voice,MAX_VOICES,0);
+
+ return voice[p_voice].level;
+}
+
+
+void AudioEffectChorus::set_voice_cutoff_hz(int p_voice,float p_cutoff_hz){
+
+ ERR_FAIL_INDEX(p_voice,MAX_VOICES);
+
+ voice[p_voice].cutoff=p_cutoff_hz;
+}
+float AudioEffectChorus::get_voice_cutoff_hz(int p_voice) const{
+
+ ERR_FAIL_INDEX_V(p_voice,MAX_VOICES,0);
+
+ return voice[p_voice].cutoff;
+}
+
+void AudioEffectChorus::set_voice_pan(int p_voice,float p_pan){
+
+ ERR_FAIL_INDEX(p_voice,MAX_VOICES);
+
+ voice[p_voice].pan=p_pan;
+}
+float AudioEffectChorus::get_voice_pan(int p_voice) const{
+
+ ERR_FAIL_INDEX_V(p_voice,MAX_VOICES,0);
+
+ return voice[p_voice].pan;
+}
+
+
+void AudioEffectChorus::set_wet(float amount){
+
+
+ wet=amount;
+}
+float AudioEffectChorus::get_wet() const{
+
+ return wet;
+}
+
+void AudioEffectChorus::set_dry(float amount){
+
+ dry=amount;
+
+}
+float AudioEffectChorus::get_dry() const{
+
+ return dry;
+}
+
+void AudioEffectChorus::_validate_property(PropertyInfo& property) const {
+
+ if (property.name.begins_with("voice/")) {
+ int voice_idx = property.name.get_slice("/",1).to_int();
+ if (voice_idx>voice_count) {
+ property.usage=0;
+ }
+ }
+}
+
+
+void AudioEffectChorus::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_voice_count","voices"),&AudioEffectChorus::set_voice_count);
+ ClassDB::bind_method(D_METHOD("get_voice_count"),&AudioEffectChorus::get_voice_count);
+
+
+ ClassDB::bind_method(D_METHOD("set_voice_delay_ms","voice_idx","delay_ms"),&AudioEffectChorus::set_voice_delay_ms);
+ ClassDB::bind_method(D_METHOD("get_voice_delay_ms","voice_idx"),&AudioEffectChorus::get_voice_delay_ms);
+
+ ClassDB::bind_method(D_METHOD("set_voice_rate_hz","voice_idx","rate_hz"),&AudioEffectChorus::set_voice_rate_hz);
+ ClassDB::bind_method(D_METHOD("get_voice_rate_hz","voice_idx"),&AudioEffectChorus::get_voice_rate_hz);
+
+ ClassDB::bind_method(D_METHOD("set_voice_depth_ms","voice_idx","depth_ms"),&AudioEffectChorus::set_voice_depth_ms);
+ ClassDB::bind_method(D_METHOD("get_voice_depth_ms","voice_idx"),&AudioEffectChorus::get_voice_depth_ms);
+
+ ClassDB::bind_method(D_METHOD("set_voice_level_db","voice_idx","level_db"),&AudioEffectChorus::set_voice_level_db);
+ ClassDB::bind_method(D_METHOD("get_voice_level_db","voice_idx"),&AudioEffectChorus::get_voice_level_db);
+
+ ClassDB::bind_method(D_METHOD("set_voice_cutoff_hz","voice_idx","cutoff_hz"),&AudioEffectChorus::set_voice_cutoff_hz);
+ ClassDB::bind_method(D_METHOD("get_voice_cutoff_hz","voice_idx"),&AudioEffectChorus::get_voice_cutoff_hz);
+
+ ClassDB::bind_method(D_METHOD("set_voice_pan","voice_idx","pan"),&AudioEffectChorus::set_voice_pan);
+ ClassDB::bind_method(D_METHOD("get_voice_pan","voice_idx"),&AudioEffectChorus::get_voice_pan);
+
+ ClassDB::bind_method(D_METHOD("set_wet","amount"),&AudioEffectChorus::set_wet);
+ ClassDB::bind_method(D_METHOD("get_wet"),&AudioEffectChorus::get_wet);
+
+ ClassDB::bind_method(D_METHOD("set_dry","amount"),&AudioEffectChorus::set_dry);
+ ClassDB::bind_method(D_METHOD("get_dry"),&AudioEffectChorus::get_dry);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"voice_count",PROPERTY_HINT_RANGE,"1,4,1"),"set_voice_count","get_voice_count");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_dry","get_dry");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"wet",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_wet","get_wet");
+
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_voice_delay_ms","get_voice_delay_ms",0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),"set_voice_rate_hz","get_voice_rate_hz",0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),"set_voice_depth_ms","get_voice_depth_ms",0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),"set_voice_level_db","get_voice_level_db",0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),"set_voice_cutoff_hz","get_voice_cutoff_hz",0);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/1/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_voice_pan","get_voice_pan",0);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_voice_delay_ms","get_voice_delay_ms",1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),"set_voice_rate_hz","get_voice_rate_hz",1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),"set_voice_depth_ms","get_voice_depth_ms",1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),"set_voice_level_db","get_voice_level_db",1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),"set_voice_cutoff_hz","get_voice_cutoff_hz",1);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/2/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_voice_pan","get_voice_pan",1);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_voice_delay_ms","get_voice_delay_ms",2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),"set_voice_rate_hz","get_voice_rate_hz",2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),"set_voice_depth_ms","get_voice_depth_ms",2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),"set_voice_level_db","get_voice_level_db",2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),"set_voice_cutoff_hz","get_voice_cutoff_hz",2);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/3/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_voice_pan","get_voice_pan",2);
+
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/delay_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_voice_delay_ms","get_voice_delay_ms",3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/rate_hz",PROPERTY_HINT_RANGE,"0.1,20,0.1"),"set_voice_rate_hz","get_voice_rate_hz",3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/depth_ms",PROPERTY_HINT_RANGE,"0,20,0.01"),"set_voice_depth_ms","get_voice_depth_ms",3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/level_db",PROPERTY_HINT_RANGE,"-60,24,0.1"),"set_voice_level_db","get_voice_level_db",3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/cutoff_hz",PROPERTY_HINT_RANGE,"1,16000,1"),"set_voice_cutoff_hz","get_voice_cutoff_hz",3);
+ ADD_PROPERTYI(PropertyInfo(Variant::REAL,"voice/4/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_voice_pan","get_voice_pan",3);
+
+}
+
+AudioEffectChorus::AudioEffectChorus()
+{
+ voice_count=2;
+ voice[0].delay=15;
+ voice[1].delay=20;
+ voice[0].rate=0.8;
+ voice[1].rate=1.2;
+ voice[0].depth=2;
+ voice[1].depth=3;
+ voice[0].cutoff=8000;
+ voice[1].cutoff=8000;
+ voice[0].pan=-0.5;
+ voice[1].pan=0.5;
+
+ wet=0.5;
+ dry=1.0;
+}
diff --git a/servers/audio/effects/audio_effect_chorus.h b/servers/audio/effects/audio_effect_chorus.h
new file mode 100644
index 0000000000..4cfba5d61a
--- /dev/null
+++ b/servers/audio/effects/audio_effect_chorus.h
@@ -0,0 +1,115 @@
+#ifndef AUDIOEFFECTCHORUS_H
+#define AUDIOEFFECTCHORUS_H
+
+
+#include "servers/audio/audio_effect.h"
+
+class AudioEffectChorus;
+
+class AudioEffectChorusInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectChorusInstance,AudioEffectInstance)
+friend class AudioEffectChorus;
+ Ref<AudioEffectChorus> base;
+
+ Vector<AudioFrame> audio_buffer;
+ unsigned int buffer_pos;
+ unsigned int buffer_mask;
+
+ AudioFrame filter_h[4];
+ uint64_t cycles[4];
+
+ void _process_chunk(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+};
+
+
+class AudioEffectChorus : public AudioEffect {
+ GDCLASS(AudioEffectChorus,AudioEffect)
+
+friend class AudioEffectChorusInstance;
+public:
+ enum {
+
+ MAX_DELAY_MS=50,
+ MAX_DEPTH_MS=20,
+ MAX_WIDTH_MS=50,
+ MAX_VOICES=4,
+ CYCLES_FRAC=16,
+ CYCLES_MASK=(1<<CYCLES_FRAC)-1,
+ MAX_CHANNELS=4,
+ MS_CUTOFF_MAX=16000
+ };
+
+private:
+
+ struct Voice {
+
+ float delay;
+ float rate;
+ float depth;
+ float level;
+ float cutoff;
+ float pan;
+
+ Voice() {
+
+ delay=12.0;
+ rate=1;
+ depth=0;
+ level=0;
+ cutoff=MS_CUTOFF_MAX;
+ pan=0;
+
+ }
+
+ } voice[MAX_VOICES];
+
+ int voice_count;
+
+ float wet;
+ float dry;
+
+
+protected:
+ void _validate_property(PropertyInfo& property) const;
+
+ static void _bind_methods();
+public:
+
+ void set_voice_count(int p_voices);
+ int get_voice_count() const;
+
+ void set_voice_delay_ms(int p_voice,float p_delay_ms);
+ float get_voice_delay_ms(int p_voice) const;
+
+ void set_voice_rate_hz(int p_voice,float p_rate_hz);
+ float get_voice_rate_hz(int p_voice) const;
+
+ void set_voice_depth_ms(int p_voice,float p_depth_ms);
+ float get_voice_depth_ms(int p_voice) const;
+
+ void set_voice_level_db(int p_voice,float p_level_db);
+ float get_voice_level_db(int p_voice) const;
+
+ void set_voice_cutoff_hz(int p_voice,float p_cutoff_hz);
+ float get_voice_cutoff_hz(int p_voice) const;
+
+ void set_voice_pan(int p_voice,float p_pan);
+ float get_voice_pan(int p_voice) const;
+
+ void set_wet(float amount);
+ float get_wet() const;
+
+ void set_dry(float amount);
+ float get_dry() const;
+
+ Ref<AudioEffectInstance> instance();
+
+ AudioEffectChorus();
+};
+
+#endif // AUDIOEFFECTCHORUS_H
diff --git a/servers/audio/effects/audio_effect_compressor.cpp b/servers/audio/effects/audio_effect_compressor.cpp
new file mode 100644
index 0000000000..d20c5bb4bd
--- /dev/null
+++ b/servers/audio/effects/audio_effect_compressor.cpp
@@ -0,0 +1,227 @@
+#include "audio_effect_compressor.h"
+#include "servers/audio_server.h"
+
+void AudioEffectCompressorInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+
+ float treshold = Math::db2linear(base->treshold);
+ float sample_rate=AudioServer::get_singleton()->get_mix_rate();
+
+ float ratatcoef = exp(-1 / (0.00001f * sample_rate));
+ float ratrelcoef = exp(-1 / (0.5f * sample_rate));
+ float attime = base->attack_us / 1000000.0;
+ float reltime = base->release_ms / 1000.0;
+ float atcoef = exp(-1 / (attime * sample_rate));
+ float relcoef = exp(-1 / (reltime * sample_rate));
+
+ float makeup = Math::db2linear(base->gain);
+
+ float mix = base->mix;
+ float gr_meter_decay = exp(1 / (1 * sample_rate));
+
+ const AudioFrame *src = p_src_frames;
+
+ if (base->sidechain!=StringName() && current_channel!=-1) {
+
+ int bus = AudioServer::get_singleton()->thread_find_bus_index(base->sidechain);
+ if (bus>=0) {
+ src = AudioServer::get_singleton()->thread_get_channel_mix_buffer(bus,current_channel);
+ }
+ }
+
+ for(int i=0;i<p_frame_count;i++) {
+
+ AudioFrame s = src[i];
+ //convert to positive
+ s.l = Math::abs(s.l);
+ s.r = Math::abs(s.r);
+
+ float peak = MAX(s.l,s.r);
+
+ float overdb = 2.08136898f * Math::linear2db(peak/treshold);
+
+ if (overdb<0.0) //we only care about what goes over to compress
+ overdb=0.0;
+
+ if(overdb-rundb>5) // diffeence is too large
+ averatio = 4;
+
+ if(overdb > rundb) {
+ rundb = overdb + atcoef * (rundb - overdb);
+ runratio = averatio + ratatcoef * (runratio - averatio);
+ } else {
+ rundb = overdb + relcoef * (rundb - overdb);
+ runratio = averatio + ratrelcoef * (runratio - averatio);
+ }
+
+ overdb = rundb;
+ averatio = runratio;
+
+ float cratio;
+
+ if(false) { //rato all-in
+ cratio = 12 + averatio;
+ } else {
+ cratio = base->ratio;
+ }
+
+ float gr = -overdb * (cratio-1)/cratio;
+ float grv = Math::db2linear(gr);
+
+ runmax = maxover + relcoef * (runmax - maxover); // highest peak for setting att/rel decays in reltime
+ maxover = runmax;
+
+ if (grv < gr_meter) {
+ gr_meter=grv;
+ } else {
+ gr_meter*=gr_meter_decay;
+ if(gr_meter>1)
+ gr_meter=1;
+ }
+
+
+ p_dst_frames[i] = p_src_frames[i] * grv * makeup * mix + p_src_frames[i] * (1.0-mix);
+
+ }
+
+}
+
+
+Ref<AudioEffectInstance> AudioEffectCompressor::instance() {
+ Ref<AudioEffectCompressorInstance> ins;
+ ins.instance();
+ ins->base=Ref<AudioEffectCompressor>(this);
+ ins->rundb=0;
+ ins->runratio=0;
+ ins->averatio=0;
+ ins->runmax=0;
+ ins->maxover=0;
+ ins->gr_meter=1.0;
+ ins->current_channel=-1;
+ return ins;
+}
+
+
+void AudioEffectCompressor::set_treshold(float p_treshold) {
+
+ treshold=p_treshold;
+}
+
+float AudioEffectCompressor::get_treshold() const {
+
+ return treshold;
+}
+
+void AudioEffectCompressor::set_ratio(float p_ratio) {
+
+ ratio=p_ratio;
+}
+float AudioEffectCompressor::get_ratio() const {
+
+ return ratio;
+}
+
+void AudioEffectCompressor::set_gain(float p_gain) {
+
+ gain=p_gain;
+}
+float AudioEffectCompressor::get_gain() const {
+
+ return gain;
+}
+
+void AudioEffectCompressor::set_attack_us(float p_attack_us) {
+
+ attack_us=p_attack_us;
+}
+float AudioEffectCompressor::get_attack_us() const {
+
+ return attack_us;
+}
+
+void AudioEffectCompressor::set_release_ms(float p_release_ms) {
+
+ release_ms=p_release_ms;
+}
+float AudioEffectCompressor::get_release_ms() const {
+
+ return release_ms;
+}
+
+void AudioEffectCompressor::set_mix(float p_mix) {
+
+ mix=p_mix;
+}
+float AudioEffectCompressor::get_mix() const {
+
+ return mix;
+}
+
+void AudioEffectCompressor::set_sidechain(const StringName& p_sidechain) {
+
+ AudioServer::get_singleton()->lock();
+ sidechain=p_sidechain;
+ AudioServer::get_singleton()->unlock();
+}
+
+StringName AudioEffectCompressor::get_sidechain() const {
+
+ return sidechain;
+}
+
+void AudioEffectCompressor::_validate_property(PropertyInfo& property) const {
+
+ if (property.name=="sidechain") {
+
+ String buses="";
+ for(int i=0;i<AudioServer::get_singleton()->get_bus_count();i++) {
+ buses+=",";
+ buses+=AudioServer::get_singleton()->get_bus_name(i);
+ }
+
+ property.hint_string=buses;
+ }
+}
+
+void AudioEffectCompressor::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_treshold","treshold"),&AudioEffectCompressor::set_treshold);
+ ClassDB::bind_method(D_METHOD("get_treshold"),&AudioEffectCompressor::get_treshold);
+
+ ClassDB::bind_method(D_METHOD("set_ratio","ratio"),&AudioEffectCompressor::set_ratio);
+ ClassDB::bind_method(D_METHOD("get_ratio"),&AudioEffectCompressor::get_ratio);
+
+ ClassDB::bind_method(D_METHOD("set_gain","gain"),&AudioEffectCompressor::set_gain);
+ ClassDB::bind_method(D_METHOD("get_gain"),&AudioEffectCompressor::get_gain);
+
+ ClassDB::bind_method(D_METHOD("set_attack_us","attack_us"),&AudioEffectCompressor::set_attack_us);
+ ClassDB::bind_method(D_METHOD("get_attack_us"),&AudioEffectCompressor::get_attack_us);
+
+ ClassDB::bind_method(D_METHOD("set_release_ms","release_ms"),&AudioEffectCompressor::set_release_ms);
+ ClassDB::bind_method(D_METHOD("get_release_ms"),&AudioEffectCompressor::get_release_ms);
+
+ ClassDB::bind_method(D_METHOD("set_mix","mix"),&AudioEffectCompressor::set_mix);
+ ClassDB::bind_method(D_METHOD("get_mix"),&AudioEffectCompressor::get_mix);
+
+ ClassDB::bind_method(D_METHOD("set_sidechain","sidechain"),&AudioEffectCompressor::set_sidechain);
+ ClassDB::bind_method(D_METHOD("get_sidechain"),&AudioEffectCompressor::get_sidechain);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"treshold",PROPERTY_HINT_RANGE,"-60,0,0.1"),"set_treshold","get_treshold");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ratio",PROPERTY_HINT_RANGE,"1,48,0.1"),"set_ratio","get_ratio");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"gain",PROPERTY_HINT_RANGE,"-20,20,0.1"),"set_gain","get_gain");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"attack_us",PROPERTY_HINT_RANGE,"20,2000,1"),"set_attack_us","get_attack_us");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"release_ms",PROPERTY_HINT_RANGE,"20,2000,1"),"set_release_ms","get_release_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"mix",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_mix","get_mix");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"sidechain",PROPERTY_HINT_ENUM),"set_sidechain","get_sidechain");
+
+}
+
+AudioEffectCompressor::AudioEffectCompressor()
+{
+ treshold=0;
+ ratio=4;
+ gain=0;
+ attack_us=20;
+ release_ms=250;
+ mix=1;
+}
diff --git a/servers/audio/effects/audio_effect_compressor.h b/servers/audio/effects/audio_effect_compressor.h
new file mode 100644
index 0000000000..eb06b3db77
--- /dev/null
+++ b/servers/audio/effects/audio_effect_compressor.h
@@ -0,0 +1,70 @@
+#ifndef AUDIOEFFECTCOMPRESSOR_H
+#define AUDIOEFFECTCOMPRESSOR_H
+
+
+#include "servers/audio/audio_effect.h"
+
+class AudioEffectCompressor;
+
+class AudioEffectCompressorInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectCompressorInstance,AudioEffectInstance)
+friend class AudioEffectCompressor;
+ Ref<AudioEffectCompressor> base;
+
+ float rundb,averatio,runratio,runmax,maxover,gr_meter;
+ int current_channel;
+public:
+
+ void set_current_channel(int p_channel) { current_channel=p_channel; }
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+};
+
+
+class AudioEffectCompressor : public AudioEffect {
+ GDCLASS(AudioEffectCompressor,AudioEffect)
+
+friend class AudioEffectCompressorInstance;
+ float treshold;
+ float ratio;
+ float gain;
+ float attack_us;
+ float release_ms;
+ float mix;
+ StringName sidechain;
+
+
+protected:
+ void _validate_property(PropertyInfo& property) const;
+ static void _bind_methods();
+public:
+
+
+ Ref<AudioEffectInstance> instance();
+
+
+ void set_treshold(float p_treshold);
+ float get_treshold() const;
+
+ void set_ratio(float p_ratio);
+ float get_ratio() const;
+
+ void set_gain(float p_gain);
+ float get_gain() const;
+
+ void set_attack_us(float p_attack_us);
+ float get_attack_us() const;
+
+ void set_release_ms(float p_release_ms);
+ float get_release_ms() const;
+
+ void set_mix(float p_mix);
+ float get_mix() const;
+
+ void set_sidechain(const StringName& p_sidechain);
+ StringName get_sidechain() const;
+
+ AudioEffectCompressor();
+};
+
+#endif // AUDIOEFFECTCOMPRESSOR_H
diff --git a/servers/audio/effects/audio_effect_delay.cpp b/servers/audio/effects/audio_effect_delay.cpp
new file mode 100644
index 0000000000..3d3a956b92
--- /dev/null
+++ b/servers/audio/effects/audio_effect_delay.cpp
@@ -0,0 +1,326 @@
+#include "audio_effect_delay.h"
+#include "servers/audio_server.h"
+#include "math_funcs.h"
+
+void AudioEffectDelayInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+ int todo = p_frame_count;
+
+ while(todo) {
+
+ int to_mix = MIN(todo,256); //can't mix too much
+
+ _process_chunk(p_src_frames,p_dst_frames,to_mix);
+
+ p_src_frames+=to_mix;
+ p_dst_frames+=to_mix;
+
+ todo-=to_mix;
+ }
+}
+
+void AudioEffectDelayInstance::_process_chunk(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+
+
+ float main_level_f=base->dry;
+
+
+ float mix_rate = AudioServer::get_singleton()->get_mix_rate();
+
+ float tap_1_level_f=base->tap_1_active?Math::db2linear(base->tap_1_level):0.0;
+ int tap_1_delay_frames=int((base->tap_1_delay_ms/1000.0)*mix_rate);;
+
+ float tap_2_level_f=base->tap_2_active?Math::db2linear(base->tap_2_level):0.0;
+ int tap_2_delay_frames=int((base->tap_2_delay_ms/1000.0)*mix_rate);;
+
+ float feedback_level_f=base->feedback_active?Math::db2linear(base->feedback_level):0.0;
+ unsigned int feedback_delay_frames=int((base->feedback_delay_ms/1000.0)*mix_rate);;
+
+
+ AudioFrame tap1_vol=AudioFrame(tap_1_level_f,tap_1_level_f);
+
+ tap1_vol.l*=CLAMP( 1.0 - base->tap_1_pan, 0, 1);
+ tap1_vol.r*=CLAMP( 1.0 + base->tap_1_pan, 0, 1);
+
+ AudioFrame tap2_vol=AudioFrame(tap_2_level_f,tap_2_level_f);
+
+ tap2_vol.l*=CLAMP( 1.0 - base->tap_2_pan, 0, 1);
+ tap2_vol.r*=CLAMP( 1.0 + base->tap_2_pan, 0, 1);
+
+ // feedback lowpass here
+ float lpf_c=expf(-2.0*Math_PI*base->feedback_lowpass/mix_rate); // 0 .. 10khz
+ float lpf_ic=1.0-lpf_c;
+
+ const AudioFrame *src=p_src_frames;
+ AudioFrame *dst=p_dst_frames;
+ AudioFrame *rb_buf=ring_buffer.ptr();
+ AudioFrame *fb_buf=feedback_buffer.ptr();
+
+
+ for (int i=0;i<p_frame_count;i++) {
+
+
+ rb_buf[ring_buffer_pos&ring_buffer_mask]=src[i];
+
+ AudioFrame main_val=src[i]*main_level_f;
+ AudioFrame tap_1_val=rb_buf[(ring_buffer_pos-tap_1_delay_frames)&ring_buffer_mask]*tap1_vol;
+ AudioFrame tap_2_val=rb_buf[(ring_buffer_pos-tap_2_delay_frames)&ring_buffer_mask]*tap2_vol;
+
+ AudioFrame out=main_val+tap_1_val+tap_2_val;
+
+ out+=fb_buf[ feedback_buffer_pos ];
+
+ //apply lowpass and feedback gain
+ AudioFrame fb_in=out*feedback_level_f*lpf_ic+h*lpf_c;
+ fb_in.undenormalise(); //avoid denormals
+
+ h=fb_in;
+ fb_buf[ feedback_buffer_pos ]=fb_in;
+
+ dst[i]=out;
+
+ ring_buffer_pos++;
+
+ if ( (++feedback_buffer_pos) >= feedback_delay_frames )
+ feedback_buffer_pos=0;
+ }
+}
+
+
+
+Ref<AudioEffectInstance> AudioEffectDelay::instance() {
+ Ref<AudioEffectDelayInstance> ins;
+ ins.instance();
+ ins->base=Ref<AudioEffectDelay>(this);
+
+ float ring_buffer_max_size=MAX_DELAY_MS+100; //add 100ms of extra room, just in case
+ ring_buffer_max_size/=1000.0;//convert to seconds
+ ring_buffer_max_size*=AudioServer::get_singleton()->get_mix_rate();
+
+ int ringbuff_size=ring_buffer_max_size;
+
+ int bits=0;
+
+ while(ringbuff_size>0) {
+ bits++;
+ ringbuff_size/=2;
+ }
+
+ ringbuff_size=1<<bits;
+ ins->ring_buffer_mask=ringbuff_size-1;
+ ins->ring_buffer_pos=0;
+
+ ins->ring_buffer.resize( ringbuff_size );
+ ins->feedback_buffer.resize( ringbuff_size );
+
+ ins->feedback_buffer_pos=0;
+
+ ins->h=AudioFrame(0,0);
+
+ return ins;
+}
+
+
+void AudioEffectDelay::set_dry(float p_dry) {
+
+ dry=p_dry;
+}
+
+float AudioEffectDelay::get_dry(){
+
+ return dry;
+}
+
+void AudioEffectDelay::set_tap1_active(bool p_active){
+
+ tap_1_active=p_active;
+}
+bool AudioEffectDelay::is_tap1_active() const{
+
+ return tap_1_active;
+}
+
+void AudioEffectDelay::set_tap1_delay_ms(float p_delay_ms){
+
+ tap_1_delay_ms=p_delay_ms;
+}
+float AudioEffectDelay::get_tap1_delay_ms() const{
+
+ return tap_1_delay_ms;
+}
+
+void AudioEffectDelay::set_tap1_level_db(float p_level_db){
+
+ tap_1_level=p_level_db;
+}
+float AudioEffectDelay::get_tap1_level_db() const{
+
+ return tap_1_level;
+}
+
+void AudioEffectDelay::set_tap1_pan(float p_pan){
+
+ tap_1_pan=p_pan;
+}
+float AudioEffectDelay::get_tap1_pan() const{
+
+ return tap_1_pan;
+}
+
+
+void AudioEffectDelay::set_tap2_active(bool p_active){
+
+ tap_2_active=p_active;
+}
+bool AudioEffectDelay::is_tap2_active() const{
+
+ return tap_2_active;
+}
+
+void AudioEffectDelay::set_tap2_delay_ms(float p_delay_ms){
+
+ tap_2_delay_ms=p_delay_ms;
+}
+float AudioEffectDelay::get_tap2_delay_ms() const{
+
+ return tap_2_delay_ms;
+}
+
+void AudioEffectDelay::set_tap2_level_db(float p_level_db){
+
+ tap_2_level=p_level_db;
+}
+float AudioEffectDelay::get_tap2_level_db() const{
+
+ return tap_2_level;
+}
+
+void AudioEffectDelay::set_tap2_pan(float p_pan){
+
+ tap_2_pan=p_pan;
+}
+float AudioEffectDelay::get_tap2_pan() const{
+
+ return tap_2_pan;
+}
+
+void AudioEffectDelay::set_feedback_active(bool p_active){
+
+ feedback_active=p_active;
+}
+bool AudioEffectDelay::is_feedback_active() const{
+
+ return feedback_active;
+}
+
+void AudioEffectDelay::set_feedback_delay_ms(float p_delay_ms){
+
+ feedback_delay_ms=p_delay_ms;
+}
+float AudioEffectDelay::get_feedback_delay_ms() const{
+
+ return feedback_delay_ms;
+}
+
+void AudioEffectDelay::set_feedback_level_db(float p_level_db){
+
+ feedback_level=p_level_db;
+}
+float AudioEffectDelay::get_feedback_level_db() const{
+
+ return feedback_level;
+}
+
+void AudioEffectDelay::set_feedback_lowpass(float p_lowpass){
+
+ feedback_lowpass=p_lowpass;
+}
+float AudioEffectDelay::get_feedback_lowpass() const{
+
+ return feedback_lowpass;
+}
+
+
+void AudioEffectDelay::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_dry","amount"),&AudioEffectDelay::set_dry);
+ ClassDB::bind_method(D_METHOD("get_dry"),&AudioEffectDelay::get_dry);
+
+ ClassDB::bind_method(D_METHOD("set_tap1_active","amount"),&AudioEffectDelay::set_tap1_active);
+ ClassDB::bind_method(D_METHOD("is_tap1_active"),&AudioEffectDelay::is_tap1_active);
+
+ ClassDB::bind_method(D_METHOD("set_tap1_delay_ms","amount"),&AudioEffectDelay::set_tap1_delay_ms);
+ ClassDB::bind_method(D_METHOD("get_tap1_delay_ms"),&AudioEffectDelay::get_tap1_delay_ms);
+
+ ClassDB::bind_method(D_METHOD("set_tap1_level_db","amount"),&AudioEffectDelay::set_tap1_level_db);
+ ClassDB::bind_method(D_METHOD("get_tap1_level_db"),&AudioEffectDelay::get_tap1_level_db);
+
+ ClassDB::bind_method(D_METHOD("set_tap1_pan","amount"),&AudioEffectDelay::set_tap1_pan);
+ ClassDB::bind_method(D_METHOD("get_tap1_pan"),&AudioEffectDelay::get_tap1_pan);
+
+ ClassDB::bind_method(D_METHOD("set_tap2_active","amount"),&AudioEffectDelay::set_tap2_active);
+ ClassDB::bind_method(D_METHOD("is_tap2_active"),&AudioEffectDelay::is_tap2_active);
+
+ ClassDB::bind_method(D_METHOD("set_tap2_delay_ms","amount"),&AudioEffectDelay::set_tap2_delay_ms);
+ ClassDB::bind_method(D_METHOD("get_tap2_delay_ms"),&AudioEffectDelay::get_tap2_delay_ms);
+
+ ClassDB::bind_method(D_METHOD("set_tap2_level_db","amount"),&AudioEffectDelay::set_tap2_level_db);
+ ClassDB::bind_method(D_METHOD("get_tap2_level_db"),&AudioEffectDelay::get_tap2_level_db);
+
+ ClassDB::bind_method(D_METHOD("set_tap2_pan","amount"),&AudioEffectDelay::set_tap2_pan);
+ ClassDB::bind_method(D_METHOD("get_tap2_pan"),&AudioEffectDelay::get_tap2_pan);
+
+
+ ClassDB::bind_method(D_METHOD("set_feedback_active","amount"),&AudioEffectDelay::set_feedback_active);
+ ClassDB::bind_method(D_METHOD("is_feedback_active"),&AudioEffectDelay::is_feedback_active);
+
+ ClassDB::bind_method(D_METHOD("set_feedback_delay_ms","amount"),&AudioEffectDelay::set_feedback_delay_ms);
+ ClassDB::bind_method(D_METHOD("get_feedback_delay_ms"),&AudioEffectDelay::get_feedback_delay_ms);
+
+ ClassDB::bind_method(D_METHOD("set_feedback_level_db","amount"),&AudioEffectDelay::set_feedback_level_db);
+ ClassDB::bind_method(D_METHOD("get_feedback_level_db"),&AudioEffectDelay::get_feedback_level_db);
+
+ ClassDB::bind_method(D_METHOD("set_feedback_lowpass","amount"),&AudioEffectDelay::set_feedback_lowpass);
+ ClassDB::bind_method(D_METHOD("get_feedback_lowpass"),&AudioEffectDelay::get_feedback_lowpass);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_dry","get_dry");
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"tap1/active"),"set_tap1_active","is_tap1_active");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),"set_tap1_delay_ms","get_tap1_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),"set_tap1_level_db","get_tap1_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap1/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_tap1_pan","get_tap1_pan");
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"tap2/active"),"set_tap2_active","is_tap2_active");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),"set_tap2_delay_ms","get_tap2_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),"set_tap2_level_db","get_tap2_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"tap2/pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_tap2_pan","get_tap2_pan");
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL,"feedback/active"),"set_feedback_active","is_feedback_active");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/delay_ms",PROPERTY_HINT_RANGE,"0,1500,1"),"set_feedback_delay_ms","get_feedback_delay_ms");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/level_db",PROPERTY_HINT_RANGE,"-60,0,0.01"),"set_feedback_level_db","get_feedback_level_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback/lowpass",PROPERTY_HINT_RANGE,"1,16000,1"),"set_feedback_lowpass","get_feedback_lowpass");
+
+
+}
+
+AudioEffectDelay::AudioEffectDelay()
+{
+ tap_1_active=true;
+ tap_1_delay_ms=250;
+ tap_1_level=-6;
+ tap_1_pan=0.2;
+
+ tap_2_active=true;
+ tap_2_delay_ms=500;
+ tap_2_level=-12;
+ tap_2_pan=-0.4;
+
+ feedback_active=false;
+ feedback_delay_ms=340;
+ feedback_level=-6;
+ feedback_lowpass=16000;
+
+ dry=1.0;
+
+}
diff --git a/servers/audio/effects/audio_effect_delay.h b/servers/audio/effects/audio_effect_delay.h
new file mode 100644
index 0000000000..645561138b
--- /dev/null
+++ b/servers/audio/effects/audio_effect_delay.h
@@ -0,0 +1,112 @@
+#ifndef AUDIOEFFECTECHO_H
+#define AUDIOEFFECTECHO_H
+
+#include "servers/audio/audio_effect.h"
+
+class AudioEffectDelay;
+
+class AudioEffectDelayInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectDelayInstance,AudioEffectInstance)
+friend class AudioEffectDelay;
+ Ref<AudioEffectDelay> base;
+
+ Vector<AudioFrame> ring_buffer;
+
+ unsigned int ring_buffer_pos;
+ unsigned int ring_buffer_mask;
+
+ /* feedback buffer */
+ Vector<AudioFrame> feedback_buffer;
+
+ unsigned int feedback_buffer_pos;
+
+ AudioFrame h;
+ void _process_chunk(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+};
+
+
+class AudioEffectDelay : public AudioEffect {
+ GDCLASS(AudioEffectDelay,AudioEffect)
+
+friend class AudioEffectDelayInstance;
+ enum {
+
+ MAX_DELAY_MS=3000,
+ MAX_TAPS=2
+ };
+
+ float dry;
+
+ bool tap_1_active;
+ float tap_1_delay_ms;
+ float tap_1_level;
+ float tap_1_pan;
+
+ bool tap_2_active;
+ float tap_2_delay_ms;
+ float tap_2_level;
+ float tap_2_pan;
+
+ bool feedback_active;
+ float feedback_delay_ms;
+ float feedback_level;
+ float feedback_lowpass;
+
+
+
+protected:
+
+ static void _bind_methods();
+public:
+
+ void set_dry(float p_dry);
+ float get_dry();
+
+ void set_tap1_active(bool p_active);
+ bool is_tap1_active() const;
+
+ void set_tap1_delay_ms(float p_delay_ms);
+ float get_tap1_delay_ms() const;
+
+ void set_tap1_level_db(float p_level_db);
+ float get_tap1_level_db() const;
+
+ void set_tap1_pan(float p_pan);
+ float get_tap1_pan() const;
+
+ void set_tap2_active(bool p_active);
+ bool is_tap2_active() const;
+
+ void set_tap2_delay_ms(float p_delay_ms);
+ float get_tap2_delay_ms() const;
+
+ void set_tap2_level_db(float p_level_db);
+ float get_tap2_level_db() const;
+
+ void set_tap2_pan(float p_pan);
+ float get_tap2_pan() const;
+
+ void set_feedback_active(bool p_active);
+ bool is_feedback_active() const;
+
+ void set_feedback_delay_ms(float p_delay_ms);
+ float get_feedback_delay_ms() const;
+
+ void set_feedback_level_db(float p_level_db);
+ float get_feedback_level_db() const;
+
+ void set_feedback_lowpass(float p_lowpass);
+ float get_feedback_lowpass() const;
+
+ Ref<AudioEffectInstance> instance();
+
+ AudioEffectDelay();
+};
+
+
+#endif // AUDIOEFFECTECHO_H
diff --git a/servers/audio/effects/audio_effect_distortion.cpp b/servers/audio/effects/audio_effect_distortion.cpp
new file mode 100644
index 0000000000..d0f526fe24
--- /dev/null
+++ b/servers/audio/effects/audio_effect_distortion.cpp
@@ -0,0 +1,171 @@
+#include "audio_effect_distortion.h"
+#include "servers/audio_server.h"
+#include "math_funcs.h"
+
+
+
+void AudioEffectDistortionInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+ const float *src = (const float*)p_src_frames;
+ float *dst = (float*)p_dst_frames;
+
+ //float lpf_c=expf(-2.0*Math_PI*keep_hf_hz.get()/(mix_rate*(float)OVERSAMPLE));
+ float lpf_c=expf(-2.0*Math_PI*base->keep_hf_hz/(AudioServer::get_singleton()->get_mix_rate()));
+ float lpf_ic=1.0-lpf_c;
+
+ float drive_f=base->drive;
+ float pregain_f=Math::db2linear(base->pre_gain);
+ float postgain_f=Math::db2linear(base->post_gain);
+
+ float atan_mult=pow(10,drive_f*drive_f*3.0)-1.0+0.001;
+ float atan_div=1.0/(atanf(atan_mult)*(1.0+drive_f*8));
+
+ float lofi_mult=powf(2.0,2.0+(1.0-drive_f)*14); //goes from 16 to 2 bits
+
+ for (int i=0;i<p_frame_count*2;i++) {
+
+ float out=undenormalise(src[i]*lpf_ic+lpf_c*h[i&1]);
+ h[i&1]=out;
+ float a=out;
+ float ha=src[i]-out; //high freqs
+ a*=pregain_f;
+
+ switch (base->mode) {
+
+ case AudioEffectDistortion::MODE_CLIP: {
+
+ a=powf(a,1.0001-drive_f);
+ if (a>1.0)
+ a=1.0;
+ else if (a<(-1.0))
+ a=-1.0;
+
+ } break;
+ case AudioEffectDistortion::MODE_ATAN: {
+
+
+ a=atanf(a*atan_mult)*atan_div;
+
+ } break;
+ case AudioEffectDistortion::MODE_LOFI: {
+
+ a = floorf(a*lofi_mult+0.5)/lofi_mult;
+
+ } break;
+ case AudioEffectDistortion::MODE_OVERDRIVE: {
+
+
+ const double x = a * 0.686306;
+ const double z = 1 + exp (sqrt (fabs (x)) * -0.75);
+ a = (expf(x) - expf(-x * z)) / (expf(x) + expf(-x));
+ } break;
+ case AudioEffectDistortion::MODE_WAVESHAPE: {
+ float x = a;
+ float k= 2*drive_f/(1.00001-drive_f);
+
+ a = (1.0+k)*x/(1.0+k*fabsf(x));
+
+
+ } break;
+ }
+
+ dst[i]=a*postgain_f+ha;
+
+ }
+
+
+}
+
+
+Ref<AudioEffectInstance> AudioEffectDistortion::instance() {
+ Ref<AudioEffectDistortionInstance> ins;
+ ins.instance();
+ ins->base=Ref<AudioEffectDistortion>(this);
+ ins->h[0]=0;
+ ins->h[1]=0;
+
+ return ins;
+}
+
+
+void AudioEffectDistortion::set_mode(Mode p_mode) {
+
+ mode=p_mode;
+}
+
+AudioEffectDistortion::Mode AudioEffectDistortion::get_mode() const{
+
+ return mode;
+}
+
+void AudioEffectDistortion::set_pre_gain(float p_pre_gain){
+
+ pre_gain=p_pre_gain;
+}
+float AudioEffectDistortion::get_pre_gain() const{
+
+ return pre_gain;
+}
+
+void AudioEffectDistortion::set_keep_hf_hz(float p_keep_hf_hz){
+
+ keep_hf_hz=p_keep_hf_hz;
+}
+float AudioEffectDistortion::get_keep_hf_hz() const{
+
+ return keep_hf_hz;
+}
+
+void AudioEffectDistortion::set_drive(float p_drive){
+
+ drive=p_drive;
+}
+float AudioEffectDistortion::get_drive() const{
+
+ return drive;
+}
+
+void AudioEffectDistortion::set_post_gain(float p_post_gain){
+
+ post_gain=p_post_gain;
+}
+float AudioEffectDistortion::get_post_gain() const{
+
+ return post_gain;
+}
+
+
+void AudioEffectDistortion::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_mode","mode"),&AudioEffectDistortion::set_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"),&AudioEffectDistortion::get_mode);
+
+ ClassDB::bind_method(D_METHOD("set_pre_gain","pre_gain"),&AudioEffectDistortion::set_pre_gain);
+ ClassDB::bind_method(D_METHOD("get_pre_gain"),&AudioEffectDistortion::get_pre_gain);
+
+ ClassDB::bind_method(D_METHOD("set_keep_hf_hz","keep_hf_hz"),&AudioEffectDistortion::set_keep_hf_hz);
+ ClassDB::bind_method(D_METHOD("get_keep_hf_hz"),&AudioEffectDistortion::get_keep_hf_hz);
+
+ ClassDB::bind_method(D_METHOD("set_drive","drive"),&AudioEffectDistortion::set_drive);
+ ClassDB::bind_method(D_METHOD("get_drive"),&AudioEffectDistortion::get_drive);
+
+
+ ClassDB::bind_method(D_METHOD("set_post_gain","post_gain"),&AudioEffectDistortion::set_post_gain);
+ ClassDB::bind_method(D_METHOD("get_post_gain"),&AudioEffectDistortion::get_post_gain);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"mode",PROPERTY_HINT_ENUM,"Clip,ATan,LoFi,Overdrive,WaveShape"),"set_mode","get_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"pre_gain",PROPERTY_HINT_RANGE,"-60,60,0.01"),"set_pre_gain","get_pre_gain");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"keep_hf_hz",PROPERTY_HINT_RANGE,"1,20000,1"),"set_keep_hf_hz","get_keep_hf_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"drive",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_drive","get_drive");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"post_gain",PROPERTY_HINT_RANGE,"-80,24,0.01"),"set_post_gain","get_post_gain");
+}
+
+AudioEffectDistortion::AudioEffectDistortion()
+{
+ mode=MODE_CLIP;
+ pre_gain=0;
+ post_gain=0;
+ keep_hf_hz=16000;
+ drive=0;
+}
+
diff --git a/servers/audio/effects/audio_effect_distortion.h b/servers/audio/effects/audio_effect_distortion.h
new file mode 100644
index 0000000000..1d2433faeb
--- /dev/null
+++ b/servers/audio/effects/audio_effect_distortion.h
@@ -0,0 +1,69 @@
+#ifndef AUDIOEFFECTDISTORTION_H
+#define AUDIOEFFECTDISTORTION_H
+
+#include "servers/audio/audio_effect.h"
+
+class AudioEffectDistortion;
+
+class AudioEffectDistortionInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectDistortionInstance,AudioEffectInstance)
+friend class AudioEffectDistortion;
+ Ref<AudioEffectDistortion> base;
+ float h[2];
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+};
+
+
+class AudioEffectDistortion : public AudioEffect {
+ GDCLASS(AudioEffectDistortion,AudioEffect)
+public:
+ enum Mode {
+ MODE_CLIP,
+ MODE_ATAN,
+ MODE_LOFI,
+ MODE_OVERDRIVE,
+ MODE_WAVESHAPE,
+ };
+
+friend class AudioEffectDistortionInstance;
+ Mode mode;
+ float pre_gain;
+ float post_gain;
+ float keep_hf_hz;
+ float drive;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+
+ Ref<AudioEffectInstance> instance();
+
+
+ void set_mode(Mode p_mode);
+ Mode get_mode() const;
+
+ void set_pre_gain(float pre_gain);
+ float get_pre_gain() const;
+
+ void set_keep_hf_hz(float keep_hf_hz);
+ float get_keep_hf_hz() const;
+
+ void set_drive(float drive);
+ float get_drive() const;
+
+ void set_post_gain(float post_gain);
+ float get_post_gain() const;
+
+
+
+ AudioEffectDistortion();
+};
+
+VARIANT_ENUM_CAST( AudioEffectDistortion::Mode )
+
+#endif // AUDIOEFFECTDISTORTION_H
diff --git a/servers/audio/effects/audio_effect_eq.cpp b/servers/audio/effects/audio_effect_eq.cpp
new file mode 100644
index 0000000000..5f42f2826f
--- /dev/null
+++ b/servers/audio/effects/audio_effect_eq.cpp
@@ -0,0 +1,122 @@
+#include "audio_effect_eq.h"
+#include "servers/audio_server.h"
+
+
+void AudioEffectEQInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+ int band_count = bands[0].size();
+ EQ::BandProcess *proc_l = bands[0].ptr();
+ EQ::BandProcess *proc_r = bands[1].ptr();
+ float *bgain = gains.ptr();
+ for(int i=0;i<band_count;i++) {
+ bgain[i]=Math::db2linear(base->gain[i]);
+ }
+
+
+ for(int i=0;i<p_frame_count;i++) {
+
+ AudioFrame src = p_src_frames[i];
+ AudioFrame dst = AudioFrame(0,0);
+
+ for(int j=0;j<band_count;j++) {
+
+ float l = src.l;
+ float r = src.r;
+
+ proc_l[j].process_one(l);
+ proc_r[j].process_one(r);
+
+ dst.l+=l * bgain[j];
+ dst.r+=r * bgain[j];
+ }
+
+ p_dst_frames[i]=dst;
+ }
+
+}
+
+
+Ref<AudioEffectInstance> AudioEffectEQ::instance() {
+ Ref<AudioEffectEQInstance> ins;
+ ins.instance();
+ ins->base=Ref<AudioEffectEQ>(this);
+ ins->gains.resize(eq.get_band_count());
+ for(int i=0;i<2;i++) {
+ ins->bands[i].resize(eq.get_band_count());
+ for(int j=0;j<ins->bands[i].size();j++) {
+ ins->bands[i][j]=eq.get_band_processor(j);
+ }
+ }
+
+ return ins;
+}
+
+void AudioEffectEQ::set_band_gain_db(int p_band,float p_volume) {
+ ERR_FAIL_INDEX(p_band,gain.size());
+ gain[p_band]=p_volume;
+}
+
+float AudioEffectEQ::get_band_gain_db(int p_band) const {
+ ERR_FAIL_INDEX_V(p_band,gain.size(),0);
+
+ return gain[p_band];
+}
+int AudioEffectEQ::get_band_count() const {
+ return gain.size();
+}
+
+bool AudioEffectEQ::_set(const StringName& p_name, const Variant& p_value) {
+
+ const Map<StringName,int>::Element *E=prop_band_map.find(p_name);
+ if (E) {
+ set_band_gain_db(E->get(),p_value);
+ return true;
+ }
+
+ return false;
+}
+
+bool AudioEffectEQ::_get(const StringName& p_name,Variant &r_ret) const{
+
+ const Map<StringName,int>::Element *E=prop_band_map.find(p_name);
+ if (E) {
+ r_ret=get_band_gain_db(E->get());
+ return true;
+ }
+
+ return false;
+
+}
+
+void AudioEffectEQ::_get_property_list( List<PropertyInfo> *p_list) const{
+
+ for(int i=0;i<band_names.size();i++) {
+
+ p_list->push_back(PropertyInfo(Variant::REAL,band_names[i],PROPERTY_HINT_RANGE,"-60,24,0.1"));
+ }
+}
+
+
+
+void AudioEffectEQ::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_band_gain_db","band_idx","volume_db"),&AudioEffectEQ::set_band_gain_db);
+ ClassDB::bind_method(D_METHOD("get_band_gain_db","band_idx"),&AudioEffectEQ::get_band_gain_db);
+ ClassDB::bind_method(D_METHOD("get_band_count"),&AudioEffectEQ::get_band_count);
+
+}
+
+AudioEffectEQ::AudioEffectEQ(EQ::Preset p_preset)
+{
+
+
+ eq.set_mix_rate(AudioServer::get_singleton()->get_mix_rate());
+ eq.set_preset_band_mode(p_preset);
+ gain.resize(eq.get_band_count());
+ for(int i=0;i<gain.size();i++) {
+ gain[i]=0.0;
+ String name = "band_db/"+itos(eq.get_band_frequency(i))+"_hz";
+ prop_band_map[name]=i;
+ band_names.push_back(name);
+ }
+}
diff --git a/servers/audio/effects/audio_effect_eq.h b/servers/audio/effects/audio_effect_eq.h
new file mode 100644
index 0000000000..3fcc2c0056
--- /dev/null
+++ b/servers/audio/effects/audio_effect_eq.h
@@ -0,0 +1,72 @@
+#ifndef AUDIOEFFECTEQ_H
+#define AUDIOEFFECTEQ_H
+
+
+#include "servers/audio/audio_effect.h"
+#include "servers/audio/effects/eq.h"
+
+class AudioEffectEQ;
+
+class AudioEffectEQInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectEQInstance,AudioEffectInstance)
+friend class AudioEffectEQ;
+ Ref<AudioEffectEQ> base;
+
+ Vector<EQ::BandProcess> bands[2];
+ Vector<float> gains;
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+};
+
+
+class AudioEffectEQ : public AudioEffect {
+ GDCLASS(AudioEffectEQ,AudioEffect)
+
+friend class AudioEffectEQInstance;
+
+ EQ eq;
+ Vector<float> gain;
+ Map<StringName,int> prop_band_map;
+ Vector<String> band_names;
+
+protected:
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List<PropertyInfo> *p_list) const;
+
+
+
+ static void _bind_methods();
+public:
+
+
+ Ref<AudioEffectInstance> instance();
+ void set_band_gain_db(int p_band,float p_volume);
+ float get_band_gain_db(int p_band) const;
+ int get_band_count() const;
+
+ AudioEffectEQ(EQ::Preset p_preset=EQ::PRESET_6_BANDS);
+};
+
+
+class AudioEffectEQ6 : public AudioEffectEQ {
+ GDCLASS(AudioEffectEQ6,AudioEffectEQ)
+public:
+ AudioEffectEQ6() : AudioEffectEQ(EQ::PRESET_6_BANDS) {}
+};
+
+class AudioEffectEQ10 : public AudioEffectEQ {
+ GDCLASS(AudioEffectEQ10,AudioEffectEQ)
+public:
+ AudioEffectEQ10() : AudioEffectEQ(EQ::PRESET_10_BANDS) {}
+};
+
+class AudioEffectEQ21 : public AudioEffectEQ {
+ GDCLASS(AudioEffectEQ21,AudioEffectEQ)
+public:
+ AudioEffectEQ21() : AudioEffectEQ(EQ::PRESET_21_BANDS) {}
+};
+
+#endif // AUDIOEFFECTEQ_H
diff --git a/servers/audio/effects/audio_effect_filter.cpp b/servers/audio/effects/audio_effect_filter.cpp
new file mode 100644
index 0000000000..e7af7ca9c0
--- /dev/null
+++ b/servers/audio/effects/audio_effect_filter.cpp
@@ -0,0 +1,151 @@
+#include "audio_effect_filter.h"
+#include "servers/audio_server.h"
+
+template<int S>
+void AudioEffectFilterInstance::_process_filter(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+ for(int i=0;i<p_frame_count;i++) {
+ float f = p_src_frames[i].l;
+ filter_process[0][0].process_one(f);
+ if (S>1)
+ filter_process[0][1].process_one(f);
+ if (S>2)
+ filter_process[0][2].process_one(f);
+ if (S>3)
+ filter_process[0][3].process_one(f);
+
+ p_dst_frames[i].l=f;
+ }
+
+ for(int i=0;i<p_frame_count;i++) {
+ float f = p_src_frames[i].r;
+ filter_process[1][0].process_one(f);
+ if (S>1)
+ filter_process[1][1].process_one(f);
+ if (S>2)
+ filter_process[1][2].process_one(f);
+ if (S>3)
+ filter_process[1][3].process_one(f);
+
+ p_dst_frames[i].r=f;
+ }
+
+}
+
+void AudioEffectFilterInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+ filter.set_cutoff(base->cutoff);
+ filter.set_gain(base->gain);
+ filter.set_resonance(base->resonance);
+ filter.set_mode(base->mode);
+ int stages = int(base->db)+1;
+ filter.set_stages(stages);
+ filter.set_sampling_rate(AudioServer::get_singleton()->get_mix_rate());
+
+ for(int i=0;i<2;i++) {
+ for(int j=0;j<4;j++) {
+ filter_process[i][j].update_coeffs();
+ }
+ }
+
+
+ if (stages==1) {
+ _process_filter<1>(p_src_frames,p_dst_frames,p_frame_count);
+ } else if (stages==2) {
+ _process_filter<2>(p_src_frames,p_dst_frames,p_frame_count);
+ } else if (stages==3) {
+ _process_filter<3>(p_src_frames,p_dst_frames,p_frame_count);
+ } else if (stages==4) {
+ _process_filter<4>(p_src_frames,p_dst_frames,p_frame_count);
+ }
+
+}
+
+
+AudioEffectFilterInstance::AudioEffectFilterInstance() {
+
+ for(int i=0;i<2;i++) {
+ for(int j=0;j<4;j++) {
+ filter_process[i][j].set_filter(&filter);
+ }
+ }
+
+}
+
+
+Ref<AudioEffectInstance> AudioEffectFilter::instance() {
+ Ref<AudioEffectFilterInstance> ins;
+ ins.instance();
+ ins->base=Ref<AudioEffectFilter>(this);
+
+ return ins;
+}
+
+void AudioEffectFilter::set_cutoff(float p_freq) {
+
+ cutoff=p_freq;
+}
+
+float AudioEffectFilter::get_cutoff() const{
+
+ return cutoff;
+}
+
+void AudioEffectFilter::set_resonance(float p_amount){
+
+ resonance=p_amount;
+}
+float AudioEffectFilter::get_resonance() const{
+
+ return resonance;
+}
+
+void AudioEffectFilter::set_gain(float p_amount){
+
+ gain=p_amount;
+}
+float AudioEffectFilter::get_gain() const {
+
+ return gain;
+}
+
+
+
+void AudioEffectFilter::set_db(FilterDB p_db) {
+ db=p_db;
+}
+
+AudioEffectFilter::FilterDB AudioEffectFilter::get_db() const {
+
+ return db;
+}
+
+void AudioEffectFilter::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_cutoff","freq"),&AudioEffectFilter::set_cutoff);
+ ClassDB::bind_method(D_METHOD("get_cutoff"),&AudioEffectFilter::get_cutoff);
+
+ ClassDB::bind_method(D_METHOD("set_resonance","amount"),&AudioEffectFilter::set_resonance);
+ ClassDB::bind_method(D_METHOD("get_resonance"),&AudioEffectFilter::get_resonance);
+
+ ClassDB::bind_method(D_METHOD("set_gain","amount"),&AudioEffectFilter::set_gain);
+ ClassDB::bind_method(D_METHOD("get_gain"),&AudioEffectFilter::get_gain);
+
+ ClassDB::bind_method(D_METHOD("set_db","amount"),&AudioEffectFilter::set_db);
+ ClassDB::bind_method(D_METHOD("get_db"),&AudioEffectFilter::get_db);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"cutoff_hz",PROPERTY_HINT_RANGE,"1,40000,0.1"),"set_cutoff","get_cutoff");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"resonance",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_resonance","get_resonance");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"gain",PROPERTY_HINT_RANGE,"0,4,0.01"),"set_gain","get_gain");
+ ADD_PROPERTY(PropertyInfo(Variant::INT,"dB",PROPERTY_HINT_ENUM,"6db,12db,18db,24db"),"set_db","get_db");
+}
+
+AudioEffectFilter::AudioEffectFilter(AudioFilterSW::Mode p_mode)
+{
+
+ mode=p_mode;
+ cutoff=2000;
+ resonance=0.5;
+ gain=1.0;
+ db=FILTER_6DB;
+}
diff --git a/servers/audio/effects/audio_effect_filter.h b/servers/audio/effects/audio_effect_filter.h
new file mode 100644
index 0000000000..d0bc7a446a
--- /dev/null
+++ b/servers/audio/effects/audio_effect_filter.h
@@ -0,0 +1,125 @@
+#ifndef AUDIOEFFECTFILTER_H
+#define AUDIOEFFECTFILTER_H
+
+#include "servers/audio/audio_effect.h"
+#include "servers/audio/audio_filter_sw.h"
+
+class AudioEffectFilter;
+
+class AudioEffectFilterInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectFilterInstance,AudioEffectInstance)
+friend class AudioEffectFilter;
+
+ Ref<AudioEffectFilter> base;
+
+ AudioFilterSW filter;
+ AudioFilterSW::Processor filter_process[2][4];
+
+ template<int S>
+ void _process_filter(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+ AudioEffectFilterInstance();
+};
+
+
+class AudioEffectFilter : public AudioEffect {
+ GDCLASS(AudioEffectFilter,AudioEffect)
+public:
+
+ enum FilterDB {
+ FILTER_6DB,
+ FILTER_12DB,
+ FILTER_18DB,
+ FILTER_24DB,
+ };
+ friend class AudioEffectFilterInstance;
+
+ AudioFilterSW::Mode mode;
+ float cutoff;
+ float resonance;
+ float gain;
+ FilterDB db;
+
+
+protected:
+
+
+ static void _bind_methods();
+public:
+
+ void set_cutoff(float p_freq);
+ float get_cutoff() const;
+
+ void set_resonance(float p_amount);
+ float get_resonance() const;
+
+ void set_gain(float p_amount);
+ float get_gain() const;
+
+ void set_db(FilterDB p_db);
+ FilterDB get_db() const;
+
+ Ref<AudioEffectInstance> instance();
+
+ AudioEffectFilter(AudioFilterSW::Mode p_mode=AudioFilterSW::LOWPASS);
+};
+
+VARIANT_ENUM_CAST(AudioEffectFilter::FilterDB)
+
+class AudioEffectLowPassFilter : public AudioEffectFilter {
+ GDCLASS(AudioEffectLowPassFilter,AudioEffectFilter)
+public:
+
+ AudioEffectLowPassFilter() : AudioEffectFilter(AudioFilterSW::LOWPASS) {}
+};
+
+class AudioEffectHighPassFilter : public AudioEffectFilter {
+ GDCLASS(AudioEffectHighPassFilter,AudioEffectFilter)
+public:
+
+ AudioEffectHighPassFilter() : AudioEffectFilter(AudioFilterSW::HIGHPASS) {}
+};
+
+class AudioEffectBandPassFilter : public AudioEffectFilter {
+ GDCLASS(AudioEffectBandPassFilter,AudioEffectFilter)
+public:
+
+ AudioEffectBandPassFilter() : AudioEffectFilter(AudioFilterSW::BANDPASS) {}
+};
+
+class AudioEffectNotchFilter : public AudioEffectFilter {
+ GDCLASS(AudioEffectNotchFilter,AudioEffectFilter)
+public:
+
+ AudioEffectNotchFilter() : AudioEffectFilter(AudioFilterSW::NOTCH) {}
+};
+
+class AudioEffectBandLimitFilter : public AudioEffectFilter {
+ GDCLASS(AudioEffectBandLimitFilter,AudioEffectFilter)
+public:
+
+ AudioEffectBandLimitFilter() : AudioEffectFilter(AudioFilterSW::BANDLIMIT) {}
+};
+
+
+class AudioEffectLowShelfFilter : public AudioEffectFilter {
+ GDCLASS(AudioEffectLowShelfFilter,AudioEffectFilter)
+public:
+
+ AudioEffectLowShelfFilter() : AudioEffectFilter(AudioFilterSW::LOWSHELF) {}
+};
+
+
+class AudioEffectHighShelfFilter : public AudioEffectFilter {
+ GDCLASS(AudioEffectHighShelfFilter,AudioEffectFilter)
+public:
+
+ AudioEffectHighShelfFilter() : AudioEffectFilter(AudioFilterSW::HIGHSHELF) {}
+};
+
+
+
+#endif // AUDIOEFFECTFILTER_H
diff --git a/servers/audio/effects/audio_effect_limiter.cpp b/servers/audio/effects/audio_effect_limiter.cpp
new file mode 100644
index 0000000000..bce1e0a0df
--- /dev/null
+++ b/servers/audio/effects/audio_effect_limiter.cpp
@@ -0,0 +1,124 @@
+#include "audio_effect_limiter.h"
+
+void AudioEffectLimiterInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+ float thresh = Math::db2linear(base->treshold);
+ float threshdb = base->treshold;
+ float ceiling = Math::db2linear(base->ceiling);
+ float ceildb = base->ceiling;
+ float makeup = Math::db2linear(ceildb - threshdb);
+ float makeupdb = ceildb - threshdb;
+ float sc = -base->soft_clip;
+ float scv = Math::db2linear(sc);
+ float sccomp = Math::db2linear(-sc);
+ float peakdb = ceildb + 25;
+ float peaklvl = Math::db2linear(peakdb);
+ float scratio = base->soft_clip_ratio;
+ float scmult = Math::abs((ceildb - sc) / (peakdb - sc));
+
+ for(int i=0;i<p_frame_count;i++) {
+
+ float spl0 = p_src_frames[i].l;
+ float spl1 = p_src_frames[i].r;
+ spl0 = spl0 * makeup;
+ spl1 = spl1 * makeup;
+ float sign0 = (spl0 < 0.0 ? -1.0 : 1.0 );
+ float sign1 = (spl1 < 0.0 ? -1.0 : 1.0 );
+ float abs0 = Math::abs(spl0);
+ float abs1 = Math::abs(spl1);
+ float overdb0 = Math::linear2db(abs0) - ceildb;
+ float overdb1 = Math::linear2db(abs1) - ceildb;
+
+ if (abs0 > scv)
+ {
+ spl0 = sign0 * (scv + Math::db2linear(overdb0 * scmult));
+ }
+ if (abs1 > scv)
+ {
+ spl1 = sign1 * (scv + Math::db2linear(overdb1 * scmult));
+ }
+
+ spl0 = MIN(ceiling, Math::abs(spl0)) * (spl0 < 0.0 ? -1.0 : 1.0);
+ spl1 = MIN(ceiling, Math::abs(spl1)) * (spl1 < 0.0 ? -1.0 : 1.0);
+
+ p_dst_frames[i].l = spl0;
+ p_dst_frames[i].r = spl1;
+ }
+
+}
+
+
+Ref<AudioEffectInstance> AudioEffectLimiter::instance() {
+ Ref<AudioEffectLimiterInstance> ins;
+ ins.instance();
+ ins->base=Ref<AudioEffectLimiter>(this);
+
+ return ins;
+}
+
+
+void AudioEffectLimiter::set_treshold_db(float p_treshold) {
+
+ treshold=p_treshold;
+}
+
+float AudioEffectLimiter::get_treshold_db() const{
+
+ return treshold;
+}
+
+void AudioEffectLimiter::set_ceiling_db(float p_ceiling){
+
+ ceiling=p_ceiling;
+}
+float AudioEffectLimiter::get_ceiling_db() const{
+
+ return ceiling;
+}
+
+void AudioEffectLimiter::set_soft_clip_db(float p_soft_clip){
+
+ soft_clip=p_soft_clip;
+}
+float AudioEffectLimiter::get_soft_clip_db() const{
+
+ return soft_clip;
+}
+
+void AudioEffectLimiter::set_soft_clip_ratio(float p_soft_clip){
+
+ soft_clip_ratio=p_soft_clip;
+}
+float AudioEffectLimiter::get_soft_clip_ratio() const{
+
+ return soft_clip;
+}
+
+
+void AudioEffectLimiter::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_ceiling_db","ceiling"),&AudioEffectLimiter::set_ceiling_db);
+ ClassDB::bind_method(D_METHOD("get_ceiling_db"),&AudioEffectLimiter::get_ceiling_db);
+
+ ClassDB::bind_method(D_METHOD("set_treshold_db","treshold"),&AudioEffectLimiter::set_treshold_db);
+ ClassDB::bind_method(D_METHOD("get_treshold_db"),&AudioEffectLimiter::get_treshold_db);
+
+ ClassDB::bind_method(D_METHOD("set_soft_clip_db","soft_clip"),&AudioEffectLimiter::set_soft_clip_db);
+ ClassDB::bind_method(D_METHOD("get_soft_clip_db"),&AudioEffectLimiter::get_soft_clip_db);
+
+ ClassDB::bind_method(D_METHOD("set_soft_clip_ratio","soft_clip"),&AudioEffectLimiter::set_soft_clip_ratio);
+ ClassDB::bind_method(D_METHOD("get_soft_clip_ratio"),&AudioEffectLimiter::get_soft_clip_ratio);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"ceiling_db",PROPERTY_HINT_RANGE,"-20,-0.1,0.1"),"set_ceiling_db","get_ceiling_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"treshold_db",PROPERTY_HINT_RANGE,"-30,0,0.1"),"set_treshold_db","get_treshold_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"soft_clip_db",PROPERTY_HINT_RANGE,"0,6,0.1"),"set_soft_clip_db","get_soft_clip_db");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"soft_clip_ratio",PROPERTY_HINT_RANGE,"3,20,0.1"),"set_soft_clip_ratio","get_soft_clip_ratio");
+}
+
+AudioEffectLimiter::AudioEffectLimiter()
+{
+ treshold=0;
+ ceiling=-0.1;
+ soft_clip=2;
+ soft_clip_ratio=10;
+}
diff --git a/servers/audio/effects/audio_effect_limiter.h b/servers/audio/effects/audio_effect_limiter.h
new file mode 100644
index 0000000000..b0d7321205
--- /dev/null
+++ b/servers/audio/effects/audio_effect_limiter.h
@@ -0,0 +1,58 @@
+#ifndef AUDIO_EFFECT_LIMITER_H
+#define AUDIO_EFFECT_LIMITER_H
+
+
+#include "servers/audio/audio_effect.h"
+
+class AudioEffectLimiter;
+
+class AudioEffectLimiterInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectLimiterInstance,AudioEffectInstance)
+friend class AudioEffectLimiter;
+ Ref<AudioEffectLimiter> base;
+
+ float mix_volume_db;
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+};
+
+
+class AudioEffectLimiter : public AudioEffect {
+ GDCLASS(AudioEffectLimiter,AudioEffect)
+
+friend class AudioEffectLimiterInstance;
+ float treshold;
+ float ceiling;
+ float soft_clip;
+ float soft_clip_ratio;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+
+ void set_treshold_db(float p_treshold);
+ float get_treshold_db() const;
+
+ void set_ceiling_db(float p_ceiling);
+ float get_ceiling_db() const;
+
+ void set_soft_clip_db(float p_soft_clip);
+ float get_soft_clip_db() const;
+
+ void set_soft_clip_ratio(float p_soft_clip);
+ float get_soft_clip_ratio() const;
+
+
+ Ref<AudioEffectInstance> instance();
+ void set_volume_db(float p_volume);
+ float get_volume_db() const;
+
+ AudioEffectLimiter();
+};
+
+
+#endif // AUDIO_EFFECT_LIMITER_H
diff --git a/servers/audio/effects/audio_effect_panner.cpp b/servers/audio/effects/audio_effect_panner.cpp
new file mode 100644
index 0000000000..75ef9c3e3a
--- /dev/null
+++ b/servers/audio/effects/audio_effect_panner.cpp
@@ -0,0 +1,47 @@
+#include "audio_effect_panner.h"
+
+
+void AudioEffectPannerInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+
+ float lvol = CLAMP( 1.0 - base->pan, 0, 1);
+ float rvol = CLAMP( 1.0 + base->pan, 0, 1);
+
+ for(int i=0;i<p_frame_count;i++) {
+
+ p_dst_frames[i].l = p_src_frames[i].l * lvol + p_src_frames[i].r * (1.0 - rvol);
+ p_dst_frames[i].r = p_src_frames[i].r * rvol + p_src_frames[i].l * (1.0 - lvol);
+
+ }
+
+}
+
+
+Ref<AudioEffectInstance> AudioEffectPanner::instance() {
+ Ref<AudioEffectPannerInstance> ins;
+ ins.instance();
+ ins->base=Ref<AudioEffectPanner>(this);
+ return ins;
+}
+
+void AudioEffectPanner::set_pan(float p_cpanume) {
+ pan=p_cpanume;
+}
+
+float AudioEffectPanner::get_pan() const {
+
+ return pan;
+}
+
+void AudioEffectPanner::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_pan","cpanume"),&AudioEffectPanner::set_pan);
+ ClassDB::bind_method(D_METHOD("get_pan"),&AudioEffectPanner::get_pan);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"pan",PROPERTY_HINT_RANGE,"-1,1,0.01"),"set_pan","get_pan");
+}
+
+AudioEffectPanner::AudioEffectPanner()
+{
+ pan=0;
+}
diff --git a/servers/audio/effects/audio_effect_panner.h b/servers/audio/effects/audio_effect_panner.h
new file mode 100644
index 0000000000..bc1bb00815
--- /dev/null
+++ b/servers/audio/effects/audio_effect_panner.h
@@ -0,0 +1,40 @@
+#ifndef AUDIOEFFECTPANNER_H
+#define AUDIOEFFECTPANNER_H
+
+#include "servers/audio/audio_effect.h"
+
+class AudioEffectPanner;
+
+class AudioEffectPannerInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectPannerInstance,AudioEffectInstance)
+friend class AudioEffectPanner;
+ Ref<AudioEffectPanner> base;
+
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+};
+
+
+class AudioEffectPanner : public AudioEffect {
+ GDCLASS(AudioEffectPanner,AudioEffect)
+
+friend class AudioEffectPannerInstance;
+ float pan;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+
+ Ref<AudioEffectInstance> instance();
+ void set_pan(float p_volume);
+ float get_pan() const;
+
+ AudioEffectPanner();
+};
+
+
+#endif // AUDIOEFFECTPANNER_H
diff --git a/servers/audio/effects/audio_effect_phaser.cpp b/servers/audio/effects/audio_effect_phaser.cpp
new file mode 100644
index 0000000000..c5e49e6cc6
--- /dev/null
+++ b/servers/audio/effects/audio_effect_phaser.cpp
@@ -0,0 +1,148 @@
+#include "audio_effect_phaser.h"
+#include "servers/audio_server.h"
+#include "math_funcs.h"
+
+void AudioEffectPhaserInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+ float sampling_rate = AudioServer::get_singleton()->get_mix_rate();
+
+ float dmin = base->range_min / (sampling_rate/2.0);
+ float dmax = base->range_max / (sampling_rate/2.0);
+
+ float increment = 2.f * Math_PI * (base->rate / sampling_rate);
+
+ for(int i=0;i<p_frame_count;i++) {
+
+ phase += increment;
+
+ while ( phase >= Math_PI * 2.f ) {
+ phase -= Math_PI * 2.f;
+ }
+
+ float d = dmin + (dmax-dmin) * ((sin( phase ) + 1.f)/2.f);
+
+
+ //update filter coeffs
+ for( int j=0; j<6; j++ ) {
+ allpass[0][j].delay( d );
+ allpass[1][j].delay( d );
+ }
+
+ //calculate output
+ float y = allpass[0][0].update(
+ allpass[0][1].update(
+ allpass[0][2].update(
+ allpass[0][3].update(
+ allpass[0][4].update(
+ allpass[0][5].update( p_src_frames[i].l + h.l * base->feedback ))))));
+ h.l=y;
+
+ p_dst_frames[i].l = p_src_frames[i].l + y * base->depth;
+
+ y = allpass[1][0].update(
+ allpass[1][1].update(
+ allpass[1][2].update(
+ allpass[1][3].update(
+ allpass[1][4].update(
+ allpass[1][5].update( p_src_frames[i].r + h.r * base->feedback ))))));
+ h.r=y;
+
+ p_dst_frames[i].r = p_src_frames[i].r + y * base->depth;
+
+
+ }
+
+}
+
+
+Ref<AudioEffectInstance> AudioEffectPhaser::instance() {
+ Ref<AudioEffectPhaserInstance> ins;
+ ins.instance();
+ ins->base=Ref<AudioEffectPhaser>(this);
+ ins->phase=0;
+ ins->h=AudioFrame(0,0);
+
+ return ins;
+}
+
+
+void AudioEffectPhaser::set_range_min_hz(float p_hz) {
+
+ range_min=p_hz;
+}
+
+float AudioEffectPhaser::get_range_min_hz() const{
+
+ return range_min;
+}
+
+void AudioEffectPhaser::set_range_max_hz(float p_hz){
+
+ range_max=p_hz;
+}
+float AudioEffectPhaser::get_range_max_hz() const{
+
+ return range_max;
+}
+
+void AudioEffectPhaser::set_rate_hz(float p_hz){
+
+ rate=p_hz;
+}
+float AudioEffectPhaser::get_rate_hz() const{
+
+ return rate;
+}
+
+void AudioEffectPhaser::set_feedback(float p_fbk){
+
+ feedback=p_fbk;
+}
+float AudioEffectPhaser::get_feedback() const{
+
+ return feedback;
+}
+
+void AudioEffectPhaser::set_depth(float p_depth) {
+
+ depth=p_depth;
+}
+
+float AudioEffectPhaser::get_depth() const {
+
+ return depth;
+}
+
+void AudioEffectPhaser::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_range_min_hz","hz"),&AudioEffectPhaser::set_range_min_hz);
+ ClassDB::bind_method(D_METHOD("get_range_min_hz"),&AudioEffectPhaser::get_range_min_hz);
+
+ ClassDB::bind_method(D_METHOD("set_range_max_hz","hz"),&AudioEffectPhaser::set_range_max_hz);
+ ClassDB::bind_method(D_METHOD("get_range_max_hz"),&AudioEffectPhaser::get_range_max_hz);
+
+ ClassDB::bind_method(D_METHOD("set_rate_hz","hz"),&AudioEffectPhaser::set_rate_hz);
+ ClassDB::bind_method(D_METHOD("get_rate_hz"),&AudioEffectPhaser::get_rate_hz);
+
+ ClassDB::bind_method(D_METHOD("set_feedback","fbk"),&AudioEffectPhaser::set_feedback);
+ ClassDB::bind_method(D_METHOD("get_feedback"),&AudioEffectPhaser::get_feedback);
+
+ ClassDB::bind_method(D_METHOD("set_depth","depth"),&AudioEffectPhaser::set_depth);
+ ClassDB::bind_method(D_METHOD("get_depth"),&AudioEffectPhaser::get_depth);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"range_min_hz",PROPERTY_HINT_RANGE,"10,10000"),"set_range_min_hz","get_range_min_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"range_max_hz",PROPERTY_HINT_RANGE,"10,10000"),"set_range_max_hz","get_range_max_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"rate_hz",PROPERTY_HINT_RANGE,"0.01,20"),"set_rate_hz","get_rate_hz");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"feedback",PROPERTY_HINT_RANGE,"0.1,0.9,0.1"),"set_feedback","get_feedback");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"depth",PROPERTY_HINT_RANGE,"0.1,4,0.1"),"set_depth","get_depth");
+
+}
+
+AudioEffectPhaser::AudioEffectPhaser()
+{
+ range_min=440;
+ range_max=1600;
+ rate=0.5;
+ feedback=0.7;
+ depth=1;
+}
diff --git a/servers/audio/effects/audio_effect_phaser.h b/servers/audio/effects/audio_effect_phaser.h
new file mode 100644
index 0000000000..53a8ab8bd8
--- /dev/null
+++ b/servers/audio/effects/audio_effect_phaser.h
@@ -0,0 +1,81 @@
+#ifndef AUDIO_EFFECT_PHASER_H
+#define AUDIO_EFFECT_PHASER_H
+
+
+
+#include "servers/audio/audio_effect.h"
+
+class AudioEffectPhaser;
+
+class AudioEffectPhaserInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectPhaserInstance,AudioEffectInstance)
+friend class AudioEffectPhaser;
+ Ref<AudioEffectPhaser> base;
+
+ float phase;
+ AudioFrame h;
+
+ class AllpassDelay{
+ float a, h;
+ public:
+
+ _ALWAYS_INLINE_ void delay( float d ) {
+ a = (1.f - d) / (1.f + d);
+ }
+
+ _ALWAYS_INLINE_ float update( float s ){
+ float y = s * -a + h;
+ h = y * a + s;
+ return y;
+ }
+
+ AllpassDelay() { a =0; h = 0;}
+
+ };
+
+ AllpassDelay allpass[2][6];
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+};
+
+
+class AudioEffectPhaser : public AudioEffect {
+ GDCLASS(AudioEffectPhaser,AudioEffect)
+
+friend class AudioEffectPhaserInstance;
+ float range_min;
+ float range_max;
+ float rate;
+ float feedback;
+ float depth;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+
+ Ref<AudioEffectInstance> instance();
+
+ void set_range_min_hz(float p_hz);
+ float get_range_min_hz() const;
+
+ void set_range_max_hz(float p_hz);
+ float get_range_max_hz() const;
+
+ void set_rate_hz(float p_hz);
+ float get_rate_hz() const;
+
+ void set_feedback(float p_fbk);
+ float get_feedback() const;
+
+ void set_depth(float p_depth);
+ float get_depth() const;
+
+ AudioEffectPhaser();
+};
+
+
+#endif // AUDIO_EFFECT_PHASER_H
diff --git a/servers/audio/effects/audio_effect_pitch_shift.cpp b/servers/audio/effects/audio_effect_pitch_shift.cpp
new file mode 100644
index 0000000000..1222c7b1b2
--- /dev/null
+++ b/servers/audio/effects/audio_effect_pitch_shift.cpp
@@ -0,0 +1,298 @@
+#include "audio_effect_pitch_shift.h"
+#include "servers/audio_server.h"
+#include "math_funcs.h"
+/****************************************************************************
+*
+* NAME: smbPitchShift.cpp
+* VERSION: 1.2
+* HOME URL: http://blogs.zynaptiq.com/bernsee
+* KNOWN BUGS: none
+*
+* SYNOPSIS: Routine for doing pitch shifting while maintaining
+* duration using the Short Time Fourier Transform.
+*
+* DESCRIPTION: The routine takes a pitchShift factor value which is between 0.5
+* (one octave down) and 2. (one octave up). A value of exactly 1 does not change
+* the pitch. numSampsToProcess tells the routine how many samples in indata[0...
+* numSampsToProcess-1] should be pitch shifted and moved to outdata[0 ...
+* numSampsToProcess-1]. The two buffers can be identical (ie. it can process the
+* data in-place). fftFrameSize defines the FFT frame size used for the
+* processing. Typical values are 1024, 2048 and 4096. It may be any value <=
+* MAX_FRAME_LENGTH but it MUST be a power of 2. osamp is the STFT
+* oversampling factor which also determines the overlap between adjacent STFT
+* frames. It should at least be 4 for moderate scaling ratios. A value of 32 is
+* recommended for best quality. sampleRate takes the sample rate for the signal
+* in unit Hz, ie. 44100 for 44.1 kHz audio. The data passed to the routine in
+* indata[] should be in the range [-1.0, 1.0), which is also the output range
+* for the data, make sure you scale the data accordingly (for 16bit signed integers
+* you would have to divide (and multiply) by 32768).
+*
+* COPYRIGHT 1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com>
+*
+* The Wide Open License (WOL)
+*
+* Permission to use, copy, modify, distribute and sell this software and its
+* documentation for any purpose is hereby granted without fee, provided that
+* the above copyright notice and this license appear in all source copies.
+* THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY OF
+* ANY KIND. See http://www.dspguru.com/wol.htm for more information.
+*
+*****************************************************************************/
+
+
+void SMBPitchShift::PitchShift(float pitchShift, long numSampsToProcess, long fftFrameSize, long osamp, float sampleRate, float *indata, float *outdata,int stride) {
+
+
+ /*
+ Routine smbPitchShift(). See top of file for explanation
+ Purpose: doing pitch shifting while maintaining duration using the Short
+ Time Fourier Transform.
+ Author: (c)1999-2015 Stephan M. Bernsee <s.bernsee [AT] zynaptiq [DOT] com>
+ */
+
+ double magn, phase, tmp, window, real, imag;
+ double freqPerBin, expct;
+ long i,k, qpd, index, inFifoLatency, stepSize, fftFrameSize2;
+
+ /* set up some handy variables */
+ fftFrameSize2 = fftFrameSize/2;
+ stepSize = fftFrameSize/osamp;
+ freqPerBin = sampleRate/(double)fftFrameSize;
+ expct = 2.*Math_PI*(double)stepSize/(double)fftFrameSize;
+ inFifoLatency = fftFrameSize-stepSize;
+ if (gRover == 0) gRover = inFifoLatency;
+
+ /* initialize our static arrays */
+
+ /* main processing loop */
+ for (i = 0; i < numSampsToProcess; i++){
+
+ /* As long as we have not yet collected enough data just read in */
+ gInFIFO[gRover] = indata[i*stride];
+ outdata[i*stride] = gOutFIFO[gRover-inFifoLatency];
+ gRover++;
+
+ /* now we have enough data for processing */
+ if (gRover >= fftFrameSize) {
+ gRover = inFifoLatency;
+
+ /* do windowing and re,im interleave */
+ for (k = 0; k < fftFrameSize;k++) {
+ window = -.5*cos(2.*Math_PI*(double)k/(double)fftFrameSize)+.5;
+ gFFTworksp[2*k] = gInFIFO[k] * window;
+ gFFTworksp[2*k+1] = 0.;
+ }
+
+
+ /* ***************** ANALYSIS ******************* */
+ /* do transform */
+ smbFft(gFFTworksp, fftFrameSize, -1);
+
+ /* this is the analysis step */
+ for (k = 0; k <= fftFrameSize2; k++) {
+
+ /* de-interlace FFT buffer */
+ real = gFFTworksp[2*k];
+ imag = gFFTworksp[2*k+1];
+
+ /* compute magnitude and phase */
+ magn = 2.*sqrt(real*real + imag*imag);
+ phase = atan2(imag,real);
+
+ /* compute phase difference */
+ tmp = phase - gLastPhase[k];
+ gLastPhase[k] = phase;
+
+ /* subtract expected phase difference */
+ tmp -= (double)k*expct;
+
+ /* map delta phase into +/- Pi interval */
+ qpd = tmp/Math_PI;
+ if (qpd >= 0) qpd += qpd&1;
+ else qpd -= qpd&1;
+ tmp -= Math_PI*(double)qpd;
+
+ /* get deviation from bin frequency from the +/- Pi interval */
+ tmp = osamp*tmp/(2.*Math_PI);
+
+ /* compute the k-th partials' true frequency */
+ tmp = (double)k*freqPerBin + tmp*freqPerBin;
+
+ /* store magnitude and true frequency in analysis arrays */
+ gAnaMagn[k] = magn;
+ gAnaFreq[k] = tmp;
+
+ }
+
+ /* ***************** PROCESSING ******************* */
+ /* this does the actual pitch shifting */
+ memset(gSynMagn, 0, fftFrameSize*sizeof(float));
+ memset(gSynFreq, 0, fftFrameSize*sizeof(float));
+ for (k = 0; k <= fftFrameSize2; k++) {
+ index = k*pitchShift;
+ if (index <= fftFrameSize2) {
+ gSynMagn[index] += gAnaMagn[k];
+ gSynFreq[index] = gAnaFreq[k] * pitchShift;
+ }
+ }
+
+ /* ***************** SYNTHESIS ******************* */
+ /* this is the synthesis step */
+ for (k = 0; k <= fftFrameSize2; k++) {
+
+ /* get magnitude and true frequency from synthesis arrays */
+ magn = gSynMagn[k];
+ tmp = gSynFreq[k];
+
+ /* subtract bin mid frequency */
+ tmp -= (double)k*freqPerBin;
+
+ /* get bin deviation from freq deviation */
+ tmp /= freqPerBin;
+
+ /* take osamp into account */
+ tmp = 2.*Math_PI*tmp/osamp;
+
+ /* add the overlap phase advance back in */
+ tmp += (double)k*expct;
+
+ /* accumulate delta phase to get bin phase */
+ gSumPhase[k] += tmp;
+ phase = gSumPhase[k];
+
+ /* get real and imag part and re-interleave */
+ gFFTworksp[2*k] = magn*cos(phase);
+ gFFTworksp[2*k+1] = magn*sin(phase);
+ }
+
+ /* zero negative frequencies */
+ for (k = fftFrameSize+2; k < 2*fftFrameSize; k++) gFFTworksp[k] = 0.;
+
+ /* do inverse transform */
+ smbFft(gFFTworksp, fftFrameSize, 1);
+
+ /* do windowing and add to output accumulator */
+ for(k=0; k < fftFrameSize; k++) {
+ window = -.5*cos(2.*Math_PI*(double)k/(double)fftFrameSize)+.5;
+ gOutputAccum[k] += 2.*window*gFFTworksp[2*k]/(fftFrameSize2*osamp);
+ }
+ for (k = 0; k < stepSize; k++) gOutFIFO[k] = gOutputAccum[k];
+
+ /* shift accumulator */
+ memmove(gOutputAccum, gOutputAccum+stepSize, fftFrameSize*sizeof(float));
+
+ /* move input FIFO */
+ for (k = 0; k < inFifoLatency; k++) gInFIFO[k] = gInFIFO[k+stepSize];
+ }
+ }
+
+
+
+}
+
+
+void SMBPitchShift::smbFft(float *fftBuffer, long fftFrameSize, long sign)
+/*
+ FFT routine, (C)1996 S.M.Bernsee. Sign = -1 is FFT, 1 is iFFT (inverse)
+ Fills fftBuffer[0...2*fftFrameSize-1] with the Fourier transform of the
+ time domain data in fftBuffer[0...2*fftFrameSize-1]. The FFT array takes
+ and returns the cosine and sine parts in an interleaved manner, ie.
+ fftBuffer[0] = cosPart[0], fftBuffer[1] = sinPart[0], asf. fftFrameSize
+ must be a power of 2. It expects a complex input signal (see footnote 2),
+ ie. when working with 'common' audio signals our input signal has to be
+ passed as {in[0],0.,in[1],0.,in[2],0.,...} asf. In that case, the transform
+ of the frequencies of interest is in fftBuffer[0...fftFrameSize].
+*/
+{
+ float wr, wi, arg, *p1, *p2, temp;
+ float tr, ti, ur, ui, *p1r, *p1i, *p2r, *p2i;
+ long i, bitm, j, le, le2, k;
+
+ for (i = 2; i < 2*fftFrameSize-2; i += 2) {
+ for (bitm = 2, j = 0; bitm < 2*fftFrameSize; bitm <<= 1) {
+ if (i & bitm) j++;
+ j <<= 1;
+ }
+ if (i < j) {
+ p1 = fftBuffer+i; p2 = fftBuffer+j;
+ temp = *p1; *(p1++) = *p2;
+ *(p2++) = temp; temp = *p1;
+ *p1 = *p2; *p2 = temp;
+ }
+ }
+ for (k = 0, le = 2; k < (long)(log((double)fftFrameSize)/log(2.)+.5); k++) {
+ le <<= 1;
+ le2 = le>>1;
+ ur = 1.0;
+ ui = 0.0;
+ arg = Math_PI / (le2>>1);
+ wr = cos(arg);
+ wi = sign*sin(arg);
+ for (j = 0; j < le2; j += 2) {
+ p1r = fftBuffer+j; p1i = p1r+1;
+ p2r = p1r+le2; p2i = p2r+1;
+ for (i = j; i < 2*fftFrameSize; i += le) {
+ tr = *p2r * ur - *p2i * ui;
+ ti = *p2r * ui + *p2i * ur;
+ *p2r = *p1r - tr; *p2i = *p1i - ti;
+ *p1r += tr; *p1i += ti;
+ p1r += le; p1i += le;
+ p2r += le; p2i += le;
+ }
+ tr = ur*wr - ui*wi;
+ ui = ur*wi + ui*wr;
+ ur = tr;
+ }
+ }
+}
+
+
+void AudioEffectPitchShiftInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+ float sample_rate = AudioServer::get_singleton()->get_mix_rate();
+
+ float *in_l = (float*)p_src_frames;
+ float *in_r = in_l + 1;
+
+ float *out_l = (float*)p_dst_frames;
+ float *out_r = out_l + 1;
+
+ shift_l.PitchShift(base->pitch_scale,p_frame_count,2048,4,sample_rate,in_l,out_l,2);
+ shift_r.PitchShift(base->pitch_scale,p_frame_count,2048,4,sample_rate,in_r,out_r,2);
+
+}
+
+
+Ref<AudioEffectInstance> AudioEffectPitchShift::instance() {
+ Ref<AudioEffectPitchShiftInstance> ins;
+ ins.instance();
+ ins->base=Ref<AudioEffectPitchShift>(this);
+
+
+ return ins;
+}
+
+void AudioEffectPitchShift::set_pitch_scale(float p_adjust) {
+
+ pitch_scale=p_adjust;
+}
+
+float AudioEffectPitchShift::get_pitch_scale() const {
+
+ return pitch_scale;
+}
+
+
+void AudioEffectPitchShift::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_pitch_scale","rate"),&AudioEffectPitchShift::set_pitch_scale);
+ ClassDB::bind_method(D_METHOD("get_pitch_scale"),&AudioEffectPitchShift::get_pitch_scale);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"pitch_scale",PROPERTY_HINT_RANGE,"0.01,16,0.01"),"set_pitch_scale","get_pitch_scale");
+
+}
+
+AudioEffectPitchShift::AudioEffectPitchShift() {
+ pitch_scale=1.0;
+
+}
diff --git a/servers/audio/effects/audio_effect_pitch_shift.h b/servers/audio/effects/audio_effect_pitch_shift.h
new file mode 100644
index 0000000000..d1343a0745
--- /dev/null
+++ b/servers/audio/effects/audio_effect_pitch_shift.h
@@ -0,0 +1,89 @@
+#ifndef AUDIO_EFFECT_PITCH_SHIFT_H
+#define AUDIO_EFFECT_PITCH_SHIFT_H
+
+
+#include "servers/audio/audio_effect.h"
+
+class SMBPitchShift {
+
+ enum {
+ MAX_FRAME_LENGTH=8192
+ };
+
+ float gInFIFO[MAX_FRAME_LENGTH];
+ float gOutFIFO[MAX_FRAME_LENGTH];
+ float gFFTworksp[2*MAX_FRAME_LENGTH];
+ float gLastPhase[MAX_FRAME_LENGTH/2+1];
+ float gSumPhase[MAX_FRAME_LENGTH/2+1];
+ float gOutputAccum[2*MAX_FRAME_LENGTH];
+ float gAnaFreq[MAX_FRAME_LENGTH];
+ float gAnaMagn[MAX_FRAME_LENGTH];
+ float gSynFreq[MAX_FRAME_LENGTH];
+ float gSynMagn[MAX_FRAME_LENGTH];
+ long gRover;
+
+ void smbFft(float *fftBuffer, long fftFrameSize, long sign);
+public:
+ void PitchShift(float pitchShift, long numSampsToProcess, long fftFrameSize, long osamp, float sampleRate, float *indata, float *outdata, int stride);
+
+ SMBPitchShift() {
+ gRover=0;
+ memset(gInFIFO, 0, MAX_FRAME_LENGTH*sizeof(float));
+ memset(gOutFIFO, 0, MAX_FRAME_LENGTH*sizeof(float));
+ memset(gFFTworksp, 0, 2*MAX_FRAME_LENGTH*sizeof(float));
+ memset(gLastPhase, 0, (MAX_FRAME_LENGTH/2+1)*sizeof(float));
+ memset(gSumPhase, 0, (MAX_FRAME_LENGTH/2+1)*sizeof(float));
+ memset(gOutputAccum, 0, 2*MAX_FRAME_LENGTH*sizeof(float));
+ memset(gAnaFreq, 0, MAX_FRAME_LENGTH*sizeof(float));
+ memset(gAnaMagn, 0, MAX_FRAME_LENGTH*sizeof(float));
+ }
+
+
+};
+
+
+class AudioEffectPitchShift;
+
+class AudioEffectPitchShiftInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectPitchShiftInstance,AudioEffectInstance)
+friend class AudioEffectPitchShift;
+ Ref<AudioEffectPitchShift> base;
+
+ SMBPitchShift shift_l;
+ SMBPitchShift shift_r;
+
+
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+};
+
+
+class AudioEffectPitchShift : public AudioEffect {
+ GDCLASS(AudioEffectPitchShift,AudioEffect)
+
+friend class AudioEffectPitchShiftInstance;
+
+ float pitch_scale;
+ int window_size;
+ float wet;
+ float dry;
+ bool filter;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+
+ Ref<AudioEffectInstance> instance();
+
+ void set_pitch_scale(float p_adjust);
+ float get_pitch_scale() const;
+
+ AudioEffectPitchShift();
+};
+
+
+#endif // AUDIO_EFFECT_PITCH_SHIFT_H
diff --git a/servers/audio/effects/audio_effect_reverb.cpp b/servers/audio/effects/audio_effect_reverb.cpp
new file mode 100644
index 0000000000..f84dffdd36
--- /dev/null
+++ b/servers/audio/effects/audio_effect_reverb.cpp
@@ -0,0 +1,182 @@
+#include "audio_effect_reverb.h"
+#include "servers/audio_server.h"
+void AudioEffectReverbInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+ for(int i=0;i<2;i++) {
+ Reverb &r=reverb[i];
+
+ r.set_predelay( base->predelay);
+ r.set_predelay_feedback( base->predelay_fb );
+ r.set_highpass( base->hpf );
+ r.set_room_size( base->room_size );
+ r.set_damp( base->damping );
+ r.set_extra_spread( base->spread );
+ r.set_wet( base->wet );
+ r.set_dry( base->dry );
+ }
+
+ int todo = p_frame_count;
+ int offset=0;
+
+ while(todo) {
+
+ int to_mix = MIN(todo,Reverb::INPUT_BUFFER_MAX_SIZE);
+
+ for(int j=0;j<to_mix;j++) {
+ tmp_src[j]=p_src_frames[offset+j].l;
+ }
+
+ reverb[0].process(tmp_src,tmp_dst,to_mix);
+
+ for(int j=0;j<to_mix;j++) {
+ p_dst_frames[offset+j].l=tmp_dst[j];
+ tmp_src[j]=p_src_frames[offset+j].r;
+ }
+
+ reverb[1].process(tmp_src,tmp_dst,to_mix);
+
+ for(int j=0;j<to_mix;j++) {
+ p_dst_frames[offset+j].r=tmp_dst[j];
+ }
+
+ offset+=to_mix;
+ todo-=to_mix;
+ }
+}
+
+AudioEffectReverbInstance::AudioEffectReverbInstance() {
+
+ reverb[0].set_mix_rate( AudioServer::get_singleton()->get_mix_rate() );
+ reverb[0].set_extra_spread_base(0);
+ reverb[1].set_mix_rate( AudioServer::get_singleton()->get_mix_rate() );
+ reverb[1].set_extra_spread_base(0.000521); //for stereo effect
+
+}
+
+Ref<AudioEffectInstance> AudioEffectReverb::instance() {
+ Ref<AudioEffectReverbInstance> ins;
+ ins.instance();
+ ins->base=Ref<AudioEffectReverb>(this);
+ return ins;
+}
+
+void AudioEffectReverb::set_predelay_msec(float p_msec) {
+
+ predelay=p_msec;
+}
+
+void AudioEffectReverb::set_predelay_feedback(float p_feedback){
+
+ predelay_fb=p_feedback;
+}
+void AudioEffectReverb::set_room_size(float p_size){
+
+ room_size=p_size;
+}
+void AudioEffectReverb::set_damping(float p_damping){
+
+ damping=p_damping;
+}
+void AudioEffectReverb::set_spread(float p_spread){
+
+ spread=p_spread;
+}
+
+void AudioEffectReverb::set_dry(float p_dry){
+
+ dry=p_dry;
+}
+void AudioEffectReverb::set_wet(float p_wet){
+
+ wet=p_wet;
+}
+void AudioEffectReverb::set_hpf(float p_hpf) {
+
+ hpf=p_hpf;
+}
+
+float AudioEffectReverb::get_predelay_msec() const {
+
+ return predelay;
+}
+float AudioEffectReverb::get_predelay_feedback() const {
+
+ return predelay_fb;
+}
+float AudioEffectReverb::get_room_size() const {
+
+ return room_size;
+}
+float AudioEffectReverb::get_damping() const {
+
+ return damping;
+}
+float AudioEffectReverb::get_spread() const {
+
+ return spread;
+}
+float AudioEffectReverb::get_dry() const {
+
+ return dry;
+}
+float AudioEffectReverb::get_wet() const {
+
+ return wet;
+}
+float AudioEffectReverb::get_hpf() const {
+
+ return hpf;
+}
+
+
+void AudioEffectReverb::_bind_methods() {
+
+
+ ClassDB::bind_method(D_METHOD("set_predelay_msec","msec"),&AudioEffectReverb::set_predelay_msec);
+ ClassDB::bind_method(D_METHOD("get_predelay_msec"),&AudioEffectReverb::get_predelay_msec);
+
+ ClassDB::bind_method(D_METHOD("set_predelay_feedback","feedback"),&AudioEffectReverb::set_predelay_feedback);
+ ClassDB::bind_method(D_METHOD("get_predelay_feedback"),&AudioEffectReverb::get_predelay_feedback);
+
+ ClassDB::bind_method(D_METHOD("set_room_size","size"),&AudioEffectReverb::set_room_size);
+ ClassDB::bind_method(D_METHOD("get_room_size"),&AudioEffectReverb::get_room_size);
+
+ ClassDB::bind_method(D_METHOD("set_damping","amount"),&AudioEffectReverb::set_damping);
+ ClassDB::bind_method(D_METHOD("get_damping"),&AudioEffectReverb::get_damping);
+
+ ClassDB::bind_method(D_METHOD("set_spread","amount"),&AudioEffectReverb::set_spread);
+ ClassDB::bind_method(D_METHOD("get_spread"),&AudioEffectReverb::get_spread);
+
+ ClassDB::bind_method(D_METHOD("set_dry","amount"),&AudioEffectReverb::set_dry);
+ ClassDB::bind_method(D_METHOD("get_dry"),&AudioEffectReverb::get_dry);
+
+ ClassDB::bind_method(D_METHOD("set_wet","amount"),&AudioEffectReverb::set_wet);
+ ClassDB::bind_method(D_METHOD("get_wet"),&AudioEffectReverb::get_wet);
+
+ ClassDB::bind_method(D_METHOD("set_hpf","amount"),&AudioEffectReverb::set_hpf);
+ ClassDB::bind_method(D_METHOD("get_hpf"),&AudioEffectReverb::get_hpf);
+
+
+ ADD_GROUP("Predelay","predelay_");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"predelay_msec",PROPERTY_HINT_RANGE,"20,500,1"),"set_predelay_msec","get_predelay_msec");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"predelay_feedback",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_predelay_msec","get_predelay_msec");
+ ADD_GROUP("","");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"room_size",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_room_size","get_room_size");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"damping",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_damping","get_damping");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"spread",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_spread","get_spread");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"hipass",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_hpf","get_hpf");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"dry",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_dry","get_dry");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"wet",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_wet","get_wet");
+}
+
+AudioEffectReverb::AudioEffectReverb() {
+ predelay=150;
+ predelay_fb=0.4;
+ hpf=0;
+ room_size=0.8;
+ damping=0.5;
+ spread=1.0;
+ dry=1.0;
+ wet=0.5;
+
+}
diff --git a/servers/audio/effects/audio_effect_reverb.h b/servers/audio/effects/audio_effect_reverb.h
new file mode 100644
index 0000000000..e05ffe422f
--- /dev/null
+++ b/servers/audio/effects/audio_effect_reverb.h
@@ -0,0 +1,76 @@
+#ifndef AUDIOEFFECTREVERB_H
+#define AUDIOEFFECTREVERB_H
+
+
+#include "servers/audio/audio_effect.h"
+#include "servers/audio/effects/reverb.h"
+
+class AudioEffectReverb;
+
+class AudioEffectReverbInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectReverbInstance,AudioEffectInstance)
+
+ Ref<AudioEffectReverb> base;
+
+ float tmp_src[Reverb::INPUT_BUFFER_MAX_SIZE];
+ float tmp_dst[Reverb::INPUT_BUFFER_MAX_SIZE];
+
+friend class AudioEffectReverb;
+
+ Reverb reverb[2];
+
+
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+ AudioEffectReverbInstance();
+};
+
+
+class AudioEffectReverb : public AudioEffect {
+ GDCLASS(AudioEffectReverb,AudioEffect)
+
+friend class AudioEffectReverbInstance;
+
+ float predelay;
+ float predelay_fb;
+ float hpf;
+ float room_size;
+ float damping;
+ float spread;
+ float dry;
+ float wet;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+
+ void set_predelay_msec(float p_msec);
+ void set_predelay_feedback(float p_feedback);
+ void set_room_size(float p_size);
+ void set_damping(float p_damping);
+ void set_spread(float p_spread);
+ void set_dry(float p_dry);
+ void set_wet(float p_wet);
+ void set_hpf(float p_hpf);
+
+ float get_predelay_msec() const;
+ float get_predelay_feedback() const;
+ float get_room_size() const;
+ float get_damping() const;
+ float get_spread() const;
+ float get_dry() const;
+ float get_wet() const;
+ float get_hpf() const;
+
+ Ref<AudioEffectInstance> instance();
+ void set_volume_db(float p_volume);
+ float get_volume_db() const;
+
+ AudioEffectReverb();
+};
+
+
+#endif // AUDIOEFFECTREVERB_H
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.cpp b/servers/audio/effects/audio_effect_stereo_enhance.cpp
new file mode 100644
index 0000000000..0afabc8f3d
--- /dev/null
+++ b/servers/audio/effects/audio_effect_stereo_enhance.cpp
@@ -0,0 +1,135 @@
+#include "audio_effect_stereo_enhance.h"
+#include "servers/audio_server.h"
+void AudioEffectStereoEnhanceInstance::process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count) {
+
+
+ float intensity=base->pan_pullout;
+ bool surround_mode=base->surround>0;
+ float surround_amount=base->surround;
+ unsigned int delay_frames=(base->time_pullout/1000.0)*AudioServer::get_singleton()->get_mix_rate();
+
+ for (int i=0;i<p_frame_count;i++) {
+
+ float l=p_src_frames[i].l;
+ float r=p_src_frames[i].r;
+
+ float center=(l+r)/2.0f;
+
+ l=( center+(l-center)*intensity );
+ r=( center+(r-center)*intensity );
+
+ if (surround_mode) {
+
+ float val=(l+r)/2.0;
+
+ delay_ringbuff[ringbuff_pos&ringbuff_mask]=val;
+
+ float out=delay_ringbuff[(ringbuff_pos-delay_frames)&ringbuff_mask]*surround_amount;
+
+ l+=out;
+ r+=-out;
+ } else {
+
+ float val=r;
+
+ delay_ringbuff[ringbuff_pos&ringbuff_mask]=val;
+
+ //r is delayed
+ r=delay_ringbuff[(ringbuff_pos-delay_frames)&ringbuff_mask];;
+
+
+ }
+
+ p_dst_frames[i].l=l;
+ p_dst_frames[i].r=r;
+ ringbuff_pos++;
+
+ }
+
+}
+
+
+AudioEffectStereoEnhanceInstance::~AudioEffectStereoEnhanceInstance() {
+
+ memdelete_arr(delay_ringbuff);
+}
+
+Ref<AudioEffectInstance> AudioEffectStereoEnhance::instance() {
+ Ref<AudioEffectStereoEnhanceInstance> ins;
+ ins.instance();
+
+ ins->base=Ref<AudioEffectStereoEnhance>(this);
+
+
+ float ring_buffer_max_size=AudioEffectStereoEnhanceInstance::MAX_DELAY_MS+2;
+ ring_buffer_max_size/=1000.0;//convert to seconds
+ ring_buffer_max_size*=AudioServer::get_singleton()->get_mix_rate();
+
+ int ringbuff_size=(int)ring_buffer_max_size;
+
+ int bits=0;
+
+ while(ringbuff_size>0) {
+ bits++;
+ ringbuff_size/=2;
+ }
+
+ ringbuff_size=1<<bits;
+ ins->ringbuff_mask=ringbuff_size-1;
+ ins->ringbuff_pos=0;
+
+ ins->delay_ringbuff = memnew_arr(float,ringbuff_size );
+
+ return ins;
+}
+
+void AudioEffectStereoEnhance::set_pan_pullout(float p_amount) {
+
+ pan_pullout=p_amount;
+}
+
+float AudioEffectStereoEnhance::get_pan_pullout() const {
+
+ return pan_pullout;
+}
+
+void AudioEffectStereoEnhance::set_time_pullout(float p_amount) {
+
+ time_pullout=p_amount;
+}
+float AudioEffectStereoEnhance::get_time_pullout() const {
+
+ return time_pullout;
+}
+
+void AudioEffectStereoEnhance::set_surround(float p_amount) {
+
+ surround=p_amount;
+}
+float AudioEffectStereoEnhance::get_surround() const {
+
+ return surround;
+}
+
+void AudioEffectStereoEnhance::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_pan_pullout","amount"),&AudioEffectStereoEnhance::set_pan_pullout);
+ ClassDB::bind_method(D_METHOD("get_pan_pullout"),&AudioEffectStereoEnhance::get_pan_pullout);
+
+ ClassDB::bind_method(D_METHOD("set_time_pullout","amount"),&AudioEffectStereoEnhance::set_time_pullout);
+ ClassDB::bind_method(D_METHOD("get_time_pullout"),&AudioEffectStereoEnhance::get_time_pullout);
+
+ ClassDB::bind_method(D_METHOD("set_surround","amount"),&AudioEffectStereoEnhance::set_surround);
+ ClassDB::bind_method(D_METHOD("get_surround"),&AudioEffectStereoEnhance::get_surround);
+
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"pan_pullout",PROPERTY_HINT_RANGE,"0,4,0.01"),"set_pan_pullout","get_pan_pullout");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"time_pullout_ms",PROPERTY_HINT_RANGE,"0,50,0.01"),"set_time_pullout","get_time_pullout");
+ ADD_PROPERTY(PropertyInfo(Variant::REAL,"surround",PROPERTY_HINT_RANGE,"0,1,0.01"),"set_surround","get_surround");
+}
+
+AudioEffectStereoEnhance::AudioEffectStereoEnhance()
+{
+ pan_pullout=1;
+ time_pullout=0;
+ surround=0;
+}
diff --git a/servers/audio/effects/audio_effect_stereo_enhance.h b/servers/audio/effects/audio_effect_stereo_enhance.h
new file mode 100644
index 0000000000..06762acbf3
--- /dev/null
+++ b/servers/audio/effects/audio_effect_stereo_enhance.h
@@ -0,0 +1,62 @@
+#ifndef AUDIOEFFECTSTEREOENHANCE_H
+#define AUDIOEFFECTSTEREOENHANCE_H
+
+
+#include "servers/audio/audio_effect.h"
+
+class AudioEffectStereoEnhance;
+
+class AudioEffectStereoEnhanceInstance : public AudioEffectInstance {
+ GDCLASS(AudioEffectStereoEnhanceInstance,AudioEffectInstance)
+friend class AudioEffectStereoEnhance;
+ Ref<AudioEffectStereoEnhance> base;
+
+ enum {
+
+ MAX_DELAY_MS=50
+ };
+
+ float *delay_ringbuff;
+ unsigned int ringbuff_pos;
+ unsigned int ringbuff_mask;
+
+
+public:
+
+ virtual void process(const AudioFrame *p_src_frames,AudioFrame *p_dst_frames,int p_frame_count);
+
+ ~AudioEffectStereoEnhanceInstance();
+};
+
+
+class AudioEffectStereoEnhance : public AudioEffect {
+ GDCLASS(AudioEffectStereoEnhance,AudioEffect)
+
+friend class AudioEffectStereoEnhanceInstance;
+ float volume_db;
+
+ float pan_pullout;
+ float time_pullout;
+ float surround;
+
+protected:
+
+ static void _bind_methods();
+public:
+
+
+ Ref<AudioEffectInstance> instance();
+
+ void set_pan_pullout(float p_amount);
+ float get_pan_pullout() const;
+
+ void set_time_pullout(float p_amount);
+ float get_time_pullout() const;
+
+ void set_surround(float p_amount);
+ float get_surround() const;
+
+ AudioEffectStereoEnhance();
+};
+
+#endif // AUDIOEFFECTSTEREOENHANCE_H
diff --git a/servers/audio/effects/eq.cpp b/servers/audio/effects/eq.cpp
new file mode 100644
index 0000000000..5aab60a558
--- /dev/null
+++ b/servers/audio/effects/eq.cpp
@@ -0,0 +1,219 @@
+//
+// C++ Interface: eq
+//
+// Description:
+//
+//
+// Author: reduzio@gmail.com (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#include "eq.h"
+#include <math.h>
+#include "error_macros.h"
+#include "math_funcs.h"
+
+#define POW2(v) ((v)*(v))
+
+/* Helper */
+ static int solve_quadratic(double a,double b,double c,double *r1, double *r2) {
+//solves quadractic and returns number of roots
+
+ double base=2*a;
+ if (base == 0.0f)
+ return 0;
+
+ double squared=b*b-4*a*c;
+ if (squared<0.0)
+ return 0;
+
+ squared=sqrt(squared);
+
+ *r1=(-b+squared)/base;
+ *r2=(-b-squared)/base;
+
+ if (*r1==*r2)
+ return 1;
+ else
+ return 2;
+ }
+
+EQ::BandProcess::BandProcess() {
+
+ c1=c2=c3=history.a1=history.a2=history.a3=0;
+ history.b1=history.b2=history.b3=0;
+}
+
+void EQ::recalculate_band_coefficients() {
+
+#define BAND_LOG( m_f ) ( log((m_f)) / log(2.) )
+
+ for (int i=0;i<band.size();i++) {
+
+ double octave_size;
+
+ double frq=band[i].freq;
+
+ if (i==0) {
+
+ octave_size=BAND_LOG(band[1].freq)-BAND_LOG(frq);
+ } else if (i==(band.size()-1)) {
+
+ octave_size=BAND_LOG(frq)-BAND_LOG(band[i-1].freq);
+ } else {
+
+ double next=BAND_LOG(band[i+1].freq)-BAND_LOG(frq);
+ double prev=BAND_LOG(frq)-BAND_LOG(band[i-1].freq);
+ octave_size=(next+prev)/2.0;
+ }
+
+
+
+ double frq_l=round(frq/pow(2.0,octave_size/2.0));
+
+
+
+ double side_gain2=POW2(Math_SQRT12);
+ double th=2.0*Math_PI*frq/mix_rate;
+ double th_l=2.0*Math_PI*frq_l/mix_rate;
+
+ double c2a=side_gain2 * POW2(cos(th))
+ - 2.0 * side_gain2 * cos(th_l) * cos(th)
+ + side_gain2
+ - POW2(sin(th_l));
+
+ double c2b=2.0 * side_gain2 * POW2(cos(th_l))
+ + side_gain2 * POW2(cos(th))
+ - 2.0 * side_gain2 * cos(th_l) * cos(th)
+ - side_gain2
+ + POW2(sin(th_l));
+
+ double c2c=0.25 * side_gain2 * POW2(cos(th))
+ - 0.5 * side_gain2 * cos(th_l) * cos(th)
+ + 0.25 * side_gain2
+ - 0.25 * POW2(sin(th_l));
+
+ //printf("band %i, precoefs = %f,%f,%f\n",i,c2a,c2b,c2c);
+
+ double r1,r2; //roots
+ int roots=solve_quadratic(c2a,c2b,c2c,&r1,&r2);
+
+ ERR_CONTINUE( roots==0 );
+
+ band[i].c1=2.0 * ((0.5-r1)/2.0);
+ band[i].c2=2.0 * r1;
+ band[i].c3=2.0 * (0.5+r1) * cos(th);
+ //printf("band %i, coefs = %f,%f,%f\n",i,(float)bands[i].c1,(float)bands[i].c2,(float)bands[i].c3);
+
+ }
+}
+
+void EQ::set_preset_band_mode(Preset p_preset) {
+
+
+ band.clear();
+
+#define PUSH_BANDS(m_bands) \
+ for (int i=0;i<m_bands;i++) { \
+ Band b; \
+ b.freq=bands[i];\
+ band.push_back(b);\
+ }
+
+ switch (p_preset) {
+
+ case PRESET_6_BANDS: {
+
+ static const double bands[] = { 32 , 100 , 320 , 1e3, 3200, 10e3 };
+ PUSH_BANDS(6);
+
+ } break;
+
+ case PRESET_8_BANDS: {
+
+ static const double bands[] = { 32,72,192,512,1200,3000,7500,16e3 };
+
+ PUSH_BANDS(8);
+ } break;
+
+ case PRESET_10_BANDS: {
+ static const double bands[] = { 31.25, 62.5, 125 , 250 , 500 , 1e3, 2e3, 4e3, 8e3, 16e3 };
+
+ PUSH_BANDS(10);
+
+ } break;
+
+ case PRESET_21_BANDS: {
+
+ static const double bands[] = { 22 , 32 , 44 , 63 , 90 , 125 , 175 , 250 , 350 , 500 , 700 , 1e3, 1400 , 2e3, 2800 , 4e3, 5600 , 8e3, 11e3, 16e3, 22e3 };
+ PUSH_BANDS(21);
+
+ } break;
+
+ case PRESET_31_BANDS: {
+
+ static const double bands[] = { 20, 25, 31.5, 40 , 50 , 63 , 80 , 100 , 125 , 160 , 200 , 250 , 315 , 400 , 500 , 630 , 800 , 1e3 , 1250 , 1600 , 2e3, 2500 , 3150 , 4e3, 5e3, 6300 , 8e3, 10e3, 12500 , 16e3, 20e3 };
+ PUSH_BANDS(31);
+ } break;
+
+ };
+
+ recalculate_band_coefficients();
+}
+
+int EQ::get_band_count() const {
+
+ return band.size();
+}
+float EQ::get_band_frequency(int p_band) {
+
+ ERR_FAIL_INDEX_V(p_band,band.size(),0);
+ return band[p_band].freq;
+}
+void EQ::set_bands(const Vector<float>& p_bands) {
+
+ band.resize(p_bands.size());
+ for (int i=0;i<p_bands.size();i++) {
+
+ band[i].freq=p_bands[i];
+ }
+
+ recalculate_band_coefficients();
+
+}
+
+void EQ::set_mix_rate(float p_mix_rate) {
+
+ mix_rate=p_mix_rate;
+ recalculate_band_coefficients();
+}
+
+EQ::BandProcess EQ::get_band_processor(int p_band) const {
+
+
+ EQ::BandProcess band_proc;
+
+ ERR_FAIL_INDEX_V(p_band,band.size(),band_proc);
+
+ band_proc.c1=band[p_band].c1;
+ band_proc.c2=band[p_band].c2;
+ band_proc.c3=band[p_band].c3;
+
+ return band_proc;
+
+
+}
+
+
+EQ::EQ()
+{
+ mix_rate=44100;
+}
+
+
+EQ::~EQ()
+{
+}
+
+
diff --git a/servers/audio/effects/eq.h b/servers/audio/effects/eq.h
new file mode 100644
index 0000000000..2c4668cd0b
--- /dev/null
+++ b/servers/audio/effects/eq.h
@@ -0,0 +1,106 @@
+//
+// C++ Interface: eq
+//
+// Description:
+//
+//
+// Author: reduzio@gmail.com (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef EQ_FILTER_H
+#define EQ_FILTER_H
+
+
+#include "typedefs.h"
+#include "vector.h"
+
+
+/**
+@author Juan Linietsky
+*/
+
+class EQ {
+public:
+
+ enum Preset {
+
+ PRESET_6_BANDS,
+ PRESET_8_BANDS,
+ PRESET_10_BANDS,
+ PRESET_21_BANDS,
+ PRESET_31_BANDS
+ };
+
+
+
+ class BandProcess {
+
+ friend class EQ;
+ float c1,c2,c3;
+ struct History {
+ float a1,a2,a3;
+ float b1,b2,b3;
+
+ } history;
+
+ public:
+
+ inline void process_one(float & p_data);
+
+ BandProcess();
+ };
+
+private:
+ struct Band {
+
+ float freq;
+ float c1,c2,c3;
+ };
+
+ Vector<Band> band;
+
+ float mix_rate;
+
+ void recalculate_band_coefficients();
+
+public:
+
+
+ void set_mix_rate(float p_mix_rate);
+
+ int get_band_count() const;
+ void set_preset_band_mode(Preset p_preset);
+ void set_bands(const Vector<float>& p_bands);
+ BandProcess get_band_processor(int p_band) const;
+ float get_band_frequency(int p_band);
+
+ EQ();
+ ~EQ();
+
+};
+
+
+/* Inline Function */
+
+inline void EQ::BandProcess::process_one(float & p_data) {
+
+
+ history.a1=p_data;
+
+ history.b1= c1 * ( history.a1 - history.a3 )
+ + c3 * history.b2
+ - c2 * history.b3;
+
+ p_data = history.b1;
+
+ history.a3=history.a2;
+ history.a2=history.a1;
+ history.b3=history.b2;
+ history.b2=history.b1;
+
+}
+
+
+#endif
diff --git a/servers/audio/effects/reverb.cpp b/servers/audio/effects/reverb.cpp
new file mode 100644
index 0000000000..43ea0edb3a
--- /dev/null
+++ b/servers/audio/effects/reverb.cpp
@@ -0,0 +1,364 @@
+//
+// C++ Interface: reverb
+//
+// Description:
+//
+//
+// Author: Juan Linietsky <reduzio@gmail.com>, (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "reverb.h"
+#include <math.h>
+#include "math_funcs.h"
+
+
+const float Reverb::comb_tunings[MAX_COMBS]={
+ //freeverb comb tunings
+ 0.025306122448979593,
+ 0.026938775510204082,
+ 0.028956916099773241,
+ 0.03074829931972789,
+ 0.032244897959183672,
+ 0.03380952380952381,
+ 0.035306122448979592,
+ 0.036666666666666667
+};
+
+const float Reverb::allpass_tunings[MAX_ALLPASS]={
+ //freeverb allpass tunings
+ 0.0051020408163265302,
+ 0.007732426303854875,
+ 0.01,
+ 0.012607709750566893
+};
+
+
+
+void Reverb::process(float *p_src,float *p_dst,int p_frames) {
+
+ if (p_frames>INPUT_BUFFER_MAX_SIZE)
+ p_frames=INPUT_BUFFER_MAX_SIZE;
+
+ int predelay_frames=lrint((params.predelay/1000.0)*params.mix_rate);
+ if (predelay_frames<10)
+ predelay_frames=10;
+ if (predelay_frames>=echo_buffer_size)
+ predelay_frames=echo_buffer_size-1;
+
+ for (int i=0;i<p_frames;i++) {
+
+ if (echo_buffer_pos>=echo_buffer_size)
+ echo_buffer_pos=0;
+
+ int read_pos=echo_buffer_pos-predelay_frames;
+ while (read_pos<0)
+ read_pos+=echo_buffer_size;
+
+ float in=undenormalise(echo_buffer[read_pos]*params.predelay_fb+p_src[i]);
+
+ echo_buffer[echo_buffer_pos]=in;
+
+ input_buffer[i]=in;
+
+ p_dst[i]=0; //take the chance and clear this
+
+ echo_buffer_pos++;
+ }
+
+ if (params.hpf>0) {
+ float hpaux=expf(-2.0*Math_PI*params.hpf*6000/params.mix_rate);
+ float hp_a1=(1.0+hpaux)/2.0;
+ float hp_a2=-(1.0+hpaux)/2.0;
+ float hp_b1=hpaux;
+
+ for (int i=0;i<p_frames;i++) {
+
+ float in=input_buffer[i];
+ input_buffer[i]=in*hp_a1+hpf_h1*hp_a2+hpf_h2*hp_b1;
+ hpf_h2=input_buffer[i];
+ hpf_h1=in;
+ }
+ }
+
+ for (int i=0;i<MAX_COMBS;i++) {
+
+ Comb &c=comb[i];
+
+ int size_limit=c.size-lrintf((float)c.extra_spread_frames*(1.0-params.extra_spread));
+ for (int j=0;j<p_frames;j++) {
+
+ if (c.pos>=size_limit) //reset this now just in case
+ c.pos=0;
+
+ float out=undenormalise(c.buffer[c.pos]*c.feedback);
+ out=out*(1.0-c.damp)+c.damp_h*c.damp; //lowpass
+ c.damp_h=out;
+ c.buffer[c.pos]=input_buffer[j]+out;
+ p_dst[j]+=out;
+ c.pos++;
+ }
+
+ }
+
+
+ static const float allpass_feedback=0.7;
+ /* this one works, but the other version is just nicer....
+ int ap_size_limit[MAX_ALLPASS];
+
+ for (int i=0;i<MAX_ALLPASS;i++) {
+
+ AllPass &a=allpass[i];
+ ap_size_limit[i]=a.size-lrintf((float)a.extra_spread_frames*(1.0-params.extra_spread));
+ }
+
+ for (int i=0;i<p_frames;i++) {
+
+ float sample=p_dst[i];
+ float aux,in;
+ float AllPass*ap;
+
+#define PROCESS_ALLPASS(m_ap) \
+ ap=&allpass[m_ap]; \
+ if (ap->pos>=ap_size_limit[m_ap]) \
+ ap->pos=0; \
+ aux=undenormalise(ap->buffer[ap->pos]); \
+ in=sample; \
+ sample=-in+aux; \
+ ap->pos++;
+
+
+ PROCESS_ALLPASS(0);
+ PROCESS_ALLPASS(1);
+ PROCESS_ALLPASS(2);
+ PROCESS_ALLPASS(3);
+
+ p_dst[i]=sample;
+ }
+ */
+
+ for (int i=0;i<MAX_ALLPASS;i++) {
+
+ AllPass &a=allpass[i];
+ int size_limit=a.size-lrintf((float)a.extra_spread_frames*(1.0-params.extra_spread));
+
+ for (int j=0;j<p_frames;j++) {
+
+ if (a.pos>=size_limit)
+ a.pos=0;
+
+ float aux=a.buffer[a.pos];
+ a.buffer[a.pos]=undenormalise(allpass_feedback*aux+p_dst[j]);
+ p_dst[j]=aux-allpass_feedback*a.buffer[a.pos];
+ a.pos++;
+
+ }
+ }
+
+ static const float wet_scale=0.6;
+
+ for (int i=0;i<p_frames;i++) {
+
+
+ p_dst[i]=p_dst[i]*params.wet*wet_scale+p_src[i]*params.dry;
+ }
+
+}
+
+
+void Reverb::set_room_size(float p_size) {
+
+ params.room_size=p_size;
+ update_parameters();
+
+}
+void Reverb::set_damp(float p_damp) {
+
+ params.damp=p_damp;
+ update_parameters();
+
+}
+void Reverb::set_wet(float p_wet) {
+
+ params.wet=p_wet;
+
+}
+
+void Reverb::set_dry(float p_dry) {
+
+ params.dry=p_dry;
+
+}
+
+void Reverb::set_predelay(float p_predelay) {
+
+ params.predelay=p_predelay;
+}
+void Reverb::set_predelay_feedback(float p_predelay_fb) {
+
+ params.predelay_fb=p_predelay_fb;
+
+}
+
+void Reverb::set_highpass(float p_frq) {
+
+ if (p_frq>1)
+ p_frq=1;
+ if (p_frq<0)
+ p_frq=0;
+ params.hpf=p_frq;
+}
+
+void Reverb::set_extra_spread(float p_spread) {
+
+ params.extra_spread=p_spread;
+
+}
+
+
+void Reverb::set_mix_rate(float p_mix_rate) {
+
+ params.mix_rate=p_mix_rate;
+ configure_buffers();
+}
+
+void Reverb::set_extra_spread_base(float p_sec) {
+
+ params.extra_spread_base=p_sec;
+ configure_buffers();
+}
+
+
+void Reverb::configure_buffers() {
+
+ clear_buffers(); //clear if necesary
+
+ for (int i=0;i<MAX_COMBS;i++) {
+
+ Comb &c=comb[i];
+
+
+ c.extra_spread_frames=lrint(params.extra_spread_base*params.mix_rate);
+
+ int len=lrint(comb_tunings[i]*params.mix_rate)+c.extra_spread_frames;
+ if (len<5)
+ len=5; //may this happen?
+
+ c.buffer = memnew_arr(float,len);
+ c.pos=0;
+ for (int j=0;j<len;j++)
+ c.buffer[j]=0;
+ c.size=len;
+
+ }
+
+ for (int i=0;i<MAX_ALLPASS;i++) {
+
+ AllPass &a=allpass[i];
+
+ a.extra_spread_frames=lrint(params.extra_spread_base*params.mix_rate);
+
+ int len=lrint(allpass_tunings[i]*params.mix_rate)+a.extra_spread_frames;
+ if (len<5)
+ len=5; //may this happen?
+
+ a.buffer = memnew_arr(float,len);
+ a.pos=0;
+ for (int j=0;j<len;j++)
+ a.buffer[j]=0;
+ a.size=len;
+ }
+
+ echo_buffer_size=(int)(((float)MAX_ECHO_MS/1000.0)*params.mix_rate+1.0);
+ echo_buffer = memnew_arr(float,echo_buffer_size);
+ for (int i=0;i<echo_buffer_size;i++) {
+
+ echo_buffer[i]=0;
+ }
+
+ echo_buffer_pos=0;
+}
+
+
+void Reverb::update_parameters() {
+
+ //more freeverb derived constants
+ static const float room_scale = 0.28f;
+ static const float room_offset = 0.7f;
+
+ for (int i=0;i<MAX_COMBS;i++) {
+
+ Comb &c=comb[i];
+ c.feedback=room_offset+params.room_size*room_scale;
+ if (c.feedback<room_offset)
+ c.feedback=room_offset;
+ else if (c.feedback>(room_offset+room_scale))
+ c.feedback=(room_offset+room_scale);
+
+ float auxdmp=params.damp/2.0+0.5; //only half the range (0.5 .. 1.0 is enough)
+ auxdmp*=auxdmp;
+
+ c.damp=expf(-2.0*Math_PI*auxdmp*10000/params.mix_rate); // 0 .. 10khz
+ }
+
+}
+
+void Reverb::clear_buffers() {
+
+ if (echo_buffer)
+ memdelete_arr(echo_buffer);
+
+ for (int i=0;i<MAX_COMBS;i++) {
+
+ if (comb[i].buffer)
+ memdelete_arr(comb[i].buffer);
+
+ comb[i].buffer=0;
+
+ }
+
+ for (int i=0;i<MAX_ALLPASS;i++) {
+
+ if (allpass[i].buffer)
+ memdelete_arr(allpass[i].buffer);
+
+ allpass[i].buffer=0;
+ }
+
+}
+
+Reverb::Reverb() {
+
+ params.room_size=0.8;
+ params.damp=0.5;
+ params.dry=1.0;
+ params.wet=0.0;
+ params.mix_rate=44100;
+ params.extra_spread_base=0;
+ params.extra_spread=1.0;
+ params.predelay=150;
+ params.predelay_fb=0.4;
+ params.hpf=0;
+ hpf_h1=0;
+ hpf_h2=0;
+
+
+ input_buffer=memnew_arr(float,INPUT_BUFFER_MAX_SIZE);
+ echo_buffer=0;
+
+ configure_buffers();
+ update_parameters();
+
+
+}
+
+
+Reverb::~Reverb() {
+
+ memdelete_arr(input_buffer);
+ clear_buffers();
+}
+
+
diff --git a/servers/audio/effects/reverb.h b/servers/audio/effects/reverb.h
new file mode 100644
index 0000000000..2c82be9156
--- /dev/null
+++ b/servers/audio/effects/reverb.h
@@ -0,0 +1,111 @@
+//
+// C++ Interface: reverb
+//
+// Description:
+//
+//
+// Author: Juan Linietsky <reduzio@gmail.com>, (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef REVERB_H
+#define REVERB_H
+
+#include "typedefs.h"
+#include "os/memory.h"
+#include "audio_frame.h"
+
+class Reverb {
+public:
+ enum {
+ INPUT_BUFFER_MAX_SIZE=1024,
+
+ };
+private:
+ enum {
+
+ MAX_COMBS=8,
+ MAX_ALLPASS=4,
+ MAX_ECHO_MS=500
+
+ };
+
+
+
+ static const float comb_tunings[MAX_COMBS];
+ static const float allpass_tunings[MAX_ALLPASS];
+
+ struct Comb {
+
+ int size;
+ float *buffer;
+ float feedback;
+ float damp; //lowpass
+ float damp_h; //history
+ int pos;
+ int extra_spread_frames;
+
+ Comb() { size=0; buffer=0; feedback=0; damp_h=0; pos=0; }
+ };
+
+ struct AllPass {
+
+ int size;
+ float *buffer;
+ int pos;
+ int extra_spread_frames;
+ AllPass() { size=0; buffer=0; pos=0; }
+ };
+
+ Comb comb[MAX_COMBS];
+ AllPass allpass[MAX_ALLPASS];
+ float *input_buffer;
+ float *echo_buffer;
+ int echo_buffer_size;
+ int echo_buffer_pos;
+
+ float hpf_h1,hpf_h2;
+
+
+ struct Parameters {
+
+ float room_size;
+ float damp;
+ float wet;
+ float dry;
+ float mix_rate;
+ float extra_spread_base;
+ float extra_spread;
+ float predelay;
+ float predelay_fb;
+ float hpf;
+ } params;
+
+ void configure_buffers();
+ void update_parameters();
+ void clear_buffers();
+public:
+
+ void set_room_size(float p_size);
+ void set_damp(float p_damp);
+ void set_wet(float p_wet);
+ void set_dry(float p_dry);
+ void set_predelay(float p_predelay); // in ms
+ void set_predelay_feedback(float p_predelay_fb); // in ms
+ void set_highpass(float p_frq);
+ void set_mix_rate(float p_mix_rate);
+ void set_extra_spread(float p_spread);
+ void set_extra_spread_base(float p_sec);
+
+ void process(float *p_src,float *p_dst,int p_frames);
+
+ Reverb();
+
+ ~Reverb();
+
+};
+
+
+
+#endif
diff --git a/servers/audio/reverb_sw.cpp b/servers/audio/reverb_sw.cpp
index 5721403ba3..5e02f37679 100644
--- a/servers/audio/reverb_sw.cpp
+++ b/servers/audio/reverb_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -100,145 +100,145 @@ struct ReverbParamsSW {
static ReverbParamsSW reverb_params_Room = {
0x26C0/2,
-// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
+ //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
0x6D80, 0x54B8, -0x4130, 0x0000, 0x0000, -0x4580,
-// gReva gRevb gInputL gInputR
+ //gReva gRevb gInputL gInputR
0x5800, 0x5300, -0x8000, -0x8000,
-// nRevaOldL nRevaOldR nRevbOldL nRevbOldR
+ //nRevaOldL nRevaOldR nRevbOldL nRevbOldR
0x01B4 - 0x007D, 0x0136 - 0x007D, 0x00B8 - 0x005B, 0x005C - 0x005B,
-// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
+ //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
0x04D6, 0x0333, 0x03F0, 0x0227, 0x0374, 0x01EF,
-// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
+ //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
0x0334, 0x01B5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
+ //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
0x0000, 0x0000, 0x01B4, 0x0136, 0x00B8, 0x005C
};
static ReverbParamsSW reverb_params_StudioSmall = {
0x1F40/2,
-// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
+ //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
0x70F0, 0x4FA8, -0x4320, 0x4410, -0x3F10, -0x6400,
-// gReva gRevb gInputL gInputR
+ //gReva gRevb gInputL gInputR
0x5280, 0x4EC0, -0x8000, -0x8000,
-// nRevaOldL nRevaOldR nRevbOldL nRevbOldR
+ //nRevaOldL nRevaOldR nRevbOldL nRevbOldR
0x00B4 - 0x0033, 0x0080 - 0x0033, 0x004C - 0x0025, 0x0026 - 0x0025,
-// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
+ //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
0x03E4, 0x031B, 0x03A4, 0x02AF, 0x0372, 0x0266,
-// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
+ //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
0x031C, 0x025D, 0x025C, 0x018E, 0x022F, 0x0135, 0x01D2, 0x00B7,
-// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
+ //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
0x018F, 0x00B5, 0x00B4, 0x0080, 0x004C, 0x0026
};
static ReverbParamsSW reverb_params_StudioMedium = {
0x4840/2,
-// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
+ //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
0x70F0, 0x4FA8, -0x4320, 0x4510, -0x4110, -0x4B40,
-// gReva gRevb gInputL gInputR
+ //gReva gRevb gInputL gInputR
0x5280, 0x4EC0, -0x8000, -0x8000,
-// nRevaOldL nRevaOldR nRevbOldL nRevbOldR
+ //nRevaOldL nRevaOldR nRevbOldL nRevbOldR
0x0264 - 0x00B1, 0x01B2 - 0x00B1, 0x0100 - 0x007F, 0x0080 - 0x007F,
-// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
+ //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
0x0904, 0x076B, 0x0824, 0x065F, 0x07A2, 0x0616,
-// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
+ //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
0x076C, 0x05ED, 0x05EC, 0x042E, 0x050F, 0x0305, 0x0462, 0x02B7,
-// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
+ //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
0x042F, 0x0265, 0x0264, 0x01B2, 0x0100, 0x0080
};
static ReverbParamsSW reverb_params_StudioLarge = {
0x6FE0/2,
-// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
+ //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
0x6F60, 0x4FA8, -0x4320, 0x4510, -0x4110, -0x5980,
-// gReva gRevb gInputL gInputR
+ //gReva gRevb gInputL gInputR
0x5680, 0x52C0, -0x8000, -0x8000,
-// nRevaOldL nRevaOldR nRevbOldL nRevbOldR
+ //nRevaOldL nRevaOldR nRevbOldL nRevbOldR
0x031C - 0x00E3, 0x0238 - 0x00E3, 0x0154 - 0x00A9, 0x00AA - 0x00A9,
-// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
+ //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
0x0DFB, 0x0B58, 0x0D09, 0x0A3C, 0x0BD9, 0x0973,
-// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
+ //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
0x0B59, 0x08DA, 0x08D9, 0x05E9, 0x07EC, 0x04B0, 0x06EF, 0x03D2,
-// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
+ //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
0x05EA, 0x031D, 0x031C, 0x0238, 0x0154, 0x00AA
};
static ReverbParamsSW reverb_params_Hall = {
0xADE0/2,
-// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
+ //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
0x6000, 0x5000, 0x4C00, -0x4800, -0x4400, -0x4000,
-// gReva gRevb gInputL gInputR
+ //gReva gRevb gInputL gInputR
0x6000, 0x5C00, -0x8000, -0x8000,
-// nRevaOldL nRevaOldR nRevbOldL nRevbOldR
+ //nRevaOldL nRevaOldR nRevbOldL nRevbOldR
0x05C0 - 0x01A5, 0x041A - 0x01A5, 0x0274 - 0x0139, 0x013A - 0x0139,
-// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
+ //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
0x15BA, 0x11BB, 0x14C2, 0x10BD, 0x11BC, 0x0DC1,
-// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
+ //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
0x11C0, 0x0DC3, 0x0DC0, 0x09C1, 0x0BC4, 0x07C1, 0x0A00, 0x06CD,
-// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
+ //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
0x09C2, 0x05C1, 0x05C0, 0x041A, 0x0274, 0x013A
};
static ReverbParamsSW reverb_params_SpaceEcho = {
0xF6C0/2,
-// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
+ //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
0x7E00, 0x5000, -0x4C00, -0x5000, 0x4C00, -0x5000,
-// gReva gRevb gInputL gInputR
+ //gReva gRevb gInputL gInputR
0x6000, 0x5400, -0x8000, -0x8000,
-// nRevaOldL nRevaOldR nRevbOldL nRevbOldR
+ //nRevaOldL nRevaOldR nRevbOldL nRevbOldR
0x0AE0 - 0x033D, 0x07A2 - 0x033D, 0x0464 - 0x0231, 0x0232 - 0x0231,
-// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
+ //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
0x1ED6, 0x1A31, 0x1D14, 0x183B, 0x1BC2, 0x16B2,
-// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
+ //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
0x1A32, 0x15EF, 0x15EE, 0x1055, 0x1334, 0x0F2D, 0x11F6, 0x0C5D,
-// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
+ //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
0x1056, 0x0AE1, 0x0AE0, 0x07A2, 0x0464, 0x0232
};
static ReverbParamsSW reverb_params_Echo = {
0x18040/2,
-// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
+ //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
0x7FFF, 0x7FFF, 0x0000, 0x0000, 0x0000, -0x7F00,
-// gReva gRevb gInputL gInputR
+ //gReva gRevb gInputL gInputR
0x0000, 0x0000, -0x8000, -0x8000,
-// nRevaOldL nRevaOldR nRevbOldL nRevbOldR
+ //nRevaOldL nRevaOldR nRevbOldL nRevbOldR
0x1004 - 0x0001, 0x1002 - 0x0001, 0x0004 - 0x0001, 0x0002 - 0x0001,
-// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
+ //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
0x1FFF, 0x0FFF, 0x1005, 0x0005, 0x0000, 0x0000,
-// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
+ //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
0x1005, 0x0005, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
+ //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
0x0000, 0x0000, 0x1004, 0x1002, 0x0004, 0x0002
};
static ReverbParamsSW reverb_params_Delay = {
0x18040/2,
-// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
+ //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
0x7FFF, 0x7FFF, 0x0000, 0x0000, 0x0000, 0x0000,
-// gReva gRevb gInputL gInputR
+ //gReva gRevb gInputL gInputR
0x0000, 0x0000, -0x8000, -0x8000,
-// nRevaOldL nRevaOldR nRevbOldL nRevbOldR
+ //nRevaOldL nRevaOldR nRevbOldL nRevbOldR
0x1004 - 0x0001, 0x1002 - 0x0001, 0x0004 - 0x0001, 0x0002 - 0x0001,
-// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
+ //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
0x1FFF, 0x0FFF, 0x1005, 0x0005, 0x0000, 0x0000,
-// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
+ //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
0x1005, 0x0005, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
-// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
+ //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
0x0000, 0x0000, 0x1004, 0x1002, 0x0004, 0x0002
};
static ReverbParamsSW reverb_params_HalfEcho = {
0x3C00/2,
-// gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
+ //gLPF gEcho0 gEcho1 gEcho2 gEcho3 gWall
0x70F0, 0x4FA8, -0x4320, 0x4510, -0x4110, -0x7B00,
-// gReva gRevb gInputL gInputR
+ //gReva gRevb gInputL gInputR
0x5F80, 0x54C0, -0x8000, -0x8000,
-// nRevaOldL nRevaOldR nRevbOldL nRevbOldR
+ //nRevaOldL nRevaOldR nRevbOldL nRevbOldR
0x0058 - 0x0017, 0x0040 - 0x0017, 0x0028 - 0x0013, 0x0014 - 0x0013,
-// nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
+ //nLwlNew nRwrNew nEcho0L nEcho0R nEcho1L nEcho1R
0x0371, 0x02AF, 0x02E5, 0x01DF, 0x02B0, 0x01D7,
-// nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
+ //nLwlOld nRwrOld nLwrNew nRwlNew nEcho2L nEcho2R nEcho3L nEcho3R
0x0358, 0x026A, 0x01D6, 0x011E, 0x012D, 0x00B1, 0x011F, 0x0059,
-// nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
+ //nLwrOld nRwlOld nRevaNewL nRevaNewR nRevbNewL nRevbNewR
0x01A0, 0x00E3, 0x0058, 0x0040, 0x0028, 0x0014
};
@@ -265,7 +265,7 @@ bool ReverbSW::process(int *p_input,int *p_output,int p_frames,int p_stereo_stri
// p_input must point to a non-looping buffer.
// BOTH p_input and p_output must be touched (use ClearModuleBuffer).
- // �������LOCAL MACROS ������۲
+ // LOCAL MACROS
#undef LM_SETSRCOFFSET
#define LM_SETSRCOFFSET(x) \
@@ -296,14 +296,14 @@ MULSHIFT_S32 ( x, current_params->y, 15 )
#undef LM_REVERB
#define LM_REVERB(x) reverb_buffer[ (x) + cSample ]
- // �������LOCAL VARIABLES ������۲
+ // LOCAL VARIABLES
unsigned int Offset;
int lwl, lwr, rwl, rwr;
-// unsigned char HZShift;
+ //unsigned char HZShift;
- // �������CODE ������۲
+ // CODE
lwl = state.lwl;
diff --git a/servers/audio/reverb_sw.h b/servers/audio/reverb_sw.h
index b028a245c8..d9f16a5fbb 100644
--- a/servers/audio/reverb_sw.h
+++ b/servers/audio/reverb_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio/sample_manager_sw.cpp b/servers/audio/sample_manager_sw.cpp
deleted file mode 100644
index 60f4d16659..0000000000
--- a/servers/audio/sample_manager_sw.cpp
+++ /dev/null
@@ -1,320 +0,0 @@
-/*************************************************************************/
-/* sample_manager_sw.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 "sample_manager_sw.h"
-
-#include "print_string.h"
-
-SampleManagerSW::~SampleManagerSW()
-{
-}
-
-
-
-RID SampleManagerMallocSW::sample_create(AS::SampleFormat p_format, bool p_stereo, int p_length) {
-
- Sample *s = memnew( Sample );
- int datalen = p_length;
- if (p_format==AS::SAMPLE_FORMAT_PCM16)
- datalen*=2;
- else if (p_format==AS::SAMPLE_FORMAT_IMA_ADPCM) {
- if (datalen&1) {
- datalen++;
- }
- datalen/=2;
- datalen+=4;
- }
-
- if (p_stereo)
- datalen*=2;
-
-#define SAMPLE_EXTRA 16
-
- s->data = memalloc(datalen+SAMPLE_EXTRA); //help the interpolator by allocating a little more..
- for(int i=0;i<SAMPLE_EXTRA;i++) {
-
- uint8_t *data = (uint8_t*)s->data;
- data[datalen+i]=0;
- }
- if (!s->data) {
-
- memdelete(s);
- ERR_EXPLAIN("Cannot allocate sample of requested size.");
- ERR_FAIL_V(RID());
- }
-
- s->format=p_format;
- s->length=p_length;
- s->length_bytes=datalen;
- s->stereo=p_stereo;
- s->loop_begin=0;
- s->loop_end=0;
- s->loop_format=AS::SAMPLE_LOOP_NONE;
- s->mix_rate=44100;
-
- AudioServer::get_singleton()->lock();
- RID rid = sample_owner.make_rid(s);
- AudioServer::get_singleton()->unlock();
-
- return rid;
-}
-
-void SampleManagerMallocSW::sample_set_description(RID p_sample, const String& p_description) {
-
- Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND(!s);
-
- s->description=p_description;
-}
-
-String SampleManagerMallocSW::sample_get_description(RID p_sample) const {
-
- const Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!s,String());
-
- return s->description;
-}
-
-
-AS::SampleFormat SampleManagerMallocSW::sample_get_format(RID p_sample) const {
-
- const Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!s,AS::SAMPLE_FORMAT_PCM8);
-
- return s->format;
-}
-
-bool SampleManagerMallocSW::sample_is_stereo(RID p_sample) const {
-
- const Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!s,false);
-
- return s->stereo;
-
-}
-int SampleManagerMallocSW::sample_get_length(RID p_sample) const {
-
- const Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!s,-1);
-
- return s->length;
-}
-
-void SampleManagerMallocSW::sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer) {
-
- Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND(!s);
-
- int buff_size=p_buffer.size();
- ERR_FAIL_COND(buff_size==0);
-
-
- ERR_EXPLAIN("Sample buffer size does not match sample size.");
- //print_line("len bytes: "+itos(s->length_bytes)+" bufsize: "+itos(buff_size));
- ERR_FAIL_COND(s->length_bytes!=buff_size);
- DVector<uint8_t>::Read buffer_r=p_buffer.read();
- const uint8_t *src = buffer_r.ptr();
- uint8_t *dst = (uint8_t*)s->data;
- //print_line("set data: "+itos(s->length_bytes));
-
- for(int i=0;i<s->length_bytes;i++) {
-
- dst[i]=src[i];
- }
-
- switch(s->format) {
-
- case AS::SAMPLE_FORMAT_PCM8: {
-
- if (s->stereo) {
- dst[s->length]=dst[s->length-2];
- dst[s->length+1]=dst[s->length-1];
- } else {
-
- dst[s->length]=dst[s->length-1];
- }
-
- } break;
- case AS::SAMPLE_FORMAT_PCM16: {
-
- if (s->stereo) {
- dst[s->length]=dst[s->length-4];
- dst[s->length+1]=dst[s->length-3];
- dst[s->length+2]=dst[s->length-2];
- dst[s->length+3]=dst[s->length-1];
- } else {
-
- dst[s->length]=dst[s->length-2];
- dst[s->length+1]=dst[s->length-1];
- }
-
- } break;
-
- }
-
-
-
-}
-
-const DVector<uint8_t> SampleManagerMallocSW::sample_get_data(RID p_sample) const {
-
- Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!s,DVector<uint8_t>());
-
- DVector<uint8_t> ret_buffer;
- ret_buffer.resize(s->length_bytes);
- DVector<uint8_t>::Write buffer_w=ret_buffer.write();
- uint8_t *dst = buffer_w.ptr();
- const uint8_t *src = (const uint8_t*)s->data;
-
- for(int i=0;i<s->length_bytes;i++) {
-
- dst[i]=src[i];
- }
-
- buffer_w = DVector<uint8_t>::Write(); //unlock
-
- return ret_buffer;
-}
-
-void *SampleManagerMallocSW::sample_get_data_ptr(RID p_sample) const {
-
- const Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!s,NULL);
-
- return s->data;
-
-}
-
-void SampleManagerMallocSW::sample_set_mix_rate(RID p_sample,int p_rate) {
-
- ERR_FAIL_COND(p_rate<1);
-
- Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND(!s);
-
- s->mix_rate=p_rate;
-
-
-}
-int SampleManagerMallocSW::sample_get_mix_rate(RID p_sample) const {
-
- const Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!s,-1);
-
- return s->mix_rate;
-
-}
-void SampleManagerMallocSW::sample_set_loop_format(RID p_sample,AS::SampleLoopFormat p_format) {
-
- Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND(!s);
-
- s->loop_format=p_format;
-
-}
-AS::SampleLoopFormat SampleManagerMallocSW::sample_get_loop_format(RID p_sample) const {
-
- const Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!s,AS::SAMPLE_LOOP_NONE);
-
- return s->loop_format;
-}
-
-void SampleManagerMallocSW::sample_set_loop_begin(RID p_sample,int p_pos) {
-
- Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND(!s);
- ERR_FAIL_INDEX(p_pos,s->length);
-
- s->loop_begin=p_pos;
-}
-int SampleManagerMallocSW::sample_get_loop_begin(RID p_sample) const {
-
- const Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!s,-1);
-
- return s->loop_begin;
-}
-
-void SampleManagerMallocSW::sample_set_loop_end(RID p_sample,int p_pos) {
-
- Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND(!s);
- if (p_pos>s->length)
- p_pos=s->length;
- s->loop_end=p_pos;
-
-}
-int SampleManagerMallocSW::sample_get_loop_end(RID p_sample) const {
-
- const Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND_V(!s,-1);
-
- return s->loop_end;
-}
-
-bool SampleManagerMallocSW::is_sample(RID p_sample) const {
-
- return sample_owner.owns(p_sample);
-
-}
-void SampleManagerMallocSW::free(RID p_sample) {
-
- Sample *s = sample_owner.get(p_sample);
- ERR_FAIL_COND(!s);
- AudioServer::get_singleton()->lock();
- sample_owner.free(p_sample);
- AudioServer::get_singleton()->unlock();
-
- memfree(s->data);
- memdelete(s);
-
-}
-
-SampleManagerMallocSW::SampleManagerMallocSW() {
-
-
-}
-
-SampleManagerMallocSW::~SampleManagerMallocSW() {
-
- // check for sample leakage
- List<RID> owned_list;
- sample_owner.get_owned_list(&owned_list);
-
- while(owned_list.size()) {
-
- Sample *s = sample_owner.get(owned_list.front()->get());
- String err="Leaked sample of size: "+itos(s->length_bytes)+" description: "+s->description;
- ERR_PRINT(err.utf8().get_data());
- free(owned_list.front()->get());
- owned_list.pop_front();
- }
-
-}
diff --git a/servers/audio/sample_manager_sw.h b/servers/audio/sample_manager_sw.h
deleted file mode 100644
index bd7a11a3d2..0000000000
--- a/servers/audio/sample_manager_sw.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*************************************************************************/
-/* sample_manager_sw.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 SAMPLE_MANAGER_SW_H
-#define SAMPLE_MANAGER_SW_H
-
-#include "servers/audio_server.h"
-
-class SampleManagerSW {
-public:
-
- /* SAMPLE API */
-
- virtual RID sample_create(AS::SampleFormat p_format, bool p_stereo, int p_length)=0;
-
- virtual void sample_set_description(RID p_sample, const String& p_description)=0;
- virtual String sample_get_description(RID p_sample) const=0;
-
- virtual AS::SampleFormat sample_get_format(RID p_sample) const=0;
- virtual bool sample_is_stereo(RID p_sample) const=0;
- virtual int sample_get_length(RID p_sample) const=0;
-
- virtual void sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer)=0;
- virtual const DVector<uint8_t> sample_get_data(RID p_sample) const=0;
-
- virtual void *sample_get_data_ptr(RID p_sample) const=0;
-
- virtual void sample_set_mix_rate(RID p_sample,int p_rate)=0;
- virtual int sample_get_mix_rate(RID p_sample) const=0;
-
- virtual void sample_set_loop_format(RID p_sample,AS::SampleLoopFormat p_format)=0;
- virtual AS::SampleLoopFormat sample_get_loop_format(RID p_sample) const=0;
-
- virtual void sample_set_loop_begin(RID p_sample,int p_pos)=0;
- virtual int sample_get_loop_begin(RID p_sample) const=0;
-
- virtual void sample_set_loop_end(RID p_sample,int p_pos)=0;
- virtual int sample_get_loop_end(RID p_sample) const=0;
-
- virtual bool is_sample(RID) const=0;
- virtual void free(RID p_sample)=0;
-
-
-
- virtual ~SampleManagerSW();
-};
-
-
-class SampleManagerMallocSW : public SampleManagerSW {
-
-
- struct Sample {
-
- void *data;
- int length;
- int length_bytes;
- AS::SampleFormat format;
- bool stereo;
- AS::SampleLoopFormat loop_format;
- int loop_begin;
- int loop_end;
- int mix_rate;
- String description;
- };
-
- mutable RID_Owner<Sample> sample_owner;
-public:
-
- /* SAMPLE API */
-
- virtual RID sample_create(AS::SampleFormat p_format, bool p_stereo, int p_length);
-
- virtual void sample_set_description(RID p_sample, const String& p_description);
- virtual String sample_get_description(RID p_sample) const;
-
- virtual AS::SampleFormat sample_get_format(RID p_sample) const;
- virtual bool sample_is_stereo(RID p_sample) const;
- virtual int sample_get_length(RID p_sample) const;
-
- virtual void sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer);
- virtual const DVector<uint8_t> sample_get_data(RID p_sample) const;
-
- virtual void *sample_get_data_ptr(RID p_sample) const;
-
- virtual void sample_set_mix_rate(RID p_sample,int p_rate);
- virtual int sample_get_mix_rate(RID p_sample) const;
-
- virtual void sample_set_loop_format(RID p_sample,AS::SampleLoopFormat p_format);
- virtual AS::SampleLoopFormat sample_get_loop_format(RID p_sample) const;
-
- virtual void sample_set_loop_begin(RID p_sample,int p_pos);
- virtual int sample_get_loop_begin(RID p_sample) const;
-
- virtual void sample_set_loop_end(RID p_sample,int p_pos);
- virtual int sample_get_loop_end(RID p_sample) const;
-
- virtual bool is_sample(RID) const;
- virtual void free(RID p_sample);
-
- SampleManagerMallocSW();
- virtual ~SampleManagerMallocSW();
-};
-
-#endif // SAMPLE_MANAGER_SW_H
diff --git a/servers/audio/voice_rb_sw.h b/servers/audio/voice_rb_sw.h
index f785646577..cbf1392482 100644
--- a/servers/audio/voice_rb_sw.h
+++ b/servers/audio/voice_rb_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/audio_server.cpp b/servers/audio_server.cpp
index 1f0a2e403a..192d958a64 100644
--- a/servers/audio_server.cpp
+++ b/servers/audio_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,178 +27,1195 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "audio_server.h"
-#include "globals.h"
+#include "global_config.h"
+#include "os/os.h"
+#include "servers/audio/effects/audio_effect_compressor.h"
+#include "io/resource_loader.h"
+#include "os/file_access.h"
+#ifdef TOOLS_ENABLED
-void AudioMixer::audio_mixer_chunk_call(int p_frames) {
+#define MARK_EDITED set_edited(true);
- AudioServer::get_singleton()->audio_mixer_chunk_callback(p_frames);
+#else
+
+#define MARK_EDITED
+
+#endif
+
+AudioDriver *AudioDriver::singleton=NULL;
+AudioDriver *AudioDriver::get_singleton() {
+
+ return singleton;
}
-AudioMixer *AudioServer::EventStream::get_mixer() const {
+void AudioDriver::set_singleton() {
- return AudioServer::get_singleton()->get_mixer();
+ singleton=this;
}
-AudioServer *AudioServer::singleton=NULL;
+void AudioDriver::audio_server_process(int p_frames,int32_t *p_buffer,bool p_update_mix_time) {
-AudioServer *AudioServer::get_singleton() {
- return singleton;
+ if (p_update_mix_time)
+ update_mix_time(p_frames);
+
+ if (AudioServer::get_singleton())
+ AudioServer::get_singleton()->_driver_process(p_frames,p_buffer);
+}
+
+
+
+void AudioDriver::update_mix_time(int p_frames) {
+
+ _mix_amount+=p_frames;
+ _last_mix_time=OS::get_singleton()->get_ticks_usec();
+}
+
+double AudioDriver::get_mix_time() const {
+
+ double total = (OS::get_singleton()->get_ticks_usec() - _last_mix_time) / 1000000.0;
+ total+=_mix_amount/(double)get_mix_rate();
+ return total;
+
+}
+
+
+AudioDriver::AudioDriver() {
+
+ _last_mix_time=0;
+ _mix_amount=0;
+}
+
+
+AudioDriver *AudioDriverManager::drivers[MAX_DRIVERS];
+int AudioDriverManager::driver_count=0;
+
+
+void AudioDriverManager::add_driver(AudioDriver *p_driver) {
+
+ ERR_FAIL_COND(driver_count>=MAX_DRIVERS);
+ drivers[driver_count++]=p_driver;
}
-void AudioServer::sample_set_signed_data(RID p_sample, const DVector<float>& p_buffer) {
+int AudioDriverManager::get_driver_count() {
- SampleFormat format = sample_get_format(p_sample);
+ return driver_count;
+}
+AudioDriver *AudioDriverManager::get_driver(int p_driver) {
+
+ ERR_FAIL_INDEX_V(p_driver,driver_count,NULL);
+ return drivers[p_driver];
+}
+
+
+//////////////////////////////////////////////
+//////////////////////////////////////////////
+//////////////////////////////////////////////
+//////////////////////////////////////////////
+
+void AudioServer::_driver_process(int p_frames,int32_t* p_buffer) {
+
+ int todo=p_frames;
- ERR_EXPLAIN("IMA ADPCM is not supported.");
- ERR_FAIL_COND(format==SAMPLE_FORMAT_IMA_ADPCM);
+ while(todo) {
- int len = p_buffer.size();
- ERR_FAIL_COND( len == 0 );
+ if (to_mix==0) {
+ _mix_step();
+ }
- DVector<uint8_t> data;
- DVector<uint8_t>::Write w;
- DVector<float>::Read r = p_buffer.read();
+ int to_copy = MIN(to_mix,todo);
- switch(format) {
- case SAMPLE_FORMAT_PCM8: {
- data.resize(len);
- w=data.write();
+ Bus *master = buses[0];
- int8_t *samples8 = (int8_t*)w.ptr();
+ int from = buffer_size-to_mix;
+ int from_buf=p_frames-todo;
- for(int i=0;i<len;i++) {
+ //master master, send to output
+ int cs = master->channels.size();
+ for(int k=0;k<cs;k++) {
- float sample = Math::floor( r[i] * (1<<8) );
- if (sample<-128)
- sample=-128;
- else if (sample>127)
- sample=127;
- samples8[i]=sample;
+ if (master->channels[k].active) {
+
+ AudioFrame *buf = master->channels[k].buffer.ptr();
+
+ for(int j=0;j<to_copy;j++) {
+
+ float l = CLAMP(buf[from+j].l,-1.0,1.0);
+ int32_t vl = l*((1<<20)-1);
+ p_buffer[(from_buf+j)*(cs*2)+k*2+0]=vl<<11;
+
+ float r = CLAMP(buf[from+j].r,-1.0,1.0);
+ int32_t vr = r*((1<<20)-1);
+ p_buffer[(from_buf+j)*(cs*2)+k*2+1]=vr<<11;
+ }
+
+ } else {
+ for(int j=0;j<to_copy;j++) {
+
+ p_buffer[(from_buf+j)*(cs*2)+k*2+0]=0;
+ p_buffer[(from_buf+j)*(cs*2)+k*2+1]=0;
+ }
}
- } break;
- case SAMPLE_FORMAT_PCM16: {
- data.resize(len*2);
- w=data.write();
- int16_t *samples16 = (int16_t*)w.ptr();
+ }
+
+ todo-=to_copy;
+ to_mix-=to_copy;
+
+ }
+
+}
+
+void AudioServer::_mix_step() {
+
+ for(int i=0;i<buses.size();i++) {
+ Bus *bus = buses[i];
+ bus->index_cache=i; //might be moved around by editor, so..
+ for(int k=0;k<bus->channels.size();k++) {
+
+ bus->channels[k].used=false;
+ }
+ }
+
+ //make callbacks for mixing the audio
+ for (Set<CallbackItem>::Element *E=callbacks.front();E;E=E->next()) {
+
+ E->get().callback(E->get().userdata);
+ }
+
+ for(int i=buses.size()-1;i>=0;i--) {
+ //go bus by bus
+ Bus *bus = buses[i];
+
+
+ for(int k=0;k<bus->channels.size();k++) {
+
+ if (bus->channels[k].active && !bus->channels[k].used) {
+ //buffer was not used, but it's still active, so it must be cleaned
+ AudioFrame *buf = bus->channels[k].buffer.ptr();
+
+ for(uint32_t j=0;j<buffer_size;j++) {
+
+ buf[j]=AudioFrame(0,0);
+ }
+ }
+
+ }
+
+
+ //process effects
+ for(int j=0;j<bus->effects.size();j++) {
+
+ if (!bus->effects[j].enabled)
+ continue;
+
+ for(int k=0;k<bus->channels.size();k++) {
+
+ if (!bus->channels[k].active)
+ continue;
+ bus->channels[k].effect_instances[j]->process(bus->channels[k].buffer.ptr(),temp_buffer[k].ptr(),buffer_size);
+ }
+
+ //swap buffers, so internal buffer always has the right data
+ for(int k=0;k<bus->channels.size();k++) {
+
+ if (!buses[i]->channels[k].active)
+ continue;
+ SWAP(bus->channels[k].buffer,temp_buffer[k]);
+ }
+ }
+
+ //process send
+
+ Bus *send=NULL;
+
+ if (i>0) {
+ //everything has a send save for master bus
+ if (!bus_map.has(bus->send)) {
+ send=buses[0];
+ } else {
+ send=bus_map[bus->send];
+ if (send->index_cache>=bus->index_cache) { //invalid, send to master
+ send=buses[0];
+ }
+ }
+ }
+
+
+ for(int k=0;k<bus->channels.size();k++) {
+
+ if (!bus->channels[k].active)
+ continue;
+
+ AudioFrame *buf = bus->channels[k].buffer.ptr();
+
+
+ AudioFrame peak = AudioFrame(0,0);
+ for(uint32_t j=0;j<buffer_size;j++) {
+ float l = ABS(buf[j].l);
+ if (l>peak.l) {
+ peak.l=l;
+ }
+ float r = ABS(buf[j].r);
+ if (r>peak.r) {
+ peak.r=r;
+ }
+ }
+
+ bus->channels[k].peak_volume=AudioFrame(Math::linear2db(peak.l+0.0000000001),Math::linear2db(peak.r+0.0000000001));
+
+
+ if (!bus->channels[k].used) {
+ //see if any audio is contained, because channel was not used
+
+
+ if (MAX(peak.r,peak.l) > Math::db2linear(channel_disable_treshold_db)) {
+ bus->channels[k].last_mix_with_audio=mix_frames;
+ } else if (mix_frames-bus->channels[k].last_mix_with_audio > channel_disable_frames ) {
+ bus->channels[k].active=false;
+ continue; //went inactive, dont mix.
+ }
+ }
+
+ if (send) {
+ //if not master bus, send
+ AudioFrame *target_buf = thread_get_channel_mix_buffer(send->index_cache,k);
+
+ for(uint32_t j=0;j<buffer_size;j++) {
+ target_buf[j]+=buf[j];
+ }
+ }
+
+ }
+
+ }
+
+
+ mix_frames+=buffer_size;
+ to_mix=buffer_size;
+
+}
+
+AudioFrame *AudioServer::thread_get_channel_mix_buffer(int p_bus,int p_buffer) {
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),NULL);
+ ERR_FAIL_INDEX_V(p_buffer,buses[p_bus]->channels.size(),NULL);
+
+ AudioFrame *data = buses[p_bus]->channels[p_buffer].buffer.ptr();
+
+
+ if (!buses[p_bus]->channels[p_buffer].used) {
+ buses[p_bus]->channels[p_buffer].used=true;
+ buses[p_bus]->channels[p_buffer].active=true;
+ buses[p_bus]->channels[p_buffer].last_mix_with_audio=mix_frames;
+ for(uint32_t i=0;i<buffer_size;i++) {
+ data[i]=AudioFrame(0,0);
+ }
+ }
+
+ return data;
+}
+
+int AudioServer::thread_get_mix_buffer_size() const {
+
+ return buffer_size;
+}
+
+int AudioServer::thread_find_bus_index(const StringName& p_name) {
+
+ if (bus_map.has(p_name)) {
+ return bus_map[p_name]->index_cache;
+ } else {
+ return 0;
+ }
+
+}
+
+void AudioServer::set_bus_count(int p_count) {
+
+ ERR_FAIL_COND(p_count<1);
+ ERR_FAIL_INDEX(p_count,256);
+
+ MARK_EDITED
+
+ lock();
+ int cb = buses.size();
+
+ if (p_count<buses.size()) {
+ for(int i=p_count;i<buses.size();i++) {
+ bus_map.erase(buses[i]->name);
+ memdelete(buses[i]);
+ }
+ }
+
+ buses.resize(p_count);
+
+ for(int i=cb;i<buses.size();i++) {
+
+ String attempt="New Bus";
+ int attempts=1;
+ while(true) {
+
+ bool name_free=true;
+ for(int j=0;j<i;j++) {
+
+ if (buses[j]->name==attempt) {
+ name_free=false;
+ break;
+ }
+ }
+
+ if (!name_free) {
+ attempts++;
+ attempt="New Bus " +itos(attempts);
+ } else {
+ break;
+ }
+
+ }
+
+
+ buses[i]=memnew(Bus);
+ buses[i]->channels.resize(_get_channel_count());
+ for(int j=0;j<_get_channel_count();j++) {
+ buses[i]->channels[j].buffer.resize(buffer_size);
+ }
+ buses[i]->name=attempt;
+ buses[i]->solo=false;
+ buses[i]->mute=false;
+ buses[i]->bypass=false;
+ buses[i]->volume_db=0;
+ if (i>0) {
+ buses[i]->send="Master";
+ }
+
+ bus_map[attempt]=buses[i];
+
+ }
+
+ unlock();
+
+ emit_signal("bus_layout_changed");
+}
+
+
+void AudioServer::remove_bus(int p_index) {
- for(int i=0;i<len;i++) {
+ ERR_FAIL_INDEX(p_index,buses.size());
+ ERR_FAIL_COND(p_index==0);
- float sample = Math::floor( r[i] * (1<<16) );
- if (sample<-32768)
- sample=-32768;
- else if (sample>32767)
- sample=32767;
- samples16[i]=sample;
+ MARK_EDITED
+
+ lock();
+ bus_map.erase(buses[p_index]->name);
+ memdelete(buses[p_index]);
+ buses.remove(p_index);
+ unlock();
+}
+
+void AudioServer::add_bus(int p_at_pos) {
+
+ MARK_EDITED
+
+ if (p_at_pos>=buses.size()) {
+ p_at_pos=-1;
+ } else if (p_at_pos==0) {
+ if (buses.size()>1)
+ p_at_pos=1;
+ else
+ p_at_pos=-1;
+ }
+
+ String attempt="New Bus";
+ int attempts=1;
+ while(true) {
+
+ bool name_free=true;
+ for(int j=0;j<buses.size();j++) {
+
+ if (buses[j]->name==attempt) {
+ name_free=false;
+ break;
}
+ }
+
+ if (!name_free) {
+ attempts++;
+ attempt="New Bus " +itos(attempts);
+ } else {
+ break;
+ }
+
+ }
+
+ Bus* bus =memnew(Bus);
+ bus->channels.resize(_get_channel_count());
+ for(int j=0;j<_get_channel_count();j++) {
+ bus->channels[j].buffer.resize(buffer_size);
+ }
+ bus->name=attempt;
+ bus->solo=false;
+ bus->mute=false;
+ bus->bypass=false;
+ bus->volume_db=0;
+
+ bus_map[attempt]=bus;
+
+ if (p_at_pos==-1)
+ buses.push_back(bus);
+ else
+ buses.insert(p_at_pos,bus);
+
+}
+
+void AudioServer::move_bus(int p_bus,int p_to_pos) {
+
+ ERR_FAIL_COND(p_bus<1 || p_bus>=buses.size());
+ ERR_FAIL_COND(p_to_pos!=-1 && (p_to_pos<1 || p_to_pos>buses.size()));
+
+ MARK_EDITED
+
+ if (p_bus==p_to_pos)
+ return;
+
+ Bus *bus = buses[p_bus];
+ buses.remove(p_bus);
+
+ if (p_to_pos==-1) {
+ buses.push_back(bus);
+ } else if (p_to_pos<p_bus) {
+ buses.insert(p_to_pos,bus);
+ } else {
+ buses.insert(p_to_pos-1,bus);
+ }
+}
+
+int AudioServer::get_bus_count() const {
+
+ return buses.size();
+}
+
+
+void AudioServer::set_bus_name(int p_bus,const String& p_name) {
+
+ ERR_FAIL_INDEX(p_bus,buses.size());
+ if (p_bus==0 && p_name!="Master")
+ return; //bus 0 is always master
+
+ MARK_EDITED
+
+ lock();
+
+ if (buses[p_bus]->name==p_name) {
+ unlock();
+ return;
+ }
+
+ String attempt=p_name;
+ int attempts=1;
+
+ while(true) {
+
+ bool name_free=true;
+ for(int i=0;i<buses.size();i++) {
+
+ if (buses[i]->name==attempt) {
+ name_free=false;
+ break;
+ }
+ }
+
+ if (name_free) {
+ break;
+ }
+
+ attempts++;
+ attempt=p_name+" "+itos(attempts);
+ }
+ bus_map.erase(buses[p_bus]->name);
+ buses[p_bus]->name=attempt;
+ bus_map[attempt]=buses[p_bus];
+ unlock();
+
+ emit_signal("bus_layout_changed");
+
+}
+String AudioServer::get_bus_name(int p_bus) const {
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),String());
+ return buses[p_bus]->name;
+}
+
+void AudioServer::set_bus_volume_db(int p_bus,float p_volume_db) {
+
+ ERR_FAIL_INDEX(p_bus,buses.size());
+
+ MARK_EDITED
+
+ buses[p_bus]->volume_db=p_volume_db;
+
+}
+float AudioServer::get_bus_volume_db(int p_bus) const {
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),0);
+ return buses[p_bus]->volume_db;
+
+}
+
+void AudioServer::set_bus_send(int p_bus,const StringName& p_send) {
+
+ ERR_FAIL_INDEX(p_bus,buses.size());
+
+ MARK_EDITED
+
+ buses[p_bus]->send=p_send;
+
+}
+
+StringName AudioServer::get_bus_send(int p_bus) const {
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),StringName());
+ return buses[p_bus]->send;
+
+}
+
+
+void AudioServer::set_bus_solo(int p_bus,bool p_enable) {
+
+ ERR_FAIL_INDEX(p_bus,buses.size());
+
+ MARK_EDITED
+
+ buses[p_bus]->solo=p_enable;
+
+}
+
+bool AudioServer::is_bus_solo(int p_bus) const{
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),false);
+
+ return buses[p_bus]->solo;
+
+}
+
+void AudioServer::set_bus_mute(int p_bus,bool p_enable){
+
+ ERR_FAIL_INDEX(p_bus,buses.size());
+
+ MARK_EDITED
+
+ buses[p_bus]->mute=p_enable;
+}
+bool AudioServer::is_bus_mute(int p_bus) const{
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),false);
+
+ return buses[p_bus]->mute;
+
+}
+
+void AudioServer::set_bus_bypass_effects(int p_bus,bool p_enable){
+
+ ERR_FAIL_INDEX(p_bus,buses.size());
+
+ MARK_EDITED
+
+ buses[p_bus]->bypass=p_enable;
+}
+bool AudioServer::is_bus_bypassing_effects(int p_bus) const{
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),false);
+
+ return buses[p_bus]->bypass;
+
+}
+
+
+void AudioServer::_update_bus_effects(int p_bus) {
+
+ for(int i=0;i<buses[p_bus]->channels.size();i++) {
+ buses[p_bus]->channels[i].effect_instances.resize(buses[p_bus]->effects.size());
+ for(int j=0;j<buses[p_bus]->effects.size();j++) {
+ Ref<AudioEffectInstance> fx = buses[p_bus]->effects[j].effect->instance();
+ if (fx->cast_to<AudioEffectCompressorInstance>()) {
+ fx->cast_to<AudioEffectCompressorInstance>()->set_current_channel(i);
+ }
+ buses[p_bus]->channels[i].effect_instances[j]=fx;
+
+ }
+ }
+}
+
+
+void AudioServer::add_bus_effect(int p_bus,const Ref<AudioEffect>& p_effect,int p_at_pos) {
+
+ ERR_FAIL_COND(p_effect.is_null());
+ ERR_FAIL_INDEX(p_bus,buses.size());
+
+ MARK_EDITED
+
+
+ lock();
+
+ Bus::Effect fx;
+ fx.effect=p_effect;
+ //fx.instance=p_effect->instance();
+ fx.enabled=true;
+
+ if (p_at_pos>=buses[p_bus]->effects.size() || p_at_pos<0) {
+ buses[p_bus]->effects.push_back(fx);
+ } else {
+ buses[p_bus]->effects.insert(p_at_pos,fx);
+ }
+
+ _update_bus_effects(p_bus);
+
+ unlock();
+}
+
+
+void AudioServer::remove_bus_effect(int p_bus,int p_effect) {
+
+ ERR_FAIL_INDEX(p_bus,buses.size());
+
+ MARK_EDITED
+
+
+ lock();
+
+ buses[p_bus]->effects.remove(p_effect);
+ _update_bus_effects(p_bus);
+
+ unlock();
+}
+
+int AudioServer::get_bus_effect_count(int p_bus) {
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),0);
+
+ return buses[p_bus]->effects.size();
+
+}
+
+Ref<AudioEffect> AudioServer::get_bus_effect(int p_bus,int p_effect) {
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),Ref<AudioEffect>());
+ ERR_FAIL_INDEX_V(p_effect,buses[p_bus]->effects.size(),Ref<AudioEffect>());
+
+ return buses[p_bus]->effects[p_effect].effect;
+
+}
+
+void AudioServer::swap_bus_effects(int p_bus,int p_effect,int p_by_effect) {
+
+ ERR_FAIL_INDEX(p_bus,buses.size());
+ ERR_FAIL_INDEX(p_effect,buses[p_bus]->effects.size());
+ ERR_FAIL_INDEX(p_by_effect,buses[p_bus]->effects.size());
+
+ MARK_EDITED
+
+
+ lock();
+ SWAP( buses[p_bus]->effects[p_effect], buses[p_bus]->effects[p_by_effect] );
+ _update_bus_effects(p_bus);
+ unlock();
+}
+
+void AudioServer::set_bus_effect_enabled(int p_bus,int p_effect,bool p_enabled) {
+
+ ERR_FAIL_INDEX(p_bus,buses.size());
+ ERR_FAIL_INDEX(p_effect,buses[p_bus]->effects.size());
+
+ MARK_EDITED
+
+
+ buses[p_bus]->effects[p_effect].enabled=p_enabled;
+
+}
+bool AudioServer::is_bus_effect_enabled(int p_bus,int p_effect) const {
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),false);
+ ERR_FAIL_INDEX_V(p_effect,buses[p_bus]->effects.size(),false);
+ return buses[p_bus]->effects[p_effect].enabled;
+
+}
+
+
+float AudioServer::get_bus_peak_volume_left_db(int p_bus,int p_channel) const {
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),0);
+ ERR_FAIL_INDEX_V(p_channel,buses[p_bus]->channels.size(),0);
+
+ return buses[p_bus]->channels[p_channel].peak_volume.l;
+
+}
+float AudioServer::get_bus_peak_volume_right_db(int p_bus,int p_channel) const {
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),0);
+ ERR_FAIL_INDEX_V(p_channel,buses[p_bus]->channels.size(),0);
+
+ return buses[p_bus]->channels[p_channel].peak_volume.r;
+
+}
+
+bool AudioServer::is_bus_channel_active(int p_bus,int p_channel) const {
+
+ ERR_FAIL_INDEX_V(p_bus,buses.size(),false);
+ ERR_FAIL_INDEX_V(p_channel,buses[p_bus]->channels.size(),false);
+
+ return buses[p_bus]->channels[p_channel].active;
+
+}
+
+void AudioServer::init() {
+
+ channel_disable_treshold_db=GLOBAL_DEF("audio/channel_disable_treshold_db",-60.0);
+ channel_disable_frames=float(GLOBAL_DEF("audio/channel_disable_time",2.0))*get_mix_rate();
+ buffer_size=1024; //harcoded for now
+ switch( get_speaker_mode() ) {
+ case SPEAKER_MODE_STEREO: {
+ temp_buffer.resize(1);
+ } break;
+ case SPEAKER_SURROUND_51: {
+ temp_buffer.resize(3);
+ } break;
+ case SPEAKER_SURROUND_71: {
+ temp_buffer.resize(4);
} break;
}
- w = DVector<uint8_t>::Write();
+ for(int i=0;i<temp_buffer.size();i++) {
+ temp_buffer[i].resize(buffer_size);
+ }
+
+ mix_count=0;
+ set_bus_count(1);;
+ set_bus_name(0,"Master");
- sample_set_data(p_sample,data);
+ if (AudioDriver::get_singleton())
+ AudioDriver::get_singleton()->start();
+#ifdef TOOLS_ENABLED
+ set_edited(false); //avoid editors from thinking this was edited
+#endif
}
-void AudioServer::_bind_methods() {
+void AudioServer::load_default_bus_layout() {
- ObjectTypeDB::bind_method(_MD("sample_create","format","stereo","length"), &AudioServer::sample_create );
- ObjectTypeDB::bind_method(_MD("sample_set_description","sample","description"), &AudioServer::sample_set_description );
- ObjectTypeDB::bind_method(_MD("sample_get_description","sample"), &AudioServer::sample_get_description );
+ if (FileAccess::exists("res://default_bus_layout.tres")) {
+ Ref<AudioBusLayout> default_layout = ResourceLoader::load("res://default_bus_layout.tres");
+ if (default_layout.is_valid()) {
+ set_bus_layout(default_layout);
+ }
+ }
- ObjectTypeDB::bind_method(_MD("sample_get_format","sample"), &AudioServer::sample_get_format );
- ObjectTypeDB::bind_method(_MD("sample_is_stereo","sample"), &AudioServer::sample_is_stereo );
- ObjectTypeDB::bind_method(_MD("sample_get_length","sample"), &AudioServer::sample_get_length );
+}
- ObjectTypeDB::bind_method(_MD("sample_set_signed_data","sample","data"), &AudioServer::sample_set_signed_data );
- ObjectTypeDB::bind_method(_MD("sample_set_data","sample","data"), &AudioServer::sample_set_data );
- ObjectTypeDB::bind_method(_MD("sample_get_data","sample"), &AudioServer::sample_get_data );
+void AudioServer::finish() {
- ObjectTypeDB::bind_method(_MD("sample_set_mix_rate","sample","mix_rate"), &AudioServer::sample_set_mix_rate );
- ObjectTypeDB::bind_method(_MD("sample_get_mix_rate","sample"), &AudioServer::sample_get_mix_rate );
+ for(int i=0;i<buses.size();i++) {
+ memdelete(buses[i]);
+ }
- ObjectTypeDB::bind_method(_MD("sample_set_loop_format","sample","loop_format"), &AudioServer::sample_set_loop_format );
- ObjectTypeDB::bind_method(_MD("sample_get_loop_format","sample"), &AudioServer::sample_get_loop_format );
+ buses.clear();
+}
+void AudioServer::update() {
- ObjectTypeDB::bind_method(_MD("sample_set_loop_begin","sample","pos"), &AudioServer::sample_set_loop_begin );
- ObjectTypeDB::bind_method(_MD("sample_get_loop_begin","sample"), &AudioServer::sample_get_loop_begin );
+}
- ObjectTypeDB::bind_method(_MD("sample_set_loop_end","sample","pos"), &AudioServer::sample_set_loop_end );
- ObjectTypeDB::bind_method(_MD("sample_get_loop_end","sample"), &AudioServer::sample_get_loop_end );
+/* MISC config */
+void AudioServer::lock() {
+ AudioDriver::get_singleton()->lock();
+}
+void AudioServer::unlock() {
- ObjectTypeDB::bind_method(_MD("voice_create"), &AudioServer::voice_create );
- ObjectTypeDB::bind_method(_MD("voice_play","voice","sample"), &AudioServer::voice_play );
- ObjectTypeDB::bind_method(_MD("voice_set_volume","voice","volume"), &AudioServer::voice_set_volume );
- ObjectTypeDB::bind_method(_MD("voice_set_pan","voice","pan","depth","height"), &AudioServer::voice_set_pan,DEFVAL(0),DEFVAL(0) );
- ObjectTypeDB::bind_method(_MD("voice_set_filter","voice","type","cutoff","resonance","gain"), &AudioServer::voice_set_filter,DEFVAL(0) );
- ObjectTypeDB::bind_method(_MD("voice_set_chorus","voice","chorus"), &AudioServer::voice_set_chorus );
- ObjectTypeDB::bind_method(_MD("voice_set_reverb","voice","room","reverb"), &AudioServer::voice_set_reverb );
- ObjectTypeDB::bind_method(_MD("voice_set_mix_rate","voice","rate"), &AudioServer::voice_set_mix_rate );
- ObjectTypeDB::bind_method(_MD("voice_set_positional","voice","enabled"), &AudioServer::voice_set_positional );
+ AudioDriver::get_singleton()->unlock();
+}
- ObjectTypeDB::bind_method(_MD("voice_get_volume","voice"), &AudioServer::voice_get_volume );
- ObjectTypeDB::bind_method(_MD("voice_get_pan","voice"), &AudioServer::voice_get_pan );
- ObjectTypeDB::bind_method(_MD("voice_get_pan_height","voice"), &AudioServer::voice_get_pan_height );
- ObjectTypeDB::bind_method(_MD("voice_get_pan_depth","voice"), &AudioServer::voice_get_pan_depth );
- ObjectTypeDB::bind_method(_MD("voice_get_filter_type","voice"), &AudioServer::voice_get_filter_type );
- ObjectTypeDB::bind_method(_MD("voice_get_filter_cutoff","voice"), &AudioServer::voice_get_filter_cutoff );
- ObjectTypeDB::bind_method(_MD("voice_get_filter_resonance","voice"), &AudioServer::voice_get_filter_resonance );
- ObjectTypeDB::bind_method(_MD("voice_get_chorus","voice"), &AudioServer::voice_get_chorus );
- ObjectTypeDB::bind_method(_MD("voice_get_reverb_type","voice"), &AudioServer::voice_get_reverb_type );
- ObjectTypeDB::bind_method(_MD("voice_get_reverb","voice"), &AudioServer::voice_get_reverb );
- ObjectTypeDB::bind_method(_MD("voice_get_mix_rate","voice"), &AudioServer::voice_get_mix_rate );
- ObjectTypeDB::bind_method(_MD("voice_is_positional","voice"), &AudioServer::voice_is_positional );
- ObjectTypeDB::bind_method(_MD("voice_stop","voice"), &AudioServer::voice_stop );
+AudioServer::SpeakerMode AudioServer::get_speaker_mode() const {
- ObjectTypeDB::bind_method(_MD("free_rid","rid"), &AudioServer::free );
+ return (AudioServer::SpeakerMode)AudioDriver::get_singleton()->get_speaker_mode();
+}
+float AudioServer::get_mix_rate() const {
+
+ return AudioDriver::get_singleton()->get_mix_rate();
+}
- ObjectTypeDB::bind_method(_MD("set_stream_global_volume_scale","scale"), &AudioServer::set_stream_global_volume_scale );
- ObjectTypeDB::bind_method(_MD("get_stream_global_volume_scale"), &AudioServer::get_stream_global_volume_scale );
+float AudioServer::read_output_peak_db() const {
- ObjectTypeDB::bind_method(_MD("set_fx_global_volume_scale","scale"), &AudioServer::set_fx_global_volume_scale );
- ObjectTypeDB::bind_method(_MD("get_fx_global_volume_scale"), &AudioServer::get_fx_global_volume_scale );
+ return 0;
+}
- ObjectTypeDB::bind_method(_MD("set_event_voice_global_volume_scale","scale"), &AudioServer::set_event_voice_global_volume_scale );
- ObjectTypeDB::bind_method(_MD("get_event_voice_global_volume_scale"), &AudioServer::get_event_voice_global_volume_scale );
+AudioServer *AudioServer::get_singleton() {
+
+ return singleton;
+}
+
+double AudioServer::get_mix_time() const {
+
+ return 0;
+}
+double AudioServer::get_output_delay() const {
+
+ return 0;
+}
- BIND_CONSTANT( SAMPLE_FORMAT_PCM8 );
- BIND_CONSTANT( SAMPLE_FORMAT_PCM16 );
- BIND_CONSTANT( SAMPLE_FORMAT_IMA_ADPCM );
+AudioServer* AudioServer::singleton=NULL;
- BIND_CONSTANT( SAMPLE_LOOP_NONE );
- BIND_CONSTANT( SAMPLE_LOOP_FORWARD );
- BIND_CONSTANT( SAMPLE_LOOP_PING_PONG );
- BIND_CONSTANT( FILTER_NONE );
- BIND_CONSTANT( FILTER_LOWPASS );
- BIND_CONSTANT( FILTER_BANDPASS );
- BIND_CONSTANT( FILTER_HIPASS );
- BIND_CONSTANT( FILTER_NOTCH );
- BIND_CONSTANT( FILTER_BANDLIMIT ); ///< cutoff is LP resonace is HP
- BIND_CONSTANT( REVERB_SMALL );
- BIND_CONSTANT( REVERB_MEDIUM );
- BIND_CONSTANT( REVERB_LARGE );
- BIND_CONSTANT( REVERB_HALL );
- GLOBAL_DEF("audio/stream_buffering_ms",500);
- GLOBAL_DEF("audio/video_delay_compensation_ms",300);
+void* AudioServer::audio_data_alloc(uint32_t p_data_len,const uint8_t *p_from_data) {
+ void * ad = memalloc( p_data_len );
+ ERR_FAIL_COND_V(!ad,NULL);
+ if (p_from_data) {
+ copymem(ad,p_from_data,p_data_len);
+ }
+
+ audio_data_lock->lock();
+ audio_data[ad]=p_data_len;
+ audio_data_total_mem+=p_data_len;
+ audio_data_max_mem=MAX(audio_data_total_mem,audio_data_max_mem);
+ audio_data_lock->unlock();
+
+ return ad;
+}
+
+void AudioServer::audio_data_free(void* p_data) {
+
+ audio_data_lock->lock();
+ if (!audio_data.has(p_data)) {
+ audio_data_lock->unlock();
+ ERR_FAIL();
+ }
+
+ audio_data_total_mem-=audio_data[p_data];
+ audio_data.erase(p_data);
+ memfree(p_data);
+ audio_data_lock->unlock();
+
+
+}
+
+size_t AudioServer::audio_data_get_total_memory_usage() const{
+
+ return audio_data_total_mem;
+}
+size_t AudioServer::audio_data_get_max_memory_usage() const{
+
+ return audio_data_max_mem;
+
+}
+
+void AudioServer::add_callback(AudioCallback p_callback,void *p_userdata) {
+ lock();
+ CallbackItem ci;
+ ci.callback=p_callback;
+ ci.userdata=p_userdata;
+ callbacks.insert(ci);
+ unlock();
+}
+
+void AudioServer::remove_callback(AudioCallback p_callback,void *p_userdata) {
+
+ lock();
+ CallbackItem ci;
+ ci.callback=p_callback;
+ ci.userdata=p_userdata;
+ callbacks.erase(ci);
+ unlock();
+
+}
+
+void AudioServer::set_bus_layout(const Ref<AudioBusLayout> &p_state) {
+
+ ERR_FAIL_COND(p_state.is_null() || p_state->buses.size()==0);
+
+ lock();
+ for(int i=0;i<buses.size();i++) {
+ memdelete(buses[i]);
+ }
+ buses.resize(p_state->buses.size());
+ bus_map.clear();
+ for(int i=0;i<p_state->buses.size();i++) {
+ Bus * bus = memnew(Bus);
+ if (i==0) {
+ bus->name="Master";
+ } else {
+ bus->name=p_state->buses[i].name;
+ bus->send=p_state->buses[i].send;
+ }
+
+ bus->solo=p_state->buses[i].solo;
+ bus->mute=p_state->buses[i].mute;
+ bus->bypass=p_state->buses[i].bypass;
+ bus->volume_db=p_state->buses[i].volume_db;
+
+ for(int j=0;j<p_state->buses[i].effects.size();j++) {
+
+ Ref<AudioEffect> fx = p_state->buses[i].effects[j].effect;
+
+ if (fx.is_valid()) {
+
+ Bus::Effect bfx;
+ bfx.effect=fx;
+ bfx.enabled=p_state->buses[i].effects[j].enabled;
+ bus->effects.push_back(bfx);
+ }
+ }
+
+ bus_map[bus->name]=bus;
+ buses[i]=bus;
+
+ buses[i]->channels.resize(_get_channel_count());
+ for(int j=0;j<_get_channel_count();j++) {
+ buses[i]->channels[j].buffer.resize(buffer_size);
+ }
+ _update_bus_effects(i);
+ }
+#ifdef TOOLS_ENABLED
+ set_edited(false);
+#endif
+ unlock();
+
+}
+
+
+Ref<AudioBusLayout> AudioServer::generate_bus_layout() const {
+
+ Ref<AudioBusLayout> state;
+ state.instance();
+
+ state->buses.resize( buses.size() );
+
+ for(int i=0;i<buses.size();i++) {
+
+ state->buses[i].name=buses[i]->name;
+ state->buses[i].send=buses[i]->send;
+ state->buses[i].mute=buses[i]->mute;
+ state->buses[i].solo=buses[i]->solo;
+ state->buses[i].bypass=buses[i]->bypass;
+ state->buses[i].volume_db=buses[i]->volume_db;
+ for(int j=0;j<buses[i]->effects.size();j++) {
+ AudioBusLayout::Bus::Effect fx;
+ fx.effect=buses[i]->effects[j].effect;
+ fx.enabled=buses[i]->effects[j].enabled;
+ state->buses[i].effects.push_back(fx);
+
+ }
+ }
+
+ return state;
+}
+
+
+void AudioServer::_bind_methods() {
+
+
+ ClassDB::bind_method(D_METHOD("set_bus_count","amount"),&AudioServer::set_bus_count);
+ ClassDB::bind_method(D_METHOD("get_bus_count"),&AudioServer::get_bus_count);
+
+ ClassDB::bind_method(D_METHOD("remove_bus","index"),&AudioServer::remove_bus);
+ ClassDB::bind_method(D_METHOD("add_bus","at_pos"),&AudioServer::add_bus,DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("move_bus","index","to_index"),&AudioServer::move_bus);
+
+ ClassDB::bind_method(D_METHOD("set_bus_name","bus_idx","name"),&AudioServer::set_bus_name);
+ ClassDB::bind_method(D_METHOD("get_bus_name","bus_idx"),&AudioServer::get_bus_name);
+
+ ClassDB::bind_method(D_METHOD("set_bus_volume_db","bus_idx","volume_db"),&AudioServer::set_bus_volume_db);
+ ClassDB::bind_method(D_METHOD("get_bus_volume_db","bus_idx"),&AudioServer::get_bus_volume_db);
+
+ ClassDB::bind_method(D_METHOD("set_bus_send","bus_idx","send"),&AudioServer::set_bus_send);
+ ClassDB::bind_method(D_METHOD("get_bus_send","bus_idx"),&AudioServer::get_bus_send);
+
+ ClassDB::bind_method(D_METHOD("set_bus_solo","bus_idx","enable"),&AudioServer::set_bus_solo);
+ ClassDB::bind_method(D_METHOD("is_bus_solo","bus_idx"),&AudioServer::is_bus_solo);
+
+ ClassDB::bind_method(D_METHOD("set_bus_mute","bus_idx","enable"),&AudioServer::set_bus_mute);
+ ClassDB::bind_method(D_METHOD("is_bus_mute","bus_idx"),&AudioServer::is_bus_mute);
+
+ ClassDB::bind_method(D_METHOD("set_bus_bypass_effects","bus_idx","enable"),&AudioServer::set_bus_bypass_effects);
+ ClassDB::bind_method(D_METHOD("is_bus_bypassing_effects","bus_idx"),&AudioServer::is_bus_bypassing_effects);
+
+ ClassDB::bind_method(D_METHOD("add_bus_effect","bus_idx","effect:AudioEffect"),&AudioServer::add_bus_effect,DEFVAL(-1));
+ ClassDB::bind_method(D_METHOD("remove_bus_effect","bus_idx","effect_idx"),&AudioServer::remove_bus_effect);
+
+ ClassDB::bind_method(D_METHOD("get_bus_effect_count","bus_idx"),&AudioServer::add_bus_effect);
+ ClassDB::bind_method(D_METHOD("get_bus_effect:AudioEffect","bus_idx","effect_idx"),&AudioServer::get_bus_effect);
+ ClassDB::bind_method(D_METHOD("swap_bus_effects","bus_idx","effect_idx","by_effect_idx"),&AudioServer::swap_bus_effects);
+
+ ClassDB::bind_method(D_METHOD("set_bus_effect_enabled","bus_idx","effect_idx","enabled"),&AudioServer::set_bus_effect_enabled);
+ ClassDB::bind_method(D_METHOD("is_bus_effect_enabled","bus_idx","effect_idx"),&AudioServer::is_bus_effect_enabled);
+
+ ClassDB::bind_method(D_METHOD("get_bus_peak_volume_left_db","bus_idx","channel"),&AudioServer::get_bus_peak_volume_left_db);
+ ClassDB::bind_method(D_METHOD("get_bus_peak_volume_right_db","bus_idx","channel"),&AudioServer::get_bus_peak_volume_right_db);
+
+ ClassDB::bind_method(D_METHOD("lock"),&AudioServer::lock);
+ ClassDB::bind_method(D_METHOD("unlock"),&AudioServer::unlock);
+
+ ClassDB::bind_method(D_METHOD("get_speaker_mode"),&AudioServer::get_speaker_mode);
+ ClassDB::bind_method(D_METHOD("get_mix_rate"),&AudioServer::get_mix_rate);
+
+ ClassDB::bind_method(D_METHOD("set_state","state:AudioServerState"),&AudioServer::set_bus_layout);
+ ClassDB::bind_method(D_METHOD("generate_state:AudioServerState"),&AudioServer::generate_bus_layout);
+
+ ADD_SIGNAL(MethodInfo("bus_layout_changed") );
}
AudioServer::AudioServer() {
singleton=this;
+ audio_data_total_mem=0;
+ audio_data_max_mem=0;
+ audio_data_lock=Mutex::create();
+ mix_frames=0;
+ to_mix=0;
+
}
AudioServer::~AudioServer() {
+ memdelete(audio_data_lock);
+}
+
+/////////////////////////////////
+
+
+
+bool AudioBusLayout::_set(const StringName& p_name, const Variant& p_value) {
+
+ String s = p_name;
+ if (s.begins_with("bus/")) {
+ int index = s.get_slice("/",1).to_int();
+ if (buses.size()<=index) {
+ buses.resize(index+1);
+ }
+
+ Bus &bus = buses[index];
+
+ String what = s.get_slice("/",2);
+
+ if (what=="name") {
+ bus.name=p_value;
+ } else if (what=="solo") {
+ bus.solo=p_value;
+ } else if (what=="mute") {
+ bus.mute=p_value;
+ } else if (what=="bypass_fx") {
+ bus.bypass=p_value;
+ } else if (what=="volume_db") {
+ bus.volume_db=p_value;
+ } else if (what=="send") {
+ bus.send=p_value;
+ } else if (what=="effect") {
+ int which = s.get_slice("/",3).to_int();
+ if (bus.effects.size()<=which) {
+ bus.effects.resize(which+1);
+ }
+
+ Bus::Effect &fx = bus.effects[which];
+
+ String fxwhat = s.get_slice("/",4);
+ if (fxwhat=="effect") {
+ fx.effect=p_value;
+ } else if (fxwhat=="enabled") {
+ fx.enabled=p_value;
+ } else {
+ return false;
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+
+}
+
+bool AudioBusLayout::_get(const StringName& p_name,Variant &r_ret) const{
+
+ String s = p_name;
+ if (s.begins_with("bus/")) {
+
+ int index = s.get_slice("/",1).to_int();
+ if (index<0 || index>=buses.size())
+ return false;
+
+ const Bus &bus = buses[index];
+
+ String what = s.get_slice("/",2);
+
+ if (what=="name") {
+ r_ret=bus.name;
+ } else if (what=="solo") {
+ r_ret=bus.solo;
+ } else if (what=="mute") {
+ r_ret=bus.mute;
+ } else if (what=="bypass_fx") {
+ r_ret=bus.bypass;
+ } else if (what=="volume_db") {
+ r_ret=bus.volume_db;
+ } else if (what=="send") {
+ r_ret=bus.send;
+ } else if (what=="effect") {
+ int which = s.get_slice("/",3).to_int();
+ if (which<0 || which>=bus.effects.size()) {
+ return false;
+ }
+
+ const Bus::Effect &fx = bus.effects[which];
+
+ String fxwhat = s.get_slice("/",4);
+ if (fxwhat=="effect") {
+ r_ret=fx.effect;
+ } else if (fxwhat=="enabled") {
+ r_ret=fx.enabled;
+ } else {
+ return false;
+ }
+
+ return true;
+ } else {
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
+
+}
+void AudioBusLayout::_get_property_list( List<PropertyInfo> *p_list) const{
+
+ for(int i=0;i<buses.size();i++) {
+ p_list->push_back(PropertyInfo(Variant::STRING,"bus/"+itos(i)+"/name",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"bus/"+itos(i)+"/solo",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"bus/"+itos(i)+"/mute",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"bus/"+itos(i)+"/bypass_fx",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::REAL,"bus/"+itos(i)+"/volume_db",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::REAL,"bus/"+itos(i)+"/send",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR));
+
+ for(int j=0;j<buses[i].effects.size();j++) {
+ p_list->push_back(PropertyInfo(Variant::OBJECT,"bus/"+itos(i)+"/effect/"+itos(j)+"/effect",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR));
+ p_list->push_back(PropertyInfo(Variant::BOOL,"bus/"+itos(i)+"/effect/"+itos(j)+"/enabled",PROPERTY_HINT_NONE,"",PROPERTY_USAGE_NOEDITOR));
+ }
+ }
+}
+
+
+AudioBusLayout::AudioBusLayout() {
+ buses.resize(1);
+ buses[0].name="Master";
}
diff --git a/servers/audio_server.h b/servers/audio_server.h
index 9e21e6b183..88849bb591 100644
--- a/servers/audio_server.h
+++ b/servers/audio_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,261 +31,326 @@
#include "variant.h"
#include "object.h"
+#include "audio_frame.h"
+#include "servers/audio/audio_effect.h"
+
+
+class AudioDriver {
+
+
+ static AudioDriver *singleton;
+ uint64_t _last_mix_time;
+ uint64_t _mix_amount;
+
-class AudioMixer {
protected:
- void audio_mixer_chunk_call(int p_frames);
+ void audio_server_process(int p_frames,int32_t *p_buffer,bool p_update_mix_time=true);
+ void update_mix_time(int p_frames);
+
public:
- enum {
- INVALID_CHANNEL=0xFFFFFFFF
+ double get_mix_time() const; //useful for video -> audio sync
+
+ enum SpeakerMode {
+ SPEAKER_MODE_STEREO,
+ SPEAKER_SURROUND_51,
+ SPEAKER_SURROUND_71,
};
- typedef uint32_t ChannelID;
+ static AudioDriver *get_singleton();
+ void set_singleton();
- /* CHANNEL API */
+ virtual const char* get_name() const=0;
- enum FilterType {
- FILTER_NONE,
- FILTER_LOWPASS,
- FILTER_BANDPASS,
- FILTER_HIPASS,
- FILTER_NOTCH,
- FILTER_PEAK,
- FILTER_BANDLIMIT, ///< cutoff is LP resonace is HP
- FILTER_LOW_SHELF,
- FILTER_HIGH_SHELF
+ virtual Error init()=0;
+ virtual void start()=0;
+ virtual int get_mix_rate() const =0;
+ virtual SpeakerMode get_speaker_mode() const=0;
+ virtual void lock()=0;
+ virtual void unlock()=0;
+ virtual void finish()=0;
- };
+ virtual float get_latency() { return 0; }
- enum ReverbRoomType {
- REVERB_SMALL,
- REVERB_MEDIUM,
- REVERB_LARGE,
- REVERB_HALL,
- MAX_REVERBS
- };
- virtual ChannelID channel_alloc(RID p_sample)=0;
- virtual void channel_set_volume(ChannelID p_channel, float p_gain)=0;
- virtual void channel_set_pan(ChannelID p_channel, float p_pan, float p_depth=0,float height=0)=0; //pan and depth go from -1 to 1
- virtual void channel_set_filter(ChannelID p_channel, FilterType p_type, float p_cutoff, float p_resonance, float p_gain=1.0)=0;
- virtual void channel_set_chorus(ChannelID p_channel, float p_chorus )=0;
- virtual void channel_set_reverb(ChannelID p_channel, ReverbRoomType p_room_type, float p_reverb)=0;
- virtual void channel_set_mix_rate(ChannelID p_channel, int p_mix_rate)=0;
- virtual void channel_set_positional(ChannelID p_channel, bool p_positional)=0;
+ AudioDriver();
+ virtual ~AudioDriver() {}
+};
- virtual float channel_get_volume(ChannelID p_channel) const=0;
- virtual float channel_get_pan(ChannelID p_channel) const=0; //pan and depth go from -1 to 1
- virtual float channel_get_pan_depth(ChannelID p_channel) const=0; //pan and depth go from -1 to 1
- virtual float channel_get_pan_height(ChannelID p_channel) const=0; //pan and depth go from -1 to 1
- virtual FilterType channel_get_filter_type(ChannelID p_channel) const=0;
- virtual float channel_get_filter_cutoff(ChannelID p_channel) const=0;
- virtual float channel_get_filter_resonance(ChannelID p_channel) const=0;
- virtual float channel_get_filter_gain(ChannelID p_channel) const=0;
- virtual float channel_get_chorus(ChannelID p_channel) const=0;
- virtual ReverbRoomType channel_get_reverb_type(ChannelID p_channel) const=0;
- virtual float channel_get_reverb(ChannelID p_channel) const=0;
- virtual int channel_get_mix_rate(ChannelID p_channel) const=0;
- virtual bool channel_is_positional(ChannelID p_channel) const=0;
- virtual bool channel_is_valid(ChannelID p_channel) const=0;
+class AudioDriverManager {
- virtual void channel_free(ChannelID p_channel)=0;
+ enum {
- virtual void set_mixer_volume(float p_volume)=0;
+ MAX_DRIVERS=10
+ };
+ static AudioDriver *drivers[MAX_DRIVERS];
+ static int driver_count;
+public:
- virtual ~AudioMixer() {}
+ static void add_driver(AudioDriver *p_driver);
+ static int get_driver_count();
+ static AudioDriver *get_driver(int p_driver);
};
+class AudioBusLayout;
+
class AudioServer : public Object {
- OBJ_TYPE( AudioServer, Object );
+ GDCLASS( AudioServer, Object )
+public:
+ //re-expose this her, as AudioDriver is not exposed to script
+ enum SpeakerMode {
+ SPEAKER_MODE_STEREO,
+ SPEAKER_SURROUND_51,
+ SPEAKER_SURROUND_71,
+ };
+
+ enum {
+ AUDIO_DATA_INVALID_ID=-1
+ };
- static AudioServer *singleton;
-protected:
-friend class AudioStream;
-friend class EventStream;
-friend class AudioMixer;
+ typedef void (*AudioCallback)(void* p_userdata);
- virtual AudioMixer *get_mixer()=0;
- virtual void audio_mixer_chunk_callback(int p_frames)=0;
+private:
+ uint32_t buffer_size;
+ uint64_t mix_count;
+ uint64_t mix_frames;
- static void _bind_methods();
-public:
+ float channel_disable_treshold_db;
+ uint32_t channel_disable_frames;
+ int to_mix;
- class EventStream {
- protected:
- AudioMixer *get_mixer() const;
- public:
- virtual void update(uint64_t p_usec)=0;
+ struct Bus {
- virtual ~EventStream() {}
- };
+ StringName name;
+ bool solo;
+ bool mute;
+ bool bypass;
- class AudioStream {
- public:
- virtual int get_channel_count() const=0;
- virtual void set_mix_rate(int p_rate)=0; //notify the stream of the mix rate
- virtual bool mix(int32_t *p_buffer,int p_frames)=0;
- virtual void update()=0;
- virtual bool can_update_mt() const { return true; }
- virtual ~AudioStream() {}
- };
+ //Each channel is a stereo pair.
+ struct Channel {
+ bool used;
+ bool active;
+ AudioFrame peak_volume;
+ Vector<AudioFrame> buffer;
+ Vector<Ref<AudioEffectInstance> > effect_instances;
+ uint64_t last_mix_with_audio;
+ Channel() { last_mix_with_audio=0; used=false; active=false; peak_volume=AudioFrame(0,0); }
+ };
+
+ Vector<Channel> channels;
- enum SampleFormat {
+ struct Effect {
+ Ref<AudioEffect> effect;
+ bool enabled;
+ };
- SAMPLE_FORMAT_PCM8,
- SAMPLE_FORMAT_PCM16,
- SAMPLE_FORMAT_IMA_ADPCM
+ Vector<Effect> effects;
+ float volume_db;
+ StringName send;
+ int index_cache;
};
- enum SampleLoopFormat {
- SAMPLE_LOOP_NONE,
- SAMPLE_LOOP_FORWARD,
- SAMPLE_LOOP_PING_PONG // not supported in every platform
- };
+ Vector< Vector<AudioFrame> >temp_buffer; //temp_buffer for each level
+ Vector<Bus*> buses;
+ Map<StringName,Bus*> bus_map;
- /* SAMPLE API */
+ _FORCE_INLINE_ int _get_channel_count() const {
+ switch (AudioDriver::get_singleton()->get_speaker_mode()) {
+ case AudioDriver::SPEAKER_MODE_STEREO: return 1;
+ case AudioDriver::SPEAKER_SURROUND_51: return 3;
+ case AudioDriver::SPEAKER_SURROUND_71: return 4;
- virtual RID sample_create(SampleFormat p_format, bool p_stereo, int p_length)=0;
+ }
+ ERR_FAIL_V(1);
+ }
- virtual void sample_set_description(RID p_sample, const String& p_description)=0;
- virtual String sample_get_description(RID p_sample) const=0;
- virtual SampleFormat sample_get_format(RID p_sample) const=0;
- virtual bool sample_is_stereo(RID p_sample) const=0;
- virtual int sample_get_length(RID p_sample) const=0;
- virtual const void* sample_get_data_ptr(RID p_sample) const=0;
+ void _update_bus_effects(int p_bus);
- virtual void sample_set_signed_data(RID p_sample, const DVector<float>& p_buffer);
- virtual void sample_set_data(RID p_sample, const DVector<uint8_t>& p_buffer)=0;
- virtual DVector<uint8_t> sample_get_data(RID p_sample) const=0;
- virtual void sample_set_mix_rate(RID p_sample,int p_rate)=0;
- virtual int sample_get_mix_rate(RID p_sample) const=0;
+ static AudioServer* singleton;
- virtual void sample_set_loop_format(RID p_sample,SampleLoopFormat p_format)=0;
- virtual SampleLoopFormat sample_get_loop_format(RID p_sample) const=0;
+ // TODO create an audiodata pool to optimize memory
- virtual void sample_set_loop_begin(RID p_sample,int p_pos)=0;
- virtual int sample_get_loop_begin(RID p_sample) const=0;
- virtual void sample_set_loop_end(RID p_sample,int p_pos)=0;
- virtual int sample_get_loop_end(RID p_sample) const=0;
+ Map<void*,uint32_t> audio_data;
+ size_t audio_data_total_mem;
+ size_t audio_data_max_mem;
+ Mutex *audio_data_lock;
- /* VOICE API */
+ void _mix_step();
- enum FilterType {
- FILTER_NONE,
- FILTER_LOWPASS,
- FILTER_BANDPASS,
- FILTER_HIPASS,
- FILTER_NOTCH,
- FILTER_PEAK,
- FILTER_BANDLIMIT, ///< cutoff is LP resonace is HP
- FILTER_LOW_SHELF,
- FILTER_HIGH_SHELF
- };
+ struct CallbackItem {
- enum ReverbRoomType {
+ AudioCallback callback;
+ void *userdata;
- REVERB_SMALL,
- REVERB_MEDIUM,
- REVERB_LARGE,
- REVERB_HALL
+ bool operator<(const CallbackItem& p_item) const {
+ return (callback==p_item.callback ? userdata < p_item.userdata : callback < p_item.callback);
+ }
};
- virtual RID voice_create()=0;
+ Set<CallbackItem> callbacks;
- virtual void voice_play(RID p_voice, RID p_sample)=0;
+friend class AudioDriver;
+ void _driver_process(int p_frames, int32_t *p_buffer);
+protected:
- virtual void voice_set_volume(RID p_voice, float p_volume)=0;
- virtual void voice_set_pan(RID p_voice, float p_pan, float p_depth=0,float height=0)=0; //pan and depth go from -1 to 1
- virtual void voice_set_filter(RID p_voice, FilterType p_type, float p_cutoff, float p_resonance, float p_gain=0)=0;
- virtual void voice_set_chorus(RID p_voice, float p_chorus )=0;
- virtual void voice_set_reverb(RID p_voice, ReverbRoomType p_room_type, float p_reverb)=0;
- virtual void voice_set_mix_rate(RID p_voice, int p_mix_rate)=0;
- virtual void voice_set_positional(RID p_voice, bool p_positional)=0;
+ static void _bind_methods();
+public:
- virtual float voice_get_volume(RID p_voice) const=0;
- virtual float voice_get_pan(RID p_voice) const=0; //pan and depth go from -1 to 1
- virtual float voice_get_pan_depth(RID p_voice) const=0; //pan and depth go from -1 to 1
- virtual float voice_get_pan_height(RID p_voice) const=0; //pan and depth go from -1 to 1
- virtual FilterType voice_get_filter_type(RID p_voice) const=0;
- virtual float voice_get_filter_cutoff(RID p_voice) const=0;
- virtual float voice_get_filter_resonance(RID p_voice) const=0;
- virtual float voice_get_chorus(RID p_voice) const=0;
- virtual ReverbRoomType voice_get_reverb_type(RID p_voice) const=0;
- virtual float voice_get_reverb(RID p_voice) const=0;
+ //do not use from outside audio thread
+ AudioFrame *thread_get_channel_mix_buffer(int p_bus,int p_buffer);
+ int thread_get_mix_buffer_size() const;
+ int thread_find_bus_index(const StringName& p_name);
- virtual int voice_get_mix_rate(RID p_voice) const=0;
- virtual bool voice_is_positional(RID p_voice) const=0;
- virtual void voice_stop(RID p_voice)=0;
- virtual bool voice_is_active(RID p_voice) const=0;
+ void set_bus_count(int p_count);
+ int get_bus_count() const;
- /* STREAM API */
+ void remove_bus(int p_index);
+ void add_bus(int p_at_pos=-1);
- virtual RID audio_stream_create(AudioStream *p_stream)=0;
- virtual RID event_stream_create(EventStream *p_stream)=0;
+ void move_bus(int p_bus,int p_to_pos);
- virtual void stream_set_active(RID p_stream, bool p_active)=0;
- virtual bool stream_is_active(RID p_stream) const=0;
+ void set_bus_name(int p_bus,const String& p_name);
+ String get_bus_name(int p_bus) const;
- virtual void stream_set_volume_scale(RID p_stream, float p_scale)=0;
- virtual float stream_set_volume_scale(RID p_stream) const=0;
+ void set_bus_volume_db(int p_bus,float p_volume_db);
+ float get_bus_volume_db(int p_bus) const;
- /* Audio Physics API */
- virtual void free(RID p_id)=0;
+ void set_bus_send(int p_bus,const StringName& p_send);
+ StringName get_bus_send(int p_bus) const;
- virtual void init()=0;
- virtual void finish()=0;
- virtual void update()=0;
+ void set_bus_solo(int p_bus,bool p_enable);
+ bool is_bus_solo(int p_bus) const;
+
+ void set_bus_mute(int p_bus,bool p_enable);
+ bool is_bus_mute(int p_bus) const;
+
+ void set_bus_bypass_effects(int p_bus,bool p_enable);
+ bool is_bus_bypassing_effects(int p_bus) const;
+
+ void add_bus_effect(int p_bus,const Ref<AudioEffect>& p_effect,int p_at_pos=-1);
+ void remove_bus_effect(int p_bus,int p_effect);
+
+ int get_bus_effect_count(int p_bus);
+ Ref<AudioEffect> get_bus_effect(int p_bus,int p_effect);
+
+ void swap_bus_effects(int p_bus,int p_effect,int p_by_effect);
+
+ void set_bus_effect_enabled(int p_bus,int p_effect,bool p_enabled);
+ bool is_bus_effect_enabled(int p_bus,int p_effect) const;
+
+ float get_bus_peak_volume_left_db(int p_bus,int p_channel) const;
+ float get_bus_peak_volume_right_db(int p_bus,int p_channel) const;
+
+ bool is_bus_channel_active(int p_bus,int p_channel) const;
+
+ virtual void init();
+ virtual void finish();
+ virtual void update();
+ virtual void load_default_bus_layout();
/* MISC config */
- virtual void lock()=0;
- virtual void unlock()=0;
- virtual int get_default_channel_count() const=0;
- virtual int get_default_mix_rate() const=0;
+ virtual void lock();
+ virtual void unlock();
- virtual void set_stream_global_volume_scale(float p_volume)=0;
- virtual void set_fx_global_volume_scale(float p_volume)=0;
- virtual void set_event_voice_global_volume_scale(float p_volume)=0;
- virtual float get_stream_global_volume_scale() const=0;
- virtual float get_fx_global_volume_scale() const=0;
- virtual float get_event_voice_global_volume_scale() const=0;
+ virtual SpeakerMode get_speaker_mode() const;
+ virtual float get_mix_rate() const;
- virtual uint32_t read_output_peak() const=0;
+ virtual float read_output_peak_db() const;
static AudioServer *get_singleton();
- virtual double get_mix_time() const=0; //useful for video -> audio sync
- virtual double get_output_delay() const=0;
+ virtual double get_mix_time() const; //useful for video -> audio sync
+ virtual double get_output_delay() const;
+
+ void* audio_data_alloc(uint32_t p_data_len, const uint8_t *p_from_data=NULL);
+ void audio_data_free(void* p_data);
+
+ size_t audio_data_get_total_memory_usage() const;
+ size_t audio_data_get_max_memory_usage() const;
+
+
+ void add_callback(AudioCallback p_callback,void *p_userdata);
+ void remove_callback(AudioCallback p_callback,void *p_userdata);
+
+ void set_bus_layout(const Ref<AudioBusLayout>& p_state);
+ Ref<AudioBusLayout> generate_bus_layout() const;
AudioServer();
virtual ~AudioServer();
};
-VARIANT_ENUM_CAST( AudioServer::SampleFormat );
-VARIANT_ENUM_CAST( AudioServer::SampleLoopFormat );
-VARIANT_ENUM_CAST( AudioServer::FilterType );
-VARIANT_ENUM_CAST( AudioServer::ReverbRoomType );
+VARIANT_ENUM_CAST( AudioServer::SpeakerMode )
+
+class AudioBusLayout : public Resource {
+
+ GDCLASS(AudioBusLayout,Resource)
+
+friend class AudioServer;
+
+ struct Bus {
+
+ StringName name;
+ bool solo;
+ bool mute;
+ bool bypass;
+
+ struct Effect {
+ Ref<AudioEffect> effect;
+ bool enabled;
+ };
+
+ Vector<Effect> effects;
+
+ float volume_db;
+ StringName send;
+
+ Bus() {
+ solo=false;
+ mute=false;
+ bypass=false;
+ volume_db=0;
+ }
+ };
+
+ Vector<Bus> buses;
+
+protected:
+
+ bool _set(const StringName& p_name, const Variant& p_value);
+ bool _get(const StringName& p_name,Variant &r_ret) const;
+ void _get_property_list( List<PropertyInfo> *p_list) const;
+
+public:
+
+ AudioBusLayout();
+};
+
+
+
+
+
typedef AudioServer AS;
+
#endif // AUDIO_SERVER_H
diff --git a/servers/physics/SCsub b/servers/physics/SCsub
index 95296eadbe..c0ee2cc739 100644
--- a/servers/physics/SCsub
+++ b/servers/physics/SCsub
@@ -1,6 +1,8 @@
+#!/usr/bin/env python
+
Import('env')
-env.add_source_files(env.servers_sources,"*.cpp")
+env.add_source_files(env.servers_sources, "*.cpp")
Export('env')
diff --git a/servers/physics/area_pair_sw.cpp b/servers/physics/area_pair_sw.cpp
index 24f3b75ca5..3aa0816b06 100644
--- a/servers/physics/area_pair_sw.cpp
+++ b/servers/physics/area_pair_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,7 +30,7 @@
#include "collision_solver_sw.h"
-bool AreaPairSW::setup(float p_step) {
+bool AreaPairSW::setup(real_t p_step) {
if (!area->test_collision_mask(body)) {
colliding = false;
@@ -64,7 +64,7 @@ bool AreaPairSW::setup(float p_step) {
return false; //never do any post solving
}
-void AreaPairSW::solve(float p_step) {
+void AreaPairSW::solve(real_t p_step) {
}
@@ -103,14 +103,14 @@ AreaPairSW::~AreaPairSW() {
-bool Area2PairSW::setup(float p_step) {
+bool Area2PairSW::setup(real_t p_step) {
if (!area_a->test_collision_mask(area_b)) {
colliding = false;
return false;
}
-// bool result = area_a->test_collision_mask(area_b) && CollisionSolverSW::solve(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),Vector2(),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),Vector2(),NULL,this);
+ //bool result = area_a->test_collision_mask(area_b) && CollisionSolverSW::solve(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),Vector2(),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),Vector2(),NULL,this);
bool result = CollisionSolverSW::solve_static(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),NULL,this);
if (result!=colliding) {
@@ -139,7 +139,7 @@ bool Area2PairSW::setup(float p_step) {
return false; //never do any post solving
}
-void Area2PairSW::solve(float p_step) {
+void Area2PairSW::solve(real_t p_step) {
}
diff --git a/servers/physics/area_pair_sw.h b/servers/physics/area_pair_sw.h
index 09a2934467..637976a095 100644
--- a/servers/physics/area_pair_sw.h
+++ b/servers/physics/area_pair_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,8 +42,8 @@ class AreaPairSW : public ConstraintSW {
bool colliding;
public:
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
AreaPairSW(BodySW *p_body,int p_body_shape, AreaSW *p_area,int p_area_shape);
~AreaPairSW();
@@ -59,8 +59,8 @@ class Area2PairSW : public ConstraintSW {
bool colliding;
public:
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
Area2PairSW(AreaSW *p_area_a,int p_shape_a, AreaSW *p_area_b,int p_shape_b);
~Area2PairSW();
diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp
index dbc82da316..8aed07d5e5 100644
--- a/servers/physics/area_sw.cpp
+++ b/servers/physics/area_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -126,14 +126,14 @@ void AreaSW::set_space_override_mode(PhysicsServer::AreaSpaceOverrideMode p_mode
void AreaSW::set_param(PhysicsServer::AreaParameter p_param, const Variant& p_value) {
switch(p_param) {
- case PhysicsServer::AREA_PARAM_GRAVITY: gravity=p_value; ; break;
- case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; ; break;
- case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; ; break;
- case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; ; break;
- case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; ; break;
- case PhysicsServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; ; break;
- case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; ; break;
- case PhysicsServer::AREA_PARAM_PRIORITY: priority=p_value; ; break;
+ case PhysicsServer::AREA_PARAM_GRAVITY: gravity=p_value; break;
+ case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; break;
+ case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; break;
+ case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; break;
+ case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; break;
+ case PhysicsServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; break;
+ case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; break;
+ case PhysicsServer::AREA_PARAM_PRIORITY: priority=p_value; break;
}
diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h
index 622eeb5e23..4e6f1c5a51 100644
--- a/servers/physics/area_sw.h
+++ b/servers/physics/area_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,13 +42,13 @@ class AreaSW : public CollisionObjectSW{
PhysicsServer::AreaSpaceOverrideMode space_override_mode;
- float gravity;
+ real_t gravity;
Vector3 gravity_vector;
bool gravity_is_point;
- float gravity_distance_scale;
- float point_attenuation;
- float linear_damp;
- float angular_damp;
+ real_t gravity_distance_scale;
+ real_t point_attenuation;
+ real_t linear_damp;
+ real_t angular_damp;
int priority;
bool monitorable;
@@ -131,8 +131,8 @@ public:
void set_space_override_mode(PhysicsServer::AreaSpaceOverrideMode p_mode);
PhysicsServer::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; }
- _FORCE_INLINE_ void set_gravity(float p_gravity) { gravity=p_gravity; }
- _FORCE_INLINE_ float get_gravity() const { return gravity; }
+ _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity=p_gravity; }
+ _FORCE_INLINE_ real_t get_gravity() const { return gravity; }
_FORCE_INLINE_ void set_gravity_vector(const Vector3& p_gravity) { gravity_vector=p_gravity; }
_FORCE_INLINE_ Vector3 get_gravity_vector() const { return gravity_vector; }
@@ -140,17 +140,17 @@ public:
_FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point=p_enable; }
_FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; }
- _FORCE_INLINE_ void set_gravity_distance_scale(float scale) { gravity_distance_scale=scale; }
- _FORCE_INLINE_ float get_gravity_distance_scale() const { return gravity_distance_scale; }
+ _FORCE_INLINE_ void set_gravity_distance_scale(real_t scale) { gravity_distance_scale=scale; }
+ _FORCE_INLINE_ real_t get_gravity_distance_scale() const { return gravity_distance_scale; }
- _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; }
- _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; }
+ _FORCE_INLINE_ void set_point_attenuation(real_t p_point_attenuation) { point_attenuation=p_point_attenuation; }
+ _FORCE_INLINE_ real_t get_point_attenuation() const { return point_attenuation; }
- _FORCE_INLINE_ void set_linear_damp(float p_linear_damp) { linear_damp=p_linear_damp; }
- _FORCE_INLINE_ float get_linear_damp() const { return linear_damp; }
+ _FORCE_INLINE_ void set_linear_damp(real_t p_linear_damp) { linear_damp=p_linear_damp; }
+ _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; }
- _FORCE_INLINE_ void set_angular_damp(float p_angular_damp) { angular_damp=p_angular_damp; }
- _FORCE_INLINE_ float get_angular_damp() const { return angular_damp; }
+ _FORCE_INLINE_ void set_angular_damp(real_t p_angular_damp) { angular_damp=p_angular_damp; }
+ _FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; }
_FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; }
_FORCE_INLINE_ int get_priority() const { return priority; }
diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp
index 43e52f26e8..7fb3def387 100644
--- a/servers/physics/body_pair_sw.cpp
+++ b/servers/physics/body_pair_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -105,7 +105,7 @@ void BodyPairSW::contact_added_callback(const Vector3& p_point_A,const Vector3&
// remove the contact with the minimum depth
int least_deep=-1;
- float min_depth=1e10;
+ real_t min_depth=1e10;
for (int i=0;i<=contact_count;i++) {
@@ -114,7 +114,7 @@ void BodyPairSW::contact_added_callback(const Vector3& p_point_A,const Vector3&
Vector3 global_B = B->get_transform().basis.xform(c.local_B)+offset_B;
Vector3 axis = global_A - global_B;
- float depth = axis.dot( c.normal );
+ real_t depth = axis.dot( c.normal );
if (depth<min_depth) {
@@ -154,7 +154,7 @@ void BodyPairSW::validate_contacts() {
Vector3 global_A = A->get_transform().basis.xform(c.local_A);
Vector3 global_B = B->get_transform().basis.xform(c.local_B)+offset_B;
Vector3 axis = global_A - global_B;
- float depth = axis.dot( c.normal );
+ real_t depth = axis.dot( c.normal );
if (depth < -contact_max_separation || (global_B + c.normal * depth - global_A).length() > contact_max_separation) {
// contact no longer needed, remove
@@ -173,7 +173,7 @@ void BodyPairSW::validate_contacts() {
}
-bool BodyPairSW::_test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B) {
+bool BodyPairSW::_test_ccd(real_t p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B) {
@@ -211,14 +211,14 @@ bool BodyPairSW::_test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transfo
//shorten the linear velocity so it does not hit, but gets close enough, next frame will hit softly or soft enough
Vector3 hitpos = p_xform_B.xform(rpos);
- float newlen = hitpos.distance_to(from)-(max-min)*0.01;
+ real_t newlen = hitpos.distance_to(from)-(max-min)*0.01;
p_A->set_linear_velocity((mnormal*newlen)/p_step);
return true;
}
-bool BodyPairSW::setup(float p_step) {
+bool BodyPairSW::setup(real_t p_step) {
//cannot collide
if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode()<=PhysicsServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported()==0 && B->get_max_contacts_reported()==0)) {
@@ -264,7 +264,7 @@ bool BodyPairSW::setup(float p_step) {
real_t max_penetration = space->get_contact_max_allowed_penetration();
- float bias = 0.3f;
+ real_t bias = (real_t)0.3;
if (shape_A_ptr->get_custom_bias() || shape_B_ptr->get_custom_bias()) {
@@ -307,8 +307,8 @@ bool BodyPairSW::setup(float p_step) {
}
#endif
- c.rA = global_A;
- c.rB = global_B-offset_B;
+ c.rA = global_A-A->get_center_of_mass();
+ c.rB = global_B-B->get_center_of_mass()-offset_B;
// contact query reporting...
#if 0
@@ -356,7 +356,7 @@ bool BodyPairSW::setup(float p_step) {
if (depth > max_penetration) {
c.bias = (depth - max_penetration) * (1.0/(p_step*(1.0/RELAXATION_TIMESTEPS)));
} else {
- float approach = -0.1f * (depth - max_penetration) / (CMP_EPSILON + max_penetration);
+ real_t approach = -0.1 * (depth - max_penetration) / (CMP_EPSILON + max_penetration);
approach = CLAMP( approach, CMP_EPSILON, 1.0 );
c.bias = approach * (depth - max_penetration) * (1.0/p_step);
}
@@ -364,12 +364,12 @@ bool BodyPairSW::setup(float p_step) {
c.depth=depth;
Vector3 j_vec = c.normal * c.acc_normal_impulse + c.acc_tangent_impulse;
- A->apply_impulse( c.rA, -j_vec );
- B->apply_impulse( c.rB, j_vec );
+ A->apply_impulse( c.rA+A->get_center_of_mass(), -j_vec );
+ B->apply_impulse( c.rB+B->get_center_of_mass(), j_vec );
c.acc_bias_impulse=0;
Vector3 jb_vec = c.normal * c.acc_bias_impulse;
- A->apply_bias_impulse( c.rA, -jb_vec );
- B->apply_bias_impulse( c.rB, jb_vec );
+ A->apply_bias_impulse( c.rA+A->get_center_of_mass(), -jb_vec );
+ B->apply_bias_impulse( c.rB+B->get_center_of_mass(), jb_vec );
c.bounce = MAX(A->get_bounce(),B->get_bounce());
if (c.bounce) {
@@ -387,7 +387,7 @@ bool BodyPairSW::setup(float p_step) {
return true;
}
-void BodyPairSW::solve(float p_step) {
+void BodyPairSW::solve(real_t p_step) {
if (!collided)
return;
@@ -418,8 +418,8 @@ void BodyPairSW::solve(float p_step) {
Vector3 jb = c.normal * (c.acc_bias_impulse - jbnOld);
- A->apply_bias_impulse(c.rA,-jb);
- B->apply_bias_impulse(c.rB, jb);
+ A->apply_bias_impulse(c.rA+A->get_center_of_mass(),-jb);
+ B->apply_bias_impulse(c.rB+B->get_center_of_mass(), jb);
c.active=true;
}
@@ -442,8 +442,8 @@ void BodyPairSW::solve(float p_step) {
Vector3 j =c.normal * (c.acc_normal_impulse - jnOld);
- A->apply_impulse(c.rA,-j);
- B->apply_impulse(c.rB, j);
+ A->apply_impulse(c.rA+A->get_center_of_mass(),-j);
+ B->apply_impulse(c.rB+B->get_center_of_mass(), j);
c.active=true;
}
@@ -489,8 +489,8 @@ void BodyPairSW::solve(float p_step) {
jt = c.acc_tangent_impulse - jtOld;
- A->apply_impulse( c.rA, -jt );
- B->apply_impulse( c.rB, jt );
+ A->apply_impulse( c.rA+A->get_center_of_mass(), -jt );
+ B->apply_impulse( c.rB+B->get_center_of_mass(), jt );
c.active=true;
diff --git a/servers/physics/body_pair_sw.h b/servers/physics/body_pair_sw.h
index da637ade05..f282a56b9e 100644
--- a/servers/physics/body_pair_sw.h
+++ b/servers/physics/body_pair_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -65,7 +65,7 @@ class BodyPairSW : public ConstraintSW {
real_t depth;
bool active;
- Vector3 rA,rB;
+ Vector3 rA,rB; // Offset in world orientation with respect to center of mass
};
Vector3 offset_B; //use local A coordinates to avoid numerical issues on collision detection
@@ -82,14 +82,14 @@ class BodyPairSW : public ConstraintSW {
void contact_added_callback(const Vector3& p_point_A,const Vector3& p_point_B);
void validate_contacts();
- bool _test_ccd(float p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B);
+ bool _test_ccd(real_t p_step,BodySW *p_A, int p_shape_A,const Transform& p_xform_A,BodySW *p_B, int p_shape_B,const Transform& p_xform_B);
SpaceSW *space;
public:
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
BodyPairSW(BodySW *p_A, int p_shape_A,BodySW *p_B, int p_shape_B);
~BodyPairSW();
diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp
index b0ed99cb48..7fcd767268 100644
--- a/servers/physics/body_sw.cpp
+++ b/servers/physics/body_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,12 +37,16 @@ void BodySW::_update_inertia() {
}
+void BodySW::_update_transform_dependant() {
+
+ center_of_mass = get_transform().basis.xform(center_of_mass_local);
+ principal_inertia_axes = get_transform().basis * principal_inertia_axes_local;
-void BodySW::_update_inertia_tensor() {
-
- Matrix3 tb = get_transform().basis;
+ // update inertia tensor
+ Basis tb = principal_inertia_axes;
+ Basis tbt = tb.transposed();
tb.scale(_inv_inertia);
- _inv_inertia_tensor = tb * get_transform().basis.transposed();
+ _inv_inertia_tensor = tb * tbt;
}
@@ -54,33 +58,56 @@ void BodySW::update_inertias() {
case PhysicsServer::BODY_MODE_RIGID: {
- //update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet)
- float total_area=0;
+ //update tensor for all shapes, not the best way but should be somehow OK. (inspired from bullet)
+ real_t total_area=0;
for (int i=0;i<get_shape_count();i++) {
- total_area+=get_shape_aabb(i).get_area();
+ total_area+=get_shape_area(i);
}
- Vector3 _inertia;
+ // We have to recompute the center of mass
+ center_of_mass_local.zero();
+
+ for (int i=0; i<get_shape_count(); i++) {
+ real_t area=get_shape_area(i);
+
+ real_t mass = area * this->mass / total_area;
+
+ // NOTE: we assume that the shape origin is also its center of mass
+ center_of_mass_local += mass * get_shape_transform(i).origin;
+ }
+ center_of_mass_local /= mass;
+
+ // Recompute the inertia tensor
+ Basis inertia_tensor;
+ inertia_tensor.set_zero();
for (int i=0;i<get_shape_count();i++) {
const ShapeSW* shape=get_shape(i);
- float area=get_shape_aabb(i).get_area();
+ real_t area=get_shape_area(i);
+
+ real_t mass = area * this->mass / total_area;
+
+ Basis shape_inertia_tensor=shape->get_moment_of_inertia(mass).to_diagonal_matrix();
+ Transform shape_transform=get_shape_transform(i);
+ Basis shape_basis = shape_transform.basis.orthonormalized();
+
+ // NOTE: we don't take the scale of collision shapes into account when computing the inertia tensor!
+ shape_inertia_tensor = shape_basis * shape_inertia_tensor * shape_basis.transposed();
- float mass = area * this->mass / total_area;
+ Vector3 shape_origin = shape_transform.origin - center_of_mass_local;
+ inertia_tensor += shape_inertia_tensor + (Basis()*shape_origin.dot(shape_origin)-shape_origin.outer(shape_origin))*mass;
- _inertia += shape->get_moment_of_inertia(mass) + mass * get_shape_transform(i).get_origin();
}
- if (_inertia!=Vector3())
- _inv_inertia=_inertia.inverse();
- else
- _inv_inertia=Vector3();
+ // Compute the principal axes of inertia
+ principal_inertia_axes_local = inertia_tensor.diagonalize().transposed();
+ _inv_inertia = inertia_tensor.get_main_diagonal().inverse();
if (mass)
_inv_mass=1.0/mass;
@@ -92,20 +119,21 @@ void BodySW::update_inertias() {
case PhysicsServer::BODY_MODE_KINEMATIC:
case PhysicsServer::BODY_MODE_STATIC: {
- _inv_inertia=Vector3();
+ _inv_inertia_tensor.set_zero();
_inv_mass=0;
} break;
case PhysicsServer::BODY_MODE_CHARACTER: {
- _inv_inertia=Vector3();
+ _inv_inertia_tensor.set_zero();
_inv_mass=1.0/mass;
} break;
}
- _update_inertia_tensor();
+
//_update_shapes();
+ _update_transform_dependant();
}
@@ -142,7 +170,7 @@ void BodySW::set_active(bool p_active) {
-void BodySW::set_param(PhysicsServer::BodyParameter p_param, float p_value) {
+void BodySW::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) {
switch(p_param) {
case PhysicsServer::BODY_PARAM_BOUNCE: {
@@ -174,7 +202,7 @@ void BodySW::set_param(PhysicsServer::BodyParameter p_param, float p_value) {
}
}
-float BodySW::get_param(PhysicsServer::BodyParameter p_param) const {
+real_t BodySW::get_param(PhysicsServer::BodyParameter p_param) const {
switch(p_param) {
case PhysicsServer::BODY_PARAM_BOUNCE: {
@@ -242,8 +270,10 @@ void BodySW::set_mode(PhysicsServer::BodyMode p_mode) {
}
_update_inertia();
- //if (get_space())
-// _update_queries();
+ /*
+ if (get_space())
+ _update_queries();
+ */
}
PhysicsServer::BodyMode BodySW::get_mode() const {
@@ -291,14 +321,18 @@ void BodySW::set_state(PhysicsServer::BodyState p_state, const Variant& p_varian
} break;
case PhysicsServer::BODY_STATE_LINEAR_VELOCITY: {
- //if (mode==PhysicsServer::BODY_MODE_STATIC)
- // break;
+ /*
+ if (mode==PhysicsServer::BODY_MODE_STATIC)
+ break;
+ */
linear_velocity=p_variant;
wakeup();
} break;
case PhysicsServer::BODY_STATE_ANGULAR_VELOCITY: {
- //if (mode!=PhysicsServer::BODY_MODE_RIGID)
- // break;
+ /*
+ if (mode!=PhysicsServer::BODY_MODE_RIGID)
+ break;
+ */
angular_velocity=p_variant;
wakeup();
@@ -372,11 +406,13 @@ void BodySW::set_space(SpaceSW *p_space){
_update_inertia();
if (active)
get_space()->body_add_to_active_list(&active_list);
-// _update_queries();
- //if (is_active()) {
- // active=false;
- // set_active(true);
- //}
+ /*
+ _update_queries();
+ if (is_active()) {
+ active=false;
+ set_active(true);
+ }
+ */
}
@@ -451,13 +487,17 @@ void BodySW::integrate_forces(real_t p_step) {
// If less than 0, override dampenings with that of the Body
if (angular_damp>=0)
area_angular_damp=angular_damp;
- //else
- // area_angular_damp=damp_area->get_angular_damp();
+ /*
+ else
+ area_angular_damp=damp_area->get_angular_damp();
+ */
if (linear_damp>=0)
area_linear_damp=linear_damp;
- //else
- // area_linear_damp=damp_area->get_linear_damp();
+ /*
+ else
+ area_linear_damp=damp_area->get_linear_damp();
+ */
Vector3 motion;
@@ -469,9 +509,9 @@ void BodySW::integrate_forces(real_t p_step) {
linear_velocity = (new_transform.origin - get_transform().origin)/p_step;
//compute a FAKE angular velocity, not so easy
- Matrix3 rot=new_transform.basis.orthonormalized().transposed() * get_transform().basis.orthonormalized();
+ Basis rot=new_transform.basis.orthonormalized().transposed() * get_transform().basis.orthonormalized();
Vector3 axis;
- float angle;
+ real_t angle;
rot.get_axis_and_angle(axis,angle);
axis.normalize();
@@ -575,13 +615,15 @@ void BodySW::integrate_velocities(real_t p_step) {
- float ang_vel = total_angular_velocity.length();
+ real_t ang_vel = total_angular_velocity.length();
Transform transform = get_transform();
if (ang_vel!=0.0) {
Vector3 ang_vel_axis = total_angular_velocity / ang_vel;
- Matrix3 rot( ang_vel_axis, -ang_vel*p_step );
+ Basis rot( ang_vel_axis, ang_vel*p_step );
+ Basis identity3(1, 0, 0, 0, 1, 0, 0, 0, 1);
+ transform.origin += ((identity3 - rot) * transform.basis).xform(center_of_mass_local);
transform.basis = rot * transform.basis;
transform.orthonormalize();
}
@@ -598,12 +640,12 @@ void BodySW::integrate_velocities(real_t p_step) {
_set_transform(transform);
_set_inv_transform(get_transform().inverse());
- _update_inertia_tensor();
-
- //if (fi_callback) {
+ _update_transform_dependant();
- // get_space()->body_add_to_state_query_list(&direct_state_query_list);
- //
+ /*
+ if (fi_callback) {
+ get_space()->body_add_to_state_query_list(&direct_state_query_list);
+ */
}
/*
@@ -624,7 +666,7 @@ void BodySW::simulate_motion(const Transform& p_xform,real_t p_step) {
//compute a FAKE angular velocity, not so easy
Matrix3 rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized();
Vector3 axis;
- float angle;
+ real_t angle;
rot.get_axis_and_angle(axis,angle);
axis.normalize();
@@ -742,12 +784,12 @@ BodySW::BodySW() : CollisionObjectSW(TYPE_BODY), active_list(this), inertia_upda
active=true;
mass=1;
-// _inv_inertia=Transform();
+ //_inv_inertia=Transform();
_inv_mass=1;
bounce=0;
friction=1;
omit_force_integration=false;
-// applied_torque=0;
+ //applied_torque=0;
island_step=0;
island_next=NULL;
island_list_next=NULL;
diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h
index 870e8357f1..2383d2d688 100644
--- a/servers/physics/body_sw.h
+++ b/servers/physics/body_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -57,8 +57,16 @@ class BodySW : public CollisionObjectSW {
PhysicsServer::BodyAxisLock axis_lock;
real_t _inv_mass;
- Vector3 _inv_inertia;
- Matrix3 _inv_inertia_tensor;
+ Vector3 _inv_inertia; // Relative to the principal axes of inertia
+
+ // Relative to the local frame of reference
+ Basis principal_inertia_axes_local;
+ Vector3 center_of_mass_local;
+
+ // In world orientation with local origin
+ Basis _inv_inertia_tensor;
+ Basis principal_inertia_axes;
+ Vector3 center_of_mass;
Vector3 gravity;
@@ -67,8 +75,8 @@ class BodySW : public CollisionObjectSW {
Vector3 applied_force;
Vector3 applied_torque;
- float area_angular_damp;
- float area_linear_damp;
+ real_t area_angular_damp;
+ real_t area_linear_damp;
SelfList<BodySW> active_list;
@@ -107,7 +115,7 @@ class BodySW : public CollisionObjectSW {
Vector3 local_pos;
Vector3 local_normal;
- float depth;
+ real_t depth;
int local_shape;
Vector3 collider_pos;
int collider_shape;
@@ -135,7 +143,7 @@ class BodySW : public CollisionObjectSW {
_FORCE_INLINE_ void _compute_area_gravity_and_dampenings(const AreaSW *p_area);
- _FORCE_INLINE_ void _update_inertia_tensor();
+ _FORCE_INLINE_ void _update_transform_dependant();
friend class PhysicsDirectBodyStateSW; // i give up, too many functions to expose
@@ -166,7 +174,7 @@ public:
_FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); }
_FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); }
- _FORCE_INLINE_ void add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, float p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos);
+ _FORCE_INLINE_ void add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, real_t p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos);
_FORCE_INLINE_ void add_exception(const RID& p_exception) { exceptions.insert(p_exception);}
@@ -190,6 +198,10 @@ public:
_FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration=p_omit_force_integration; }
_FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; }
+ _FORCE_INLINE_ Basis get_principal_inertia_axes() const { return principal_inertia_axes; }
+ _FORCE_INLINE_ Vector3 get_center_of_mass() const { return center_of_mass; }
+ _FORCE_INLINE_ Vector3 xform_local_to_principal(const Vector3& p_pos) const { return principal_inertia_axes_local.xform(p_pos - center_of_mass_local); }
+
_FORCE_INLINE_ void set_linear_velocity(const Vector3& p_velocity) {linear_velocity=p_velocity; }
_FORCE_INLINE_ Vector3 get_linear_velocity() const { return linear_velocity; }
@@ -202,18 +214,23 @@ public:
_FORCE_INLINE_ void apply_impulse(const Vector3& p_pos, const Vector3& p_j) {
linear_velocity += p_j * _inv_mass;
- angular_velocity += _inv_inertia_tensor.xform( p_pos.cross(p_j) );
+ angular_velocity += _inv_inertia_tensor.xform( (p_pos-center_of_mass).cross(p_j) );
+ }
+
+ _FORCE_INLINE_ void apply_torque_impulse(const Vector3& p_j) {
+
+ angular_velocity += _inv_inertia_tensor.xform(p_j);
}
_FORCE_INLINE_ void apply_bias_impulse(const Vector3& p_pos, const Vector3& p_j) {
biased_linear_velocity += p_j * _inv_mass;
- biased_angular_velocity += _inv_inertia_tensor.xform( p_pos.cross(p_j) );
+ biased_angular_velocity += _inv_inertia_tensor.xform( (p_pos-center_of_mass).cross(p_j) );
}
- _FORCE_INLINE_ void apply_torque_impulse(const Vector3& p_j) {
+ _FORCE_INLINE_ void apply_bias_torque_impulse(const Vector3& p_j) {
- angular_velocity += _inv_inertia_tensor.xform(p_j);
+ biased_angular_velocity += _inv_inertia_tensor.xform(p_j);
}
_FORCE_INLINE_ void add_force(const Vector3& p_force, const Vector3& p_pos) {
@@ -231,8 +248,8 @@ public:
set_active(true);
}
- void set_param(PhysicsServer::BodyParameter p_param, float);
- float get_param(PhysicsServer::BodyParameter p_param) const;
+ void set_param(PhysicsServer::BodyParameter p_param, real_t);
+ real_t get_param(PhysicsServer::BodyParameter p_param) const;
void set_mode(PhysicsServer::BodyMode p_mode);
PhysicsServer::BodyMode get_mode() const;
@@ -255,7 +272,7 @@ public:
_FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; }
_FORCE_INLINE_ Vector3 get_inv_inertia() const { return _inv_inertia; }
- _FORCE_INLINE_ Matrix3 get_inv_inertia_tensor() const { return _inv_inertia_tensor; }
+ _FORCE_INLINE_ Basis get_inv_inertia_tensor() const { return _inv_inertia_tensor; }
_FORCE_INLINE_ real_t get_friction() const { return friction; }
_FORCE_INLINE_ Vector3 get_gravity() const { return gravity; }
_FORCE_INLINE_ real_t get_bounce() const { return bounce; }
@@ -268,12 +285,12 @@ public:
_FORCE_INLINE_ Vector3 get_velocity_in_local_point(const Vector3& rel_pos) const {
- return linear_velocity + angular_velocity.cross(rel_pos);
+ return linear_velocity + angular_velocity.cross(rel_pos-center_of_mass);
}
_FORCE_INLINE_ real_t compute_impulse_denominator(const Vector3& p_pos, const Vector3& p_normal) const {
- Vector3 r0 = p_pos - get_transform().origin;
+ Vector3 r0 = p_pos - get_transform().origin - center_of_mass;
Vector3 c0 = (r0).cross(p_normal);
@@ -302,7 +319,7 @@ public:
//add contact inline
-void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, float p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos) {
+void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_normal, real_t p_depth, int p_local_shape, const Vector3& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector3& p_collider_velocity_at_pos) {
int c_max=contacts.size();
@@ -318,7 +335,7 @@ void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_norma
idx=contact_count++;
} else {
- float least_depth=1e20;
+ real_t least_depth=1e20;
int least_deep=-1;
for(int i=0;i<c_max;i++) {
@@ -351,7 +368,7 @@ void BodySW::add_contact(const Vector3& p_local_pos,const Vector3& p_local_norma
class PhysicsDirectBodyStateSW : public PhysicsDirectBodyState {
- OBJ_TYPE( PhysicsDirectBodyStateSW, PhysicsDirectBodyState );
+ GDCLASS( PhysicsDirectBodyStateSW, PhysicsDirectBodyState );
public:
@@ -360,12 +377,15 @@ public:
real_t step;
virtual Vector3 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area
- virtual float get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area
- virtual float get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area
+ virtual real_t get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area
+ virtual real_t get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area
+
+ virtual Vector3 get_center_of_mass() const { return body->get_center_of_mass(); }
+ virtual Basis get_principal_inertia_axes() const { return body->get_principal_inertia_axes(); }
- virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
+ virtual real_t get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
virtual Vector3 get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space
- virtual Matrix3 get_inverse_inertia_tensor() const { return body->get_inv_inertia_tensor(); } // get density of this body space
+ virtual Basis get_inverse_inertia_tensor() const { return body->get_inv_inertia_tensor(); } // get density of this body space
virtual void set_linear_velocity(const Vector3& p_velocity) { body->set_linear_velocity(p_velocity); }
virtual Vector3 get_linear_velocity() const { return body->get_linear_velocity(); }
@@ -378,6 +398,7 @@ public:
virtual void add_force(const Vector3& p_force, const Vector3& p_pos) { body->add_force(p_force,p_pos); }
virtual void apply_impulse(const Vector3& p_pos, const Vector3& p_j) { body->apply_impulse(p_pos,p_j); }
+ virtual void apply_torque_impulse(const Vector3& p_j) { body->apply_torque_impulse(p_j); }
virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); }
virtual bool is_sleeping() const { return !body->is_active(); }
diff --git a/servers/physics/broad_phase_basic.cpp b/servers/physics/broad_phase_basic.cpp
index 0bed56d398..f1c22caae3 100644
--- a/servers/physics/broad_phase_basic.cpp
+++ b/servers/physics/broad_phase_basic.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -47,7 +47,7 @@ BroadPhaseSW::ID BroadPhaseBasic::create(CollisionObjectSW *p_object_, int p_sub
return current;
}
-void BroadPhaseBasic::move(ID p_id, const AABB& p_aabb) {
+void BroadPhaseBasic::move(ID p_id, const Rect3& p_aabb) {
Map<ID,Element>::Element *E=element_map.find(p_id);
ERR_FAIL_COND(!E);
@@ -115,7 +115,7 @@ int BroadPhaseBasic::cull_segment(const Vector3& p_from, const Vector3& p_to,Col
for (Map<ID,Element>::Element *E=element_map.front();E;E=E->next()) {
- const AABB aabb=E->get().aabb;
+ const Rect3 aabb=E->get().aabb;
if (aabb.intersects_segment(p_from,p_to)) {
p_results[rc]=E->get().owner;
@@ -129,13 +129,13 @@ int BroadPhaseBasic::cull_segment(const Vector3& p_from, const Vector3& p_to,Col
return rc;
}
-int BroadPhaseBasic::cull_aabb(const AABB& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices) {
+int BroadPhaseBasic::cull_aabb(const Rect3& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices) {
int rc=0;
for (Map<ID,Element>::Element *E=element_map.front();E;E=E->next()) {
- const AABB aabb=E->get().aabb;
+ const Rect3 aabb=E->get().aabb;
if (aabb.intersects(p_aabb)) {
p_results[rc]=E->get().owner;
diff --git a/servers/physics/broad_phase_basic.h b/servers/physics/broad_phase_basic.h
index 6bf024044e..9f07e896c4 100644
--- a/servers/physics/broad_phase_basic.h
+++ b/servers/physics/broad_phase_basic.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -38,7 +38,7 @@ class BroadPhaseBasic : public BroadPhaseSW {
CollisionObjectSW *owner;
bool _static;
- AABB aabb;
+ Rect3 aabb;
int subindex;
};
@@ -78,7 +78,7 @@ public:
// 0 is an invalid ID
virtual ID create(CollisionObjectSW *p_object_, int p_subindex=0);
- virtual void move(ID p_id, const AABB& p_aabb);
+ virtual void move(ID p_id, const Rect3& p_aabb);
virtual void set_static(ID p_id, bool p_static);
virtual void remove(ID p_id);
@@ -87,7 +87,7 @@ public:
virtual int get_subindex(ID p_id) const;
virtual int cull_segment(const Vector3& p_from, const Vector3& p_to,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL);
- virtual int cull_aabb(const AABB& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL);
+ virtual int cull_aabb(const Rect3& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL);
virtual void set_pair_callback(PairCallback p_pair_callback,void *p_userdata);
virtual void set_unpair_callback(UnpairCallback p_unpair_callback,void *p_userdata);
diff --git a/servers/physics/broad_phase_octree.cpp b/servers/physics/broad_phase_octree.cpp
index bfe41f8423..89581997a2 100644
--- a/servers/physics/broad_phase_octree.cpp
+++ b/servers/physics/broad_phase_octree.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,13 +29,13 @@
#include "broad_phase_octree.h"
#include "collision_object_sw.h"
-ID BroadPhaseOctree::create(CollisionObjectSW *p_object, int p_subindex) {
+BroadPhaseSW::ID BroadPhaseOctree::create(CollisionObjectSW *p_object, int p_subindex) {
- ID oid = octree.create(p_object,AABB(),p_subindex,false,1<<p_object->get_type(),0);
+ ID oid = octree.create(p_object,Rect3(),p_subindex,false,1<<p_object->get_type(),0);
return oid;
}
-void BroadPhaseOctree::move(ID p_id, const AABB& p_aabb){
+void BroadPhaseOctree::move(ID p_id, const Rect3& p_aabb){
octree.move(p_id,p_aabb);
}
@@ -71,7 +71,7 @@ int BroadPhaseOctree::cull_segment(const Vector3& p_from, const Vector3& p_to,Co
return octree.cull_segment(p_from,p_to,p_results,p_max_results,p_result_indices);
}
-int BroadPhaseOctree::cull_aabb(const AABB& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices) {
+int BroadPhaseOctree::cull_aabb(const Rect3& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices) {
return octree.cull_AABB(p_aabb,p_results,p_max_results,p_result_indices);
diff --git a/servers/physics/broad_phase_octree.h b/servers/physics/broad_phase_octree.h
index b87996a58c..29f1123edf 100644
--- a/servers/physics/broad_phase_octree.h
+++ b/servers/physics/broad_phase_octree.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -50,7 +50,7 @@ public:
// 0 is an invalid ID
virtual ID create(CollisionObjectSW *p_object_, int p_subindex=0);
- virtual void move(ID p_id, const AABB& p_aabb);
+ virtual void move(ID p_id, const Rect3& p_aabb);
virtual void set_static(ID p_id, bool p_static);
virtual void remove(ID p_id);
@@ -59,7 +59,7 @@ public:
virtual int get_subindex(ID p_id) const;
virtual int cull_segment(const Vector3& p_from, const Vector3& p_to,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL);
- virtual int cull_aabb(const AABB& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL);
+ virtual int cull_aabb(const Rect3& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL);
virtual void set_pair_callback(PairCallback p_pair_callback,void *p_userdata);
virtual void set_unpair_callback(UnpairCallback p_unpair_callback,void *p_userdata);
diff --git a/servers/physics/broad_phase_sw.cpp b/servers/physics/broad_phase_sw.cpp
index a382df6a46..2a897dea2b 100644
--- a/servers/physics/broad_phase_sw.cpp
+++ b/servers/physics/broad_phase_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/broad_phase_sw.h b/servers/physics/broad_phase_sw.h
index 409c249865..20b3efc7fb 100644
--- a/servers/physics/broad_phase_sw.h
+++ b/servers/physics/broad_phase_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,7 +30,7 @@
#define BROAD_PHASE_SW_H
#include "math_funcs.h"
-#include "aabb.h"
+#include "rect3.h"
class CollisionObjectSW;
@@ -50,7 +50,7 @@ public:
// 0 is an invalid ID
virtual ID create(CollisionObjectSW *p_object_, int p_subindex=0)=0;
- virtual void move(ID p_id, const AABB& p_aabb)=0;
+ virtual void move(ID p_id, const Rect3& p_aabb)=0;
virtual void set_static(ID p_id, bool p_static)=0;
virtual void remove(ID p_id)=0;
@@ -59,7 +59,7 @@ public:
virtual int get_subindex(ID p_id) const=0;
virtual int cull_segment(const Vector3& p_from, const Vector3& p_to,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL)=0;
- virtual int cull_aabb(const AABB& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL)=0;
+ virtual int cull_aabb(const Rect3& p_aabb,CollisionObjectSW** p_results,int p_max_results,int *p_result_indices=NULL)=0;
virtual void set_pair_callback(PairCallback p_pair_callback,void *p_userdata)=0;
virtual void set_unpair_callback(UnpairCallback p_unpair_callback,void *p_userdata)=0;
diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp
index f2864ee95e..88aa737579 100644
--- a/servers/physics/collision_object_sw.cpp
+++ b/servers/physics/collision_object_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -138,12 +138,14 @@ void CollisionObjectSW::_update_shapes() {
}
//not quite correct, should compute the next matrix..
- AABB shape_aabb=s.shape->get_aabb();
+ Rect3 shape_aabb=s.shape->get_aabb();
Transform xform = transform * s.xform;
shape_aabb=xform.xform(shape_aabb);
s.aabb_cache=shape_aabb;
s.aabb_cache=s.aabb_cache.grow( (s.aabb_cache.size.x + s.aabb_cache.size.y)*0.5*0.05 );
+ Vector3 scale = xform.get_basis().get_scale();
+ s.area_cache=s.shape->get_area()*scale.x*scale.y*scale.z;
space->get_broadphase()->move(s.bpid,s.aabb_cache);
}
@@ -165,10 +167,10 @@ void CollisionObjectSW::_update_shapes_with_motion(const Vector3& p_motion) {
}
//not quite correct, should compute the next matrix..
- AABB shape_aabb=s.shape->get_aabb();
+ Rect3 shape_aabb=s.shape->get_aabb();
Transform xform = transform * s.xform;
shape_aabb=xform.xform(shape_aabb);
- shape_aabb=shape_aabb.merge(AABB( shape_aabb.pos+p_motion,shape_aabb.size)); //use motion
+ shape_aabb=shape_aabb.merge(Rect3( shape_aabb.pos+p_motion,shape_aabb.size)); //use motion
s.aabb_cache=shape_aabb;
space->get_broadphase()->move(s.bpid,shape_aabb);
diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h
index bc71c2709b..c46a7f4a5f 100644
--- a/servers/physics/collision_object_sw.h
+++ b/servers/physics/collision_object_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -60,7 +60,8 @@ private:
Transform xform;
Transform xform_inv;
BroadPhaseSW::ID bpid;
- AABB aabb_cache; //for rayqueries
+ Rect3 aabb_cache; //for rayqueries
+ real_t area_cache;
ShapeSW *shape;
bool trigger;
@@ -122,7 +123,8 @@ public:
_FORCE_INLINE_ ShapeSW *get_shape(int p_index) const { return shapes[p_index].shape; }
_FORCE_INLINE_ const Transform& get_shape_transform(int p_index) const { return shapes[p_index].xform; }
_FORCE_INLINE_ const Transform& get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
- _FORCE_INLINE_ const AABB& get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
+ _FORCE_INLINE_ const Rect3& get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
+ _FORCE_INLINE_ const real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; }
_FORCE_INLINE_ Transform get_transform() const { return transform; }
_FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; }
diff --git a/servers/physics/collision_solver_sat.cpp b/servers/physics/collision_solver_sat.cpp
index 3e7719e5eb..9d3e1db47b 100644
--- a/servers/physics/collision_solver_sat.cpp
+++ b/servers/physics/collision_solver_sat.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,9 +42,11 @@ struct _CollectorCallback {
_FORCE_INLINE_ void call(const Vector3& p_point_A, const Vector3& p_point_B) {
- //if (normal.dot(p_point_A) >= normal.dot(p_point_B))
- // return;
-// print_line("** A: "+p_point_A+" B: "+p_point_B+" D: "+rtos(p_point_A.distance_to(p_point_B)));
+ /*
+ if (normal.dot(p_point_A) >= normal.dot(p_point_B))
+ return;
+ print_line("** A: "+p_point_A+" B: "+p_point_B+" D: "+rtos(p_point_A.distance_to(p_point_B)));
+ */
if (swap)
callback(p_point_B,p_point_A,userdata);
@@ -108,7 +110,7 @@ static void _generate_contacts_edge_edge(const Vector3 * p_points_A,int p_point_
Vector3 c=rel_A.cross(rel_B).cross(rel_B);
-// if ( Math::abs(rel_A.dot(c) )<_EDGE_IS_VALID_SUPPORT_TRESHOLD ) {
+ //if ( Math::abs(rel_A.dot(c) )<_EDGE_IS_VALID_SUPPORT_TRESHOLD ) {
if ( Math::abs(rel_A.dot(c) )<CMP_EPSILON ) {
// should handle somehow..
@@ -120,9 +122,9 @@ static void _generate_contacts_edge_edge(const Vector3 * p_points_A,int p_point_
Vector3 base_B = p_points_B[0] - axis * axis.dot(p_points_B[0]);
//sort all 4 points in axis
- float dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) };
+ real_t dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) };
- SortArray<float> sa;
+ SortArray<real_t> sa;
sa.sort(dvec,4);
//use the middle ones as contacts
@@ -205,7 +207,7 @@ static void _generate_contacts_face_face(const Vector3 * p_points_A,int p_point_
// check for different sides and non coplanar
-// if ( (dist0*dist1) < -CMP_EPSILON && !(edge && j)) {
+ //if ( (dist0*dist1) < -CMP_EPSILON && !(edge && j)) {
if ( (dist0*dist1) < 0 && !(edge && j)) {
// calculate intersection
@@ -232,9 +234,11 @@ static void _generate_contacts_face_face(const Vector3 * p_points_A,int p_point_
for (int i=0;i<clipbuf_len;i++) {
- float d = plane_B.distance_to(clipbuf_src[i]);
- //if (d>CMP_EPSILON)
- // continue;
+ real_t d = plane_B.distance_to(clipbuf_src[i]);
+ /*
+ if (d>CMP_EPSILON)
+ continue;
+ */
Vector3 closest_B=clipbuf_src[i] - plane_B.normal*d;
@@ -472,11 +476,11 @@ public:
/****** SAT TESTS *******/
-typedef void (*CollisionFunc)(const ShapeSW*,const Transform&,const ShapeSW*,const Transform&,_CollectorCallback *p_callback,float,float);
+typedef void (*CollisionFunc)(const ShapeSW*,const Transform&,const ShapeSW*,const Transform&,_CollectorCallback *p_callback,real_t,real_t);
template<bool withMargin>
-static void _collision_sphere_sphere(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_sphere_sphere(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a);
@@ -496,7 +500,7 @@ static void _collision_sphere_sphere(const ShapeSW *p_a,const Transform &p_trans
}
template<bool withMargin>
-static void _collision_sphere_box(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_sphere_box(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a);
@@ -551,7 +555,7 @@ static void _collision_sphere_box(const ShapeSW *p_a,const Transform &p_transfor
}
template<bool withMargin>
-static void _collision_sphere_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_sphere_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a);
const CapsuleShapeSW *capsule_B = static_cast<const CapsuleShapeSW*>(p_b);
@@ -591,7 +595,7 @@ static void _collision_sphere_capsule(const ShapeSW *p_a,const Transform &p_tran
}
template<bool withMargin>
-static void _collision_sphere_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_sphere_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a);
@@ -635,7 +639,7 @@ static void _collision_sphere_convex_polygon(const ShapeSW *p_a,const Transform
Vector3 n1=v2-v1;
Vector3 n2=v2-v3;
- Vector3 axis = n1.cross(n2).cross(n1).normalized();;
+ Vector3 axis = n1.cross(n2).cross(n1).normalized();
if (!separator.test_axis( axis ))
return;
@@ -662,7 +666,7 @@ static void _collision_sphere_convex_polygon(const ShapeSW *p_a,const Transform
}
template<bool withMargin>
-static void _collision_sphere_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_sphere_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const SphereShapeSW *sphere_A = static_cast<const SphereShapeSW*>(p_a);
const FaceShapeSW *face_B = static_cast<const FaceShapeSW*>(p_b);
@@ -706,7 +710,7 @@ static void _collision_sphere_face(const ShapeSW *p_a,const Transform &p_transfo
template<bool withMargin>
-static void _collision_box_box(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_box_box(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const BoxShapeSW *box_A = static_cast<const BoxShapeSW*>(p_a);
@@ -814,7 +818,7 @@ static void _collision_box_box(const ShapeSW *p_a,const Transform &p_transform_a
}
template<bool withMargin>
-static void _collision_box_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_box_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const BoxShapeSW *box_A = static_cast<const BoxShapeSW*>(p_a);
const CapsuleShapeSW *capsule_B = static_cast<const CapsuleShapeSW*>(p_b);
@@ -914,7 +918,7 @@ static void _collision_box_capsule(const ShapeSW *p_a,const Transform &p_transfo
}
template<bool withMargin>
-static void _collision_box_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_box_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
@@ -1042,7 +1046,7 @@ static void _collision_box_convex_polygon(const ShapeSW *p_a,const Transform &p_
template<bool withMargin>
-static void _collision_box_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_box_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const BoxShapeSW *box_A = static_cast<const BoxShapeSW*>(p_a);
@@ -1154,7 +1158,7 @@ static void _collision_box_face(const ShapeSW *p_a,const Transform &p_transform_
template<bool withMargin>
-static void _collision_capsule_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_capsule_capsule(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const CapsuleShapeSW *capsule_A = static_cast<const CapsuleShapeSW*>(p_a);
const CapsuleShapeSW *capsule_B = static_cast<const CapsuleShapeSW*>(p_b);
@@ -1212,7 +1216,7 @@ static void _collision_capsule_capsule(const ShapeSW *p_a,const Transform &p_tra
}
template<bool withMargin>
-static void _collision_capsule_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_capsule_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const CapsuleShapeSW *capsule_A = static_cast<const CapsuleShapeSW*>(p_a);
@@ -1283,7 +1287,7 @@ static void _collision_capsule_convex_polygon(const ShapeSW *p_a,const Transform
template<bool withMargin>
-static void _collision_capsule_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_capsule_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const CapsuleShapeSW *capsule_A = static_cast<const CapsuleShapeSW*>(p_a);
const FaceShapeSW *face_B = static_cast<const FaceShapeSW*>(p_b);
@@ -1346,7 +1350,7 @@ static void _collision_capsule_face(const ShapeSW *p_a,const Transform &p_transf
template<bool withMargin>
-static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Transform &p_transform_a,const ShapeSW *p_b,const Transform &p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const ConvexPolygonShapeSW *convex_polygon_A = static_cast<const ConvexPolygonShapeSW*>(p_a);
@@ -1379,7 +1383,7 @@ static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Tr
for (int i=0;i<face_count_A;i++) {
Vector3 axis = p_transform_a.xform( faces_A[i].plane ).normal;
-// Vector3 axis = p_transform_a.basis.xform( faces_A[i].plane.normal ).normalized();
+ //Vector3 axis = p_transform_a.basis.xform( faces_A[i].plane.normal ).normalized();
if (!separator.test_axis( axis ))
return;
@@ -1389,7 +1393,7 @@ static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Tr
for (int i=0;i<face_count_B;i++) {
Vector3 axis = p_transform_b.xform( faces_B[i].plane ).normal;
-// Vector3 axis = p_transform_b.basis.xform( faces_B[i].plane.normal ).normalized();
+ //Vector3 axis = p_transform_b.basis.xform( faces_B[i].plane.normal ).normalized();
if (!separator.test_axis( axis ))
@@ -1470,7 +1474,7 @@ static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a,const Tr
template<bool withMargin>
-static void _collision_convex_polygon_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,float p_margin_a,float p_margin_b) {
+static void _collision_convex_polygon_face(const ShapeSW *p_a,const Transform &p_transform_a, const ShapeSW *p_b,const Transform& p_transform_b,_CollectorCallback *p_collector,real_t p_margin_a,real_t p_margin_b) {
const ConvexPolygonShapeSW *convex_polygon_A = static_cast<const ConvexPolygonShapeSW*>(p_a);
@@ -1502,7 +1506,7 @@ static void _collision_convex_polygon_face(const ShapeSW *p_a,const Transform &p
// faces of A
for (int i=0;i<face_count;i++) {
-// Vector3 axis = p_transform_a.xform( faces[i].plane ).normal;
+ //Vector3 axis = p_transform_a.xform( faces[i].plane ).normal;
Vector3 axis = p_transform_a.basis.xform( faces[i].plane.normal ).normalized();
if (!separator.test_axis( axis ))
@@ -1581,7 +1585,7 @@ static void _collision_convex_polygon_face(const ShapeSW *p_a,const Transform &p
}
-bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_transform_A, const ShapeSW *p_shape_B, const Transform& p_transform_B, CollisionSolverSW::CallbackResult p_result_callback,void *p_userdata,bool p_swap,Vector3* r_prev_axis,float p_margin_a,float p_margin_b) {
+bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_transform_A, const ShapeSW *p_shape_B, const Transform& p_transform_B, CollisionSolverSW::CallbackResult p_result_callback,void *p_userdata,bool p_swap,Vector3* r_prev_axis,real_t p_margin_a,real_t p_margin_b) {
PhysicsServer::ShapeType type_A=p_shape_A->get_type();
@@ -1663,8 +1667,8 @@ bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_tran
const ShapeSW *B=p_shape_B;
const Transform *transform_A=&p_transform_A;
const Transform *transform_B=&p_transform_B;
- float margin_A=p_margin_a;
- float margin_B=p_margin_b;
+ real_t margin_A=p_margin_a;
+ real_t margin_B=p_margin_b;
if (type_A > type_B) {
SWAP(A,B);
diff --git a/servers/physics/collision_solver_sat.h b/servers/physics/collision_solver_sat.h
index 57f5bdbbc0..15fe7dc34a 100644
--- a/servers/physics/collision_solver_sat.h
+++ b/servers/physics/collision_solver_sat.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,6 +32,6 @@
#include "collision_solver_sw.h"
-bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_transform_A, const ShapeSW *p_shape_B, const Transform& p_transform_B, CollisionSolverSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector3* r_prev_axis=NULL,float p_margin_a=0,float p_margin_b=0);
+bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform& p_transform_A, const ShapeSW *p_shape_B, const Transform& p_transform_B, CollisionSolverSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector3* r_prev_axis=NULL,real_t p_margin_a=0,real_t p_margin_b=0);
#endif // COLLISION_SOLVER_SAT_H
diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp
index 716e724637..f0ddde3a76 100644
--- a/servers/physics/collision_solver_sw.cpp
+++ b/servers/physics/collision_solver_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -115,8 +115,8 @@ struct _ConcaveCollisionInfo {
int aabb_tests;
int collisions;
bool tested;
- float margin_A;
- float margin_B;
+ real_t margin_A;
+ real_t margin_B;
Vector3 close_A,close_B;
};
@@ -136,7 +136,7 @@ void CollisionSolverSW::concave_callback(void *p_userdata, ShapeSW *p_convex) {
}
-bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,float p_margin_A,float p_margin_B) {
+bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,real_t p_margin_A,real_t p_margin_B) {
const ConcaveShapeSW *concave_B=static_cast<const ConcaveShapeSW*>(p_shape_B);
@@ -160,14 +160,14 @@ bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A,const Transform&
//quickly compute a local AABB
- AABB local_aabb;
+ Rect3 local_aabb;
for(int i=0;i<3;i++) {
Vector3 axis( p_transform_B.basis.get_axis(i) );
- float axis_scale = 1.0/axis.length();
+ real_t axis_scale = 1.0/axis.length();
axis*=axis_scale;
- float smin,smax;
+ real_t smin,smax;
p_shape_A->project_range(axis,rel_transform,smin,smax);
smin-=p_margin_A;
smax+=p_margin_A;
@@ -186,7 +186,7 @@ bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A,const Transform&
}
-bool CollisionSolverSW::solve_static(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,Vector3 *r_sep_axis,float p_margin_A,float p_margin_B) {
+bool CollisionSolverSW::solve_static(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,Vector3 *r_sep_axis,real_t p_margin_A,real_t p_margin_B) {
PhysicsServer::ShapeType type_A=p_shape_A->get_type();
@@ -291,7 +291,7 @@ bool CollisionSolverSW::solve_distance_plane(const ShapeSW *p_shape_A,const Tran
bool collided=false;
Vector3 closest;
- float closest_d;
+ real_t closest_d;
for(int i=0;i<support_count;i++) {
@@ -313,7 +313,7 @@ bool CollisionSolverSW::solve_distance_plane(const ShapeSW *p_shape_A,const Tran
return collided;
}
-bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B,const AABB& p_concave_hint,Vector3 *r_sep_axis) {
+bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B,const Rect3& p_concave_hint,Vector3 *r_sep_axis) {
if (p_shape_A->is_concave())
return false;
@@ -351,21 +351,21 @@ bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform&
//quickly compute a local AABB
- bool use_cc_hint=p_concave_hint!=AABB();
- AABB cc_hint_aabb;
+ bool use_cc_hint=p_concave_hint!=Rect3();
+ Rect3 cc_hint_aabb;
if (use_cc_hint) {
cc_hint_aabb=p_concave_hint;
cc_hint_aabb.pos-=p_transform_B.origin;
}
- AABB local_aabb;
+ Rect3 local_aabb;
for(int i=0;i<3;i++) {
Vector3 axis( p_transform_B.basis.get_axis(i) );
- float axis_scale = 1.0/axis.length();
+ real_t axis_scale = ((real_t)1.0)/axis.length();
axis*=axis_scale;
- float smin,smax;
+ real_t smin,smax;
if (use_cc_hint) {
cc_hint_aabb.project_range_in_plane(Plane(axis,0),smin,smax);
@@ -383,7 +383,7 @@ bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A,const Transform&
concave_B->cull(local_aabb,concave_distance_callback,&cinfo);
if (!cinfo.collided) {
-// print_line(itos(cinfo.tested));
+ //print_line(itos(cinfo.tested));
r_point_A=cinfo.close_A;
r_point_B=cinfo.close_B;
diff --git a/servers/physics/collision_solver_sw.h b/servers/physics/collision_solver_sw.h
index abc50cae2c..b8d37a8a96 100644
--- a/servers/physics/collision_solver_sw.h
+++ b/servers/physics/collision_solver_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -40,15 +40,15 @@ private:
static void concave_callback(void *p_userdata, ShapeSW *p_convex);
static bool solve_static_plane(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result);
static bool solve_ray(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result);
- static bool solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,float p_margin_A=0,float p_margin_B=0);
+ static bool solve_concave(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,real_t p_margin_A=0,real_t p_margin_B=0);
static void concave_distance_callback(void *p_userdata, ShapeSW *p_convex);
static bool solve_distance_plane(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B);
public:
- static bool solve_static(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,Vector3 *r_sep_axis=NULL,float p_margin_A=0,float p_margin_B=0);
- static bool solve_distance(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B,const AABB& p_concave_hint,Vector3 *r_sep_axis=NULL);
+ static bool solve_static(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,CallbackResult p_result_callback,void *p_userdata,Vector3 *r_sep_axis=NULL,real_t p_margin_A=0,real_t p_margin_B=0);
+ static bool solve_distance(const ShapeSW *p_shape_A,const Transform& p_transform_A,const ShapeSW *p_shape_B,const Transform& p_transform_B,Vector3& r_point_A,Vector3& r_point_B,const Rect3& p_concave_hint,Vector3 *r_sep_axis=NULL);
};
diff --git a/servers/physics/constraint_sw.h b/servers/physics/constraint_sw.h
index d61701ac07..f5bbe4bbd0 100644
--- a/servers/physics/constraint_sw.h
+++ b/servers/physics/constraint_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,7 +31,7 @@
#include "body_sw.h"
-class ConstraintSW {
+class ConstraintSW : public RID_Data {
BodySW **_body_ptr;
int _body_count;
@@ -67,8 +67,8 @@ public:
_FORCE_INLINE_ int get_priority() const { return priority; }
- virtual bool setup(float p_step)=0;
- virtual void solve(float p_step)=0;
+ virtual bool setup(real_t p_step)=0;
+ virtual void solve(real_t p_step)=0;
virtual ~ConstraintSW() {}
};
diff --git a/servers/physics/gjk_epa.cpp b/servers/physics/gjk_epa.cpp
index 71d6fee2ab..92ca5ea8dd 100644
--- a/servers/physics/gjk_epa.cpp
+++ b/servers/physics/gjk_epa.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/gjk_epa.h b/servers/physics/gjk_epa.h
index 78afd3149f..58cf8f50ce 100644
--- a/servers/physics/gjk_epa.h
+++ b/servers/physics/gjk_epa.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/joints/SCsub b/servers/physics/joints/SCsub
index d31af2c1c4..ccc76e823f 100644
--- a/servers/physics/joints/SCsub
+++ b/servers/physics/joints/SCsub
@@ -1,5 +1,7 @@
+#!/usr/bin/env python
+
Import('env')
-env.add_source_files(env.servers_sources,"*.cpp")
+env.add_source_files(env.servers_sources, "*.cpp")
Export('env')
diff --git a/servers/physics/joints/cone_twist_joint_sw.cpp b/servers/physics/joints/cone_twist_joint_sw.cpp
index 5f1dde4e20..d78bcbd16d 100644
--- a/servers/physics/joints/cone_twist_joint_sw.cpp
+++ b/servers/physics/joints/cone_twist_joint_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -96,7 +96,7 @@ ConeTwistJointSW::ConeTwistJointSW(BodySW* rbA,BodySW* rbB,const Transform& rbAF
}
-bool ConeTwistJointSW::setup(float p_step) {
+bool ConeTwistJointSW::setup(real_t p_step) {
m_appliedImpulse = real_t(0.);
//set bias, sign, clear accumulator
@@ -128,10 +128,10 @@ bool ConeTwistJointSW::setup(float p_step) {
for (int i=0;i<3;i++)
{
memnew_placement(&m_jac[i], JacobianEntrySW(
- A->get_transform().basis.transposed(),
- B->get_transform().basis.transposed(),
- pivotAInW - A->get_transform().origin,
- pivotBInW - B->get_transform().origin,
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ pivotAInW - A->get_transform().origin - A->get_center_of_mass(),
+ pivotBInW - B->get_transform().origin - B->get_center_of_mass(),
normal[i],
A->get_inv_inertia(),
A->get_inv_mass(),
@@ -156,7 +156,7 @@ bool ConeTwistJointSW::setup(float p_step) {
if (m_swingSpan1 >= real_t(0.05f))
{
b1Axis2 = A->get_transform().basis.xform( this->m_rbAFrame.basis.get_axis(1) );
-// swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) );
+ //swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) );
swx = b2Axis1.dot(b1Axis1);
swy = b2Axis1.dot(b1Axis2);
swing1 = atan2fast(swy, swx);
@@ -169,7 +169,7 @@ bool ConeTwistJointSW::setup(float p_step) {
if (m_swingSpan2 >= real_t(0.05f))
{
b1Axis3 = A->get_transform().basis.xform( this->m_rbAFrame.basis.get_axis(2) );
-// swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) );
+ //swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) );
swx = b2Axis1.dot(b1Axis1);
swy = b2Axis1.dot(b1Axis3);
swing2 = atan2fast(swy, swx);
@@ -318,7 +318,7 @@ void ConeTwistJointSW::solve(real_t timeStep)
}
-void ConeTwistJointSW::set_param(PhysicsServer::ConeTwistJointParam p_param, float p_value) {
+void ConeTwistJointSW::set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value) {
switch(p_param) {
case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN: {
@@ -345,7 +345,7 @@ void ConeTwistJointSW::set_param(PhysicsServer::ConeTwistJointParam p_param, flo
}
}
-float ConeTwistJointSW::get_param(PhysicsServer::ConeTwistJointParam p_param) const{
+real_t ConeTwistJointSW::get_param(PhysicsServer::ConeTwistJointParam p_param) const{
switch(p_param) {
case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN: {
diff --git a/servers/physics/joints/cone_twist_joint_sw.h b/servers/physics/joints/cone_twist_joint_sw.h
index 653259071d..eb7a5cd1b1 100644
--- a/servers/physics/joints/cone_twist_joint_sw.h
+++ b/servers/physics/joints/cone_twist_joint_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -109,8 +109,8 @@ public:
virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_CONE_TWIST; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
ConeTwistJointSW(BodySW* rbA,BodySW* rbB,const Transform& rbAFrame, const Transform& rbBFrame);
@@ -146,8 +146,8 @@ public:
return m_twistLimitSign;
}
- void set_param(PhysicsServer::ConeTwistJointParam p_param, float p_value);
- float get_param(PhysicsServer::ConeTwistJointParam p_param) const;
+ void set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value);
+ real_t get_param(PhysicsServer::ConeTwistJointParam p_param) const;
};
diff --git a/servers/physics/joints/generic_6dof_joint_sw.cpp b/servers/physics/joints/generic_6dof_joint_sw.cpp
index 06015a5228..bd07f3122a 100644
--- a/servers/physics/joints/generic_6dof_joint_sw.cpp
+++ b/servers/physics/joints/generic_6dof_joint_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -38,55 +38,6 @@ See corresponding header file for licensing info.
#define GENERIC_D6_DISABLE_WARMSTARTING 1
-real_t btGetMatrixElem(const Matrix3& mat, int index);
-real_t btGetMatrixElem(const Matrix3& mat, int index)
-{
- int i = index%3;
- int j = index/3;
- return mat[i][j];
-}
-
-///MatrixToEulerXYZ from http://www.geometrictools.com/LibFoundation/Mathematics/Wm4Matrix3.inl.html
-bool matrixToEulerXYZ(const Matrix3& mat,Vector3& xyz);
-bool matrixToEulerXYZ(const Matrix3& mat,Vector3& xyz)
-{
-// // rot = cy*cz -cy*sz sy
-// // cz*sx*sy+cx*sz cx*cz-sx*sy*sz -cy*sx
-// // -cx*cz*sy+sx*sz cz*sx+cx*sy*sz cx*cy
-//
-
- if (btGetMatrixElem(mat,2) < real_t(1.0))
- {
- if (btGetMatrixElem(mat,2) > real_t(-1.0))
- {
- xyz[0] = Math::atan2(-btGetMatrixElem(mat,5),btGetMatrixElem(mat,8));
- xyz[1] = Math::asin(btGetMatrixElem(mat,2));
- xyz[2] = Math::atan2(-btGetMatrixElem(mat,1),btGetMatrixElem(mat,0));
- return true;
- }
- else
- {
- // WARNING. Not unique. XA - ZA = -atan2(r10,r11)
- xyz[0] = -Math::atan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
- xyz[1] = -Math_PI*0.5;
- xyz[2] = real_t(0.0);
- return false;
- }
- }
- else
- {
- // WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
- xyz[0] = Math::atan2(btGetMatrixElem(mat,3),btGetMatrixElem(mat,4));
- xyz[1] = Math_PI*0.5;
- xyz[2] = 0.0;
-
- }
-
-
- return false;
-}
-
-
//////////////////////////// G6DOFRotationalLimitMotorSW ////////////////////////////////////
@@ -296,9 +247,9 @@ Generic6DOFJointSW::Generic6DOFJointSW(BodySW* rbA, BodySW* rbB, const Transform
void Generic6DOFJointSW::calculateAngleInfo()
{
- Matrix3 relative_frame = m_calculatedTransformA.basis.inverse()*m_calculatedTransformB.basis;
+ Basis relative_frame = m_calculatedTransformA.basis.inverse()*m_calculatedTransformB.basis;
- matrixToEulerXYZ(relative_frame,m_calculatedAxisAngleDiff);
+ m_calculatedAxisAngleDiff = relative_frame.get_euler();
@@ -325,16 +276,18 @@ void Generic6DOFJointSW::calculateAngleInfo()
m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]);
-// if(m_debugDrawer)
-// {
-//
-// char buff[300];
-// sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ",
-// m_calculatedAxisAngleDiff[0],
-// m_calculatedAxisAngleDiff[1],
-// m_calculatedAxisAngleDiff[2]);
-// m_debugDrawer->reportErrorWarning(buff);
-// }
+ /*
+ if(m_debugDrawer)
+ {
+
+ char buff[300];
+ sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ",
+ m_calculatedAxisAngleDiff[0],
+ m_calculatedAxisAngleDiff[1],
+ m_calculatedAxisAngleDiff[2]);
+ m_debugDrawer->reportErrorWarning(buff);
+ }
+ */
}
@@ -352,10 +305,10 @@ void Generic6DOFJointSW::buildLinearJacobian(
const Vector3 & pivotAInW,const Vector3 & pivotBInW)
{
memnew_placement(&jacLinear, JacobianEntrySW(
- A->get_transform().basis.transposed(),
- B->get_transform().basis.transposed(),
- pivotAInW - A->get_transform().origin,
- pivotBInW - B->get_transform().origin,
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ pivotAInW - A->get_transform().origin - A->get_center_of_mass(),
+ pivotBInW - B->get_transform().origin - B->get_center_of_mass(),
normalWorld,
A->get_inv_inertia(),
A->get_inv_mass(),
@@ -368,8 +321,8 @@ void Generic6DOFJointSW::buildAngularJacobian(
JacobianEntrySW & jacAngular,const Vector3 & jointAxisW)
{
memnew_placement(&jacAngular, JacobianEntrySW(jointAxisW,
- A->get_transform().basis.transposed(),
- B->get_transform().basis.transposed(),
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
A->get_inv_inertia(),
B->get_inv_inertia()));
@@ -384,7 +337,7 @@ bool Generic6DOFJointSW::testAngularLimitMotor(int axis_index)
return m_angularLimits[axis_index].needApplyTorques();
}
-bool Generic6DOFJointSW::setup(float p_step) {
+bool Generic6DOFJointSW::setup(real_t p_step) {
// Clear accumulated impulses for the next simulation step
m_linearLimits.m_accumulatedImpulse=Vector3(real_t(0.), real_t(0.), real_t(0.));
@@ -440,7 +393,7 @@ bool Generic6DOFJointSW::setup(float p_step) {
}
-void Generic6DOFJointSW::solve(real_t timeStep)
+void Generic6DOFJointSW::solve(real_t timeStep)
{
m_timeStep = timeStep;
@@ -530,7 +483,7 @@ void Generic6DOFJointSW::calcAnchorPos(void)
} // Generic6DOFJointSW::calcAnchorPos()
-void Generic6DOFJointSW::set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param, float p_value) {
+void Generic6DOFJointSW::set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value) {
ERR_FAIL_INDEX(p_axis,3);
switch(p_param) {
@@ -606,7 +559,7 @@ void Generic6DOFJointSW::set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJoin
}
}
-float Generic6DOFJointSW::get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param) const{
+real_t Generic6DOFJointSW::get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param) const{
ERR_FAIL_INDEX_V(p_axis,3,0);
switch(p_param) {
case PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT: {
@@ -675,7 +628,7 @@ float Generic6DOFJointSW::get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJoi
} break;
case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: {
- return m_angularLimits[p_axis].m_maxLimitForce;
+ return m_angularLimits[p_axis].m_maxMotorForce;
} break;
}
diff --git a/servers/physics/joints/generic_6dof_joint_sw.h b/servers/physics/joints/generic_6dof_joint_sw.h
index 47ef43156d..207ae85a45 100644
--- a/servers/physics/joints/generic_6dof_joint_sw.h
+++ b/servers/physics/joints/generic_6dof_joint_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -295,8 +295,8 @@ public:
virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_6DOF; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
//! Calcs global transform of the offsets
@@ -449,8 +449,8 @@ public:
virtual void calcAnchorPos(void); // overridable
- void set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param, float p_value);
- float get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param) const;
+ void set_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value);
+ real_t get_param(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisParam p_param) const;
void set_flag(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisFlag p_flag, bool p_value);
bool get_flag(Vector3::Axis p_axis,PhysicsServer::G6DOFJointAxisFlag p_flag) const;
diff --git a/servers/physics/joints/hinge_joint_sw.cpp b/servers/physics/joints/hinge_joint_sw.cpp
index 035407065c..9617eb8794 100644
--- a/servers/physics/joints/hinge_joint_sw.cpp
+++ b/servers/physics/joints/hinge_joint_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -112,7 +112,7 @@ HingeJointSW::HingeJointSW(BodySW* rbA,BodySW* rbB, const Vector3& pivotInA,cons
rbAxisA1 = rbAxisA2.cross(axisInA);
}
- m_rbAFrame.basis=Matrix3( rbAxisA1.x,rbAxisA2.x,axisInA.x,
+ m_rbAFrame.basis=Basis( rbAxisA1.x,rbAxisA2.x,axisInA.x,
rbAxisA1.y,rbAxisA2.y,axisInA.y,
rbAxisA1.z,rbAxisA2.z,axisInA.z );
@@ -121,7 +121,7 @@ HingeJointSW::HingeJointSW(BodySW* rbA,BodySW* rbB, const Vector3& pivotInA,cons
Vector3 rbAxisB2 = axisInB.cross(rbAxisB1);
m_rbBFrame.origin = pivotInB;
- m_rbBFrame.basis=Matrix3( rbAxisB1.x,rbAxisB2.x,-axisInB.x,
+ m_rbBFrame.basis=Basis( rbAxisB1.x,rbAxisB2.x,-axisInB.x,
rbAxisB1.y,rbAxisB2.y,-axisInB.y,
rbAxisB1.z,rbAxisB2.z,-axisInB.z );
@@ -148,7 +148,7 @@ HingeJointSW::HingeJointSW(BodySW* rbA,BodySW* rbB, const Vector3& pivotInA,cons
-bool HingeJointSW::setup(float p_step) {
+bool HingeJointSW::setup(real_t p_step) {
m_appliedImpulse = real_t(0.);
@@ -173,10 +173,10 @@ bool HingeJointSW::setup(float p_step) {
for (int i=0;i<3;i++)
{
memnew_placement(&m_jac[i], JacobianEntrySW(
- A->get_transform().basis.transposed(),
- B->get_transform().basis.transposed(),
- pivotAInW - A->get_transform().origin,
- pivotBInW - B->get_transform().origin,
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ pivotAInW - A->get_transform().origin - A->get_center_of_mass(),
+ pivotBInW - B->get_transform().origin - B->get_center_of_mass(),
normal[i],
A->get_inv_inertia(),
A->get_inv_mass(),
@@ -200,20 +200,20 @@ bool HingeJointSW::setup(float p_step) {
Vector3 hingeAxisWorld = A->get_transform().basis.xform( m_rbAFrame.basis.get_axis(2) );
memnew_placement(&m_jacAng[0], JacobianEntrySW(jointAxis0,
- A->get_transform().basis.transposed(),
- B->get_transform().basis.transposed(),
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
A->get_inv_inertia(),
B->get_inv_inertia()));
memnew_placement(&m_jacAng[1], JacobianEntrySW(jointAxis1,
- A->get_transform().basis.transposed(),
- B->get_transform().basis.transposed(),
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
A->get_inv_inertia(),
B->get_inv_inertia()));
memnew_placement(&m_jacAng[2], JacobianEntrySW(hingeAxisWorld,
- A->get_transform().basis.transposed(),
- B->get_transform().basis.transposed(),
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
A->get_inv_inertia(),
B->get_inv_inertia()));
@@ -221,7 +221,7 @@ bool HingeJointSW::setup(float p_step) {
// Compute limit information
real_t hingeAngle = get_hinge_angle();
-// print_line("angle: "+rtos(hingeAngle));
+ //print_line("angle: "+rtos(hingeAngle));
//set bias, sign, clear accumulator
m_correction = real_t(0.);
m_limitSign = real_t(0.);
@@ -235,17 +235,17 @@ bool HingeJointSW::setup(float p_step) {
print_line("hi: "+rtos(m_upperLimit));
}*/
-// if (m_lowerLimit < m_upperLimit)
+ //if (m_lowerLimit < m_upperLimit)
if (m_useLimit && m_lowerLimit <= m_upperLimit)
{
-// if (hingeAngle <= m_lowerLimit*m_limitSoftness)
+ //if (hingeAngle <= m_lowerLimit*m_limitSoftness)
if (hingeAngle <= m_lowerLimit)
{
m_correction = (m_lowerLimit - hingeAngle);
m_limitSign = 1.0f;
m_solveLimit = true;
}
-// else if (hingeAngle >= m_upperLimit*m_limitSoftness)
+ //else if (hingeAngle >= m_upperLimit*m_limitSoftness)
else if (hingeAngle >= m_upperLimit)
{
m_correction = m_upperLimit - hingeAngle;
@@ -262,7 +262,7 @@ bool HingeJointSW::setup(float p_step) {
return true;
}
-void HingeJointSW::solve(float p_step) {
+void HingeJointSW::solve(real_t p_step) {
Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin);
Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin);
@@ -371,7 +371,7 @@ void HingeJointSW::solve(float p_step) {
real_t desiredMotorVel = m_motorTargetVelocity;
real_t motor_relvel = desiredMotorVel - projRelVel;
- real_t unclippedMotorImpulse = m_kHinge * motor_relvel;;
+ real_t unclippedMotorImpulse = m_kHinge * motor_relvel;
//todo: should clip against accumulated impulse
real_t clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse;
clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse;
@@ -418,7 +418,7 @@ real_t HingeJointSW::get_hinge_angle() {
}
-void HingeJointSW::set_param(PhysicsServer::HingeJointParam p_param, float p_value) {
+void HingeJointSW::set_param(PhysicsServer::HingeJointParam p_param, real_t p_value) {
switch (p_param) {
@@ -434,7 +434,7 @@ void HingeJointSW::set_param(PhysicsServer::HingeJointParam p_param, float p_val
}
}
-float HingeJointSW::get_param(PhysicsServer::HingeJointParam p_param) const{
+real_t HingeJointSW::get_param(PhysicsServer::HingeJointParam p_param) const{
switch (p_param) {
diff --git a/servers/physics/joints/hinge_joint_sw.h b/servers/physics/joints/hinge_joint_sw.h
index f87c2ac4c5..8469fd1ca0 100644
--- a/servers/physics/joints/hinge_joint_sw.h
+++ b/servers/physics/joints/hinge_joint_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -103,13 +103,13 @@ public:
virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_HINGE; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
real_t get_hinge_angle();
- void set_param(PhysicsServer::HingeJointParam p_param, float p_value);
- float get_param(PhysicsServer::HingeJointParam p_param) const;
+ void set_param(PhysicsServer::HingeJointParam p_param, real_t p_value);
+ real_t get_param(PhysicsServer::HingeJointParam p_param) const;
void set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_value);
bool get_flag(PhysicsServer::HingeJointFlag p_flag) const;
diff --git a/servers/physics/joints/jacobian_entry_sw.h b/servers/physics/joints/jacobian_entry_sw.h
index b7ab58f16b..cd85162ba5 100644
--- a/servers/physics/joints/jacobian_entry_sw.h
+++ b/servers/physics/joints/jacobian_entry_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -56,8 +56,8 @@ public:
JacobianEntrySW() {};
//constraint between two different rigidbodies
JacobianEntrySW(
- const Matrix3& world2A,
- const Matrix3& world2B,
+ const Basis& world2A,
+ const Basis& world2B,
const Vector3& rel_pos1,const Vector3& rel_pos2,
const Vector3& jointAxis,
const Vector3& inertiaInvA,
@@ -77,8 +77,8 @@ public:
//angular constraint between two different rigidbodies
JacobianEntrySW(const Vector3& jointAxis,
- const Matrix3& world2A,
- const Matrix3& world2B,
+ const Basis& world2A,
+ const Basis& world2B,
const Vector3& inertiaInvA,
const Vector3& inertiaInvB)
:m_linearJointAxis(Vector3(real_t(0.),real_t(0.),real_t(0.)))
@@ -110,7 +110,7 @@ public:
//constraint on one rigidbody
JacobianEntrySW(
- const Matrix3& world2A,
+ const Basis& world2A,
const Vector3& rel_pos1,const Vector3& rel_pos2,
const Vector3& jointAxis,
const Vector3& inertiaInvA,
diff --git a/servers/physics/joints/pin_joint_sw.cpp b/servers/physics/joints/pin_joint_sw.cpp
index 013d750b4f..b545ae630b 100644
--- a/servers/physics/joints/pin_joint_sw.cpp
+++ b/servers/physics/joints/pin_joint_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,7 +34,7 @@ See corresponding header file for licensing info.
#include "pin_joint_sw.h"
-bool PinJointSW::setup(float p_step) {
+bool PinJointSW::setup(real_t p_step) {
m_appliedImpulse = real_t(0.);
@@ -44,10 +44,10 @@ bool PinJointSW::setup(float p_step) {
{
normal[i] = 1;
memnew_placement(&m_jac[i],JacobianEntrySW(
- A->get_transform().basis.transposed(),
- B->get_transform().basis.transposed(),
- A->get_transform().xform(m_pivotInA) - A->get_transform().origin,
- B->get_transform().xform(m_pivotInB) - B->get_transform().origin,
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ A->get_transform().xform(m_pivotInA) - A->get_transform().origin - A->get_center_of_mass(),
+ B->get_transform().xform(m_pivotInB) - B->get_transform().origin - B->get_center_of_mass(),
normal,
A->get_inv_inertia(),
A->get_inv_mass(),
@@ -59,7 +59,7 @@ bool PinJointSW::setup(float p_step) {
return true;
}
-void PinJointSW::solve(float p_step){
+void PinJointSW::solve(real_t p_step){
Vector3 pivotAInW = A->get_transform().xform(m_pivotInA);
Vector3 pivotBInW = B->get_transform().xform(m_pivotInB);
@@ -68,8 +68,8 @@ void PinJointSW::solve(float p_step){
Vector3 normal(0,0,0);
-// Vector3 angvelA = A->get_transform().origin.getBasis().transpose() * A->getAngularVelocity();
-// Vector3 angvelB = B->get_transform().origin.getBasis().transpose() * B->getAngularVelocity();
+ //Vector3 angvelA = A->get_transform().origin.getBasis().transpose() * A->getAngularVelocity();
+ //Vector3 angvelB = B->get_transform().origin.getBasis().transpose() * B->getAngularVelocity();
for (int i=0;i<3;i++)
{
@@ -116,7 +116,7 @@ void PinJointSW::solve(float p_step){
}
}
-void PinJointSW::set_param(PhysicsServer::PinJointParam p_param,float p_value) {
+void PinJointSW::set_param(PhysicsServer::PinJointParam p_param,real_t p_value) {
switch(p_param) {
case PhysicsServer::PIN_JOINT_BIAS: m_tau=p_value; break;
@@ -125,7 +125,7 @@ void PinJointSW::set_param(PhysicsServer::PinJointParam p_param,float p_value) {
}
}
-float PinJointSW::get_param(PhysicsServer::PinJointParam p_param) const{
+real_t PinJointSW::get_param(PhysicsServer::PinJointParam p_param) const{
switch(p_param) {
case PhysicsServer::PIN_JOINT_BIAS: return m_tau;
diff --git a/servers/physics/joints/pin_joint_sw.h b/servers/physics/joints/pin_joint_sw.h
index 4ef134fe73..b72b21219d 100644
--- a/servers/physics/joints/pin_joint_sw.h
+++ b/servers/physics/joints/pin_joint_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -79,11 +79,11 @@ public:
virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_PIN; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
- void set_param(PhysicsServer::PinJointParam p_param,float p_value);
- float get_param(PhysicsServer::PinJointParam p_param) const;
+ void set_param(PhysicsServer::PinJointParam p_param,real_t p_value);
+ real_t get_param(PhysicsServer::PinJointParam p_param) const;
void set_pos_A(const Vector3& p_pos) { m_pivotInA=p_pos; }
void set_pos_B(const Vector3& p_pos) { m_pivotInB=p_pos; }
diff --git a/servers/physics/joints/slider_joint_sw.cpp b/servers/physics/joints/slider_joint_sw.cpp
index a9072e5de3..fc728ed0ba 100644
--- a/servers/physics/joints/slider_joint_sw.cpp
+++ b/servers/physics/joints/slider_joint_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -112,7 +112,7 @@ SliderJointSW::SliderJointSW(BodySW* rbA, BodySW* rbB, const Transform& frameInA
//-----------------------------------------------------------------------------
-bool SliderJointSW::setup(float p_step)
+bool SliderJointSW::setup(real_t p_step)
{
//calculate transforms
@@ -132,10 +132,10 @@ bool SliderJointSW::setup(float p_step)
{
normalWorld = m_calculatedTransformA.basis.get_axis(i);
memnew_placement(&m_jacLin[i], JacobianEntrySW(
- A->get_transform().basis.transposed(),
- B->get_transform().basis.transposed(),
- m_relPosA,
- m_relPosB,
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
+ m_relPosA - A->get_center_of_mass(),
+ m_relPosB - B->get_center_of_mass(),
normalWorld,
A->get_inv_inertia(),
A->get_inv_mass(),
@@ -152,8 +152,8 @@ bool SliderJointSW::setup(float p_step)
normalWorld = m_calculatedTransformA.basis.get_axis(i);
memnew_placement(&m_jacAng[i], JacobianEntrySW(
normalWorld,
- A->get_transform().basis.transposed(),
- B->get_transform().basis.transposed(),
+ A->get_principal_inertia_axes().transposed(),
+ B->get_principal_inertia_axes().transposed(),
A->get_inv_inertia(),
B->get_inv_inertia()
));
@@ -406,7 +406,7 @@ Vector3 SliderJointSW::getAncorInB(void)
return ancorInB;
} // SliderJointSW::getAncorInB();
-void SliderJointSW::set_param(PhysicsServer::SliderJointParam p_param, float p_value) {
+void SliderJointSW::set_param(PhysicsServer::SliderJointParam p_param, real_t p_value) {
switch(p_param) {
case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: m_upperLinLimit=p_value; break;
@@ -437,7 +437,7 @@ void SliderJointSW::set_param(PhysicsServer::SliderJointParam p_param, float p_v
}
-float SliderJointSW::get_param(PhysicsServer::SliderJointParam p_param) const {
+real_t SliderJointSW::get_param(PhysicsServer::SliderJointParam p_param) const {
switch(p_param) {
case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: return m_upperLinLimit;
diff --git a/servers/physics/joints/slider_joint_sw.h b/servers/physics/joints/slider_joint_sw.h
index 9ee6c83800..d01038df59 100644
--- a/servers/physics/joints/slider_joint_sw.h
+++ b/servers/physics/joints/slider_joint_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -237,11 +237,11 @@ public:
Vector3 getAncorInA(void);
Vector3 getAncorInB(void);
- void set_param(PhysicsServer::SliderJointParam p_param, float p_value);
- float get_param(PhysicsServer::SliderJointParam p_param) const;
+ void set_param(PhysicsServer::SliderJointParam p_param, real_t p_value);
+ real_t get_param(PhysicsServer::SliderJointParam p_param) const;
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_SLIDER; }
diff --git a/servers/physics/joints_sw.h b/servers/physics/joints_sw.h
index b54c655ea1..c87c86b599 100644
--- a/servers/physics/joints_sw.h
+++ b/servers/physics/joints_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp
index 6c098a6df2..67e3b27852 100644
--- a/servers/physics/physics_server_sw.cpp
+++ b/servers/physics/physics_server_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -727,7 +727,7 @@ uint32_t PhysicsServerSW::body_get_user_flags(RID p_body, uint32_t p_flags) cons
return 0;
};
-void PhysicsServerSW::body_set_param(RID p_body, BodyParameter p_param, float p_value) {
+void PhysicsServerSW::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -735,7 +735,7 @@ void PhysicsServerSW::body_set_param(RID p_body, BodyParameter p_param, float p_
body->set_param(p_param,p_value);
};
-float PhysicsServerSW::body_get_param(RID p_body, BodyParameter p_param) const {
+real_t PhysicsServerSW::body_get_param(RID p_body, BodyParameter p_param) const {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,0);
@@ -805,6 +805,15 @@ void PhysicsServerSW::body_apply_impulse(RID p_body, const Vector3& p_pos, const
body->wakeup();
};
+void PhysicsServerSW::body_apply_torque_impulse(RID p_body, const Vector3& p_impulse) {
+
+ BodySW *body = body_owner.get(p_body);
+ ERR_FAIL_COND(!body);
+
+ body->apply_torque_impulse(p_impulse);
+ body->wakeup();
+};
+
void PhysicsServerSW::body_set_axis_velocity(RID p_body, const Vector3& p_axis_velocity) {
BodySW *body = body_owner.get(p_body);
@@ -870,14 +879,14 @@ void PhysicsServerSW::body_get_collision_exceptions(RID p_body, List<RID> *p_exc
};
-void PhysicsServerSW::body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold) {
+void PhysicsServerSW::body_set_contacts_reported_depth_treshold(RID p_body, real_t p_treshold) {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
};
-float PhysicsServerSW::body_get_contacts_reported_depth_treshold(RID p_body) const {
+real_t PhysicsServerSW::body_get_contacts_reported_depth_treshold(RID p_body) const {
BodySW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,0);
@@ -962,7 +971,7 @@ RID PhysicsServerSW::joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID
return rid;
}
-void PhysicsServerSW::pin_joint_set_param(RID p_joint,PinJointParam p_param, float p_value){
+void PhysicsServerSW::pin_joint_set_param(RID p_joint,PinJointParam p_param, real_t p_value){
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND(!joint);
@@ -971,7 +980,7 @@ void PhysicsServerSW::pin_joint_set_param(RID p_joint,PinJointParam p_param, flo
pin_joint->set_param(p_param,p_value);
}
-float PhysicsServerSW::pin_joint_get_param(RID p_joint,PinJointParam p_param) const{
+real_t PhysicsServerSW::pin_joint_get_param(RID p_joint,PinJointParam p_param) const{
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND_V(!joint,0);
@@ -1065,7 +1074,7 @@ RID PhysicsServerSW::joint_create_hinge_simple(RID p_body_A,const Vector3& p_piv
}
-void PhysicsServerSW::hinge_joint_set_param(RID p_joint,HingeJointParam p_param, float p_value){
+void PhysicsServerSW::hinge_joint_set_param(RID p_joint,HingeJointParam p_param, real_t p_value){
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND(!joint);
@@ -1074,7 +1083,7 @@ void PhysicsServerSW::hinge_joint_set_param(RID p_joint,HingeJointParam p_param,
hinge_joint->set_param(p_param,p_value);
}
-float PhysicsServerSW::hinge_joint_get_param(RID p_joint,HingeJointParam p_param) const{
+real_t PhysicsServerSW::hinge_joint_get_param(RID p_joint,HingeJointParam p_param) const{
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND_V(!joint,0);
@@ -1145,7 +1154,7 @@ RID PhysicsServerSW::joint_create_slider(RID p_body_A,const Transform& p_local_f
return rid;
}
-void PhysicsServerSW::slider_joint_set_param(RID p_joint,SliderJointParam p_param, float p_value){
+void PhysicsServerSW::slider_joint_set_param(RID p_joint,SliderJointParam p_param, real_t p_value){
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND(!joint);
@@ -1153,7 +1162,7 @@ void PhysicsServerSW::slider_joint_set_param(RID p_joint,SliderJointParam p_para
SliderJointSW *slider_joint = static_cast<SliderJointSW*>(joint);
slider_joint->set_param(p_param,p_value);
}
-float PhysicsServerSW::slider_joint_get_param(RID p_joint,SliderJointParam p_param) const{
+real_t PhysicsServerSW::slider_joint_get_param(RID p_joint,SliderJointParam p_param) const{
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND_V(!joint,0);
@@ -1184,7 +1193,7 @@ RID PhysicsServerSW::joint_create_cone_twist(RID p_body_A,const Transform& p_loc
return rid;
}
-void PhysicsServerSW::cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam p_param, float p_value) {
+void PhysicsServerSW::cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam p_param, real_t p_value) {
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND(!joint);
@@ -1192,7 +1201,7 @@ void PhysicsServerSW::cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam
ConeTwistJointSW *cone_twist_joint = static_cast<ConeTwistJointSW*>(joint);
cone_twist_joint->set_param(p_param,p_value);
}
-float PhysicsServerSW::cone_twist_joint_get_param(RID p_joint,ConeTwistJointParam p_param) const {
+real_t PhysicsServerSW::cone_twist_joint_get_param(RID p_joint,ConeTwistJointParam p_param) const {
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND_V(!joint,0);
@@ -1223,7 +1232,7 @@ RID PhysicsServerSW::joint_create_generic_6dof(RID p_body_A,const Transform& p_l
return rid;
}
-void PhysicsServerSW::generic_6dof_joint_set_param(RID p_joint,Vector3::Axis p_axis,G6DOFJointAxisParam p_param, float p_value){
+void PhysicsServerSW::generic_6dof_joint_set_param(RID p_joint,Vector3::Axis p_axis,G6DOFJointAxisParam p_param, real_t p_value){
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND(!joint);
@@ -1231,7 +1240,7 @@ void PhysicsServerSW::generic_6dof_joint_set_param(RID p_joint,Vector3::Axis p_a
Generic6DOFJointSW *generic_6dof_joint = static_cast<Generic6DOFJointSW*>(joint);
generic_6dof_joint->set_param(p_axis,p_param,p_value);
}
-float PhysicsServerSW::generic_6dof_joint_get_param(RID p_joint,Vector3::Axis p_axis,G6DOFJointAxisParam p_param){
+real_t PhysicsServerSW::generic_6dof_joint_get_param(RID p_joint,Vector3::Axis p_axis,G6DOFJointAxisParam p_param){
JointSW *joint = joint_owner.get(p_joint);
ERR_FAIL_COND_V(!joint,0);
@@ -1386,11 +1395,13 @@ void PhysicsServerSW::free(RID p_rid) {
BodySW *body = body_owner.get(p_rid);
-// if (body->get_state_query())
-// _clear_query(body->get_state_query());
+ /*
+ if (body->get_state_query())
+ _clear_query(body->get_state_query());
-// if (body->get_direct_state_query())
-// _clear_query(body->get_direct_state_query());
+ if (body->get_direct_state_query())
+ _clear_query(body->get_direct_state_query());
+ */
body->set_space(NULL);
@@ -1413,8 +1424,10 @@ void PhysicsServerSW::free(RID p_rid) {
AreaSW *area = area_owner.get(p_rid);
-// if (area->get_monitor_query())
-// _clear_query(area->get_monitor_query());
+ /*
+ if (area->get_monitor_query())
+ _clear_query(area->get_monitor_query());
+ */
area->set_space(NULL);
@@ -1475,7 +1488,7 @@ void PhysicsServerSW::init() {
};
-void PhysicsServerSW::step(float p_step) {
+void PhysicsServerSW::step(real_t p_step) {
if (!active)
@@ -1598,11 +1611,11 @@ void PhysicsServerSW::_shape_col_cbk(const Vector3& p_point_A,const Vector3& p_p
if (cbk->amount == cbk->max) {
//find least deep
- float min_depth=1e20;
+ real_t min_depth=1e20;
int min_depth_idx=0;
for(int i=0;i<cbk->amount;i++) {
- float d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]);
+ real_t d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]);
if (d<min_depth) {
min_depth=d;
min_depth_idx=i;
@@ -1610,7 +1623,7 @@ void PhysicsServerSW::_shape_col_cbk(const Vector3& p_point_A,const Vector3& p_p
}
- float d = p_point_A.distance_squared_to(p_point_B);
+ real_t d = p_point_A.distance_squared_to(p_point_B);
if (d<min_depth)
return;
cbk->ptr[min_depth_idx*2+0]=p_point_A;
diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h
index 59eeeb42a7..6e20474350 100644
--- a/servers/physics/physics_server_sw.h
+++ b/servers/physics/physics_server_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -39,7 +39,7 @@
class PhysicsServerSW : public PhysicsServer {
- OBJ_TYPE( PhysicsServerSW, PhysicsServer );
+ GDCLASS( PhysicsServerSW, PhysicsServer );
friend class PhysicsDirectSpaceStateSW;
bool active;
@@ -62,7 +62,7 @@ friend class PhysicsDirectSpaceStateSW;
mutable RID_Owner<BodySW> body_owner;
mutable RID_Owner<JointSW> joint_owner;
-// void _clear_query(QuerySW *p_query);
+ //void _clear_query(QuerySW *p_query);
public:
struct CollCbkData {
@@ -180,8 +180,8 @@ public:
virtual void body_set_user_flags(RID p_body, uint32_t p_flags);
virtual uint32_t body_get_user_flags(RID p_body, uint32_t p_flags) const;
- virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value);
- virtual float body_get_param(RID p_body, BodyParameter p_param) const;
+ virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value);
+ virtual real_t body_get_param(RID p_body, BodyParameter p_param) const;
virtual void body_set_state(RID p_body, BodyState p_state, const Variant& p_variant);
virtual Variant body_get_state(RID p_body, BodyState p_state) const;
@@ -193,6 +193,7 @@ public:
virtual Vector3 body_get_applied_torque(RID p_body) const;
virtual void body_apply_impulse(RID p_body, const Vector3& p_pos, const Vector3& p_impulse);
+ virtual void body_apply_torque_impulse(RID p_body, const Vector3& p_impulse);
virtual void body_set_axis_velocity(RID p_body, const Vector3& p_axis_velocity);
virtual void body_set_axis_lock(RID p_body,BodyAxisLock p_lock);
@@ -202,8 +203,8 @@ public:
virtual void body_remove_collision_exception(RID p_body, RID p_body_b);
virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions);
- virtual void body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold);
- virtual float body_get_contacts_reported_depth_treshold(RID p_body) const;
+ virtual void body_set_contacts_reported_depth_treshold(RID p_body, real_t p_treshold);
+ virtual real_t body_get_contacts_reported_depth_treshold(RID p_body) const;
virtual void body_set_omit_force_integration(RID p_body,bool p_omit);
virtual bool body_is_omitting_force_integration(RID p_body) const;
@@ -220,8 +221,8 @@ public:
virtual RID joint_create_pin(RID p_body_A,const Vector3& p_local_A,RID p_body_B,const Vector3& p_local_B);
- virtual void pin_joint_set_param(RID p_joint,PinJointParam p_param, float p_value);
- virtual float pin_joint_get_param(RID p_joint,PinJointParam p_param) const;
+ virtual void pin_joint_set_param(RID p_joint,PinJointParam p_param, real_t p_value);
+ virtual real_t pin_joint_get_param(RID p_joint,PinJointParam p_param) const;
virtual void pin_joint_set_local_A(RID p_joint, const Vector3& p_A);
virtual Vector3 pin_joint_get_local_A(RID p_joint) const;
@@ -232,8 +233,8 @@ public:
virtual RID joint_create_hinge(RID p_body_A,const Transform& p_frame_A,RID p_body_B,const Transform& p_frame_B);
virtual RID joint_create_hinge_simple(RID p_body_A,const Vector3& p_pivot_A,const Vector3& p_axis_A,RID p_body_B,const Vector3& p_pivot_B,const Vector3& p_axis_B);
- virtual void hinge_joint_set_param(RID p_joint,HingeJointParam p_param, float p_value);
- virtual float hinge_joint_get_param(RID p_joint,HingeJointParam p_param) const;
+ virtual void hinge_joint_set_param(RID p_joint,HingeJointParam p_param, real_t p_value);
+ virtual real_t hinge_joint_get_param(RID p_joint,HingeJointParam p_param) const;
virtual void hinge_joint_set_flag(RID p_joint,HingeJointFlag p_flag, bool p_value);
virtual bool hinge_joint_get_flag(RID p_joint,HingeJointFlag p_flag) const;
@@ -241,18 +242,18 @@ public:
virtual RID joint_create_slider(RID p_body_A,const Transform& p_local_frame_A,RID p_body_B,const Transform& p_local_frame_B); //reference frame is A
- virtual void slider_joint_set_param(RID p_joint,SliderJointParam p_param, float p_value);
- virtual float slider_joint_get_param(RID p_joint,SliderJointParam p_param) const;
+ virtual void slider_joint_set_param(RID p_joint,SliderJointParam p_param, real_t p_value);
+ virtual real_t slider_joint_get_param(RID p_joint,SliderJointParam p_param) const;
virtual RID joint_create_cone_twist(RID p_body_A,const Transform& p_local_frame_A,RID p_body_B,const Transform& p_local_frame_B); //reference frame is A
- virtual void cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam p_param, float p_value);
- virtual float cone_twist_joint_get_param(RID p_joint,ConeTwistJointParam p_param) const;
+ virtual void cone_twist_joint_set_param(RID p_joint,ConeTwistJointParam p_param, real_t p_value);
+ virtual real_t cone_twist_joint_get_param(RID p_joint,ConeTwistJointParam p_param) const;
virtual RID joint_create_generic_6dof(RID p_body_A,const Transform& p_local_frame_A,RID p_body_B,const Transform& p_local_frame_B); //reference frame is A
- virtual void generic_6dof_joint_set_param(RID p_joint,Vector3::Axis,G6DOFJointAxisParam p_param, float p_value);
- virtual float generic_6dof_joint_get_param(RID p_joint,Vector3::Axis,G6DOFJointAxisParam p_param);
+ virtual void generic_6dof_joint_set_param(RID p_joint,Vector3::Axis,G6DOFJointAxisParam p_param, real_t p_value);
+ virtual real_t generic_6dof_joint_get_param(RID p_joint,Vector3::Axis,G6DOFJointAxisParam p_param);
virtual void generic_6dof_joint_set_flag(RID p_joint,Vector3::Axis,G6DOFJointAxisFlag p_flag, bool p_enable);
virtual bool generic_6dof_joint_get_flag(RID p_joint,Vector3::Axis,G6DOFJointAxisFlag p_flag);
@@ -280,7 +281,7 @@ public:
virtual void set_active(bool p_active);
virtual void init();
- virtual void step(float p_step);
+ virtual void step(real_t p_step);
virtual void sync();
virtual void flush_queries();
virtual void finish();
diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp
index 1d4914c945..10500a306f 100644
--- a/servers/physics/shape_sw.cpp
+++ b/servers/physics/shape_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,7 +35,7 @@
#define _FACE_IS_VALID_SUPPORT_TRESHOLD 0.9998
-void ShapeSW::configure(const AABB& p_aabb) {
+void ShapeSW::configure(const Rect3& p_aabb) {
aabb=p_aabb;
configured=true;
for (Map<ShapeOwnerSW*,int>::Element *E=owners.front();E;E=E->next()) {
@@ -125,7 +125,7 @@ bool PlaneShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end
return inters;
}
-Vector3 PlaneShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 PlaneShapeSW::get_moment_of_inertia(real_t p_mass) const {
return Vector3(); //wtf
}
@@ -133,7 +133,7 @@ Vector3 PlaneShapeSW::get_moment_of_inertia(float p_mass) const {
void PlaneShapeSW::_setup(const Plane& p_plane) {
plane=p_plane;
- configure(AABB(Vector3(-1e4,-1e4,-1e4),Vector3(1e4*2,1e4*2,1e4*2)));
+ configure(Rect3(Vector3(-1e4,-1e4,-1e4),Vector3(1e4*2,1e4*2,1e4*2)));
}
void PlaneShapeSW::set_data(const Variant& p_data) {
@@ -154,7 +154,7 @@ PlaneShapeSW::PlaneShapeSW() {
//
-float RayShapeSW::get_length() const {
+real_t RayShapeSW::get_length() const {
return length;
}
@@ -196,15 +196,15 @@ bool RayShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end,V
return false; //simply not possible
}
-Vector3 RayShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 RayShapeSW::get_moment_of_inertia(real_t p_mass) const {
return Vector3();
}
-void RayShapeSW::_setup(float p_length) {
+void RayShapeSW::_setup(real_t p_length) {
length=p_length;
- configure(AABB(Vector3(0,0,0),Vector3(0.1,0.1,length)));
+ configure(Rect3(Vector3(0,0,0),Vector3(0.1,0.1,length)));
}
void RayShapeSW::set_data(const Variant& p_data) {
@@ -234,11 +234,11 @@ real_t SphereShapeSW::get_radius() const {
void SphereShapeSW::project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const {
- float d = p_normal.dot( p_transform.origin );
+ real_t d = p_normal.dot( p_transform.origin );
// figure out scale at point
Vector3 local_normal = p_transform.basis.xform_inv(p_normal);
- float scale = local_normal.length();
+ real_t scale = local_normal.length();
r_min = d - (radius) * scale;
r_max = d + (radius) * scale;
@@ -261,9 +261,9 @@ bool SphereShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_en
return Geometry::segment_intersects_sphere(p_begin,p_end,Vector3(),radius,&r_result,&r_normal);
}
-Vector3 SphereShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 SphereShapeSW::get_moment_of_inertia(real_t p_mass) const {
- float s = 0.4 * p_mass * radius * radius;
+ real_t s = 0.4 * p_mass * radius * radius;
return Vector3(s,s,s);
}
@@ -271,7 +271,7 @@ void SphereShapeSW::_setup(real_t p_radius) {
radius=p_radius;
- configure(AABB( Vector3(-radius,-radius,-radius), Vector3(radius*2.0,radius*2.0,radius*2.0)));
+ configure(Rect3( Vector3(-radius,-radius,-radius), Vector3(radius*2.0,radius*2.0,radius*2.0)));
}
@@ -299,8 +299,8 @@ void BoxShapeSW::project_range(const Vector3& p_normal, const Transform& p_trans
// no matter the angle, the box is mirrored anyway
Vector3 local_normal=p_transform.basis.xform_inv(p_normal);
- float length = local_normal.abs().dot(half_extents);
- float distance = p_normal.dot( p_transform.origin );
+ real_t length = local_normal.abs().dot(half_extents);
+ real_t distance = p_normal.dot( p_transform.origin );
r_min = distance - length;
r_max = distance + length;
@@ -329,7 +329,7 @@ void BoxShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_suppo
Vector3 axis;
axis[i]=1.0;
- float dot = p_normal.dot( axis );
+ real_t dot = p_normal.dot( axis );
if ( Math::abs( dot ) > _FACE_IS_VALID_SUPPORT_TRESHOLD ) {
//Vector3 axis_b;
@@ -343,7 +343,7 @@ void BoxShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_suppo
int i_n=next[i];
int i_n2=next2[i];
- static const float sign[4][2]={
+ static const real_t sign[4][2]={
{-1.0, 1.0},
{ 1.0, 1.0},
@@ -412,17 +412,17 @@ void BoxShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_suppo
bool BoxShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const {
- AABB aabb(-half_extents,half_extents*2.0);
+ Rect3 aabb(-half_extents,half_extents*2.0);
return aabb.intersects_segment(p_begin,p_end,&r_result,&r_normal);
}
-Vector3 BoxShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 BoxShapeSW::get_moment_of_inertia(real_t p_mass) const {
- float lx=half_extents.x;
- float ly=half_extents.y;
- float lz=half_extents.z;
+ real_t lx=half_extents.x;
+ real_t ly=half_extents.y;
+ real_t lz=half_extents.z;
return Vector3( (p_mass/3.0) * (ly*ly + lz*lz), (p_mass/3.0) * (lx*lx + lz*lz), (p_mass/3.0) * (lx*lx + ly*ly) );
@@ -432,7 +432,7 @@ void BoxShapeSW::_setup(const Vector3& p_half_extents) {
half_extents=p_half_extents.abs();
- configure(AABB(-half_extents,half_extents*2));
+ configure(Rect3(-half_extents,half_extents*2));
}
@@ -460,7 +460,7 @@ BoxShapeSW::BoxShapeSW() {
void CapsuleShapeSW::project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const {
Vector3 n=p_transform.basis.xform_inv(p_normal).normalized();
- float h = (n.z > 0) ? height : -height;
+ real_t h = (n.z > 0) ? height : -height;
n *= radius;
n.z += h * 0.5;
@@ -471,8 +471,8 @@ void CapsuleShapeSW::project_range(const Vector3& p_normal, const Transform& p_t
n = p_transform.basis.xform(n);
- float distance = p_normal.dot( p_transform.origin );
- float length = Math::abs(p_normal.dot(n));
+ real_t distance = p_normal.dot( p_transform.origin );
+ real_t length = Math::abs(p_normal.dot(n));
r_min = distance - length;
r_max = distance + length;
@@ -484,7 +484,7 @@ Vector3 CapsuleShapeSW::get_support(const Vector3& p_normal) const {
Vector3 n=p_normal;
- float h = (n.z > 0) ? height : -height;
+ real_t h = (n.z > 0) ? height : -height;
n*=radius;
n.z += h*0.5;
@@ -496,7 +496,7 @@ void CapsuleShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_s
Vector3 n=p_normal;
- float d = n.z;
+ real_t d = n.z;
if (Math::abs( d )<_EDGE_IS_VALID_SUPPORT_TRESHOLD ) {
@@ -513,7 +513,7 @@ void CapsuleShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_s
} else {
- float h = (d > 0) ? height : -height;
+ real_t h = (d > 0) ? height : -height;
n*=radius;
n.z += h*0.5;
@@ -528,7 +528,7 @@ void CapsuleShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_s
bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const {
Vector3 norm=(p_end-p_begin).normalized();
- float min_d=1e20;
+ real_t min_d=1e20;
Vector3 res,n;
@@ -542,7 +542,7 @@ bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_e
collided = Geometry::segment_intersects_cylinder(p_begin,p_end,height,radius,&auxres,&auxn);
if (collided) {
- float d=norm.dot(auxres);
+ real_t d=norm.dot(auxres);
if (d<min_d) {
min_d=d;
res=auxres;
@@ -554,7 +554,7 @@ bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_e
collided = Geometry::segment_intersects_sphere(p_begin,p_end,Vector3(0,0,height*0.5),radius,&auxres,&auxn);
if (collided) {
- float d=norm.dot(auxres);
+ real_t d=norm.dot(auxres);
if (d<min_d) {
min_d=d;
res=auxres;
@@ -566,7 +566,7 @@ bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_e
collided = Geometry::segment_intersects_sphere(p_begin,p_end,Vector3(0,0,height*-0.5),radius,&auxres,&auxn);
if (collided) {
- float d=norm.dot(auxres);
+ real_t d=norm.dot(auxres);
if (d<min_d) {
min_d=d;
@@ -584,7 +584,7 @@ bool CapsuleShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_e
return collision;
}
-Vector3 CapsuleShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 CapsuleShapeSW::get_moment_of_inertia(real_t p_mass) const {
// use crappy AABB approximation
Vector3 extents=get_aabb().size*0.5;
@@ -604,7 +604,7 @@ void CapsuleShapeSW::_setup(real_t p_height,real_t p_radius) {
height=p_height;
radius=p_radius;
- configure(AABB(Vector3(-radius,-radius,-height*0.5-radius),Vector3(radius*2,radius*2,height+radius*2.0)));
+ configure(Rect3(Vector3(-radius,-radius,-height*0.5-radius),Vector3(radius*2,radius*2,height+radius*2.0)));
}
@@ -647,7 +647,7 @@ void ConvexPolygonShapeSW::project_range(const Vector3& p_normal, const Transfor
for (int i=0;i<vertex_count;i++) {
- float d=p_normal.dot( p_transform.xform( vrts[i] ) );
+ real_t d=p_normal.dot( p_transform.xform( vrts[i] ) );
if (i==0 || d > r_max)
r_max=d;
@@ -661,7 +661,7 @@ Vector3 ConvexPolygonShapeSW::get_support(const Vector3& p_normal) const {
Vector3 n=p_normal;
int vert_support_idx=-1;
- float support_max;
+ real_t support_max;
int vertex_count=mesh.vertices.size();
if (vertex_count==0)
@@ -671,7 +671,7 @@ Vector3 ConvexPolygonShapeSW::get_support(const Vector3& p_normal) const {
for (int i=0;i<vertex_count;i++) {
- float d=n.dot(vrts[i]);
+ real_t d=n.dot(vrts[i]);
if (i==0 || d > support_max) {
support_max=d;
@@ -702,7 +702,7 @@ void ConvexPolygonShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector
for (int i=0;i<vc;i++) {
- float d=p_normal.dot(vertices[i]);
+ real_t d=p_normal.dot(vertices[i]);
if (i==0 || d > max) {
max=d;
@@ -742,7 +742,7 @@ void ConvexPolygonShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector
for(int i=0;i<ec;i++) {
- float dot=(vertices[edges[i].a]-vertices[edges[i].b]).normalized().dot(p_normal);
+ real_t dot=(vertices[edges[i].a]-vertices[edges[i].b]).normalized().dot(p_normal);
dot=ABS(dot);
if (dot < _EDGE_IS_VALID_SUPPORT_TRESHOLD && (edges[i].a==vtx || edges[i].b==vtx)) {
@@ -768,7 +768,7 @@ bool ConvexPolygonShapeSW::intersect_segment(const Vector3& p_begin,const Vector
const Vector3 *vertices = mesh.vertices.ptr();
Vector3 n = p_end-p_begin;
- float min = 1e20;
+ real_t min = 1e20;
bool col=false;
for(int i=0;i<fc;i++) {
@@ -784,7 +784,7 @@ bool ConvexPolygonShapeSW::intersect_segment(const Vector3& p_begin,const Vector
Face3 f(vertices[ind[0]],vertices[ind[j]],vertices[ind[j+1]]);
Vector3 result;
if (f.intersects_segment(p_begin,p_end,&result)) {
- float d = n.dot(result);
+ real_t d = n.dot(result);
if (d<min) {
min=d;
r_result=result;
@@ -802,7 +802,7 @@ bool ConvexPolygonShapeSW::intersect_segment(const Vector3& p_begin,const Vector
}
-Vector3 ConvexPolygonShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 ConvexPolygonShapeSW::get_moment_of_inertia(real_t p_mass) const {
// use crappy AABB approximation
Vector3 extents=get_aabb().size*0.5;
@@ -818,7 +818,7 @@ Vector3 ConvexPolygonShapeSW::get_moment_of_inertia(float p_mass) const {
void ConvexPolygonShapeSW::_setup(const Vector<Vector3>& p_vertices) {
Error err = QuickHull::build(p_vertices,mesh);
- AABB _aabb;
+ Rect3 _aabb;
for(int i=0;i<mesh.vertices.size();i++) {
@@ -859,7 +859,7 @@ void FaceShapeSW::project_range(const Vector3& p_normal, const Transform& p_tran
for (int i=0;i<3;i++) {
Vector3 v=p_transform.xform(vertex[i]);
- float d=p_normal.dot(v);
+ real_t d=p_normal.dot(v);
if (i==0 || d > r_max)
r_max=d;
@@ -873,11 +873,11 @@ Vector3 FaceShapeSW::get_support(const Vector3& p_normal) const {
int vert_support_idx=-1;
- float support_max;
+ real_t support_max;
for (int i=0;i<3;i++) {
- float d=p_normal.dot(vertex[i]);
+ real_t d=p_normal.dot(vertex[i]);
if (i==0 || d > support_max) {
support_max=d;
@@ -907,11 +907,11 @@ void FaceShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supp
/** FIND SUPPORT VERTEX **/
int vert_support_idx=-1;
- float support_max;
+ real_t support_max;
for (int i=0;i<3;i++) {
- float d=n.dot(vertex[i]);
+ real_t d=n.dot(vertex[i]);
if (i==0 || d > support_max) {
support_max=d;
@@ -928,7 +928,7 @@ void FaceShapeSW::get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supp
continue;
// check if edge is valid as a support
- float dot=(vertex[i]-vertex[nx]).normalized().dot(n);
+ real_t dot=(vertex[i]-vertex[nx]).normalized().dot(n);
dot=ABS(dot);
if (dot < _EDGE_IS_VALID_SUPPORT_TRESHOLD) {
@@ -957,7 +957,7 @@ bool FaceShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p_end,
return c;
}
-Vector3 FaceShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 FaceShapeSW::get_moment_of_inertia(real_t p_mass) const {
return Vector3(); // Sorry, but i don't think anyone cares, FaceShape!
@@ -965,16 +965,16 @@ Vector3 FaceShapeSW::get_moment_of_inertia(float p_mass) const {
FaceShapeSW::FaceShapeSW() {
- configure(AABB());
+ configure(Rect3());
}
-DVector<Vector3> ConcavePolygonShapeSW::get_faces() const {
+PoolVector<Vector3> ConcavePolygonShapeSW::get_faces() const {
- DVector<Vector3> rfaces;
+ PoolVector<Vector3> rfaces;
rfaces.resize(faces.size()*3);
for(int i=0;i<faces.size();i++) {
@@ -998,12 +998,12 @@ void ConcavePolygonShapeSW::project_range(const Vector3& p_normal, const Transfo
r_max=0;
return;
}
- DVector<Vector3>::Read r=vertices.read();
+ PoolVector<Vector3>::Read r=vertices.read();
const Vector3 *vptr=r.ptr();
for (int i=0;i<count;i++) {
- float d=p_normal.dot( p_transform.xform( vptr[i] ) );
+ real_t d=p_normal.dot( p_transform.xform( vptr[i] ) );
if (i==0 || d > r_max)
r_max=d;
@@ -1020,17 +1020,17 @@ Vector3 ConcavePolygonShapeSW::get_support(const Vector3& p_normal) const {
if (count==0)
return Vector3();
- DVector<Vector3>::Read r=vertices.read();
+ PoolVector<Vector3>::Read r=vertices.read();
const Vector3 *vptr=r.ptr();
Vector3 n=p_normal;
int vert_support_idx=-1;
- float support_max;
+ real_t support_max;
for (int i=0;i<count;i++) {
- float d=n.dot(vptr[i]);
+ real_t d=n.dot(vptr[i]);
if (i==0 || d > support_max) {
support_max=d;
@@ -1048,8 +1048,10 @@ void ConcavePolygonShapeSW::_cull_segment(int p_idx,_SegmentCullParams *p_params
const BVH *bvh=&p_params->bvh[p_idx];
- //if (p_params->dir.dot(bvh->aabb.get_support(-p_params->dir))>p_params->min_d)
- // return; //test against whole AABB, which isn't very costly
+ /*
+ if (p_params->dir.dot(bvh->aabb.get_support(-p_params->dir))>p_params->min_d)
+ return; //test against whole AABB, which isn't very costly
+ */
//printf("addr: %p\n",bvh);
@@ -1078,7 +1080,7 @@ void ConcavePolygonShapeSW::_cull_segment(int p_idx,_SegmentCullParams *p_params
&res)) {
- float d=p_params->dir.dot(res) - p_params->dir.dot(p_params->from);
+ real_t d=p_params->dir.dot(res) - p_params->dir.dot(p_params->from);
//TODO, seems segmen/triangle intersection is broken :(
if (d>0 && d<p_params->min_d) {
@@ -1111,9 +1113,9 @@ bool ConcavePolygonShapeSW::intersect_segment(const Vector3& p_begin,const Vecto
return false;
// unlock data
- DVector<Face>::Read fr=faces.read();
- DVector<Vector3>::Read vr=vertices.read();
- DVector<BVH>::Read br=bvh.read();
+ PoolVector<Face>::Read fr=faces.read();
+ PoolVector<Vector3>::Read vr=vertices.read();
+ PoolVector<BVH>::Read br=bvh.read();
_SegmentCullParams params;
@@ -1175,18 +1177,18 @@ void ConcavePolygonShapeSW::_cull(int p_idx,_CullParams *p_params) const {
}
}
-void ConcavePolygonShapeSW::cull(const AABB& p_local_aabb,Callback p_callback,void* p_userdata) const {
+void ConcavePolygonShapeSW::cull(const Rect3& p_local_aabb,Callback p_callback,void* p_userdata) const {
// make matrix local to concave
if (faces.size()==0)
return;
- AABB local_aabb=p_local_aabb;
+ Rect3 local_aabb=p_local_aabb;
// unlock data
- DVector<Face>::Read fr=faces.read();
- DVector<Vector3>::Read vr=vertices.read();
- DVector<BVH>::Read br=bvh.read();
+ PoolVector<Face>::Read fr=faces.read();
+ PoolVector<Vector3>::Read vr=vertices.read();
+ PoolVector<BVH>::Read br=bvh.read();
FaceShapeSW face; // use this to send in the callback
@@ -1204,7 +1206,7 @@ void ConcavePolygonShapeSW::cull(const AABB& p_local_aabb,Callback p_callback,vo
}
-Vector3 ConcavePolygonShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 ConcavePolygonShapeSW::get_moment_of_inertia(real_t p_mass) const {
// use crappy AABB approximation
Vector3 extents=get_aabb().size*0.5;
@@ -1219,7 +1221,7 @@ Vector3 ConcavePolygonShapeSW::get_moment_of_inertia(float p_mass) const {
struct _VolumeSW_BVH_Element {
- AABB aabb;
+ Rect3 aabb;
Vector3 center;
int face_index;
};
@@ -1251,7 +1253,7 @@ struct _VolumeSW_BVH_CompareZ {
struct _VolumeSW_BVH {
- AABB aabb;
+ Rect3 aabb;
_VolumeSW_BVH *left;
_VolumeSW_BVH *right;
@@ -1276,7 +1278,7 @@ _VolumeSW_BVH* _volume_sw_build_bvh(_VolumeSW_BVH_Element *p_elements,int p_size
bvh->face_index=-1;
}
- AABB aabb;
+ Rect3 aabb;
for(int i=0;i<p_size;i++) {
if (i==0)
@@ -1309,7 +1311,7 @@ _VolumeSW_BVH* _volume_sw_build_bvh(_VolumeSW_BVH_Element *p_elements,int p_size
bvh->left=_volume_sw_build_bvh(p_elements,split,count);
bvh->right=_volume_sw_build_bvh(&p_elements[split],p_size-split,count);
-// printf("branch at %p - %i: %i\n",bvh,count,bvh->face_index);
+ //printf("branch at %p - %i: %i\n",bvh,count,bvh->face_index);
count++;
return bvh;
}
@@ -1322,7 +1324,7 @@ void ConcavePolygonShapeSW::_fill_bvh(_VolumeSW_BVH* p_bvh_tree,BVH* p_bvh_array
p_bvh_array[idx].aabb=p_bvh_tree->aabb;
p_bvh_array[idx].face_index=p_bvh_tree->face_index;
-// printf("%p - %i: %i(%p) -- %p:%p\n",%p_bvh_array[idx],p_idx,p_bvh_array[i]->face_index,&p_bvh_tree->face_index,p_bvh_tree->left,p_bvh_tree->right);
+ //printf("%p - %i: %i(%p) -- %p:%p\n",%p_bvh_array[idx],p_idx,p_bvh_array[i]->face_index,&p_bvh_tree->face_index,p_bvh_tree->left,p_bvh_tree->right);
if (p_bvh_tree->left) {
@@ -1347,17 +1349,17 @@ void ConcavePolygonShapeSW::_fill_bvh(_VolumeSW_BVH* p_bvh_tree,BVH* p_bvh_array
}
-void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) {
+void ConcavePolygonShapeSW::_setup(PoolVector<Vector3> p_faces) {
int src_face_count=p_faces.size();
if (src_face_count==0) {
- configure(AABB());
+ configure(Rect3());
return;
}
ERR_FAIL_COND(src_face_count%3);
src_face_count/=3;
- DVector<Vector3>::Read r = p_faces.read();
+ PoolVector<Vector3>::Read r = p_faces.read();
const Vector3 * facesr= r.ptr();
#if 0
@@ -1399,7 +1401,7 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) {
vertices.resize( point_map.size() );
- DVector<Vector3>::Write vw = vertices.write();
+ PoolVector<Vector3>::Write vw = vertices.write();
Vector3 *verticesw=vw.ptr();
AABB _aabb;
@@ -1418,7 +1420,7 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) {
point_map.clear(); // not needed anymore
faces.resize(face_list.size());
- DVector<Face>::Write w = faces.write();
+ PoolVector<Face>::Write w = faces.write();
Face *facesw=w.ptr();
int fc=0;
@@ -1431,10 +1433,10 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) {
face_list.clear();
- DVector<_VolumeSW_BVH_Element> bvh_array;
+ PoolVector<_VolumeSW_BVH_Element> bvh_array;
bvh_array.resize( fc );
- DVector<_VolumeSW_BVH_Element>::Write bvhw = bvh_array.write();
+ PoolVector<_VolumeSW_BVH_Element>::Write bvhw = bvh_array.write();
_VolumeSW_BVH_Element *bvh_arrayw=bvhw.ptr();
@@ -1451,8 +1453,8 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) {
}
- w=DVector<Face>::Write();
- vw=DVector<Vector3>::Write();
+ w=PoolVector<Face>::Write();
+ vw=PoolVector<Vector3>::Write();
int count=0;
@@ -1460,11 +1462,11 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) {
ERR_FAIL_COND(count==0);
- bvhw=DVector<_VolumeSW_BVH_Element>::Write();
+ bvhw=PoolVector<_VolumeSW_BVH_Element>::Write();
bvh.resize( count+1 );
- DVector<BVH>::Write bvhw2 = bvh.write();
+ PoolVector<BVH>::Write bvhw2 = bvh.write();
BVH*bvh_arrayw2=bvhw2.ptr();
int idx=0;
@@ -1473,22 +1475,22 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) {
set_aabb(_aabb);
#else
- DVector<_VolumeSW_BVH_Element> bvh_array;
+ PoolVector<_VolumeSW_BVH_Element> bvh_array;
bvh_array.resize( src_face_count );
- DVector<_VolumeSW_BVH_Element>::Write bvhw = bvh_array.write();
+ PoolVector<_VolumeSW_BVH_Element>::Write bvhw = bvh_array.write();
_VolumeSW_BVH_Element *bvh_arrayw=bvhw.ptr();
faces.resize(src_face_count);
- DVector<Face>::Write w = faces.write();
+ PoolVector<Face>::Write w = faces.write();
Face *facesw=w.ptr();
vertices.resize( src_face_count*3 );
- DVector<Vector3>::Write vw = vertices.write();
+ PoolVector<Vector3>::Write vw = vertices.write();
Vector3 *verticesw=vw.ptr();
- AABB _aabb;
+ Rect3 _aabb;
for(int i=0;i<src_face_count;i++) {
@@ -1512,15 +1514,15 @@ void ConcavePolygonShapeSW::_setup(DVector<Vector3> p_faces) {
}
- w=DVector<Face>::Write();
- vw=DVector<Vector3>::Write();
+ w=PoolVector<Face>::Write();
+ vw=PoolVector<Vector3>::Write();
int count=0;
_VolumeSW_BVH *bvh_tree=_volume_sw_build_bvh(bvh_arrayw,src_face_count,count);
bvh.resize( count+1 );
- DVector<BVH>::Write bvhw2 = bvh.write();
+ PoolVector<BVH>::Write bvhw2 = bvh.write();
BVH*bvh_arrayw2=bvhw2.ptr();
int idx=0;
@@ -1553,7 +1555,7 @@ ConcavePolygonShapeSW::ConcavePolygonShapeSW() {
/* HEIGHT MAP SHAPE */
-DVector<float> HeightMapShapeSW::get_heights() const {
+PoolVector<real_t> HeightMapShapeSW::get_heights() const {
return heights;
}
@@ -1565,7 +1567,7 @@ int HeightMapShapeSW::get_depth() const {
return depth;
}
-float HeightMapShapeSW::get_cell_size() const {
+real_t HeightMapShapeSW::get_cell_size() const {
return cell_size;
}
@@ -1593,14 +1595,14 @@ bool HeightMapShapeSW::intersect_segment(const Vector3& p_begin,const Vector3& p
}
-void HeightMapShapeSW::cull(const AABB& p_local_aabb,Callback p_callback,void* p_userdata) const {
+void HeightMapShapeSW::cull(const Rect3& p_local_aabb,Callback p_callback,void* p_userdata) const {
}
-Vector3 HeightMapShapeSW::get_moment_of_inertia(float p_mass) const {
+Vector3 HeightMapShapeSW::get_moment_of_inertia(real_t p_mass) const {
// use crappy AABB approximation
@@ -1614,22 +1616,22 @@ Vector3 HeightMapShapeSW::get_moment_of_inertia(float p_mass) const {
}
-void HeightMapShapeSW::_setup(DVector<real_t> p_heights,int p_width,int p_depth,real_t p_cell_size) {
+void HeightMapShapeSW::_setup(PoolVector<real_t> p_heights,int p_width,int p_depth,real_t p_cell_size) {
heights=p_heights;
width=p_width;
- depth=p_depth;;
+ depth=p_depth;
cell_size=p_cell_size;
- DVector<real_t>::Read r = heights. read();
+ PoolVector<real_t>::Read r = heights. read();
- AABB aabb;
+ Rect3 aabb;
for(int i=0;i<depth;i++) {
for(int j=0;j<width;j++) {
- float h = r[i*width+j];
+ real_t h = r[i*width+j];
Vector3 pos( j*cell_size, h, i*cell_size );
if (i==0 || j==0)
@@ -1655,8 +1657,8 @@ void HeightMapShapeSW::set_data(const Variant& p_data) {
int width=d["width"];
int depth=d["depth"];
- float cell_size=d["cell_size"];
- DVector<float> heights=d["heights"];
+ real_t cell_size=d["cell_size"];
+ PoolVector<real_t> heights=d["heights"];
ERR_FAIL_COND( width<= 0);
ERR_FAIL_COND( depth<= 0);
diff --git a/servers/physics/shape_sw.h b/servers/physics/shape_sw.h
index 39779bcda3..c8194ad755 100644
--- a/servers/physics/shape_sw.h
+++ b/servers/physics/shape_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,8 +35,8 @@
/*
SHAPE_LINE, ///< plane:"plane"
-SHAPE_SEGMENT, ///< float:"length"
-SHAPE_CIRCLE, ///< float:"radius"
+SHAPE_SEGMENT, ///< real_t:"length"
+SHAPE_CIRCLE, ///< real_t:"radius"
SHAPE_RECTANGLE, ///< vec3:"extents"
SHAPE_CONVEX_POLYGON, ///< array of planes:"planes"
SHAPE_CONCAVE_POLYGON, ///< Vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array)
@@ -46,7 +46,7 @@ SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_creat
class ShapeSW;
-class ShapeOwnerSW {
+class ShapeOwnerSW : public RID_Data {
public:
virtual void _shape_changed()=0;
@@ -56,29 +56,31 @@ public:
};
-class ShapeSW {
+class ShapeSW : public RID_Data {
RID self;
- AABB aabb;
+ Rect3 aabb;
bool configured;
real_t custom_bias;
Map<ShapeOwnerSW*,int> owners;
protected:
- void configure(const AABB& p_aabb);
+ void configure(const Rect3& p_aabb);
public:
enum {
MAX_SUPPORTS=8
};
+ virtual real_t get_area() const { return aabb.get_area();}
+
_FORCE_INLINE_ void set_self(const RID& p_self) { self=p_self; }
_FORCE_INLINE_ RID get_self() const {return self; }
virtual PhysicsServer::ShapeType get_type() const=0;
- _FORCE_INLINE_ AABB get_aabb() const { return aabb; }
+ _FORCE_INLINE_ Rect3 get_aabb() const { return aabb; }
_FORCE_INLINE_ bool is_configured() const { return configured; }
virtual bool is_concave() const { return false; }
@@ -88,7 +90,7 @@ public:
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const=0;
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_point, Vector3 &r_normal) const=0;
- virtual Vector3 get_moment_of_inertia(float p_mass) const=0;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const=0;
virtual void set_data(const Variant& p_data)=0;
virtual Variant get_data() const=0;
@@ -114,7 +116,7 @@ public:
typedef void (*Callback)(void* p_userdata,ShapeSW *p_convex);
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const { r_amount=0; }
- virtual void cull(const AABB& p_local_aabb,Callback p_callback,void* p_userdata) const=0;
+ virtual void cull(const Rect3& p_local_aabb,Callback p_callback,void* p_userdata) const=0;
ConcaveShapeSW() {}
};
@@ -128,6 +130,7 @@ public:
Plane get_plane() const;
+ virtual real_t get_area() const { return INFINITY; }
virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_PLANE; }
virtual void project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3& p_normal) const;
@@ -135,7 +138,7 @@ public:
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -145,13 +148,14 @@ public:
class RayShapeSW : public ShapeSW {
- float length;
+ real_t length;
- void _setup(float p_length);
+ void _setup(real_t p_length);
public:
- float get_length() const;
+ real_t get_length() const;
+ virtual real_t get_area() const { return 0.0; }
virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_RAY; }
virtual void project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const;
virtual Vector3 get_support(const Vector3& p_normal) const;
@@ -159,7 +163,7 @@ public:
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -176,6 +180,8 @@ public:
real_t get_radius() const;
+ virtual real_t get_area() const { return 4.0/3.0 * Math_PI * radius * radius * radius; }
+
virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_SPHERE; }
virtual void project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const;
@@ -183,7 +189,7 @@ public:
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const;
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -198,6 +204,7 @@ class BoxShapeSW : public ShapeSW {
public:
_FORCE_INLINE_ Vector3 get_half_extents() const { return half_extents; }
+ virtual real_t get_area() const { return 8 * half_extents.x * half_extents.y * half_extents.z; }
virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_BOX; }
@@ -206,7 +213,7 @@ public:
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const;
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -226,6 +233,8 @@ public:
_FORCE_INLINE_ real_t get_height() const { return height; }
_FORCE_INLINE_ real_t get_radius() const { return radius; }
+ virtual real_t get_area() { return 4.0/3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; }
+
virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CAPSULE; }
virtual void project_range(const Vector3& p_normal, const Transform& p_transform, real_t &r_min, real_t &r_max) const;
@@ -233,7 +242,7 @@ public:
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const;
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -257,7 +266,7 @@ public:
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const;
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -279,23 +288,23 @@ struct ConcavePolygonShapeSW : public ConcaveShapeSW {
int indices[3];
};
- DVector<Face> faces;
- DVector<Vector3> vertices;
+ PoolVector<Face> faces;
+ PoolVector<Vector3> vertices;
struct BVH {
- AABB aabb;
+ Rect3 aabb;
int left;
int right;
int face_index;
};
- DVector<BVH> bvh;
+ PoolVector<BVH> bvh;
struct _CullParams {
- AABB aabb;
+ Rect3 aabb;
Callback callback;
void *userdata;
const Face *faces;
@@ -326,10 +335,10 @@ struct ConcavePolygonShapeSW : public ConcaveShapeSW {
void _fill_bvh(_VolumeSW_BVH* p_bvh_tree,BVH* p_bvh_array,int& p_idx);
- void _setup(DVector<Vector3> p_faces);
+ void _setup(PoolVector<Vector3> p_faces);
public:
- DVector<Vector3> get_faces() const;
+ PoolVector<Vector3> get_faces() const;
virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CONCAVE_POLYGON; }
@@ -338,9 +347,9 @@ public:
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual void cull(const AABB& p_local_aabb,Callback p_callback,void* p_userdata) const;
+ virtual void cull(const Rect3& p_local_aabb,Callback p_callback,void* p_userdata) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -352,21 +361,21 @@ public:
struct HeightMapShapeSW : public ConcaveShapeSW {
- DVector<real_t> heights;
+ PoolVector<real_t> heights;
int width;
int depth;
- float cell_size;
+ real_t cell_size;
-// void _cull_segment(int p_idx,_SegmentCullParams *p_params) const;
-// void _cull(int p_idx,_CullParams *p_params) const;
+ //void _cull_segment(int p_idx,_SegmentCullParams *p_params) const;
+ //void _cull(int p_idx,_CullParams *p_params) const;
- void _setup(DVector<float> p_heights,int p_width,int p_depth,float p_cell_size);
+ void _setup(PoolVector<real_t> p_heights,int p_width,int p_depth,real_t p_cell_size);
public:
- DVector<real_t> get_heights() const;
+ PoolVector<real_t> get_heights() const;
int get_width() const;
int get_depth() const;
- float get_cell_size() const;
+ real_t get_cell_size() const;
virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_HEIGHTMAP; }
@@ -374,9 +383,9 @@ public:
virtual Vector3 get_support(const Vector3& p_normal) const;
virtual bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- virtual void cull(const AABB& p_local_aabb,Callback p_callback,void* p_userdata) const;
+ virtual void cull(const Rect3& p_local_aabb,Callback p_callback,void* p_userdata) const;
- virtual Vector3 get_moment_of_inertia(float p_mass) const;
+ virtual Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
@@ -400,7 +409,7 @@ struct FaceShapeSW : public ShapeSW {
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const;
bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const;
- Vector3 get_moment_of_inertia(float p_mass) const;
+ Vector3 get_moment_of_inertia(real_t p_mass) const;
virtual void set_data(const Variant& p_data) {}
virtual Variant get_data() const { return Variant(); }
@@ -441,12 +450,12 @@ struct MotionShapeSW : public ShapeSW {
virtual void get_supports(const Vector3& p_normal,int p_max,Vector3 *r_supports,int & r_amount) const { r_amount=0; }
bool intersect_segment(const Vector3& p_begin,const Vector3& p_end,Vector3 &r_result, Vector3 &r_normal) const { return false; }
- Vector3 get_moment_of_inertia(float p_mass) const { return Vector3(); }
+ Vector3 get_moment_of_inertia(real_t p_mass) const { return Vector3(); }
virtual void set_data(const Variant& p_data) {}
virtual Variant get_data() const { return Variant(); }
- MotionShapeSW() { configure(AABB()); }
+ MotionShapeSW() { configure(Rect3()); }
};
diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp
index 7077146420..0bc11041de 100644
--- a/servers/physics/space_sw.cpp
+++ b/servers/physics/space_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -26,7 +26,7 @@
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
-#include "globals.h"
+#include "global_config.h"
#include "space_sw.h"
#include "collision_solver_sw.h"
#include "physics_server_sw.h"
@@ -138,7 +138,7 @@ bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3& p_from, const Vecto
}
-int PhysicsDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transform& p_xform,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+int PhysicsDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transform& p_xform,real_t p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
if (p_result_max<=0)
return 0;
@@ -146,7 +146,7 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transfo
ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape,0);
- AABB aabb = p_xform.xform(shape->get_aabb());
+ Rect3 aabb = p_xform.xform(shape->get_aabb());
int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);
@@ -193,24 +193,26 @@ int PhysicsDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transfo
}
-bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform& p_xform,const Vector3& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask,ShapeRestInfo *r_info) {
+bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform& p_xform,const Vector3& p_motion,real_t p_margin,real_t &p_closest_safe,real_t &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask,ShapeRestInfo *r_info) {
ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape,false);
- AABB aabb = p_xform.xform(shape->get_aabb());
- aabb=aabb.merge(AABB(aabb.pos+p_motion,aabb.size)); //motion
+ Rect3 aabb = p_xform.xform(shape->get_aabb());
+ aabb=aabb.merge(Rect3(aabb.pos+p_motion,aabb.size)); //motion
aabb=aabb.grow(p_margin);
- //if (p_motion!=Vector3())
- // print_line(p_motion);
+ /*
+ if (p_motion!=Vector3())
+ print_line(p_motion);
+ */
int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);
- float best_safe=1;
- float best_unsafe=1;
+ real_t best_safe=1;
+ real_t best_unsafe=1;
Transform xform_inv = p_xform.affine_inverse();
MotionShapeSW mshape;
@@ -262,13 +264,13 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform&
//just do kinematic solving
- float low=0;
- float hi=1;
+ real_t low=0;
+ real_t hi=1;
Vector3 mnormal=p_motion.normalized();
for(int i=0;i<8;i++) { //steps should be customizable..
- float ofs = (low+hi)*0.5;
+ real_t ofs = (low+hi)*0.5;
Vector3 sep=mnormal; //important optimization for this to work fast enough
@@ -321,7 +323,7 @@ bool PhysicsDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform&
return true;
}
-bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform& p_shape_xform,float p_margin,Vector3 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask){
+bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform& p_shape_xform,real_t p_margin,Vector3 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask){
if (p_result_max<=0)
return 0;
@@ -329,7 +331,7 @@ bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform& p_sh
ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape,0);
- AABB aabb = p_shape_xform.xform(shape->get_aabb());
+ Rect3 aabb = p_shape_xform.xform(shape->get_aabb());
aabb=aabb.grow(p_margin);
int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);
@@ -386,7 +388,7 @@ struct _RestCallbackData {
int best_shape;
Vector3 best_contact;
Vector3 best_normal;
- float best_len;
+ real_t best_len;
};
static void _rest_cbk_result(const Vector3& p_point_A,const Vector3& p_point_B,void *p_userdata) {
@@ -395,7 +397,7 @@ static void _rest_cbk_result(const Vector3& p_point_A,const Vector3& p_point_B,v
_RestCallbackData *rd=(_RestCallbackData*)p_userdata;
Vector3 contact_rel = p_point_B - p_point_A;
- float len = contact_rel.length();
+ real_t len = contact_rel.length();
if (len <= rd->best_len)
return;
@@ -406,13 +408,13 @@ static void _rest_cbk_result(const Vector3& p_point_A,const Vector3& p_point_B,v
rd->best_shape=rd->shape;
}
-bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform& p_shape_xform,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform& p_shape_xform,real_t p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
ShapeSW *shape = static_cast<PhysicsServerSW*>(PhysicsServer::get_singleton())->shape_owner.get(p_shape);
ERR_FAIL_COND_V(!shape,0);
- AABB aabb = p_shape_xform.xform(shape->get_aabb());
+ Rect3 aabb = p_shape_xform.xform(shape->get_aabb());
aabb=aabb.grow(p_margin);
int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,SpaceSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);
@@ -719,9 +721,9 @@ SpaceSW::SpaceSW() {
contact_max_allowed_penetration= 0.01;
constraint_bias = 0.01;
- body_linear_velocity_sleep_threshold=GLOBAL_DEF("physics/sleep_threshold_linear",0.1);
- body_angular_velocity_sleep_threshold=GLOBAL_DEF("physics/sleep_threshold_angular", (8.0 / 180.0 * Math_PI) );
- body_time_to_sleep=0.5;
+ body_linear_velocity_sleep_threshold=GLOBAL_DEF("physics/3d/sleep_threshold_linear",0.1);
+ body_angular_velocity_sleep_threshold=GLOBAL_DEF("physics/3d/sleep_threshold_angular", (8.0 / 180.0 * Math_PI) );
+ body_time_to_sleep=GLOBAL_DEF("physics/3d/time_before_sleep",0.5);
body_angular_velocity_damp_ratio=10;
diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h
index 3fdef7e62b..208831914f 100644
--- a/servers/physics/space_sw.h
+++ b/servers/physics/space_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,27 +37,28 @@
#include "area_pair_sw.h"
#include "broad_phase_sw.h"
#include "collision_object_sw.h"
+#include "global_config.h"
class PhysicsDirectSpaceStateSW : public PhysicsDirectSpaceState {
- OBJ_TYPE( PhysicsDirectSpaceStateSW, PhysicsDirectSpaceState );
+ GDCLASS( PhysicsDirectSpaceStateSW, PhysicsDirectSpaceState );
public:
SpaceSW *space;
virtual bool intersect_ray(const Vector3& p_from, const Vector3& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION,bool p_pick_ray=false);
- virtual int intersect_shape(const RID& p_shape, const Transform& p_xform,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
- virtual bool cast_motion(const RID& p_shape, const Transform& p_xform,const Vector3& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION,ShapeRestInfo *r_info=NULL);
- virtual bool collide_shape(RID p_shape, const Transform& p_shape_xform,float p_margin,Vector3 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
- virtual bool rest_info(RID p_shape, const Transform& p_shape_xform,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
+ virtual int intersect_shape(const RID& p_shape, const Transform& p_xform,real_t p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
+ virtual bool cast_motion(const RID& p_shape, const Transform& p_xform,const Vector3& p_motion,real_t p_margin,real_t &p_closest_safe,real_t &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION,ShapeRestInfo *r_info=NULL);
+ virtual bool collide_shape(RID p_shape, const Transform& p_shape_xform,real_t p_margin,Vector3 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
+ virtual bool rest_info(RID p_shape, const Transform& p_shape_xform,real_t p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
PhysicsDirectSpaceStateSW();
};
-class SpaceSW {
+class SpaceSW : public RID_Data {
public:
@@ -104,10 +105,10 @@ private:
CollisionObjectSW *intersection_query_results[INTERSECTION_QUERY_MAX];
int intersection_query_subindex_results[INTERSECTION_QUERY_MAX];
- float body_linear_velocity_sleep_threshold;
- float body_angular_velocity_sleep_threshold;
- float body_time_to_sleep;
- float body_angular_velocity_damp_ratio;
+ real_t body_linear_velocity_sleep_threshold;
+ real_t body_angular_velocity_sleep_threshold;
+ real_t body_time_to_sleep;
+ real_t body_angular_velocity_damp_ratio;
bool locked;
diff --git a/servers/physics/step_sw.cpp b/servers/physics/step_sw.cpp
index 5b7ebce817..0bd5a874ea 100644
--- a/servers/physics/step_sw.cpp
+++ b/servers/physics/step_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -58,7 +58,7 @@ void StepSW::_populate_island(BodySW* p_body,BodySW** p_island,ConstraintSW **p_
}
}
-void StepSW::_setup_island(ConstraintSW *p_island,float p_delta) {
+void StepSW::_setup_island(ConstraintSW *p_island,real_t p_delta) {
ConstraintSW *ci=p_island;
while(ci) {
@@ -68,7 +68,7 @@ void StepSW::_setup_island(ConstraintSW *p_island,float p_delta) {
}
}
-void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta){
+void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,real_t p_delta){
int at_priority=1;
@@ -107,7 +107,7 @@ void StepSW::_solve_island(ConstraintSW *p_island,int p_iterations,float p_delta
}
-void StepSW::_check_suspend(BodySW *p_island,float p_delta) {
+void StepSW::_check_suspend(BodySW *p_island,real_t p_delta) {
bool can_sleep=true;
@@ -145,7 +145,7 @@ void StepSW::_check_suspend(BodySW *p_island,float p_delta) {
}
}
-void StepSW::step(SpaceSW* p_space,float p_delta,int p_iterations) {
+void StepSW::step(SpaceSW* p_space,real_t p_delta,int p_iterations) {
p_space->lock(); // can't access space during this
@@ -233,7 +233,7 @@ void StepSW::step(SpaceSW* p_space,float p_delta,int p_iterations) {
}
-// print_line("island count: "+itos(island_count)+" active count: "+itos(active_count));
+ //print_line("island count: "+itos(island_count)+" active count: "+itos(active_count));
/* SETUP CONSTRAINT ISLANDS */
{
diff --git a/servers/physics/step_sw.h b/servers/physics/step_sw.h
index f6362f3777..7048a76937 100644
--- a/servers/physics/step_sw.h
+++ b/servers/physics/step_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,12 +36,12 @@ class StepSW {
uint64_t _step;
void _populate_island(BodySW* p_body,BodySW** p_island,ConstraintSW **p_constraint_island);
- void _setup_island(ConstraintSW *p_island,float p_delta);
- void _solve_island(ConstraintSW *p_island,int p_iterations,float p_delta);
- void _check_suspend(BodySW *p_island,float p_delta);
+ void _setup_island(ConstraintSW *p_island,real_t p_delta);
+ void _solve_island(ConstraintSW *p_island,int p_iterations,real_t p_delta);
+ void _check_suspend(BodySW *p_island,real_t p_delta);
public:
- void step(SpaceSW* p_space,float p_delta,int p_iterations);
+ void step(SpaceSW* p_space,real_t p_delta,int p_iterations);
StepSW();
};
diff --git a/servers/physics_2d/SCsub b/servers/physics_2d/SCsub
index ebb7f8be00..d730144861 100644
--- a/servers/physics_2d/SCsub
+++ b/servers/physics_2d/SCsub
@@ -1,3 +1,5 @@
+#!/usr/bin/env python
+
Import('env')
-env.add_source_files(env.servers_sources,"*.cpp")
+env.add_source_files(env.servers_sources, "*.cpp")
diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp
index 759a37e84f..2625502717 100644
--- a/servers/physics_2d/area_2d_sw.cpp
+++ b/servers/physics_2d/area_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -38,7 +38,7 @@ void Area2DSW::_shapes_changed() {
}
-void Area2DSW::set_transform(const Matrix32& p_transform) {
+void Area2DSW::set_transform(const Transform2D& p_transform) {
if (!moved_list.in_list() && get_space())
get_space()->area_add_to_moved_list(&moved_list);
@@ -125,14 +125,14 @@ void Area2DSW::set_space_override_mode(Physics2DServer::AreaSpaceOverrideMode p_
void Area2DSW::set_param(Physics2DServer::AreaParameter p_param, const Variant& p_value) {
switch(p_param) {
- case Physics2DServer::AREA_PARAM_GRAVITY: gravity=p_value; ; break;
- case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; ; break;
- case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; ; break;
- case Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; ; break;
- case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; ; break;
- case Physics2DServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; ; break;
- case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; ; break;
- case Physics2DServer::AREA_PARAM_PRIORITY: priority=p_value; ; break;
+ case Physics2DServer::AREA_PARAM_GRAVITY: gravity=p_value; break;
+ case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector=p_value; break;
+ case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point=p_value; break;
+ case Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale=p_value; break;
+ case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation=p_value; break;
+ case Physics2DServer::AREA_PARAM_LINEAR_DAMP: linear_damp=p_value; break;
+ case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: angular_damp=p_value; break;
+ case Physics2DServer::AREA_PARAM_PRIORITY: priority=p_value; break;
}
diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h
index 71192db1df..02a65962e5 100644
--- a/servers/physics_2d/area_2d_sw.h
+++ b/servers/physics_2d/area_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -43,13 +43,13 @@ class Area2DSW : public CollisionObject2DSW{
Physics2DServer::AreaSpaceOverrideMode space_override_mode;
- float gravity;
+ real_t gravity;
Vector2 gravity_vector;
bool gravity_is_point;
- float gravity_distance_scale;
- float point_attenuation;
- float linear_damp;
- float angular_damp;
+ real_t gravity_distance_scale;
+ real_t point_attenuation;
+ real_t linear_damp;
+ real_t angular_damp;
int priority;
bool monitorable;
@@ -131,8 +131,8 @@ public:
void set_space_override_mode(Physics2DServer::AreaSpaceOverrideMode p_mode);
Physics2DServer::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; }
- _FORCE_INLINE_ void set_gravity(float p_gravity) { gravity=p_gravity; }
- _FORCE_INLINE_ float get_gravity() const { return gravity; }
+ _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity=p_gravity; }
+ _FORCE_INLINE_ real_t get_gravity() const { return gravity; }
_FORCE_INLINE_ void set_gravity_vector(const Vector2& p_gravity) { gravity_vector=p_gravity; }
_FORCE_INLINE_ Vector2 get_gravity_vector() const { return gravity_vector; }
@@ -140,17 +140,17 @@ public:
_FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point=p_enable; }
_FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; }
- _FORCE_INLINE_ void set_gravity_distance_scale(float scale) { gravity_distance_scale=scale; }
- _FORCE_INLINE_ float get_gravity_distance_scale() const { return gravity_distance_scale; }
+ _FORCE_INLINE_ void set_gravity_distance_scale(real_t scale) { gravity_distance_scale=scale; }
+ _FORCE_INLINE_ real_t get_gravity_distance_scale() const { return gravity_distance_scale; }
- _FORCE_INLINE_ void set_point_attenuation(float p_point_attenuation) { point_attenuation=p_point_attenuation; }
- _FORCE_INLINE_ float get_point_attenuation() const { return point_attenuation; }
+ _FORCE_INLINE_ void set_point_attenuation(real_t p_point_attenuation) { point_attenuation=p_point_attenuation; }
+ _FORCE_INLINE_ real_t get_point_attenuation() const { return point_attenuation; }
- _FORCE_INLINE_ void set_linear_damp(float p_linear_damp) { linear_damp=p_linear_damp; }
- _FORCE_INLINE_ float get_linear_damp() const { return linear_damp; }
+ _FORCE_INLINE_ void set_linear_damp(real_t p_linear_damp) { linear_damp=p_linear_damp; }
+ _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; }
- _FORCE_INLINE_ void set_angular_damp(float p_angular_damp) { angular_damp=p_angular_damp; }
- _FORCE_INLINE_ float get_angular_damp() const { return angular_damp; }
+ _FORCE_INLINE_ void set_angular_damp(real_t p_angular_damp) { angular_damp=p_angular_damp; }
+ _FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; }
_FORCE_INLINE_ void set_priority(int p_priority) { priority=p_priority; }
_FORCE_INLINE_ int get_priority() const { return priority; }
@@ -162,7 +162,7 @@ public:
void set_monitorable(bool p_monitorable);
_FORCE_INLINE_ bool is_monitorable() const { return monitorable; }
- void set_transform(const Matrix32& p_transform);
+ void set_transform(const Transform2D& p_transform);
void set_space(Space2DSW *p_space);
diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp
index 0682d8abdd..cb91caf626 100644
--- a/servers/physics_2d/area_pair_2d_sw.cpp
+++ b/servers/physics_2d/area_pair_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,7 +30,7 @@
#include "collision_solver_2d_sw.h"
-bool AreaPair2DSW::setup(float p_step) {
+bool AreaPair2DSW::setup(real_t p_step) {
bool result = area->test_collision_mask(body) && CollisionSolver2DSW::solve(body->get_shape(body_shape),body->get_transform() * body->get_shape_transform(body_shape),Vector2(),area->get_shape(area_shape),area->get_transform() * area->get_shape_transform(area_shape),Vector2(),NULL,this);
@@ -59,7 +59,7 @@ bool AreaPair2DSW::setup(float p_step) {
return false; //never do any post solving
}
-void AreaPair2DSW::solve(float p_step) {
+void AreaPair2DSW::solve(real_t p_step) {
}
@@ -100,7 +100,7 @@ AreaPair2DSW::~AreaPair2DSW() {
-bool Area2Pair2DSW::setup(float p_step) {
+bool Area2Pair2DSW::setup(real_t p_step) {
bool result = area_a->test_collision_mask(area_b) && CollisionSolver2DSW::solve(area_a->get_shape(shape_a),area_a->get_transform() * area_a->get_shape_transform(shape_a),Vector2(),area_b->get_shape(shape_b),area_b->get_transform() * area_b->get_shape_transform(shape_b),Vector2(),NULL,this);
@@ -130,7 +130,7 @@ bool Area2Pair2DSW::setup(float p_step) {
return false; //never do any post solving
}
-void Area2Pair2DSW::solve(float p_step) {
+void Area2Pair2DSW::solve(real_t p_step) {
}
diff --git a/servers/physics_2d/area_pair_2d_sw.h b/servers/physics_2d/area_pair_2d_sw.h
index a03bdb572a..219ca30c4b 100644
--- a/servers/physics_2d/area_pair_2d_sw.h
+++ b/servers/physics_2d/area_pair_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,8 +42,8 @@ class AreaPair2DSW : public Constraint2DSW {
bool colliding;
public:
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
AreaPair2DSW(Body2DSW *p_body,int p_body_shape, Area2DSW *p_area,int p_area_shape);
~AreaPair2DSW();
@@ -59,8 +59,8 @@ class Area2Pair2DSW : public Constraint2DSW {
bool colliding;
public:
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
Area2Pair2DSW(Area2DSW *p_area_a,int p_shape_a, Area2DSW *p_area_b,int p_shape_b);
~Area2Pair2DSW();
diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp
index 12ac0bd1ca..0dab534ef9 100644
--- a/servers/physics_2d/body_2d_sw.cpp
+++ b/servers/physics_2d/body_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -51,7 +51,7 @@ void Body2DSW::update_inertias() {
if(user_inertia) break;
//update tensor for allshapes, not the best way but should be somehow OK. (inspired from bullet)
- float total_area=0;
+ real_t total_area=0;
for (int i=0;i<get_shape_count();i++) {
@@ -64,11 +64,11 @@ void Body2DSW::update_inertias() {
const Shape2DSW* shape=get_shape(i);
- float area=get_shape_aabb(i).get_area();
+ real_t area=get_shape_aabb(i).get_area();
- float mass = area * this->mass / total_area;
+ real_t mass = area * this->mass / total_area;
- Matrix32 mtx = get_shape_transform(i);
+ Transform2D mtx = get_shape_transform(i);
Vector2 scale = mtx.get_scale();
_inertia += shape->get_moment_of_inertia(mass,scale) + mass * mtx.get_origin().length_squared();
//Rect2 ab = get_shape_aabb(i);
@@ -142,7 +142,7 @@ void Body2DSW::set_active(bool p_active) {
-void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, float p_value) {
+void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, real_t p_value) {
switch(p_param) {
case Physics2DServer::BODY_PARAM_BOUNCE: {
@@ -183,7 +183,7 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, float p_value)
}
}
-float Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const {
+real_t Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const {
switch(p_param) {
case Physics2DServer::BODY_PARAM_BOUNCE: {
@@ -251,8 +251,10 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) {
}
_update_inertia();
- //if (get_space())
-// _update_queries();
+ /*
+ if (get_space())
+ _update_queries();
+ */
}
Physics2DServer::BodyMode Body2DSW::get_mode() const {
@@ -287,7 +289,7 @@ void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant& p_va
_set_inv_transform(get_transform().affine_inverse());
wakeup_neighbours();
} else {
- Matrix32 t = p_variant;
+ Transform2D t = p_variant;
t.orthonormalize();
new_transform=get_transform(); //used as old to compute motion
if (t==new_transform)
@@ -301,15 +303,19 @@ void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant& p_va
} break;
case Physics2DServer::BODY_STATE_LINEAR_VELOCITY: {
- //if (mode==Physics2DServer::BODY_MODE_STATIC)
- // break;
+ /*
+ if (mode==Physics2DServer::BODY_MODE_STATIC)
+ break;
+ */
linear_velocity=p_variant;
wakeup();
} break;
case Physics2DServer::BODY_STATE_ANGULAR_VELOCITY: {
- //if (mode!=Physics2DServer::BODY_MODE_RIGID)
- // break;
+ /*
+ if (mode!=Physics2DServer::BODY_MODE_RIGID)
+ break;
+ */
angular_velocity=p_variant;
wakeup();
@@ -385,11 +391,13 @@ void Body2DSW::set_space(Space2DSW *p_space){
_update_inertia();
if (active)
get_space()->body_add_to_active_list(&active_list);
-// _update_queries();
- //if (is_active()) {
- // active=false;
- // set_active(true);
- //}
+ /*
+ _update_queries();
+ if (is_active()) {
+ active=false;
+ set_active(true);
+ }
+ */
}
@@ -459,13 +467,17 @@ void Body2DSW::integrate_forces(real_t p_step) {
// If less than 0, override dampenings with that of the Body2D
if (angular_damp>=0)
area_angular_damp = angular_damp;
- //else
- // area_angular_damp=damp_area->get_angular_damp();
+ /*
+ else
+ area_angular_damp=damp_area->get_angular_damp();
+ */
if (linear_damp>=0)
area_linear_damp = linear_damp;
- //else
- // area_linear_damp=damp_area->get_linear_damp();
+ /*
+ else
+ area_linear_damp=damp_area->get_linear_damp();
+ */
Vector2 motion;
bool do_motion=false;
@@ -473,18 +485,21 @@ void Body2DSW::integrate_forces(real_t p_step) {
if (mode==Physics2DServer::BODY_MODE_KINEMATIC) {
//compute motion, angular and etc. velocities from prev transform
- linear_velocity = (new_transform.elements[2] - get_transform().elements[2])/p_step;
+ motion = new_transform.get_origin() - get_transform().get_origin();
+ linear_velocity = motion/p_step;
- real_t rot = new_transform.affine_inverse().basis_xform(get_transform().elements[1]).angle();
+ real_t rot = new_transform.get_rotation() - get_transform().get_rotation();
angular_velocity = rot / p_step;
- motion = new_transform.elements[2] - get_transform().elements[2];
+
do_motion=true;
- //for(int i=0;i<get_shape_count();i++) {
- // set_shape_kinematic_advance(i,Vector2());
- // set_shape_kinematic_retreat(i,0);
- //}
+ /*
+ for(int i=0;i<get_shape_count();i++) {
+ set_shape_kinematic_advance(i,Vector2());
+ set_shape_kinematic_retreat(i,0);
+ }
+ */
} else {
if (!omit_force_integration && !first_integration) {
@@ -556,10 +571,10 @@ void Body2DSW::integrate_velocities(real_t p_step) {
real_t total_angular_velocity = angular_velocity+biased_angular_velocity;
Vector2 total_linear_velocity=linear_velocity+biased_linear_velocity;
- real_t angle = get_transform().get_rotation() - total_angular_velocity * p_step;
+ real_t angle = get_transform().get_rotation() + total_angular_velocity * p_step;
Vector2 pos = get_transform().get_origin() + total_linear_velocity * p_step;
- _set_transform(Matrix32(angle,pos),continuous_cd_mode==Physics2DServer::CCD_MODE_DISABLED);
+ _set_transform(Transform2D(angle,pos),continuous_cd_mode==Physics2DServer::CCD_MODE_DISABLED);
_set_inv_transform(get_transform().inverse());
if (continuous_cd_mode!=Physics2DServer::CCD_MODE_DISABLED)
diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h
index ed98017629..3fb01959a9 100644
--- a/servers/physics_2d/body_2d_sw.h
+++ b/servers/physics_2d/body_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -69,7 +69,7 @@ class Body2DSW : public CollisionObject2DSW {
real_t applied_torque;
Vector2 one_way_collision_direction;
- float one_way_collision_max_depth;
+ real_t one_way_collision_max_depth;
SelfList<Body2DSW> active_list;
@@ -86,7 +86,7 @@ class Body2DSW : public CollisionObject2DSW {
bool using_one_way_cache;
void _update_inertia();
virtual void _shapes_changed();
- Matrix32 new_transform;
+ Transform2D new_transform;
Map<Constraint2DSW*,int> constraint_map;
@@ -109,7 +109,7 @@ class Body2DSW : public CollisionObject2DSW {
Vector2 local_pos;
Vector2 local_normal;
- float depth;
+ real_t depth;
int local_shape;
Vector2 collider_pos;
int collider_shape;
@@ -168,7 +168,7 @@ public:
_FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); }
_FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); }
- _FORCE_INLINE_ void add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, float p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos);
+ _FORCE_INLINE_ void add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, real_t p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos);
_FORCE_INLINE_ void add_exception(const RID& p_exception) { exceptions.insert(p_exception);}
@@ -229,8 +229,8 @@ public:
- void set_param(Physics2DServer::BodyParameter p_param, float);
- float get_param(Physics2DServer::BodyParameter p_param) const;
+ void set_param(Physics2DServer::BodyParameter p_param, real_t);
+ real_t get_param(Physics2DServer::BodyParameter p_param) const;
void set_mode(Physics2DServer::BodyMode p_mode);
Physics2DServer::BodyMode get_mode() const;
@@ -259,8 +259,8 @@ public:
}
Vector2 get_one_way_collision_direction() const { return one_way_collision_direction; }
- void set_one_way_collision_max_depth(float p_depth) { one_way_collision_max_depth=p_depth; }
- float get_one_way_collision_max_depth() const { return one_way_collision_max_depth; }
+ void set_one_way_collision_max_depth(real_t p_depth) { one_way_collision_max_depth=p_depth; }
+ real_t get_one_way_collision_max_depth() const { return one_way_collision_max_depth; }
_FORCE_INLINE_ bool is_using_one_way_collision() const { return using_one_way_cache; }
@@ -303,7 +303,7 @@ public:
//add contact inline
-void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, float p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos) {
+void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_normal, real_t p_depth, int p_local_shape, const Vector2& p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID& p_collider,const Vector2& p_collider_velocity_at_pos) {
int c_max=contacts.size();
@@ -319,7 +319,7 @@ void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_nor
idx=contact_count++;
} else {
- float least_depth=1e20;
+ real_t least_depth=1e20;
int least_deep=-1;
for(int i=0;i<c_max;i++) {
@@ -352,7 +352,7 @@ void Body2DSW::add_contact(const Vector2& p_local_pos,const Vector2& p_local_nor
class Physics2DDirectBodyStateSW : public Physics2DDirectBodyState {
- OBJ_TYPE( Physics2DDirectBodyStateSW, Physics2DDirectBodyState );
+ GDCLASS( Physics2DDirectBodyStateSW, Physics2DDirectBodyState );
public:
@@ -361,10 +361,10 @@ public:
real_t step;
virtual Vector2 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area
- virtual float get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area
- virtual float get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area
+ virtual real_t get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area
+ virtual real_t get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area
- virtual float get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
+ virtual real_t get_inverse_mass() const { return body->get_inv_mass(); } // get the mass
virtual real_t get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space
virtual void set_linear_velocity(const Vector2& p_velocity) { body->set_linear_velocity(p_velocity); }
@@ -373,8 +373,8 @@ public:
virtual void set_angular_velocity(real_t p_velocity) { body->set_angular_velocity(p_velocity); }
virtual real_t get_angular_velocity() const { return body->get_angular_velocity(); }
- virtual void set_transform(const Matrix32& p_transform) { body->set_state(Physics2DServer::BODY_STATE_TRANSFORM,p_transform); }
- virtual Matrix32 get_transform() const { return body->get_transform(); }
+ virtual void set_transform(const Transform2D& p_transform) { body->set_state(Physics2DServer::BODY_STATE_TRANSFORM,p_transform); }
+ virtual Transform2D get_transform() const { return body->get_transform(); }
virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); }
virtual bool is_sleeping() const { return !body->is_active(); }
diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp
index ba0358a1f2..c05d61b658 100644
--- a/servers/physics_2d/body_pair_2d_sw.cpp
+++ b/servers/physics_2d/body_pair_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -99,7 +99,7 @@ void BodyPair2DSW::_contact_added_callback(const Vector2& p_point_A,const Vector
Vector2 global_B = B->get_transform().basis_xform(c.local_B)+offset_B;
Vector2 axis = global_A - global_B;
- float depth = axis.dot( c.normal );
+ real_t depth = axis.dot( c.normal );
if (depth<min_depth) {
@@ -149,7 +149,7 @@ void BodyPair2DSW::_validate_contacts() {
Vector2 global_A = A->get_transform().basis_xform(c.local_A);
Vector2 global_B = B->get_transform().basis_xform(c.local_B)+offset_B;
Vector2 axis = global_A - global_B;
- float depth = axis.dot( c.normal );
+ real_t depth = axis.dot( c.normal );
@@ -175,7 +175,7 @@ void BodyPair2DSW::_validate_contacts() {
}
-bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Matrix32& p_xform_A,Body2DSW *p_B, int p_shape_B,const Matrix32& p_xform_B,bool p_swap_result) {
+bool BodyPair2DSW::_test_ccd(real_t p_step,Body2DSW *p_A, int p_shape_A,const Transform2D& p_xform_A,Body2DSW *p_B, int p_shape_B,const Transform2D& p_xform_B,bool p_swap_result) {
@@ -202,7 +202,7 @@ bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Mat
Vector2 from = p_xform_A.xform(s[0]);
Vector2 to = from + motion;
- Matrix32 from_inv = p_xform_B.affine_inverse();
+ Transform2D from_inv = p_xform_B.affine_inverse();
Vector2 local_from = from_inv.xform(from-mnormal*mlen*0.1); //start from a little inside the bounding box
Vector2 local_to = from_inv.xform(to);
@@ -230,7 +230,7 @@ bool BodyPair2DSW::_test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Mat
return true;
}
-bool BodyPair2DSW::setup(float p_step) {
+bool BodyPair2DSW::setup(real_t p_step) {
//cannot collide
@@ -245,12 +245,12 @@ bool BodyPair2DSW::setup(float p_step) {
_validate_contacts();
Vector2 offset_A = A->get_transform().get_origin();
- Matrix32 xform_Au = A->get_transform().untranslated();
- Matrix32 xform_A = xform_Au * A->get_shape_transform(shape_A);
+ Transform2D xform_Au = A->get_transform().untranslated();
+ Transform2D xform_A = xform_Au * A->get_shape_transform(shape_A);
- Matrix32 xform_Bu = B->get_transform();
+ Transform2D xform_Bu = B->get_transform();
xform_Bu.elements[2]-=A->get_transform().get_origin();
- Matrix32 xform_B = xform_Bu * B->get_shape_transform(shape_B);
+ Transform2D xform_B = xform_Bu * B->get_shape_transform(shape_B);
Shape2DSW *shape_A_ptr=A->get_shape(shape_A);
Shape2DSW *shape_B_ptr=B->get_shape(shape_B);
@@ -343,7 +343,7 @@ bool BodyPair2DSW::setup(float p_step) {
real_t max_penetration = space->get_contact_max_allowed_penetration();
- float bias = 0.3f;
+ real_t bias = 0.3;
if (shape_A_ptr->get_custom_bias() || shape_B_ptr->get_custom_bias()) {
if (shape_A_ptr->get_custom_bias()==0)
@@ -464,7 +464,7 @@ bool BodyPair2DSW::setup(float p_step) {
return do_process;
}
-void BodyPair2DSW::solve(float p_step) {
+void BodyPair2DSW::solve(real_t p_step) {
if (!collided)
return;
diff --git a/servers/physics_2d/body_pair_2d_sw.h b/servers/physics_2d/body_pair_2d_sw.h
index a16320585e..7a4771782a 100644
--- a/servers/physics_2d/body_pair_2d_sw.h
+++ b/servers/physics_2d/body_pair_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -66,7 +66,7 @@ class BodyPair2DSW : public Constraint2DSW {
bool active;
Vector2 rA,rB;
bool reused;
- float bounce;
+ real_t bounce;
};
@@ -80,15 +80,15 @@ class BodyPair2DSW : public Constraint2DSW {
int cc;
- bool _test_ccd(float p_step,Body2DSW *p_A, int p_shape_A,const Matrix32& p_xform_A,Body2DSW *p_B, int p_shape_B,const Matrix32& p_xform_B,bool p_swap_result=false);
+ bool _test_ccd(real_t p_step,Body2DSW *p_A, int p_shape_A,const Transform2D& p_xform_A,Body2DSW *p_B, int p_shape_B,const Transform2D& p_xform_B,bool p_swap_result=false);
void _validate_contacts();
static void _add_contact(const Vector2& p_point_A,const Vector2& p_point_B,void *p_self);
_FORCE_INLINE_ void _contact_added_callback(const Vector2& p_point_A,const Vector2& p_point_B);
public:
- bool setup(float p_step);
- void solve(float p_step);
+ bool setup(real_t p_step);
+ void solve(real_t p_step);
BodyPair2DSW(Body2DSW *p_A, int p_shape_A,Body2DSW *p_B, int p_shape_B);
~BodyPair2DSW();
diff --git a/servers/physics_2d/broad_phase_2d_basic.cpp b/servers/physics_2d/broad_phase_2d_basic.cpp
index 3a95bb2411..e1f6f4f92b 100644
--- a/servers/physics_2d/broad_phase_2d_basic.cpp
+++ b/servers/physics_2d/broad_phase_2d_basic.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -28,7 +28,7 @@
/*************************************************************************/
#include "broad_phase_2d_basic.h"
-ID BroadPhase2DBasic::create(CollisionObject2DSW *p_object_, int p_subindex) {
+BroadPhase2DBasic::ID BroadPhase2DBasic::create(CollisionObject2DSW *p_object_, int p_subindex) {
current++;
diff --git a/servers/physics_2d/broad_phase_2d_basic.h b/servers/physics_2d/broad_phase_2d_basic.h
index 80aa423819..82e91118ce 100644
--- a/servers/physics_2d/broad_phase_2d_basic.h
+++ b/servers/physics_2d/broad_phase_2d_basic.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.cpp b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
index 953c87021f..06eead64cd 100644
--- a/servers/physics_2d/broad_phase_2d_hash_grid.cpp
+++ b/servers/physics_2d/broad_phase_2d_hash_grid.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "broad_phase_2d_hash_grid.h"
-#include "globals.h"
+#include "global_config.h"
#define LARGE_ELEMENT_FI 1.01239812
@@ -539,14 +539,14 @@ int BroadPhase2DHashGrid::cull_segment(const Vector2& p_from, const Vector2& p_t
Vector2 max;
if (dir.x<0)
- max.x= (Math::floor(pos.x)*cell_size - p_from.x) / dir.x;
+ max.x= (Math::floor((double)pos.x)*cell_size - p_from.x) / dir.x;
else
- max.x= (Math::floor(pos.x + 1)*cell_size - p_from.x) / dir.x;
+ max.x= (Math::floor((double)pos.x + 1)*cell_size - p_from.x) / dir.x;
if (dir.y<0)
- max.y= (Math::floor(pos.y)*cell_size - p_from.y) / dir.y;
+ max.y= (Math::floor((double)pos.y)*cell_size - p_from.y) / dir.y;
else
- max.y= (Math::floor(pos.y + 1)*cell_size - p_from.y) / dir.y;
+ max.y= (Math::floor((double)pos.y + 1)*cell_size - p_from.y) / dir.y;
int cullcount=0;
_cull<false,true>(pos,Rect2(),p_from,p_to,p_results,p_max_results,p_result_indices,cullcount);
@@ -599,8 +599,10 @@ int BroadPhase2DHashGrid::cull_segment(const Vector2& p_from, const Vector2& p_t
E->key()->pass=pass;
-// if (use_aabb && !p_aabb.intersects(E->key()->aabb))
-// continue;
+ /*
+ if (use_aabb && !p_aabb.intersects(E->key()->aabb))
+ continue;
+ */
if (!E->key()->aabb.intersects_segment(p_from,p_to))
continue;
@@ -645,8 +647,10 @@ int BroadPhase2DHashGrid::cull_aabb(const Rect2& p_aabb,CollisionObject2DSW** p_
if (!p_aabb.intersects(E->key()->aabb))
continue;
-// if (!E->key()->aabb.intersects_segment(p_from,p_to))
-// continue;
+ /*
+ if (!E->key()->aabb.intersects_segment(p_from,p_to))
+ continue;
+ */
p_results[cullcount]=E->key()->owner;
p_result_indices[cullcount]=E->key()->subindex;
@@ -683,12 +687,12 @@ BroadPhase2DSW *BroadPhase2DHashGrid::_create() {
BroadPhase2DHashGrid::BroadPhase2DHashGrid() {
- hash_table_size = GLOBAL_DEF("physics_2d/bp_hash_table_size",4096);
+ hash_table_size = GLOBAL_DEF("physics/2d/bp_hash_table_size",4096);
hash_table_size = Math::larger_prime(hash_table_size);
hash_table = memnew_arr( PosBin*, hash_table_size);
- cell_size = GLOBAL_DEF("physics_2d/cell_size",128);
- large_object_min_surface = GLOBAL_DEF("physics_2d/large_object_surface_treshold_in_cells",512);
+ cell_size = GLOBAL_DEF("physics/2d/cell_size",128);
+ large_object_min_surface = GLOBAL_DEF("physics/2d/large_object_surface_treshold_in_cells",512);
for(int i=0;i<hash_table_size;i++)
hash_table[i]=NULL;
diff --git a/servers/physics_2d/broad_phase_2d_hash_grid.h b/servers/physics_2d/broad_phase_2d_hash_grid.h
index 561d488484..857053ccf0 100644
--- a/servers/physics_2d/broad_phase_2d_hash_grid.h
+++ b/servers/physics_2d/broad_phase_2d_hash_grid.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_sw.cpp b/servers/physics_2d/broad_phase_2d_sw.cpp
index 0dead94ca1..4347155c2c 100644
--- a/servers/physics_2d/broad_phase_2d_sw.cpp
+++ b/servers/physics_2d/broad_phase_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/broad_phase_2d_sw.h b/servers/physics_2d/broad_phase_2d_sw.h
index 056ef664fd..b9ec434ae9 100644
--- a/servers/physics_2d/broad_phase_2d_sw.h
+++ b/servers/physics_2d/broad_phase_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp
index 7f9d3312b9..9ae0e40417 100644
--- a/servers/physics_2d/collision_object_2d_sw.cpp
+++ b/servers/physics_2d/collision_object_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,7 +29,7 @@
#include "collision_object_2d_sw.h"
#include "space_2d_sw.h"
-void CollisionObject2DSW::add_shape(Shape2DSW *p_shape,const Matrix32& p_transform) {
+void CollisionObject2DSW::add_shape(Shape2DSW *p_shape,const Transform2D& p_transform) {
Shape s;
s.shape=p_shape;
@@ -63,7 +63,7 @@ void CollisionObject2DSW::set_shape_metadata(int p_index,const Variant& p_metada
}
-void CollisionObject2DSW::set_shape_transform(int p_index,const Matrix32& p_transform){
+void CollisionObject2DSW::set_shape_transform(int p_index,const Transform2D& p_transform){
ERR_FAIL_INDEX(p_index,shapes.size());
@@ -149,7 +149,7 @@ void CollisionObject2DSW::_update_shapes() {
//not quite correct, should compute the next matrix..
Rect2 shape_aabb=s.shape->get_aabb();
- Matrix32 xform = transform * s.xform;
+ Transform2D xform = transform * s.xform;
shape_aabb=xform.xform(shape_aabb);
s.aabb_cache=shape_aabb;
s.aabb_cache=s.aabb_cache.grow( (s.aabb_cache.size.x + s.aabb_cache.size.y)*0.5*0.05 );
@@ -176,7 +176,7 @@ void CollisionObject2DSW::_update_shapes_with_motion(const Vector2& p_motion) {
//not quite correct, should compute the next matrix..
Rect2 shape_aabb=s.shape->get_aabb();
- Matrix32 xform = transform * s.xform;
+ Transform2D xform = transform * s.xform;
shape_aabb=xform.xform(shape_aabb);
shape_aabb=shape_aabb.merge(Rect2( shape_aabb.pos+p_motion,shape_aabb.size)); //use motion
s.aabb_cache=shape_aabb;
diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h
index 1f213d8444..0f77e9b426 100644
--- a/servers/physics_2d/collision_object_2d_sw.h
+++ b/servers/physics_2d/collision_object_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -51,8 +51,8 @@ private:
struct Shape {
- Matrix32 xform;
- Matrix32 xform_inv;
+ Transform2D xform;
+ Transform2D xform_inv;
BroadPhase2DSW::ID bpid;
Rect2 aabb_cache; //for rayqueries
Shape2DSW *shape;
@@ -63,8 +63,8 @@ private:
Vector<Shape> shapes;
Space2DSW *space;
- Matrix32 transform;
- Matrix32 inv_transform;
+ Transform2D transform;
+ Transform2D inv_transform;
uint32_t collision_mask;
uint32_t layer_mask;
bool _static;
@@ -77,8 +77,8 @@ protected:
void _update_shapes_with_motion(const Vector2& p_motion);
void _unregister_shapes();
- _FORCE_INLINE_ void _set_transform(const Matrix32& p_transform, bool p_update_shapes=true) { transform=p_transform; if (p_update_shapes) {_update_shapes();} }
- _FORCE_INLINE_ void _set_inv_transform(const Matrix32& p_transform) { inv_transform=p_transform; }
+ _FORCE_INLINE_ void _set_transform(const Transform2D& p_transform, bool p_update_shapes=true) { transform=p_transform; if (p_update_shapes) {_update_shapes();} }
+ _FORCE_INLINE_ void _set_inv_transform(const Transform2D& p_transform) { inv_transform=p_transform; }
void _set_static(bool p_static);
virtual void _shapes_changed()=0;
@@ -96,21 +96,21 @@ public:
void _shape_changed();
_FORCE_INLINE_ Type get_type() const { return type; }
- void add_shape(Shape2DSW *p_shape,const Matrix32& p_transform=Matrix32());
+ void add_shape(Shape2DSW *p_shape,const Transform2D& p_transform=Transform2D());
void set_shape(int p_index,Shape2DSW *p_shape);
- void set_shape_transform(int p_index,const Matrix32& p_transform);
+ void set_shape_transform(int p_index,const Transform2D& p_transform);
void set_shape_metadata(int p_index,const Variant& p_metadata);
_FORCE_INLINE_ int get_shape_count() const { return shapes.size(); }
_FORCE_INLINE_ Shape2DSW *get_shape(int p_index) const { return shapes[p_index].shape; }
- _FORCE_INLINE_ const Matrix32& get_shape_transform(int p_index) const { return shapes[p_index].xform; }
- _FORCE_INLINE_ const Matrix32& get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
+ _FORCE_INLINE_ const Transform2D& get_shape_transform(int p_index) const { return shapes[p_index].xform; }
+ _FORCE_INLINE_ const Transform2D& get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; }
_FORCE_INLINE_ const Rect2& get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; }
_FORCE_INLINE_ const Variant& get_shape_metadata(int p_index) const { return shapes[p_index].metadata; }
- _FORCE_INLINE_ Matrix32 get_transform() const { return transform; }
- _FORCE_INLINE_ Matrix32 get_inv_transform() const { return inv_transform; }
+ _FORCE_INLINE_ Transform2D get_transform() const { return transform; }
+ _FORCE_INLINE_ Transform2D get_inv_transform() const { return inv_transform; }
_FORCE_INLINE_ Space2DSW* get_space() const { return space; }
_FORCE_INLINE_ void set_shape_as_trigger(int p_idx,bool p_enable) { shapes[p_idx].trigger=p_enable; }
diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp
index a6d12bdada..4c116cee3f 100644
--- a/servers/physics_2d/collision_solver_2d_sat.cpp
+++ b/servers/physics_2d/collision_solver_2d_sat.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -40,8 +40,10 @@ struct _CollectorCallback2D {
_FORCE_INLINE_ void call(const Vector2& p_point_A, const Vector2& p_point_B) {
- //if (normal.dot(p_point_A) >= normal.dot(p_point_B))
- // return;
+ /*
+ if (normal.dot(p_point_A) >= normal.dot(p_point_B))
+ return;
+ */
if (swap)
callback(p_point_B,p_point_A,userdata);
else
@@ -79,7 +81,7 @@ _FORCE_INLINE_ static void _generate_contacts_point_edge(const Vector2 * p_point
struct _generate_contacts_Pair {
bool a;
int idx;
- float d;
+ real_t d;
_FORCE_INLINE_ bool operator <(const _generate_contacts_Pair& l) const { return d< l.d; }
};
@@ -106,7 +108,7 @@ _FORCE_INLINE_ static void _generate_contacts_edge_edge(const Vector2 * p_points
SWAP(pA[0],pA[1]);
}
- float dB[2]={t.dot(p_points_B[0]),t.dot(p_points_B[1])};
+ real_t dB[2]={t.dot(p_points_B[0]),t.dot(p_points_B[1])};
Vector2 pB[2]={p_points_B[0],p_points_B[1]};
if (dB[0]>dB[1]) {
SWAP(dB[0],dB[1]);
@@ -263,10 +265,10 @@ _FORCE_INLINE_ static void _generate_contacts_edge_edge(const Vector2 * p_points
Vector2 base_B = p_points_B[0] - axis * axis.dot(p_points_B[0]);
//sort all 4 points in axis
- float dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) };
+ real_t dvec[4]={ axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) };
//todo , find max/min and then use 2 central points
- SortArray<float> sa;
+ SortArray<real_t> sa;
sa.sort(dvec,4);
//use the middle ones as contacts
@@ -343,8 +345,8 @@ class SeparatorAxisTest2D {
const ShapeA *shape_A;
const ShapeB *shape_B;
- const Matrix32 *transform_A;
- const Matrix32 *transform_B;
+ const Transform2D *transform_A;
+ const Transform2D *transform_B;
real_t best_depth;
Vector2 best_axis;
int best_axis_count;
@@ -462,7 +464,7 @@ public:
}
}
- // print_line("test axis: "+p_axis+" depth: "+rtos(best_depth));
+ //print_line("test axis: "+p_axis+" depth: "+rtos(best_depth));
#ifdef DEBUG_ENABLED
best_axis_count++;
#endif
@@ -560,7 +562,7 @@ public:
}
- _FORCE_INLINE_ SeparatorAxisTest2D(const ShapeA *p_shape_A,const Matrix32& p_transform_a, const ShapeB *p_shape_B,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_A=Vector2(), const Vector2& p_motion_B=Vector2(),real_t p_margin_A=0,real_t p_margin_B=0) {
+ _FORCE_INLINE_ SeparatorAxisTest2D(const ShapeA *p_shape_A,const Transform2D& p_transform_a, const ShapeB *p_shape_B,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_A=Vector2(), const Vector2& p_motion_B=Vector2(),real_t p_margin_A=0,real_t p_margin_B=0) {
margin_A=p_margin_A;
margin_B=p_margin_B;
@@ -594,11 +596,11 @@ public:
(castA && castB && !separator.test_axis(((m_a)+p_motion_a-((m_b)+p_motion_b)).normalized())) )
-typedef void (*CollisionFunc)(const Shape2DSW*,const Matrix32&,const Shape2DSW*,const Matrix32&,_CollectorCallback2D *p_collector,const Vector2&,const Vector2&,float,float);
+typedef void (*CollisionFunc)(const Shape2DSW*,const Transform2D&,const Shape2DSW*,const Transform2D&,_CollectorCallback2D *p_collector,const Vector2&,const Vector2&,real_t,real_t);
template<bool castA, bool castB,bool withMargin>
-static void _collision_segment_segment(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_segment_segment(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
const SegmentShape2DSW *segment_B = static_cast<const SegmentShape2DSW*>(p_b);
@@ -610,8 +612,10 @@ static void _collision_segment_segment(const Shape2DSW* p_a,const Matrix32& p_tr
//this collision is kind of pointless
- //if (!separator.test_previous_axis())
- // return;
+ /*
+ if (!separator.test_previous_axis())
+ return;
+ */
if (!separator.test_cast())
return;
@@ -641,7 +645,7 @@ static void _collision_segment_segment(const Shape2DSW* p_a,const Matrix32& p_tr
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_segment_circle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_segment_circle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
@@ -674,7 +678,7 @@ static void _collision_segment_circle(const Shape2DSW* p_a,const Matrix32& p_tra
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_segment_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_segment_rectangle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);
@@ -698,7 +702,7 @@ static void _collision_segment_rectangle(const Shape2DSW* p_a,const Matrix32& p_
if (withMargin) {
- Matrix32 inv = p_transform_b.affine_inverse();
+ Transform2D inv = p_transform_b.affine_inverse();
Vector2 a = p_transform_a.xform(segment_A->get_a());
Vector2 b = p_transform_a.xform(segment_A->get_b());
@@ -739,7 +743,7 @@ static void _collision_segment_rectangle(const Shape2DSW* p_a,const Matrix32& p_
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_segment_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_segment_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
@@ -771,7 +775,7 @@ static void _collision_segment_capsule(const Shape2DSW* p_a,const Matrix32& p_tr
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_segment_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_segment_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW*>(p_a);
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
@@ -811,7 +815,7 @@ static void _collision_segment_convex_polygon(const Shape2DSW* p_a,const Matrix3
/////////
template<bool castA, bool castB,bool withMargin>
-static void _collision_circle_circle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_circle_circle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW*>(p_b);
@@ -834,7 +838,7 @@ static void _collision_circle_circle(const Shape2DSW* p_a,const Matrix32& p_tran
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_circle_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_circle_rectangle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);
@@ -850,7 +854,7 @@ static void _collision_circle_rectangle(const Shape2DSW* p_a,const Matrix32& p_t
const Vector2 &sphere=p_transform_a.elements[2];
const Vector2 *axis=&p_transform_b.elements[0];
-// const Vector2& half_extents = rectangle_B->get_half_extents();
+ //const Vector2& half_extents = rectangle_B->get_half_extents();
if (!separator.test_axis(axis[0].normalized()))
return;
@@ -858,7 +862,7 @@ static void _collision_circle_rectangle(const Shape2DSW* p_a,const Matrix32& p_t
if (!separator.test_axis(axis[1].normalized()))
return;
- Matrix32 binv = p_transform_b.affine_inverse();
+ Transform2D binv = p_transform_b.affine_inverse();
{
if (!separator.test_axis( rectangle_B->get_circle_axis(p_transform_b,binv,sphere ) ) )
@@ -890,7 +894,7 @@ static void _collision_circle_rectangle(const Shape2DSW* p_a,const Matrix32& p_t
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_circle_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_circle_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
@@ -920,7 +924,7 @@ static void _collision_circle_capsule(const Shape2DSW* p_a,const Matrix32& p_tra
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_circle_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_circle_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW*>(p_a);
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
@@ -952,7 +956,7 @@ static void _collision_circle_convex_polygon(const Shape2DSW* p_a,const Matrix32
/////////
template<bool castA, bool castB,bool withMargin>
-static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW*>(p_b);
@@ -982,22 +986,22 @@ static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Matrix32&
if (withMargin) {
- Matrix32 invA=p_transform_a.affine_inverse();
- Matrix32 invB=p_transform_b.affine_inverse();
+ Transform2D invA=p_transform_a.affine_inverse();
+ Transform2D invB=p_transform_b.affine_inverse();
if (!separator.test_axis( rectangle_A->get_box_axis(p_transform_a,invA,rectangle_B,p_transform_b,invB) ) )
return;
if (castA || castB) {
- Matrix32 aofs = p_transform_a;
+ Transform2D aofs = p_transform_a;
aofs.elements[2]+=p_motion_a;
- Matrix32 bofs = p_transform_b;
+ Transform2D bofs = p_transform_b;
bofs.elements[2]+=p_motion_b;
- Matrix32 aofsinv = aofs.affine_inverse();
- Matrix32 bofsinv = bofs.affine_inverse();
+ Transform2D aofsinv = aofs.affine_inverse();
+ Transform2D bofsinv = bofs.affine_inverse();
if (castA) {
@@ -1023,7 +1027,7 @@ static void _collision_rectangle_rectangle(const Shape2DSW* p_a,const Matrix32&
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
@@ -1051,7 +1055,7 @@ static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Matrix32& p_
//box endpoints to capsule circles
- Matrix32 boxinv = p_transform_a.affine_inverse();
+ Transform2D boxinv = p_transform_a.affine_inverse();
for(int i=0;i<2;i++) {
@@ -1096,7 +1100,7 @@ static void _collision_rectangle_capsule(const Shape2DSW* p_a,const Matrix32& p_
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW*>(p_a);
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
@@ -1118,7 +1122,7 @@ static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matri
return;
//convex faces
- Matrix32 boxinv;
+ Transform2D boxinv;
if (withMargin) {
boxinv=p_transform_a.affine_inverse();
}
@@ -1158,7 +1162,7 @@ static void _collision_rectangle_convex_polygon(const Shape2DSW* p_a,const Matri
/////////
template<bool castA, bool castB,bool withMargin>
-static void _collision_capsule_capsule(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_capsule_capsule(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW*>(p_a);
const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW*>(p_b);
@@ -1201,7 +1205,7 @@ static void _collision_capsule_capsule(const Shape2DSW* p_a,const Matrix32& p_tr
}
template<bool castA, bool castB,bool withMargin>
-static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW*>(p_a);
const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW*>(p_b);
@@ -1247,7 +1251,7 @@ static void _collision_capsule_convex_polygon(const Shape2DSW* p_a,const Matrix3
template<bool castA, bool castB,bool withMargin>
-static void _collision_convex_polygon_convex_polygon(const Shape2DSW* p_a,const Matrix32& p_transform_a,const Shape2DSW* p_b,const Matrix32& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,float p_margin_A,float p_margin_B) {
+static void _collision_convex_polygon_convex_polygon(const Shape2DSW* p_a,const Transform2D& p_transform_a,const Shape2DSW* p_b,const Transform2D& p_transform_b,_CollectorCallback2D *p_collector,const Vector2& p_motion_a,const Vector2& p_motion_b,real_t p_margin_A,real_t p_margin_B) {
const ConvexPolygonShape2DSW *convex_A = static_cast<const ConvexPolygonShape2DSW*>(p_a);
@@ -1294,7 +1298,7 @@ static void _collision_convex_polygon_convex_polygon(const Shape2DSW* p_a,const
////////
-bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32& p_transform_A, const Vector2& p_motion_A, const Shape2DSW *p_shape_B, const Matrix32& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap,Vector2 *sep_axis,float p_margin_A,float p_margin_B) {
+bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D& p_transform_A, const Vector2& p_motion_A, const Shape2DSW *p_shape_B, const Transform2D& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap,Vector2 *sep_axis,real_t p_margin_A,real_t p_margin_B) {
Physics2DServer::ShapeType type_A=p_shape_A->get_type();
@@ -1551,8 +1555,8 @@ bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32& p_
const Shape2DSW *A=p_shape_A;
const Shape2DSW *B=p_shape_B;
- const Matrix32 *transform_A=&p_transform_A;
- const Matrix32 *transform_B=&p_transform_B;
+ const Transform2D *transform_A=&p_transform_A;
+ const Transform2D *transform_B=&p_transform_B;
const Vector2 *motion_A=&p_motion_A;
const Vector2 *motion_B=&p_motion_B;
real_t margin_A=p_margin_A,margin_B=p_margin_B;
diff --git a/servers/physics_2d/collision_solver_2d_sat.h b/servers/physics_2d/collision_solver_2d_sat.h
index 91aeb53030..6b698a09f2 100644
--- a/servers/physics_2d/collision_solver_2d_sat.h
+++ b/servers/physics_2d/collision_solver_2d_sat.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -32,6 +32,6 @@
#include "collision_solver_2d_sw.h"
-bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32& p_transform_A, const Vector2& p_motion_A,const Shape2DSW *p_shape_B, const Matrix32& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector2 *sep_axis=NULL,float p_margin_A=0,float p_margin_B=0);
+bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D& p_transform_A, const Vector2& p_motion_A,const Shape2DSW *p_shape_B, const Transform2D& p_transform_B,const Vector2& p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback,void *p_userdata, bool p_swap=false,Vector2 *sep_axis=NULL,real_t p_margin_A=0,real_t p_margin_B=0);
#endif // COLLISION_SOLVER_2D_SAT_H
diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp
index fcc3f8067a..3fdecdf413 100644
--- a/servers/physics_2d/collision_solver_2d_sw.cpp
+++ b/servers/physics_2d/collision_solver_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,7 +34,7 @@
//#define collision_solver gjk_epa_calculate_penetration
-bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result) {
+bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result) {
const LineShape2DSW *line = static_cast<const LineShape2DSW*>(p_shape_A);
@@ -77,7 +77,7 @@ bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A,const Mat
return found;
}
-bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis) {
+bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis) {
@@ -89,7 +89,7 @@ bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A,const Matrix3
Vector2 to = from+p_transform_A[1]*ray->get_length();
Vector2 support_A=to;
- Matrix32 invb = p_transform_B.affine_inverse();
+ Transform2D invb = p_transform_B.affine_inverse();
from = invb.xform(from);
to = invb.xform(to);
@@ -145,9 +145,9 @@ bool CollisionSolver2DSW::solve_ray(const Shape2DSW *p_shape_A,const Matrix32& p
struct _ConcaveCollisionInfo2D {
- const Matrix32 *transform_A;
+ const Transform2D *transform_A;
const Shape2DSW *shape_A;
- const Matrix32 *transform_B;
+ const Transform2D *transform_B;
Vector2 motion_A;
Vector2 motion_B;
real_t margin_A;
@@ -181,7 +181,7 @@ void CollisionSolver2DSW::concave_callback(void *p_userdata, Shape2DSW *p_convex
}
-bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis,float p_margin_A,float p_margin_B) {
+bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis,real_t p_margin_A,real_t p_margin_B) {
const ConcaveShape2DSW *concave_B=static_cast<const ConcaveShape2DSW*>(p_shape_B);
@@ -202,8 +202,8 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Matrix3
cinfo.aabb_tests=0;
- Matrix32 rel_transform = p_transform_A;
- rel_transform.elements[2]-=p_transform_B.elements[2];
+ Transform2D rel_transform = p_transform_A;
+ rel_transform.elements[2]-=p_transform_B.get_origin();
//quickly compute a local Rect2
@@ -211,10 +211,10 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Matrix3
for(int i=0;i<2;i++) {
Vector2 axis( p_transform_B.elements[i] );
- float axis_scale = 1.0/axis.length();
+ real_t axis_scale = 1.0/axis.length();
axis*=axis_scale;
- float smin,smax;
+ real_t smin,smax;
p_shape_A->project_rangev(axis,rel_transform,smin,smax);
smin*=axis_scale;
smax*=axis_scale;
@@ -226,12 +226,12 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A,const Matrix3
concave_B->cull(local_aabb,concave_callback,&cinfo);
-// print_line("Rect2 TESTS: "+itos(cinfo.aabb_tests));
+ //print_line("Rect2 TESTS: "+itos(cinfo.aabb_tests));
return cinfo.collided;
}
-bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis,float p_margin_A,float p_margin_B) {
+bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis,real_t p_margin_A,real_t p_margin_B) {
@@ -255,9 +255,11 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A,const Matrix32& p_tra
if (type_B==Physics2DServer::SHAPE_LINE || type_B==Physics2DServer::SHAPE_RAY) {
return false;
- //if (type_B==Physics2DServer::SHAPE_RAY) {
- // return false;
}
+ /*
+ if (type_B==Physics2DServer::SHAPE_RAY) {
+ return false;
+ */
if (swap) {
return solve_static_line(p_shape_B,p_transform_B,p_shape_A,p_transform_A,p_result_callback,p_userdata,true);
diff --git a/servers/physics_2d/collision_solver_2d_sw.h b/servers/physics_2d/collision_solver_2d_sw.h
index 7e3542805c..2a5fc9fe1d 100644
--- a/servers/physics_2d/collision_solver_2d_sw.h
+++ b/servers/physics_2d/collision_solver_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,16 +35,16 @@ class CollisionSolver2DSW {
public:
typedef void (*CallbackResult)(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata);
private:
- static bool solve_static_line(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result);
+ static bool solve_static_line(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result);
static void concave_callback(void *p_userdata, Shape2DSW *p_convex);
- static bool solve_concave(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL,float p_margin_A=0,float p_margin_B=0);
- static bool solve_raycast(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL);
+ static bool solve_concave(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL,real_t p_margin_A=0,real_t p_margin_B=0);
+ static bool solve_raycast(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,CallbackResult p_result_callback,void *p_userdata,bool p_swap_result,Vector2 *sep_axis=NULL);
public:
- static bool solve(const Shape2DSW *p_shape_A,const Matrix32& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Matrix32& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis=NULL,float p_margin_A=0,float p_margin_B=0);
+ static bool solve(const Shape2DSW *p_shape_A,const Transform2D& p_transform_A,const Vector2& p_motion_A,const Shape2DSW *p_shape_B,const Transform2D& p_transform_B,const Vector2& p_motion_B,CallbackResult p_result_callback,void *p_userdata,Vector2 *sep_axis=NULL,real_t p_margin_A=0,real_t p_margin_B=0);
};
diff --git a/servers/physics_2d/constraint_2d_sw.h b/servers/physics_2d/constraint_2d_sw.h
index f776dbfe2c..cce668405c 100644
--- a/servers/physics_2d/constraint_2d_sw.h
+++ b/servers/physics_2d/constraint_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -31,7 +31,7 @@
#include "body_2d_sw.h"
-class Constraint2DSW {
+class Constraint2DSW : public RID_Data {
Body2DSW **_body_ptr;
int _body_count;
@@ -63,8 +63,8 @@ public:
_FORCE_INLINE_ int get_body_count() const { return _body_count; }
- virtual bool setup(float p_step)=0;
- virtual void solve(float p_step)=0;
+ virtual bool setup(real_t p_step)=0;
+ virtual void solve(real_t p_step)=0;
virtual ~Constraint2DSW() {}
};
diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp
index 958780c2e6..76adf06429 100644
--- a/servers/physics_2d/joints_2d_sw.cpp
+++ b/servers/physics_2d/joints_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -91,7 +91,7 @@ normal_relative_velocity(Body2DSW *a, Body2DSW *b, Vector2 rA, Vector2 rB, Vecto
#if 0
-bool PinJoint2DSW::setup(float p_step) {
+bool PinJoint2DSW::setup(real_t p_step) {
Space2DSW *space = A->get_space();
ERR_FAIL_COND_V(!space,false;)
@@ -136,7 +136,7 @@ bool PinJoint2DSW::setup(float p_step) {
-void PinJoint2DSW::solve(float p_step){
+void PinJoint2DSW::solve(real_t p_step){
if (!correct)
return;
@@ -189,7 +189,7 @@ PinJoint2DSW::~PinJoint2DSW() {
#else
-bool PinJoint2DSW::setup(float p_step) {
+bool PinJoint2DSW::setup(real_t p_step) {
Space2DSW *space = A->get_space();
ERR_FAIL_COND_V(!space,false;)
@@ -215,21 +215,21 @@ bool PinJoint2DSW::setup(float p_step) {
real_t B_inv_mass = B?B->get_inv_mass():0.0;
- Matrix32 K1;
+ Transform2D K1;
K1[0].x = A->get_inv_mass() + B_inv_mass; K1[1].x = 0.0f;
K1[0].y = 0.0f; K1[1].y = A->get_inv_mass() + B_inv_mass;
- Matrix32 K2;
+ Transform2D K2;
K2[0].x = A->get_inv_inertia() * rA.y * rA.y; K2[1].x = -A->get_inv_inertia() * rA.x * rA.y;
K2[0].y = -A->get_inv_inertia() * rA.x * rA.y; K2[1].y = A->get_inv_inertia() * rA.x * rA.x;
- Matrix32 K;
+ Transform2D K;
K[0]= K1[0] + K2[0];
K[1]= K1[1] + K2[1];
if (B) {
- Matrix32 K3;
+ Transform2D K3;
K3[0].x = B->get_inv_inertia() * rB.y * rB.y; K3[1].x = -B->get_inv_inertia() * rB.x * rB.y;
K3[0].y = -B->get_inv_inertia() * rB.x * rB.y; K3[1].y = B->get_inv_inertia() * rB.x * rB.x;
@@ -257,7 +257,7 @@ bool PinJoint2DSW::setup(float p_step) {
return true;
}
-void PinJoint2DSW::solve(float p_step){
+void PinJoint2DSW::solve(real_t p_step){
// compute relative velocity
@@ -370,7 +370,7 @@ mult_k(const Vector2& vr, const Vector2 &k1, const Vector2 &k2)
return Vector2(vr.dot(k1), vr.dot(k2));
}
-bool GrooveJoint2DSW::setup(float p_step) {
+bool GrooveJoint2DSW::setup(real_t p_step) {
// calculate endpoints in worldspace
@@ -407,12 +407,12 @@ bool GrooveJoint2DSW::setup(float p_step) {
jn_max = get_max_force() * p_step;
// calculate bias velocity
-// cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
-// joint->bias = cpvclamp(cpvmult(delta, -joint->constraint.biasCoef*dt_inv), joint->constraint.maxBias);
+ //cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1));
+ //joint->bias = cpvclamp(cpvmult(delta, -joint->constraint.biasCoef*dt_inv), joint->constraint.maxBias);
Vector2 delta = (B->get_transform().get_origin() +rB) - (A->get_transform().get_origin() + rA);
- float _b = get_bias();
+ real_t _b = get_bias();
_b=0.001;
gbias=(delta*-(_b==0?space->get_constraint_bias():_b)*(1.0/p_step)).clamped(get_max_bias());
@@ -424,7 +424,7 @@ bool GrooveJoint2DSW::setup(float p_step) {
return true;
}
-void GrooveJoint2DSW::solve(float p_step){
+void GrooveJoint2DSW::solve(real_t p_step){
// compute impulse
@@ -470,7 +470,7 @@ GrooveJoint2DSW::~GrooveJoint2DSW() {
//////////////////////////////////////////////
-bool DampedSpringJoint2DSW::setup(float p_step) {
+bool DampedSpringJoint2DSW::setup(real_t p_step) {
rA = A->get_transform().basis_xform(anchor_A);
rB = B->get_transform().basis_xform(anchor_B);
@@ -500,7 +500,7 @@ bool DampedSpringJoint2DSW::setup(float p_step) {
return true;
}
-void DampedSpringJoint2DSW::solve(float p_step) {
+void DampedSpringJoint2DSW::solve(real_t p_step) {
// compute relative velocity
real_t vrn = normal_relative_velocity(A, B, rA, rB, n) - target_vrn;
diff --git a/servers/physics_2d/joints_2d_sw.h b/servers/physics_2d/joints_2d_sw.h
index 86a1397c53..1be15e4edc 100644
--- a/servers/physics_2d/joints_2d_sw.h
+++ b/servers/physics_2d/joints_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -85,8 +85,8 @@ public:
virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_PIN; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
PinJoint2DSW(const Vector2& p_pos,Body2DSW* p_body_a,Body2DSW* p_body_b=NULL);
@@ -106,7 +106,7 @@ class PinJoint2DSW : public Joint2DSW {
Body2DSW *_arr[2];
};
- Matrix32 M;
+ Transform2D M;
Vector2 rA,rB;
Vector2 anchor_A;
Vector2 anchor_B;
@@ -118,8 +118,8 @@ public:
virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_PIN; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
void set_param(Physics2DServer::PinJointParam p_param, real_t p_value);
real_t get_param(Physics2DServer::PinJointParam p_param) const;
@@ -160,8 +160,8 @@ public:
virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_GROOVE; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
GrooveJoint2DSW(const Vector2& p_a_groove1,const Vector2& p_a_groove2, const Vector2& p_b_anchor, Body2DSW* p_body_a,Body2DSW* p_body_b);
@@ -198,8 +198,8 @@ public:
virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_DAMPED_SPRING; }
- virtual bool setup(float p_step);
- virtual void solve(float p_step);
+ virtual bool setup(real_t p_step);
+ virtual void solve(real_t p_step);
void set_param(Physics2DServer::DampedStringParam p_param, real_t p_value);
real_t get_param(Physics2DServer::DampedStringParam p_param) const;
diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp
index 8e92a475ab..920742ea0b 100644
--- a/servers/physics_2d/physics_2d_server_sw.cpp
+++ b/servers/physics_2d/physics_2d_server_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,7 +30,7 @@
#include "broad_phase_2d_basic.h"
#include "broad_phase_2d_hash_grid.h"
#include "collision_solver_2d_sw.h"
-#include "globals.h"
+#include "global_config.h"
#include "script_language.h"
#include "os/os.h"
@@ -158,11 +158,11 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2& p_point_A,const Vector2& p
if (cbk->amount == cbk->max) {
//find least deep
- float min_depth=1e20;
+ real_t min_depth=1e20;
int min_depth_idx=0;
for(int i=0;i<cbk->amount;i++) {
- float d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]);
+ real_t d = cbk->ptr[i*2+0].distance_squared_to(cbk->ptr[i*2+1]);
if (d<min_depth) {
min_depth=d;
min_depth_idx=i;
@@ -170,7 +170,7 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2& p_point_A,const Vector2& p
}
- float d = p_point_A.distance_squared_to(p_point_B);
+ real_t d = p_point_A.distance_squared_to(p_point_B);
if (d<min_depth)
return;
cbk->ptr[min_depth_idx*2+0]=p_point_A;
@@ -185,7 +185,7 @@ void Physics2DServerSW::_shape_col_cbk(const Vector2& p_point_A,const Vector2& p
}
}
-bool Physics2DServerSW::shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) {
+bool Physics2DServerSW::shape_collide(RID p_shape_A, const Transform2D& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Transform2D& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) {
Shape2DSW *shape_A = shape_owner.get(p_shape_A);
@@ -348,7 +348,7 @@ Physics2DServer::AreaSpaceOverrideMode Physics2DServerSW::area_get_space_overrid
}
-void Physics2DServerSW::area_add_shape(RID p_area, RID p_shape, const Matrix32& p_transform) {
+void Physics2DServerSW::area_add_shape(RID p_area, RID p_shape, const Transform2D& p_transform) {
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
@@ -372,7 +372,7 @@ void Physics2DServerSW::area_set_shape(RID p_area, int p_shape_idx,RID p_shape)
area->set_shape(p_shape_idx,shape);
}
-void Physics2DServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Matrix32& p_transform) {
+void Physics2DServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D& p_transform) {
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
@@ -398,10 +398,10 @@ RID Physics2DServerSW::area_get_shape(RID p_area, int p_shape_idx) const {
return shape->get_self();
}
-Matrix32 Physics2DServerSW::area_get_shape_transform(RID p_area, int p_shape_idx) const {
+Transform2D Physics2DServerSW::area_get_shape_transform(RID p_area, int p_shape_idx) const {
Area2DSW *area = area_owner.get(p_area);
- ERR_FAIL_COND_V(!area,Matrix32());
+ ERR_FAIL_COND_V(!area,Transform2D());
return area->get_shape_transform(p_shape_idx);
}
@@ -462,7 +462,7 @@ void Physics2DServerSW::area_set_param(RID p_area,AreaParameter p_param,const Va
};
-void Physics2DServerSW::area_set_transform(RID p_area, const Matrix32& p_transform) {
+void Physics2DServerSW::area_set_transform(RID p_area, const Transform2D& p_transform) {
Area2DSW *area = area_owner.get(p_area);
ERR_FAIL_COND(!area);
@@ -482,10 +482,10 @@ Variant Physics2DServerSW::area_get_param(RID p_area,AreaParameter p_param) cons
return area->get_param(p_param);
};
-Matrix32 Physics2DServerSW::area_get_transform(RID p_area) const {
+Transform2D Physics2DServerSW::area_get_transform(RID p_area) const {
Area2DSW *area = area_owner.get(p_area);
- ERR_FAIL_COND_V(!area,Matrix32());
+ ERR_FAIL_COND_V(!area,Transform2D());
return area->get_transform();
};
@@ -600,7 +600,7 @@ Physics2DServer::BodyMode Physics2DServerSW::body_get_mode(RID p_body) const {
return body->get_mode();
};
-void Physics2DServerSW::body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform) {
+void Physics2DServerSW::body_add_shape(RID p_body, RID p_shape, const Transform2D& p_transform) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -624,7 +624,7 @@ void Physics2DServerSW::body_set_shape(RID p_body, int p_shape_idx,RID p_shape)
body->set_shape(p_shape_idx,shape);
}
-void Physics2DServerSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Matrix32& p_transform) {
+void Physics2DServerSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D& p_transform) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -666,10 +666,10 @@ RID Physics2DServerSW::body_get_shape(RID p_body, int p_shape_idx) const {
return shape->get_self();
}
-Matrix32 Physics2DServerSW::body_get_shape_transform(RID p_body, int p_shape_idx) const {
+Transform2D Physics2DServerSW::body_get_shape_transform(RID p_body, int p_shape_idx) const {
Body2DSW *body = body_owner.get(p_body);
- ERR_FAIL_COND_V(!body,Matrix32());
+ ERR_FAIL_COND_V(!body,Transform2D());
return body->get_shape_transform(p_shape_idx);
}
@@ -785,7 +785,7 @@ uint32_t Physics2DServerSW::body_get_collision_mask(RID p_body) const {
return body->get_collision_mask();
};
-void Physics2DServerSW::body_set_param(RID p_body, BodyParameter p_param, float p_value) {
+void Physics2DServerSW::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -793,7 +793,7 @@ void Physics2DServerSW::body_set_param(RID p_body, BodyParameter p_param, float
body->set_param(p_param,p_value);
};
-float Physics2DServerSW::body_get_param(RID p_body, BodyParameter p_param) const {
+real_t Physics2DServerSW::body_get_param(RID p_body, BodyParameter p_param) const {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,0);
@@ -837,7 +837,7 @@ Vector2 Physics2DServerSW::body_get_applied_force(RID p_body) const {
return body->get_applied_force();
};
-void Physics2DServerSW::body_set_applied_torque(RID p_body, float p_torque) {
+void Physics2DServerSW::body_set_applied_torque(RID p_body, real_t p_torque) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -846,7 +846,7 @@ void Physics2DServerSW::body_set_applied_torque(RID p_body, float p_torque) {
body->wakeup();
};
-float Physics2DServerSW::body_get_applied_torque(RID p_body) const {
+real_t Physics2DServerSW::body_get_applied_torque(RID p_body) const {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,0);
@@ -915,14 +915,14 @@ void Physics2DServerSW::body_get_collision_exceptions(RID p_body, List<RID> *p_e
};
-void Physics2DServerSW::body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold) {
+void Physics2DServerSW::body_set_contacts_reported_depth_treshold(RID p_body, real_t p_treshold) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
};
-float Physics2DServerSW::body_get_contacts_reported_depth_treshold(RID p_body) const {
+real_t Physics2DServerSW::body_get_contacts_reported_depth_treshold(RID p_body) const {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,0);
@@ -973,7 +973,7 @@ Vector2 Physics2DServerSW::body_get_one_way_collision_direction(RID p_body) cons
}
-void Physics2DServerSW::body_set_one_way_collision_max_depth(RID p_body,float p_max_depth) {
+void Physics2DServerSW::body_set_one_way_collision_max_depth(RID p_body,real_t p_max_depth) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND(!body);
@@ -981,7 +981,7 @@ void Physics2DServerSW::body_set_one_way_collision_max_depth(RID p_body,float p_
}
-float Physics2DServerSW::body_get_one_way_collision_max_depth(RID p_body) const {
+real_t Physics2DServerSW::body_get_one_way_collision_max_depth(RID p_body) const {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,0);
@@ -998,7 +998,7 @@ void Physics2DServerSW::body_set_force_integration_callback(RID p_body,Object *p
}
-bool Physics2DServerSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count) {
+bool Physics2DServerSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,false);
@@ -1016,7 +1016,7 @@ void Physics2DServerSW::body_set_pickable(RID p_body,bool p_pickable) {
}
-bool Physics2DServerSW::body_test_motion(RID p_body, const Matrix32 &p_from, const Vector2& p_motion, float p_margin, MotionResult *r_result) {
+bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2& p_motion, real_t p_margin, MotionResult *r_result) {
Body2DSW *body = body_owner.get(p_body);
ERR_FAIL_COND_V(!body,false);
@@ -1176,11 +1176,13 @@ void Physics2DServerSW::free(RID p_rid) {
Body2DSW *body = body_owner.get(p_rid);
-// if (body->get_state_query())
-// _clear_query(body->get_state_query());
+ /*
+ if (body->get_state_query())
+ _clear_query(body->get_state_query());
-// if (body->get_direct_state_query())
-// _clear_query(body->get_direct_state_query());
+ if (body->get_direct_state_query())
+ _clear_query(body->get_direct_state_query());
+ */
body->set_space(NULL);
@@ -1203,8 +1205,10 @@ void Physics2DServerSW::free(RID p_rid) {
Area2DSW *area = area_owner.get(p_rid);
-// if (area->get_monitor_query())
-// _clear_query(area->get_monitor_query());
+ /*
+ if (area->get_monitor_query())
+ _clear_query(area->get_monitor_query());
+ */
area->set_space(NULL);
@@ -1259,7 +1263,7 @@ void Physics2DServerSW::init() {
};
-void Physics2DServerSW::step(float p_step) {
+void Physics2DServerSW::step(real_t p_step) {
if (!active)
@@ -1380,13 +1384,13 @@ Physics2DServerSW::Physics2DServerSW() {
singletonsw=this;
BroadPhase2DSW::create_func=BroadPhase2DHashGrid::_create;
-// BroadPhase2DSW::create_func=BroadPhase2DBasic::_create;
+ //BroadPhase2DSW::create_func=BroadPhase2DBasic::_create;
active=true;
island_count=0;
active_objects=0;
collision_pairs=0;
- using_threads=int(Globals::get_singleton()->get("physics_2d/thread_model"))==2;
+ using_threads=int(GlobalConfig::get_singleton()->get("physics/2d/thread_model"))==2;
};
diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h
index 1dc735289a..e33e2d78c7 100644
--- a/servers/physics_2d/physics_2d_server_sw.h
+++ b/servers/physics_2d/physics_2d_server_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -39,7 +39,7 @@
class Physics2DServerSW : public Physics2DServer {
- OBJ_TYPE( Physics2DServerSW, Physics2DServer );
+ GDCLASS( Physics2DServerSW, Physics2DServer );
friend class Physics2DDirectSpaceStateSW;
friend class Physics2DDirectBodyStateSW;
@@ -70,13 +70,13 @@ friend class Physics2DDirectBodyStateSW;
static Physics2DServerSW *singletonsw;
-// void _clear_query(Query2DSW *p_query);
+ //void _clear_query(Query2DSW *p_query);
public:
struct CollCbkData {
Vector2 valid_dir;
- float valid_depth;
+ real_t valid_depth;
int max;
int amount;
Vector2 *ptr;
@@ -93,7 +93,7 @@ public:
virtual Variant shape_get_data(RID p_shape) const;
virtual real_t shape_get_custom_solver_bias(RID p_shape) const;
- virtual bool shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count);
+ virtual bool shape_collide(RID p_shape_A, const Transform2D& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Transform2D& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count);
/* SPACE API */
@@ -123,13 +123,13 @@ public:
virtual void area_set_space(RID p_area, RID p_space);
virtual RID area_get_space(RID p_area) const;
- virtual void area_add_shape(RID p_area, RID p_shape, const Matrix32& p_transform=Matrix32());
+ virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D& p_transform=Transform2D());
virtual void area_set_shape(RID p_area, int p_shape_idx,RID p_shape);
- virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Matrix32& p_transform);
+ virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D& p_transform);
virtual int area_get_shape_count(RID p_area) const;
virtual RID area_get_shape(RID p_area, int p_shape_idx) const;
- virtual Matrix32 area_get_shape_transform(RID p_area, int p_shape_idx) const;
+ virtual Transform2D area_get_shape_transform(RID p_area, int p_shape_idx) const;
virtual void area_remove_shape(RID p_area, int p_shape_idx);
virtual void area_clear_shapes(RID p_area);
@@ -138,10 +138,10 @@ public:
virtual ObjectID area_get_object_instance_ID(RID p_area) const;
virtual void area_set_param(RID p_area,AreaParameter p_param,const Variant& p_value);
- virtual void area_set_transform(RID p_area, const Matrix32& p_transform);
+ virtual void area_set_transform(RID p_area, const Transform2D& p_transform);
virtual Variant area_get_param(RID p_parea,AreaParameter p_param) const;
- virtual Matrix32 area_get_transform(RID p_area) const;
+ virtual Transform2D area_get_transform(RID p_area) const;
virtual void area_set_monitorable(RID p_area,bool p_monitorable);
virtual void area_set_collision_mask(RID p_area,uint32_t p_mask);
virtual void area_set_layer_mask(RID p_area,uint32_t p_mask);
@@ -163,15 +163,15 @@ public:
virtual void body_set_mode(RID p_body, BodyMode p_mode);
virtual BodyMode body_get_mode(RID p_body) const;
- virtual void body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform=Matrix32());
+ virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D& p_transform=Transform2D());
virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape);
- virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Matrix32& p_transform);
+ virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D& p_transform);
virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant& p_metadata);
virtual int body_get_shape_count(RID p_body) const;
virtual RID body_get_shape(RID p_body, int p_shape_idx) const;
- virtual Matrix32 body_get_shape_transform(RID p_body, int p_shape_idx) const;
+ virtual Transform2D body_get_shape_transform(RID p_body, int p_shape_idx) const;
virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const;
@@ -193,8 +193,8 @@ public:
virtual void body_set_collision_mask(RID p_body, uint32_t p_mask);
virtual uint32_t body_get_collision_mask(RID p_) const;
- virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value);
- virtual float body_get_param(RID p_body, BodyParameter p_param) const;
+ virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value);
+ virtual real_t body_get_param(RID p_body, BodyParameter p_param) const;
virtual void body_set_state(RID p_body, BodyState p_state, const Variant& p_variant);
@@ -203,8 +203,8 @@ public:
virtual void body_set_applied_force(RID p_body, const Vector2& p_force);
virtual Vector2 body_get_applied_force(RID p_body) const;
- virtual void body_set_applied_torque(RID p_body, float p_torque);
- virtual float body_get_applied_torque(RID p_body) const;
+ virtual void body_set_applied_torque(RID p_body, real_t p_torque);
+ virtual real_t body_get_applied_torque(RID p_body) const;
virtual void body_add_force(RID p_body, const Vector2& p_offset, const Vector2& p_force);
@@ -215,8 +215,8 @@ public:
virtual void body_remove_collision_exception(RID p_body, RID p_body_b);
virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions);
- virtual void body_set_contacts_reported_depth_treshold(RID p_body, float p_treshold);
- virtual float body_get_contacts_reported_depth_treshold(RID p_body) const;
+ virtual void body_set_contacts_reported_depth_treshold(RID p_body, real_t p_treshold);
+ virtual real_t body_get_contacts_reported_depth_treshold(RID p_body) const;
virtual void body_set_omit_force_integration(RID p_body,bool p_omit);
virtual bool body_is_omitting_force_integration(RID p_body) const;
@@ -227,16 +227,16 @@ public:
virtual void body_set_one_way_collision_direction(RID p_body,const Vector2& p_direction);
virtual Vector2 body_get_one_way_collision_direction(RID p_body) const;
- virtual void body_set_one_way_collision_max_depth(RID p_body,float p_max_depth);
- virtual float body_get_one_way_collision_max_depth(RID p_body) const;
+ virtual void body_set_one_way_collision_max_depth(RID p_body,real_t p_max_depth);
+ virtual real_t body_get_one_way_collision_max_depth(RID p_body) const;
virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant());
- virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count);
+ virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count);
virtual void body_set_pickable(RID p_body,bool p_pickable);
- virtual bool body_test_motion(RID p_body,const Matrix32& p_from,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL);
+ virtual bool body_test_motion(RID p_body,const Transform2D& p_from,const Vector2& p_motion,real_t p_margin=0.001,MotionResult *r_result=NULL);
/* JOINT API */
@@ -260,7 +260,7 @@ public:
virtual void set_active(bool p_active);
virtual void init();
- virtual void step(float p_step);
+ virtual void step(real_t p_step);
virtual void sync();
virtual void flush_queries();
virtual void end_sync();
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp
index 3e8b284b9b..34ba149d23 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.cpp
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,7 +35,7 @@ void Physics2DServerWrapMT::thread_exit() {
exit=true;
}
-void Physics2DServerWrapMT::thread_step(float p_delta) {
+void Physics2DServerWrapMT::thread_step(real_t p_delta) {
physics_2d_server->step(p_delta);
step_sem->post();
@@ -75,7 +75,7 @@ void Physics2DServerWrapMT::thread_loop() {
/* EVENT QUEUING */
-void Physics2DServerWrapMT::step(float p_step) {
+void Physics2DServerWrapMT::step(real_t p_step) {
if (create_thread) {
@@ -95,7 +95,7 @@ void Physics2DServerWrapMT::sync() {
else
step_sem->wait(); //must not wait if a step was not issued
}
- physics_2d_server->sync();;
+ physics_2d_server->sync();
}
void Physics2DServerWrapMT::flush_queries(){
@@ -105,7 +105,7 @@ void Physics2DServerWrapMT::flush_queries(){
void Physics2DServerWrapMT::end_sync() {
- physics_2d_server->end_sync();;
+ physics_2d_server->end_sync();
}
void Physics2DServerWrapMT::init() {
@@ -168,12 +168,12 @@ Physics2DServerWrapMT::Physics2DServerWrapMT(Physics2DServer* p_contained,bool p
step_thread_up=false;
alloc_mutex=Mutex::create();
- shape_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20);
- area_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20);
- body_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20);
- pin_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20);
- groove_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20);
- damped_spring_joint_pool_max_size=GLOBAL_DEF("core/thread_rid_pool_prealloc",20);
+ shape_pool_max_size=GLOBAL_GET("memory/multithread/thread_rid_pool_prealloc");
+ area_pool_max_size=GLOBAL_GET("memory/multithread/thread_rid_pool_prealloc");
+ body_pool_max_size=GLOBAL_GET("memory/multithread/thread_rid_pool_prealloc");
+ pin_joint_pool_max_size=GLOBAL_GET("memory/multithread/thread_rid_pool_prealloc");
+ groove_joint_pool_max_size=GLOBAL_GET("memory/multithread/thread_rid_pool_prealloc");
+ damped_spring_joint_pool_max_size=GLOBAL_GET("memory/multithread/thread_rid_pool_prealloc");
if (!p_create_thread) {
server_thread=Thread::get_caller_ID();
diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h
index 57da958f9a..f8b533080e 100644
--- a/servers/physics_2d/physics_2d_server_wrap_mt.h
+++ b/servers/physics_2d/physics_2d_server_wrap_mt.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -33,7 +33,7 @@
#include "servers/physics_2d_server.h"
#include "command_queue_mt.h"
#include "os/thread.h"
-#include "globals.h"
+#include "global_config.h"
#ifdef DEBUG_SYNC
#define SYNC_DEBUG print_line("sync on: "+String(__FUNCTION__));
@@ -60,7 +60,7 @@ class Physics2DServerWrapMT : public Physics2DServer {
Semaphore *step_sem;
int step_pending;
- void thread_step(float p_delta);
+ void thread_step(real_t p_delta);
void thread_flush();
void thread_exit();
@@ -100,7 +100,7 @@ public:
//these work well, but should be used from the main thread only
- bool shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) {
+ bool shape_collide(RID p_shape_A, const Transform2D& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Transform2D& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count) {
ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),false);
return physics_2d_server->shape_collide(p_shape_A,p_xform_A,p_motion_A,p_shape_B,p_xform_B,p_motion_B,r_results,p_result_max,r_result_count);
@@ -150,13 +150,13 @@ public:
FUNC2(area_set_space_override_mode,RID,AreaSpaceOverrideMode);
FUNC1RC(AreaSpaceOverrideMode,area_get_space_override_mode,RID);
- FUNC3(area_add_shape,RID,RID,const Matrix32&);
+ FUNC3(area_add_shape,RID,RID,const Transform2D&);
FUNC3(area_set_shape,RID,int,RID);
- FUNC3(area_set_shape_transform,RID,int,const Matrix32&);
+ FUNC3(area_set_shape_transform,RID,int,const Transform2D&);
FUNC1RC(int,area_get_shape_count,RID);
FUNC2RC(RID,area_get_shape,RID,int);
- FUNC2RC(Matrix32,area_get_shape_transform,RID,int);
+ FUNC2RC(Transform2D,area_get_shape_transform,RID,int);
FUNC2(area_remove_shape,RID,int);
FUNC1(area_clear_shapes,RID);
@@ -164,10 +164,10 @@ public:
FUNC1RC(ObjectID,area_get_object_instance_ID,RID);
FUNC3(area_set_param,RID,AreaParameter,const Variant&);
- FUNC2(area_set_transform,RID,const Matrix32&);
+ FUNC2(area_set_transform,RID,const Transform2D&);
FUNC2RC(Variant,area_get_param,RID,AreaParameter);
- FUNC1RC(Matrix32,area_get_transform,RID);
+ FUNC1RC(Transform2D,area_get_transform,RID);
FUNC2(area_set_collision_mask,RID,uint32_t);
FUNC2(area_set_layer_mask,RID,uint32_t);
@@ -191,13 +191,13 @@ public:
FUNC1RC(BodyMode,body_get_mode,RID);
- FUNC3(body_add_shape,RID,RID,const Matrix32&);
+ FUNC3(body_add_shape,RID,RID,const Transform2D&);
FUNC3(body_set_shape,RID,int,RID);
- FUNC3(body_set_shape_transform,RID,int,const Matrix32&);
+ FUNC3(body_set_shape_transform,RID,int,const Transform2D&);
FUNC3(body_set_shape_metadata,RID,int,const Variant&);
FUNC1RC(int,body_get_shape_count,RID);
- FUNC2RC(Matrix32,body_get_shape_transform,RID,int);
+ FUNC2RC(Transform2D,body_get_shape_transform,RID,int);
FUNC2RC(Variant,body_get_shape_metadata,RID,int);
FUNC2RC(RID,body_get_shape,RID,int);
@@ -220,8 +220,8 @@ public:
FUNC1RC(uint32_t,body_get_collision_mask,RID);
- FUNC3(body_set_param,RID,BodyParameter,float);
- FUNC2RC(float,body_get_param,RID,BodyParameter);
+ FUNC3(body_set_param,RID,BodyParameter,real_t);
+ FUNC2RC(real_t,body_get_param,RID,BodyParameter);
FUNC3(body_set_state,RID,BodyState,const Variant&);
@@ -230,8 +230,8 @@ public:
FUNC2(body_set_applied_force,RID,const Vector2&);
FUNC1RC(Vector2,body_get_applied_force,RID);
- FUNC2(body_set_applied_torque,RID,float);
- FUNC1RC(float,body_get_applied_torque,RID);
+ FUNC2(body_set_applied_torque,RID,real_t);
+ FUNC1RC(real_t,body_get_applied_torque,RID);
FUNC3(body_add_force,RID,const Vector2&,const Vector2&);
FUNC3(body_apply_impulse,RID,const Vector2&,const Vector2&);
@@ -247,12 +247,12 @@ public:
FUNC2(body_set_one_way_collision_direction,RID,const Vector2&);
FUNC1RC(Vector2,body_get_one_way_collision_direction,RID);
- FUNC2(body_set_one_way_collision_max_depth,RID,float);
- FUNC1RC(float,body_get_one_way_collision_max_depth,RID);
+ FUNC2(body_set_one_way_collision_max_depth,RID,real_t);
+ FUNC1RC(real_t,body_get_one_way_collision_max_depth,RID);
- FUNC2(body_set_contacts_reported_depth_treshold,RID,float);
- FUNC1RC(float,body_get_contacts_reported_depth_treshold,RID);
+ FUNC2(body_set_contacts_reported_depth_treshold,RID,real_t);
+ FUNC1RC(real_t,body_get_contacts_reported_depth_treshold,RID);
FUNC2(body_set_omit_force_integration,RID,bool);
FUNC1RC(bool,body_is_omitting_force_integration,RID);
@@ -260,13 +260,13 @@ public:
FUNC4(body_set_force_integration_callback,RID ,Object *,const StringName& ,const Variant& );
- bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count) {
+ bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count) {
return physics_2d_server->body_collide_shape(p_body,p_body_shape,p_shape,p_shape_xform,p_motion,r_results,p_result_max,r_result_count);
}
FUNC2(body_set_pickable,RID,bool);
- bool body_test_motion(RID p_body,const Matrix32& p_from,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL) {
+ bool body_test_motion(RID p_body,const Transform2D& p_from,const Vector2& p_motion,real_t p_margin=0.001,MotionResult *r_result=NULL) {
ERR_FAIL_COND_V(main_thread!=Thread::get_caller_ID(),false);
return physics_2d_server->body_test_motion(p_body,p_from,p_motion,p_margin,r_result);
@@ -303,7 +303,7 @@ public:
FUNC1(set_active,bool);
virtual void init();
- virtual void step(float p_step);
+ virtual void step(real_t p_step);
virtual void sync();
virtual void end_sync();
virtual void flush_queries();
@@ -320,7 +320,7 @@ public:
template<class T>
static Physics2DServer* init_server() {
- int tm = GLOBAL_DEF("physics_2d/thread_model",1);
+ int tm = GLOBAL_DEF("physics/2d/thread_model",1);
if (tm==0) //single unsafe
return memnew( T );
else if (tm==1) //single saef
diff --git a/servers/physics_2d/shape_2d_sw.cpp b/servers/physics_2d/shape_2d_sw.cpp
index 9291aa6c17..b6eb427131 100644
--- a/servers/physics_2d/shape_2d_sw.cpp
+++ b/servers/physics_2d/shape_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -136,7 +136,7 @@ bool LineShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_en
return true;
}
-real_t LineShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const {
+real_t LineShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
return 0;
}
@@ -191,7 +191,7 @@ bool RayShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end
}
-real_t RayShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const {
+real_t RayShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
return 0; //rays are mass-less
}
@@ -224,7 +224,7 @@ void SegmentShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,
}
- float dp=p_normal.dot(b-a);
+ real_t dp=p_normal.dot(b-a);
if (dp>0)
*r_supports=b;
else
@@ -252,14 +252,14 @@ bool SegmentShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p
return true;
}
-real_t SegmentShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const {
+real_t SegmentShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
Vector2 s[2]={a*p_scale,b*p_scale};
real_t l = s[1].distance_to(s[0]);
Vector2 ofs = (s[0]+s[1])*0.5;
- return p_mass*(l*l/12.0f + ofs.length_squared());
+ return p_mass*(l*l/12.0 + ofs.length_squared());
}
void SegmentShape2DSW::set_data(const Variant& p_data) {
@@ -336,7 +336,7 @@ bool CircleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_
return true;
}
-real_t CircleShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const {
+real_t CircleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
return (radius*radius)*(p_scale.x*0.5+p_scale.y*0.5);
@@ -367,11 +367,11 @@ void RectangleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_support
Vector2 ag;
ag[i]=1.0;
- float dp = ag.dot(p_normal);
+ real_t dp = ag.dot(p_normal);
if (Math::abs(dp)<_SEGMENT_IS_VALID_SUPPORT_TRESHOLD)
continue;
- float sgn = dp>0 ? 1.0 : -1.0;
+ real_t sgn = dp>0 ? 1.0 : -1.0;
r_amount=2;
@@ -407,10 +407,10 @@ bool RectangleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2&
return get_aabb().intersects_segment(p_begin,p_end,&r_point,&r_normal);
}
-real_t RectangleShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const {
+real_t RectangleShape2DSW::get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const {
Vector2 he2=half_extents*2*p_scale;
- return p_mass*he2.dot(he2)/12.0f;
+ return p_mass*he2.dot(he2)/12.0;
}
void RectangleShape2DSW::set_data(const Variant& p_data) {
@@ -438,7 +438,7 @@ void CapsuleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,
Vector2 n=p_normal;
- float d = n.y;
+ real_t d = n.y;
if (Math::abs( d )<(1.0-_SEGMENT_IS_VALID_SUPPORT_TRESHOLD) ) {
@@ -455,7 +455,7 @@ void CapsuleShape2DSW::get_supports(const Vector2& p_normal,Vector2 *r_supports,
} else {
- float h = (d > 0) ? height : -height;
+ real_t h = (d > 0) ? height : -height;
n*=radius;
n.y += h*0.5;
@@ -479,7 +479,7 @@ bool CapsuleShape2DSW::contains_point(const Vector2& p_point) const {
bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const {
- float d = 1e10;
+ real_t d = 1e10;
Vector2 n = (p_end-p_begin).normalized();
bool collided=false;
@@ -488,7 +488,7 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p
Vector2 begin = p_begin;
Vector2 end = p_end;
- float ofs = (i==0)?-height*0.5:height*0.5;
+ real_t ofs = (i==0)?-height*0.5:height*0.5;
begin.y+=ofs;
end.y+=ofs;
@@ -540,10 +540,10 @@ bool CapsuleShape2DSW::intersect_segment(const Vector2& p_begin,const Vector2& p
return collided; //todo
}
-real_t CapsuleShape2DSW::get_moment_of_inertia(float p_mass, const Vector2 &p_scale) const {
+real_t CapsuleShape2DSW::get_moment_of_inertia(real_t p_mass, const Size2 &p_scale) const {
Vector2 he2=Vector2(radius*2,height+radius*2)*p_scale;
- return p_mass*he2.dot(he2)/12.0f;
+ return p_mass*he2.dot(he2)/12.0;
}
void CapsuleShape2DSW::set_data(const Variant& p_data) {
@@ -619,7 +619,7 @@ bool ConvexPolygonShape2DSW::contains_point(const Vector2& p_point) const {
for(int i=0;i<point_count;i++) {
- float d = points[i].normal.dot(p_point) - points[i].normal.dot(points[i].pos);
+ real_t d = points[i].normal.dot(p_point) - points[i].normal.dot(points[i].pos);
if (d>0)
out=true;
else
@@ -639,8 +639,10 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vect
for(int i=0;i<point_count;i++) {
//hmm crap.. no can do..
- //if (d.dot(points[i].normal)>=0)
- // continue;
+ /*
+ if (d.dot(points[i].normal)>=0)
+ continue;
+ */
Vector2 res;
@@ -648,7 +650,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vect
if (!Geometry::segment_intersects_segment_2d(p_begin,p_end,points[i].pos,points[(i+1)%point_count].pos,&res))
continue;
- float nd = n.dot(res);
+ real_t nd = n.dot(res);
if (nd<d) {
d=nd;
@@ -670,7 +672,7 @@ bool ConvexPolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vect
return inters; //todo
}
-real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass,const Vector2& p_scale) const {
+real_t ConvexPolygonShape2DSW::get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const {
Rect2 aabb;
aabb.pos=points[0].pos*p_scale;
@@ -679,12 +681,12 @@ real_t ConvexPolygonShape2DSW::get_moment_of_inertia(float p_mass,const Vector2&
aabb.expand_to(points[i].pos*p_scale);
}
- return p_mass*aabb.size.dot(aabb.size)/12.0f + p_mass * (aabb.pos+aabb.size*0.5).length_squared();
+ return p_mass*aabb.size.dot(aabb.size)/12.0 + p_mass * (aabb.pos+aabb.size*0.5).length_squared();
}
void ConvexPolygonShape2DSW::set_data(const Variant& p_data) {
- ERR_FAIL_COND(p_data.get_type()!=Variant::VECTOR2_ARRAY && p_data.get_type()!=Variant::REAL_ARRAY);
+ ERR_FAIL_COND(p_data.get_type()!=Variant::POOL_VECTOR2_ARRAY && p_data.get_type()!=Variant::POOL_REAL_ARRAY);
if (points)
@@ -692,12 +694,12 @@ void ConvexPolygonShape2DSW::set_data(const Variant& p_data) {
points=NULL;
point_count=0;
- if (p_data.get_type()==Variant::VECTOR2_ARRAY) {
- DVector<Vector2> arr=p_data;
+ if (p_data.get_type()==Variant::POOL_VECTOR2_ARRAY) {
+ PoolVector<Vector2> arr=p_data;
ERR_FAIL_COND(arr.size()==0);
point_count=arr.size();
points = memnew_arr(Point,point_count);
- DVector<Vector2>::Read r = arr.read();
+ PoolVector<Vector2>::Read r = arr.read();
for(int i=0;i<point_count;i++) {
points[i].pos=r[i];
@@ -711,12 +713,12 @@ void ConvexPolygonShape2DSW::set_data(const Variant& p_data) {
}
} else {
- DVector<real_t> dvr = p_data;
+ PoolVector<real_t> dvr = p_data;
point_count=dvr.size()/4;
ERR_FAIL_COND(point_count==0);
points = memnew_arr(Point,point_count);
- DVector<real_t>::Read r = dvr.read();
+ PoolVector<real_t>::Read r = dvr.read();
for(int i=0;i<point_count;i++) {
@@ -741,7 +743,7 @@ void ConvexPolygonShape2DSW::set_data(const Variant& p_data) {
Variant ConvexPolygonShape2DSW::get_data() const {
- DVector<Vector2> dvr;
+ PoolVector<Vector2> dvr;
dvr.resize(point_count);
@@ -816,8 +818,10 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vec
real_t d=1e10;
bool inters=false;
- //for(int i=0;i<bvh_depth;i++)
- // stack[i]=0;
+ /*
+ for(int i=0;i<bvh_depth;i++)
+ stack[i]=0;
+ */
int level=0;
@@ -855,7 +859,7 @@ bool ConcavePolygonShape2DSW::intersect_segment(const Vector2& p_begin,const Vec
if (Geometry::segment_intersects_segment_2d(p_begin,p_end,a,b,&res)) {
- float nd = n.dot(res);
+ real_t nd = n.dot(res);
if (nd<d) {
d=nd;
@@ -964,13 +968,13 @@ int ConcavePolygonShape2DSW::_generate_bvh(BVH *p_bvh,int p_len,int p_depth) {
void ConcavePolygonShape2DSW::set_data(const Variant& p_data) {
- ERR_FAIL_COND(p_data.get_type()!=Variant::VECTOR2_ARRAY && p_data.get_type()!=Variant::REAL_ARRAY);
+ ERR_FAIL_COND(p_data.get_type()!=Variant::POOL_VECTOR2_ARRAY && p_data.get_type()!=Variant::POOL_REAL_ARRAY);
Rect2 aabb;
- if (p_data.get_type()==Variant::VECTOR2_ARRAY) {
+ if (p_data.get_type()==Variant::POOL_VECTOR2_ARRAY) {
- DVector<Vector2> p2arr = p_data;
+ PoolVector<Vector2> p2arr = p_data;
int len = p2arr.size();
ERR_FAIL_COND(len%2);
@@ -984,7 +988,7 @@ void ConcavePolygonShape2DSW::set_data(const Variant& p_data) {
return;
}
- DVector<Vector2>::Read arr = p2arr.read();
+ PoolVector<Vector2>::Read arr = p2arr.read();
Map<Point2,int> pointmap;
for(int i=0;i<len;i+=2) {
@@ -1046,17 +1050,17 @@ void ConcavePolygonShape2DSW::set_data(const Variant& p_data) {
Variant ConcavePolygonShape2DSW::get_data() const {
- DVector<Vector2> rsegments;
+ PoolVector<Vector2> rsegments;
int len = segments.size();
rsegments.resize(len*2);
- DVector<Vector2>::Write w = rsegments.write();
+ PoolVector<Vector2>::Write w = rsegments.write();
for(int i=0;i<len;i++) {
w[(i<<1)+0]=points[segments[i].points[0]];
w[(i<<1)+1]=points[segments[i].points[1]];
}
- w=DVector<Vector2>::Write();
+ w=PoolVector<Vector2>::Write();
return rsegments;
}
@@ -1077,8 +1081,10 @@ void ConcavePolygonShape2DSW::cull(const Rect2& p_local_aabb,Callback p_callback
};
- //for(int i=0;i<bvh_depth;i++)
- // stack[i]=0;
+ /*
+ for(int i=0;i<bvh_depth;i++)
+ stack[i]=0;
+ */
int level=0;
diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h
index 4164896696..c04cdfa456 100644
--- a/servers/physics_2d/shape_2d_sw.h
+++ b/servers/physics_2d/shape_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -35,8 +35,8 @@
/*
SHAPE_LINE, ///< plane:"plane"
-SHAPE_SEGMENT, ///< float:"length"
-SHAPE_CIRCLE, ///< float:"radius"
+SHAPE_SEGMENT, ///< real_t:"length"
+SHAPE_CIRCLE, ///< real_t:"radius"
SHAPE_RECTANGLE, ///< vec3:"extents"
SHAPE_CONVEX_POLYGON, ///< array of planes:"planes"
SHAPE_CONCAVE_POLYGON, ///< Vector2 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector2 array)
@@ -46,7 +46,7 @@ SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_creat
class Shape2DSW;
-class ShapeOwner2DSW {
+class ShapeOwner2DSW : public RID_Data{
public:
virtual void _shape_changed()=0;
@@ -55,7 +55,7 @@ public:
virtual ~ShapeOwner2DSW() {}
};
-class Shape2DSW {
+class Shape2DSW : public RID_Data {
RID self;
Rect2 aabb;
@@ -80,13 +80,13 @@ public:
virtual bool contains_point(const Vector2& p_point) const=0;
- virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const=0;
- virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const=0;
+ virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const=0;
+ virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const=0;
virtual Vector2 get_support(const Vector2& p_normal) const;
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const=0;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const=0;
- virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const=0;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const=0;
virtual void set_data(const Variant& p_data)=0;
virtual Variant get_data() const=0;
@@ -99,7 +99,7 @@ public:
const Map<ShapeOwner2DSW*,int>& get_owners() const;
- _FORCE_INLINE_ void get_supports_transformed_cast(const Vector2& p_cast,const Vector2& p_normal,const Matrix32& p_xform,Vector2 *r_supports,int & r_amount) const {
+ _FORCE_INLINE_ void get_supports_transformed_cast(const Vector2& p_cast,const Vector2& p_normal,const Transform2D& p_xform,Vector2 *r_supports,int & r_amount) const {
get_supports(p_xform.basis_xform_inv(p_normal).normalized(),r_supports,r_amount);
for(int i=0;i<r_amount;i++)
@@ -142,14 +142,14 @@ public:
//let the optimizer do the magic
#define DEFAULT_PROJECT_RANGE_CAST \
-virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {\
+virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {\
project_range_cast(p_cast,p_normal,p_transform,r_min,r_max);\
}\
-_FORCE_INLINE_ void project_range_cast(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {\
+_FORCE_INLINE_ void project_range_cast(const Vector2& p_cast, const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {\
\
real_t mina,maxa;\
real_t minb,maxb;\
- Matrix32 ofsb=p_transform;\
+ Transform2D ofsb=p_transform;\
ofsb.elements[2]+=p_cast;\
project_range(p_normal,p_transform,mina,maxa);\
project_range(p_normal,ofsb,minb,maxb); \
@@ -170,27 +170,27 @@ public:
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_LINE; }
- virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
+ virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
- _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
+ _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {
//real large
r_min=-1e10;
r_max=1e10;
}
- virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
+ virtual void project_range_castv(const Vector2& p_cast, const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {
project_range_cast(p_cast,p_normal,p_transform,r_min,r_max);
}
- _FORCE_INLINE_ void project_range_cast(const Vector2& p_cast, const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
+ _FORCE_INLINE_ void project_range_cast(const Vector2& p_cast, const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {
//real large
r_min=-1e10;
r_max=1e10;
@@ -213,17 +213,17 @@ public:
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_RAY; }
- virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
+ virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
- _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
+ _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {
//real large
r_max = p_normal.dot(p_transform.get_origin());
r_min = p_normal.dot(p_transform.xform(Vector2(0,length)));
@@ -257,21 +257,21 @@ public:
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_SEGMENT; }
- _FORCE_INLINE_ Vector2 get_xformed_normal(const Matrix32& p_xform) const {
+ _FORCE_INLINE_ Vector2 get_xformed_normal(const Transform2D& p_xform) const {
return (p_xform.xform(b) - p_xform.xform(a)).normalized().tangent();
}
- virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
+ virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
- _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
+ _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {
//real large
r_max = p_normal.dot(p_transform.xform(a));
r_min = p_normal.dot(p_transform.xform(b));
@@ -299,17 +299,17 @@ public:
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CIRCLE; }
- virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
+ virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
- _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
+ _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {
//real large
real_t d = p_normal.dot( p_transform.get_origin() );
@@ -339,17 +339,17 @@ public:
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_RECTANGLE; }
- virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
+ virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
- _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
+ _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {
// no matter the angle, the box is mirrored anyway
r_max=-1e20;
r_min=1e20;
@@ -367,7 +367,7 @@ public:
- _FORCE_INLINE_ Vector2 get_circle_axis(const Matrix32& p_xform, const Matrix32& p_xform_inv,const Vector2& p_circle) const {
+ _FORCE_INLINE_ Vector2 get_circle_axis(const Transform2D& p_xform, const Transform2D& p_xform_inv,const Vector2& p_circle) const {
Vector2 local_v = p_xform_inv.xform(p_circle);
@@ -379,7 +379,7 @@ public:
return (p_xform.xform(he)-p_circle).normalized();
}
- _FORCE_INLINE_ Vector2 get_box_axis(const Matrix32& p_xform, const Matrix32& p_xform_inv,const RectangleShape2DSW *p_B,const Matrix32& p_B_xform, const Matrix32& p_B_xform_inv) const {
+ _FORCE_INLINE_ Vector2 get_box_axis(const Transform2D& p_xform, const Transform2D& p_xform_inv,const RectangleShape2DSW *p_B,const Transform2D& p_B_xform, const Transform2D& p_B_xform_inv) const {
Vector2 a,b;
@@ -427,20 +427,20 @@ public:
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CAPSULE; }
- virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
+ virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
- _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
+ _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {
// no matter the angle, the box is mirrored anyway
Vector2 n=p_transform.basis_xform_inv(p_normal).normalized();
- float h = (n.y > 0) ? height : -height;
+ real_t h = (n.y > 0) ? height : -height;
n *= radius;
n.y += h * 0.5;
@@ -480,7 +480,7 @@ public:
_FORCE_INLINE_ int get_point_count() const { return point_count; }
_FORCE_INLINE_ const Vector2& get_point(int p_idx) const { return points[p_idx].pos; }
_FORCE_INLINE_ const Vector2& get_segment_normal(int p_idx) const { return points[p_idx].normal; }
- _FORCE_INLINE_ Vector2 get_xformed_segment_normal(const Matrix32& p_xform, int p_idx) const {
+ _FORCE_INLINE_ Vector2 get_xformed_segment_normal(const Transform2D& p_xform, int p_idx) const {
Vector2 a = points[p_idx].pos;
p_idx++;
@@ -490,23 +490,23 @@ public:
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CONVEX_POLYGON; }
- virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
+ virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal,p_transform,r_min,r_max); }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const;
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const;
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
- _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const {
+ _FORCE_INLINE_ void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const {
// no matter the angle, the box is mirrored anyway
r_min = r_max = p_normal.dot(p_transform.xform(points[0].pos));
for(int i=1;i<point_count;i++) {
- float d = p_normal.dot(p_transform.xform(points[i].pos));
+ real_t d = p_normal.dot(p_transform.xform(points[i].pos));
if (d>r_max)
r_max=d;
if (d<r_min)
@@ -577,14 +577,14 @@ public:
virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CONCAVE_POLYGON; }
- virtual void project_rangev(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ }
- virtual void project_range(const Vector2& p_normal, const Matrix32& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ }
+ virtual void project_rangev(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ }
+ virtual void project_range(const Vector2& p_normal, const Transform2D& p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ }
virtual void get_supports(const Vector2& p_normal,Vector2 *r_supports,int & r_amount) const;
virtual bool contains_point(const Vector2& p_point) const;
virtual bool intersect_segment(const Vector2& p_begin,const Vector2& p_end,Vector2 &r_point, Vector2 &r_normal) const;
- virtual real_t get_moment_of_inertia(float p_mass,const Vector2& p_scale) const { return 0; }
+ virtual real_t get_moment_of_inertia(real_t p_mass,const Size2& p_scale) const { return 0; }
virtual void set_data(const Variant& p_data);
virtual Variant get_data() const;
diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp
index d0dcee7763..9bced50061 100644
--- a/servers/physics_2d/space_2d_sw.cpp
+++ b/servers/physics_2d/space_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -81,6 +81,9 @@ int Physics2DDirectSpaceStateSW::intersect_point(const Vector2& p_point,ShapeRes
if (!shape->contains_point(local_point))
continue;
+ if (cc>=p_result_max)
+ continue;
+
r_results[cc].collider_id=col_obj->get_instance_id();
if (r_results[cc].collider_id!=0)
r_results[cc].collider=ObjectDB::get_instance(r_results[cc].collider_id);
@@ -130,7 +133,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec
const CollisionObject2DSW *col_obj=space->intersection_query_results[i];
int shape_idx=space->intersection_query_subindex_results[i];
- Matrix32 inv_xform = col_obj->get_shape_inv_transform(shape_idx) * col_obj->get_inv_transform();
+ Transform2D inv_xform = col_obj->get_shape_inv_transform(shape_idx) * col_obj->get_inv_transform();
Vector2 local_from = inv_xform.xform(begin);
Vector2 local_to = inv_xform.xform(end);
@@ -150,7 +153,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec
- Matrix32 xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+ Transform2D xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
shape_point=xform.xform(shape_point);
real_t ld = normal.dot(shape_point);
@@ -187,7 +190,7 @@ bool Physics2DDirectSpaceStateSW::intersect_ray(const Vector2& p_from, const Vec
}
-int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,real_t p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
if (p_result_max<=0)
return 0;
@@ -234,7 +237,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID& p_shape, const Matri
-bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,real_t p_margin,real_t &p_closest_safe,real_t &p_closest_unsafe, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
@@ -245,13 +248,15 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32
aabb=aabb.merge(Rect2(aabb.pos+p_motion,aabb.size)); //motion
aabb=aabb.grow(p_margin);
- //if (p_motion!=Vector2())
- // print_line(p_motion);
+ /*
+ if (p_motion!=Vector2())
+ print_line(p_motion);
+ */
int amount = space->broadphase->cull_aabb(aabb,space->intersection_query_results,Space2DSW::INTERSECTION_QUERY_MAX,space->intersection_query_subindex_results);
- float best_safe=1;
- float best_unsafe=1;
+ real_t best_safe=1;
+ real_t best_unsafe=1;
for(int i=0;i<amount;i++) {
@@ -277,7 +282,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32
}*/
- Matrix32 col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+ Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
if (!CollisionSolver2DSW::solve(shape,p_xform,p_motion,col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,p_margin)) {
continue;
@@ -300,13 +305,13 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32
//just do kinematic solving
- float low=0;
- float hi=1;
+ real_t low=0;
+ real_t hi=1;
Vector2 mnormal=p_motion.normalized();
for(int i=0;i<8;i++) { //steps should be customizable..
- float ofs = (low+hi)*0.5;
+ real_t ofs = (low+hi)*0.5;
Vector2 sep=mnormal; //important optimization for this to work fast enough
bool collided = CollisionSolver2DSW::solve(shape,p_xform,p_motion*ofs,col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),NULL,NULL,&sep,p_margin);
@@ -359,7 +364,7 @@ bool Physics2DDirectSpaceStateSW::cast_motion(const RID& p_shape, const Matrix32
}
-bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,real_t p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
if (p_result_max<=0)
@@ -431,9 +436,9 @@ struct _RestCallbackData2D {
int best_shape;
Vector2 best_contact;
Vector2 best_normal;
- float best_len;
+ real_t best_len;
Vector2 valid_dir;
- float valid_depth;
+ real_t valid_depth;
};
static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,void *p_userdata) {
@@ -453,7 +458,7 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v
}
Vector2 contact_rel = p_point_B - p_point_A;
- float len = contact_rel.length();
+ real_t len = contact_rel.length();
if (len <= rd->best_len)
return;
@@ -468,7 +473,7 @@ static void _rest_cbk_result(const Vector2& p_point_A,const Vector2& p_point_B,v
}
-bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
+bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,real_t p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude,uint32_t p_layer_mask,uint32_t p_object_type_mask) {
Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.get(p_shape);
@@ -589,7 +594,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body,const Rect2& p_aabb) {
return amount;
}
-bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const Vector2&p_motion, float p_margin, Physics2DServer::MotionResult *r_result) {
+bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2&p_motion, real_t p_margin, Physics2DServer::MotionResult *r_result) {
//give me back regular physics engine logic
//this is madness
@@ -615,7 +620,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
body_aabb=body_aabb.grow(p_margin);
- Matrix32 body_transform = p_from;
+ Transform2D body_transform = p_from;
+
{
//STEP 1, FREE BODY IF STUCK
@@ -640,13 +646,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
bool collided=false;
+
int amount = _cull_aabb_for_body(p_body,body_aabb);
for(int j=0;j<p_body->get_shape_count();j++) {
if (p_body->is_shape_set_as_trigger(j))
continue;
- Matrix32 body_shape_xform = body_transform * p_body->get_shape_transform(j);
+ Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j);
Shape2DSW *body_shape = p_body->get_shape(j);
for(int i=0;i<amount;i++) {
@@ -658,8 +665,10 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
const Body2DSW *body=static_cast<const Body2DSW*>(col_obj);
Vector2 cdir = body->get_one_way_collision_direction();
- //if (cdir!=Vector2() && p_motion.dot(cdir)<0)
- // continue;
+ /*
+ if (cdir!=Vector2() && p_motion.dot(cdir)<0)
+ continue;
+ */
cbk.valid_dir=cdir;
cbk.valid_depth=body->get_one_way_collision_max_depth();
@@ -675,11 +684,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
}
- if (!collided)
+ if (!collided) {
break;
+ }
Vector2 recover_motion;
+
for(int i=0;i<cbk.amount;i++) {
Vector2 a = sr[i*2+0];
@@ -687,19 +698,18 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
#if 0
Vector2 rel = b-a;
- float d = rel.length();
+ real_t d = rel.length();
if (d==0)
continue;
Vector2 n = rel/d;
- float traveled = n.dot(recover_motion);
+ real_t traveled = n.dot(recover_motion);
a+=n*traveled;
+ real_t d = a.distance_to(b);
+ if (d<margin)
+ continue;
#endif
- // float d = a.distance_to(b);
-
- //if (d<margin)
- /// continue;
recover_motion+=(b-a)*0.4;
}
@@ -718,8 +728,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
- float safe = 1.0;
- float unsafe = 1.0;
+ real_t safe = 1.0;
+ real_t unsafe = 1.0;
int best_shape=-1;
{
@@ -736,13 +746,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
if (p_body->is_shape_set_as_trigger(j))
continue;
- Matrix32 body_shape_xform = body_transform * p_body->get_shape_transform(j);
+ Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j);
Shape2DSW *body_shape = p_body->get_shape(j);
bool stuck=false;
- float best_safe=1;
- float best_unsafe=1;
+ real_t best_safe=1;
+ real_t best_unsafe=1;
for(int i=0;i<amount;i++) {
@@ -750,7 +760,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
int shape_idx=intersection_query_subindex_results[i];
- Matrix32 col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
+ Transform2D col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx);
//test initial overlap, does it collide if going all the way?
if (!CollisionSolver2DSW::solve(body_shape,body_shape_xform,p_motion,col_obj->get_shape(shape_idx),col_obj_xform,Vector2() ,NULL,NULL,NULL,0)) {
continue;
@@ -774,13 +784,13 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
//just do kinematic solving
- float low=0;
- float hi=1;
+ real_t low=0;
+ real_t hi=1;
Vector2 mnormal=p_motion.normalized();
for(int i=0;i<8;i++) { //steps should be customizable..
- float ofs = (low+hi)*0.5;
+ real_t ofs = (low+hi)*0.5;
Vector2 sep=mnormal; //important optimization for this to work fast enough
bool collided = CollisionSolver2DSW::solve(body_shape,body_shape_xform,p_motion*ofs,col_obj->get_shape(shape_idx),col_obj_xform,Vector2(),NULL,NULL,&sep,0);
@@ -849,14 +859,14 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
if (r_result) {
r_result->motion=p_motion;
- r_result->remainder=Vector2();
- r_result->motion+=(body_transform.elements[2]-p_from.elements[2]);
+ r_result->remainder=Vector2();
+ r_result->motion+=(body_transform.get_origin()-p_from.get_origin());
}
} else {
//it collided, let's get the rest info in unsafe advance
- Matrix32 ugt = body_transform;
+ Transform2D ugt = body_transform;
ugt.elements[2]+=p_motion*unsafe;
_RestCallbackData2D rcd;
@@ -864,7 +874,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
rcd.best_object=NULL;
rcd.best_shape=0;
- Matrix32 body_shape_xform = ugt * p_body->get_shape_transform(best_shape);
+ Transform2D body_shape_xform = ugt * p_body->get_shape_transform(best_shape);
Shape2DSW *body_shape = p_body->get_shape(best_shape);
body_aabb.pos+=p_motion*unsafe;
@@ -913,7 +923,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
r_result->motion=safe*p_motion;
r_result->remainder=p_motion - safe * p_motion;
- r_result->motion+=(body_transform.elements[2]-p_from.elements[2]);
+ r_result->motion+=(body_transform.get_origin()-p_from.get_origin());
}
@@ -923,7 +933,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
r_result->motion=p_motion;
r_result->remainder=Vector2();
- r_result->motion+=(body_transform.elements[2]-p_from.elements[2]);
+ r_result->motion+=(body_transform.get_origin()-p_from.get_origin());
}
collided=false;
@@ -969,7 +979,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
if (collide_character)
mask|=Physics2DDirectSpaceState::TYPE_MASK_CHARACTER_BODY;
-// print_line("motion: "+p_motion+" margin: "+rtos(margin));
+ //print_line("motion: "+p_motion+" margin: "+rtos(margin));
//print_line("margin: "+rtos(margin));
do {
@@ -994,10 +1004,12 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
Vector2 a = sr[i*2+0];
Vector2 b = sr[i*2+1];
- float d = a.distance_to(b);
+ real_t d = a.distance_to(b);
- //if (d<margin)
- /// continue;
+ /*
+ if (d<margin)
+ continue;
+ */
recover_motion+=(b-a)*0.4;
}
@@ -1016,8 +1028,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
//move second
- float safe = 1.0;
- float unsafe = 1.0;
+ real_t safe = 1.0;
+ real_t unsafe = 1.0;
int best_shape=-1;
for(int i=0;i<get_shape_count();i++) {
@@ -1025,7 +1037,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const
if (is_shape_set_as_trigger(i))
continue;
- float lsafe,lunsafe;
+ real_t lsafe,lunsafe;
bool valid = dss->cast_motion(get_shape(i)->get_rid(), get_global_transform() * get_shape_transform(i), p_motion, 0,lsafe,lunsafe,exclude,get_layer_mask(),mask);
//print_line("shape: "+itos(i)+" travel:"+rtos(ltravel));
if (!valid) {
@@ -1321,14 +1333,14 @@ Space2DSW::Space2DSW() {
contact_debug_count=0;
locked=false;
- contact_recycle_radius=0.01;
- contact_max_separation=0.05;
- contact_max_allowed_penetration= 0.01;
-
- constraint_bias = 0.01;
- body_linear_velocity_sleep_treshold=0.01;
- body_angular_velocity_sleep_treshold=(8.0 / 180.0 * Math_PI);
- body_time_to_sleep=0.5;
+ contact_recycle_radius=1.0;
+ contact_max_separation=1.5;
+ contact_max_allowed_penetration= 0.3;
+
+ constraint_bias = 0.2;
+ body_linear_velocity_sleep_treshold=GLOBAL_DEF("physics/2d/sleep_threashold_linear",2.0);
+ body_angular_velocity_sleep_treshold=GLOBAL_DEF("physics/2d/sleep_threshold_angular",(8.0 / 180.0 * Math_PI));
+ body_time_to_sleep=GLOBAL_DEF("physics/2d/time_before_sleep",0.5);
broadphase = BroadPhase2DSW::create_func();
diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h
index f58e8c3fe7..071aa7bdfb 100644
--- a/servers/physics_2d/space_2d_sw.h
+++ b/servers/physics_2d/space_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,28 +37,29 @@
#include "area_pair_2d_sw.h"
#include "broad_phase_2d_sw.h"
#include "collision_object_2d_sw.h"
+#include "global_config.h"
class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState {
- OBJ_TYPE( Physics2DDirectSpaceStateSW, Physics2DDirectSpaceState );
+ GDCLASS( Physics2DDirectSpaceStateSW, Physics2DDirectSpaceState );
public:
Space2DSW *space;
virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION, bool p_pick_point=false);
virtual bool intersect_ray(const Vector2& p_from, const Vector2& p_to,RayResult &r_result,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
- virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
- virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
- virtual bool collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
- virtual bool rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
+ virtual int intersect_shape(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,real_t p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
+ virtual bool cast_motion(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,real_t p_margin,real_t &p_closest_safe,real_t &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
+ virtual bool collide_shape(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,real_t p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
+ virtual bool rest_info(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,real_t p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
Physics2DDirectSpaceStateSW();
};
-class Space2DSW {
+class Space2DSW : public RID_Data {
public:
@@ -105,9 +106,9 @@ private:
CollisionObject2DSW *intersection_query_results[INTERSECTION_QUERY_MAX];
int intersection_query_subindex_results[INTERSECTION_QUERY_MAX];
- float body_linear_velocity_sleep_treshold;
- float body_angular_velocity_sleep_treshold;
- float body_time_to_sleep;
+ real_t body_linear_velocity_sleep_treshold;
+ real_t body_angular_velocity_sleep_treshold;
+ real_t body_time_to_sleep;
bool locked;
@@ -184,7 +185,7 @@ public:
int get_collision_pairs() const { return collision_pairs; }
- bool test_body_motion(Body2DSW *p_body, const Matrix32 &p_from, const Vector2&p_motion, float p_margin, Physics2DServer::MotionResult *r_result);
+ bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2&p_motion, real_t p_margin, Physics2DServer::MotionResult *r_result);
void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); }
diff --git a/servers/physics_2d/step_2d_sw.cpp b/servers/physics_2d/step_2d_sw.cpp
index 4f86168c1e..355cc25a69 100644
--- a/servers/physics_2d/step_2d_sw.cpp
+++ b/servers/physics_2d/step_2d_sw.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -56,7 +56,7 @@ void Step2DSW::_populate_island(Body2DSW* p_body,Body2DSW** p_island,Constraint2
}
}
-bool Step2DSW::_setup_island(Constraint2DSW *p_island,float p_delta) {
+bool Step2DSW::_setup_island(Constraint2DSW *p_island,real_t p_delta) {
Constraint2DSW *ci=p_island;
Constraint2DSW *prev_ci=NULL;
@@ -81,7 +81,7 @@ bool Step2DSW::_setup_island(Constraint2DSW *p_island,float p_delta) {
return removed_root;
}
-void Step2DSW::_solve_island(Constraint2DSW *p_island,int p_iterations,float p_delta){
+void Step2DSW::_solve_island(Constraint2DSW *p_island,int p_iterations,real_t p_delta){
for(int i=0;i<p_iterations;i++) {
@@ -94,7 +94,7 @@ void Step2DSW::_solve_island(Constraint2DSW *p_island,int p_iterations,float p_d
}
}
-void Step2DSW::_check_suspend(Body2DSW *p_island,float p_delta) {
+void Step2DSW::_check_suspend(Body2DSW *p_island,real_t p_delta) {
bool can_sleep=true;
@@ -132,7 +132,7 @@ void Step2DSW::_check_suspend(Body2DSW *p_island,float p_delta) {
}
}
-void Step2DSW::step(Space2DSW* p_space,float p_delta,int p_iterations) {
+void Step2DSW::step(Space2DSW* p_space,real_t p_delta,int p_iterations) {
p_space->lock(); // can't access space during this
@@ -216,7 +216,7 @@ void Step2DSW::step(Space2DSW* p_space,float p_delta,int p_iterations) {
p_space->area_remove_from_moved_list((SelfList<Area2DSW>*)aml.first()); //faster to remove here
}
-// print_line("island count: "+itos(island_count)+" active count: "+itos(active_count));
+ //print_line("island count: "+itos(island_count)+" active count: "+itos(active_count));
{ //profile
profile_endtime=OS::get_singleton()->get_ticks_usec();
diff --git a/servers/physics_2d/step_2d_sw.h b/servers/physics_2d/step_2d_sw.h
index 0c374d7e12..0896e1016d 100644
--- a/servers/physics_2d/step_2d_sw.h
+++ b/servers/physics_2d/step_2d_sw.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,12 +36,12 @@ class Step2DSW {
uint64_t _step;
void _populate_island(Body2DSW* p_body,Body2DSW** p_island,Constraint2DSW **p_constraint_island);
- bool _setup_island(Constraint2DSW *p_island,float p_delta);
- void _solve_island(Constraint2DSW *p_island,int p_iterations,float p_delta);
- void _check_suspend(Body2DSW *p_island,float p_delta);
+ bool _setup_island(Constraint2DSW *p_island,real_t p_delta);
+ void _solve_island(Constraint2DSW *p_island,int p_iterations,real_t p_delta);
+ void _check_suspend(Body2DSW *p_island,real_t p_delta);
public:
- void step(Space2DSW* p_space,float p_delta,int p_iterations);
+ void step(Space2DSW* p_space,real_t p_delta,int p_iterations);
Step2DSW();
};
diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp
index a77b13eb21..bdbe85612f 100644
--- a/servers/physics_2d_server.cpp
+++ b/servers/physics_2d_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -73,40 +73,40 @@ Physics2DServer * Physics2DServer::get_singleton() {
void Physics2DDirectBodyState::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("get_total_gravity"),&Physics2DDirectBodyState::get_total_gravity);
- ObjectTypeDB::bind_method(_MD("get_total_linear_damp"),&Physics2DDirectBodyState::get_total_linear_damp);
- ObjectTypeDB::bind_method(_MD("get_total_angular_damp"),&Physics2DDirectBodyState::get_total_angular_damp);
+ ClassDB::bind_method(D_METHOD("get_total_gravity"),&Physics2DDirectBodyState::get_total_gravity);
+ ClassDB::bind_method(D_METHOD("get_total_linear_damp"),&Physics2DDirectBodyState::get_total_linear_damp);
+ ClassDB::bind_method(D_METHOD("get_total_angular_damp"),&Physics2DDirectBodyState::get_total_angular_damp);
- ObjectTypeDB::bind_method(_MD("get_inverse_mass"),&Physics2DDirectBodyState::get_inverse_mass);
- ObjectTypeDB::bind_method(_MD("get_inverse_inertia"),&Physics2DDirectBodyState::get_inverse_inertia);
+ ClassDB::bind_method(D_METHOD("get_inverse_mass"),&Physics2DDirectBodyState::get_inverse_mass);
+ ClassDB::bind_method(D_METHOD("get_inverse_inertia"),&Physics2DDirectBodyState::get_inverse_inertia);
- ObjectTypeDB::bind_method(_MD("set_linear_velocity","velocity"),&Physics2DDirectBodyState::set_linear_velocity);
- ObjectTypeDB::bind_method(_MD("get_linear_velocity"),&Physics2DDirectBodyState::get_linear_velocity);
+ ClassDB::bind_method(D_METHOD("set_linear_velocity","velocity"),&Physics2DDirectBodyState::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"),&Physics2DDirectBodyState::get_linear_velocity);
- ObjectTypeDB::bind_method(_MD("set_angular_velocity","velocity"),&Physics2DDirectBodyState::set_angular_velocity);
- ObjectTypeDB::bind_method(_MD("get_angular_velocity"),&Physics2DDirectBodyState::get_angular_velocity);
+ ClassDB::bind_method(D_METHOD("set_angular_velocity","velocity"),&Physics2DDirectBodyState::set_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_angular_velocity"),&Physics2DDirectBodyState::get_angular_velocity);
- ObjectTypeDB::bind_method(_MD("set_transform","transform"),&Physics2DDirectBodyState::set_transform);
- ObjectTypeDB::bind_method(_MD("get_transform"),&Physics2DDirectBodyState::get_transform);
+ ClassDB::bind_method(D_METHOD("set_transform","transform"),&Physics2DDirectBodyState::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"),&Physics2DDirectBodyState::get_transform);
- ObjectTypeDB::bind_method(_MD("set_sleep_state","enabled"),&Physics2DDirectBodyState::set_sleep_state);
- ObjectTypeDB::bind_method(_MD("is_sleeping"),&Physics2DDirectBodyState::is_sleeping);
+ ClassDB::bind_method(D_METHOD("set_sleep_state","enabled"),&Physics2DDirectBodyState::set_sleep_state);
+ ClassDB::bind_method(D_METHOD("is_sleeping"),&Physics2DDirectBodyState::is_sleeping);
- ObjectTypeDB::bind_method(_MD("get_contact_count"),&Physics2DDirectBodyState::get_contact_count);
+ ClassDB::bind_method(D_METHOD("get_contact_count"),&Physics2DDirectBodyState::get_contact_count);
- ObjectTypeDB::bind_method(_MD("get_contact_local_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_local_pos);
- ObjectTypeDB::bind_method(_MD("get_contact_local_normal","contact_idx"),&Physics2DDirectBodyState::get_contact_local_normal);
- ObjectTypeDB::bind_method(_MD("get_contact_local_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_local_shape);
- ObjectTypeDB::bind_method(_MD("get_contact_collider","contact_idx"),&Physics2DDirectBodyState::get_contact_collider);
- ObjectTypeDB::bind_method(_MD("get_contact_collider_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_pos);
- ObjectTypeDB::bind_method(_MD("get_contact_collider_id","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_id);
- ObjectTypeDB::bind_method(_MD("get_contact_collider_object","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_object);
- ObjectTypeDB::bind_method(_MD("get_contact_collider_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape);
- ObjectTypeDB::bind_method(_MD("get_contact_collider_shape_metadata:Variant","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape_metadata);
- ObjectTypeDB::bind_method(_MD("get_contact_collider_velocity_at_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_velocity_at_pos);
- ObjectTypeDB::bind_method(_MD("get_step"),&Physics2DDirectBodyState::get_step);
- ObjectTypeDB::bind_method(_MD("integrate_forces"),&Physics2DDirectBodyState::integrate_forces);
- ObjectTypeDB::bind_method(_MD("get_space_state:Physics2DDirectSpaceState"),&Physics2DDirectBodyState::get_space_state);
+ ClassDB::bind_method(D_METHOD("get_contact_local_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_local_pos);
+ ClassDB::bind_method(D_METHOD("get_contact_local_normal","contact_idx"),&Physics2DDirectBodyState::get_contact_local_normal);
+ ClassDB::bind_method(D_METHOD("get_contact_local_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_local_shape);
+ ClassDB::bind_method(D_METHOD("get_contact_collider","contact_idx"),&Physics2DDirectBodyState::get_contact_collider);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_pos);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_id","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_id);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_object","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_object);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_shape","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_shape_metadata:Variant","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_shape_metadata);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_pos","contact_idx"),&Physics2DDirectBodyState::get_contact_collider_velocity_at_pos);
+ ClassDB::bind_method(D_METHOD("get_step"),&Physics2DDirectBodyState::get_step);
+ ClassDB::bind_method(D_METHOD("integrate_forces"),&Physics2DDirectBodyState::integrate_forces);
+ ClassDB::bind_method(D_METHOD("get_space_state:Physics2DDirectSpaceState"),&Physics2DDirectBodyState::get_space_state);
}
@@ -132,11 +132,11 @@ RID Physics2DShapeQueryParameters::get_shape_rid() const {
return shape;
}
-void Physics2DShapeQueryParameters::set_transform(const Matrix32& p_transform){
+void Physics2DShapeQueryParameters::set_transform(const Transform2D& p_transform){
transform=p_transform;
}
-Matrix32 Physics2DShapeQueryParameters::get_transform() const{
+Transform2D Physics2DShapeQueryParameters::get_transform() const{
return transform;
}
@@ -179,7 +179,7 @@ int Physics2DShapeQueryParameters::get_object_type_mask() const{
}
void Physics2DShapeQueryParameters::set_exclude(const Vector<RID>& p_exclude) {
- exclude.clear();;
+ exclude.clear();
for(int i=0;i<p_exclude.size();i++)
exclude.insert(p_exclude[i]);
@@ -198,27 +198,27 @@ Vector<RID> Physics2DShapeQueryParameters::get_exclude() const{
void Physics2DShapeQueryParameters::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("set_shape","shape:Shape2D"),&Physics2DShapeQueryParameters::set_shape);
- ObjectTypeDB::bind_method(_MD("set_shape_rid","shape"),&Physics2DShapeQueryParameters::set_shape_rid);
- ObjectTypeDB::bind_method(_MD("get_shape_rid"),&Physics2DShapeQueryParameters::get_shape_rid);
+ ClassDB::bind_method(D_METHOD("set_shape","shape:Shape2D"),&Physics2DShapeQueryParameters::set_shape);
+ ClassDB::bind_method(D_METHOD("set_shape_rid","shape"),&Physics2DShapeQueryParameters::set_shape_rid);
+ ClassDB::bind_method(D_METHOD("get_shape_rid"),&Physics2DShapeQueryParameters::get_shape_rid);
- ObjectTypeDB::bind_method(_MD("set_transform","transform"),&Physics2DShapeQueryParameters::set_transform);
- ObjectTypeDB::bind_method(_MD("get_transform"),&Physics2DShapeQueryParameters::get_transform);
+ ClassDB::bind_method(D_METHOD("set_transform","transform"),&Physics2DShapeQueryParameters::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"),&Physics2DShapeQueryParameters::get_transform);
- ObjectTypeDB::bind_method(_MD("set_motion","motion"),&Physics2DShapeQueryParameters::set_motion);
- ObjectTypeDB::bind_method(_MD("get_motion"),&Physics2DShapeQueryParameters::get_motion);
+ ClassDB::bind_method(D_METHOD("set_motion","motion"),&Physics2DShapeQueryParameters::set_motion);
+ ClassDB::bind_method(D_METHOD("get_motion"),&Physics2DShapeQueryParameters::get_motion);
- ObjectTypeDB::bind_method(_MD("set_margin","margin"),&Physics2DShapeQueryParameters::set_margin);
- ObjectTypeDB::bind_method(_MD("get_margin"),&Physics2DShapeQueryParameters::get_margin);
+ ClassDB::bind_method(D_METHOD("set_margin","margin"),&Physics2DShapeQueryParameters::set_margin);
+ ClassDB::bind_method(D_METHOD("get_margin"),&Physics2DShapeQueryParameters::get_margin);
- ObjectTypeDB::bind_method(_MD("set_layer_mask","layer_mask"),&Physics2DShapeQueryParameters::set_layer_mask);
- ObjectTypeDB::bind_method(_MD("get_layer_mask"),&Physics2DShapeQueryParameters::get_layer_mask);
+ ClassDB::bind_method(D_METHOD("set_layer_mask","layer_mask"),&Physics2DShapeQueryParameters::set_layer_mask);
+ ClassDB::bind_method(D_METHOD("get_layer_mask"),&Physics2DShapeQueryParameters::get_layer_mask);
- ObjectTypeDB::bind_method(_MD("set_object_type_mask","object_type_mask"),&Physics2DShapeQueryParameters::set_object_type_mask);
- ObjectTypeDB::bind_method(_MD("get_object_type_mask"),&Physics2DShapeQueryParameters::get_object_type_mask);
+ ClassDB::bind_method(D_METHOD("set_object_type_mask","object_type_mask"),&Physics2DShapeQueryParameters::set_object_type_mask);
+ ClassDB::bind_method(D_METHOD("get_object_type_mask"),&Physics2DShapeQueryParameters::get_object_type_mask);
- ObjectTypeDB::bind_method(_MD("set_exclude","exclude"),&Physics2DShapeQueryParameters::set_exclude);
- ObjectTypeDB::bind_method(_MD("get_exclude"),&Physics2DShapeQueryParameters::get_exclude);
+ ClassDB::bind_method(D_METHOD("set_exclude","exclude"),&Physics2DShapeQueryParameters::set_exclude);
+ ClassDB::bind_method(D_METHOD("get_exclude"),&Physics2DShapeQueryParameters::get_exclude);
}
@@ -241,9 +241,9 @@ Dictionary Physics2DDirectSpaceState::_intersect_ray(const Vector2& p_from, cons
bool res = intersect_ray(p_from,p_to,inters,exclude,p_layers,p_object_type_mask);
if (!res)
- return Dictionary(true);
+ return Dictionary();
- Dictionary d(true);
+ Dictionary d;
d["position"]=inters.position;
d["normal"]=inters.normal;
d["collider_id"]=inters.collider_id;
@@ -282,7 +282,7 @@ Array Physics2DDirectSpaceState::_cast_motion(const Ref<Physics2DShapeQueryParam
bool res = cast_motion(psq->shape,psq->transform,psq->motion,psq->margin,closest_safe,closest_unsafe,psq->exclude,psq->layer_mask,psq->object_type_mask);
if (!res)
return Array();
- Array ret(true);
+ Array ret;
ret.resize(2);
ret[0]=closest_safe;
ret[1]=closest_unsafe;
@@ -339,7 +339,7 @@ Dictionary Physics2DDirectSpaceState::_get_rest_info(const Ref<Physics2DShapeQue
ShapeRestInfo sri;
bool res = rest_info(psq->shape,psq->transform,psq->motion,psq->margin,&sri,psq->exclude,psq->layer_mask,psq->object_type_mask);
- Dictionary r(true);
+ Dictionary r;
if (!res)
return r;
@@ -366,13 +366,13 @@ Physics2DDirectSpaceState::Physics2DDirectSpaceState() {
void Physics2DDirectSpaceState::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("intersect_point","point","max_results","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_point,DEFVAL(32),DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
- ObjectTypeDB::bind_method(_MD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
- ObjectTypeDB::bind_method(_MD("intersect_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(32));
- ObjectTypeDB::bind_method(_MD("cast_motion","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_cast_motion);
- ObjectTypeDB::bind_method(_MD("collide_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_collide_shape,DEFVAL(32));
- ObjectTypeDB::bind_method(_MD("get_rest_info","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_get_rest_info);
- //ObjectTypeDB::bind_method(_MD("cast_motion","shape","xform","motion","exclude","umask"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0));
+ ClassDB::bind_method(D_METHOD("intersect_point","point","max_results","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_point,DEFVAL(32),DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
+ ClassDB::bind_method(D_METHOD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&Physics2DDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
+ ClassDB::bind_method(D_METHOD("intersect_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("cast_motion","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_cast_motion);
+ ClassDB::bind_method(D_METHOD("collide_shape","shape:Physics2DShapeQueryParameters","max_results"),&Physics2DDirectSpaceState::_collide_shape,DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("get_rest_info","shape:Physics2DShapeQueryParameters"),&Physics2DDirectSpaceState::_get_rest_info);
+ //ClassDB::bind_method(D_METHOD("cast_motion","shape","xform","motion","exclude","umask"),&Physics2DDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0));
BIND_CONSTANT( TYPE_MASK_STATIC_BODY );
BIND_CONSTANT( TYPE_MASK_KINEMATIC_BODY );
@@ -412,11 +412,11 @@ Physics2DShapeQueryResult::Physics2DShapeQueryResult() {
void Physics2DShapeQueryResult::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("get_result_count"),&Physics2DShapeQueryResult::get_result_count);
- ObjectTypeDB::bind_method(_MD("get_result_rid","idx"),&Physics2DShapeQueryResult::get_result_rid);
- ObjectTypeDB::bind_method(_MD("get_result_object_id","idx"),&Physics2DShapeQueryResult::get_result_object_id);
- ObjectTypeDB::bind_method(_MD("get_result_object","idx"),&Physics2DShapeQueryResult::get_result_object);
- ObjectTypeDB::bind_method(_MD("get_result_object_shape","idx"),&Physics2DShapeQueryResult::get_result_object_shape);
+ ClassDB::bind_method(D_METHOD("get_result_count"),&Physics2DShapeQueryResult::get_result_count);
+ ClassDB::bind_method(D_METHOD("get_result_rid","idx"),&Physics2DShapeQueryResult::get_result_rid);
+ ClassDB::bind_method(D_METHOD("get_result_object_id","idx"),&Physics2DShapeQueryResult::get_result_object_id);
+ ClassDB::bind_method(D_METHOD("get_result_object","idx"),&Physics2DShapeQueryResult::get_result_object);
+ ClassDB::bind_method(D_METHOD("get_result_object_shape","idx"),&Physics2DShapeQueryResult::get_result_object_shape);
}
@@ -468,16 +468,16 @@ int Physics2DTestMotionResult::get_collider_shape() const{
void Physics2DTestMotionResult::_bind_methods() {
- //ObjectTypeDB::bind_method(_MD("is_colliding"),&Physics2DTestMotionResult::is_colliding);
- ObjectTypeDB::bind_method(_MD("get_motion"),&Physics2DTestMotionResult::get_motion);
- ObjectTypeDB::bind_method(_MD("get_motion_remainder"),&Physics2DTestMotionResult::get_motion_remainder);
- ObjectTypeDB::bind_method(_MD("get_collision_point"),&Physics2DTestMotionResult::get_collision_point);
- ObjectTypeDB::bind_method(_MD("get_collision_normal"),&Physics2DTestMotionResult::get_collision_normal);
- ObjectTypeDB::bind_method(_MD("get_collider_velocity"),&Physics2DTestMotionResult::get_collider_velocity);
- ObjectTypeDB::bind_method(_MD("get_collider_id"),&Physics2DTestMotionResult::get_collider_id);
- ObjectTypeDB::bind_method(_MD("get_collider_rid"),&Physics2DTestMotionResult::get_collider_rid);
- ObjectTypeDB::bind_method(_MD("get_collider"),&Physics2DTestMotionResult::get_collider);
- ObjectTypeDB::bind_method(_MD("get_collider_shape"),&Physics2DTestMotionResult::get_collider_shape);
+ //ClassDB::bind_method(D_METHOD("is_colliding"),&Physics2DTestMotionResult::is_colliding);
+ ClassDB::bind_method(D_METHOD("get_motion"),&Physics2DTestMotionResult::get_motion);
+ ClassDB::bind_method(D_METHOD("get_motion_remainder"),&Physics2DTestMotionResult::get_motion_remainder);
+ ClassDB::bind_method(D_METHOD("get_collision_point"),&Physics2DTestMotionResult::get_collision_point);
+ ClassDB::bind_method(D_METHOD("get_collision_normal"),&Physics2DTestMotionResult::get_collision_normal);
+ ClassDB::bind_method(D_METHOD("get_collider_velocity"),&Physics2DTestMotionResult::get_collider_velocity);
+ ClassDB::bind_method(D_METHOD("get_collider_id"),&Physics2DTestMotionResult::get_collider_id);
+ ClassDB::bind_method(D_METHOD("get_collider_rid"),&Physics2DTestMotionResult::get_collider_rid);
+ ClassDB::bind_method(D_METHOD("get_collider"),&Physics2DTestMotionResult::get_collider);
+ ClassDB::bind_method(D_METHOD("get_collider_shape"),&Physics2DTestMotionResult::get_collider_shape);
}
@@ -493,7 +493,7 @@ Physics2DTestMotionResult::Physics2DTestMotionResult(){
-bool Physics2DServer::_body_test_motion(RID p_body,const Matrix32& p_from,const Vector2& p_motion,float p_margin,const Ref<Physics2DTestMotionResult>& p_result) {
+bool Physics2DServer::_body_test_motion(RID p_body,const Transform2D& p_from,const Vector2& p_motion,float p_margin,const Ref<Physics2DTestMotionResult>& p_result) {
MotionResult *r=NULL;
if (p_result.is_valid())
@@ -504,147 +504,147 @@ bool Physics2DServer::_body_test_motion(RID p_body,const Matrix32& p_from,const
void Physics2DServer::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("shape_create","type"),&Physics2DServer::shape_create);
- ObjectTypeDB::bind_method(_MD("shape_set_data","shape","data"),&Physics2DServer::shape_set_data);
+ ClassDB::bind_method(D_METHOD("shape_create","type"),&Physics2DServer::shape_create);
+ ClassDB::bind_method(D_METHOD("shape_set_data","shape","data"),&Physics2DServer::shape_set_data);
- ObjectTypeDB::bind_method(_MD("shape_get_type","shape"),&Physics2DServer::shape_get_type);
- ObjectTypeDB::bind_method(_MD("shape_get_data","shape"),&Physics2DServer::shape_get_data);
+ ClassDB::bind_method(D_METHOD("shape_get_type","shape"),&Physics2DServer::shape_get_type);
+ ClassDB::bind_method(D_METHOD("shape_get_data","shape"),&Physics2DServer::shape_get_data);
- ObjectTypeDB::bind_method(_MD("space_create"),&Physics2DServer::space_create);
- ObjectTypeDB::bind_method(_MD("space_set_active","space","active"),&Physics2DServer::space_set_active);
- ObjectTypeDB::bind_method(_MD("space_is_active","space"),&Physics2DServer::space_is_active);
- ObjectTypeDB::bind_method(_MD("space_set_param","space","param","value"),&Physics2DServer::space_set_param);
- ObjectTypeDB::bind_method(_MD("space_get_param","space","param"),&Physics2DServer::space_get_param);
- ObjectTypeDB::bind_method(_MD("space_get_direct_state:Physics2DDirectSpaceState","space"),&Physics2DServer::space_get_direct_state);
+ ClassDB::bind_method(D_METHOD("space_create"),&Physics2DServer::space_create);
+ ClassDB::bind_method(D_METHOD("space_set_active","space","active"),&Physics2DServer::space_set_active);
+ ClassDB::bind_method(D_METHOD("space_is_active","space"),&Physics2DServer::space_is_active);
+ ClassDB::bind_method(D_METHOD("space_set_param","space","param","value"),&Physics2DServer::space_set_param);
+ ClassDB::bind_method(D_METHOD("space_get_param","space","param"),&Physics2DServer::space_get_param);
+ ClassDB::bind_method(D_METHOD("space_get_direct_state:Physics2DDirectSpaceState","space"),&Physics2DServer::space_get_direct_state);
- ObjectTypeDB::bind_method(_MD("area_create"),&Physics2DServer::area_create);
- ObjectTypeDB::bind_method(_MD("area_set_space","area","space"),&Physics2DServer::area_set_space);
- ObjectTypeDB::bind_method(_MD("area_get_space","area"),&Physics2DServer::area_get_space);
+ ClassDB::bind_method(D_METHOD("area_create"),&Physics2DServer::area_create);
+ ClassDB::bind_method(D_METHOD("area_set_space","area","space"),&Physics2DServer::area_set_space);
+ ClassDB::bind_method(D_METHOD("area_get_space","area"),&Physics2DServer::area_get_space);
- ObjectTypeDB::bind_method(_MD("area_set_space_override_mode","area","mode"),&Physics2DServer::area_set_space_override_mode);
- ObjectTypeDB::bind_method(_MD("area_get_space_override_mode","area"),&Physics2DServer::area_get_space_override_mode);
+ ClassDB::bind_method(D_METHOD("area_set_space_override_mode","area","mode"),&Physics2DServer::area_set_space_override_mode);
+ ClassDB::bind_method(D_METHOD("area_get_space_override_mode","area"),&Physics2DServer::area_get_space_override_mode);
- ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&Physics2DServer::area_add_shape,DEFVAL(Matrix32()));
- ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&Physics2DServer::area_set_shape);
- ObjectTypeDB::bind_method(_MD("area_set_shape_transform","area","shape_idx","transform"),&Physics2DServer::area_set_shape_transform);
+ ClassDB::bind_method(D_METHOD("area_add_shape","area","shape","transform"),&Physics2DServer::area_add_shape,DEFVAL(Transform2D()));
+ ClassDB::bind_method(D_METHOD("area_set_shape","area","shape_idx","shape"),&Physics2DServer::area_set_shape);
+ ClassDB::bind_method(D_METHOD("area_set_shape_transform","area","shape_idx","transform"),&Physics2DServer::area_set_shape_transform);
- ObjectTypeDB::bind_method(_MD("area_get_shape_count","area"),&Physics2DServer::area_get_shape_count);
- ObjectTypeDB::bind_method(_MD("area_get_shape","area","shape_idx"),&Physics2DServer::area_get_shape);
- ObjectTypeDB::bind_method(_MD("area_get_shape_transform","area","shape_idx"),&Physics2DServer::area_get_shape_transform);
+ ClassDB::bind_method(D_METHOD("area_get_shape_count","area"),&Physics2DServer::area_get_shape_count);
+ ClassDB::bind_method(D_METHOD("area_get_shape","area","shape_idx"),&Physics2DServer::area_get_shape);
+ ClassDB::bind_method(D_METHOD("area_get_shape_transform","area","shape_idx"),&Physics2DServer::area_get_shape_transform);
- ObjectTypeDB::bind_method(_MD("area_remove_shape","area","shape_idx"),&Physics2DServer::area_remove_shape);
- ObjectTypeDB::bind_method(_MD("area_clear_shapes","area"),&Physics2DServer::area_clear_shapes);
+ ClassDB::bind_method(D_METHOD("area_remove_shape","area","shape_idx"),&Physics2DServer::area_remove_shape);
+ ClassDB::bind_method(D_METHOD("area_clear_shapes","area"),&Physics2DServer::area_clear_shapes);
- ObjectTypeDB::bind_method(_MD("area_set_layer_mask","area","mask"),&Physics2DServer::area_set_layer_mask);
- ObjectTypeDB::bind_method(_MD("area_set_collision_mask","area","mask"),&Physics2DServer::area_set_collision_mask);
+ ClassDB::bind_method(D_METHOD("area_set_layer_mask","area","mask"),&Physics2DServer::area_set_layer_mask);
+ ClassDB::bind_method(D_METHOD("area_set_collision_mask","area","mask"),&Physics2DServer::area_set_collision_mask);
- ObjectTypeDB::bind_method(_MD("area_set_param","area","param","value"),&Physics2DServer::area_set_param);
- ObjectTypeDB::bind_method(_MD("area_set_transform","area","transform"),&Physics2DServer::area_set_transform);
+ ClassDB::bind_method(D_METHOD("area_set_param","area","param","value"),&Physics2DServer::area_set_param);
+ ClassDB::bind_method(D_METHOD("area_set_transform","area","transform"),&Physics2DServer::area_set_transform);
- ObjectTypeDB::bind_method(_MD("area_get_param","area","param"),&Physics2DServer::area_get_param);
- ObjectTypeDB::bind_method(_MD("area_get_transform","area"),&Physics2DServer::area_get_transform);
+ ClassDB::bind_method(D_METHOD("area_get_param","area","param"),&Physics2DServer::area_get_param);
+ ClassDB::bind_method(D_METHOD("area_get_transform","area"),&Physics2DServer::area_get_transform);
- ObjectTypeDB::bind_method(_MD("area_attach_object_instance_ID","area","id"),&Physics2DServer::area_attach_object_instance_ID);
- ObjectTypeDB::bind_method(_MD("area_get_object_instance_ID","area"),&Physics2DServer::area_get_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("area_attach_object_instance_ID","area","id"),&Physics2DServer::area_attach_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("area_get_object_instance_ID","area"),&Physics2DServer::area_get_object_instance_ID);
- ObjectTypeDB::bind_method(_MD("area_set_monitor_callback","area","receiver","method"),&Physics2DServer::area_set_monitor_callback);
+ ClassDB::bind_method(D_METHOD("area_set_monitor_callback","area","receiver","method"),&Physics2DServer::area_set_monitor_callback);
- ObjectTypeDB::bind_method(_MD("body_create","mode","init_sleeping"),&Physics2DServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("body_create","mode","init_sleeping"),&Physics2DServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false));
- ObjectTypeDB::bind_method(_MD("body_set_space","body","space"),&Physics2DServer::body_set_space);
- ObjectTypeDB::bind_method(_MD("body_get_space","body"),&Physics2DServer::body_get_space);
+ ClassDB::bind_method(D_METHOD("body_set_space","body","space"),&Physics2DServer::body_set_space);
+ ClassDB::bind_method(D_METHOD("body_get_space","body"),&Physics2DServer::body_get_space);
- ObjectTypeDB::bind_method(_MD("body_set_mode","body","mode"),&Physics2DServer::body_set_mode);
- ObjectTypeDB::bind_method(_MD("body_get_mode","body"),&Physics2DServer::body_get_mode);
+ ClassDB::bind_method(D_METHOD("body_set_mode","body","mode"),&Physics2DServer::body_set_mode);
+ ClassDB::bind_method(D_METHOD("body_get_mode","body"),&Physics2DServer::body_get_mode);
- ObjectTypeDB::bind_method(_MD("body_add_shape","body","shape","transform"),&Physics2DServer::body_add_shape,DEFVAL(Matrix32()));
- ObjectTypeDB::bind_method(_MD("body_set_shape","body","shape_idx","shape"),&Physics2DServer::body_set_shape);
- ObjectTypeDB::bind_method(_MD("body_set_shape_transform","body","shape_idx","transform"),&Physics2DServer::body_set_shape_transform);
- ObjectTypeDB::bind_method(_MD("body_set_shape_metadata","body","shape_idx","metadata"),&Physics2DServer::body_set_shape_metadata);
+ ClassDB::bind_method(D_METHOD("body_add_shape","body","shape","transform"),&Physics2DServer::body_add_shape,DEFVAL(Transform2D()));
+ ClassDB::bind_method(D_METHOD("body_set_shape","body","shape_idx","shape"),&Physics2DServer::body_set_shape);
+ ClassDB::bind_method(D_METHOD("body_set_shape_transform","body","shape_idx","transform"),&Physics2DServer::body_set_shape_transform);
+ ClassDB::bind_method(D_METHOD("body_set_shape_metadata","body","shape_idx","metadata"),&Physics2DServer::body_set_shape_metadata);
- ObjectTypeDB::bind_method(_MD("body_get_shape_count","body"),&Physics2DServer::body_get_shape_count);
- ObjectTypeDB::bind_method(_MD("body_get_shape","body","shape_idx"),&Physics2DServer::body_get_shape);
- ObjectTypeDB::bind_method(_MD("body_get_shape_transform","body","shape_idx"),&Physics2DServer::body_get_shape_transform);
- ObjectTypeDB::bind_method(_MD("body_get_shape_metadata","body","shape_idx"),&Physics2DServer::body_get_shape_metadata);
+ ClassDB::bind_method(D_METHOD("body_get_shape_count","body"),&Physics2DServer::body_get_shape_count);
+ ClassDB::bind_method(D_METHOD("body_get_shape","body","shape_idx"),&Physics2DServer::body_get_shape);
+ ClassDB::bind_method(D_METHOD("body_get_shape_transform","body","shape_idx"),&Physics2DServer::body_get_shape_transform);
+ ClassDB::bind_method(D_METHOD("body_get_shape_metadata","body","shape_idx"),&Physics2DServer::body_get_shape_metadata);
- ObjectTypeDB::bind_method(_MD("body_remove_shape","body","shape_idx"),&Physics2DServer::body_remove_shape);
- ObjectTypeDB::bind_method(_MD("body_clear_shapes","body"),&Physics2DServer::body_clear_shapes);
+ ClassDB::bind_method(D_METHOD("body_remove_shape","body","shape_idx"),&Physics2DServer::body_remove_shape);
+ ClassDB::bind_method(D_METHOD("body_clear_shapes","body"),&Physics2DServer::body_clear_shapes);
- ObjectTypeDB::bind_method(_MD("body_set_shape_as_trigger","body","shape_idx","enable"),&Physics2DServer::body_set_shape_as_trigger);
- ObjectTypeDB::bind_method(_MD("body_is_shape_set_as_trigger","body","shape_idx"),&Physics2DServer::body_is_shape_set_as_trigger);
+ ClassDB::bind_method(D_METHOD("body_set_shape_as_trigger","body","shape_idx","enable"),&Physics2DServer::body_set_shape_as_trigger);
+ ClassDB::bind_method(D_METHOD("body_is_shape_set_as_trigger","body","shape_idx"),&Physics2DServer::body_is_shape_set_as_trigger);
- ObjectTypeDB::bind_method(_MD("body_attach_object_instance_ID","body","id"),&Physics2DServer::body_attach_object_instance_ID);
- ObjectTypeDB::bind_method(_MD("body_get_object_instance_ID","body"),&Physics2DServer::body_get_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("body_attach_object_instance_ID","body","id"),&Physics2DServer::body_attach_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("body_get_object_instance_ID","body"),&Physics2DServer::body_get_object_instance_ID);
- ObjectTypeDB::bind_method(_MD("body_set_continuous_collision_detection_mode","body","mode"),&Physics2DServer::body_set_continuous_collision_detection_mode);
- ObjectTypeDB::bind_method(_MD("body_get_continuous_collision_detection_mode","body"),&Physics2DServer::body_get_continuous_collision_detection_mode);
+ ClassDB::bind_method(D_METHOD("body_set_continuous_collision_detection_mode","body","mode"),&Physics2DServer::body_set_continuous_collision_detection_mode);
+ ClassDB::bind_method(D_METHOD("body_get_continuous_collision_detection_mode","body"),&Physics2DServer::body_get_continuous_collision_detection_mode);
- ObjectTypeDB::bind_method(_MD("body_set_layer_mask","body","mask"),&Physics2DServer::body_set_layer_mask);
- ObjectTypeDB::bind_method(_MD("body_get_layer_mask","body"),&Physics2DServer::body_get_layer_mask);
+ ClassDB::bind_method(D_METHOD("body_set_layer_mask","body","mask"),&Physics2DServer::body_set_layer_mask);
+ ClassDB::bind_method(D_METHOD("body_get_layer_mask","body"),&Physics2DServer::body_get_layer_mask);
- ObjectTypeDB::bind_method(_MD("body_set_collision_mask","body","mask"),&Physics2DServer::body_set_collision_mask);
- ObjectTypeDB::bind_method(_MD("body_get_collision_mask","body"),&Physics2DServer::body_get_collision_mask);
+ ClassDB::bind_method(D_METHOD("body_set_collision_mask","body","mask"),&Physics2DServer::body_set_collision_mask);
+ ClassDB::bind_method(D_METHOD("body_get_collision_mask","body"),&Physics2DServer::body_get_collision_mask);
- ObjectTypeDB::bind_method(_MD("body_set_param","body","param","value"),&Physics2DServer::body_set_param);
- ObjectTypeDB::bind_method(_MD("body_get_param","body","param"),&Physics2DServer::body_get_param);
+ ClassDB::bind_method(D_METHOD("body_set_param","body","param","value"),&Physics2DServer::body_set_param);
+ ClassDB::bind_method(D_METHOD("body_get_param","body","param"),&Physics2DServer::body_get_param);
- ObjectTypeDB::bind_method(_MD("body_set_state","body","state","value"),&Physics2DServer::body_set_state);
- ObjectTypeDB::bind_method(_MD("body_get_state","body","state"),&Physics2DServer::body_get_state);
+ ClassDB::bind_method(D_METHOD("body_set_state","body","state","value"),&Physics2DServer::body_set_state);
+ ClassDB::bind_method(D_METHOD("body_get_state","body","state"),&Physics2DServer::body_get_state);
- ObjectTypeDB::bind_method(_MD("body_apply_impulse","body","pos","impulse"),&Physics2DServer::body_apply_impulse);
- ObjectTypeDB::bind_method(_MD("body_add_force","body","offset","force"),&Physics2DServer::body_add_force);
- ObjectTypeDB::bind_method(_MD("body_set_axis_velocity","body","axis_velocity"),&Physics2DServer::body_set_axis_velocity);
+ ClassDB::bind_method(D_METHOD("body_apply_impulse","body","pos","impulse"),&Physics2DServer::body_apply_impulse);
+ ClassDB::bind_method(D_METHOD("body_add_force","body","offset","force"),&Physics2DServer::body_add_force);
+ ClassDB::bind_method(D_METHOD("body_set_axis_velocity","body","axis_velocity"),&Physics2DServer::body_set_axis_velocity);
- ObjectTypeDB::bind_method(_MD("body_add_collision_exception","body","excepted_body"),&Physics2DServer::body_add_collision_exception);
- ObjectTypeDB::bind_method(_MD("body_remove_collision_exception","body","excepted_body"),&Physics2DServer::body_remove_collision_exception);
-// virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions)=0;
+ ClassDB::bind_method(D_METHOD("body_add_collision_exception","body","excepted_body"),&Physics2DServer::body_add_collision_exception);
+ ClassDB::bind_method(D_METHOD("body_remove_collision_exception","body","excepted_body"),&Physics2DServer::body_remove_collision_exception);
+ //virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions)=0;
- ObjectTypeDB::bind_method(_MD("body_set_max_contacts_reported","body","amount"),&Physics2DServer::body_set_max_contacts_reported);
- ObjectTypeDB::bind_method(_MD("body_get_max_contacts_reported","body"),&Physics2DServer::body_get_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("body_set_max_contacts_reported","body","amount"),&Physics2DServer::body_set_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("body_get_max_contacts_reported","body"),&Physics2DServer::body_get_max_contacts_reported);
- ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_direction","body","normal"),&Physics2DServer::body_set_one_way_collision_direction);
- ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_direction","body"),&Physics2DServer::body_get_one_way_collision_direction);
+ ClassDB::bind_method(D_METHOD("body_set_one_way_collision_direction","body","normal"),&Physics2DServer::body_set_one_way_collision_direction);
+ ClassDB::bind_method(D_METHOD("body_get_one_way_collision_direction","body"),&Physics2DServer::body_get_one_way_collision_direction);
- ObjectTypeDB::bind_method(_MD("body_set_one_way_collision_max_depth","body","depth"),&Physics2DServer::body_set_one_way_collision_max_depth);
- ObjectTypeDB::bind_method(_MD("body_get_one_way_collision_max_depth","body"),&Physics2DServer::body_get_one_way_collision_max_depth);
+ ClassDB::bind_method(D_METHOD("body_set_one_way_collision_max_depth","body","depth"),&Physics2DServer::body_set_one_way_collision_max_depth);
+ ClassDB::bind_method(D_METHOD("body_get_one_way_collision_max_depth","body"),&Physics2DServer::body_get_one_way_collision_max_depth);
- ObjectTypeDB::bind_method(_MD("body_set_omit_force_integration","body","enable"),&Physics2DServer::body_set_omit_force_integration);
- ObjectTypeDB::bind_method(_MD("body_is_omitting_force_integration","body"),&Physics2DServer::body_is_omitting_force_integration);
+ ClassDB::bind_method(D_METHOD("body_set_omit_force_integration","body","enable"),&Physics2DServer::body_set_omit_force_integration);
+ ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration","body"),&Physics2DServer::body_is_omitting_force_integration);
- ObjectTypeDB::bind_method(_MD("body_set_force_integration_callback","body","receiver","method","userdata"),&Physics2DServer::body_set_force_integration_callback,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("body_set_force_integration_callback","body","receiver","method","userdata"),&Physics2DServer::body_set_force_integration_callback,DEFVAL(Variant()));
- ObjectTypeDB::bind_method(_MD("body_test_motion","body","from","motion","margin","result:Physics2DTestMotionResult"),&Physics2DServer::_body_test_motion,DEFVAL(0.08),DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("body_test_motion","body","from","motion","margin","result:Physics2DTestMotionResult"),&Physics2DServer::_body_test_motion,DEFVAL(0.08),DEFVAL(Variant()));
/* JOINT API */
- ObjectTypeDB::bind_method(_MD("joint_set_param","joint","param","value"),&Physics2DServer::joint_set_param);
- ObjectTypeDB::bind_method(_MD("joint_get_param","joint","param"),&Physics2DServer::joint_get_param);
+ ClassDB::bind_method(D_METHOD("joint_set_param","joint","param","value"),&Physics2DServer::joint_set_param);
+ ClassDB::bind_method(D_METHOD("joint_get_param","joint","param"),&Physics2DServer::joint_get_param);
- ObjectTypeDB::bind_method(_MD("pin_joint_create","anchor","body_a","body_b"),&Physics2DServer::pin_joint_create,DEFVAL(RID()));
- ObjectTypeDB::bind_method(_MD("groove_joint_create","groove1_a","groove2_a","anchor_b","body_a","body_b"),&Physics2DServer::groove_joint_create,DEFVAL(RID()),DEFVAL(RID()));
- ObjectTypeDB::bind_method(_MD("damped_spring_joint_create","anchor_a","anchor_b","body_a","body_b"),&Physics2DServer::damped_spring_joint_create,DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("pin_joint_create","anchor","body_a","body_b"),&Physics2DServer::pin_joint_create,DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("groove_joint_create","groove1_a","groove2_a","anchor_b","body_a","body_b"),&Physics2DServer::groove_joint_create,DEFVAL(RID()),DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("damped_spring_joint_create","anchor_a","anchor_b","body_a","body_b"),&Physics2DServer::damped_spring_joint_create,DEFVAL(RID()));
- ObjectTypeDB::bind_method(_MD("damped_string_joint_set_param","joint","param","value"),&Physics2DServer::damped_string_joint_set_param);
- ObjectTypeDB::bind_method(_MD("damped_string_joint_get_param","joint","param"),&Physics2DServer::damped_string_joint_get_param);
+ ClassDB::bind_method(D_METHOD("damped_string_joint_set_param","joint","param","value"),&Physics2DServer::damped_string_joint_set_param);
+ ClassDB::bind_method(D_METHOD("damped_string_joint_get_param","joint","param"),&Physics2DServer::damped_string_joint_get_param);
- ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&Physics2DServer::joint_get_type);
+ ClassDB::bind_method(D_METHOD("joint_get_type","joint"),&Physics2DServer::joint_get_type);
- ObjectTypeDB::bind_method(_MD("free_rid","rid"),&Physics2DServer::free);
+ ClassDB::bind_method(D_METHOD("free_rid","rid"),&Physics2DServer::free);
- ObjectTypeDB::bind_method(_MD("set_active","active"),&Physics2DServer::set_active);
+ ClassDB::bind_method(D_METHOD("set_active","active"),&Physics2DServer::set_active);
- ObjectTypeDB::bind_method(_MD("get_process_info","process_info"),&Physics2DServer::get_process_info);
+ ClassDB::bind_method(D_METHOD("get_process_info","process_info"),&Physics2DServer::get_process_info);
-// ObjectTypeDB::bind_method(_MD("init"),&Physics2DServer::init);
-// ObjectTypeDB::bind_method(_MD("step"),&Physics2DServer::step);
-// ObjectTypeDB::bind_method(_MD("sync"),&Physics2DServer::sync);
- //ObjectTypeDB::bind_method(_MD("flush_queries"),&Physics2DServer::flush_queries);
+ //ClassDB::bind_method(D_METHOD("init"),&Physics2DServer::init);
+ //ClassDB::bind_method(D_METHOD("step"),&Physics2DServer::step);
+ //ClassDB::bind_method(D_METHOD("sync"),&Physics2DServer::sync);
+ //ClassDB::bind_method(D_METHOD("flush_queries"),&Physics2DServer::flush_queries);
BIND_CONSTANT( SPACE_PARAM_CONTACT_RECYCLE_RADIUS );
BIND_CONSTANT( SPACE_PARAM_CONTACT_MAX_SEPARATION );
@@ -710,8 +710,8 @@ void Physics2DServer::_bind_methods() {
BIND_CONSTANT( CCD_MODE_CAST_RAY );
BIND_CONSTANT( CCD_MODE_CAST_SHAPE );
-// BIND_CONSTANT( TYPE_BODY );
-// BIND_CONSTANT( TYPE_AREA );
+ //BIND_CONSTANT( TYPE_BODY );
+ //BIND_CONSTANT( TYPE_AREA );
BIND_CONSTANT( AREA_BODY_ADDED );
BIND_CONSTANT( AREA_BODY_REMOVED );
diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h
index 10707e9314..424d2fa7ce 100644
--- a/servers/physics_2d_server.h
+++ b/servers/physics_2d_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -37,7 +37,7 @@ class Physics2DDirectSpaceState;
class Physics2DDirectBodyState : public Object {
- OBJ_TYPE( Physics2DDirectBodyState, Object );
+ GDCLASS( Physics2DDirectBodyState, Object );
protected:
static void _bind_methods();
public:
@@ -55,8 +55,8 @@ public:
virtual void set_angular_velocity(real_t p_velocity)=0;
virtual real_t get_angular_velocity() const=0;
- virtual void set_transform(const Matrix32& p_transform)=0;
- virtual Matrix32 get_transform() const=0;
+ virtual void set_transform(const Transform2D& p_transform)=0;
+ virtual Transform2D get_transform() const=0;
virtual void set_sleep_state(bool p_enable)=0;
virtual bool is_sleeping() const=0;
@@ -90,10 +90,10 @@ class Physics2DShapeQueryResult;
//used for script
class Physics2DShapeQueryParameters : public Reference {
- OBJ_TYPE(Physics2DShapeQueryParameters, Reference);
+ GDCLASS(Physics2DShapeQueryParameters, Reference);
friend class Physics2DDirectSpaceState;
RID shape;
- Matrix32 transform;
+ Transform2D transform;
Vector2 motion;
float margin;
Set<RID> exclude;
@@ -108,8 +108,8 @@ public:
void set_shape_rid(const RID& p_shape);
RID get_shape_rid() const;
- void set_transform(const Matrix32& p_transform);
- Matrix32 get_transform() const;
+ void set_transform(const Transform2D& p_transform);
+ Transform2D get_transform() const;
void set_motion(const Vector2& p_motion);
Vector2 get_motion() const;
@@ -133,7 +133,7 @@ public:
class Physics2DDirectSpaceState : public Object {
- OBJ_TYPE( Physics2DDirectSpaceState, Object );
+ GDCLASS( Physics2DDirectSpaceState, Object );
Dictionary _intersect_ray(const Vector2& p_from, const Vector2& p_to,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_layers=0,uint32_t p_object_type_mask=TYPE_MASK_COLLISION);
@@ -184,11 +184,11 @@ public:
virtual int intersect_point(const Vector2& p_point,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION,bool p_pick_point=false)=0;
- virtual int intersect_shape(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
+ virtual int intersect_shape(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,float p_margin,ShapeResult *r_results,int p_result_max,const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
- virtual bool cast_motion(const RID& p_shape, const Matrix32& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
+ virtual bool cast_motion(const RID& p_shape, const Transform2D& p_xform,const Vector2& p_motion,float p_margin,float &p_closest_safe,float &p_closest_unsafe, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
- virtual bool collide_shape(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
+ virtual bool collide_shape(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,float p_margin,Vector2 *r_results,int p_result_max,int &r_result_count, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
struct ShapeRestInfo {
@@ -202,7 +202,7 @@ public:
};
- virtual bool rest_info(RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
+ virtual bool rest_info(RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,float p_margin,ShapeRestInfo *r_info, const Set<RID>& p_exclude=Set<RID>(),uint32_t p_layer_mask=0xFFFFFFFF,uint32_t p_object_type_mask=TYPE_MASK_COLLISION)=0;
Physics2DDirectSpaceState();
@@ -211,7 +211,7 @@ public:
class Physics2DShapeQueryResult : public Reference {
- OBJ_TYPE( Physics2DShapeQueryResult, Reference );
+ GDCLASS( Physics2DShapeQueryResult, Reference );
Vector<Physics2DDirectSpaceState::ShapeResult> result;
@@ -234,11 +234,11 @@ class Physics2DTestMotionResult;
class Physics2DServer : public Object {
- OBJ_TYPE( Physics2DServer, Object );
+ GDCLASS( Physics2DServer, Object );
static Physics2DServer * singleton;
- virtual bool _body_test_motion(RID p_body, const Matrix32 &p_from, const Vector2& p_motion, float p_margin=0.08, const Ref<Physics2DTestMotionResult>& p_result=Ref<Physics2DTestMotionResult>());
+ virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2& p_motion, float p_margin=0.08, const Ref<Physics2DTestMotionResult>& p_result=Ref<Physics2DTestMotionResult>());
protected:
static void _bind_methods();
@@ -268,7 +268,7 @@ public:
virtual real_t shape_get_custom_solver_bias(RID p_shape) const=0;
//these work well, but should be used from the main thread only
- virtual bool shape_collide(RID p_shape_A, const Matrix32& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Matrix32& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count)=0;
+ virtual bool shape_collide(RID p_shape_A, const Transform2D& p_xform_A,const Vector2& p_motion_A,RID p_shape_B, const Transform2D& p_xform_B, const Vector2& p_motion_B,Vector2 *r_results,int p_result_max,int &r_result_count)=0;
/* SPACE API */
@@ -333,13 +333,13 @@ public:
virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode)=0;
virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const=0;
- virtual void area_add_shape(RID p_area, RID p_shape, const Matrix32& p_transform=Matrix32())=0;
+ virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D& p_transform=Transform2D())=0;
virtual void area_set_shape(RID p_area, int p_shape_idx,RID p_shape)=0;
- virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Matrix32& p_transform)=0;
+ virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D& p_transform)=0;
virtual int area_get_shape_count(RID p_area) const=0;
virtual RID area_get_shape(RID p_area, int p_shape_idx) const=0;
- virtual Matrix32 area_get_shape_transform(RID p_area, int p_shape_idx) const=0;
+ virtual Transform2D area_get_shape_transform(RID p_area, int p_shape_idx) const=0;
virtual void area_remove_shape(RID p_area, int p_shape_idx)=0;
virtual void area_clear_shapes(RID p_area)=0;
@@ -348,10 +348,10 @@ public:
virtual ObjectID area_get_object_instance_ID(RID p_area) const=0;
virtual void area_set_param(RID p_area,AreaParameter p_param,const Variant& p_value)=0;
- virtual void area_set_transform(RID p_area, const Matrix32& p_transform)=0;
+ virtual void area_set_transform(RID p_area, const Transform2D& p_transform)=0;
virtual Variant area_get_param(RID p_parea,AreaParameter p_param) const=0;
- virtual Matrix32 area_get_transform(RID p_area) const=0;
+ virtual Transform2D area_get_transform(RID p_area) const=0;
virtual void area_set_collision_mask(RID p_area,uint32_t p_mask)=0;
virtual void area_set_layer_mask(RID p_area,uint32_t p_mask)=0;
@@ -382,14 +382,14 @@ public:
virtual void body_set_mode(RID p_body, BodyMode p_mode)=0;
virtual BodyMode body_get_mode(RID p_body) const=0;
- virtual void body_add_shape(RID p_body, RID p_shape, const Matrix32& p_transform=Matrix32())=0;
+ virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D& p_transform=Transform2D())=0;
virtual void body_set_shape(RID p_body, int p_shape_idx,RID p_shape)=0;
- virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Matrix32& p_transform)=0;
+ virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D& p_transform)=0;
virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant& p_metadata)=0;
virtual int body_get_shape_count(RID p_body) const=0;
virtual RID body_get_shape(RID p_body, int p_shape_idx) const=0;
- virtual Matrix32 body_get_shape_transform(RID p_body, int p_shape_idx) const=0;
+ virtual Transform2D body_get_shape_transform(RID p_body, int p_shape_idx) const=0;
virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const=0;
virtual void body_set_shape_as_trigger(RID p_body, int p_shape_idx,bool p_enable)=0;
@@ -479,7 +479,7 @@ public:
virtual void body_set_force_integration_callback(RID p_body,Object *p_receiver,const StringName& p_method,const Variant& p_udata=Variant())=0;
- virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Matrix32& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count)=0;
+ virtual bool body_collide_shape(RID p_body, int p_body_shape,RID p_shape, const Transform2D& p_shape_xform,const Vector2& p_motion,Vector2 *r_results,int p_result_max,int &r_result_count)=0;
virtual void body_set_pickable(RID p_body,bool p_pickable)=0;
@@ -497,7 +497,7 @@ public:
Variant collider_metadata;
};
- virtual bool body_test_motion(RID p_body,const Matrix32& p_from,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL)=0;
+ virtual bool body_test_motion(RID p_body,const Transform2D& p_from,const Vector2& p_motion,float p_margin=0.001,MotionResult *r_result=NULL)=0;
/* JOINT API */
@@ -576,7 +576,7 @@ public:
class Physics2DTestMotionResult : public Reference {
- OBJ_TYPE( Physics2DTestMotionResult, Reference );
+ GDCLASS( Physics2DTestMotionResult, Reference );
Physics2DServer::MotionResult result;
bool colliding;
diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp
index 685477ed79..e76bfd113c 100644
--- a/servers/physics_server.cpp
+++ b/servers/physics_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -74,42 +74,46 @@ PhysicsServer * PhysicsServer::get_singleton() {
void PhysicsDirectBodyState::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("get_total_gravity"),&PhysicsDirectBodyState::get_total_gravity);
- ObjectTypeDB::bind_method(_MD("get_total_linear_damp"),&PhysicsDirectBodyState::get_total_linear_damp);
- ObjectTypeDB::bind_method(_MD("get_total_angular_damp"),&PhysicsDirectBodyState::get_total_angular_damp);
+ ClassDB::bind_method(D_METHOD("get_total_gravity"),&PhysicsDirectBodyState::get_total_gravity);
+ ClassDB::bind_method(D_METHOD("get_total_linear_damp"),&PhysicsDirectBodyState::get_total_linear_damp);
+ ClassDB::bind_method(D_METHOD("get_total_angular_damp"),&PhysicsDirectBodyState::get_total_angular_damp);
- ObjectTypeDB::bind_method(_MD("get_inverse_mass"),&PhysicsDirectBodyState::get_inverse_mass);
- ObjectTypeDB::bind_method(_MD("get_inverse_inertia"),&PhysicsDirectBodyState::get_inverse_inertia);
+ ClassDB::bind_method(D_METHOD("get_center_of_mass"),&PhysicsDirectBodyState::get_center_of_mass);
+ ClassDB::bind_method(D_METHOD("get_principal_inetria_axes"),&PhysicsDirectBodyState::get_principal_inertia_axes);
- ObjectTypeDB::bind_method(_MD("set_linear_velocity","velocity"),&PhysicsDirectBodyState::set_linear_velocity);
- ObjectTypeDB::bind_method(_MD("get_linear_velocity"),&PhysicsDirectBodyState::get_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_inverse_mass"),&PhysicsDirectBodyState::get_inverse_mass);
+ ClassDB::bind_method(D_METHOD("get_inverse_inertia"),&PhysicsDirectBodyState::get_inverse_inertia);
- ObjectTypeDB::bind_method(_MD("set_angular_velocity","velocity"),&PhysicsDirectBodyState::set_angular_velocity);
- ObjectTypeDB::bind_method(_MD("get_angular_velocity"),&PhysicsDirectBodyState::get_angular_velocity);
+ ClassDB::bind_method(D_METHOD("set_linear_velocity","velocity"),&PhysicsDirectBodyState::set_linear_velocity);
+ ClassDB::bind_method(D_METHOD("get_linear_velocity"),&PhysicsDirectBodyState::get_linear_velocity);
- ObjectTypeDB::bind_method(_MD("set_transform","transform"),&PhysicsDirectBodyState::set_transform);
- ObjectTypeDB::bind_method(_MD("get_transform"),&PhysicsDirectBodyState::get_transform);
+ ClassDB::bind_method(D_METHOD("set_angular_velocity","velocity"),&PhysicsDirectBodyState::set_angular_velocity);
+ ClassDB::bind_method(D_METHOD("get_angular_velocity"),&PhysicsDirectBodyState::get_angular_velocity);
- ObjectTypeDB::bind_method(_MD("add_force","force","pos"),&PhysicsDirectBodyState::add_force);
- ObjectTypeDB::bind_method(_MD("apply_impulse","pos","j"),&PhysicsDirectBodyState::apply_impulse);
+ ClassDB::bind_method(D_METHOD("set_transform","transform"),&PhysicsDirectBodyState::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"),&PhysicsDirectBodyState::get_transform);
- ObjectTypeDB::bind_method(_MD("set_sleep_state","enabled"),&PhysicsDirectBodyState::set_sleep_state);
- ObjectTypeDB::bind_method(_MD("is_sleeping"),&PhysicsDirectBodyState::is_sleeping);
+ ClassDB::bind_method(D_METHOD("add_force","force","pos"),&PhysicsDirectBodyState::add_force);
+ ClassDB::bind_method(D_METHOD("apply_impulse","pos","j"),&PhysicsDirectBodyState::apply_impulse);
+ ClassDB::bind_method(D_METHOD("apply_torqe_impulse","j"),&PhysicsDirectBodyState::apply_torque_impulse);
- ObjectTypeDB::bind_method(_MD("get_contact_count"),&PhysicsDirectBodyState::get_contact_count);
+ ClassDB::bind_method(D_METHOD("set_sleep_state","enabled"),&PhysicsDirectBodyState::set_sleep_state);
+ ClassDB::bind_method(D_METHOD("is_sleeping"),&PhysicsDirectBodyState::is_sleeping);
- ObjectTypeDB::bind_method(_MD("get_contact_local_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_local_pos);
- ObjectTypeDB::bind_method(_MD("get_contact_local_normal","contact_idx"),&PhysicsDirectBodyState::get_contact_local_normal);
- ObjectTypeDB::bind_method(_MD("get_contact_local_shape","contact_idx"),&PhysicsDirectBodyState::get_contact_local_shape);
- ObjectTypeDB::bind_method(_MD("get_contact_collider","contact_idx"),&PhysicsDirectBodyState::get_contact_collider);
- ObjectTypeDB::bind_method(_MD("get_contact_collider_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_pos);
- ObjectTypeDB::bind_method(_MD("get_contact_collider_id","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_id);
- ObjectTypeDB::bind_method(_MD("get_contact_collider_object","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_object);
- ObjectTypeDB::bind_method(_MD("get_contact_collider_shape","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_shape);
- ObjectTypeDB::bind_method(_MD("get_contact_collider_velocity_at_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_velocity_at_pos);
- ObjectTypeDB::bind_method(_MD("get_step"),&PhysicsDirectBodyState::get_step);
- ObjectTypeDB::bind_method(_MD("integrate_forces"),&PhysicsDirectBodyState::integrate_forces);
- ObjectTypeDB::bind_method(_MD("get_space_state:PhysicsDirectSpaceState"),&PhysicsDirectBodyState::get_space_state);
+ ClassDB::bind_method(D_METHOD("get_contact_count"),&PhysicsDirectBodyState::get_contact_count);
+
+ ClassDB::bind_method(D_METHOD("get_contact_local_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_local_pos);
+ ClassDB::bind_method(D_METHOD("get_contact_local_normal","contact_idx"),&PhysicsDirectBodyState::get_contact_local_normal);
+ ClassDB::bind_method(D_METHOD("get_contact_local_shape","contact_idx"),&PhysicsDirectBodyState::get_contact_local_shape);
+ ClassDB::bind_method(D_METHOD("get_contact_collider","contact_idx"),&PhysicsDirectBodyState::get_contact_collider);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_pos);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_id","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_id);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_object","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_object);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_shape","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_shape);
+ ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_pos","contact_idx"),&PhysicsDirectBodyState::get_contact_collider_velocity_at_pos);
+ ClassDB::bind_method(D_METHOD("get_step"),&PhysicsDirectBodyState::get_step);
+ ClassDB::bind_method(D_METHOD("integrate_forces"),&PhysicsDirectBodyState::integrate_forces);
+ ClassDB::bind_method(D_METHOD("get_space_state:PhysicsDirectSpaceState"),&PhysicsDirectBodyState::get_space_state);
}
@@ -174,7 +178,7 @@ int PhysicsShapeQueryParameters::get_object_type_mask() const{
}
void PhysicsShapeQueryParameters::set_exclude(const Vector<RID>& p_exclude) {
- exclude.clear();;
+ exclude.clear();
for(int i=0;i<p_exclude.size();i++)
exclude.insert(p_exclude[i]);
@@ -193,24 +197,24 @@ Vector<RID> PhysicsShapeQueryParameters::get_exclude() const{
void PhysicsShapeQueryParameters::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("set_shape","shape:Shape"),&PhysicsShapeQueryParameters::set_shape);
- ObjectTypeDB::bind_method(_MD("set_shape_rid","shape"),&PhysicsShapeQueryParameters::set_shape_rid);
- ObjectTypeDB::bind_method(_MD("get_shape_rid"),&PhysicsShapeQueryParameters::get_shape_rid);
+ ClassDB::bind_method(D_METHOD("set_shape","shape:Shape"),&PhysicsShapeQueryParameters::set_shape);
+ ClassDB::bind_method(D_METHOD("set_shape_rid","shape"),&PhysicsShapeQueryParameters::set_shape_rid);
+ ClassDB::bind_method(D_METHOD("get_shape_rid"),&PhysicsShapeQueryParameters::get_shape_rid);
- ObjectTypeDB::bind_method(_MD("set_transform","transform"),&PhysicsShapeQueryParameters::set_transform);
- ObjectTypeDB::bind_method(_MD("get_transform"),&PhysicsShapeQueryParameters::get_transform);
+ ClassDB::bind_method(D_METHOD("set_transform","transform"),&PhysicsShapeQueryParameters::set_transform);
+ ClassDB::bind_method(D_METHOD("get_transform"),&PhysicsShapeQueryParameters::get_transform);
- ObjectTypeDB::bind_method(_MD("set_margin","margin"),&PhysicsShapeQueryParameters::set_margin);
- ObjectTypeDB::bind_method(_MD("get_margin"),&PhysicsShapeQueryParameters::get_margin);
+ ClassDB::bind_method(D_METHOD("set_margin","margin"),&PhysicsShapeQueryParameters::set_margin);
+ ClassDB::bind_method(D_METHOD("get_margin"),&PhysicsShapeQueryParameters::get_margin);
- ObjectTypeDB::bind_method(_MD("set_layer_mask","layer_mask"),&PhysicsShapeQueryParameters::set_layer_mask);
- ObjectTypeDB::bind_method(_MD("get_layer_mask"),&PhysicsShapeQueryParameters::get_layer_mask);
+ ClassDB::bind_method(D_METHOD("set_layer_mask","layer_mask"),&PhysicsShapeQueryParameters::set_layer_mask);
+ ClassDB::bind_method(D_METHOD("get_layer_mask"),&PhysicsShapeQueryParameters::get_layer_mask);
- ObjectTypeDB::bind_method(_MD("set_object_type_mask","object_type_mask"),&PhysicsShapeQueryParameters::set_object_type_mask);
- ObjectTypeDB::bind_method(_MD("get_object_type_mask"),&PhysicsShapeQueryParameters::get_object_type_mask);
+ ClassDB::bind_method(D_METHOD("set_object_type_mask","object_type_mask"),&PhysicsShapeQueryParameters::set_object_type_mask);
+ ClassDB::bind_method(D_METHOD("get_object_type_mask"),&PhysicsShapeQueryParameters::get_object_type_mask);
- ObjectTypeDB::bind_method(_MD("set_exclude","exclude"),&PhysicsShapeQueryParameters::set_exclude);
- ObjectTypeDB::bind_method(_MD("get_exclude"),&PhysicsShapeQueryParameters::get_exclude);
+ ClassDB::bind_method(D_METHOD("set_exclude","exclude"),&PhysicsShapeQueryParameters::set_exclude);
+ ClassDB::bind_method(D_METHOD("get_exclude"),&PhysicsShapeQueryParameters::get_exclude);
}
@@ -267,9 +271,9 @@ Dictionary PhysicsDirectSpaceState::_intersect_ray(const Vector3& p_from, const
bool res = intersect_ray(p_from,p_to,inters,exclude,p_layers,p_object_type_mask);
if (!res)
- return Dictionary(true);
+ return Dictionary();
- Dictionary d(true);
+ Dictionary d;
d["position"]=inters.position;
d["normal"]=inters.normal;
d["collider_id"]=inters.collider_id;
@@ -306,7 +310,7 @@ Array PhysicsDirectSpaceState::_cast_motion(const Ref<PhysicsShapeQueryParameter
bool res = cast_motion(psq->shape,psq->transform,p_motion,psq->margin,closest_safe,closest_unsafe,psq->exclude,psq->layer_mask,psq->object_type_mask);
if (!res)
return Array();
- Array ret(true);
+ Array ret;
ret.resize(2);
ret[0]=closest_safe;
ret[1]=closest_unsafe;
@@ -333,7 +337,7 @@ Dictionary PhysicsDirectSpaceState::_get_rest_info(const Ref<PhysicsShapeQueryPa
ShapeRestInfo sri;
bool res = rest_info(psq->shape,psq->transform,psq->margin,&sri,psq->exclude,psq->layer_mask,psq->object_type_mask);
- Dictionary r(true);
+ Dictionary r;
if (!res)
return r;
@@ -359,14 +363,14 @@ PhysicsDirectSpaceState::PhysicsDirectSpaceState() {
void PhysicsDirectSpaceState::_bind_methods() {
-// ObjectTypeDB::bind_method(_MD("intersect_ray","from","to","exclude","umask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0));
-// ObjectTypeDB::bind_method(_MD("intersect_shape:PhysicsShapeQueryResult","shape","xform","result_max","exclude","umask"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0));
+ //ClassDB::bind_method(D_METHOD("intersect_ray","from","to","exclude","umask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0));
+ //ClassDB::bind_method(D_METHOD("intersect_shape:PhysicsShapeQueryResult","shape","xform","result_max","exclude","umask"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(Array()),DEFVAL(0));
- ObjectTypeDB::bind_method(_MD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
- ObjectTypeDB::bind_method(_MD("intersect_shape","shape:PhysicsShapeQueryParameters","max_results"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(32));
- ObjectTypeDB::bind_method(_MD("cast_motion","shape:PhysicsShapeQueryParameters","motion"),&PhysicsDirectSpaceState::_cast_motion);
- ObjectTypeDB::bind_method(_MD("collide_shape","shape:PhysicsShapeQueryParameters","max_results"),&PhysicsDirectSpaceState::_collide_shape,DEFVAL(32));
- ObjectTypeDB::bind_method(_MD("get_rest_info","shape:PhysicsShapeQueryParameters"),&PhysicsDirectSpaceState::_get_rest_info);
+ ClassDB::bind_method(D_METHOD("intersect_ray:Dictionary","from","to","exclude","layer_mask","type_mask"),&PhysicsDirectSpaceState::_intersect_ray,DEFVAL(Array()),DEFVAL(0x7FFFFFFF),DEFVAL(TYPE_MASK_COLLISION));
+ ClassDB::bind_method(D_METHOD("intersect_shape","shape:PhysicsShapeQueryParameters","max_results"),&PhysicsDirectSpaceState::_intersect_shape,DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("cast_motion","shape:PhysicsShapeQueryParameters","motion"),&PhysicsDirectSpaceState::_cast_motion);
+ ClassDB::bind_method(D_METHOD("collide_shape","shape:PhysicsShapeQueryParameters","max_results"),&PhysicsDirectSpaceState::_collide_shape,DEFVAL(32));
+ ClassDB::bind_method(D_METHOD("get_rest_info","shape:PhysicsShapeQueryParameters"),&PhysicsDirectSpaceState::_get_rest_info);
BIND_CONSTANT( TYPE_MASK_STATIC_BODY );
@@ -407,11 +411,11 @@ PhysicsShapeQueryResult::PhysicsShapeQueryResult() {
void PhysicsShapeQueryResult::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("get_result_count"),&PhysicsShapeQueryResult::get_result_count);
- ObjectTypeDB::bind_method(_MD("get_result_rid","idx"),&PhysicsShapeQueryResult::get_result_rid);
- ObjectTypeDB::bind_method(_MD("get_result_object_id","idx"),&PhysicsShapeQueryResult::get_result_object_id);
- ObjectTypeDB::bind_method(_MD("get_result_object","idx"),&PhysicsShapeQueryResult::get_result_object);
- ObjectTypeDB::bind_method(_MD("get_result_object_shape","idx"),&PhysicsShapeQueryResult::get_result_object_shape);
+ ClassDB::bind_method(D_METHOD("get_result_count"),&PhysicsShapeQueryResult::get_result_count);
+ ClassDB::bind_method(D_METHOD("get_result_rid","idx"),&PhysicsShapeQueryResult::get_result_rid);
+ ClassDB::bind_method(D_METHOD("get_result_object_id","idx"),&PhysicsShapeQueryResult::get_result_object_id);
+ ClassDB::bind_method(D_METHOD("get_result_object","idx"),&PhysicsShapeQueryResult::get_result_object);
+ ClassDB::bind_method(D_METHOD("get_result_object_shape","idx"),&PhysicsShapeQueryResult::get_result_object_shape);
}
@@ -425,117 +429,118 @@ void PhysicsShapeQueryResult::_bind_methods() {
void PhysicsServer::_bind_methods() {
- ObjectTypeDB::bind_method(_MD("shape_create","type"),&PhysicsServer::shape_create);
- ObjectTypeDB::bind_method(_MD("shape_set_data","shape","data"),&PhysicsServer::shape_set_data);
+ ClassDB::bind_method(D_METHOD("shape_create","type"),&PhysicsServer::shape_create);
+ ClassDB::bind_method(D_METHOD("shape_set_data","shape","data"),&PhysicsServer::shape_set_data);
- ObjectTypeDB::bind_method(_MD("shape_get_type","shape"),&PhysicsServer::shape_get_type);
- ObjectTypeDB::bind_method(_MD("shape_get_data","shape"),&PhysicsServer::shape_get_data);
+ ClassDB::bind_method(D_METHOD("shape_get_type","shape"),&PhysicsServer::shape_get_type);
+ ClassDB::bind_method(D_METHOD("shape_get_data","shape"),&PhysicsServer::shape_get_data);
- ObjectTypeDB::bind_method(_MD("space_create"),&PhysicsServer::space_create);
- ObjectTypeDB::bind_method(_MD("space_set_active","space","active"),&PhysicsServer::space_set_active);
- ObjectTypeDB::bind_method(_MD("space_is_active","space"),&PhysicsServer::space_is_active);
- ObjectTypeDB::bind_method(_MD("space_set_param","space","param","value"),&PhysicsServer::space_set_param);
- ObjectTypeDB::bind_method(_MD("space_get_param","space","param"),&PhysicsServer::space_get_param);
- ObjectTypeDB::bind_method(_MD("space_get_direct_state:PhysicsDirectSpaceState","space"),&PhysicsServer::space_get_direct_state);
+ ClassDB::bind_method(D_METHOD("space_create"),&PhysicsServer::space_create);
+ ClassDB::bind_method(D_METHOD("space_set_active","space","active"),&PhysicsServer::space_set_active);
+ ClassDB::bind_method(D_METHOD("space_is_active","space"),&PhysicsServer::space_is_active);
+ ClassDB::bind_method(D_METHOD("space_set_param","space","param","value"),&PhysicsServer::space_set_param);
+ ClassDB::bind_method(D_METHOD("space_get_param","space","param"),&PhysicsServer::space_get_param);
+ ClassDB::bind_method(D_METHOD("space_get_direct_state:PhysicsDirectSpaceState","space"),&PhysicsServer::space_get_direct_state);
- ObjectTypeDB::bind_method(_MD("area_create"),&PhysicsServer::area_create);
- ObjectTypeDB::bind_method(_MD("area_set_space","area","space"),&PhysicsServer::area_set_space);
- ObjectTypeDB::bind_method(_MD("area_get_space","area"),&PhysicsServer::area_get_space);
+ ClassDB::bind_method(D_METHOD("area_create"),&PhysicsServer::area_create);
+ ClassDB::bind_method(D_METHOD("area_set_space","area","space"),&PhysicsServer::area_set_space);
+ ClassDB::bind_method(D_METHOD("area_get_space","area"),&PhysicsServer::area_get_space);
- ObjectTypeDB::bind_method(_MD("area_set_space_override_mode","area","mode"),&PhysicsServer::area_set_space_override_mode);
- ObjectTypeDB::bind_method(_MD("area_get_space_override_mode","area"),&PhysicsServer::area_get_space_override_mode);
+ ClassDB::bind_method(D_METHOD("area_set_space_override_mode","area","mode"),&PhysicsServer::area_set_space_override_mode);
+ ClassDB::bind_method(D_METHOD("area_get_space_override_mode","area"),&PhysicsServer::area_get_space_override_mode);
- ObjectTypeDB::bind_method(_MD("area_add_shape","area","shape","transform"),&PhysicsServer::area_add_shape,DEFVAL(Transform()));
- ObjectTypeDB::bind_method(_MD("area_set_shape","area","shape_idx","shape"),&PhysicsServer::area_set_shape);
- ObjectTypeDB::bind_method(_MD("area_set_shape_transform","area","shape_idx","transform"),&PhysicsServer::area_set_shape_transform);
+ ClassDB::bind_method(D_METHOD("area_add_shape","area","shape","transform"),&PhysicsServer::area_add_shape,DEFVAL(Transform()));
+ ClassDB::bind_method(D_METHOD("area_set_shape","area","shape_idx","shape"),&PhysicsServer::area_set_shape);
+ ClassDB::bind_method(D_METHOD("area_set_shape_transform","area","shape_idx","transform"),&PhysicsServer::area_set_shape_transform);
- ObjectTypeDB::bind_method(_MD("area_get_shape_count","area"),&PhysicsServer::area_get_shape_count);
- ObjectTypeDB::bind_method(_MD("area_get_shape","area","shape_idx"),&PhysicsServer::area_get_shape);
- ObjectTypeDB::bind_method(_MD("area_get_shape_transform","area","shape_idx"),&PhysicsServer::area_get_shape_transform);
+ ClassDB::bind_method(D_METHOD("area_get_shape_count","area"),&PhysicsServer::area_get_shape_count);
+ ClassDB::bind_method(D_METHOD("area_get_shape","area","shape_idx"),&PhysicsServer::area_get_shape);
+ ClassDB::bind_method(D_METHOD("area_get_shape_transform","area","shape_idx"),&PhysicsServer::area_get_shape_transform);
- ObjectTypeDB::bind_method(_MD("area_remove_shape","area","shape_idx"),&PhysicsServer::area_remove_shape);
- ObjectTypeDB::bind_method(_MD("area_clear_shapes","area"),&PhysicsServer::area_clear_shapes);
+ ClassDB::bind_method(D_METHOD("area_remove_shape","area","shape_idx"),&PhysicsServer::area_remove_shape);
+ ClassDB::bind_method(D_METHOD("area_clear_shapes","area"),&PhysicsServer::area_clear_shapes);
- ObjectTypeDB::bind_method(_MD("area_set_layer_mask","area","mask"),&PhysicsServer::area_set_layer_mask);
- ObjectTypeDB::bind_method(_MD("area_set_collision_mask","area","mask"),&PhysicsServer::area_set_collision_mask);
+ ClassDB::bind_method(D_METHOD("area_set_layer_mask","area","mask"),&PhysicsServer::area_set_layer_mask);
+ ClassDB::bind_method(D_METHOD("area_set_collision_mask","area","mask"),&PhysicsServer::area_set_collision_mask);
- ObjectTypeDB::bind_method(_MD("area_set_param","area","param","value"),&PhysicsServer::area_set_param);
- ObjectTypeDB::bind_method(_MD("area_set_transform","area","transform"),&PhysicsServer::area_set_transform);
+ ClassDB::bind_method(D_METHOD("area_set_param","area","param","value"),&PhysicsServer::area_set_param);
+ ClassDB::bind_method(D_METHOD("area_set_transform","area","transform"),&PhysicsServer::area_set_transform);
- ObjectTypeDB::bind_method(_MD("area_get_param","area","param"),&PhysicsServer::area_get_param);
- ObjectTypeDB::bind_method(_MD("area_get_transform","area"),&PhysicsServer::area_get_transform);
+ ClassDB::bind_method(D_METHOD("area_get_param","area","param"),&PhysicsServer::area_get_param);
+ ClassDB::bind_method(D_METHOD("area_get_transform","area"),&PhysicsServer::area_get_transform);
- ObjectTypeDB::bind_method(_MD("area_attach_object_instance_ID","area","id"),&PhysicsServer::area_attach_object_instance_ID);
- ObjectTypeDB::bind_method(_MD("area_get_object_instance_ID","area"),&PhysicsServer::area_get_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("area_attach_object_instance_ID","area","id"),&PhysicsServer::area_attach_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("area_get_object_instance_ID","area"),&PhysicsServer::area_get_object_instance_ID);
- ObjectTypeDB::bind_method(_MD("area_set_monitor_callback","area","receiver","method"),&PhysicsServer::area_set_monitor_callback);
+ ClassDB::bind_method(D_METHOD("area_set_monitor_callback","area","receiver","method"),&PhysicsServer::area_set_monitor_callback);
- ObjectTypeDB::bind_method(_MD("area_set_ray_pickable","area","enable"),&PhysicsServer::area_set_ray_pickable);
- ObjectTypeDB::bind_method(_MD("area_is_ray_pickable","area"),&PhysicsServer::area_is_ray_pickable);
+ ClassDB::bind_method(D_METHOD("area_set_ray_pickable","area","enable"),&PhysicsServer::area_set_ray_pickable);
+ ClassDB::bind_method(D_METHOD("area_is_ray_pickable","area"),&PhysicsServer::area_is_ray_pickable);
- ObjectTypeDB::bind_method(_MD("body_create","mode","init_sleeping"),&PhysicsServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("body_create","mode","init_sleeping"),&PhysicsServer::body_create,DEFVAL(BODY_MODE_RIGID),DEFVAL(false));
- ObjectTypeDB::bind_method(_MD("body_set_space","body","space"),&PhysicsServer::body_set_space);
- ObjectTypeDB::bind_method(_MD("body_get_space","body"),&PhysicsServer::body_get_space);
+ ClassDB::bind_method(D_METHOD("body_set_space","body","space"),&PhysicsServer::body_set_space);
+ ClassDB::bind_method(D_METHOD("body_get_space","body"),&PhysicsServer::body_get_space);
- ObjectTypeDB::bind_method(_MD("body_set_mode","body","mode"),&PhysicsServer::body_set_mode);
- ObjectTypeDB::bind_method(_MD("body_get_mode","body"),&PhysicsServer::body_get_mode);
+ ClassDB::bind_method(D_METHOD("body_set_mode","body","mode"),&PhysicsServer::body_set_mode);
+ ClassDB::bind_method(D_METHOD("body_get_mode","body"),&PhysicsServer::body_get_mode);
- ObjectTypeDB::bind_method(_MD("body_set_layer_mask","body","mask"),&PhysicsServer::body_set_layer_mask);
- ObjectTypeDB::bind_method(_MD("body_get_layer_mask","body"),&PhysicsServer::body_get_layer_mask);
+ ClassDB::bind_method(D_METHOD("body_set_layer_mask","body","mask"),&PhysicsServer::body_set_layer_mask);
+ ClassDB::bind_method(D_METHOD("body_get_layer_mask","body"),&PhysicsServer::body_get_layer_mask);
- ObjectTypeDB::bind_method(_MD("body_set_collision_mask","body","mask"),&PhysicsServer::body_set_collision_mask);
- ObjectTypeDB::bind_method(_MD("body_get_collision_mask","body"),&PhysicsServer::body_get_collision_mask);
+ ClassDB::bind_method(D_METHOD("body_set_collision_mask","body","mask"),&PhysicsServer::body_set_collision_mask);
+ ClassDB::bind_method(D_METHOD("body_get_collision_mask","body"),&PhysicsServer::body_get_collision_mask);
- ObjectTypeDB::bind_method(_MD("body_add_shape","body","shape","transform"),&PhysicsServer::body_add_shape,DEFVAL(Transform()));
- ObjectTypeDB::bind_method(_MD("body_set_shape","body","shape_idx","shape"),&PhysicsServer::body_set_shape);
- ObjectTypeDB::bind_method(_MD("body_set_shape_transform","body","shape_idx","transform"),&PhysicsServer::body_set_shape_transform);
+ ClassDB::bind_method(D_METHOD("body_add_shape","body","shape","transform"),&PhysicsServer::body_add_shape,DEFVAL(Transform()));
+ ClassDB::bind_method(D_METHOD("body_set_shape","body","shape_idx","shape"),&PhysicsServer::body_set_shape);
+ ClassDB::bind_method(D_METHOD("body_set_shape_transform","body","shape_idx","transform"),&PhysicsServer::body_set_shape_transform);
- ObjectTypeDB::bind_method(_MD("body_get_shape_count","body"),&PhysicsServer::body_get_shape_count);
- ObjectTypeDB::bind_method(_MD("body_get_shape","body","shape_idx"),&PhysicsServer::body_get_shape);
- ObjectTypeDB::bind_method(_MD("body_get_shape_transform","body","shape_idx"),&PhysicsServer::body_get_shape_transform);
+ ClassDB::bind_method(D_METHOD("body_get_shape_count","body"),&PhysicsServer::body_get_shape_count);
+ ClassDB::bind_method(D_METHOD("body_get_shape","body","shape_idx"),&PhysicsServer::body_get_shape);
+ ClassDB::bind_method(D_METHOD("body_get_shape_transform","body","shape_idx"),&PhysicsServer::body_get_shape_transform);
- ObjectTypeDB::bind_method(_MD("body_remove_shape","body","shape_idx"),&PhysicsServer::body_remove_shape);
- ObjectTypeDB::bind_method(_MD("body_clear_shapes","body"),&PhysicsServer::body_clear_shapes);
+ ClassDB::bind_method(D_METHOD("body_remove_shape","body","shape_idx"),&PhysicsServer::body_remove_shape);
+ ClassDB::bind_method(D_METHOD("body_clear_shapes","body"),&PhysicsServer::body_clear_shapes);
- ObjectTypeDB::bind_method(_MD("body_attach_object_instance_ID","body","id"),&PhysicsServer::body_attach_object_instance_ID);
- ObjectTypeDB::bind_method(_MD("body_get_object_instance_ID","body"),&PhysicsServer::body_get_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("body_attach_object_instance_ID","body","id"),&PhysicsServer::body_attach_object_instance_ID);
+ ClassDB::bind_method(D_METHOD("body_get_object_instance_ID","body"),&PhysicsServer::body_get_object_instance_ID);
- ObjectTypeDB::bind_method(_MD("body_set_enable_continuous_collision_detection","body","enable"),&PhysicsServer::body_set_enable_continuous_collision_detection);
- ObjectTypeDB::bind_method(_MD("body_is_continuous_collision_detection_enabled","body"),&PhysicsServer::body_is_continuous_collision_detection_enabled);
+ ClassDB::bind_method(D_METHOD("body_set_enable_continuous_collision_detection","body","enable"),&PhysicsServer::body_set_enable_continuous_collision_detection);
+ ClassDB::bind_method(D_METHOD("body_is_continuous_collision_detection_enabled","body"),&PhysicsServer::body_is_continuous_collision_detection_enabled);
- //ObjectTypeDB::bind_method(_MD("body_set_user_flags","flags""),&PhysicsServer::body_set_shape,DEFVAL(Transform));
- //ObjectTypeDB::bind_method(_MD("body_get_user_flags","body","shape_idx","shape"),&PhysicsServer::body_get_shape);
+ //ClassDB::bind_method(D_METHOD("body_set_user_flags","flags""),&PhysicsServer::body_set_shape,DEFVAL(Transform));
+ //ClassDB::bind_method(D_METHOD("body_get_user_flags","body","shape_idx","shape"),&PhysicsServer::body_get_shape);
- ObjectTypeDB::bind_method(_MD("body_set_param","body","param","value"),&PhysicsServer::body_set_param);
- ObjectTypeDB::bind_method(_MD("body_get_param","body","param"),&PhysicsServer::body_get_param);
+ ClassDB::bind_method(D_METHOD("body_set_param","body","param","value"),&PhysicsServer::body_set_param);
+ ClassDB::bind_method(D_METHOD("body_get_param","body","param"),&PhysicsServer::body_get_param);
- ObjectTypeDB::bind_method(_MD("body_set_state","body","state","value"),&PhysicsServer::body_set_state);
- ObjectTypeDB::bind_method(_MD("body_get_state","body","state"),&PhysicsServer::body_get_state);
+ ClassDB::bind_method(D_METHOD("body_set_state","body","state","value"),&PhysicsServer::body_set_state);
+ ClassDB::bind_method(D_METHOD("body_get_state","body","state"),&PhysicsServer::body_get_state);
- ObjectTypeDB::bind_method(_MD("body_apply_impulse","body","pos","impulse"),&PhysicsServer::body_apply_impulse);
- ObjectTypeDB::bind_method(_MD("body_set_axis_velocity","body","axis_velocity"),&PhysicsServer::body_set_axis_velocity);
+ ClassDB::bind_method(D_METHOD("body_apply_impulse","body","pos","impulse"),&PhysicsServer::body_apply_impulse);
+ ClassDB::bind_method(D_METHOD("body_apply_torque_impulse","body","impulse"),&PhysicsServer::body_apply_torque_impulse);
+ ClassDB::bind_method(D_METHOD("body_set_axis_velocity","body","axis_velocity"),&PhysicsServer::body_set_axis_velocity);
- ObjectTypeDB::bind_method(_MD("body_set_axis_lock","body","axis"),&PhysicsServer::body_set_axis_lock);
- ObjectTypeDB::bind_method(_MD("body_get_axis_lock","body"),&PhysicsServer::body_get_axis_lock);
+ ClassDB::bind_method(D_METHOD("body_set_axis_lock","body","axis"),&PhysicsServer::body_set_axis_lock);
+ ClassDB::bind_method(D_METHOD("body_get_axis_lock","body"),&PhysicsServer::body_get_axis_lock);
- ObjectTypeDB::bind_method(_MD("body_add_collision_exception","body","excepted_body"),&PhysicsServer::body_add_collision_exception);
- ObjectTypeDB::bind_method(_MD("body_remove_collision_exception","body","excepted_body"),&PhysicsServer::body_remove_collision_exception);
-// virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions)=0;
+ ClassDB::bind_method(D_METHOD("body_add_collision_exception","body","excepted_body"),&PhysicsServer::body_add_collision_exception);
+ ClassDB::bind_method(D_METHOD("body_remove_collision_exception","body","excepted_body"),&PhysicsServer::body_remove_collision_exception);
+ //virtual void body_get_collision_exceptions(RID p_body, List<RID> *p_exceptions)=0;
- ObjectTypeDB::bind_method(_MD("body_set_max_contacts_reported","body","amount"),&PhysicsServer::body_set_max_contacts_reported);
- ObjectTypeDB::bind_method(_MD("body_get_max_contacts_reported","body"),&PhysicsServer::body_get_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("body_set_max_contacts_reported","body","amount"),&PhysicsServer::body_set_max_contacts_reported);
+ ClassDB::bind_method(D_METHOD("body_get_max_contacts_reported","body"),&PhysicsServer::body_get_max_contacts_reported);
- ObjectTypeDB::bind_method(_MD("body_set_omit_force_integration","body","enable"),&PhysicsServer::body_set_omit_force_integration);
- ObjectTypeDB::bind_method(_MD("body_is_omitting_force_integration","body"),&PhysicsServer::body_is_omitting_force_integration);
+ ClassDB::bind_method(D_METHOD("body_set_omit_force_integration","body","enable"),&PhysicsServer::body_set_omit_force_integration);
+ ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration","body"),&PhysicsServer::body_is_omitting_force_integration);
- ObjectTypeDB::bind_method(_MD("body_set_force_integration_callback","body","receiver","method","userdata"),&PhysicsServer::body_set_force_integration_callback,DEFVAL(Variant()));
+ ClassDB::bind_method(D_METHOD("body_set_force_integration_callback","body","receiver","method","userdata"),&PhysicsServer::body_set_force_integration_callback,DEFVAL(Variant()));
- ObjectTypeDB::bind_method(_MD("body_set_ray_pickable","body","enable"),&PhysicsServer::body_set_ray_pickable);
- ObjectTypeDB::bind_method(_MD("body_is_ray_pickable","body"),&PhysicsServer::body_is_ray_pickable);
+ ClassDB::bind_method(D_METHOD("body_set_ray_pickable","body","enable"),&PhysicsServer::body_set_ray_pickable);
+ ClassDB::bind_method(D_METHOD("body_is_ray_pickable","body"),&PhysicsServer::body_is_ray_pickable);
/* JOINT API */
@@ -545,15 +550,15 @@ void PhysicsServer::_bind_methods() {
BIND_CONSTANT( JOINT_CONE_TWIST );
BIND_CONSTANT( JOINT_6DOF );
- ObjectTypeDB::bind_method(_MD("joint_create_pin","body_A","local_A","body_B","local_B"),&PhysicsServer::joint_create_pin);
- ObjectTypeDB::bind_method(_MD("pin_joint_set_param","joint","param","value"),&PhysicsServer::pin_joint_set_param);
- ObjectTypeDB::bind_method(_MD("pin_joint_get_param","joint","param"),&PhysicsServer::pin_joint_get_param);
+ ClassDB::bind_method(D_METHOD("joint_create_pin","body_A","local_A","body_B","local_B"),&PhysicsServer::joint_create_pin);
+ ClassDB::bind_method(D_METHOD("pin_joint_set_param","joint","param","value"),&PhysicsServer::pin_joint_set_param);
+ ClassDB::bind_method(D_METHOD("pin_joint_get_param","joint","param"),&PhysicsServer::pin_joint_get_param);
- ObjectTypeDB::bind_method(_MD("pin_joint_set_local_A","joint","local_A"),&PhysicsServer::pin_joint_set_local_A);
- ObjectTypeDB::bind_method(_MD("pin_joint_get_local_A","joint"),&PhysicsServer::pin_joint_get_local_A);
+ ClassDB::bind_method(D_METHOD("pin_joint_set_local_A","joint","local_A"),&PhysicsServer::pin_joint_set_local_A);
+ ClassDB::bind_method(D_METHOD("pin_joint_get_local_A","joint"),&PhysicsServer::pin_joint_get_local_A);
- ObjectTypeDB::bind_method(_MD("pin_joint_set_local_B","joint","local_B"),&PhysicsServer::pin_joint_set_local_B);
- ObjectTypeDB::bind_method(_MD("pin_joint_get_local_B","joint"),&PhysicsServer::pin_joint_get_local_B);
+ ClassDB::bind_method(D_METHOD("pin_joint_set_local_B","joint","local_B"),&PhysicsServer::pin_joint_set_local_B);
+ ClassDB::bind_method(D_METHOD("pin_joint_get_local_B","joint"),&PhysicsServer::pin_joint_get_local_B);
BIND_CONSTANT(PIN_JOINT_BIAS );
BIND_CONSTANT(PIN_JOINT_DAMPING );
@@ -571,18 +576,18 @@ void PhysicsServer::_bind_methods() {
BIND_CONSTANT(HINGE_JOINT_FLAG_USE_LIMIT);
BIND_CONSTANT(HINGE_JOINT_FLAG_ENABLE_MOTOR);
- ObjectTypeDB::bind_method(_MD("joint_create_hinge","body_A","hinge_A","body_B","hinge_B"),&PhysicsServer::joint_create_hinge);
+ ClassDB::bind_method(D_METHOD("joint_create_hinge","body_A","hinge_A","body_B","hinge_B"),&PhysicsServer::joint_create_hinge);
- ObjectTypeDB::bind_method(_MD("hinge_joint_set_param","joint","param","value"),&PhysicsServer::hinge_joint_set_param);
- ObjectTypeDB::bind_method(_MD("hinge_joint_get_param","joint","param"),&PhysicsServer::hinge_joint_get_param);
+ ClassDB::bind_method(D_METHOD("hinge_joint_set_param","joint","param","value"),&PhysicsServer::hinge_joint_set_param);
+ ClassDB::bind_method(D_METHOD("hinge_joint_get_param","joint","param"),&PhysicsServer::hinge_joint_get_param);
- ObjectTypeDB::bind_method(_MD("hinge_joint_set_flag","joint","flag","enabled"),&PhysicsServer::hinge_joint_set_flag);
- ObjectTypeDB::bind_method(_MD("hinge_joint_get_flag","joint","flag"),&PhysicsServer::hinge_joint_get_flag);
+ ClassDB::bind_method(D_METHOD("hinge_joint_set_flag","joint","flag","enabled"),&PhysicsServer::hinge_joint_set_flag);
+ ClassDB::bind_method(D_METHOD("hinge_joint_get_flag","joint","flag"),&PhysicsServer::hinge_joint_get_flag);
- ObjectTypeDB::bind_method(_MD("joint_create_slider","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_slider);
+ ClassDB::bind_method(D_METHOD("joint_create_slider","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_slider);
- ObjectTypeDB::bind_method(_MD("slider_joint_set_param","joint","param","value"),&PhysicsServer::slider_joint_set_param);
- ObjectTypeDB::bind_method(_MD("slider_joint_get_param","joint","param"),&PhysicsServer::slider_joint_get_param);
+ ClassDB::bind_method(D_METHOD("slider_joint_set_param","joint","param","value"),&PhysicsServer::slider_joint_set_param);
+ ClassDB::bind_method(D_METHOD("slider_joint_get_param","joint","param"),&PhysicsServer::slider_joint_get_param);
BIND_CONSTANT( SLIDER_JOINT_LINEAR_LIMIT_UPPER );
BIND_CONSTANT( SLIDER_JOINT_LINEAR_LIMIT_LOWER );
@@ -610,10 +615,10 @@ void PhysicsServer::_bind_methods() {
BIND_CONSTANT( SLIDER_JOINT_MAX );
- ObjectTypeDB::bind_method(_MD("joint_create_cone_twist","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_cone_twist);
+ ClassDB::bind_method(D_METHOD("joint_create_cone_twist","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_cone_twist);
- ObjectTypeDB::bind_method(_MD("cone_twist_joint_set_param","joint","param","value"),&PhysicsServer::cone_twist_joint_set_param);
- ObjectTypeDB::bind_method(_MD("cone_twist_joint_get_param","joint","param"),&PhysicsServer::cone_twist_joint_get_param);
+ ClassDB::bind_method(D_METHOD("cone_twist_joint_set_param","joint","param","value"),&PhysicsServer::cone_twist_joint_set_param);
+ ClassDB::bind_method(D_METHOD("cone_twist_joint_get_param","joint","param"),&PhysicsServer::cone_twist_joint_get_param);
BIND_CONSTANT( CONE_TWIST_JOINT_SWING_SPAN );
BIND_CONSTANT( CONE_TWIST_JOINT_TWIST_SPAN );
@@ -642,44 +647,44 @@ void PhysicsServer::_bind_methods() {
BIND_CONSTANT( G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT );
BIND_CONSTANT( G6DOF_JOINT_FLAG_ENABLE_MOTOR );
- ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
+ ClassDB::bind_method(D_METHOD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
- ObjectTypeDB::bind_method(_MD("joint_set_solver_priority","joint","priority"),&PhysicsServer::joint_set_solver_priority);
- ObjectTypeDB::bind_method(_MD("joint_get_solver_priority","joint"),&PhysicsServer::joint_get_solver_priority);
+ ClassDB::bind_method(D_METHOD("joint_set_solver_priority","joint","priority"),&PhysicsServer::joint_set_solver_priority);
+ ClassDB::bind_method(D_METHOD("joint_get_solver_priority","joint"),&PhysicsServer::joint_get_solver_priority);
- ObjectTypeDB::bind_method(_MD("joint_create_generic_6dof","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_generic_6dof);
+ ClassDB::bind_method(D_METHOD("joint_create_generic_6dof","body_A","local_ref_A","body_B","local_ref_B"),&PhysicsServer::joint_create_generic_6dof);
- ObjectTypeDB::bind_method(_MD("generic_6dof_joint_set_param","joint","axis","param","value"),&PhysicsServer::generic_6dof_joint_set_param);
- ObjectTypeDB::bind_method(_MD("generic_6dof_joint_get_param","joint","axis","param"),&PhysicsServer::generic_6dof_joint_get_param);
+ ClassDB::bind_method(D_METHOD("generic_6dof_joint_set_param","joint","axis","param","value"),&PhysicsServer::generic_6dof_joint_set_param);
+ ClassDB::bind_method(D_METHOD("generic_6dof_joint_get_param","joint","axis","param"),&PhysicsServer::generic_6dof_joint_get_param);
- ObjectTypeDB::bind_method(_MD("generic_6dof_joint_set_flag","joint","axis","flag","enable"),&PhysicsServer::generic_6dof_joint_set_flag);
- ObjectTypeDB::bind_method(_MD("generic_6dof_joint_get_flag","joint","axis","flag"),&PhysicsServer::generic_6dof_joint_get_flag);
+ ClassDB::bind_method(D_METHOD("generic_6dof_joint_set_flag","joint","axis","flag","enable"),&PhysicsServer::generic_6dof_joint_set_flag);
+ ClassDB::bind_method(D_METHOD("generic_6dof_joint_get_flag","joint","axis","flag"),&PhysicsServer::generic_6dof_joint_get_flag);
/*
- ObjectTypeDB::bind_method(_MD("joint_set_param","joint","param","value"),&PhysicsServer::joint_set_param);
- ObjectTypeDB::bind_method(_MD("joint_get_param","joint","param"),&PhysicsServer::joint_get_param);
+ ClassDB::bind_method(D_METHOD("joint_set_param","joint","param","value"),&PhysicsServer::joint_set_param);
+ ClassDB::bind_method(D_METHOD("joint_get_param","joint","param"),&PhysicsServer::joint_get_param);
- ObjectTypeDB::bind_method(_MD("pin_joint_create","anchor","body_a","body_b"),&PhysicsServer::pin_joint_create,DEFVAL(RID()));
- ObjectTypeDB::bind_method(_MD("groove_joint_create","groove1_a","groove2_a","anchor_b","body_a","body_b"),&PhysicsServer::groove_joint_create,DEFVAL(RID()),DEFVAL(RID()));
- ObjectTypeDB::bind_method(_MD("damped_spring_joint_create","anchor_a","anchor_b","body_a","body_b"),&PhysicsServer::damped_spring_joint_create,DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("pin_joint_create","anchor","body_a","body_b"),&PhysicsServer::pin_joint_create,DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("groove_joint_create","groove1_a","groove2_a","anchor_b","body_a","body_b"),&PhysicsServer::groove_joint_create,DEFVAL(RID()),DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("damped_spring_joint_create","anchor_a","anchor_b","body_a","body_b"),&PhysicsServer::damped_spring_joint_create,DEFVAL(RID()));
- ObjectTypeDB::bind_method(_MD("damped_string_joint_set_param","joint","param","value"),&PhysicsServer::damped_string_joint_set_param,DEFVAL(RID()));
- ObjectTypeDB::bind_method(_MD("damped_string_joint_get_param","joint","param"),&PhysicsServer::damped_string_joint_get_param);
+ ClassDB::bind_method(D_METHOD("damped_string_joint_set_param","joint","param","value"),&PhysicsServer::damped_string_joint_set_param,DEFVAL(RID()));
+ ClassDB::bind_method(D_METHOD("damped_string_joint_get_param","joint","param"),&PhysicsServer::damped_string_joint_get_param);
- ObjectTypeDB::bind_method(_MD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
+ ClassDB::bind_method(D_METHOD("joint_get_type","joint"),&PhysicsServer::joint_get_type);
*/
- ObjectTypeDB::bind_method(_MD("free_rid","rid"),&PhysicsServer::free);
+ ClassDB::bind_method(D_METHOD("free_rid","rid"),&PhysicsServer::free);
- ObjectTypeDB::bind_method(_MD("set_active","active"),&PhysicsServer::set_active);
+ ClassDB::bind_method(D_METHOD("set_active","active"),&PhysicsServer::set_active);
-// ObjectTypeDB::bind_method(_MD("init"),&PhysicsServer::init);
-// ObjectTypeDB::bind_method(_MD("step"),&PhysicsServer::step);
-// ObjectTypeDB::bind_method(_MD("sync"),&PhysicsServer::sync);
- //ObjectTypeDB::bind_method(_MD("flush_queries"),&PhysicsServer::flush_queries);
+ //ClassDB::bind_method(D_METHOD("init"),&PhysicsServer::init);
+ //ClassDB::bind_method(D_METHOD("step"),&PhysicsServer::step);
+ //ClassDB::bind_method(D_METHOD("sync"),&PhysicsServer::sync);
+ //ClassDB::bind_method(D_METHOD("flush_queries"),&PhysicsServer::flush_queries);
- ObjectTypeDB::bind_method(_MD("get_process_info","process_info"),&PhysicsServer::get_process_info);
+ ClassDB::bind_method(D_METHOD("get_process_info","process_info"),&PhysicsServer::get_process_info);
BIND_CONSTANT( SHAPE_PLANE );
BIND_CONSTANT( SHAPE_RAY );
@@ -734,8 +739,8 @@ void PhysicsServer::_bind_methods() {
BIND_CONSTANT( DAMPED_STRING_STIFFNESS );
BIND_CONSTANT( DAMPED_STRING_DAMPING );
*/
-// BIND_CONSTANT( TYPE_BODY );
-// BIND_CONSTANT( TYPE_AREA );
+ //BIND_CONSTANT( TYPE_BODY );
+ //BIND_CONSTANT( TYPE_AREA );
BIND_CONSTANT( AREA_BODY_ADDED );
BIND_CONSTANT( AREA_BODY_REMOVED );
diff --git a/servers/physics_server.h b/servers/physics_server.h
index 5221b38ccb..653959be45 100644
--- a/servers/physics_server.h
+++ b/servers/physics_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -36,7 +36,7 @@ class PhysicsDirectSpaceState;
class PhysicsDirectBodyState : public Object {
- OBJ_TYPE( PhysicsDirectBodyState, Object );
+ GDCLASS( PhysicsDirectBodyState, Object );
protected:
static void _bind_methods();
public:
@@ -45,9 +45,11 @@ public:
virtual float get_total_angular_damp() const=0;
virtual float get_total_linear_damp() const=0;
+ virtual Vector3 get_center_of_mass() const=0;
+ virtual Basis get_principal_inertia_axes() const=0;
virtual float get_inverse_mass() const=0; // get the mass
virtual Vector3 get_inverse_inertia() const=0; // get density of this body space
- virtual Matrix3 get_inverse_inertia_tensor() const=0; // get density of this body space
+ virtual Basis get_inverse_inertia_tensor() const=0; // get density of this body space
virtual void set_linear_velocity(const Vector3& p_velocity)=0;
virtual Vector3 get_linear_velocity() const=0;
@@ -60,6 +62,7 @@ public:
virtual void add_force(const Vector3& p_force, const Vector3& p_pos)=0;
virtual void apply_impulse(const Vector3& p_pos, const Vector3& p_j)=0;
+ virtual void apply_torque_impulse(const Vector3& p_j)=0;
virtual void set_sleep_state(bool p_enable)=0;
virtual bool is_sleeping() const=0;
@@ -90,7 +93,7 @@ class PhysicsShapeQueryResult;
class PhysicsShapeQueryParameters : public Reference {
- OBJ_TYPE(PhysicsShapeQueryParameters, Reference);
+ GDCLASS(PhysicsShapeQueryParameters, Reference);
friend class PhysicsDirectSpaceState;
RID shape;
Transform transform;
@@ -130,10 +133,10 @@ public:
class PhysicsDirectSpaceState : public Object {
- OBJ_TYPE( PhysicsDirectSpaceState, Object );
+ GDCLASS( PhysicsDirectSpaceState, Object );
-// Variant _intersect_ray(const Vector3& p_from, const Vector3& p_to,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_collision_mask=0);
-// Variant _intersect_shape(const RID& p_shape, const Transform& p_xform,int p_result_max=64,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_collision_mask=0);
+ //Variant _intersect_ray(const Vector3& p_from, const Vector3& p_to,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_collision_mask=0);
+ //Variant _intersect_shape(const RID& p_shape, const Transform& p_xform,int p_result_max=64,const Vector<RID>& p_exclude=Vector<RID>(),uint32_t p_collision_mask=0);
public:
enum ObjectTypeMask {
@@ -207,7 +210,7 @@ public:
class PhysicsShapeQueryResult : public Reference {
- OBJ_TYPE( PhysicsShapeQueryResult, Reference );
+ GDCLASS( PhysicsShapeQueryResult, Reference );
Vector<PhysicsDirectSpaceState::ShapeResult> result;
@@ -229,7 +232,7 @@ public:
class PhysicsServer : public Object {
- OBJ_TYPE( PhysicsServer, Object );
+ GDCLASS( PhysicsServer, Object );
static PhysicsServer * singleton;
@@ -441,6 +444,7 @@ public:
virtual Vector3 body_get_applied_torque(RID p_body) const=0;
virtual void body_apply_impulse(RID p_body, const Vector3& p_pos, const Vector3& p_impulse)=0;
+ virtual void body_apply_torque_impulse(RID p_body, const Vector3& p_impulse)=0;
virtual void body_set_axis_velocity(RID p_body, const Vector3& p_axis_velocity)=0;
enum BodyAxisLock {
diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp
index 06eaa4d122..0d0619e880 100644
--- a/servers/register_server_types.cpp
+++ b/servers/register_server_types.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,15 +27,29 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "register_server_types.h"
-#include "globals.h"
+#include "global_config.h"
#include "visual_server.h"
#include "audio_server.h"
#include "physics_server.h"
#include "physics_2d_server.h"
-#include "spatial_sound_server.h"
-#include "spatial_sound_2d_server.h"
#include "script_debugger_remote.h"
+#include "visual/shader_types.h"
+#include "audio/audio_stream.h"
+#include "audio/audio_effect.h"
+#include "audio/effects/audio_effect_amplify.h"
+#include "audio/effects/audio_effect_reverb.h"
+#include "audio/effects/audio_effect_filter.h"
+#include "audio/effects/audio_effect_eq.h"
+#include "audio/effects/audio_effect_distortion.h"
+#include "audio/effects/audio_effect_stereo_enhance.h"
+#include "audio/effects/audio_effect_panner.h"
+#include "audio/effects/audio_effect_chorus.h"
+#include "audio/effects/audio_effect_delay.h"
+#include "audio/effects/audio_effect_compressor.h"
+#include "audio/effects/audio_effect_limiter.h"
+#include "audio/effects/audio_effect_pitch_shift.h"
+#include "audio/effects/audio_effect_phaser.h"
static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsage>* r_usage) {
@@ -55,37 +69,71 @@ static void _debugger_get_resource_usage(List<ScriptDebuggerRemote::ResourceUsag
}
+ShaderTypes *shader_types=NULL;
+
void register_server_types() {
- Globals::get_singleton()->add_singleton( Globals::Singleton("VisualServer",VisualServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("VS",VisualServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("AudioServer",AudioServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("AS",AudioServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("PhysicsServer",PhysicsServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("PS",PhysicsServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("Physics2DServer",Physics2DServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("PS2D",Physics2DServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("SpatialSoundServer",SpatialSoundServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("SS",SpatialSoundServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("SpatialSound2DServer",SpatialSound2DServer::get_singleton()) );
- Globals::get_singleton()->add_singleton( Globals::Singleton("SS2D",SpatialSound2DServer::get_singleton()) );
-
-
- ObjectTypeDB::register_virtual_type<Physics2DDirectBodyState>();
- ObjectTypeDB::register_virtual_type<Physics2DDirectSpaceState>();
- ObjectTypeDB::register_virtual_type<Physics2DShapeQueryResult>();
- ObjectTypeDB::register_type<Physics2DTestMotionResult>();
- ObjectTypeDB::register_type<Physics2DShapeQueryParameters>();
-
- ObjectTypeDB::register_type<PhysicsShapeQueryParameters>();
- ObjectTypeDB::register_virtual_type<PhysicsDirectBodyState>();
- ObjectTypeDB::register_virtual_type<PhysicsDirectSpaceState>();
- ObjectTypeDB::register_virtual_type<PhysicsShapeQueryResult>();
+ GLOBAL_DEF("memory/multithread/thread_rid_pool_prealloc",20);
+
+ GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("VisualServer",VisualServer::get_singleton()) );
+ GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("AudioServer",AudioServer::get_singleton()) );
+ GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("PhysicsServer",PhysicsServer::get_singleton()) );
+ GlobalConfig::get_singleton()->add_singleton( GlobalConfig::Singleton("Physics2DServer",Physics2DServer::get_singleton()) );
+
+ shader_types = memnew( ShaderTypes );
+
+ ClassDB::register_virtual_class<AudioStream>();
+ ClassDB::register_virtual_class<AudioStreamPlayback>();
+ ClassDB::register_virtual_class<AudioEffect>();
+ ClassDB::register_class<AudioBusLayout>();
+
+ {
+ //audio effects
+ ClassDB::register_class<AudioEffectAmplify>();
+
+ ClassDB::register_class<AudioEffectReverb>();
+
+ ClassDB::register_class<AudioEffectLowPassFilter>();
+ ClassDB::register_class<AudioEffectHighPassFilter>();
+ ClassDB::register_class<AudioEffectBandPassFilter>();
+ ClassDB::register_class<AudioEffectNotchFilter>();
+ ClassDB::register_class<AudioEffectBandLimitFilter>();
+ ClassDB::register_class<AudioEffectLowShelfFilter>();
+ ClassDB::register_class<AudioEffectHighShelfFilter>();
+
+ ClassDB::register_class<AudioEffectEQ6>();
+ ClassDB::register_class<AudioEffectEQ10>();
+ ClassDB::register_class<AudioEffectEQ21>();
+
+ ClassDB::register_class<AudioEffectDistortion>();
+
+ ClassDB::register_class<AudioEffectStereoEnhance>();
+
+ ClassDB::register_class<AudioEffectPanner>();
+ ClassDB::register_class<AudioEffectChorus>();
+ ClassDB::register_class<AudioEffectDelay>();
+ ClassDB::register_class<AudioEffectCompressor>();
+ ClassDB::register_class<AudioEffectLimiter>();
+ ClassDB::register_class<AudioEffectPitchShift>();
+ ClassDB::register_class<AudioEffectPhaser>();
+ }
+
+
+ ClassDB::register_virtual_class<Physics2DDirectBodyState>();
+ ClassDB::register_virtual_class<Physics2DDirectSpaceState>();
+ ClassDB::register_virtual_class<Physics2DShapeQueryResult>();
+ ClassDB::register_class<Physics2DTestMotionResult>();
+ ClassDB::register_class<Physics2DShapeQueryParameters>();
+
+ ClassDB::register_class<PhysicsShapeQueryParameters>();
+ ClassDB::register_virtual_class<PhysicsDirectBodyState>();
+ ClassDB::register_virtual_class<PhysicsDirectSpaceState>();
+ ClassDB::register_virtual_class<PhysicsShapeQueryResult>();
ScriptDebuggerRemote::resource_usage_func=_debugger_get_resource_usage;
}
void unregister_server_types(){
-
+ memdelete( shader_types );
}
diff --git a/servers/register_server_types.h b/servers/register_server_types.h
index a62af905b3..a3e7d3ee32 100644
--- a/servers/register_server_types.h
+++ b/servers/register_server_types.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/server_wrap_mt_common.h b/servers/server_wrap_mt_common.h
index dd9d603852..fbc68fc879 100644
--- a/servers/server_wrap_mt_common.h
+++ b/servers/server_wrap_mt_common.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
diff --git a/servers/spatial_sound/SCsub b/servers/spatial_sound/SCsub
deleted file mode 100644
index d31af2c1c4..0000000000
--- a/servers/spatial_sound/SCsub
+++ /dev/null
@@ -1,5 +0,0 @@
-Import('env')
-
-env.add_source_files(env.servers_sources,"*.cpp")
-
-Export('env')
diff --git a/servers/spatial_sound/spatial_sound_server_sw.cpp b/servers/spatial_sound/spatial_sound_server_sw.cpp
deleted file mode 100644
index dc15d61afa..0000000000
--- a/servers/spatial_sound/spatial_sound_server_sw.cpp
+++ /dev/null
@@ -1,1071 +0,0 @@
-/*************************************************************************/
-/* spatial_sound_server_sw.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 "spatial_sound_server_sw.h"
-#include "os/os.h"
-#include "servers/audio/audio_filter_sw.h"
-
-
-
-int SpatialSoundServerSW::InternalAudioStream::get_channel_count() const {
-
- return AudioServer::get_singleton()->get_default_channel_count();
-}
-
-void SpatialSoundServerSW::InternalAudioStream::set_mix_rate(int p_rate) {
-
-
-}
-
-void SpatialSoundServerSW::InternalAudioStream::update() {
-
- owner->_update_sources();
-}
-
-bool SpatialSoundServerSW::InternalAudioStream::mix(int32_t *p_buffer,int p_frames) {
-
- return owner->internal_buffer_mix(p_buffer,p_frames);
-}
-
-void SpatialSoundServerSW::_update_sources() {
-
- _THREAD_SAFE_METHOD_
- for (Set<Source*>::Element *E=streaming_sources.front();E;E=E->next()) {
-
- Source *s=E->get();
- ERR_CONTINUE(!s->stream);
- s->stream->update();
- }
-}
-
-
-SpatialSoundServerSW::Room::Room() {
-
-// params[ROOM_PARAM_SPEED_OF_SOUND]=343.0;
- params[ROOM_PARAM_SPEED_OF_SOUND_SCALE]=1;
- params[ROOM_PARAM_DOPPLER_FACTOR]=1.0;
- params[ROOM_PARAM_PITCH_SCALE]=1.0;
- params[ROOM_PARAM_VOLUME_SCALE_DB]=0;
- params[ROOM_PARAM_REVERB_SEND]=0;
- params[ROOM_PARAM_CHORUS_SEND]=0;
- params[ROOM_PARAM_ATTENUATION_SCALE]=1.0;
- params[ROOM_PARAM_ATTENUATION_HF_CUTOFF]=5000;
- params[ROOM_PARAM_ATTENUATION_HF_FLOOR_DB]=-24.0;
- params[ROOM_PARAM_ATTENUATION_HF_RATIO_EXP]=1.0;
- params[ROOM_PARAM_ATTENUATION_REVERB_SCALE]=0.0;
- override_other_sources=false;
- reverb=ROOM_REVERB_HALL;
- octree_id=0;
- level=-1;
-
-
-}
-
-
-SpatialSoundServerSW::Source::Source() {
-
- params[SOURCE_PARAM_VOLUME_DB]=0.0;
- params[SOURCE_PARAM_PITCH_SCALE]=1.0;
- params[SOURCE_PARAM_ATTENUATION_MIN_DISTANCE]=1;
- params[SOURCE_PARAM_ATTENUATION_MAX_DISTANCE]=100;
- params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP]=1.0; //linear (and not really good)
- params[SOURCE_PARAM_EMISSION_CONE_DEGREES]=180.0; //cone disabled
- params[SOURCE_PARAM_EMISSION_CONE_ATTENUATION_DB]=-6.0; //minus 6 db attenuation
- stream=NULL;
- voices.resize(1);
- last_voice=0;
-}
-
-SpatialSoundServerSW::Source::Voice::Voice() {
-
- active=false;
- restart=false;
- pitch_scale=1.0;
- volume_scale=0.0;
- voice_rid=AudioServer::get_singleton()->voice_create();
-
-}
-SpatialSoundServerSW::Source::Voice::~Voice() {
-
- AudioServer::get_singleton()->free(voice_rid);
-}
-
-
-SpatialSoundServerSW::Listener::Listener() {
-
- params[LISTENER_PARAM_VOLUME_SCALE_DB]=0.0;
- params[LISTENER_PARAM_PITCH_SCALE]=1.0;
- params[LISTENER_PARAM_ATTENUATION_SCALE]=1.0;
- params[LISTENER_PARAM_RECEPTION_CONE_DEGREES]=60.0;
- params[LISTENER_PARAM_RECEPTION_CONE_ATTENUATION_DB]=-6; // minus six decibels
-
-}
-
-/* SPACE */
-RID SpatialSoundServerSW::space_create() {
-
- Space* space = memnew( Space );
- RID space_rid = space_owner.make_rid(space);
- space->default_room=room_create();
- room_set_space(space->default_room,space_rid);
- return space_rid;
-}
-
-/* ROOM */
-
-RID SpatialSoundServerSW::room_create() {
-
- Room *room = memnew( Room );
- return room_owner.make_rid(room);
-}
-
-void SpatialSoundServerSW::room_set_space(RID p_room,RID p_space) {
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
-
- if (room->space.is_valid()) {
-
- Space *space = space_owner.get(room->space);
- space->rooms.erase(p_room);
- space->octree.erase(room->octree_id);
- //room->octree_id=0;
- }
-
- room->space=RID();
-
- if (p_space.is_valid()) {
-
- Space *space = space_owner.get(p_space);
- ERR_FAIL_COND(!space);
- space->rooms.insert(p_room);
- room->octree_id=space->octree.create(room,AABB());
- //set bounds
- AABB aabb = room->bounds.is_empty()?AABB():room->bounds.get_aabb();
- space->octree.move(room->octree_id,room->transform.xform(aabb));
- room->space=p_space;
- }
-
-
-}
-
-RID SpatialSoundServerSW::room_get_space(RID p_room) const {
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,RID());
-
-
- return room->space;
-}
-
-
-
-void SpatialSoundServerSW::room_set_bounds(RID p_room, const BSP_Tree& p_bounds) {
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
-
- room->bounds=p_bounds;
-
- if (!room->space.is_valid())
- return;
-
- AABB aabb = room->bounds.is_empty()?AABB():room->bounds.get_aabb();
- Space* space = space_owner.get(room->space);
- ERR_FAIL_COND(!space);
-
- space->octree.move(room->octree_id,room->transform.xform(aabb));
-
-}
-BSP_Tree SpatialSoundServerSW::room_get_bounds(RID p_room) const {
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,BSP_Tree());
-
- return room->bounds;
-}
-
-void SpatialSoundServerSW::room_set_transform(RID p_room, const Transform& p_transform) {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
- room->transform=p_transform;
- room->inverse_transform=p_transform.affine_inverse(); // needs to be done to unscale BSP properly
-
- if (!room->space.is_valid())
- return;
-
- if (!room->bounds.is_empty()) {
-
- Space* space = space_owner.get(room->space);
- ERR_FAIL_COND(!space);
-
- space->octree.move(room->octree_id,room->transform.xform(room->bounds.get_aabb()));
- }
-}
-
-Transform SpatialSoundServerSW::room_get_transform(RID p_room) const {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,Transform());
- return room->transform;
-}
-
-
-void SpatialSoundServerSW::room_set_param(RID p_room, RoomParam p_param, float p_value) {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- ERR_FAIL_INDEX(p_param,ROOM_PARAM_MAX);
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
- room->params[p_param]=p_value;
-
-}
-float SpatialSoundServerSW::room_get_param(RID p_room, RoomParam p_param) const {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- ERR_FAIL_INDEX_V(p_param,ROOM_PARAM_MAX,0);
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,0);
- return room->params[p_param];
-}
-
-void SpatialSoundServerSW::room_set_level(RID p_room, int p_level) {
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
- room->level =p_level;
-
-}
-
-int SpatialSoundServerSW::room_get_level(RID p_room) const {
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,0);
- return room->level;
-
-}
-
-
-void SpatialSoundServerSW::room_set_reverb(RID p_room, RoomReverb p_reverb) {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
- room->reverb=p_reverb;
-
-}
-SpatialSoundServerSW::RoomReverb SpatialSoundServerSW::room_get_reverb(RID p_room) const {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,ROOM_REVERB_SMALL);
- return room->reverb;
-}
-
-//useful for underwater or rooms with very strange conditions
-void SpatialSoundServerSW::room_set_force_params_to_all_sources(RID p_room, bool p_force) {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
- room->override_other_sources=p_force;
-
-}
-bool SpatialSoundServerSW::room_is_forcing_params_to_all_sources(RID p_room) const {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,false);
- return room->override_other_sources;
-}
-
-/* SOURCE */
-
-RID SpatialSoundServerSW::source_create(RID p_space) {
-
- Space *space = space_owner.get(p_space);
- ERR_FAIL_COND_V(!space,RID());
-
- Source *source = memnew( Source );
- source->space=p_space;
- RID source_rid = source_owner.make_rid(source);
- space->sources.insert(source_rid);
-
- return source_rid;
-}
-
-
-void SpatialSoundServerSW::source_set_polyphony(RID p_source,int p_voice_count) {
-
-
- ERR_FAIL_COND(p_voice_count<=0); // more than 32 is too much, change this if you really need more
- if (p_voice_count>32) {
-
- ERR_PRINT("Voices will be clipped to 32");
- p_voice_count=32;
- }
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
-
- if (p_voice_count<source->voices.size()) {
-
- for(int i=p_voice_count;i<source->voices.size();i++) {
- active_voices.erase(ActiveVoice(source,i)); //erase from active voices
- }
- }
- source->voices.resize(p_voice_count);
-
-}
-
-int SpatialSoundServerSW::source_get_polyphony(RID p_source) const {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND_V(!source,-1);
- return source->voices.size();
-
-}
-
-void SpatialSoundServerSW::source_set_transform(RID p_source, const Transform& p_transform) {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
- source->transform=p_transform;
- source->transform.orthonormalize();
-}
-Transform SpatialSoundServerSW::source_get_transform(RID p_source) const {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND_V(!source,Transform());
- return source->transform;
-}
-
-void SpatialSoundServerSW::source_set_param(RID p_source, SourceParam p_param, float p_value) {
-
- ERR_FAIL_INDEX(p_param,SOURCE_PARAM_MAX);
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
- source->params[p_param]=p_value;
-
-}
-float SpatialSoundServerSW::source_get_param(RID p_source, SourceParam p_param) const {
- ERR_FAIL_INDEX_V(p_param,SOURCE_PARAM_MAX,0);
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND_V(!source,0);
- return source->params[p_param];
-
-
-}
-
-void SpatialSoundServerSW::source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream) {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
- AudioServer::get_singleton()->lock();
- source->stream=p_stream;
- _THREAD_SAFE_METHOD_
-
- if (!p_stream) {
- streaming_sources.erase(source);
- active_voices.erase(ActiveVoice(source,VOICE_IS_STREAM));
- } else {
- streaming_sources.insert(source);
- active_voices.insert(ActiveVoice(source,VOICE_IS_STREAM));
- zeromem(source->stream_data.filter_state,sizeof(Source::StreamData::FilterState)*4); //reset filter for safetyness
- p_stream->set_mix_rate(AudioServer::get_singleton()->get_default_mix_rate());
- }
-
- AudioServer::get_singleton()->unlock();
-
-} //null to unset
-
-SpatialSoundServer::SourceVoiceID SpatialSoundServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice) {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND_V(!source,SOURCE_INVALID_VOICE);
-
- int to_play=0;
-
- if (p_voice==SOURCE_NEXT_VOICE) {
- to_play=source->last_voice+1;
- if (to_play>=source->voices.size())
- to_play=0;
-
- } else
- to_play=p_voice;
-
- ERR_FAIL_INDEX_V(to_play,source->voices.size(),SOURCE_INVALID_VOICE);
-
- source->voices[to_play].restart=true;
- source->voices[to_play].sample_rid=p_sample;
- source->voices[to_play].sample_mix_rate=p_mix_rate;
- source->voices[to_play].pitch_scale=1;
- source->voices[to_play].volume_scale=0;
- source->last_voice=to_play;
- active_voices.insert(ActiveVoice(source,to_play));
- return to_play;
-}
-
-/* VOICES */
-void SpatialSoundServerSW::source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale) {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
- ERR_FAIL_INDEX(p_voice,source->voices.size());
- source->voices[p_voice].pitch_scale=p_pitch_scale;
-
-}
-void SpatialSoundServerSW::source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_db) {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
- ERR_FAIL_INDEX(p_voice,source->voices.size());
- source->voices[p_voice].volume_scale=p_db;
-
-}
-
-bool SpatialSoundServerSW::source_is_voice_active(RID p_source, SourceVoiceID p_voice) const {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND_V(!source,false);
- ERR_FAIL_INDEX_V(p_voice,source->voices.size(),false);
- return source->voices[p_voice].active || source->voices[p_voice].restart;
-
-}
-void SpatialSoundServerSW::source_stop_voice(RID p_source, SourceVoiceID p_voice) {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
- ERR_FAIL_INDEX(p_voice,source->voices.size());
- if (source->voices[p_voice].active) {
- AudioServer::get_singleton()->voice_stop(source->voices[p_voice].voice_rid);
- }
- source->voices[p_voice].active=false;
- source->voices[p_voice].restart=false;
- active_voices.erase(ActiveVoice(source,p_voice));
-}
-
-/* LISTENER */
-
-RID SpatialSoundServerSW::listener_create() {
-
- Listener *listener = memnew( Listener );
- RID listener_rid = listener_owner.make_rid(listener);
- return listener_rid;
-
-}
-
-void SpatialSoundServerSW::listener_set_space(RID p_listener,RID p_space) {
-
- Listener *listener = listener_owner.get(p_listener);
- ERR_FAIL_COND(!listener);
-
- if (listener->space.is_valid()) {
-
- Space *lspace = space_owner.get(listener->space);
- ERR_FAIL_COND(!lspace);
- lspace->listeners.erase(p_listener);
- }
-
- listener->space=RID();
-
- if (p_space.is_valid()) {
- Space *space = space_owner.get(p_space);
- ERR_FAIL_COND(!space);
-
- listener->space=p_space;
- space->listeners.insert(p_listener);
- }
-
-}
-
-void SpatialSoundServerSW::listener_set_transform(RID p_listener, const Transform& p_transform) {
-
- Listener *listener = listener_owner.get(p_listener);
- ERR_FAIL_COND(!listener);
- listener->transform=p_transform;
- listener->transform.orthonormalize(); //must be done..
-}
-Transform SpatialSoundServerSW::listener_get_transform(RID p_listener) const {
-
- Listener *listener = listener_owner.get(p_listener);
- ERR_FAIL_COND_V(!listener,Transform());
- return listener->transform;
-}
-
-void SpatialSoundServerSW::listener_set_param(RID p_listener, ListenerParam p_param, float p_value) {
-
- ERR_FAIL_INDEX(p_param,LISTENER_PARAM_MAX);
- Listener *listener = listener_owner.get(p_listener);
- ERR_FAIL_COND(!listener);
- listener->params[p_param]=p_value;
-}
-
-float SpatialSoundServerSW::listener_get_param(RID p_listener, ListenerParam p_param) const {
-
- ERR_FAIL_INDEX_V(p_param,LISTENER_PARAM_MAX,0);
- Listener *listener = listener_owner.get(p_listener);
- ERR_FAIL_COND_V(!listener,0);
- return listener->params[p_param];
-}
-
-
-/* MISC */
-
-void SpatialSoundServerSW::free(RID p_id) {
-
-
- if (space_owner.owns(p_id)) {
-
- Space *space = space_owner.get(p_id);
- free(space->default_room);
-
- while(space->listeners.size()) {
- listener_set_space(space->listeners.front()->get(),RID());
- }
- while(space->sources.size()) {
- free(space->sources.front()->get());
- }
- while(space->rooms.size()) {
- room_set_space(space->rooms.front()->get(),RID());
- }
- space_owner.free(p_id);
- memdelete(space);
-
- } else if (source_owner.owns(p_id)) {
-
- Source *source = source_owner.get(p_id);
- if (source->stream)
- source_set_audio_stream(p_id,NULL);
-
- Space *space = space_owner.get(source->space);
- ERR_FAIL_COND(!space);
- space->sources.erase(p_id);
- for(int i=0;i<source->voices.size();i++) {
- active_voices.erase(ActiveVoice(source,i));
- }
- source_owner.free(p_id);
- memdelete(source);
- } else if (listener_owner.owns(p_id)) {
-
- Listener *listener = listener_owner.get(p_id);
- if (listener->space.is_valid()) {
- Space *space = space_owner.get(listener->space);
- ERR_FAIL_COND(!space);
- space->listeners.erase(p_id);
- }
- listener_owner.free(p_id);
- memdelete(listener);
-
- } else if (room_owner.owns(p_id)) {
-
- Room *room = room_owner.get(p_id);
-
- if (room->space.is_valid()) {
- Space *space = space_owner.get(room->space);
- ERR_FAIL_COND(!space);
- space->octree.erase(room->octree_id);
- space->rooms.erase(p_id);
- }
- room_owner.free(p_id);
- memdelete(room);
- } else {
- ERR_PRINT("Attempt to free invalid ID") ;
- }
-
-}
-
-void SpatialSoundServerSW::_clean_up_owner(RID_OwnerBase *p_owner, const char *p_area) {
-
- List<RID> rids;
- p_owner->get_owned_list(&rids);
-
- for(List<RID>::Element *I=rids.front();I;I=I->next()) {
- if (OS::get_singleton()->is_stdout_verbose()) {
-
- print_line("Leaked RID ("+itos(I->get().get_id())+") of type "+String(p_area));
- }
- free(I->get());
- }
-}
-
-void SpatialSoundServerSW::init() {
-
- internal_buffer = memnew_arr(int32_t, INTERNAL_BUFFER_SIZE*INTERNAL_BUFFER_MAX_CHANNELS);
- internal_buffer_channels=AudioServer::get_singleton()->get_default_channel_count();
-
- internal_audio_stream = memnew( InternalAudioStream );
- internal_audio_stream->owner=this;
- internal_audio_stream_rid = AudioServer::get_singleton()->audio_stream_create(internal_audio_stream);
-
- AudioServer::get_singleton()->stream_set_active(internal_audio_stream_rid,true);
-
-}
-
-
-
-static float _get_attenuation(float cosine, float angle, float attenuation) {
-
-
- float listener_ang = Math::rad2deg(Math::acos(cosine))-angle;
-
- if (listener_ang>0 && angle<180.0) {
- listener_ang/=(180.0-angle);
- return Math::db2linear(Math::sin(listener_ang*(Math_PI/2.0))*attenuation);
- }
- return 1.0;
-}
-
-
-bool SpatialSoundServerSW::internal_buffer_mix(int32_t *p_buffer,int p_frames) {
-
- if (streaming_sources.size()==0)
- return false; //nothing to mix
-
-
- for (Set<Source*>::Element *E=streaming_sources.front();E;E=E->next()) {
-
- Source *s=E->get();
- ERR_CONTINUE(!s->stream);
-
- int channels = s->stream->get_channel_count();
- Source::StreamData &sd=s->stream_data;
-
- int todo=p_frames;
-
- AudioFilterSW filter;
- filter.set_sampling_rate(AudioServer::get_singleton()->get_default_mix_rate());
- filter.set_cutoff(sd.filter_cutoff);
- filter.set_gain(sd.filter_gain);
- filter.set_resonance(1);
- filter.set_mode(AudioFilterSW::HIGHSHELF);
- filter.set_stages(1);
- AudioFilterSW::Coeffs coefs;
- filter.prepare_coefficients(&coefs);
-
- int32_t in[4];
-#ifndef SPATIAL_SOUND_SERVER_NO_FILTER
-#define DO_FILTER(m_c)\
- {\
- float val = in[m_c];\
- float pre=val;\
- val = val*coefs.b0 + sd.filter_state[m_c].hb[0]*coefs.b1 + sd.filter_state[m_c].hb[1]*coefs.b2 + sd.filter_state[m_c].ha[0]*coefs.a1 + sd.filter_state[m_c].ha[1]*coefs.a2;\
- sd.filter_state[m_c].ha[1]=sd.filter_state[m_c].ha[0];\
- sd.filter_state[m_c].hb[1]=sd.filter_state[m_c].hb[0]; \
- sd.filter_state[m_c].hb[0]=pre;\
- sd.filter_state[m_c].ha[0]=val;\
- in[m_c]=Math::fast_ftoi(val);\
- }
-#else
-#define DO_FILTER(m_c)
-#endif
-
- while(todo) {
-
- int to_mix=MIN(todo,INTERNAL_BUFFER_SIZE);
-
- s->stream->mix(internal_buffer,to_mix);
-
- switch(internal_buffer_channels) {
-
- case 2: {
-
- float p = sd.panning.x*0.5+0.5;
- float panf[2]={ (1.0-p),p };
- panf[0]*=sd.volume;
- panf[1]*=sd.volume;
-
- int32_t pan[2]={Math::fast_ftoi(panf[0]*(1<<16)),Math::fast_ftoi(panf[1]*(1<<16))};
-
- switch(channels) {
- case 1: {
-
- for(int i=0;i<to_mix;i++) {
-
- in[0]=internal_buffer[i];
- in[1]=internal_buffer[i];
- DO_FILTER(0);
- DO_FILTER(1);
- p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]);
- p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]);
- }
- } break;
- case 2: {
-
- for(int i=0;i<to_mix;i++) {
-
- in[0]=internal_buffer[(i<<1)+0];
- in[1]=internal_buffer[(i<<1)+1];
- DO_FILTER(0);
- DO_FILTER(1);
- p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]);
- p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]);
- }
- } break;
- case 4: {
-
- for(int i=0;i<to_mix;i++) {
-
- in[0]=(internal_buffer[(i<<2)+0]+internal_buffer[(i<<2)+2])>>1;
- in[1]=(internal_buffer[(i<<2)+1]+internal_buffer[(i<<2)+3])>>1;
- DO_FILTER(0);
- DO_FILTER(1);
- p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]);
- p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]);
- }
- } break;
-
- } break;
-
- } break;
- case 4: {
-
- float xp = sd.panning.x*0.5+0.5;
- float yp = sd.panning.y*0.5+0.5;
- float panf[4]={ (1.0-xp)*(1.0-yp),(xp)*(1.0-yp),(1.0-xp)*(yp),(xp)*(yp) };
- panf[0]*=sd.volume;
- panf[1]*=sd.volume;
- panf[2]*=sd.volume;
- panf[3]*=sd.volume;
-
- int32_t pan[4]={
- Math::fast_ftoi(panf[0]*(1<<16)),
- Math::fast_ftoi(panf[1]*(1<<16)),
- Math::fast_ftoi(panf[2]*(1<<16)),
- Math::fast_ftoi(panf[3]*(1<<16))};
-
- switch(channels) {
- case 1: {
-
- for(int i=0;i<to_mix;i++) {
-
- in[0]=internal_buffer[i];
- in[1]=internal_buffer[i];
- in[2]=internal_buffer[i];
- in[3]=internal_buffer[i];
- DO_FILTER(0);
- DO_FILTER(1);
- DO_FILTER(2);
- DO_FILTER(3);
- p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]);
- p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]);
- p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]);
- p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]);
- }
- } break;
- case 2: {
-
- for(int i=0;i<to_mix;i++) {
-
- in[0]=internal_buffer[(i<<1)+0];
- in[1]=internal_buffer[(i<<1)+1];
- in[2]=internal_buffer[(i<<1)+0];
- in[3]=internal_buffer[(i<<1)+1];
- DO_FILTER(0);
- DO_FILTER(1);
- DO_FILTER(2);
- DO_FILTER(3);
- p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]);
- p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]);
- p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]);
- p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]);
- }
- } break;
- case 4: {
-
- for(int i=0;i<to_mix;i++) {
-
- in[0]=internal_buffer[(i<<2)+0];
- in[1]=internal_buffer[(i<<2)+1];
- in[2]=internal_buffer[(i<<2)+2];
- in[3]=internal_buffer[(i<<2)+3];
- DO_FILTER(0);
- DO_FILTER(1);
- DO_FILTER(2);
- DO_FILTER(3);
- p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]);
- p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]);
- p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]);
- p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]);
- }
- } break;
-
- } break;
-
- } break;
- case 6: {
-
-
- } break;
- }
- p_buffer+=to_mix*internal_buffer_channels;
- todo-=to_mix;
-
- }
-
- }
-
- return true;
-}
-
-void SpatialSoundServerSW::update(float p_delta) {
-
- List<ActiveVoice> to_disable;
-
-
- for(Set<ActiveVoice>::Element *E=active_voices.front();E;E=E->next()) {
-
- Source *source = E->get().source;
- int voice = E->get().voice;
-
- if (voice!=VOICE_IS_STREAM) {
- Source::Voice &v=source->voices[voice];
- ERR_CONTINUE(!v.active && !v.restart); // likely a bug...
- }
-
- //this could be optimized at some point... am not sure
- Space *space=space_owner.get(source->space);
- Room *room=room_owner.get(space->default_room);
- int max_level=-0x80000000;
- int rooms_culled = space->octree.cull_point(source->transform.origin,cull_rooms,MAX_CULL_ROOMS);
- for(int i=0;i<rooms_culled;i++) {
-
- Room *r=cull_rooms[i];
- ERR_CONTINUE( r->bounds.is_empty() ); // how did this happen??
- if (r->level<=max_level) //ignore optimization (level too low)
- continue;
- Vector3 local_point = r->inverse_transform.xform(source->transform.origin);
- if (!r->bounds.point_is_inside(local_point))
- continue;
- room=r;
- max_level=r->level;
-
- }
-
-
- //compute mixing weights (support for multiple listeners in the same output)
- float total_distance=0;
- for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) {
- Listener *listener=listener_owner.get(L->get());
- total_distance+=listener->transform.origin.distance_to(source->transform.origin);
- }
-
- //compute spatialization variables, weighted according to distance
- float volume_attenuation = 0.0;
- float air_absorption_hf_cutoff = 0.0;
- float air_absorption = 0.0;
- float pitch_scale=1.0;
- Vector3 panning;
-
-
- //print_line("listeners: "+itos(space->listeners.size()));
-
-
- for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) {
-
- Listener *listener=listener_owner.get(L->get());
-
- Vector3 rel_vector = listener->transform.xform_inv(source->transform.origin);
- Vector3 source_rel_vector = source->transform.xform_inv(listener->transform.origin).normalized();
- float distance=rel_vector.length();
- float weight = distance/total_distance;
- float pscale=1.0;
-
- float distance_scale=listener->params[LISTENER_PARAM_ATTENUATION_SCALE]*room->params[ROOM_PARAM_ATTENUATION_SCALE];
- float distance_min=source->params[SOURCE_PARAM_ATTENUATION_MIN_DISTANCE]*distance_scale;
- float distance_max=source->params[SOURCE_PARAM_ATTENUATION_MAX_DISTANCE]*distance_scale;
- float attenuation_exp=source->params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP];
- float attenuation=1;
-
- //print_line("DIST MIN: "+rtos(distance_min));
- //print_line("DIST MAX: "+rtos(distance_max));
- if (distance_max>0) {
- distance = CLAMP(distance,distance_min,distance_max);
- attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16));
- }
-
- float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF];
- float hf_attenuation_exp = room->params[ROOM_PARAM_ATTENUATION_HF_RATIO_EXP];
- float hf_attenuation_floor = room->params[ROOM_PARAM_ATTENUATION_HF_FLOOR_DB];
- float absorption=Math::db2linear(Math::lerp(hf_attenuation_floor,0,Math::pow(attenuation,hf_attenuation_exp)));
-
- // source emission cone
-
- float emission_deg=source->params[SOURCE_PARAM_EMISSION_CONE_DEGREES];
- float emission_attdb=source->params[SOURCE_PARAM_EMISSION_CONE_ATTENUATION_DB];
- absorption*=_get_attenuation(source_rel_vector.dot(Vector3(0,0,-1)),emission_deg,emission_attdb);
-
- Vector3 vpanning=rel_vector.normalized();
-
- //listener stuff
-
- {
-
- // head cone
-
- float reception_deg=listener->params[LISTENER_PARAM_RECEPTION_CONE_DEGREES];
- float reception_attdb=listener->params[LISTENER_PARAM_RECEPTION_CONE_ATTENUATION_DB];
-
- absorption*=_get_attenuation(vpanning.dot(Vector3(0,0,-1)),reception_deg,reception_attdb);
-
- // scale
-
- attenuation*=Math::db2linear(listener->params[LISTENER_PARAM_VOLUME_SCALE_DB]);
- pscale*=Math::db2linear(listener->params[LISTENER_PARAM_PITCH_SCALE]);
-
-
- }
-
-
-
-
- //add values
-
- volume_attenuation+=weight*attenuation; // plus other stuff i guess
- air_absorption+=weight*absorption;
- air_absorption_hf_cutoff+=weight*hf_attenuation_cutoff;
- panning+=vpanning*weight;
- //pitch_scale+=pscale*weight;
-
- }
-
- RoomReverb reverb_room;
- float reverb_send;
-
- /* APPLY ROOM SETTINGS */
-
- {
- pitch_scale*=room->params[ROOM_PARAM_PITCH_SCALE];
- volume_attenuation*=Math::db2linear(room->params[ROOM_PARAM_VOLUME_SCALE_DB]);
- reverb_room=room->reverb;
- reverb_send=Math::lerp(1.0,volume_attenuation,room->params[ROOM_PARAM_ATTENUATION_REVERB_SCALE])*room->params[ROOM_PARAM_REVERB_SEND];
-
- }
-
- /* UPDATE VOICE & STREAM */
-
-
-
- if (voice==VOICE_IS_STREAM) {
-
- //update voice!!
- source->stream_data.panning=panning;
- source->stream_data.volume=volume_attenuation*Math::db2linear(source->params[SOURCE_PARAM_VOLUME_DB]);
- source->stream_data.reverb=reverb_room;
- source->stream_data.reverb_send=reverb_send;
- source->stream_data.filter_gain=air_absorption;
- source->stream_data.filter_cutoff=air_absorption_hf_cutoff;
-
- if (!source->stream) //stream is gone bye bye
- to_disable.push_back(ActiveVoice(source,voice)); // oh well..
-
- } else if (voice>=0) {
- //update stream!!
- Source::Voice &v=source->voices[voice];
-
- if (v.restart)
- AudioServer::get_singleton()->voice_play(v.voice_rid,v.sample_rid);
-
- float volume_scale = Math::db2linear(v.volume_scale)*Math::db2linear(source->params[SOURCE_PARAM_VOLUME_DB]);
- float volume = volume_attenuation*volume_scale;
- reverb_send*=volume_scale;
- int mix_rate = v.sample_mix_rate*v.pitch_scale*pitch_scale*source->params[SOURCE_PARAM_PITCH_SCALE];
-
-
- if (mix_rate<=0) {
- ERR_PRINT("Invalid mix rate for voice (0) check for invalid pitch_scale param.");
- to_disable.push_back(ActiveVoice(source,voice)); // oh well..
- continue; //invalid mix rate, disabling
- }
- if (v.restart || v.last_volume!=volume)
- AudioServer::get_singleton()->voice_set_volume(v.voice_rid,volume);
- if (v.restart || v.last_mix_rate!=mix_rate)
- AudioServer::get_singleton()->voice_set_mix_rate(v.voice_rid,mix_rate);
- if (v.restart || v.last_filter_gain!=air_absorption || v.last_filter_cutoff!=air_absorption_hf_cutoff)
- AudioServer::get_singleton()->voice_set_filter(v.voice_rid,AudioServer::FILTER_HIGH_SHELF,air_absorption_hf_cutoff,1.0,air_absorption);
- if (v.restart || v.last_panning!=panning)
- AudioServer::get_singleton()->voice_set_pan(v.voice_rid,panning.x,panning.y,panning.z);
- if (v.restart || v.last_reverb_room!=reverb_room || v.last_reverb_send!=reverb_send)
- AudioServer::get_singleton()->voice_set_reverb(v.voice_rid,AudioServer::ReverbRoomType(reverb_room),reverb_send);
-
- v.last_volume=volume;
- v.last_mix_rate=mix_rate;
- v.last_filter_gain=air_absorption;
- v.last_filter_cutoff=air_absorption_hf_cutoff;
- v.last_panning=panning;
- v.restart=false;
- v.active=true;
-
- if (!AudioServer::get_singleton()->voice_is_active(v.voice_rid))
- to_disable.push_back(ActiveVoice(source,voice)); // oh well..
- }
- }
-
- while(to_disable.size()) {
-
- ActiveVoice av = to_disable.front()->get();
- av.source->voices[av.voice].active=false;
- av.source->voices[av.voice].restart=false;
- active_voices.erase(av);
- to_disable.pop_front();
- }
-
-}
-void SpatialSoundServerSW::finish() {
-
- AudioServer::get_singleton()->free(internal_audio_stream_rid);
- memdelete(internal_audio_stream);
-
- _clean_up_owner(&source_owner,"Source");
- _clean_up_owner(&listener_owner,"Listener");
- _clean_up_owner(&room_owner,"Room");
- _clean_up_owner(&space_owner,"Space");
-
- memdelete_arr(internal_buffer);
-}
-
-SpatialSoundServerSW::SpatialSoundServerSW() {
-
-}
diff --git a/servers/spatial_sound/spatial_sound_server_sw.h b/servers/spatial_sound/spatial_sound_server_sw.h
deleted file mode 100644
index b4295bf145..0000000000
--- a/servers/spatial_sound/spatial_sound_server_sw.h
+++ /dev/null
@@ -1,266 +0,0 @@
-/*************************************************************************/
-/* spatial_sound_server_sw.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 SPATIAL_SOUND_SERVER_SW_H
-#define SPATIAL_SOUND_SERVER_SW_H
-
-#include "servers/spatial_sound_server.h"
-#include "octree.h"
-#include "os/thread_safe.h"
-
-
-class SpatialSoundServerSW : public SpatialSoundServer {
-
- OBJ_TYPE(SpatialSoundServerSW,SpatialSoundServer);
-
- _THREAD_SAFE_CLASS_
-
- enum {
- MAX_CULL_ROOMS=128,
- INTERNAL_BUFFER_SIZE=4096,
- INTERNAL_BUFFER_MAX_CHANNELS=4,
- VOICE_IS_STREAM=-1
-
- };
-
-
- struct InternalAudioStream : public AudioServer::AudioStream {
-
- ::SpatialSoundServerSW *owner;
- virtual int get_channel_count() const;
- virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate
- virtual bool mix(int32_t *p_buffer,int p_frames);
- virtual void update();
- };
-
- InternalAudioStream *internal_audio_stream;
- RID internal_audio_stream_rid;
- int32_t *internal_buffer;
- int internal_buffer_channels;
-
- bool internal_buffer_mix(int32_t *p_buffer,int p_frames);
-
- struct Room;
-
- struct Space {
-
- RID default_room;
- Set<RID> rooms;
- Set<RID> sources;
- Set<RID> listeners;
-
- Octree<Room> octree;
- };
-
- mutable RID_Owner<Space> space_owner;
-
- struct Room {
- RID space;
- Transform transform;
- Transform inverse_transform;
- BSP_Tree bounds;
- RoomReverb reverb;
- float params[ROOM_PARAM_MAX];
- bool override_other_sources;
- OctreeElementID octree_id;
- int level;
-
- Room();
- };
-
- mutable RID_Owner<Room> room_owner;
-
-
-
- struct Source {
-
- struct Voice {
-
- RID voice_rid;
- RID sample_rid;
- bool active;
- bool restart;
- float pitch_scale;
- float volume_scale;
- int sample_mix_rate;
-
-
- float last_volume;
- float last_filter_gain;
- float last_filter_cutoff;
- Vector3 last_panning;
- int last_mix_rate;
- RoomReverb last_reverb_room;
- float last_reverb_send;
-
- Voice();
- ~Voice();
- };
-
- struct StreamData {
-
-
- Vector3 panning;
- RoomReverb reverb;
- float reverb_send;
- float volume;
- float filter_gain;
- float filter_cutoff;
-
- struct FilterState {
-
- float ha[2];
- float hb[2];
- } filter_state[4];
-
- StreamData() {
-
- reverb_send=0;
- reverb=ROOM_REVERB_HALL;
- volume=1.0;
- filter_gain=1;
- filter_cutoff=5000;
-
- }
- } stream_data;
-
- RID space;
- Transform transform;
- float params[SOURCE_PARAM_MAX];
- AudioServer::AudioStream *stream;
- Vector<Voice> voices;
- int last_voice;
-
- Source();
- };
-
- mutable RID_Owner<Source> source_owner;
-
- struct Listener {
-
- RID space;
- Transform transform;
- float params[LISTENER_PARAM_MAX];
-
- Listener();
- };
-
- mutable RID_Owner<Listener> listener_owner;
-
- struct ActiveVoice {
-
- Source *source;
- int voice;
- bool operator<(const ActiveVoice& p_voice) const { return (voice==p_voice.voice)?(source<p_voice.source):(voice<p_voice.voice); }
- ActiveVoice(Source *p_source=NULL,int p_voice=0) { source=p_source; voice=p_voice; }
- };
-
- Room *cull_rooms[MAX_CULL_ROOMS];
-
- Set<Source*> streaming_sources;
- Set<ActiveVoice> active_voices;
-
- void _clean_up_owner(RID_OwnerBase *p_owner, const char *p_area);
- void _update_sources();
-
-public:
-
- /* SPACE */
- virtual RID space_create();
-
- /* ROOM */
-
- virtual RID room_create();
- virtual void room_set_space(RID p_room,RID p_space);
- virtual RID room_get_space(RID p_room) const;
-
- virtual void room_set_bounds(RID p_room, const BSP_Tree& p_bounds);
- virtual BSP_Tree room_get_bounds(RID p_room) const;
- virtual void room_set_transform(RID p_room, const Transform& p_transform);
- virtual Transform room_get_transform(RID p_room) const;
-
-
- virtual void room_set_param(RID p_room, RoomParam p_param, float p_value);
- virtual float room_get_param(RID p_room, RoomParam p_param) const;
-
- virtual void room_set_level(RID p_room, int p_level);
- virtual int room_get_level(RID p_room) const;
-
- virtual void room_set_reverb(RID p_room, RoomReverb p_reverb);
- virtual RoomReverb room_get_reverb(RID p_room) const;
-
- //useful for underwater or rooms with very strange conditions
- virtual void room_set_force_params_to_all_sources(RID p_room, bool p_force);
- virtual bool room_is_forcing_params_to_all_sources(RID p_room) const;
-
- /* SOURCE */
-
- virtual RID source_create(RID p_space);
-
- virtual void source_set_polyphony(RID p_source,int p_voice_count);
- virtual int source_get_polyphony(RID p_source) const;
-
- virtual void source_set_transform(RID p_source, const Transform& p_transform);
- virtual Transform source_get_transform(RID p_source) const;
-
- virtual void source_set_param(RID p_source, SourceParam p_param, float p_value);
- virtual float source_get_param(RID p_source, SourceParam p_param) const;
-
- virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream); //null to unset
- virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice=SOURCE_NEXT_VOICE);
- /* VOICES */
- virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale);
- virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume);
-
- virtual bool source_is_voice_active(RID p_source, SourceVoiceID p_voice) const;
- virtual void source_stop_voice(RID p_source, SourceVoiceID p_voice);
-
- /* LISTENER */
-
- virtual RID listener_create();
- virtual void listener_set_space(RID p_listener, RID p_space);
-
- virtual void listener_set_transform(RID p_listener, const Transform& p_transform);
- virtual Transform listener_get_transform(RID p_listener) const;
-
- virtual void listener_set_param(RID p_listener, ListenerParam p_param, float p_value);
- virtual float listener_get_param(RID p_listener, ListenerParam p_param) const;
-
-
- /* MISC */
-
- virtual void free(RID p_id);
-
- virtual void init();
- virtual void update(float p_delta);
- virtual void finish();
-
- SpatialSoundServerSW();
-};
-
-#endif // SPATIAL_SOUND_SERVER_SW_H
diff --git a/servers/spatial_sound_2d/SCsub b/servers/spatial_sound_2d/SCsub
deleted file mode 100644
index d31af2c1c4..0000000000
--- a/servers/spatial_sound_2d/SCsub
+++ /dev/null
@@ -1,5 +0,0 @@
-Import('env')
-
-env.add_source_files(env.servers_sources,"*.cpp")
-
-Export('env')
diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp
deleted file mode 100644
index 6c42c2f527..0000000000
--- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.cpp
+++ /dev/null
@@ -1,1042 +0,0 @@
-/*************************************************************************/
-/* spatial_sound_2d_server_sw.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 "spatial_sound_2d_server_sw.h"
-
-#include "os/os.h"
-#include "servers/audio/audio_filter_sw.h"
-
-
-
-int SpatialSound2DServerSW::InternalAudioStream::get_channel_count() const {
-
- return AudioServer::get_singleton()->get_default_channel_count();
-}
-
-void SpatialSound2DServerSW::InternalAudioStream::set_mix_rate(int p_rate) {
-
-
-}
-
-void SpatialSound2DServerSW::InternalAudioStream::update() {
-
- owner->_update_sources();
-}
-
-bool SpatialSound2DServerSW::InternalAudioStream::mix(int32_t *p_buffer,int p_frames) {
-
- return owner->internal_buffer_mix(p_buffer,p_frames);
-}
-
-void SpatialSound2DServerSW::_update_sources() {
-
- _THREAD_SAFE_METHOD_
- for (Set<Source*>::Element *E=streaming_sources.front();E;E=E->next()) {
-
- Source *s=E->get();
- ERR_CONTINUE(!s->stream);
- s->stream->update();
- }
-}
-
-
-SpatialSound2DServerSW::Room::Room() {
-
-// params[ROOM_PARAM_SPEED_OF_SOUND]=343.0;
- params[ROOM_PARAM_PITCH_SCALE]=1.0;
- params[ROOM_PARAM_VOLUME_SCALE_DB]=0;
- params[ROOM_PARAM_REVERB_SEND]=0;
- params[ROOM_PARAM_CHORUS_SEND]=0;
- params[ROOM_PARAM_ATTENUATION_SCALE]=1.0;
- params[ROOM_PARAM_ATTENUATION_HF_CUTOFF]=5000;
- params[ROOM_PARAM_ATTENUATION_HF_FLOOR_DB]=-24.0;
- params[ROOM_PARAM_ATTENUATION_HF_RATIO_EXP]=1.0;
- params[ROOM_PARAM_ATTENUATION_REVERB_SCALE]=0.0;
- override_other_sources=false;
- reverb=ROOM_REVERB_HALL;
-// octree_id=0;
- level=-1;
-
-
-}
-
-
-SpatialSound2DServerSW::Source::Source() {
-
- params[SOURCE_PARAM_VOLUME_DB]=0.0;
- params[SOURCE_PARAM_PITCH_SCALE]=1.0;
- params[SOURCE_PARAM_ATTENUATION_MIN_DISTANCE]=1;
- params[SOURCE_PARAM_ATTENUATION_MAX_DISTANCE]=100;
- params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP]=1.0; //linear (and not really good)
- stream=NULL;
- voices.resize(1);
- last_voice=0;
-}
-
-SpatialSound2DServerSW::Source::Voice::Voice() {
-
- active=false;
- restart=false;
- pitch_scale=1.0;
- volume_scale=0.0;
- voice_rid=AudioServer::get_singleton()->voice_create();
-
-}
-SpatialSound2DServerSW::Source::Voice::~Voice() {
-
- AudioServer::get_singleton()->free(voice_rid);
-}
-
-
-SpatialSound2DServerSW::Listener::Listener() {
-
- params[LISTENER_PARAM_VOLUME_SCALE_DB]=0.0;
- params[LISTENER_PARAM_PITCH_SCALE]=1.0;
- params[LISTENER_PARAM_ATTENUATION_SCALE]=1.0;
- params[LISTENER_PARAM_PAN_RANGE]=128;
-
-}
-
-/* SPACE */
-RID SpatialSound2DServerSW::space_create() {
-
- Space* space = memnew( Space );
- RID space_rid = space_owner.make_rid(space);
- space->default_room=room_create();
- room_set_space(space->default_room,space_rid);
- return space_rid;
-}
-
-/* ROOM */
-
-RID SpatialSound2DServerSW::room_create() {
-
- Room *room = memnew( Room );
- return room_owner.make_rid(room);
-}
-
-void SpatialSound2DServerSW::room_set_space(RID p_room,RID p_space) {
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
-
- if (room->space.is_valid()) {
-
- Space *space = space_owner.get(room->space);
- space->rooms.erase(p_room);
-// space->octree.erase(room->octree_id);
- //room->octree_id=0;
- }
-
- room->space=RID();
-
- if (p_space.is_valid()) {
-
- Space *space = space_owner.get(p_space);
- ERR_FAIL_COND(!space);
- space->rooms.insert(p_room);
-// room->octree_id=space->octree.create(room,AABB());
- //set bounds
-// AABB aabb = room->bounds.is_empty()?AABB():room->bounds.get_aabb();
- // space->octree.move(room->octree_id,room->transform.xform(aabb));
- room->space=p_space;
- }
-
-
-}
-
-RID SpatialSound2DServerSW::room_get_space(RID p_room) const {
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,RID());
-
-
- return room->space;
-}
-
-
-
-void SpatialSound2DServerSW::room_set_bounds(RID p_room, const DVector<Point2>& p_bounds) {
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
-
- room->bounds=p_bounds;
-
- if (!room->space.is_valid())
- return;
-
-// AABB aabb = room->bounds.is_empty()?AABB():room->bounds.get_aabb();
-// Space* space = space_owner.get(room->space);
-// ERR_FAIL_COND(!space);
-
-// space->octree.move(room->octree_id,room->transform.xform(aabb));
-
-}
-DVector<Point2> SpatialSound2DServerSW::room_get_bounds(RID p_room) const {
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,DVector<Point2>());
-
- return room->bounds;
-}
-
-void SpatialSound2DServerSW::room_set_transform(RID p_room, const Matrix32& p_transform) {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
- room->transform=p_transform;
- room->inverse_transform=p_transform.affine_inverse(); // needs to be done to unscale BSP properly
-
- if (!room->space.is_valid())
- return;
-
- /*
- if (!room->bounds.is_empty()) {
-
- Space* space = space_owner.get(room->space);
- ERR_FAIL_COND(!space);
-
- //space->octree.move(room->octree_id,room->transform.xform(room->bounds.get_aabb()));
- }*/
-}
-
-Matrix32 SpatialSound2DServerSW::room_get_transform(RID p_room) const {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,Matrix32());
- return room->transform;
-}
-
-
-void SpatialSound2DServerSW::room_set_param(RID p_room, RoomParam p_param, float p_value) {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- ERR_FAIL_INDEX(p_param,ROOM_PARAM_MAX);
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
- room->params[p_param]=p_value;
-
-}
-float SpatialSound2DServerSW::room_get_param(RID p_room, RoomParam p_param) const {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- ERR_FAIL_INDEX_V(p_param,ROOM_PARAM_MAX,0);
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,0);
- return room->params[p_param];
-}
-
-void SpatialSound2DServerSW::room_set_level(RID p_room, int p_level) {
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
- room->level =p_level;
-
-}
-
-int SpatialSound2DServerSW::room_get_level(RID p_room) const {
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,0);
- return room->level;
-
-}
-
-
-void SpatialSound2DServerSW::room_set_reverb(RID p_room, RoomReverb p_reverb) {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
- room->reverb=p_reverb;
-
-}
-SpatialSound2DServerSW::RoomReverb SpatialSound2DServerSW::room_get_reverb(RID p_room) const {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,ROOM_REVERB_SMALL);
- return room->reverb;
-}
-
-//useful for underwater or rooms with very strange conditions
-void SpatialSound2DServerSW::room_set_force_params_to_all_sources(RID p_room, bool p_force) {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND(!room);
- room->override_other_sources=p_force;
-
-}
-bool SpatialSound2DServerSW::room_is_forcing_params_to_all_sources(RID p_room) const {
-
- if (space_owner.owns(p_room))
- p_room=space_owner.get(p_room)->default_room;
-
- Room *room = room_owner.get(p_room);
- ERR_FAIL_COND_V(!room,false);
- return room->override_other_sources;
-}
-
-/* SOURCE */
-
-RID SpatialSound2DServerSW::source_create(RID p_space) {
-
- Space *space = space_owner.get(p_space);
- ERR_FAIL_COND_V(!space,RID());
-
- Source *source = memnew( Source );
- source->space=p_space;
- RID source_rid = source_owner.make_rid(source);
- space->sources.insert(source_rid);
-
- return source_rid;
-}
-
-
-void SpatialSound2DServerSW::source_set_polyphony(RID p_source,int p_voice_count) {
-
-
- ERR_FAIL_COND(p_voice_count<=0); // more than 32 is too much, change this if you really need more
- if (p_voice_count>32) {
-
- ERR_PRINT("Voices will be clipped to 32");
- p_voice_count=32;
- }
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
-
- if (p_voice_count<source->voices.size()) {
-
- for(int i=p_voice_count;i<source->voices.size();i++) {
- active_voices.erase(ActiveVoice(source,i)); //erase from active voices
- }
- }
- source->voices.resize(p_voice_count);
-
-}
-
-int SpatialSound2DServerSW::source_get_polyphony(RID p_source) const {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND_V(!source,-1);
- return source->voices.size();
-
-}
-
-void SpatialSound2DServerSW::source_set_transform(RID p_source, const Matrix32& p_transform) {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
- source->transform=p_transform;
- source->transform.orthonormalize();
-}
-Matrix32 SpatialSound2DServerSW::source_get_transform(RID p_source) const {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND_V(!source,Matrix32());
- return source->transform;
-}
-
-void SpatialSound2DServerSW::source_set_param(RID p_source, SourceParam p_param, float p_value) {
-
- ERR_FAIL_INDEX(p_param,SOURCE_PARAM_MAX);
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
- source->params[p_param]=p_value;
-
-}
-float SpatialSound2DServerSW::source_get_param(RID p_source, SourceParam p_param) const {
- ERR_FAIL_INDEX_V(p_param,SOURCE_PARAM_MAX,0);
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND_V(!source,0);
- return source->params[p_param];
-
-
-}
-
-void SpatialSound2DServerSW::source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream) {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
- AudioServer::get_singleton()->lock();
- source->stream=p_stream;
- _THREAD_SAFE_METHOD_
-
- if (!p_stream) {
- streaming_sources.erase(source);
- active_voices.erase(ActiveVoice(source,VOICE_IS_STREAM));
- } else {
- streaming_sources.insert(source);
- active_voices.insert(ActiveVoice(source,VOICE_IS_STREAM));
- zeromem(source->stream_data.filter_state,sizeof(Source::StreamData::FilterState)*4); //reset filter for safetyness
- p_stream->set_mix_rate(AudioServer::get_singleton()->get_default_mix_rate());
- }
-
- AudioServer::get_singleton()->unlock();
-
-} //null to unset
-
-SpatialSound2DServer::SourceVoiceID SpatialSound2DServerSW::source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice) {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND_V(!source,SOURCE_INVALID_VOICE);
-
- int to_play=0;
-
- if (p_voice==SOURCE_NEXT_VOICE) {
- to_play=source->last_voice+1;
- if (to_play>=source->voices.size())
- to_play=0;
-
- } else
- to_play=p_voice;
-
- ERR_FAIL_INDEX_V(to_play,source->voices.size(),SOURCE_INVALID_VOICE);
-
- source->voices[to_play].restart=true;
- source->voices[to_play].sample_rid=p_sample;
- source->voices[to_play].sample_mix_rate=p_mix_rate;
- source->voices[to_play].pitch_scale=1;
- source->voices[to_play].volume_scale=0;
- source->last_voice=to_play;
- active_voices.insert(ActiveVoice(source,to_play));
- return to_play;
-}
-
-/* VOICES */
-void SpatialSound2DServerSW::source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale) {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
- ERR_FAIL_INDEX(p_voice,source->voices.size());
- source->voices[p_voice].pitch_scale=p_pitch_scale;
-
-}
-void SpatialSound2DServerSW::source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_db) {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
- ERR_FAIL_INDEX(p_voice,source->voices.size());
- source->voices[p_voice].volume_scale=p_db;
-
-}
-
-bool SpatialSound2DServerSW::source_is_voice_active(RID p_source, SourceVoiceID p_voice) const {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND_V(!source,false);
- ERR_FAIL_INDEX_V(p_voice,source->voices.size(),false);
- return source->voices[p_voice].active || source->voices[p_voice].restart;
-
-}
-void SpatialSound2DServerSW::source_stop_voice(RID p_source, SourceVoiceID p_voice) {
-
- Source *source = source_owner.get(p_source);
- ERR_FAIL_COND(!source);
- ERR_FAIL_INDEX(p_voice,source->voices.size());
- if (source->voices[p_voice].active) {
- AudioServer::get_singleton()->voice_stop(source->voices[p_voice].voice_rid);
- }
- source->voices[p_voice].active=false;
- source->voices[p_voice].restart=false;
- active_voices.erase(ActiveVoice(source,p_voice));
-}
-
-/* LISTENER */
-
-RID SpatialSound2DServerSW::listener_create() {
-
- Listener *listener = memnew( Listener );
- RID listener_rid = listener_owner.make_rid(listener);
- return listener_rid;
-
-}
-
-void SpatialSound2DServerSW::listener_set_space(RID p_listener,RID p_space) {
-
- Listener *listener = listener_owner.get(p_listener);
- ERR_FAIL_COND(!listener);
-
- if (listener->space.is_valid()) {
-
- Space *lspace = space_owner.get(listener->space);
- ERR_FAIL_COND(!lspace);
- lspace->listeners.erase(p_listener);
- }
-
- listener->space=RID();
-
- if (p_space.is_valid()) {
- Space *space = space_owner.get(p_space);
- ERR_FAIL_COND(!space);
-
- listener->space=p_space;
- space->listeners.insert(p_listener);
- }
-
-}
-
-void SpatialSound2DServerSW::listener_set_transform(RID p_listener, const Matrix32& p_transform) {
-
- Listener *listener = listener_owner.get(p_listener);
- ERR_FAIL_COND(!listener);
- listener->transform=p_transform;
- listener->transform.orthonormalize(); //must be done..
-}
-Matrix32 SpatialSound2DServerSW::listener_get_transform(RID p_listener) const {
-
- Listener *listener = listener_owner.get(p_listener);
- ERR_FAIL_COND_V(!listener,Matrix32());
- return listener->transform;
-}
-
-void SpatialSound2DServerSW::listener_set_param(RID p_listener, ListenerParam p_param, float p_value) {
-
- ERR_FAIL_INDEX(p_param,LISTENER_PARAM_MAX);
- Listener *listener = listener_owner.get(p_listener);
- ERR_FAIL_COND(!listener);
- listener->params[p_param]=p_value;
-}
-
-float SpatialSound2DServerSW::listener_get_param(RID p_listener, ListenerParam p_param) const {
-
- ERR_FAIL_INDEX_V(p_param,LISTENER_PARAM_MAX,0);
- Listener *listener = listener_owner.get(p_listener);
- ERR_FAIL_COND_V(!listener,0);
- return listener->params[p_param];
-}
-
-
-/* MISC */
-
-void SpatialSound2DServerSW::free(RID p_id) {
-
-
- if (space_owner.owns(p_id)) {
-
- Space *space = space_owner.get(p_id);
- free(space->default_room);
-
- while(space->listeners.size()) {
- listener_set_space(space->listeners.front()->get(),RID());
- }
- while(space->sources.size()) {
- free(space->sources.front()->get());
- }
- while(space->rooms.size()) {
- room_set_space(space->rooms.front()->get(),RID());
- }
- space_owner.free(p_id);
- memdelete(space);
-
- } else if (source_owner.owns(p_id)) {
-
- Source *source = source_owner.get(p_id);
- if (source->stream)
- source_set_audio_stream(p_id,NULL);
-
- Space *space = space_owner.get(source->space);
- ERR_FAIL_COND(!space);
- space->sources.erase(p_id);
- for(int i=0;i<source->voices.size();i++) {
- active_voices.erase(ActiveVoice(source,i));
- }
- source_owner.free(p_id);
- memdelete(source);
- } else if (listener_owner.owns(p_id)) {
-
- Listener *listener = listener_owner.get(p_id);
- if (listener->space.is_valid()) {
- Space *space = space_owner.get(listener->space);
- ERR_FAIL_COND(!space);
- space->listeners.erase(p_id);
- }
- listener_owner.free(p_id);
- memdelete(listener);
-
- } else if (room_owner.owns(p_id)) {
-
- Room *room = room_owner.get(p_id);
-
- if (room->space.is_valid()) {
- Space *space = space_owner.get(room->space);
- ERR_FAIL_COND(!space);
-// space->octree.erase(room->octree_id);
- space->rooms.erase(p_id);
- }
- room_owner.free(p_id);
- memdelete(room);
- } else {
- ERR_PRINT("Attempt to free invalid ID") ;
- }
-
-}
-
-void SpatialSound2DServerSW::_clean_up_owner(RID_OwnerBase *p_owner, const char *p_area) {
-
- List<RID> rids;
- p_owner->get_owned_list(&rids);
-
- for(List<RID>::Element *I=rids.front();I;I=I->next()) {
- if (OS::get_singleton()->is_stdout_verbose()) {
-
- print_line("Leaked RID ("+itos(I->get().get_id())+") of type "+String(p_area));
- }
- free(I->get());
- }
-}
-
-void SpatialSound2DServerSW::init() {
-
- internal_buffer = memnew_arr(int32_t, INTERNAL_BUFFER_SIZE*INTERNAL_BUFFER_MAX_CHANNELS);
- internal_buffer_channels=AudioServer::get_singleton()->get_default_channel_count();
-
- internal_audio_stream = memnew( InternalAudioStream );
- internal_audio_stream->owner=this;
- internal_audio_stream_rid = AudioServer::get_singleton()->audio_stream_create(internal_audio_stream);
-
- AudioServer::get_singleton()->stream_set_active(internal_audio_stream_rid,true);
-
-}
-
-
-
-bool SpatialSound2DServerSW::internal_buffer_mix(int32_t *p_buffer,int p_frames) {
-
- if (streaming_sources.size()==0)
- return false; //nothing to mix
-
-
- for (Set<Source*>::Element *E=streaming_sources.front();E;E=E->next()) {
-
- Source *s=E->get();
- ERR_CONTINUE(!s->stream);
-
- int channels = s->stream->get_channel_count();
- Source::StreamData &sd=s->stream_data;
-
- int todo=p_frames;
-
- AudioFilterSW filter;
- filter.set_sampling_rate(AudioServer::get_singleton()->get_default_mix_rate());
- filter.set_cutoff(sd.filter_cutoff);
- filter.set_gain(sd.filter_gain);
- filter.set_resonance(1);
- filter.set_mode(AudioFilterSW::HIGHSHELF);
- filter.set_stages(1);
- AudioFilterSW::Coeffs coefs;
- filter.prepare_coefficients(&coefs);
-
- int32_t in[4];
-#ifndef SPATIAL_SOUND_SERVER_NO_FILTER
-#define DO_FILTER(m_c)\
- {\
- float val = in[m_c];\
- float pre=val;\
- val = val*coefs.b0 + sd.filter_state[m_c].hb[0]*coefs.b1 + sd.filter_state[m_c].hb[1]*coefs.b2 + sd.filter_state[m_c].ha[0]*coefs.a1 + sd.filter_state[m_c].ha[1]*coefs.a2;\
- sd.filter_state[m_c].ha[1]=sd.filter_state[m_c].ha[0];\
- sd.filter_state[m_c].hb[1]=sd.filter_state[m_c].hb[0]; \
- sd.filter_state[m_c].hb[0]=pre;\
- sd.filter_state[m_c].ha[0]=val;\
- in[m_c]=Math::fast_ftoi(val);\
- }
-#else
-#define DO_FILTER(m_c)
-#endif
-
- while(todo) {
-
- int to_mix=MIN(todo,INTERNAL_BUFFER_SIZE);
-
- s->stream->mix(internal_buffer,to_mix);
-
- switch(internal_buffer_channels) {
-
- case 2: {
-
- float p = sd.panning.x*0.5+0.5;
- float panf[2]={ (1.0-p),p };
- panf[0]*=sd.volume;
- panf[1]*=sd.volume;
-
- int32_t pan[2]={Math::fast_ftoi(panf[0]*(1<<16)),Math::fast_ftoi(panf[1]*(1<<16))};
-
- switch(channels) {
- case 1: {
-
- for(int i=0;i<to_mix;i++) {
-
- in[0]=internal_buffer[i];
- in[1]=internal_buffer[i];
- DO_FILTER(0);
- DO_FILTER(1);
- p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]);
- p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]);
- }
- } break;
- case 2: {
-
- for(int i=0;i<to_mix;i++) {
-
- in[0]=internal_buffer[(i<<1)+0];
- in[1]=internal_buffer[(i<<1)+1];
- DO_FILTER(0);
- DO_FILTER(1);
- p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]);
- p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]);
- }
- } break;
- case 4: {
-
- for(int i=0;i<to_mix;i++) {
-
- in[0]=(internal_buffer[(i<<2)+0]+internal_buffer[(i<<2)+2])>>1;
- in[1]=(internal_buffer[(i<<2)+1]+internal_buffer[(i<<2)+3])>>1;
- DO_FILTER(0);
- DO_FILTER(1);
- p_buffer[(i<<1)+0]=((in[0]>>16)*pan[0]);
- p_buffer[(i<<1)+1]=((in[1]>>16)*pan[1]);
- }
- } break;
-
- } break;
-
- } break;
- case 4: {
-
- float xp = sd.panning.x*0.5+0.5;
- float yp = sd.panning.y*0.5+0.5;
- float panf[4]={ (1.0-xp)*(1.0-yp),(xp)*(1.0-yp),(1.0-xp)*(yp),(xp)*(yp) };
- panf[0]*=sd.volume;
- panf[1]*=sd.volume;
- panf[2]*=sd.volume;
- panf[3]*=sd.volume;
-
- int32_t pan[4]={
- Math::fast_ftoi(panf[0]*(1<<16)),
- Math::fast_ftoi(panf[1]*(1<<16)),
- Math::fast_ftoi(panf[2]*(1<<16)),
- Math::fast_ftoi(panf[3]*(1<<16))};
-
- switch(channels) {
- case 1: {
-
- for(int i=0;i<to_mix;i++) {
-
- in[0]=internal_buffer[i];
- in[1]=internal_buffer[i];
- in[2]=internal_buffer[i];
- in[3]=internal_buffer[i];
- DO_FILTER(0);
- DO_FILTER(1);
- DO_FILTER(2);
- DO_FILTER(3);
- p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]);
- p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]);
- p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]);
- p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]);
- }
- } break;
- case 2: {
-
- for(int i=0;i<to_mix;i++) {
-
- in[0]=internal_buffer[(i<<1)+0];
- in[1]=internal_buffer[(i<<1)+1];
- in[2]=internal_buffer[(i<<1)+0];
- in[3]=internal_buffer[(i<<1)+1];
- DO_FILTER(0);
- DO_FILTER(1);
- DO_FILTER(2);
- DO_FILTER(3);
- p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]);
- p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]);
- p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]);
- p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]);
- }
- } break;
- case 4: {
-
- for(int i=0;i<to_mix;i++) {
-
- in[0]=internal_buffer[(i<<2)+0];
- in[1]=internal_buffer[(i<<2)+1];
- in[2]=internal_buffer[(i<<2)+2];
- in[3]=internal_buffer[(i<<2)+3];
- DO_FILTER(0);
- DO_FILTER(1);
- DO_FILTER(2);
- DO_FILTER(3);
- p_buffer[(i<<2)+0]=((in[0]>>16)*pan[0]);
- p_buffer[(i<<2)+1]=((in[1]>>16)*pan[1]);
- p_buffer[(i<<2)+2]=((in[2]>>16)*pan[2]);
- p_buffer[(i<<2)+3]=((in[3]>>16)*pan[3]);
- }
- } break;
-
- } break;
-
- } break;
- case 6: {
-
-
- } break;
- }
- p_buffer+=to_mix*internal_buffer_channels;
- todo-=to_mix;
-
- }
-
- }
-
- return true;
-}
-
-void SpatialSound2DServerSW::update(float p_delta) {
-
- List<ActiveVoice> to_disable;
-
- for(Set<ActiveVoice>::Element *E=active_voices.front();E;E=E->next()) {
-
- Source *source = E->get().source;
- int voice = E->get().voice;
-
- if (voice!=VOICE_IS_STREAM) {
- Source::Voice &v=source->voices[voice];
- ERR_CONTINUE(!v.active && !v.restart); // likely a bug...
- }
-
- //this could be optimized at some point... am not sure
- Space *space=space_owner.get(source->space);
- Room *room=room_owner.get(space->default_room);
-
- //compute mixing weights (support for multiple listeners in the same output)
- float total_distance=0;
- for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) {
- Listener *listener=listener_owner.get(L->get());
- float d = listener->transform.get_origin().distance_to(source->transform.get_origin());
- if (d==0)
- d=0.1;
- total_distance+=d;
- }
-
- //compute spatialization variables, weighted according to distance
- float volume_attenuation = 0.0;
- float air_absorption_hf_cutoff = 0.0;
- float air_absorption = 0.0;
- float pitch_scale=0.0;
- Vector2 panning;
-
- for(Set<RID>::Element *L=space->listeners.front();L;L=L->next()) {
-
- Listener *listener=listener_owner.get(L->get());
-
- Vector2 rel_vector = -listener->transform.xform_inv(source->transform.get_origin());
- //Vector2 source_rel_vector = source->transform.xform_inv(listener->transform.get_origin()).normalized();
- float distance=rel_vector.length();
- float weight = distance/total_distance;
- float pscale=1.0;
-
- float distance_scale=listener->params[LISTENER_PARAM_ATTENUATION_SCALE]*room->params[ROOM_PARAM_ATTENUATION_SCALE];
- float distance_min=source->params[SOURCE_PARAM_ATTENUATION_MIN_DISTANCE]*distance_scale;
- float distance_max=source->params[SOURCE_PARAM_ATTENUATION_MAX_DISTANCE]*distance_scale;
- float attenuation_exp=source->params[SOURCE_PARAM_ATTENUATION_DISTANCE_EXP];
- float attenuation=1;
-
- if (distance_max>0) {
- distance = CLAMP(distance,distance_min,distance_max);
- attenuation = Math::pow(1.0 - ((distance - distance_min)/(distance_max-distance_min)),CLAMP(attenuation_exp,0.001,16));
- }
-
- float hf_attenuation_cutoff = room->params[ROOM_PARAM_ATTENUATION_HF_CUTOFF];
- float hf_attenuation_exp = room->params[ROOM_PARAM_ATTENUATION_HF_RATIO_EXP];
- float hf_attenuation_floor = room->params[ROOM_PARAM_ATTENUATION_HF_FLOOR_DB];
- float absorption=Math::db2linear(Math::lerp(hf_attenuation_floor,0,Math::pow(attenuation,hf_attenuation_exp)));
-
- // source emission cone
-/* only for 3D
- float emission_deg=source->params[SOURCE_PARAM_EMISSION_CONE_DEGREES];
- float emission_attdb=source->params[SOURCE_PARAM_EMISSION_CONE_ATTENUATION_DB];
- absorption*=_get_attenuation(source_rel_vector.dot(Vector2(0,0,-1)),emission_deg,emission_attdb);
-*/
- Vector2 vpanning=rel_vector.normalized();
- if (distance < listener->params[LISTENER_PARAM_PAN_RANGE])
- vpanning*=distance/listener->params[LISTENER_PARAM_PAN_RANGE];
-
- //listener stuff
-
- {
-
- // head cone
-/* only for 3D
- float reception_deg=listener->params[LISTENER_PARAM_RECEPTION_CONE_DEGREES];
- float reception_attdb=listener->params[LISTENER_PARAM_RECEPTION_CONE_ATTENUATION_DB];
-
- absorption*=_get_attenuation(vpanning.dot(Vector2(0,0,-1)),reception_deg,reception_attdb);
-*/
-
- // scale
-
- attenuation*=Math::db2linear(listener->params[LISTENER_PARAM_VOLUME_SCALE_DB]);
- pscale*=Math::db2linear(listener->params[LISTENER_PARAM_PITCH_SCALE]);
-
-
- }
-
-
-
-
- //add values
-
- volume_attenuation+=weight*attenuation; // plus other stuff i guess
- air_absorption+=weight*absorption;
- air_absorption_hf_cutoff+=weight*hf_attenuation_cutoff;
- panning+=vpanning*weight;
- pitch_scale+=pscale*weight;
-
- }
-
- RoomReverb reverb_room=ROOM_REVERB_HALL;
- float reverb_send=0;
-
- /* APPLY ROOM SETTINGS */
-
- {
- pitch_scale*=room->params[ROOM_PARAM_PITCH_SCALE];
- volume_attenuation*=Math::db2linear(room->params[ROOM_PARAM_VOLUME_SCALE_DB]);
- reverb_room=room->reverb;
- reverb_send=Math::lerp(1.0,volume_attenuation,room->params[ROOM_PARAM_ATTENUATION_REVERB_SCALE])*room->params[ROOM_PARAM_REVERB_SEND];
-
- }
-
- /* UPDATE VOICE & STREAM */
-
-
-
- if (voice==VOICE_IS_STREAM) {
-
- //update voice!!
- source->stream_data.panning=panning;
- source->stream_data.volume=volume_attenuation*Math::db2linear(source->params[SOURCE_PARAM_VOLUME_DB]);
- source->stream_data.reverb=reverb_room;
- source->stream_data.reverb_send=reverb_send;
- source->stream_data.filter_gain=air_absorption;
- source->stream_data.filter_cutoff=air_absorption_hf_cutoff;
-
- if (!source->stream) //stream is gone bye bye
- to_disable.push_back(ActiveVoice(source,voice)); // oh well..
-
- } else if (voice>=0) {
- //update stream!!
- Source::Voice &v=source->voices[voice];
-
- if (v.restart)
- AudioServer::get_singleton()->voice_play(v.voice_rid,v.sample_rid);
-
- float volume_scale = Math::db2linear(v.volume_scale)*Math::db2linear(source->params[SOURCE_PARAM_VOLUME_DB]);
- float volume = volume_attenuation*volume_scale;
- reverb_send*=volume_scale;
- int mix_rate = v.sample_mix_rate*v.pitch_scale*pitch_scale*source->params[SOURCE_PARAM_PITCH_SCALE];
-
-
- if (mix_rate<=0) {
-
- ERR_PRINT("Invalid mix rate for voice (0) check for invalid pitch_scale param.");
- to_disable.push_back(ActiveVoice(source,voice)); // oh well..
- continue; //invalid mix rate, disabling
- }
- if (v.restart || v.last_volume!=volume)
- AudioServer::get_singleton()->voice_set_volume(v.voice_rid,volume);
- if (v.restart || v.last_mix_rate!=mix_rate)
- AudioServer::get_singleton()->voice_set_mix_rate(v.voice_rid,mix_rate);
- if (v.restart || v.last_filter_gain!=air_absorption || v.last_filter_cutoff!=air_absorption_hf_cutoff)
- AudioServer::get_singleton()->voice_set_filter(v.voice_rid,AudioServer::FILTER_HIGH_SHELF,air_absorption_hf_cutoff,1.0,air_absorption);
- if (v.restart || v.last_panning!=panning) {
- AudioServer::get_singleton()->voice_set_pan(v.voice_rid,-panning.x,panning.y,0);
- }
- if (v.restart || v.last_reverb_room!=reverb_room || v.last_reverb_send!=reverb_send)
- AudioServer::get_singleton()->voice_set_reverb(v.voice_rid,AudioServer::ReverbRoomType(reverb_room),reverb_send);
-
- v.last_volume=volume;
- v.last_mix_rate=mix_rate;
- v.last_filter_gain=air_absorption;
- v.last_filter_cutoff=air_absorption_hf_cutoff;
- v.last_panning=panning;
- v.last_reverb_room=reverb_room;
- v.last_reverb_send=reverb_send;
- v.restart=false;
- v.active=true;
-
- if (!AudioServer::get_singleton()->voice_is_active(v.voice_rid))
- to_disable.push_back(ActiveVoice(source,voice)); // oh well..
- }
- }
-
- while(to_disable.size()) {
-
- ActiveVoice av = to_disable.front()->get();
- av.source->voices[av.voice].active=false;
- av.source->voices[av.voice].restart=false;
- active_voices.erase(av);
- to_disable.pop_front();
- }
-
-}
-void SpatialSound2DServerSW::finish() {
-
- AudioServer::get_singleton()->free(internal_audio_stream_rid);
- memdelete(internal_audio_stream);
-
- _clean_up_owner(&source_owner,"Source");
- _clean_up_owner(&listener_owner,"Listener");
- _clean_up_owner(&room_owner,"Room");
- _clean_up_owner(&space_owner,"Space");
-
- memdelete_arr(internal_buffer);
-}
-
-SpatialSound2DServerSW::SpatialSound2DServerSW() {
-
-}
diff --git a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h b/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h
deleted file mode 100644
index 619b11f376..0000000000
--- a/servers/spatial_sound_2d/spatial_sound_2d_server_sw.h
+++ /dev/null
@@ -1,265 +0,0 @@
-/*************************************************************************/
-/* spatial_sound_2d_server_sw.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 SPATIAL_SOUND_2D_SERVER_SW_H
-#define SPATIAL_SOUND_2D_SERVER_SW_H
-
-#include "servers/spatial_sound_2d_server.h"
-
-#include "os/thread_safe.h"
-
-
-class SpatialSound2DServerSW : public SpatialSound2DServer {
-
- OBJ_TYPE(SpatialSound2DServerSW,SpatialSound2DServer);
-
- _THREAD_SAFE_CLASS_
-
- enum {
- INTERNAL_BUFFER_SIZE=4096,
- INTERNAL_BUFFER_MAX_CHANNELS=4,
- VOICE_IS_STREAM=-1
-
- };
-
-
- struct InternalAudioStream : public AudioServer::AudioStream {
-
- ::SpatialSound2DServerSW *owner;
- virtual int get_channel_count() const;
- virtual void set_mix_rate(int p_rate); //notify the stream of the mix rate
- virtual bool mix(int32_t *p_buffer,int p_frames);
- virtual void update();
- };
-
- InternalAudioStream *internal_audio_stream;
- RID internal_audio_stream_rid;
- int32_t *internal_buffer;
- int internal_buffer_channels;
-
- bool internal_buffer_mix(int32_t *p_buffer,int p_frames);
-
- struct Room;
-
- struct Space {
-
- RID default_room;
- Set<RID> rooms;
- Set<RID> sources;
- Set<RID> listeners;
-
- //Octree<Room> octree;
- };
-
- mutable RID_Owner<Space> space_owner;
-
- struct Room {
- RID space;
- Matrix32 transform;
- Matrix32 inverse_transform;
- DVector<Point2> bounds;
- RoomReverb reverb;
- float params[ROOM_PARAM_MAX];
- bool override_other_sources;
- //OctreeElementID octree_id;
- int level;
-
- Room();
- };
-
- mutable RID_Owner<Room> room_owner;
-
-
-
- struct Source {
-
- struct Voice {
-
- RID voice_rid;
- RID sample_rid;
- bool active;
- bool restart;
- float pitch_scale;
- float volume_scale;
- int sample_mix_rate;
-
-
- float last_volume;
- float last_filter_gain;
- float last_filter_cutoff;
- Vector2 last_panning;
- int last_mix_rate;
- RoomReverb last_reverb_room;
- float last_reverb_send;
-
- Voice();
- ~Voice();
- };
-
- struct StreamData {
-
-
- Vector2 panning;
- RoomReverb reverb;
- float reverb_send;
- float volume;
- float filter_gain;
- float filter_cutoff;
-
- struct FilterState {
-
- float ha[2];
- float hb[2];
- } filter_state[4];
-
- StreamData() {
-
- reverb_send=0;
- reverb=ROOM_REVERB_HALL;
- volume=1.0;
- filter_gain=1;
- filter_cutoff=5000;
-
- }
- } stream_data;
-
- RID space;
- Matrix32 transform;
- float params[SOURCE_PARAM_MAX];
- AudioServer::AudioStream *stream;
- Vector<Voice> voices;
- int last_voice;
-
- Source();
- };
-
- mutable RID_Owner<Source> source_owner;
-
- struct Listener {
-
- RID space;
- Matrix32 transform;
- float params[LISTENER_PARAM_MAX];
-
- Listener();
- };
-
- mutable RID_Owner<Listener> listener_owner;
-
- struct ActiveVoice {
-
- Source *source;
- int voice;
- bool operator<(const ActiveVoice& p_voice) const { return (voice==p_voice.voice)?(source<p_voice.source):(voice<p_voice.voice); }
- ActiveVoice(Source *p_source=NULL,int p_voice=0) { source=p_source; voice=p_voice; }
- };
-
-// Room *cull_rooms[MAX_CULL_ROOMS];
-
- Set<Source*> streaming_sources;
- Set<ActiveVoice> active_voices;
-
- void _clean_up_owner(RID_OwnerBase *p_owner, const char *p_area);
- void _update_sources();
-
-public:
-
- /* SPACE */
- virtual RID space_create();
-
- /* ROOM */
-
- virtual RID room_create();
- virtual void room_set_space(RID p_room,RID p_space);
- virtual RID room_get_space(RID p_room) const;
-
- virtual void room_set_bounds(RID p_room, const DVector<Point2>& p_bounds);
- virtual DVector<Point2> room_get_bounds(RID p_room) const;
- virtual void room_set_transform(RID p_room, const Matrix32& p_transform);
- virtual Matrix32 room_get_transform(RID p_room) const;
-
-
- virtual void room_set_param(RID p_room, RoomParam p_param, float p_value);
- virtual float room_get_param(RID p_room, RoomParam p_param) const;
-
- virtual void room_set_level(RID p_room, int p_level);
- virtual int room_get_level(RID p_room) const;
-
- virtual void room_set_reverb(RID p_room, RoomReverb p_reverb);
- virtual RoomReverb room_get_reverb(RID p_room) const;
-
- //useful for underwater or rooms with very strange conditions
- virtual void room_set_force_params_to_all_sources(RID p_room, bool p_force);
- virtual bool room_is_forcing_params_to_all_sources(RID p_room) const;
-
- /* SOURCE */
-
- virtual RID source_create(RID p_space);
-
- virtual void source_set_polyphony(RID p_source,int p_voice_count);
- virtual int source_get_polyphony(RID p_source) const;
-
- virtual void source_set_transform(RID p_source, const Matrix32& p_transform);
- virtual Matrix32 source_get_transform(RID p_source) const;
-
- virtual void source_set_param(RID p_source, SourceParam p_param, float p_value);
- virtual float source_get_param(RID p_source, SourceParam p_param) const;
-
- virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream); //null to unset
- virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice=SOURCE_NEXT_VOICE);
- /* VOICES */
- virtual void source_voice_set_pitch_scale(RID p_source, SourceVoiceID p_voice, float p_pitch_scale);
- virtual void source_voice_set_volume_scale_db(RID p_source, SourceVoiceID p_voice, float p_volume);
-
- virtual bool source_is_voice_active(RID p_source, SourceVoiceID p_voice) const;
- virtual void source_stop_voice(RID p_source, SourceVoiceID p_voice);
-
- /* LISTENER */
-
- virtual RID listener_create();
- virtual void listener_set_space(RID p_listener, RID p_space);
-
- virtual void listener_set_transform(RID p_listener, const Matrix32& p_transform);
- virtual Matrix32 listener_get_transform(RID p_listener) const;
-
- virtual void listener_set_param(RID p_listener, ListenerParam p_param, float p_value);
- virtual float listener_get_param(RID p_listener, ListenerParam p_param) const;
-
-
- /* MISC */
-
- virtual void free(RID p_id);
-
- virtual void init();
- virtual void update(float p_delta);
- virtual void finish();
-
- SpatialSound2DServerSW();
-};
-
-#endif // SPATIAL_SOUND_2D_SERVER_SW_H
diff --git a/servers/spatial_sound_2d_server.h b/servers/spatial_sound_2d_server.h
deleted file mode 100644
index 2d388feb49..0000000000
--- a/servers/spatial_sound_2d_server.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*************************************************************************/
-/* spatial_sound_2d_server.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 SPATIAL_SOUND_2D_SERVER_H
-#define SPATIAL_SOUND_2D_SERVER_H
-
-#include "object.h"
-#include "bsp_tree.h"
-#include "servers/audio_server.h"
-
-class SpatialSound2DServer : public Object {
-
- OBJ_TYPE(SpatialSound2DServer,Object);
- static SpatialSound2DServer *singleton;
-public:
-
-
- enum {
- SOURCE_INVALID_VOICE=-1,
- SOURCE_NEXT_VOICE=-2,
- };
-
- typedef int SourceVoiceID;
-
- /* SPACE */
- virtual RID space_create()=0;
-
- /* ROOM */
-
- virtual RID room_create()=0;
- virtual void room_set_space(RID p_room,RID p_space)=0;
- virtual RID room_get_space(RID p_room) const=0;
-
-
- virtual void room_set_bounds(RID p_room, const DVector<Point2>& p_bounds)=0;
- virtual DVector<Point2> room_get_bounds(RID p_room) const=0;
- virtual void room_set_transform(RID p_room, const Matrix32& p_transform)=0;
- virtual Matrix32 room_get_transform(RID p_room) const=0;
-
- enum RoomParam {
- ROOM_PARAM_PITCH_SCALE,
- ROOM_PARAM_VOLUME_SCALE_DB,
- ROOM_PARAM_REVERB_SEND,
- ROOM_PARAM_CHORUS_SEND,
- ROOM_PARAM_ATTENUATION_SCALE,
- ROOM_PARAM_ATTENUATION_HF_CUTOFF,
- ROOM_PARAM_ATTENUATION_HF_FLOOR_DB,
- ROOM_PARAM_ATTENUATION_HF_RATIO_EXP,
- ROOM_PARAM_ATTENUATION_REVERB_SCALE,
- ROOM_PARAM_MAX
- };
-
- virtual void room_set_param(RID p_room, RoomParam p_param, float p_value)=0;
- virtual float room_get_param(RID p_room, RoomParam p_param) const=0;
-
- enum RoomReverb {
- ROOM_REVERB_SMALL,
- ROOM_REVERB_MEDIUM,
- ROOM_REVERB_LARGE,
- ROOM_REVERB_HALL
- };
-
- virtual void room_set_reverb(RID p_room, RoomReverb p_reverb)=0;
- virtual RoomReverb room_get_reverb(RID p_room) const=0;
-
- virtual void room_set_level(RID p_room, int p_level)=0;
- virtual int room_get_level(RID p_room) const=0;
-
- //useful for underwater or rooms with very strange conditions
- virtual void room_set_force_params_to_all_sources(RID p_room, bool p_force)=0;
- virtual bool room_is_forcing_params_to_all_sources(RID p_room) const=0;
-
- /* SOURCE */
-
- virtual RID source_create(RID p_space)=0;
-
- virtual void source_set_transform(RID p_source, const Matrix32& p_transform)=0;
- virtual Matrix32 source_get_transform(RID p_source) const=0;
-
- virtual void source_set_polyphony(RID p_source,int p_voice_count)=0;
- virtual int source_get_polyphony(RID p_source) const=0;
-
- enum SourceParam {
-
- SOURCE_PARAM_VOLUME_DB,
- SOURCE_PARAM_PITCH_SCALE,
- SOURCE_PARAM_ATTENUATION_MIN_DISTANCE,
- SOURCE_PARAM_ATTENUATION_MAX_DISTANCE,
- SOURCE_PARAM_ATTENUATION_DISTANCE_EXP,
- SOURCE_PARAM_MAX
- };
-
- virtual void source_set_param(RID p_source, SourceParam p_param, float p_value)=0;
- virtual float source_get_param(RID p_source, SourceParam p_param) const=0;
-
- virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream)=0; //null to unset
- virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice=SOURCE_NEXT_VOICE)=0;
- //voices
- virtual void source_voice_set_pitch_scale(RID p_source,SourceVoiceID p_voice, float p_pitch_scale)=0;
- virtual void source_voice_set_volume_scale_db(RID p_source,SourceVoiceID p_voice, float p_volume_db)=0;
-
- virtual bool source_is_voice_active(RID p_source,SourceVoiceID p_voice) const=0;
- virtual void source_stop_voice(RID p_source,SourceVoiceID p_voice)=0;
-
- /* LISTENER */
-
- enum ListenerParam {
-
- LISTENER_PARAM_VOLUME_SCALE_DB,
- LISTENER_PARAM_PITCH_SCALE,
- LISTENER_PARAM_ATTENUATION_SCALE,
- LISTENER_PARAM_PAN_RANGE,
- LISTENER_PARAM_MAX
- };
-
- virtual RID listener_create()=0;
- virtual void listener_set_space(RID p_listener, RID p_space)=0;
-
- virtual void listener_set_transform(RID p_listener, const Matrix32& p_transform)=0;
- virtual Matrix32 listener_get_transform(RID p_listener) const=0;
-
- virtual void listener_set_param(RID p_listener, ListenerParam p_param, float p_value)=0;
- virtual float listener_get_param(RID p_listener, ListenerParam p_param) const=0;
-
- /* MISC */
-
- virtual void free(RID p_id)=0;
-
- virtual void init()=0;
- virtual void update(float p_delta)=0;
- virtual void finish()=0;
-
- static SpatialSound2DServer *get_singleton();
-
- SpatialSound2DServer();
-
-};
-
-#endif // SPATIAL_SOUND_2D_SERVER_H
diff --git a/servers/spatial_sound_server.h b/servers/spatial_sound_server.h
deleted file mode 100644
index 5037ee6e2f..0000000000
--- a/servers/spatial_sound_server.h
+++ /dev/null
@@ -1,168 +0,0 @@
-/*************************************************************************/
-/* spatial_sound_server.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 SPATIAL_SOUND_SERVER_H
-#define SPATIAL_SOUND_SERVER_H
-
-#include "object.h"
-#include "bsp_tree.h"
-#include "servers/audio_server.h"
-
-class SpatialSoundServer : public Object {
- OBJ_TYPE(SpatialSoundServer,Object);
-
- static SpatialSoundServer *singleton;
-public:
-
-
- enum {
- SOURCE_INVALID_VOICE=-1,
- SOURCE_NEXT_VOICE=-2,
- };
-
- typedef int SourceVoiceID;
-
- /* SPACE */
- virtual RID space_create()=0;
-
- /* ROOM */
-
- virtual RID room_create()=0;
- virtual void room_set_space(RID p_room,RID p_space)=0;
- virtual RID room_get_space(RID p_room) const=0;
-
-
- virtual void room_set_bounds(RID p_room, const BSP_Tree& p_bounds)=0;
- virtual BSP_Tree room_get_bounds(RID p_room) const=0;
- virtual void room_set_transform(RID p_room, const Transform& p_transform)=0;
- virtual Transform room_get_transform(RID p_room) const=0;
-
- enum RoomParam {
- ROOM_PARAM_SPEED_OF_SOUND_SCALE,
- ROOM_PARAM_DOPPLER_FACTOR,
- ROOM_PARAM_PITCH_SCALE,
- ROOM_PARAM_VOLUME_SCALE_DB,
- ROOM_PARAM_REVERB_SEND,
- ROOM_PARAM_CHORUS_SEND,
- ROOM_PARAM_ATTENUATION_SCALE,
- ROOM_PARAM_ATTENUATION_HF_CUTOFF,
- ROOM_PARAM_ATTENUATION_HF_FLOOR_DB,
- ROOM_PARAM_ATTENUATION_HF_RATIO_EXP,
- ROOM_PARAM_ATTENUATION_REVERB_SCALE,
- ROOM_PARAM_MAX
- };
-
- virtual void room_set_param(RID p_room, RoomParam p_param, float p_value)=0;
- virtual float room_get_param(RID p_room, RoomParam p_param) const=0;
-
- enum RoomReverb {
- ROOM_REVERB_SMALL,
- ROOM_REVERB_MEDIUM,
- ROOM_REVERB_LARGE,
- ROOM_REVERB_HALL
- };
-
- virtual void room_set_reverb(RID p_room, RoomReverb p_reverb)=0;
- virtual RoomReverb room_get_reverb(RID p_room) const=0;
-
- virtual void room_set_level(RID p_room, int p_level)=0;
- virtual int room_get_level(RID p_room) const=0;
-
- //useful for underwater or rooms with very strange conditions
- virtual void room_set_force_params_to_all_sources(RID p_room, bool p_force)=0;
- virtual bool room_is_forcing_params_to_all_sources(RID p_room) const=0;
-
- /* SOURCE */
-
- virtual RID source_create(RID p_space)=0;
-
- virtual void source_set_transform(RID p_source, const Transform& p_transform)=0;
- virtual Transform source_get_transform(RID p_source) const=0;
-
- virtual void source_set_polyphony(RID p_source,int p_voice_count)=0;
- virtual int source_get_polyphony(RID p_source) const=0;
-
- enum SourceParam {
-
- SOURCE_PARAM_VOLUME_DB,
- SOURCE_PARAM_PITCH_SCALE,
- SOURCE_PARAM_ATTENUATION_MIN_DISTANCE,
- SOURCE_PARAM_ATTENUATION_MAX_DISTANCE,
- SOURCE_PARAM_ATTENUATION_DISTANCE_EXP,
- SOURCE_PARAM_EMISSION_CONE_DEGREES,
- SOURCE_PARAM_EMISSION_CONE_ATTENUATION_DB,
- SOURCE_PARAM_MAX
- };
-
- virtual void source_set_param(RID p_source, SourceParam p_param, float p_value)=0;
- virtual float source_get_param(RID p_source, SourceParam p_param) const=0;
-
- virtual void source_set_audio_stream(RID p_source, AudioServer::AudioStream *p_stream)=0; //null to unset
- virtual SourceVoiceID source_play_sample(RID p_source, RID p_sample, int p_mix_rate, int p_voice=SOURCE_NEXT_VOICE)=0;
- //voices
- virtual void source_voice_set_pitch_scale(RID p_source,SourceVoiceID p_voice, float p_pitch_scale)=0;
- virtual void source_voice_set_volume_scale_db(RID p_source,SourceVoiceID p_voice, float p_volume_db)=0;
-
- virtual bool source_is_voice_active(RID p_source,SourceVoiceID p_voice) const=0;
- virtual void source_stop_voice(RID p_source,SourceVoiceID p_voice)=0;
-
- /* LISTENER */
-
- enum ListenerParam {
-
- LISTENER_PARAM_VOLUME_SCALE_DB,
- LISTENER_PARAM_PITCH_SCALE,
- LISTENER_PARAM_ATTENUATION_SCALE,
- LISTENER_PARAM_RECEPTION_CONE_DEGREES,
- LISTENER_PARAM_RECEPTION_CONE_ATTENUATION_DB,
- LISTENER_PARAM_MAX
- };
-
- virtual RID listener_create()=0;
- virtual void listener_set_space(RID p_listener, RID p_space)=0;
-
- virtual void listener_set_transform(RID p_listener, const Transform& p_transform)=0;
- virtual Transform listener_get_transform(RID p_listener) const=0;
-
- virtual void listener_set_param(RID p_listener, ListenerParam p_param, float p_value)=0;
- virtual float listener_get_param(RID p_listener, ListenerParam p_param) const=0;
-
- /* MISC */
-
- virtual void free(RID p_id)=0;
-
- virtual void init()=0;
- virtual void update(float p_delta)=0;
- virtual void finish()=0;
-
- static SpatialSoundServer *get_singleton();
-
- SpatialSoundServer();
-};
-
-#endif // SPATIAL_SOUND_SERVER_H
diff --git a/servers/visual/SCsub b/servers/visual/SCsub
index d31af2c1c4..ccc76e823f 100644
--- a/servers/visual/SCsub
+++ b/servers/visual/SCsub
@@ -1,5 +1,7 @@
+#!/usr/bin/env python
+
Import('env')
-env.add_source_files(env.servers_sources,"*.cpp")
+env.add_source_files(env.servers_sources, "*.cpp")
Export('env')
diff --git a/servers/visual/particle_system_sw.cpp b/servers/visual/particle_system_sw.cpp
deleted file mode 100644
index 07cc6d8a2a..0000000000
--- a/servers/visual/particle_system_sw.cpp
+++ /dev/null
@@ -1,412 +0,0 @@
-/*************************************************************************/
-/* particle_system_sw.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 "particle_system_sw.h"
-#include "sort.h"
-
-
-ParticleSystemSW::ParticleSystemSW() {
-
- amount=8;
- emitting=true;
-
- for (int i=0;i<VS::PARTICLE_VAR_MAX;i++) {
- particle_randomness[i]=0.0;
- }
-
- particle_vars[VS::PARTICLE_LIFETIME]=2.0;//
- particle_vars[VS::PARTICLE_SPREAD]=0.2;//
- particle_vars[VS::PARTICLE_GRAVITY]=9.8;//
- particle_vars[VS::PARTICLE_LINEAR_VELOCITY]=0.2;//
- particle_vars[VS::PARTICLE_ANGULAR_VELOCITY]=0.0;//
- particle_vars[VS::PARTICLE_LINEAR_ACCELERATION]=0.0;//
- particle_vars[VS::PARTICLE_RADIAL_ACCELERATION]=0.0;//
- particle_vars[VS::PARTICLE_TANGENTIAL_ACCELERATION]=1.0;//
- particle_vars[VS::PARTICLE_DAMPING]=0.0;//
- particle_vars[VS::PARTICLE_INITIAL_SIZE]=1.0;
- particle_vars[VS::PARTICLE_FINAL_SIZE]=0.8;
- particle_vars[VS::PARTICLE_HEIGHT]=1;
- particle_vars[VS::PARTICLE_HEIGHT_SPEED_SCALE]=1;
-
- height_from_velocity=false;
- local_coordinates=false;
-
- particle_vars[VS::PARTICLE_INITIAL_ANGLE]=0.0;//
-
- gravity_normal=Vector3(0,-1.0,0);
- //emission_half_extents=Vector3(0.1,0.1,0.1);
- emission_half_extents=Vector3(1,1,1);
- color_phase_count=0;
- color_phases[0].pos=0.0;
- color_phases[0].color=Color(1.0,0.0,0.0);
- visibility_aabb=AABB(Vector3(-64,-64,-64),Vector3(128,128,128));
-
- attractor_count=0;
-
-}
-
-
-ParticleSystemSW::~ParticleSystemSW()
-{
-}
-
-
-#define DEFAULT_SEED 1234567
-
-_FORCE_INLINE_ static float _rand_from_seed(uint32_t *seed) {
-
- uint32_t k;
- uint32_t s = (*seed);
- if (s == 0)
- s = 0x12345987;
- k = s / 127773;
- s = 16807 * (s - k * 127773) - 2836 * k;
- if (s < 0)
- s += 2147483647;
- (*seed) = s;
-
- float v=((float)((*seed) & 0xFFFFF))/(float)0xFFFFF;
- v=v*2.0-1.0;
- return v;
-}
-
-_FORCE_INLINE_ static uint32_t _irand_from_seed(uint32_t *seed) {
-
- uint32_t k;
- uint32_t s = (*seed);
- if (s == 0)
- s = 0x12345987;
- k = s / 127773;
- s = 16807 * (s - k * 127773) - 2836 * k;
- if (s < 0)
- s += 2147483647;
- (*seed) = s;
-
- return s;
-}
-
-void ParticleSystemProcessSW::process(const ParticleSystemSW *p_system,const Transform& p_transform,float p_time) {
-
- valid=false;
- if (p_system->amount<=0) {
- ERR_EXPLAIN("Invalid amount of particles: "+itos(p_system->amount));
- ERR_FAIL_COND(p_system->amount<=0);
- }
- if (p_system->attractor_count<0 || p_system->attractor_count>VS::MAX_PARTICLE_ATTRACTORS) {
- ERR_EXPLAIN("Invalid amount of particle attractors.");
- ERR_FAIL_COND(p_system->attractor_count<0 || p_system->attractor_count>VS::MAX_PARTICLE_ATTRACTORS);
- }
- float lifetime = p_system->particle_vars[VS::PARTICLE_LIFETIME];
- if (lifetime<CMP_EPSILON) {
- ERR_EXPLAIN("Particle system lifetime too small.");
- ERR_FAIL_COND(lifetime<CMP_EPSILON);
- }
- valid=true;
- int particle_count=MIN(p_system->amount,ParticleSystemSW::MAX_PARTICLES);;
-
-
- int emission_point_count = p_system->emission_points.size();
- DVector<Vector3>::Read r;
- if (emission_point_count)
- r=p_system->emission_points.read();
-
- if (particle_count!=particle_data.size()) {
-
- //clear the whole system if particle amount changed
- particle_data.clear();
- particle_data.resize(p_system->amount);
- particle_system_time=0;
- }
-
- float next_time = particle_system_time+p_time;
-
- if (next_time > lifetime)
- next_time=Math::fmod(next_time,lifetime);
-
-
- ParticleData *pdata=&particle_data[0];
- Vector3 attractor_positions[VS::MAX_PARTICLE_ATTRACTORS];
-
- for(int i=0;i<p_system->attractor_count;i++) {
-
- attractor_positions[i]=p_transform.xform(p_system->attractors[i].pos);
- }
-
-
- for(int i=0;i<particle_count;i++) {
-
- ParticleData &p=pdata[i];
-
- float restart_time = (i * lifetime / p_system->amount);
-
- bool restart=false;
-
- if ( next_time < particle_system_time ) {
-
- if (restart_time > particle_system_time || restart_time < next_time )
- restart=true;
-
- } else if (restart_time > particle_system_time && restart_time < next_time ) {
- restart=true;
- }
-
- if (restart) {
-
-
- if (p_system->emitting) {
- if (emission_point_count==0) { //use AABB
- if (p_system->local_coordinates)
- p.pos = p_system->emission_half_extents * Vector3( _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed) );
- else
- p.pos = p_transform.xform( p_system->emission_half_extents * Vector3( _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed), _rand_from_seed(&rand_seed) ) );
- } else {
- //use preset positions
- if (p_system->local_coordinates)
- p.pos = r[_irand_from_seed(&rand_seed)%emission_point_count];
- else
- p.pos = p_transform.xform( r[_irand_from_seed(&rand_seed)%emission_point_count] );
- }
-
-
- float angle1 = _rand_from_seed(&rand_seed)*p_system->particle_vars[VS::PARTICLE_SPREAD]*Math_PI;
- float angle2 = _rand_from_seed(&rand_seed)*20.0*Math_PI; // make it more random like
-
- Vector3 rot_xz=Vector3( Math::sin(angle1), 0.0, Math::cos(angle1) );
- Vector3 rot = Vector3( Math::cos(angle2)*rot_xz.x,Math::sin(angle2)*rot_xz.x, rot_xz.z);
-
- p.vel=(rot*p_system->particle_vars[VS::PARTICLE_LINEAR_VELOCITY]+rot*p_system->particle_randomness[VS::PARTICLE_LINEAR_VELOCITY]*_rand_from_seed(&rand_seed));
- if (!p_system->local_coordinates)
- p.vel=p_transform.basis.xform( p.vel );
-
- p.vel+=p_system->emission_base_velocity;
-
- p.rot=p_system->particle_vars[VS::PARTICLE_INITIAL_ANGLE]+p_system->particle_randomness[VS::PARTICLE_INITIAL_ANGLE]*_rand_from_seed(&rand_seed);
- p.active=true;
- for(int r=0;r<PARTICLE_RANDOM_NUMBERS;r++)
- p.random[r]=_rand_from_seed(&rand_seed);
-
- } else {
-
- p.pos=Vector3();
- p.rot=0;
- p.vel=Vector3();
- p.active=false;
- }
-
- } else {
-
- if (!p.active)
- continue;
-
- Vector3 force;
- //apply gravity
- force=p_system->gravity_normal * (p_system->particle_vars[VS::PARTICLE_GRAVITY]+(p_system->particle_randomness[VS::PARTICLE_GRAVITY]*p.random[0]));
- //apply linear acceleration
- force+=p.vel.normalized() * (p_system->particle_vars[VS::PARTICLE_LINEAR_ACCELERATION]+p_system->particle_randomness[VS::PARTICLE_LINEAR_ACCELERATION]*p.random[1]);
- //apply radial acceleration
- Vector3 org;
- if (!p_system->local_coordinates)
- org=p_transform.origin;
- force+=(p.pos-org).normalized() * (p_system->particle_vars[VS::PARTICLE_RADIAL_ACCELERATION]+p_system->particle_randomness[VS::PARTICLE_RADIAL_ACCELERATION]*p.random[2]);
- //apply tangential acceleration
- force+=(p.pos-org).cross(p_system->gravity_normal).normalized() * (p_system->particle_vars[VS::PARTICLE_TANGENTIAL_ACCELERATION]+p_system->particle_randomness[VS::PARTICLE_TANGENTIAL_ACCELERATION]*p.random[3]);
- //apply attractor forces
- for(int a=0;a<p_system->attractor_count;a++) {
-
- force+=(p.pos-attractor_positions[a]).normalized() * p_system->attractors[a].force;
- }
-
-
- p.vel+=force * p_time;
- if (p_system->particle_vars[VS::PARTICLE_DAMPING]) {
-
- float v = p.vel.length();
- float damp = p_system->particle_vars[VS::PARTICLE_DAMPING] + p_system->particle_vars[VS::PARTICLE_DAMPING] * p_system->particle_randomness[VS::PARTICLE_DAMPING];
- v -= damp * p_time;
- if (v<0) {
- p.vel=Vector3();
- } else {
- p.vel=p.vel.normalized() * v;
- }
-
- }
- p.rot+=(p_system->particle_vars[VS::PARTICLE_ANGULAR_VELOCITY]+p_system->particle_randomness[VS::PARTICLE_ANGULAR_VELOCITY]*p.random[4]) *p_time;
- p.pos+=p.vel * p_time;
- }
- }
-
- particle_system_time=Math::fmod( particle_system_time+p_time, lifetime );
-
-
-}
-
-ParticleSystemProcessSW::ParticleSystemProcessSW() {
-
- particle_system_time=0;
- rand_seed=1234567;
- valid=false;
-}
-
-
-struct _ParticleSorterSW {
-
-
- _FORCE_INLINE_ bool operator()(const ParticleSystemDrawInfoSW::ParticleDrawInfo *p_a,const ParticleSystemDrawInfoSW::ParticleDrawInfo *p_b) const {
-
- return p_a->d > p_b->d; // draw from further away to closest
- }
-};
-
-void ParticleSystemDrawInfoSW::prepare(const ParticleSystemSW *p_system,const ParticleSystemProcessSW *p_process,const Transform& p_system_transform,const Transform& p_camera_transform) {
-
- ERR_FAIL_COND(p_process->particle_data.size() != p_system->amount);
- ERR_FAIL_COND(p_system->amount<=0 || p_system->amount>=ParticleSystemSW::MAX_PARTICLES);
-
- const ParticleSystemProcessSW::ParticleData *pdata=&p_process->particle_data[0];
- float time_pos=p_process->particle_system_time/p_system->particle_vars[VS::PARTICLE_LIFETIME];
-
- ParticleSystemSW::ColorPhase cphase[VS::MAX_PARTICLE_COLOR_PHASES];
-
- float last=-1;
- int col_count=0;
-
- for(int i=0;i<p_system->color_phase_count;i++) {
-
- if (p_system->color_phases[i].pos<=last)
- break;
- cphase[i]=p_system->color_phases[i];
- col_count++;
- }
-
-
-
-
-
- Vector3 camera_z_axis = p_camera_transform.basis.get_axis(2);
-
- for(int i=0;i<p_system->amount;i++) {
-
- ParticleDrawInfo &pdi=draw_info[i];
- pdi.data=&pdata[i];
- pdi.transform.origin=pdi.data->pos;
- if (p_system->local_coordinates)
- pdi.transform.origin=p_system_transform.xform(pdi.transform.origin);
-
- pdi.d=-camera_z_axis.dot(pdi.transform.origin);
-
- // adjust particle size, color and rotation
-
- float time = ((float)i / p_system->amount);
- if (time<time_pos)
- time=time_pos-time;
- else
- time=(1.0-time)+time_pos;
-
- Vector3 up=p_camera_transform.basis.get_axis(1); // up determines the rotation
- float up_scale=1.0;
-
- if (p_system->height_from_velocity) {
-
- Vector3 veld = pdi.data->vel;
- Vector3 cam_z = camera_z_axis.normalized();
- float vc = Math::abs(veld.normalized().dot(cam_z));
-
- if (vc<(1.0-CMP_EPSILON)) {
- up = Plane(cam_z,0).project(veld).normalized();
- float h = p_system->particle_vars[VS::PARTICLE_HEIGHT]+p_system->particle_randomness[VS::PARTICLE_HEIGHT]*pdi.data->random[7];
- float velh = veld.length();
- h+=velh*(p_system->particle_vars[VS::PARTICLE_HEIGHT_SPEED_SCALE]+p_system->particle_randomness[VS::PARTICLE_HEIGHT_SPEED_SCALE]*pdi.data->random[7]);
-
-
- up_scale=Math::lerp(1.0,h,(1.0-vc));
- }
-
- } else if (pdi.data->rot) {
-
- up.rotate(camera_z_axis,pdi.data->rot);
- }
-
- {
- // matrix
- Vector3 v_z = (p_camera_transform.origin-pdi.transform.origin).normalized();
-// Vector3 v_z = (p_camera_transform.origin-pdi.data->pos).normalized();
- Vector3 v_y = up;
- Vector3 v_x = v_y.cross(v_z);
- v_y = v_z.cross(v_x);
- v_x.normalize();
- v_y.normalize();
-
-
- float initial_scale, final_scale;
- initial_scale = p_system->particle_vars[VS::PARTICLE_INITIAL_SIZE]+p_system->particle_randomness[VS::PARTICLE_INITIAL_SIZE]*pdi.data->random[5];
- final_scale = p_system->particle_vars[VS::PARTICLE_FINAL_SIZE]+p_system->particle_randomness[VS::PARTICLE_FINAL_SIZE]*pdi.data->random[6];
- float scale = initial_scale + time * (final_scale - initial_scale);
-
- pdi.transform.basis.set_axis(0,v_x * scale);
- pdi.transform.basis.set_axis(1,v_y * scale * up_scale);
- pdi.transform.basis.set_axis(2,v_z * scale);
- }
-
-
-
- int cpos=0;
-
- while(cpos<col_count) {
-
- if (cphase[cpos].pos > time)
- break;
- cpos++;
- }
-
- cpos--;
-
-
- if (cpos==-1)
- pdi.color=Color(1,1,1,1);
- else {
- if (cpos==col_count-1)
- pdi.color=cphase[cpos].color;
- else {
- float diff = (cphase[cpos+1].pos-cphase[cpos].pos);
- if (diff>0)
- pdi.color=cphase[cpos].color.linear_interpolate(cphase[cpos+1].color, (time - cphase[cpos].pos) / diff );
- else
- pdi.color=cphase[cpos+1].color;
- }
- }
-
-
- draw_info_order[i]=&pdi;
-
- }
-
-
- SortArray<ParticleDrawInfo*,_ParticleSorterSW> particle_sort;
- particle_sort.sort(&draw_info_order[0],p_system->amount);
-
-}
diff --git a/servers/visual/particle_system_sw.h b/servers/visual/particle_system_sw.h
deleted file mode 100644
index 4edcecaaa9..0000000000
--- a/servers/visual/particle_system_sw.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*************************************************************************/
-/* particle_system_sw.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 PARTICLE_SYSTEM_SW_H
-#define PARTICLE_SYSTEM_SW_H
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-
-#include "servers/visual_server.h"
-
-struct ParticleSystemSW {
- enum {
-
- MAX_PARTICLES=1024
- };
-
- float particle_vars[VS::PARTICLE_VAR_MAX];
- float particle_randomness[VS::PARTICLE_VAR_MAX];
-
- Vector3 emission_half_extents;
- DVector<Vector3> emission_points;
- Vector3 gravity_normal;
- Vector3 emission_base_velocity;
- int amount;
- bool emitting;
- bool height_from_velocity;
- AABB visibility_aabb;
- bool sort;
- bool local_coordinates;
-
- struct ColorPhase {
-
- float pos;
- Color color;
- ColorPhase() { pos=1.0; color=Color(0.0,0.0,1.0,1.0); }
- };
-
- int color_phase_count;
- ColorPhase color_phases[VS::MAX_PARTICLE_COLOR_PHASES];
-
-
- struct Attractor {
-
- Vector3 pos;
- float force;
- };
-
- int attractor_count;
- Attractor attractors[VS::MAX_PARTICLE_ATTRACTORS];
-
-
- ParticleSystemSW();
- ~ParticleSystemSW();
-
-};
-
-
-struct ParticleSystemProcessSW {
-
- enum {
- PARTICLE_RANDOM_NUMBERS = 8,
- };
-
- struct ParticleData {
-
- Vector3 pos;
- Vector3 vel;
- float rot;
- bool active;
- float random[PARTICLE_RANDOM_NUMBERS];
-
- ParticleData() { active=0; rot=0; }
- };
-
-
- bool valid;
- float particle_system_time;
- uint32_t rand_seed;
- Vector<ParticleData> particle_data;
-
- void process(const ParticleSystemSW *p_system,const Transform& p_transform,float p_time);
-
- ParticleSystemProcessSW();
-};
-
-struct ParticleSystemDrawInfoSW {
-
- struct ParticleDrawInfo {
-
- const ParticleSystemProcessSW::ParticleData *data;
- float d;
- Transform transform;
- Color color;
-
- };
-
- ParticleDrawInfo draw_info[ParticleSystemSW::MAX_PARTICLES];
- ParticleDrawInfo *draw_info_order[ParticleSystemSW::MAX_PARTICLES];
-
- void prepare(const ParticleSystemSW *p_system,const ParticleSystemProcessSW *p_process,const Transform& p_system_transform,const Transform& p_camera_transform);
-
-};
-
-#endif
diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp
index 32f5b80e55..ba85f92e37 100644
--- a/servers/visual/rasterizer.cpp
+++ b/servers/visual/rasterizer.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -30,6 +30,23 @@
#include "print_string.h"
#include "os/os.h"
+
+Rasterizer* (*Rasterizer::_create_func)()=NULL;
+
+Rasterizer *Rasterizer::create() {
+
+ return _create_func();
+}
+
+RasterizerStorage*RasterizerStorage::base_signleton=NULL;
+
+RasterizerStorage::RasterizerStorage() {
+
+ base_signleton=this;
+}
+
+#if 0
+
RID Rasterizer::create_default_material() {
return material_create();
@@ -38,10 +55,10 @@ RID Rasterizer::create_default_material() {
/* Fixed MAterial SHADER API */
-RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) {
+RID Rasterizer::_create_shader(const FixedSpatialMaterialShaderKey& p_key) {
ERR_FAIL_COND_V(!p_key.valid,RID());
- Map<FixedMaterialShaderKey,FixedMaterialShader>::Element *E=fixed_material_shaders.find(p_key);
+ Map<FixedSpatialMaterialShaderKey,FixedSpatialMaterialShader>::Element *E=fixed_material_shaders.find(p_key);
if (E) {
E->get().refcount++;
@@ -50,7 +67,7 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) {
uint64_t t = OS::get_singleton()->get_ticks_usec();
- FixedMaterialShader fms;
+ FixedSpatialMaterialShader fms;
fms.refcount=1;
fms.shader=shader_create();
@@ -239,7 +256,7 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) {
vcode+="uniform float "+_fixed_material_point_size_name+";\n";
vcode+="POINT_SIZE="+_fixed_material_point_size_name+";\n";
-// vcode+="POINT_SIZE=10.0;\n";
+ //vcode+="POINT_SIZE=10.0;\n";
}
String lcode;
@@ -290,21 +307,18 @@ RID Rasterizer::_create_shader(const FixedMaterialShaderKey& p_key) {
//print_line("**VERTEX SHADER GENERATED code: \n"+vcode);
- double tf = (OS::get_singleton()->get_ticks_usec()-t)/1000.0;
-// print_line("generate: "+rtos(tf));
-
shader_set_code(fms.shader,vcode,code,lcode,0,0);
fixed_material_shaders[p_key]=fms;
return fms.shader;
}
-void Rasterizer::_free_shader(const FixedMaterialShaderKey& p_key) {
+void Rasterizer::_free_shader(const FixedSpatialMaterialShaderKey& p_key) {
if (p_key.valid==0)
return; //not a valid key
- Map<FixedMaterialShaderKey,FixedMaterialShader>::Element *E=fixed_material_shaders.find(p_key);
+ Map<FixedSpatialMaterialShaderKey,FixedSpatialMaterialShader>::Element *E=fixed_material_shaders.find(p_key);
ERR_FAIL_COND(!E);
E->get().refcount--;
@@ -316,12 +330,12 @@ void Rasterizer::_free_shader(const FixedMaterialShaderKey& p_key) {
}
-void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags p_flag, bool p_enabled) {
+void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag, bool p_enabled) {
- Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND(!E);
- FixedMaterial &fm=*E->get();
+ FixedSpatialMaterial &fm=*E->get();
switch(p_flag) {
@@ -337,11 +351,11 @@ void Rasterizer::fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags
}
-bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags p_flag) const{
+bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag) const{
- const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND_V(!E,false);
- const FixedMaterial &fm=*E->get();
+ const FixedSpatialMaterial &fm=*E->get();
switch(p_flag) {
case VS::FIXED_MATERIAL_FLAG_USE_ALPHA: return fm.use_alpha;; break;
@@ -360,8 +374,8 @@ bool Rasterizer::fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags
RID Rasterizer::fixed_material_create() {
RID mat = material_create();
- fixed_materials[mat]=memnew( FixedMaterial() );
- FixedMaterial &fm=*fixed_materials[mat];
+ fixed_materials[mat]=memnew( FixedSpatialMaterial() );
+ FixedSpatialMaterial &fm=*fixed_materials[mat];
fm.self=mat;
fm.get_key();
material_set_flag(mat,VS::MATERIAL_FLAG_COLOR_ARRAY_SRGB,true);
@@ -377,11 +391,11 @@ RID Rasterizer::fixed_material_create() {
-void Rasterizer::fixed_material_set_parameter(RID p_material, VS::FixedMaterialParam p_parameter, const Variant& p_value){
+void Rasterizer::fixed_material_set_parameter(RID p_material, VS::FixedSpatialMaterialParam p_parameter, const Variant& p_value){
- Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND(!E);
- FixedMaterial &fm=*E->get();
+ FixedSpatialMaterial &fm=*E->get();
RID material=E->key();
ERR_FAIL_INDEX(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX);
@@ -404,24 +418,24 @@ void Rasterizer::fixed_material_set_parameter(RID p_material, VS::FixedMaterialP
}
-Variant Rasterizer::fixed_material_get_parameter(RID p_material,VS::FixedMaterialParam p_parameter) const{
+Variant Rasterizer::fixed_material_get_parameter(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const{
- const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND_V(!E,Variant());
- const FixedMaterial &fm=*E->get();
+ const FixedSpatialMaterial &fm=*E->get();
ERR_FAIL_INDEX_V(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX,Variant());
return fm.param[p_parameter];
}
-void Rasterizer::fixed_material_set_texture(RID p_material,VS::FixedMaterialParam p_parameter, RID p_texture){
+void Rasterizer::fixed_material_set_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter, RID p_texture){
- Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
if (!E) {
print_line("Not found: "+itos(p_material.get_id()));
}
ERR_FAIL_COND(!E);
- FixedMaterial &fm=*E->get();
+ FixedSpatialMaterial &fm=*E->get();
ERR_FAIL_INDEX(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX);
@@ -436,22 +450,22 @@ void Rasterizer::fixed_material_set_texture(RID p_material,VS::FixedMaterialPara
}
-RID Rasterizer::fixed_material_get_texture(RID p_material,VS::FixedMaterialParam p_parameter) const{
+RID Rasterizer::fixed_material_get_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const{
- const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND_V(!E,RID());
- const FixedMaterial &fm=*E->get();
+ const FixedSpatialMaterial &fm=*E->get();
ERR_FAIL_INDEX_V(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX,RID());
return fm.texture[p_parameter];
}
-void Rasterizer::fixed_material_set_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter, VS::FixedMaterialTexCoordMode p_mode) {
+void Rasterizer::fixed_material_set_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter, VS::FixedSpatialMaterialTexCoordMode p_mode) {
- Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND(!E);
- FixedMaterial &fm=*E->get();
+ FixedSpatialMaterial &fm=*E->get();
ERR_FAIL_INDEX(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX);
fm.get_key();
@@ -463,11 +477,11 @@ void Rasterizer::fixed_material_set_texcoord_mode(RID p_material,VS::FixedMateri
}
-VS::FixedMaterialTexCoordMode Rasterizer::fixed_material_get_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter) const {
+VS::FixedSpatialMaterialTexCoordMode Rasterizer::fixed_material_get_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const {
- const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND_V(!E,VS::FIXED_MATERIAL_TEXCOORD_UV);
- const FixedMaterial &fm=*E->get();
+ const FixedSpatialMaterial &fm=*E->get();
ERR_FAIL_INDEX_V(p_parameter,VS::FIXED_MATERIAL_PARAM_MAX,VS::FIXED_MATERIAL_TEXCOORD_UV);
return fm.texture_tc[p_parameter];
@@ -475,9 +489,9 @@ VS::FixedMaterialTexCoordMode Rasterizer::fixed_material_get_texcoord_mode(RID p
void Rasterizer::fixed_material_set_uv_transform(RID p_material,const Transform& p_transform) {
- Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND(!E);
- FixedMaterial &fm=*E->get();
+ FixedSpatialMaterial &fm=*E->get();
RID material=E->key();
VS::get_singleton()->material_set_param(material,_fixed_material_uv_xform_name,p_transform);
@@ -490,18 +504,18 @@ void Rasterizer::fixed_material_set_uv_transform(RID p_material,const Transform&
Transform Rasterizer::fixed_material_get_uv_transform(RID p_material) const {
- const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND_V(!E,Transform());
- const FixedMaterial &fm=*E->get();
+ const FixedSpatialMaterial &fm=*E->get();
return fm.uv_xform;
}
-void Rasterizer::fixed_material_set_light_shader(RID p_material,VS::FixedMaterialLightShader p_shader) {
+void Rasterizer::fixed_material_set_light_shader(RID p_material,VS::FixedSpatialMaterialLightShader p_shader) {
- Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND(!E);
- FixedMaterial &fm=*E->get();
+ FixedSpatialMaterial &fm=*E->get();
fm.light_shader=p_shader;
@@ -510,20 +524,20 @@ void Rasterizer::fixed_material_set_light_shader(RID p_material,VS::FixedMateria
}
-VS::FixedMaterialLightShader Rasterizer::fixed_material_get_light_shader(RID p_material) const {
+VS::FixedSpatialMaterialLightShader Rasterizer::fixed_material_get_light_shader(RID p_material) const {
- const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND_V(!E,VS::FIXED_MATERIAL_LIGHT_SHADER_LAMBERT);
- const FixedMaterial &fm=*E->get();
+ const FixedSpatialMaterial &fm=*E->get();
return fm.light_shader;
}
void Rasterizer::fixed_material_set_point_size(RID p_material,float p_size) {
- Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND(!E);
- FixedMaterial &fm=*E->get();
+ FixedSpatialMaterial &fm=*E->get();
RID material=E->key();
VS::get_singleton()->material_set_param(material,_fixed_material_point_size_name,p_size);
@@ -535,9 +549,9 @@ void Rasterizer::fixed_material_set_point_size(RID p_material,float p_size) {
float Rasterizer::fixed_material_get_point_size(RID p_material) const{
- const Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ const Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
ERR_FAIL_COND_V(!E,1.0);
- const FixedMaterial &fm=*E->get();
+ const FixedSpatialMaterial &fm=*E->get();
return fm.point_size;
@@ -548,9 +562,9 @@ void Rasterizer::_update_fixed_materials() {
while(fixed_material_dirty_list.first()) {
- FixedMaterial &fm=*fixed_material_dirty_list.first()->self();
+ FixedSpatialMaterial &fm=*fixed_material_dirty_list.first()->self();
- FixedMaterialShaderKey new_key = fm.get_key();
+ FixedSpatialMaterialShaderKey new_key = fm.get_key();
if (new_key.key!=fm.current_key.key) {
_free_shader(fm.current_key);
@@ -580,7 +594,7 @@ void Rasterizer::_update_fixed_materials() {
void Rasterizer::_free_fixed_material(const RID& p_material) {
- Map<RID,FixedMaterial*>::Element *E = fixed_materials.find(p_material);
+ Map<RID,FixedSpatialMaterial*>::Element *E = fixed_materials.find(p_material);
if (E) {
@@ -623,7 +637,7 @@ Rasterizer::Rasterizer() {
draw_viewport_func=NULL;
- ERR_FAIL_COND( sizeof(FixedMaterialShaderKey)!=4);
+ ERR_FAIL_COND( sizeof(FixedSpatialMaterialShaderKey)!=4);
}
@@ -639,3 +653,5 @@ RID Rasterizer::create_overdraw_debug_material() {
return mat;
}
+
+#endif
diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h
index 8cc567072f..dd22986865 100644
--- a/servers/visual/rasterizer.h
+++ b/servers/visual/rasterizer.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -29,6 +29,932 @@
#ifndef RASTERIZER_H
#define RASTERIZER_H
+
+#include "servers/visual_server.h"
+#include "camera_matrix.h"
+
+#include "self_list.h"
+
+
+class RasterizerScene {
+public:
+
+ /* SHADOW ATLAS API */
+
+ virtual RID shadow_atlas_create()=0;
+ virtual void shadow_atlas_set_size(RID p_atlas,int p_size)=0;
+ virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas,int p_quadrant,int p_subdivision)=0;
+ virtual bool shadow_atlas_update_light(RID p_atlas,RID p_light_intance,float p_coverage,uint64_t p_light_version)=0;
+
+ virtual int get_directional_light_shadow_size(RID p_light_intance)=0;
+ virtual void set_directional_shadow_count(int p_count)=0;
+
+ /* ENVIRONMENT API */
+
+ virtual RID environment_create()=0;
+
+ virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg)=0;
+ virtual void environment_set_skybox(RID p_env,RID p_skybox)=0;
+ virtual void environment_set_skybox_scale(RID p_env,float p_scale)=0;
+ virtual void environment_set_bg_color(RID p_env,const Color& p_color)=0;
+ virtual void environment_set_bg_energy(RID p_env,float p_energy)=0;
+ virtual void environment_set_canvas_max_layer(RID p_env,int p_max_layer)=0;
+ virtual void environment_set_ambient_light(RID p_env,const Color& p_color,float p_energy=1.0,float p_skybox_contribution=0.0)=0;
+
+ virtual void environment_set_dof_blur_near(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,VS::EnvironmentDOFBlurQuality p_quality)=0;
+ virtual void environment_set_dof_blur_far(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,VS::EnvironmentDOFBlurQuality p_quality)=0;
+ virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,VS::EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale,bool p_bicubic_upscale)=0;
+ virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture)=0;
+
+ virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness)=0;
+ virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect,const Color &p_color,bool p_blur)=0;
+
+ virtual void environment_set_tonemap(RID p_env,VS::EnvironmentToneMapper p_tone_mapper,float p_exposure,float p_white,bool p_auto_exposure,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_scale)=0;
+
+ virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0;
+
+ struct InstanceBase : RID_Data {
+
+ VS::InstanceType base_type;
+ RID base;
+
+ RID skeleton;
+ RID material_override;
+
+ Transform transform;
+
+ int depth_layer;
+ uint32_t layer_mask;
+
+ //RID sampled_light;
+
+ Vector<RID> materials;
+ Vector<RID> light_instances;
+ Vector<RID> reflection_probe_instances;
+ Vector<RID> gi_probe_instances;
+
+ Vector<float> blend_values;
+
+ //BakedLightData *baked_light;
+ VS::ShadowCastingSetting cast_shadows;
+ //Transform *baked_light_octree_xform;
+ //int baked_lightmap_id;
+
+ bool mirror :8;
+ bool depth_scale :8;
+ bool billboard :8;
+ bool billboard_y :8;
+ bool receive_shadows : 8;
+ bool visible : 8;
+
+ float depth; //used for sorting
+
+ SelfList<InstanceBase> dependency_item;
+ InstanceBase *baked_light; //baked light to use
+ SelfList<InstanceBase> baked_light_item;
+
+ virtual void base_removed()=0;
+ virtual void base_changed()=0;
+ virtual void base_material_changed()=0;
+
+ InstanceBase() : dependency_item(this), baked_light_item(this) {
+
+ base_type=VS::INSTANCE_NONE;
+ cast_shadows=VS::SHADOW_CASTING_SETTING_ON;
+ receive_shadows=true;
+ depth_scale=false;
+ billboard=false;
+ billboard_y=false;
+ visible=true;
+ depth_layer=0;
+ layer_mask=1;
+ baked_light=NULL;
+
+
+ }
+ };
+
+ virtual RID light_instance_create(RID p_light)=0;
+ virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform)=0;
+ virtual void light_instance_set_shadow_transform(RID p_light_instance,const CameraMatrix& p_projection,const Transform& p_transform,float p_far,float p_split,int p_pass)=0;
+ virtual void light_instance_mark_visible(RID p_light_instance)=0;
+
+ virtual RID reflection_atlas_create()=0;
+ virtual void reflection_atlas_set_size(RID p_ref_atlas,int p_size)=0;
+ virtual void reflection_atlas_set_subdivision(RID p_ref_atlas,int p_subdiv)=0;
+
+ virtual RID reflection_probe_instance_create(RID p_probe)=0;
+ virtual void reflection_probe_instance_set_transform(RID p_instance,const Transform& p_transform)=0;
+ virtual void reflection_probe_release_atlas_index(RID p_instance)=0;
+ virtual bool reflection_probe_instance_needs_redraw(RID p_instance)=0;
+ virtual bool reflection_probe_instance_has_reflection(RID p_instance)=0;
+ virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas)=0;
+ virtual bool reflection_probe_instance_postprocess_step(RID p_instance)=0;
+
+ virtual RID gi_probe_instance_create()=0;
+ virtual void gi_probe_instance_set_light_data(RID p_probe,RID p_base,RID p_data)=0;
+ virtual void gi_probe_instance_set_transform_to_data(RID p_probe,const Transform& p_xform)=0;
+ virtual void gi_probe_instance_set_bounds(RID p_probe,const Vector3& p_bounds)=0;
+
+ virtual void render_scene(const Transform& p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_ortogonal,InstanceBase** p_cull_result,int p_cull_count,RID* p_light_cull_result,int p_light_cull_count,RID* p_reflection_probe_cull_result,int p_reflection_probe_cull_count,RID p_environment,RID p_shadow_atlas,RID p_reflection_atlas,RID p_reflection_probe,int p_reflection_probe_pass)=0;
+ virtual void render_shadow(RID p_light,RID p_shadow_atlas,int p_pass,InstanceBase** p_cull_result,int p_cull_count)=0;
+
+ virtual void set_scene_pass(uint64_t p_pass)=0;
+
+ virtual bool free(RID p_rid)=0;
+
+ virtual ~RasterizerScene() {}
+};
+
+
+
+
+
+
+
+class RasterizerStorage {
+public:
+ /* TEXTURE API */
+
+ virtual RID texture_create()=0;
+ virtual void texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags=VS::TEXTURE_FLAGS_DEFAULT)=0;
+ virtual void texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT)=0;
+ virtual Image texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT) const=0;
+ virtual void texture_set_flags(RID p_texture,uint32_t p_flags)=0;
+ virtual uint32_t texture_get_flags(RID p_texture) const=0;
+ virtual Image::Format texture_get_format(RID p_texture) const=0;
+ virtual uint32_t texture_get_width(RID p_texture) const=0;
+ virtual uint32_t texture_get_height(RID p_texture) const=0;
+ virtual void texture_set_size_override(RID p_texture,int p_width, int p_height)=0;
+
+ virtual void texture_set_path(RID p_texture,const String& p_path)=0;
+ virtual String texture_get_path(RID p_texture) const=0;
+
+ virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable)=0;
+
+ virtual void texture_debug_usage(List<VS::TextureInfo> *r_info)=0;
+
+ virtual RID texture_create_radiance_cubemap(RID p_source,int p_resolution=-1) const=0;
+
+ virtual void texture_set_detect_3d_callback(RID p_texture,VisualServer::TextureDetectCallback p_callback,void* p_userdata)=0;
+ virtual void texture_set_detect_srgb_callback(RID p_texture,VisualServer::TextureDetectCallback p_callback,void* p_userdata)=0;
+
+ virtual void textures_keep_original(bool p_enable)=0;
+
+ /* SKYBOX API */
+
+ virtual RID skybox_create()=0;
+ virtual void skybox_set_texture(RID p_skybox,RID p_cube_map,int p_radiance_size)=0;
+
+ /* SHADER API */
+
+
+ virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_SPATIAL)=0;
+
+ virtual void shader_set_mode(RID p_shader,VS::ShaderMode p_mode)=0;
+ virtual VS::ShaderMode shader_get_mode(RID p_shader) const=0;
+
+ virtual void shader_set_code(RID p_shader, const String& p_code)=0;
+ virtual String shader_get_code(RID p_shader) const=0;
+ virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const=0;
+
+ virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture)=0;
+ virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const=0;
+
+
+ /* COMMON MATERIAL API */
+
+ virtual RID material_create()=0;
+
+ virtual void material_set_shader(RID p_shader_material, RID p_shader)=0;
+ virtual RID material_get_shader(RID p_shader_material) const=0;
+
+ virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value)=0;
+ virtual Variant material_get_param(RID p_material, const StringName& p_param) const=0;
+
+ virtual void material_set_line_width(RID p_material, float p_width)=0;
+
+ virtual bool material_is_animated(RID p_material)=0;
+ virtual bool material_casts_shadows(RID p_material)=0;
+
+ virtual void material_add_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance)=0;
+ virtual void material_remove_instance_owner(RID p_material, RasterizerScene::InstanceBase *p_instance)=0;
+
+ /* MESH API */
+
+ virtual RID mesh_create()=0;
+
+ virtual void mesh_add_surface(RID p_mesh,uint32_t p_format,VS::PrimitiveType p_primitive,const PoolVector<uint8_t>& p_array,int p_vertex_count,const PoolVector<uint8_t>& p_index_array,int p_index_count,const Rect3& p_aabb,const Vector<PoolVector<uint8_t> >& p_blend_shapes=Vector<PoolVector<uint8_t> >(),const Vector<Rect3>& p_bone_aabbs=Vector<Rect3>())=0;
+
+ virtual void mesh_set_blend_shape_count(RID p_mesh,int p_amount)=0;
+ virtual int mesh_get_blend_shape_count(RID p_mesh) const=0;
+
+
+ virtual void mesh_set_blend_shape_mode(RID p_mesh,VS::BlendShapeMode p_mode)=0;
+ virtual VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const=0;
+
+ virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material)=0;
+ virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const=0;
+
+ virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const=0;
+ virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const=0;
+
+ virtual PoolVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const=0;
+ virtual PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const=0;
+
+
+ virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const=0;
+ virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const=0;
+
+ virtual Rect3 mesh_surface_get_aabb(RID p_mesh, int p_surface) const=0;
+ virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const=0;
+ virtual Vector<Rect3> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const=0;
+
+ virtual void mesh_remove_surface(RID p_mesh,int p_index)=0;
+ virtual int mesh_get_surface_count(RID p_mesh) const=0;
+
+ virtual void mesh_set_custom_aabb(RID p_mesh,const Rect3& p_aabb)=0;
+ virtual Rect3 mesh_get_custom_aabb(RID p_mesh) const=0;
+
+ virtual Rect3 mesh_get_aabb(RID p_mesh, RID p_skeleton) const=0;
+ virtual void mesh_clear(RID p_mesh)=0;
+
+ /* MULTIMESH API */
+
+
+ virtual RID multimesh_create()=0;
+
+ virtual void multimesh_allocate(RID p_multimesh,int p_instances,VS::MultimeshTransformFormat p_transform_format,VS::MultimeshColorFormat p_color_format)=0;
+ virtual int multimesh_get_instance_count(RID p_multimesh) const=0;
+
+ virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh)=0;
+ virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform)=0;
+ virtual void multimesh_instance_set_transform_2d(RID p_multimesh,int p_index,const Transform2D& p_transform)=0;
+ virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color)=0;
+
+ virtual RID multimesh_get_mesh(RID p_multimesh) const=0;
+
+ virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const=0;
+ virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh,int p_index) const=0;
+ virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const=0;
+
+ virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible)=0;
+ virtual int multimesh_get_visible_instances(RID p_multimesh) const=0;
+
+ virtual Rect3 multimesh_get_aabb(RID p_multimesh) const=0;
+
+ /* IMMEDIATE API */
+
+ virtual RID immediate_create()=0;
+ virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID())=0;
+ virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex)=0;
+ virtual void immediate_normal(RID p_immediate,const Vector3& p_normal)=0;
+ virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent)=0;
+ virtual void immediate_color(RID p_immediate,const Color& p_color)=0;
+ virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv)=0;
+ virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv)=0;
+ virtual void immediate_end(RID p_immediate)=0;
+ virtual void immediate_clear(RID p_immediate)=0;
+ virtual void immediate_set_material(RID p_immediate,RID p_material)=0;
+ virtual RID immediate_get_material(RID p_immediate) const=0;
+ virtual Rect3 immediate_get_aabb(RID p_immediate) const=0;
+
+
+ /* SKELETON API */
+
+ virtual RID skeleton_create()=0;
+ virtual void skeleton_allocate(RID p_skeleton,int p_bones,bool p_2d_skeleton=false)=0;
+ virtual int skeleton_get_bone_count(RID p_skeleton) const=0;
+ virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform)=0;
+ virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone) const =0;
+ virtual void skeleton_bone_set_transform_2d(RID p_skeleton,int p_bone, const Transform2D& p_transform)=0;
+ virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone) const=0;
+
+ /* Light API */
+
+ virtual RID light_create(VS::LightType p_type)=0;
+
+ virtual void light_set_color(RID p_light,const Color& p_color)=0;
+ virtual void light_set_param(RID p_light,VS::LightParam p_param,float p_value)=0;
+ virtual void light_set_shadow(RID p_light,bool p_enabled)=0;
+ virtual void light_set_shadow_color(RID p_light,const Color& p_color)=0;
+ virtual void light_set_projector(RID p_light,RID p_texture)=0;
+ virtual void light_set_negative(RID p_light,bool p_enable)=0;
+ virtual void light_set_cull_mask(RID p_light,uint32_t p_mask)=0;
+
+ virtual void light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode)=0;
+ virtual void light_omni_set_shadow_detail(RID p_light,VS::LightOmniShadowDetail p_detail)=0;
+
+ virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode)=0;
+ virtual void light_directional_set_blend_splits(RID p_light,bool p_enable)=0;
+ virtual bool light_directional_get_blend_splits(RID p_light) const=0;
+
+ virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light)=0;
+ virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light)=0;
+
+ virtual bool light_has_shadow(RID p_light) const=0;
+
+ virtual VS::LightType light_get_type(RID p_light) const=0;
+ virtual Rect3 light_get_aabb(RID p_light) const=0;
+ virtual float light_get_param(RID p_light,VS::LightParam p_param)=0;
+ virtual Color light_get_color(RID p_light)=0;
+ virtual uint64_t light_get_version(RID p_light) const=0;
+
+
+ /* PROBE API */
+
+ virtual RID reflection_probe_create()=0;
+
+ virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode)=0;
+ virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity)=0;
+ virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color& p_ambient)=0;
+ virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy)=0;
+ virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib)=0;
+ virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance)=0;
+ virtual void reflection_probe_set_extents(RID p_probe, const Vector3& p_extents)=0;
+ virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3& p_offset)=0;
+ virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable)=0;
+ virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable)=0;
+ virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable)=0;
+ virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers)=0;
+
+ virtual Rect3 reflection_probe_get_aabb(RID p_probe) const=0;
+ virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const=0;
+ virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const=0;
+ virtual Vector3 reflection_probe_get_extents(RID p_probe) const=0;
+ virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const=0;
+ virtual float reflection_probe_get_origin_max_distance(RID p_probe) const=0;
+ virtual bool reflection_probe_renders_shadows(RID p_probe) const=0;
+
+
+ /* ROOM API */
+
+ virtual RID room_create()=0;
+ virtual void room_add_bounds(RID p_room, const PoolVector<Vector2>& p_convex_polygon,float p_height,const Transform& p_transform)=0;
+ virtual void room_clear_bounds(RID p_room)=0;
+
+ /* PORTAL API */
+
+ // portals are only (x/y) points, forming a convex shape, which its clockwise
+ // order points outside. (z is 0)=0;
+
+ virtual RID portal_create()=0;
+ virtual void portal_set_shape(RID p_portal, const Vector<Point2>& p_shape)=0;
+ virtual void portal_set_enabled(RID p_portal, bool p_enabled)=0;
+ virtual void portal_set_disable_distance(RID p_portal, float p_distance)=0;
+ virtual void portal_set_disabled_color(RID p_portal, const Color& p_color)=0;
+
+ virtual void instance_add_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance)=0;
+ virtual void instance_remove_skeleton(RID p_skeleton,RasterizerScene::InstanceBase *p_instance)=0;
+
+ virtual void instance_add_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance)=0;
+ virtual void instance_remove_dependency(RID p_base,RasterizerScene::InstanceBase *p_instance)=0;
+
+ /* GI PROBE API */
+
+ virtual RID gi_probe_create()=0;
+
+ virtual void gi_probe_set_bounds(RID p_probe,const Rect3& p_bounds)=0;
+ virtual Rect3 gi_probe_get_bounds(RID p_probe) const=0;
+
+ virtual void gi_probe_set_cell_size(RID p_probe,float p_range)=0;
+ virtual float gi_probe_get_cell_size(RID p_probe) const=0;
+
+ virtual void gi_probe_set_to_cell_xform(RID p_probe,const Transform& p_xform)=0;
+ virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const=0;
+
+ virtual void gi_probe_set_dynamic_data(RID p_probe,const PoolVector<int>& p_data)=0;
+ virtual PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const=0;
+
+ virtual void gi_probe_set_dynamic_range(RID p_probe,int p_range)=0;
+ virtual int gi_probe_get_dynamic_range(RID p_probe) const=0;
+
+ virtual void gi_probe_set_energy(RID p_probe,float p_range)=0;
+ virtual float gi_probe_get_energy(RID p_probe) const=0;
+
+ virtual void gi_probe_set_bias(RID p_probe,float p_range)=0;
+ virtual float gi_probe_get_bias(RID p_probe) const=0;
+
+ virtual void gi_probe_set_propagation(RID p_probe,float p_range)=0;
+ virtual float gi_probe_get_propagation(RID p_probe) const=0;
+
+ virtual void gi_probe_set_interior(RID p_probe,bool p_enable)=0;
+ virtual bool gi_probe_is_interior(RID p_probe) const=0;
+
+ virtual void gi_probe_set_compress(RID p_probe,bool p_enable)=0;
+ virtual bool gi_probe_is_compressed(RID p_probe) const=0;
+
+ virtual uint32_t gi_probe_get_version(RID p_probe)=0;
+
+ enum GIProbeCompression {
+ GI_PROBE_UNCOMPRESSED,
+ GI_PROBE_S3TC,
+ GI_PROBE_ETC2
+ };
+
+ virtual GIProbeCompression gi_probe_get_dynamic_data_get_preferred_compression() const=0;
+ virtual RID gi_probe_dynamic_data_create(int p_width,int p_height,int p_depth,GIProbeCompression p_compression)=0;
+ virtual void gi_probe_dynamic_data_update(RID p_gi_probe_data,int p_depth_slice,int p_slice_count,int p_mipmap,const void* p_data)=0;
+
+
+ /* PARTICLES */
+
+ virtual RID particles_create()=0;
+
+ virtual void particles_set_emitting(RID p_particles,bool p_emitting)=0;
+ virtual void particles_set_amount(RID p_particles,int p_amount)=0;
+ virtual void particles_set_lifetime(RID p_particles,float p_lifetime)=0;
+ virtual void particles_set_pre_process_time(RID p_particles,float p_time)=0;
+ virtual void particles_set_explosiveness_ratio(RID p_particles,float p_ratio)=0;
+ virtual void particles_set_randomness_ratio(RID p_particles,float p_ratio)=0;
+ virtual void particles_set_custom_aabb(RID p_particles,const Rect3& p_aabb)=0;
+ virtual void particles_set_gravity(RID p_particles,const Vector3& p_gravity)=0;
+ virtual void particles_set_use_local_coordinates(RID p_particles,bool p_enable)=0;
+ virtual void particles_set_process_material(RID p_particles,RID p_material)=0;
+
+ virtual void particles_set_emission_shape(RID p_particles,VS::ParticlesEmissionShape p_shape)=0;
+ virtual void particles_set_emission_sphere_radius(RID p_particles,float p_radius)=0;
+ virtual void particles_set_emission_box_extents(RID p_particles,const Vector3& p_extents)=0;
+ virtual void particles_set_emission_points(RID p_particles,const PoolVector<Vector3>& p_points)=0;
+
+
+ virtual void particles_set_draw_order(RID p_particles,VS::ParticlesDrawOrder p_order)=0;
+
+ virtual void particles_set_draw_passes(RID p_particles,int p_count)=0;
+ virtual void particles_set_draw_pass_material(RID p_particles,int p_pass, RID p_material)=0;
+ virtual void particles_set_draw_pass_mesh(RID p_particles,int p_pass, RID p_mesh)=0;
+
+ virtual Rect3 particles_get_current_aabb(RID p_particles)=0;
+
+
+
+ /* RENDER TARGET */
+
+ enum RenderTargetFlags {
+ RENDER_TARGET_VFLIP,
+ RENDER_TARGET_TRANSPARENT,
+ RENDER_TARGET_NO_3D,
+ RENDER_TARGET_NO_SAMPLING,
+ RENDER_TARGET_HDR,
+ RENDER_TARGET_FLAG_MAX
+ };
+
+ virtual RID render_target_create()=0;
+ virtual void render_target_set_size(RID p_render_target,int p_width, int p_height)=0;
+ virtual RID render_target_get_texture(RID p_render_target) const=0;
+ virtual void render_target_set_flag(RID p_render_target,RenderTargetFlags p_flag,bool p_value)=0;
+ virtual bool render_target_renedered_in_frame(RID p_render_target)=0;
+ virtual void render_target_set_msaa(RID p_render_target,VS::ViewportMSAA p_msaa)=0;
+
+
+ /* CANVAS SHADOW */
+
+ virtual RID canvas_light_shadow_buffer_create(int p_width)=0;
+
+ /* LIGHT SHADOW MAPPING */
+
+ virtual RID canvas_light_occluder_create()=0;
+ virtual void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2>& p_lines)=0;
+
+
+ virtual VS::InstanceType get_base_type(RID p_rid) const=0;
+ virtual bool free(RID p_rid)=0;
+
+ virtual bool has_os_feature(const String& p_feature) const=0;
+
+ virtual void update_dirty_resources()=0;
+
+ static RasterizerStorage*base_signleton;
+ RasterizerStorage();
+ virtual ~RasterizerStorage() {}
+};
+
+
+
+
+
+class RasterizerCanvas {
+public:
+
+ enum CanvasRectFlags {
+
+ CANVAS_RECT_REGION=1,
+ CANVAS_RECT_TILE=2,
+ CANVAS_RECT_FLIP_H=4,
+ CANVAS_RECT_FLIP_V=8,
+ CANVAS_RECT_TRANSPOSE=16
+ };
+
+
+ struct Light : public RID_Data {
+
+
+
+ bool enabled;
+ Color color;
+ Transform2D xform;
+ float height;
+ float energy;
+ float scale;
+ int z_min;
+ int z_max;
+ int layer_min;
+ int layer_max;
+ int item_mask;
+ int item_shadow_mask;
+ VS::CanvasLightMode mode;
+ RID texture;
+ Vector2 texture_offset;
+ RID canvas;
+ RID shadow_buffer;
+ int shadow_buffer_size;
+ float shadow_gradient_length;
+ VS::CanvasLightShadowFilter shadow_filter;
+ Color shadow_color;
+
+
+ void *texture_cache; // implementation dependent
+ Rect2 rect_cache;
+ Transform2D xform_cache;
+ float radius_cache; //used for shadow far plane
+ CameraMatrix shadow_matrix_cache;
+
+ Transform2D light_shader_xform;
+ Vector2 light_shader_pos;
+
+ Light *shadows_next_ptr;
+ Light *filter_next_ptr;
+ Light *next_ptr;
+ Light *mask_next_ptr;
+
+ RID light_internal;
+
+ Light() {
+ enabled=true;
+ color=Color(1,1,1);
+ shadow_color=Color(0,0,0,0);
+ height=0;
+ z_min=-1024;
+ z_max=1024;
+ layer_min=0;
+ layer_max=0;
+ item_mask=1;
+ scale=1.0;
+ energy=1.0;
+ item_shadow_mask=-1;
+ mode=VS::CANVAS_LIGHT_MODE_ADD;
+ texture_cache=NULL;
+ next_ptr=NULL;
+ mask_next_ptr=NULL;
+ filter_next_ptr=NULL;
+ shadow_buffer_size=256;
+ shadow_gradient_length=0;
+ shadow_filter=VS::CANVAS_LIGHT_FILTER_NONE;
+
+ }
+ };
+
+ virtual RID light_internal_create()=0;
+ virtual void light_internal_update(RID p_rid, Light* p_light)=0;
+ virtual void light_internal_free(RID p_rid)=0;
+
+ struct Item : public RID_Data {
+
+ struct Command {
+
+ enum Type {
+
+ TYPE_LINE,
+ TYPE_RECT,
+ TYPE_NINEPATCH,
+ TYPE_PRIMITIVE,
+ TYPE_POLYGON,
+ TYPE_MESH,
+ TYPE_MULTIMESH,
+ TYPE_CIRCLE,
+ TYPE_TRANSFORM,
+ TYPE_CLIP_IGNORE,
+ };
+
+ Type type;
+ virtual ~Command(){}
+ };
+
+ struct CommandLine : public Command {
+
+ Point2 from,to;
+ Color color;
+ float width;
+ bool antialiased;
+ CommandLine() { type = TYPE_LINE; }
+ };
+
+ struct CommandRect : public Command {
+
+ Rect2 rect;
+ RID texture;
+ Color modulate;
+ Rect2 source;
+ uint8_t flags;
+
+ CommandRect() { flags=0; type = TYPE_RECT; }
+ };
+
+ struct CommandNinePatch : public Command {
+
+ Rect2 rect;
+ Rect2 source;
+ RID texture;
+ float margin[4];
+ bool draw_center;
+ Color color;
+ VS::NinePatchAxisMode axis_x;
+ VS::NinePatchAxisMode axis_y;
+ CommandNinePatch() { draw_center=true; type = TYPE_NINEPATCH; }
+ };
+
+ struct CommandPrimitive : public Command {
+
+ Vector<Point2> points;
+ Vector<Point2> uvs;
+ Vector<Color> colors;
+ RID texture;
+ float width;
+
+ CommandPrimitive() { type = TYPE_PRIMITIVE; width=1;}
+ };
+
+ struct CommandPolygon : public Command {
+
+ Vector<int> indices;
+ Vector<Point2> points;
+ Vector<Point2> uvs;
+ Vector<Color> colors;
+ RID texture;
+ int count;
+
+ CommandPolygon() { type = TYPE_POLYGON; count = 0; }
+ };
+
+
+ struct CommandMesh : public Command {
+
+ RID mesh;
+ RID skeleton;
+ CommandMesh() { type = TYPE_MESH; }
+ };
+
+ struct CommandMultiMesh : public Command {
+
+ RID multimesh;
+ RID skeleton;
+ CommandMultiMesh() { type = TYPE_MULTIMESH; }
+ };
+
+ struct CommandCircle : public Command {
+
+ Point2 pos;
+ float radius;
+ Color color;
+ CommandCircle() { type = TYPE_CIRCLE; }
+ };
+
+ struct CommandTransform : public Command {
+
+ Transform2D xform;
+ CommandTransform() { type = TYPE_TRANSFORM; }
+ };
+
+
+ struct CommandClipIgnore : public Command {
+
+ bool ignore;
+ CommandClipIgnore() { type = TYPE_CLIP_IGNORE; ignore=false; }
+ };
+
+
+ struct ViewportRender {
+ VisualServer*owner;
+ void* udata;
+ Rect2 rect;
+ };
+
+ Transform2D xform;
+ bool clip;
+ bool visible;
+ bool behind;
+ //VS::MaterialBlendMode blend_mode;
+ int light_mask;
+ Vector<Command*> commands;
+ mutable bool custom_rect;
+ mutable bool rect_dirty;
+ mutable Rect2 rect;
+ RID material;
+ Item*next;
+
+ struct CopyBackBuffer {
+ Rect2 rect;
+ Rect2 screen_rect;
+ bool full;
+ };
+ CopyBackBuffer *copy_back_buffer;
+
+
+ Color final_modulate;
+ Transform2D final_transform;
+ Rect2 final_clip_rect;
+ Item* final_clip_owner;
+ Item* material_owner;
+ ViewportRender *vp_render;
+ bool distance_field;
+ bool light_masked;
+
+ Rect2 global_rect_cache;
+
+ const Rect2& get_rect() const {
+ if (custom_rect || !rect_dirty)
+ return rect;
+
+ //must update rect
+ int s=commands.size();
+ if (s==0) {
+
+ rect=Rect2();
+ rect_dirty=false;
+ return rect;
+ }
+
+ Transform2D xf;
+ bool found_xform=false;
+ bool first=true;
+
+ const Item::Command * const *cmd = &commands[0];
+
+
+ for (int i=0;i<s;i++) {
+
+ const Item::Command *c=cmd[i];
+ Rect2 r;
+
+ switch(c->type) {
+ case Item::Command::TYPE_LINE: {
+
+ const Item::CommandLine* line = static_cast< const Item::CommandLine*>(c);
+ r.pos=line->from;
+ r.expand_to(line->to);
+ } break;
+ case Item::Command::TYPE_RECT: {
+
+ const Item::CommandRect* crect = static_cast< const Item::CommandRect*>(c);
+ r=crect->rect;
+
+ } break;
+ case Item::Command::TYPE_NINEPATCH: {
+
+ const Item::CommandNinePatch* style = static_cast< const Item::CommandNinePatch*>(c);
+ r=style->rect;
+ } break;
+ case Item::Command::TYPE_PRIMITIVE: {
+
+ const Item::CommandPrimitive* primitive = static_cast< const Item::CommandPrimitive*>(c);
+ r.pos=primitive->points[0];
+ for(int i=1;i<primitive->points.size();i++) {
+
+ r.expand_to(primitive->points[i]);
+
+ }
+ } break;
+ case Item::Command::TYPE_POLYGON: {
+
+ const Item::CommandPolygon* polygon = static_cast< const Item::CommandPolygon*>(c);
+ int l = polygon->points.size();
+ const Point2*pp=&polygon->points[0];
+ r.pos=pp[0];
+ for(int i=1;i<l;i++) {
+
+ r.expand_to(pp[i]);
+
+ }
+ } break;
+ case Item::Command::TYPE_MESH: {
+
+ const Item::CommandMesh* mesh = static_cast< const Item::CommandMesh*>(c);
+ Rect3 aabb = RasterizerStorage::base_signleton->mesh_get_aabb(mesh->mesh,mesh->skeleton);
+
+ r=Rect2(aabb.pos.x,aabb.pos.y,aabb.size.x,aabb.size.y);
+
+ } break;
+ case Item::Command::TYPE_MULTIMESH: {
+
+ const Item::CommandMultiMesh* multimesh = static_cast< const Item::CommandMultiMesh*>(c);
+ Rect3 aabb = RasterizerStorage::base_signleton->multimesh_get_aabb(multimesh->multimesh);
+
+ r=Rect2(aabb.pos.x,aabb.pos.y,aabb.size.x,aabb.size.y);
+
+ } break;
+ case Item::Command::TYPE_CIRCLE: {
+
+ const Item::CommandCircle* circle = static_cast< const Item::CommandCircle*>(c);
+ r.pos=Point2(-circle->radius,-circle->radius)+circle->pos;
+ r.size=Point2(circle->radius*2.0,circle->radius*2.0);
+ } break;
+ case Item::Command::TYPE_TRANSFORM: {
+
+ const Item::CommandTransform* transform = static_cast<const Item::CommandTransform*>(c);
+ xf=transform->xform;
+ found_xform=true;
+ continue;
+ } break;
+
+ case Item::Command::TYPE_CLIP_IGNORE: {
+
+ } break;
+ }
+
+ if (found_xform) {
+ r = xf.xform(r);
+ found_xform=false;
+ }
+
+
+ if (first) {
+ rect=r;
+ first=false;
+ } else
+ rect=rect.merge(r);
+ }
+
+ rect_dirty=false;
+ return rect;
+ }
+
+ void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL; light_masked=false; }
+ Item() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_modulate=Color(1,1,1,1); visible=true; rect_dirty=true; custom_rect=false; behind=false; material_owner=NULL; copy_back_buffer=NULL; distance_field=false; light_masked=false; }
+ virtual ~Item() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); }
+ };
+
+
+ virtual void canvas_begin()=0;
+
+ virtual void canvas_render_items(Item *p_item_list,int p_z,const Color& p_modulate,Light *p_light)=0;
+ virtual void canvas_debug_viewport_shadows(Light* p_lights_with_shadow)=0;
+
+
+
+ struct LightOccluderInstance : public RID_Data {
+
+
+ bool enabled;
+ RID canvas;
+ RID polygon;
+ RID polygon_buffer;
+ Rect2 aabb_cache;
+ Transform2D xform;
+ Transform2D xform_cache;
+ int light_mask;
+ VS::CanvasOccluderPolygonCullMode cull_cache;
+
+ LightOccluderInstance *next;
+
+ LightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
+ };
+
+
+
+ virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Transform2D& p_light_xform, int p_light_mask,float p_near, float p_far, LightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0;
+
+
+ virtual void reset_canvas()=0;
+
+ virtual ~RasterizerCanvas() {}
+};
+
+
+class Rasterizer {
+protected:
+ static Rasterizer* (*_create_func)();
+public:
+ static Rasterizer *create();
+
+ virtual RasterizerStorage *get_storage()=0;
+ virtual RasterizerCanvas *get_canvas()=0;
+ virtual RasterizerScene *get_scene()=0;
+
+ virtual void initialize()=0;
+ virtual void begin_frame()=0;
+ virtual void set_current_render_target(RID p_render_target)=0;
+ virtual void restore_render_target()=0;
+ virtual void clear_render_target(const Color& p_color)=0;
+ virtual void blit_render_target_to_screen(RID p_render_target,const Rect2& p_screen_rect,int p_screen=0)=0;
+ virtual void end_frame()=0;
+ virtual void finalize()=0;
+
+
+ virtual ~Rasterizer() {}
+};
+
+
+#if 0
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
@@ -41,7 +967,7 @@ class Rasterizer {
protected:
- typedef void (*CanvasItemDrawViewportFunc)(VisualServer*owner,void*ud,const Rect2& p_rect);
+ typedef void (*ItemDrawViewportFunc)(VisualServer*owner,void*ud,const Rect2& p_rect);
RID create_default_material();
RID create_overdraw_debug_material();
@@ -49,7 +975,7 @@ protected:
/* Fixed Material Shader API */
- union FixedMaterialShaderKey {
+ union FixedSpatialMaterialShaderKey {
struct {
uint16_t texcoord_mask;
@@ -65,21 +991,21 @@ protected:
uint32_t key;
- _FORCE_INLINE_ bool operator<(const FixedMaterialShaderKey& p_key) const { return key<p_key.key; }
+ _FORCE_INLINE_ bool operator<(const FixedSpatialMaterialShaderKey& p_key) const { return key<p_key.key; }
};
- struct FixedMaterialShader {
+ struct FixedSpatialMaterialShader {
int refcount;
RID shader;
};
- Map<FixedMaterialShaderKey,FixedMaterialShader> fixed_material_shaders;
+ Map<FixedSpatialMaterialShaderKey,FixedSpatialMaterialShader> fixed_material_shaders;
- RID _create_shader(const FixedMaterialShaderKey& p_key);
- void _free_shader(const FixedMaterialShaderKey& p_key);
+ RID _create_shader(const FixedSpatialMaterialShaderKey& p_key);
+ void _free_shader(const FixedSpatialMaterialShaderKey& p_key);
- struct FixedMaterial {
+ struct FixedSpatialMaterial {
RID self;
@@ -90,19 +1016,19 @@ protected:
bool use_xy_normalmap;
float point_size;
Transform uv_xform;
- VS::FixedMaterialLightShader light_shader;
+ VS::FixedSpatialMaterialLightShader light_shader;
RID texture[VS::FIXED_MATERIAL_PARAM_MAX];
Variant param[VS::FIXED_MATERIAL_PARAM_MAX];
- VS::FixedMaterialTexCoordMode texture_tc[VS::FIXED_MATERIAL_PARAM_MAX];
+ VS::FixedSpatialMaterialTexCoordMode texture_tc[VS::FIXED_MATERIAL_PARAM_MAX];
- SelfList<FixedMaterial> dirty_list;
+ SelfList<FixedSpatialMaterial> dirty_list;
- FixedMaterialShaderKey current_key;
+ FixedSpatialMaterialShaderKey current_key;
- _FORCE_INLINE_ FixedMaterialShaderKey get_key() const {
+ _FORCE_INLINE_ FixedSpatialMaterialShaderKey get_key() const {
- FixedMaterialShaderKey k;
+ FixedSpatialMaterialShaderKey k;
k.key=0;
k.use_alpha=use_alpha;
k.use_color_array=use_color_array;
@@ -123,7 +1049,7 @@ protected:
}
- FixedMaterial() : dirty_list(this) {
+ FixedSpatialMaterial() : dirty_list(this) {
use_alpha=false;
use_color_array=false;
@@ -155,9 +1081,9 @@ protected:
StringName _fixed_material_uv_xform_name;
StringName _fixed_material_point_size_name;
- Map<RID,FixedMaterial*> fixed_materials;
+ Map<RID,FixedSpatialMaterial*> fixed_materials;
- SelfList<FixedMaterial>::List fixed_material_dirty_list;
+ SelfList<FixedSpatialMaterial>::List fixed_material_dirty_list;
protected:
void _update_fixed_materials();
@@ -244,23 +1170,23 @@ public:
virtual RID fixed_material_create();
- virtual void fixed_material_set_flag(RID p_material, VS::FixedMaterialFlags p_flag, bool p_enabled);
- virtual bool fixed_material_get_flag(RID p_material, VS::FixedMaterialFlags p_flag) const;
+ virtual void fixed_material_set_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag, bool p_enabled);
+ virtual bool fixed_material_get_flag(RID p_material, VS::FixedSpatialMaterialFlags p_flag) const;
- virtual void fixed_material_set_parameter(RID p_material, VS::FixedMaterialParam p_parameter, const Variant& p_value);
- virtual Variant fixed_material_get_parameter(RID p_material,VS::FixedMaterialParam p_parameter) const;
+ virtual void fixed_material_set_parameter(RID p_material, VS::FixedSpatialMaterialParam p_parameter, const Variant& p_value);
+ virtual Variant fixed_material_get_parameter(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const;
- virtual void fixed_material_set_texture(RID p_material,VS::FixedMaterialParam p_parameter, RID p_texture);
- virtual RID fixed_material_get_texture(RID p_material,VS::FixedMaterialParam p_parameter) const;
+ virtual void fixed_material_set_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter, RID p_texture);
+ virtual RID fixed_material_get_texture(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const;
- virtual void fixed_material_set_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter, VS::FixedMaterialTexCoordMode p_mode);
- virtual VS::FixedMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,VS::FixedMaterialParam p_parameter) const;
+ virtual void fixed_material_set_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter, VS::FixedSpatialMaterialTexCoordMode p_mode);
+ virtual VS::FixedSpatialMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,VS::FixedSpatialMaterialParam p_parameter) const;
virtual void fixed_material_set_uv_transform(RID p_material,const Transform& p_transform);
virtual Transform fixed_material_get_uv_transform(RID p_material) const;
- virtual void fixed_material_set_light_shader(RID p_material,VS::FixedMaterialLightShader p_shader);
- virtual VS::FixedMaterialLightShader fixed_material_get_light_shader(RID p_material) const;
+ virtual void fixed_material_set_light_shader(RID p_material,VS::FixedSpatialMaterialLightShader p_shader);
+ virtual VS::FixedSpatialMaterialLightShader fixed_material_get_light_shader(RID p_material) const;
virtual void fixed_material_set_point_size(RID p_material,float p_size);
virtual float fixed_material_get_point_size(RID p_material) const;
@@ -311,7 +1237,7 @@ public:
virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color)=0;
virtual RID multimesh_get_mesh(RID p_multimesh) const=0;
- virtual AABB multimesh_get_aabb(RID p_multimesh) const=0;;
+ virtual AABB multimesh_get_aabb(RID p_multimesh) const=0;
virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const=0;
virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const=0;
@@ -360,8 +1286,8 @@ public:
virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity)=0;
virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const=0;
- virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points)=0;
- virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const=0;
+ virtual void particles_set_emission_points(RID p_particles, const PoolVector<Vector3>& p_points)=0;
+ virtual PoolVector<Vector3> particles_get_emission_points(RID p_particles) const=0;
virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal)=0;
virtual Vector3 particles_get_gravity_normal(RID p_particles) const=0;
@@ -581,7 +1507,7 @@ public:
};
- struct CanvasLight {
+ struct Light {
@@ -597,7 +1523,7 @@ public:
int layer_max;
int item_mask;
int item_shadow_mask;
- VS::CanvasLightMode mode;
+ VS::LightMode mode;
RID texture;
Vector2 texture_offset;
RID canvas;
@@ -616,12 +1542,12 @@ public:
Matrix32 light_shader_xform;
Vector2 light_shader_pos;
- CanvasLight *shadows_next_ptr;
- CanvasLight *filter_next_ptr;
- CanvasLight *next_ptr;
- CanvasLight *mask_next_ptr;
+ Light *shadows_next_ptr;
+ Light *filter_next_ptr;
+ Light *next_ptr;
+ Light *mask_next_ptr;
- CanvasLight() {
+ Light() {
enabled=true;
color=Color(1,1,1);
shadow_color=Color(0,0,0,0);
@@ -645,20 +1571,20 @@ public:
}
};
- struct CanvasItem;
+ struct Item;
- struct CanvasItemMaterial {
+ struct ItemMaterial {
RID shader;
Map<StringName,Variant> shader_param;
uint32_t shader_version;
- Set<CanvasItem*> owners;
- VS::CanvasItemShadingMode shading_mode;
+ Set<Item*> owners;
+ VS::ItemShadingMode shading_mode;
- CanvasItemMaterial() {shading_mode=VS::CANVAS_ITEM_SHADING_NORMAL; shader_version=0; }
+ ItemMaterial() {shading_mode=VS::CANVAS_ITEM_SHADING_NORMAL; shader_version=0; }
};
- struct CanvasItem {
+ struct Item {
struct Command {
@@ -788,8 +1714,8 @@ public:
mutable bool custom_rect;
mutable bool rect_dirty;
mutable Rect2 rect;
- CanvasItem*next;
- CanvasItemMaterial* material;
+ Item*next;
+ ItemMaterial* material;
struct CopyBackBuffer {
Rect2 rect;
Rect2 screen_rect;
@@ -801,8 +1727,8 @@ public:
float final_opacity;
Matrix32 final_transform;
Rect2 final_clip_rect;
- CanvasItem* final_clip_owner;
- CanvasItem* material_owner;
+ Item* final_clip_owner;
+ Item* material_owner;
ViewportRender *vp_render;
bool distance_field;
bool light_masked;
@@ -826,35 +1752,35 @@ public:
bool found_xform=false;
bool first=true;
- const CanvasItem::Command * const *cmd = &commands[0];
+ const Item::Command * const *cmd = &commands[0];
for (int i=0;i<s;i++) {
- const CanvasItem::Command *c=cmd[i];
+ const Item::Command *c=cmd[i];
Rect2 r;
switch(c->type) {
- case CanvasItem::Command::TYPE_LINE: {
+ case Item::Command::TYPE_LINE: {
- const CanvasItem::CommandLine* line = static_cast< const CanvasItem::CommandLine*>(c);
+ const Item::CommandLine* line = static_cast< const Item::CommandLine*>(c);
r.pos=line->from;
r.expand_to(line->to);
} break;
- case CanvasItem::Command::TYPE_RECT: {
+ case Item::Command::TYPE_RECT: {
- const CanvasItem::CommandRect* crect = static_cast< const CanvasItem::CommandRect*>(c);
+ const Item::CommandRect* crect = static_cast< const Item::CommandRect*>(c);
r=crect->rect;
} break;
- case CanvasItem::Command::TYPE_STYLE: {
+ case Item::Command::TYPE_STYLE: {
- const CanvasItem::CommandStyle* style = static_cast< const CanvasItem::CommandStyle*>(c);
+ const Item::CommandStyle* style = static_cast< const Item::CommandStyle*>(c);
r=style->rect;
} break;
- case CanvasItem::Command::TYPE_PRIMITIVE: {
+ case Item::Command::TYPE_PRIMITIVE: {
- const CanvasItem::CommandPrimitive* primitive = static_cast< const CanvasItem::CommandPrimitive*>(c);
+ const Item::CommandPrimitive* primitive = static_cast< const Item::CommandPrimitive*>(c);
r.pos=primitive->points[0];
for(int i=1;i<primitive->points.size();i++) {
@@ -862,9 +1788,9 @@ public:
}
} break;
- case CanvasItem::Command::TYPE_POLYGON: {
+ case Item::Command::TYPE_POLYGON: {
- const CanvasItem::CommandPolygon* polygon = static_cast< const CanvasItem::CommandPolygon*>(c);
+ const Item::CommandPolygon* polygon = static_cast< const Item::CommandPolygon*>(c);
int l = polygon->points.size();
const Point2*pp=&polygon->points[0];
r.pos=pp[0];
@@ -875,9 +1801,9 @@ public:
}
} break;
- case CanvasItem::Command::TYPE_POLYGON_PTR: {
+ case Item::Command::TYPE_POLYGON_PTR: {
- const CanvasItem::CommandPolygonPtr* polygon = static_cast< const CanvasItem::CommandPolygonPtr*>(c);
+ const Item::CommandPolygonPtr* polygon = static_cast< const Item::CommandPolygonPtr*>(c);
int l = polygon->count;
if (polygon->indices != NULL) {
@@ -894,23 +1820,23 @@ public:
}
}
} break;
- case CanvasItem::Command::TYPE_CIRCLE: {
+ case Item::Command::TYPE_CIRCLE: {
- const CanvasItem::CommandCircle* circle = static_cast< const CanvasItem::CommandCircle*>(c);
+ const Item::CommandCircle* circle = static_cast< const Item::CommandCircle*>(c);
r.pos=Point2(-circle->radius,-circle->radius)+circle->pos;
r.size=Point2(circle->radius*2.0,circle->radius*2.0);
} break;
- case CanvasItem::Command::TYPE_TRANSFORM: {
+ case Item::Command::TYPE_TRANSFORM: {
- const CanvasItem::CommandTransform* transform = static_cast<const CanvasItem::CommandTransform*>(c);
+ const Item::CommandTransform* transform = static_cast<const Item::CommandTransform*>(c);
xf=transform->xform;
found_xform=true;
continue;
} break;
- case CanvasItem::Command::TYPE_BLEND_MODE: {
+ case Item::Command::TYPE_BLEND_MODE: {
} break;
- case CanvasItem::Command::TYPE_CLIP_IGNORE: {
+ case Item::Command::TYPE_CLIP_IGNORE: {
} break;
}
@@ -933,12 +1859,12 @@ public:
}
void clear() { for (int i=0;i<commands.size();i++) memdelete( commands[i] ); commands.clear(); clip=false; rect_dirty=true; final_clip_owner=NULL; material_owner=NULL; light_masked=false; }
- CanvasItem() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; distance_field=false; light_masked=false; }
- virtual ~CanvasItem() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); }
+ Item() { light_mask=1; vp_render=NULL; next=NULL; final_clip_owner=NULL; clip=false; final_opacity=1; blend_mode=VS::MATERIAL_BLEND_MODE_MIX; visible=true; rect_dirty=true; custom_rect=false; ontop=true; material_owner=NULL; material=NULL; copy_back_buffer=NULL; distance_field=false; light_masked=false; }
+ virtual ~Item() { clear(); if (copy_back_buffer) memdelete(copy_back_buffer); }
};
- CanvasItemDrawViewportFunc draw_viewport_func;
+ ItemDrawViewportFunc draw_viewport_func;
virtual void begin_canvas_bg()=0;
@@ -956,17 +1882,17 @@ public:
virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor)=0;
virtual void canvas_set_transform(const Matrix32& p_transform)=0;
- virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light)=0;
- virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow)=0;
+ virtual void canvas_render_items(Item *p_item_list,int p_z,const Color& p_modulate,Light *p_light)=0;
+ virtual void canvas_debug_viewport_shadows(Light* p_lights_with_shadow)=0;
/* LIGHT SHADOW MAPPING */
virtual RID canvas_light_occluder_create()=0;
- virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines)=0;
+ virtual void canvas_light_occluder_set_polylines(RID p_occluder, const PoolVector<Vector2>& p_lines)=0;
virtual RID canvas_light_shadow_buffer_create(int p_width)=0;
- struct CanvasLightOccluderInstance {
+ struct LightOccluderInstance {
bool enabled;
@@ -979,14 +1905,14 @@ public:
int light_mask;
VS::CanvasOccluderPolygonCullMode cull_cache;
- CanvasLightOccluderInstance *next;
+ LightOccluderInstance *next;
- CanvasLightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
+ LightOccluderInstance() { enabled=true; next=NULL; light_mask=1; cull_cache=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
};
- virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0;
+ virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, LightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache)=0;
/* ENVIRONMENT */
@@ -1050,5 +1976,5 @@ public:
};
-
+#endif
#endif
diff --git a/servers/visual/rasterizer_dummy.cpp b/servers/visual/rasterizer_dummy.cpp
deleted file mode 100644
index edbdc2fe23..0000000000
--- a/servers/visual/rasterizer_dummy.cpp
+++ /dev/null
@@ -1,1961 +0,0 @@
-/*************************************************************************/
-/* rasterizer_dummy.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 "rasterizer_dummy.h"
-
-/* TEXTURE API */
-
-
-RID RasterizerDummy::texture_create() {
-
- Texture *texture = memnew(Texture);
- ERR_FAIL_COND_V(!texture,RID());
- return texture_owner.make_rid( texture );
-
-}
-
-void RasterizerDummy::texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags) {
-
-
- Texture *texture = texture_owner.get( p_texture );
- ERR_FAIL_COND(!texture);
- texture->width=p_width;
- texture->height=p_height;
- texture->format=p_format;
- texture->flags=p_flags;
-}
-
-void RasterizerDummy::texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side) {
-
- Texture * texture = texture_owner.get(p_texture);
-
- ERR_FAIL_COND(!texture);
- ERR_FAIL_COND(texture->format != p_image.get_format() );
-
- texture->image[p_cube_side]=p_image;
-
-}
-
-Image RasterizerDummy::texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side) const {
-
- Texture * texture = texture_owner.get(p_texture);
-
- ERR_FAIL_COND_V(!texture,Image());
-
- return texture->image[p_cube_side];
-}
-
-void RasterizerDummy::texture_set_flags(RID p_texture,uint32_t p_flags) {
-
- Texture *texture = texture_owner.get( p_texture );
- ERR_FAIL_COND(!texture);
- uint32_t cube = texture->flags & VS::TEXTURE_FLAG_CUBEMAP;
- texture->flags=p_flags|cube; // can't remove a cube from being a cube
-
-}
-uint32_t RasterizerDummy::texture_get_flags(RID p_texture) const {
-
- Texture * texture = texture_owner.get(p_texture);
-
- ERR_FAIL_COND_V(!texture,0);
-
- return texture->flags;
-
-}
-Image::Format RasterizerDummy::texture_get_format(RID p_texture) const {
-
- Texture * texture = texture_owner.get(p_texture);
-
- ERR_FAIL_COND_V(!texture,Image::FORMAT_GRAYSCALE);
-
- return texture->format;
-}
-uint32_t RasterizerDummy::texture_get_width(RID p_texture) const {
-
- Texture * texture = texture_owner.get(p_texture);
-
- ERR_FAIL_COND_V(!texture,0);
-
- return texture->width;
-}
-uint32_t RasterizerDummy::texture_get_height(RID p_texture) const {
-
- Texture * texture = texture_owner.get(p_texture);
-
- ERR_FAIL_COND_V(!texture,0);
-
- return texture->height;
-}
-
-bool RasterizerDummy::texture_has_alpha(RID p_texture) const {
-
- Texture * texture = texture_owner.get(p_texture);
-
- ERR_FAIL_COND_V(!texture,0);
-
- return false;
-
-}
-
-void RasterizerDummy::texture_set_size_override(RID p_texture,int p_width, int p_height) {
-
- Texture * texture = texture_owner.get(p_texture);
-
- ERR_FAIL_COND(!texture);
-
- ERR_FAIL_COND(p_width<=0 || p_width>4096);
- ERR_FAIL_COND(p_height<=0 || p_height>4096);
- //real texture size is in alloc width and height
-// texture->width=p_width;
-// texture->height=p_height;
-
-}
-
-void RasterizerDummy::texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const {
-
-
-}
-
-/* SHADER API */
-
-/* SHADER API */
-
-RID RasterizerDummy::shader_create(VS::ShaderMode p_mode) {
-
- Shader *shader = memnew( Shader );
- shader->mode=p_mode;
- shader->fragment_line=0;
- shader->vertex_line=0;
- shader->light_line=0;
- RID rid = shader_owner.make_rid(shader);
-
- return rid;
-
-}
-
-
-
-void RasterizerDummy::shader_set_mode(RID p_shader,VS::ShaderMode p_mode) {
-
- ERR_FAIL_INDEX(p_mode,3);
- Shader *shader=shader_owner.get(p_shader);
- ERR_FAIL_COND(!shader);
- shader->mode=p_mode;
-
-}
-VS::ShaderMode RasterizerDummy::shader_get_mode(RID p_shader) const {
-
- Shader *shader=shader_owner.get(p_shader);
- ERR_FAIL_COND_V(!shader,VS::SHADER_MATERIAL);
- return shader->mode;
-}
-
-void RasterizerDummy::shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs,int p_fragment_ofs,int p_light_ofs) {
-
-
- Shader *shader=shader_owner.get(p_shader);
- ERR_FAIL_COND(!shader);
- shader->fragment_code=p_fragment;
- shader->vertex_code=p_vertex;
- shader->light_code=p_light;
- shader->fragment_line=p_fragment_ofs;
- shader->vertex_line=p_vertex_ofs;
- shader->light_line=p_vertex_ofs;
-
-}
-
-
-String RasterizerDummy::shader_get_vertex_code(RID p_shader) const {
-
- Shader *shader=shader_owner.get(p_shader);
- ERR_FAIL_COND_V(!shader,String());
- return shader->vertex_code;
-
-}
-
-String RasterizerDummy::shader_get_fragment_code(RID p_shader) const {
-
- Shader *shader=shader_owner.get(p_shader);
- ERR_FAIL_COND_V(!shader,String());
- return shader->fragment_code;
-
-}
-
-String RasterizerDummy::shader_get_light_code(RID p_shader) const {
-
- Shader *shader=shader_owner.get(p_shader);
- ERR_FAIL_COND_V(!shader,String());
- return shader->light_code;
-
-}
-
-void RasterizerDummy::shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const {
-
- Shader *shader=shader_owner.get(p_shader);
- ERR_FAIL_COND(!shader);
-
-}
-
-
-void RasterizerDummy::shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture) {
-
-}
-
-RID RasterizerDummy::shader_get_default_texture_param(RID p_shader, const StringName& p_name) const {
-
- return RID();
-}
-
-Variant RasterizerDummy::shader_get_default_param(RID p_shader, const StringName& p_name) {
-
- return Variant();
-}
-
-/* COMMON MATERIAL API */
-
-
-RID RasterizerDummy::material_create() {
-
- return material_owner.make_rid( memnew( Material ) );
-}
-
-void RasterizerDummy::material_set_shader(RID p_material, RID p_shader) {
-
- Material *material = material_owner.get(p_material);
- ERR_FAIL_COND(!material);
- material->shader=p_shader;
-
-}
-
-RID RasterizerDummy::material_get_shader(RID p_material) const {
-
- Material *material = material_owner.get(p_material);
- ERR_FAIL_COND_V(!material,RID());
- return material->shader;
-}
-
-void RasterizerDummy::material_set_param(RID p_material, const StringName& p_param, const Variant& p_value) {
-
- Material *material = material_owner.get(p_material);
- ERR_FAIL_COND(!material);
-
- if (p_value.get_type()==Variant::NIL)
- material->shader_params.erase(p_param);
- else
- material->shader_params[p_param]=p_value;
-}
-Variant RasterizerDummy::material_get_param(RID p_material, const StringName& p_param) const {
-
- Material *material = material_owner.get(p_material);
- ERR_FAIL_COND_V(!material,Variant());
-
- if (material->shader_params.has(p_param))
- return material->shader_params[p_param];
- else
- return Variant();
-}
-
-
-void RasterizerDummy::material_set_flag(RID p_material, VS::MaterialFlag p_flag,bool p_enabled) {
-
- Material *material = material_owner.get(p_material);
- ERR_FAIL_COND(!material);
- ERR_FAIL_INDEX(p_flag,VS::MATERIAL_FLAG_MAX);
- material->flags[p_flag]=p_enabled;
-
-}
-bool RasterizerDummy::material_get_flag(RID p_material,VS::MaterialFlag p_flag) const {
-
- Material *material = material_owner.get(p_material);
- ERR_FAIL_COND_V(!material,false);
- ERR_FAIL_INDEX_V(p_flag,VS::MATERIAL_FLAG_MAX,false);
- return material->flags[p_flag];
-
-
-}
-
-void RasterizerDummy::material_set_depth_draw_mode(RID p_material, VS::MaterialDepthDrawMode p_mode) {
-
- Material *material = material_owner.get(p_material);
- ERR_FAIL_COND(!material);
- material->depth_draw_mode=p_mode;
-}
-
-VS::MaterialDepthDrawMode RasterizerDummy::material_get_depth_draw_mode(RID p_material) const{
-
- Material *material = material_owner.get(p_material);
- ERR_FAIL_COND_V(!material,VS::MATERIAL_DEPTH_DRAW_ALWAYS);
- return material->depth_draw_mode;
-
-}
-
-
-void RasterizerDummy::material_set_blend_mode(RID p_material,VS::MaterialBlendMode p_mode) {
-
- Material *material = material_owner.get(p_material);
- ERR_FAIL_COND(!material);
- material->blend_mode=p_mode;
-
-}
-VS::MaterialBlendMode RasterizerDummy::material_get_blend_mode(RID p_material) const {
-
- Material *material = material_owner.get(p_material);
- ERR_FAIL_COND_V(!material,VS::MATERIAL_BLEND_MODE_ADD);
- return material->blend_mode;
-}
-
-void RasterizerDummy::material_set_line_width(RID p_material,float p_line_width) {
-
- Material *material = material_owner.get(p_material);
- ERR_FAIL_COND(!material);
- material->line_width=p_line_width;
-
-}
-float RasterizerDummy::material_get_line_width(RID p_material) const {
-
- Material *material = material_owner.get(p_material);
- ERR_FAIL_COND_V(!material,0);
-
- return material->line_width;
-}
-
-/* MESH API */
-
-
-RID RasterizerDummy::mesh_create() {
-
-
- return mesh_owner.make_rid( memnew( Mesh ) );
-}
-
-
-void RasterizerDummy::mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,bool p_alpha_sort) {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND(!mesh);
-
- ERR_FAIL_INDEX( p_primitive, VS::PRIMITIVE_MAX );
- ERR_FAIL_COND(p_arrays.size()!=VS::ARRAY_MAX);
-
- Surface s;
-
-
- s.format=0;
-
- for(int i=0;i<p_arrays.size();i++) {
-
- if (p_arrays[i].get_type()==Variant::NIL)
- continue;
-
- s.format|=(1<<i);
-
- if (i==VS::ARRAY_VERTEX) {
-
- Vector3Array v = p_arrays[i];
- int len = v.size();
- ERR_FAIL_COND(len==0);
- Vector3Array::Read r = v.read();
-
-
- for(int i=0;i<len;i++) {
-
- if (i==0)
- s.aabb.pos=r[0];
- else
- s.aabb.expand_to(r[i]);
- }
-
- }
- }
-
- ERR_FAIL_COND((s.format&VS::ARRAY_FORMAT_VERTEX)==0); // mandatory
-
- s.data=p_arrays;
- s.morph_data=p_blend_shapes;
- s.primitive=p_primitive;
- s.alpha_sort=p_alpha_sort;
- s.morph_target_count=mesh->morph_target_count;
- s.morph_format=s.format;
-
-
- Surface *surface = memnew( Surface );
- *surface=s;
-
- mesh->surfaces.push_back(surface);
-
-
-}
-
-
-
-void RasterizerDummy::mesh_add_custom_surface(RID p_mesh,const Variant& p_dat) {
-
- ERR_EXPLAIN("Dummy Rasterizer does not support custom surfaces. Running on wrong platform?");
- ERR_FAIL_V();
-}
-
-Array RasterizerDummy::mesh_get_surface_arrays(RID p_mesh,int p_surface) const {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND_V(!mesh,Array());
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Array() );
- Surface *surface = mesh->surfaces[p_surface];
- ERR_FAIL_COND_V( !surface, Array() );
-
- return surface->data;
-
-
-}
-Array RasterizerDummy::mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const{
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND_V(!mesh,Array());
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), Array() );
- Surface *surface = mesh->surfaces[p_surface];
- ERR_FAIL_COND_V( !surface, Array() );
-
- return surface->morph_data;
-
-}
-
-
-void RasterizerDummy::mesh_set_morph_target_count(RID p_mesh,int p_amount) {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_COND( mesh->surfaces.size()!=0 );
-
- mesh->morph_target_count=p_amount;
-
-}
-
-int RasterizerDummy::mesh_get_morph_target_count(RID p_mesh) const{
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND_V(!mesh,-1);
-
- return mesh->morph_target_count;
-
-}
-
-void RasterizerDummy::mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode) {
-
- ERR_FAIL_INDEX(p_mode,2);
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND(!mesh);
-
- mesh->morph_target_mode=p_mode;
-
-}
-
-VS::MorphTargetMode RasterizerDummy::mesh_get_morph_target_mode(RID p_mesh) const {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND_V(!mesh,VS::MORPH_MODE_NORMALIZED);
-
- return mesh->morph_target_mode;
-
-}
-
-
-
-void RasterizerDummy::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned) {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_INDEX(p_surface, mesh->surfaces.size() );
- Surface *surface = mesh->surfaces[p_surface];
- ERR_FAIL_COND( !surface);
-
- if (surface->material_owned && surface->material.is_valid())
- free(surface->material);
-
- surface->material_owned=p_owned;
- surface->material=p_material;
-}
-
-RID RasterizerDummy::mesh_surface_get_material(RID p_mesh, int p_surface) const {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND_V(!mesh,RID());
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), RID() );
- Surface *surface = mesh->surfaces[p_surface];
- ERR_FAIL_COND_V( !surface, RID() );
-
- return surface->material;
-}
-
-int RasterizerDummy::mesh_surface_get_array_len(RID p_mesh, int p_surface) const {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND_V(!mesh,-1);
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1 );
- Surface *surface = mesh->surfaces[p_surface];
- ERR_FAIL_COND_V( !surface, -1 );
-
- Vector3Array arr = surface->data[VS::ARRAY_VERTEX];
- return arr.size();
-
-}
-
-int RasterizerDummy::mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND_V(!mesh,-1);
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1 );
- Surface *surface = mesh->surfaces[p_surface];
- ERR_FAIL_COND_V( !surface, -1 );
-
- IntArray arr = surface->data[VS::ARRAY_INDEX];
- return arr.size();
-
-}
-uint32_t RasterizerDummy::mesh_surface_get_format(RID p_mesh, int p_surface) const {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND_V(!mesh,0);
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), 0 );
- Surface *surface = mesh->surfaces[p_surface];
- ERR_FAIL_COND_V( !surface, 0 );
-
- return surface->format;
-}
-VS::PrimitiveType RasterizerDummy::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND_V(!mesh,VS::PRIMITIVE_POINTS);
- ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), VS::PRIMITIVE_POINTS );
- Surface *surface = mesh->surfaces[p_surface];
- ERR_FAIL_COND_V( !surface, VS::PRIMITIVE_POINTS );
-
- return surface->primitive;
-}
-
-void RasterizerDummy::mesh_remove_surface(RID p_mesh,int p_index) {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND(!mesh);
- ERR_FAIL_INDEX(p_index, mesh->surfaces.size() );
- Surface *surface = mesh->surfaces[p_index];
- ERR_FAIL_COND( !surface);
-
- memdelete( mesh->surfaces[p_index] );
- mesh->surfaces.remove(p_index);
-
-}
-int RasterizerDummy::mesh_get_surface_count(RID p_mesh) const {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND_V(!mesh,-1);
-
- return mesh->surfaces.size();
-}
-
-AABB RasterizerDummy::mesh_get_aabb(RID p_mesh,RID p_skeleton) const {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND_V(!mesh,AABB());
-
- AABB aabb;
-
- for (int i=0;i<mesh->surfaces.size();i++) {
-
- if (i==0)
- aabb=mesh->surfaces[i]->aabb;
- else
- aabb.merge_with(mesh->surfaces[i]->aabb);
- }
-
- return aabb;
-}
-
-void RasterizerDummy::mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb) {
-
- Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND(!mesh);
-
- mesh->custom_aabb=p_aabb;
-}
-
-AABB RasterizerDummy::mesh_get_custom_aabb(RID p_mesh) const {
-
- const Mesh *mesh = mesh_owner.get( p_mesh );
- ERR_FAIL_COND_V(!mesh,AABB());
-
- return mesh->custom_aabb;
-
-}
-
-/* MULTIMESH API */
-
-RID RasterizerDummy::multimesh_create() {
-
- return multimesh_owner.make_rid( memnew( MultiMesh ));
-}
-
-void RasterizerDummy::multimesh_set_instance_count(RID p_multimesh,int p_count) {
-
- MultiMesh *multimesh = multimesh_owner.get(p_multimesh);
- ERR_FAIL_COND(!multimesh);
-
- multimesh->elements.clear(); // make sure to delete everything, so it "fails" in all implementations
- multimesh->elements.resize(p_count);
-
-}
-int RasterizerDummy::multimesh_get_instance_count(RID p_multimesh) const {
-
- MultiMesh *multimesh = multimesh_owner.get(p_multimesh);
- ERR_FAIL_COND_V(!multimesh,-1);
-
- return multimesh->elements.size();
-}
-
-void RasterizerDummy::multimesh_set_mesh(RID p_multimesh,RID p_mesh) {
-
- MultiMesh *multimesh = multimesh_owner.get(p_multimesh);
- ERR_FAIL_COND(!multimesh);
-
- multimesh->mesh=p_mesh;
-
-}
-void RasterizerDummy::multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb) {
-
- MultiMesh *multimesh = multimesh_owner.get(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- multimesh->aabb=p_aabb;
-}
-void RasterizerDummy::multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform) {
-
- MultiMesh *multimesh = multimesh_owner.get(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- ERR_FAIL_INDEX(p_index,multimesh->elements.size());
- multimesh->elements[p_index].xform=p_transform;
-
-}
-void RasterizerDummy::multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color) {
-
- MultiMesh *multimesh = multimesh_owner.get(p_multimesh);
- ERR_FAIL_COND(!multimesh)
- ERR_FAIL_INDEX(p_index,multimesh->elements.size());
- multimesh->elements[p_index].color=p_color;
-
-}
-
-RID RasterizerDummy::multimesh_get_mesh(RID p_multimesh) const {
-
- MultiMesh *multimesh = multimesh_owner.get(p_multimesh);
- ERR_FAIL_COND_V(!multimesh,RID());
-
- return multimesh->mesh;
-}
-AABB RasterizerDummy::multimesh_get_aabb(RID p_multimesh) const {
-
- MultiMesh *multimesh = multimesh_owner.get(p_multimesh);
- ERR_FAIL_COND_V(!multimesh,AABB());
-
- return multimesh->aabb;
-}
-
-Transform RasterizerDummy::multimesh_instance_get_transform(RID p_multimesh,int p_index) const {
-
- MultiMesh *multimesh = multimesh_owner.get(p_multimesh);
- ERR_FAIL_COND_V(!multimesh,Transform());
-
- ERR_FAIL_INDEX_V(p_index,multimesh->elements.size(),Transform());
-
- return multimesh->elements[p_index].xform;
-
-}
-Color RasterizerDummy::multimesh_instance_get_color(RID p_multimesh,int p_index) const {
-
- MultiMesh *multimesh = multimesh_owner.get(p_multimesh);
- ERR_FAIL_COND_V(!multimesh,Color());
- ERR_FAIL_INDEX_V(p_index,multimesh->elements.size(),Color());
-
- return multimesh->elements[p_index].color;
-}
-
-void RasterizerDummy::multimesh_set_visible_instances(RID p_multimesh,int p_visible) {
-
- MultiMesh *multimesh = multimesh_owner.get(p_multimesh);
- ERR_FAIL_COND(!multimesh);
- multimesh->visible=p_visible;
-
-}
-
-int RasterizerDummy::multimesh_get_visible_instances(RID p_multimesh) const {
-
- MultiMesh *multimesh = multimesh_owner.get(p_multimesh);
- ERR_FAIL_COND_V(!multimesh,-1);
- return multimesh->visible;
-
-}
-
-/* IMMEDIATE API */
-
-
-RID RasterizerDummy::immediate_create() {
-
- Immediate *im = memnew( Immediate );
- return immediate_owner.make_rid(im);
-
-}
-
-void RasterizerDummy::immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture){
-
-
-}
-void RasterizerDummy::immediate_vertex(RID p_immediate,const Vector3& p_vertex){
-
-
-}
-void RasterizerDummy::immediate_normal(RID p_immediate,const Vector3& p_normal){
-
-
-}
-void RasterizerDummy::immediate_tangent(RID p_immediate,const Plane& p_tangent){
-
-
-}
-void RasterizerDummy::immediate_color(RID p_immediate,const Color& p_color){
-
-
-}
-void RasterizerDummy::immediate_uv(RID p_immediate,const Vector2& tex_uv){
-
-
-}
-void RasterizerDummy::immediate_uv2(RID p_immediate,const Vector2& tex_uv){
-
-
-}
-
-void RasterizerDummy::immediate_end(RID p_immediate){
-
-
-}
-void RasterizerDummy::immediate_clear(RID p_immediate) {
-
-
-}
-
-AABB RasterizerDummy::immediate_get_aabb(RID p_immediate) const {
-
- return AABB(Vector3(-1,-1,-1),Vector3(2,2,2));
-}
-
-void RasterizerDummy::immediate_set_material(RID p_immediate,RID p_material) {
-
- Immediate *im = immediate_owner.get(p_immediate);
- ERR_FAIL_COND(!im);
- im->material=p_material;
-
-}
-
-RID RasterizerDummy::immediate_get_material(RID p_immediate) const {
-
- const Immediate *im = immediate_owner.get(p_immediate);
- ERR_FAIL_COND_V(!im,RID());
- return im->material;
-
-}
-
-/* PARTICLES API */
-
-RID RasterizerDummy::particles_create() {
-
- Particles *particles = memnew( Particles );
- ERR_FAIL_COND_V(!particles,RID());
- return particles_owner.make_rid(particles);
-}
-
-void RasterizerDummy::particles_set_amount(RID p_particles, int p_amount) {
-
- ERR_FAIL_COND(p_amount<1);
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- particles->data.amount=p_amount;
-
-}
-
-int RasterizerDummy::particles_get_amount(RID p_particles) const {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,-1);
- return particles->data.amount;
-
-}
-
-void RasterizerDummy::particles_set_emitting(RID p_particles, bool p_emitting) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- particles->data.emitting=p_emitting;;
-
-}
-bool RasterizerDummy::particles_is_emitting(RID p_particles) const {
-
- const Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,false);
- return particles->data.emitting;
-
-}
-
-void RasterizerDummy::particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- particles->data.visibility_aabb=p_visibility;
-
-}
-
-void RasterizerDummy::particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
-
- particles->data.emission_half_extents=p_half_extents;
-}
-Vector3 RasterizerDummy::particles_get_emission_half_extents(RID p_particles) const {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,Vector3());
-
- return particles->data.emission_half_extents;
-}
-
-void RasterizerDummy::particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
-
- particles->data.emission_base_velocity=p_base_velocity;
-}
-
-Vector3 RasterizerDummy::particles_get_emission_base_velocity(RID p_particles) const {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,Vector3());
-
- return particles->data.emission_base_velocity;
-}
-
-
-void RasterizerDummy::particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
-
- particles->data.emission_points=p_points;
-}
-
-DVector<Vector3> RasterizerDummy::particles_get_emission_points(RID p_particles) const {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,DVector<Vector3>());
-
- return particles->data.emission_points;
-
-}
-
-void RasterizerDummy::particles_set_gravity_normal(RID p_particles, const Vector3& p_normal) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
-
- particles->data.gravity_normal=p_normal;
-
-}
-Vector3 RasterizerDummy::particles_get_gravity_normal(RID p_particles) const {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,Vector3());
-
- return particles->data.gravity_normal;
-}
-
-
-AABB RasterizerDummy::particles_get_visibility_aabb(RID p_particles) const {
-
- const Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,AABB());
- return particles->data.visibility_aabb;
-
-}
-
-void RasterizerDummy::particles_set_variable(RID p_particles, VS::ParticleVariable p_variable,float p_value) {
-
- ERR_FAIL_INDEX(p_variable,VS::PARTICLE_VAR_MAX);
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- particles->data.particle_vars[p_variable]=p_value;
-
-}
-float RasterizerDummy::particles_get_variable(RID p_particles, VS::ParticleVariable p_variable) const {
-
- const Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,-1);
- return particles->data.particle_vars[p_variable];
-}
-
-void RasterizerDummy::particles_set_randomness(RID p_particles, VS::ParticleVariable p_variable,float p_randomness) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- particles->data.particle_randomness[p_variable]=p_randomness;
-
-}
-float RasterizerDummy::particles_get_randomness(RID p_particles, VS::ParticleVariable p_variable) const {
-
- const Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,-1);
- return particles->data.particle_randomness[p_variable];
-
-}
-
-void RasterizerDummy::particles_set_color_phases(RID p_particles, int p_phases) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- ERR_FAIL_COND( p_phases<0 || p_phases>VS::MAX_PARTICLE_COLOR_PHASES );
- particles->data.color_phase_count=p_phases;
-
-}
-int RasterizerDummy::particles_get_color_phases(RID p_particles) const {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,-1);
- return particles->data.color_phase_count;
-}
-
-
-void RasterizerDummy::particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos) {
-
- ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES);
- if (p_pos<0.0)
- p_pos=0.0;
- if (p_pos>1.0)
- p_pos=1.0;
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- particles->data.color_phases[p_phase].pos=p_pos;
-
-}
-float RasterizerDummy::particles_get_color_phase_pos(RID p_particles, int p_phase) const {
-
- ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, -1.0);
-
- const Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,-1);
- return particles->data.color_phases[p_phase].pos;
-
-}
-
-void RasterizerDummy::particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color) {
-
- ERR_FAIL_INDEX(p_phase, VS::MAX_PARTICLE_COLOR_PHASES);
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- particles->data.color_phases[p_phase].color=p_color;
-
- //update alpha
- particles->has_alpha=false;
- for(int i=0;i<VS::MAX_PARTICLE_COLOR_PHASES;i++) {
- if (particles->data.color_phases[i].color.a<0.99)
- particles->has_alpha=true;
- }
-
-}
-
-Color RasterizerDummy::particles_get_color_phase_color(RID p_particles, int p_phase) const {
-
- ERR_FAIL_INDEX_V(p_phase, VS::MAX_PARTICLE_COLOR_PHASES, Color());
-
- const Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,Color());
- return particles->data.color_phases[p_phase].color;
-
-}
-
-void RasterizerDummy::particles_set_attractors(RID p_particles, int p_attractors) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- ERR_FAIL_COND( p_attractors<0 || p_attractors>VisualServer::MAX_PARTICLE_ATTRACTORS );
- particles->data.attractor_count=p_attractors;
-
-}
-int RasterizerDummy::particles_get_attractors(RID p_particles) const {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,-1);
- return particles->data.attractor_count;
-}
-
-void RasterizerDummy::particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- ERR_FAIL_INDEX(p_attractor,particles->data.attractor_count);
- particles->data.attractors[p_attractor].pos=p_pos;;
-}
-Vector3 RasterizerDummy::particles_get_attractor_pos(RID p_particles,int p_attractor) const {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,Vector3());
- ERR_FAIL_INDEX_V(p_attractor,particles->data.attractor_count,Vector3());
- return particles->data.attractors[p_attractor].pos;
-}
-
-void RasterizerDummy::particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- ERR_FAIL_INDEX(p_attractor,particles->data.attractor_count);
- particles->data.attractors[p_attractor].force=p_force;
-}
-
-float RasterizerDummy::particles_get_attractor_strength(RID p_particles,int p_attractor) const {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,0);
- ERR_FAIL_INDEX_V(p_attractor,particles->data.attractor_count,0);
- return particles->data.attractors[p_attractor].force;
-}
-
-void RasterizerDummy::particles_set_material(RID p_particles, RID p_material,bool p_owned) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- if (particles->material_owned && particles->material.is_valid())
- free(particles->material);
-
- particles->material_owned=p_owned;
-
- particles->material=p_material;
-
-}
-RID RasterizerDummy::particles_get_material(RID p_particles) const {
-
- const Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,RID());
- return particles->material;
-
-}
-
-void RasterizerDummy::particles_set_use_local_coordinates(RID p_particles, bool p_enable) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- particles->data.local_coordinates=p_enable;
-
-}
-
-bool RasterizerDummy::particles_is_using_local_coordinates(RID p_particles) const {
-
- const Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,false);
- return particles->data.local_coordinates;
-}
-bool RasterizerDummy::particles_has_height_from_velocity(RID p_particles) const {
-
- const Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,false);
- return particles->data.height_from_velocity;
-}
-
-void RasterizerDummy::particles_set_height_from_velocity(RID p_particles, bool p_enable) {
-
- Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND(!particles);
- particles->data.height_from_velocity=p_enable;
-
-}
-
-AABB RasterizerDummy::particles_get_aabb(RID p_particles) const {
-
- const Particles* particles = particles_owner.get( p_particles );
- ERR_FAIL_COND_V(!particles,AABB());
- return particles->data.visibility_aabb;
-}
-
-/* SKELETON API */
-
-RID RasterizerDummy::skeleton_create() {
-
- Skeleton *skeleton = memnew( Skeleton );
- ERR_FAIL_COND_V(!skeleton,RID());
- return skeleton_owner.make_rid( skeleton );
-}
-void RasterizerDummy::skeleton_resize(RID p_skeleton,int p_bones) {
-
- Skeleton *skeleton = skeleton_owner.get( p_skeleton );
- ERR_FAIL_COND(!skeleton);
- if (p_bones == skeleton->bones.size()) {
- return;
- };
-
- skeleton->bones.resize(p_bones);
-
-}
-int RasterizerDummy::skeleton_get_bone_count(RID p_skeleton) const {
-
- Skeleton *skeleton = skeleton_owner.get( p_skeleton );
- ERR_FAIL_COND_V(!skeleton, -1);
- return skeleton->bones.size();
-}
-void RasterizerDummy::skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform) {
-
- Skeleton *skeleton = skeleton_owner.get( p_skeleton );
- ERR_FAIL_COND(!skeleton);
- ERR_FAIL_INDEX( p_bone, skeleton->bones.size() );
-
- skeleton->bones[p_bone] = p_transform;
-}
-
-Transform RasterizerDummy::skeleton_bone_get_transform(RID p_skeleton,int p_bone) {
-
- Skeleton *skeleton = skeleton_owner.get( p_skeleton );
- ERR_FAIL_COND_V(!skeleton, Transform());
- ERR_FAIL_INDEX_V( p_bone, skeleton->bones.size(), Transform() );
-
- // something
- return skeleton->bones[p_bone];
-}
-
-
-/* LIGHT API */
-
-RID RasterizerDummy::light_create(VS::LightType p_type) {
-
- Light *light = memnew( Light );
- light->type=p_type;
- return light_owner.make_rid(light);
-}
-
-VS::LightType RasterizerDummy::light_get_type(RID p_light) const {
-
- Light *light = light_owner.get(p_light);
- ERR_FAIL_COND_V(!light,VS::LIGHT_OMNI);
- return light->type;
-}
-
-void RasterizerDummy::light_set_color(RID p_light,VS::LightColor p_type, const Color& p_color) {
-
- Light *light = light_owner.get(p_light);
- ERR_FAIL_COND(!light);
- ERR_FAIL_INDEX( p_type, 3 );
- light->colors[p_type]=p_color;
-}
-Color RasterizerDummy::light_get_color(RID p_light,VS::LightColor p_type) const {
-
- Light *light = light_owner.get(p_light);
- ERR_FAIL_COND_V(!light, Color());
- ERR_FAIL_INDEX_V( p_type, 3, Color() );
- return light->colors[p_type];
-}
-
-void RasterizerDummy::light_set_shadow(RID p_light,bool p_enabled) {
-
- Light *light = light_owner.get(p_light);
- ERR_FAIL_COND(!light);
- light->shadow_enabled=p_enabled;
-}
-
-bool RasterizerDummy::light_has_shadow(RID p_light) const {
-
- Light *light = light_owner.get(p_light);
- ERR_FAIL_COND_V(!light,false);
- return light->shadow_enabled;
-}
-
-void RasterizerDummy::light_set_volumetric(RID p_light,bool p_enabled) {
-
- Light *light = light_owner.get(p_light);
- ERR_FAIL_COND(!light);
- light->volumetric_enabled=p_enabled;
-
-}
-bool RasterizerDummy::light_is_volumetric(RID p_light) const {
-
- Light *light = light_owner.get(p_light);
- ERR_FAIL_COND_V(!light,false);
- return light->volumetric_enabled;
-}
-
-void RasterizerDummy::light_set_projector(RID p_light,RID p_texture) {
-
- Light *light = light_owner.get(p_light);
- ERR_FAIL_COND(!light);
- light->projector=p_texture;
-}
-RID RasterizerDummy::light_get_projector(RID p_light) const {
-
- Light *light = light_owner.get(p_light);
- ERR_FAIL_COND_V(!light,RID());
- return light->projector;
-}
-
-void RasterizerDummy::light_set_var(RID p_light, VS::LightParam p_var, float p_value) {
-
- Light * light = light_owner.get( p_light );
- ERR_FAIL_COND(!light);
- ERR_FAIL_INDEX( p_var, VS::LIGHT_PARAM_MAX );
-
- light->vars[p_var]=p_value;
-}
-float RasterizerDummy::light_get_var(RID p_light, VS::LightParam p_var) const {
-
- Light * light = light_owner.get( p_light );
- ERR_FAIL_COND_V(!light,0);
-
- ERR_FAIL_INDEX_V( p_var, VS::LIGHT_PARAM_MAX,0 );
-
- return light->vars[p_var];
-}
-
-void RasterizerDummy::light_set_operator(RID p_light,VS::LightOp p_op) {
-
- Light * light = light_owner.get( p_light );
- ERR_FAIL_COND(!light);
-
-
-};
-
-VS::LightOp RasterizerDummy::light_get_operator(RID p_light) const {
-
- return VS::LightOp(0);
-};
-
-void RasterizerDummy::light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode) {
-
-
-}
-
-VS::LightOmniShadowMode RasterizerDummy::light_omni_get_shadow_mode(RID p_light) const{
-
- return VS::LightOmniShadowMode(0);
-}
-
-void RasterizerDummy::light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode) {
-
-
-}
-
-VS::LightDirectionalShadowMode RasterizerDummy::light_directional_get_shadow_mode(RID p_light) const {
-
- return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL;
-}
-
-void RasterizerDummy::light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value) {
-
-
-}
-
-float RasterizerDummy::light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const {
-
- return 0;
-}
-
-
-AABB RasterizerDummy::light_get_aabb(RID p_light) const {
-
- Light *light = light_owner.get( p_light );
- ERR_FAIL_COND_V(!light,AABB());
-
- switch( light->type ) {
-
- case VS::LIGHT_SPOT: {
-
- float len=light->vars[VS::LIGHT_PARAM_RADIUS];
- float size=Math::tan(Math::deg2rad(light->vars[VS::LIGHT_PARAM_SPOT_ANGLE]))*len;
- return AABB( Vector3( -size,-size,-len ), Vector3( size*2, size*2, len ) );
- } break;
- case VS::LIGHT_OMNI: {
-
- float r = light->vars[VS::LIGHT_PARAM_RADIUS];
- return AABB( -Vector3(r,r,r), Vector3(r,r,r)*2 );
- } break;
- case VS::LIGHT_DIRECTIONAL: {
-
- return AABB();
- } break;
- default: {}
- }
-
- ERR_FAIL_V( AABB() );
-}
-
-
-RID RasterizerDummy::light_instance_create(RID p_light) {
-
- Light *light = light_owner.get( p_light );
- ERR_FAIL_COND_V(!light, RID());
-
- LightInstance *light_instance = memnew( LightInstance );
-
- light_instance->light=p_light;
- light_instance->base=light;
-
-
- return light_instance_owner.make_rid( light_instance );
-}
-void RasterizerDummy::light_instance_set_transform(RID p_light_instance,const Transform& p_transform) {
-
- LightInstance *lighti = light_instance_owner.get( p_light_instance );
- ERR_FAIL_COND(!lighti);
- lighti->transform=p_transform;
-
-}
-
-bool RasterizerDummy::light_instance_has_shadow(RID p_light_instance) const {
-
- return false;
-
-}
-
-
-bool RasterizerDummy::light_instance_assign_shadow(RID p_light_instance) {
-
- return false;
-
-}
-
-
-Rasterizer::ShadowType RasterizerDummy::light_instance_get_shadow_type(RID p_light_instance) const {
-
- LightInstance *lighti = light_instance_owner.get( p_light_instance );
- ERR_FAIL_COND_V(!lighti,Rasterizer::SHADOW_NONE);
-
- switch(lighti->base->type) {
-
- case VS::LIGHT_DIRECTIONAL: return SHADOW_PSM; break;
- case VS::LIGHT_OMNI: return SHADOW_DUAL_PARABOLOID; break;
- case VS::LIGHT_SPOT: return SHADOW_SIMPLE; break;
- }
-
- return Rasterizer::SHADOW_NONE;
-}
-
-Rasterizer::ShadowType RasterizerDummy::light_instance_get_shadow_type(RID p_light_instance,bool p_far) const {
-
- return SHADOW_NONE;
-}
-void RasterizerDummy::light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) {
-
-
-}
-
-int RasterizerDummy::light_instance_get_shadow_passes(RID p_light_instance) const {
-
- return 0;
-}
-
-bool RasterizerDummy::light_instance_get_pssm_shadow_overlap(RID p_light_instance) const {
-
- return false;
-}
-
-
-void RasterizerDummy::light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near,float p_split_far) {
-
- LightInstance *lighti = light_instance_owner.get( p_light_instance );
- ERR_FAIL_COND(!lighti);
-
- ERR_FAIL_COND(lighti->base->type!=VS::LIGHT_DIRECTIONAL);
- ERR_FAIL_INDEX(p_index,1);
-
- lighti->custom_projection=p_camera;
- lighti->custom_transform=p_transform;
-
-}
-void RasterizerDummy::shadow_clear_near() {
-
-
-}
-
-bool RasterizerDummy::shadow_allocate_near(RID p_light) {
-
- return false;
-}
-
-bool RasterizerDummy::shadow_allocate_far(RID p_light) {
-
- return false;
-}
-
-/* PARTICLES INSTANCE */
-
-RID RasterizerDummy::particles_instance_create(RID p_particles) {
-
- ERR_FAIL_COND_V(!particles_owner.owns(p_particles),RID());
- ParticlesInstance *particles_instance = memnew( ParticlesInstance );
- ERR_FAIL_COND_V(!particles_instance, RID() );
- particles_instance->particles=p_particles;
- return particles_instance_owner.make_rid(particles_instance);
-}
-
-void RasterizerDummy::particles_instance_set_transform(RID p_particles_instance,const Transform& p_transform) {
-
- ParticlesInstance *particles_instance=particles_instance_owner.get(p_particles_instance);
- ERR_FAIL_COND(!particles_instance);
- particles_instance->transform=p_transform;
-}
-
-
-/* RENDER API */
-/* all calls (inside begin/end shadow) are always warranted to be in the following order: */
-
-
-RID RasterizerDummy::viewport_data_create() {
-
- return RID();
-}
-
-RID RasterizerDummy::render_target_create(){
-
- return RID();
-
-}
-void RasterizerDummy::render_target_set_size(RID p_render_target, int p_width, int p_height){
-
-
-}
-RID RasterizerDummy::render_target_get_texture(RID p_render_target) const{
-
- return RID();
-
-}
-bool RasterizerDummy::render_target_renedered_in_frame(RID p_render_target){
-
- return false;
-}
-
-
-void RasterizerDummy::begin_frame() {
-
-
-
-}
-
-void RasterizerDummy::capture_viewport(Image* r_capture) {
-
-
-}
-
-
-void RasterizerDummy::clear_viewport(const Color& p_color) {
-
-
-};
-
-void RasterizerDummy::set_viewport(const VS::ViewportRect& p_viewport) {
-
-
-
-}
-
-void RasterizerDummy::set_render_target(RID p_render_target, bool p_transparent_bg, bool p_vflip) {
-
-
-}
-
-
-void RasterizerDummy::begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug) {
-
-
-};
-
-void RasterizerDummy::begin_shadow_map( RID p_light_instance, int p_shadow_pass ) {
-
-}
-
-void RasterizerDummy::set_camera(const Transform& p_world, const CameraMatrix& p_projection, bool p_ortho_hint) {
-
-
-}
-
-void RasterizerDummy::add_light( RID p_light_instance ) {
-
-
-
-}
-
-
-
-
-void RasterizerDummy::add_mesh( const RID& p_mesh, const InstanceData *p_data) {
-
-
-}
-
-void RasterizerDummy::add_multimesh( const RID& p_multimesh, const InstanceData *p_data){
-
-
-
-
-}
-
-void RasterizerDummy::add_particles( const RID& p_particle_instance, const InstanceData *p_data){
-
-
-
-}
-
-
-
-void RasterizerDummy::end_scene() {
-
-
-}
-void RasterizerDummy::end_shadow_map() {
-
-}
-
-
-void RasterizerDummy::end_frame() {
-
-
-}
-
-RID RasterizerDummy::canvas_light_occluder_create() {
- return RID();
-}
-
-void RasterizerDummy::canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines) {
-
-
-}
-
-RID RasterizerDummy::canvas_light_shadow_buffer_create(int p_width) {
-
- return RID();
-}
-
-void RasterizerDummy::canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache) {
-
-
-}
-
-void RasterizerDummy::canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow) {
-
-
-}
-
-/* CANVAS API */
-
-
-void RasterizerDummy::begin_canvas_bg() {
-
-}
-void RasterizerDummy::canvas_begin() {
-
-
-
-}
-void RasterizerDummy::canvas_disable_blending() {
-
-
-
-}
-
-void RasterizerDummy::canvas_set_opacity(float p_opacity) {
-
-
-}
-
-void RasterizerDummy::canvas_set_blend_mode(VS::MaterialBlendMode p_mode) {
-
-
-}
-
-
-void RasterizerDummy::canvas_begin_rect(const Matrix32& p_transform) {
-
-
-
-}
-
-void RasterizerDummy::canvas_set_clip(bool p_clip, const Rect2& p_rect) {
-
-
-
-
-}
-
-void RasterizerDummy::canvas_end_rect() {
-
-
-}
-
-void RasterizerDummy::canvas_draw_line(const Point2& p_from, const Point2& p_to, const Color& p_color, float p_width, bool p_antialiased) {
-
-
-
-}
-
-void RasterizerDummy::canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate) {
-
-
-
-
-}
-void RasterizerDummy::canvas_draw_style_box(const Rect2& p_rect, const Rect2& p_src_region, RID p_texture,const float *p_margin, bool p_draw_center,const Color& p_modulate) {
-
-
-}
-void RasterizerDummy::canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width) {
-
-
-
-}
-
-
-void RasterizerDummy::canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor) {
-
-
-
-}
-
-void RasterizerDummy::canvas_set_transform(const Matrix32& p_transform) {
-
-
-}
-
-void RasterizerDummy::canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light) {
-
-
-}
-
-/* ENVIRONMENT */
-
-RID RasterizerDummy::environment_create() {
-
- Environment * env = memnew( Environment );
- return environment_owner.make_rid(env);
-}
-
-void RasterizerDummy::environment_set_background(RID p_env,VS::EnvironmentBG p_bg) {
-
- ERR_FAIL_INDEX(p_bg,VS::ENV_BG_MAX);
- Environment * env = environment_owner.get(p_env);
- ERR_FAIL_COND(!env);
- env->bg_mode=p_bg;
-}
-
-VS::EnvironmentBG RasterizerDummy::environment_get_background(RID p_env) const{
-
- const Environment * env = environment_owner.get(p_env);
- ERR_FAIL_COND_V(!env,VS::ENV_BG_MAX);
- return env->bg_mode;
-}
-
-void RasterizerDummy::environment_set_background_param(RID p_env,VS::EnvironmentBGParam p_param, const Variant& p_value){
-
- ERR_FAIL_INDEX(p_param,VS::ENV_BG_PARAM_MAX);
- Environment * env = environment_owner.get(p_env);
- ERR_FAIL_COND(!env);
- env->bg_param[p_param]=p_value;
-
-}
-Variant RasterizerDummy::environment_get_background_param(RID p_env,VS::EnvironmentBGParam p_param) const{
-
- ERR_FAIL_INDEX_V(p_param,VS::ENV_BG_PARAM_MAX,Variant());
- const Environment * env = environment_owner.get(p_env);
- ERR_FAIL_COND_V(!env,Variant());
- return env->bg_param[p_param];
-
-}
-
-void RasterizerDummy::environment_set_enable_fx(RID p_env,VS::EnvironmentFx p_effect,bool p_enabled){
-
- ERR_FAIL_INDEX(p_effect,VS::ENV_FX_MAX);
- Environment * env = environment_owner.get(p_env);
- ERR_FAIL_COND(!env);
- env->fx_enabled[p_effect]=p_enabled;
-}
-bool RasterizerDummy::environment_is_fx_enabled(RID p_env,VS::EnvironmentFx p_effect) const{
-
- ERR_FAIL_INDEX_V(p_effect,VS::ENV_FX_MAX,false);
- const Environment * env = environment_owner.get(p_env);
- ERR_FAIL_COND_V(!env,false);
- return env->fx_enabled[p_effect];
-
-}
-
-void RasterizerDummy::environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value){
-
- ERR_FAIL_INDEX(p_param,VS::ENV_FX_PARAM_MAX);
- Environment * env = environment_owner.get(p_env);
- ERR_FAIL_COND(!env);
- env->fx_param[p_param]=p_value;
-}
-Variant RasterizerDummy::environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const{
-
- ERR_FAIL_INDEX_V(p_param,VS::ENV_FX_PARAM_MAX,Variant());
- const Environment * env = environment_owner.get(p_env);
- ERR_FAIL_COND_V(!env,Variant());
- return env->fx_param[p_param];
-
-}
-
-
-RID RasterizerDummy::sampled_light_dp_create(int p_width,int p_height) {
-
- return sampled_light_owner.make_rid(memnew(SampledLight));
-}
-
-void RasterizerDummy::sampled_light_dp_update(RID p_sampled_light, const Color *p_data, float p_multiplier) {
-
-
-}
-
-
-/*MISC*/
-
-bool RasterizerDummy::is_texture(const RID& p_rid) const {
-
- return texture_owner.owns(p_rid);
-}
-bool RasterizerDummy::is_material(const RID& p_rid) const {
-
- return material_owner.owns(p_rid);
-}
-bool RasterizerDummy::is_mesh(const RID& p_rid) const {
-
- return mesh_owner.owns(p_rid);
-}
-
-bool RasterizerDummy::is_immediate(const RID& p_rid) const {
-
- return immediate_owner.owns(p_rid);
-}
-
-bool RasterizerDummy::is_multimesh(const RID& p_rid) const {
-
- return multimesh_owner.owns(p_rid);
-}
-bool RasterizerDummy::is_particles(const RID &p_beam) const {
-
- return particles_owner.owns(p_beam);
-}
-
-bool RasterizerDummy::is_light(const RID& p_rid) const {
-
- return light_owner.owns(p_rid);
-}
-bool RasterizerDummy::is_light_instance(const RID& p_rid) const {
-
- return light_instance_owner.owns(p_rid);
-}
-bool RasterizerDummy::is_particles_instance(const RID& p_rid) const {
-
- return particles_instance_owner.owns(p_rid);
-}
-bool RasterizerDummy::is_skeleton(const RID& p_rid) const {
-
- return skeleton_owner.owns(p_rid);
-}
-bool RasterizerDummy::is_environment(const RID& p_rid) const {
-
- return environment_owner.owns(p_rid);
-}
-
-bool RasterizerDummy::is_canvas_light_occluder(const RID& p_rid) const {
-
- return false;
-}
-
-bool RasterizerDummy::is_shader(const RID& p_rid) const {
-
- return false;
-}
-
-void RasterizerDummy::free(const RID& p_rid) {
-
- if (texture_owner.owns(p_rid)) {
-
- // delete the texture
- Texture *texture = texture_owner.get(p_rid);
- texture_owner.free(p_rid);
- memdelete(texture);
-
- } else if (shader_owner.owns(p_rid)) {
-
- // delete the texture
- Shader *shader = shader_owner.get(p_rid);
- shader_owner.free(p_rid);
- memdelete(shader);
-
- } else if (material_owner.owns(p_rid)) {
-
- Material *material = material_owner.get( p_rid );
- material_owner.free(p_rid);
- memdelete(material);
-
- } else if (mesh_owner.owns(p_rid)) {
-
- Mesh *mesh = mesh_owner.get(p_rid);
-
- for (int i=0;i<mesh->surfaces.size();i++) {
-
- memdelete( mesh->surfaces[i] );
- };
-
- mesh->surfaces.clear();
- mesh_owner.free(p_rid);
- memdelete(mesh);
-
- } else if (multimesh_owner.owns(p_rid)) {
-
- MultiMesh *multimesh = multimesh_owner.get(p_rid);
- multimesh_owner.free(p_rid);
- memdelete(multimesh);
-
- } else if (immediate_owner.owns(p_rid)) {
-
- Immediate *immediate = immediate_owner.get(p_rid);
- immediate_owner.free(p_rid);
- memdelete(immediate);
-
- } else if (particles_owner.owns(p_rid)) {
-
- Particles *particles = particles_owner.get(p_rid);
- particles_owner.free(p_rid);
- memdelete(particles);
- } else if (particles_instance_owner.owns(p_rid)) {
-
- ParticlesInstance *particles_isntance = particles_instance_owner.get(p_rid);
- particles_instance_owner.free(p_rid);
- memdelete(particles_isntance);
-
- } else if (skeleton_owner.owns(p_rid)) {
-
- Skeleton *skeleton = skeleton_owner.get( p_rid );
- skeleton_owner.free(p_rid);
- memdelete(skeleton);
-
- } else if (light_owner.owns(p_rid)) {
-
- Light *light = light_owner.get( p_rid );
- light_owner.free(p_rid);
- memdelete(light);
-
- } else if (light_instance_owner.owns(p_rid)) {
-
- LightInstance *light_instance = light_instance_owner.get( p_rid );
- light_instance_owner.free(p_rid);
- memdelete( light_instance );
-
-
- } else if (environment_owner.owns(p_rid)) {
-
- Environment *env = environment_owner.get( p_rid );
- environment_owner.free(p_rid);
- memdelete( env );
- } else if (sampled_light_owner.owns(p_rid)) {
-
- SampledLight *sampled_light = sampled_light_owner.get( p_rid );
- ERR_FAIL_COND(!sampled_light);
-
- sampled_light_owner.free(p_rid);
- memdelete( sampled_light );
-
- };
-}
-
-
-void RasterizerDummy::custom_shade_model_set_shader(int p_model, RID p_shader) {
-
-
-};
-
-RID RasterizerDummy::custom_shade_model_get_shader(int p_model) const {
-
- return RID();
-};
-
-void RasterizerDummy::custom_shade_model_set_name(int p_model, const String& p_name) {
-
-};
-
-String RasterizerDummy::custom_shade_model_get_name(int p_model) const {
-
- return String();
-};
-
-void RasterizerDummy::custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info) {
-
-};
-
-void RasterizerDummy::custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const {
-
-};
-
-
-
-void RasterizerDummy::init() {
-
-
-}
-
-void RasterizerDummy::finish() {
-
-
-}
-
-int RasterizerDummy::get_render_info(VS::RenderInfo p_info) {
-
- return 0;
-}
-
-bool RasterizerDummy::needs_to_draw_next_frame() const {
-
- return false;
-}
-
-
-bool RasterizerDummy::has_feature(VS::Features p_feature) const {
-
- return false;
-
-}
-
-void RasterizerDummy::restore_framebuffer() {
-
-}
-
-RasterizerDummy::RasterizerDummy() {
-
-};
-
-RasterizerDummy::~RasterizerDummy() {
-
-};
diff --git a/servers/visual/rasterizer_dummy.h b/servers/visual/rasterizer_dummy.h
deleted file mode 100644
index cac36eb6fc..0000000000
--- a/servers/visual/rasterizer_dummy.h
+++ /dev/null
@@ -1,791 +0,0 @@
-/*************************************************************************/
-/* rasterizer_dummy.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 RASTERIZER_DUMMY_H
-#define RASTERIZER_DUMMY_H
-
-#include "servers/visual/rasterizer.h"
-
-
-#include "image.h"
-#include "rid.h"
-#include "servers/visual_server.h"
-#include "list.h"
-#include "map.h"
-#include "camera_matrix.h"
-#include "sort.h"
-
-
-#include "servers/visual/particle_system_sw.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-class RasterizerDummy : public Rasterizer {
-
- struct Texture {
-
- uint32_t flags;
- int width,height;
- Image::Format format;
- Image image[6];
- Texture() {
-
- flags=width=height=0;
- format=Image::FORMAT_GRAYSCALE;
- }
-
- ~Texture() {
-
- }
- };
-
- mutable RID_Owner<Texture> texture_owner;
-
- struct Shader {
-
- String vertex_code;
- String fragment_code;
- String light_code;
- VS::ShaderMode mode;
- Map<StringName,Variant> params;
- int fragment_line;
- int vertex_line;
- int light_line;
- bool valid;
- bool has_alpha;
- bool use_world_transform;
-
- };
-
- mutable RID_Owner<Shader> shader_owner;
-
-
- struct Material {
-
- bool flags[VS::MATERIAL_FLAG_MAX];
-
- VS::MaterialDepthDrawMode depth_draw_mode;
-
- VS::MaterialBlendMode blend_mode;
-
- float line_width;
- float point_size;
-
- RID shader; // shader material
-
- Map<StringName,Variant> shader_params;
-
-
- Material() {
-
-
- for(int i=0;i<VS::MATERIAL_FLAG_MAX;i++)
- flags[i]=false;
- flags[VS::MATERIAL_FLAG_VISIBLE]=true;
-
- depth_draw_mode=VS::MATERIAL_DEPTH_DRAW_OPAQUE_ONLY;
- line_width=1;
- blend_mode=VS::MATERIAL_BLEND_MODE_MIX;
- point_size = 1.0;
-
- }
- };
- mutable RID_Owner<Material> material_owner;
-
- void _material_check_alpha(Material *p_material);
-
-
- struct Geometry {
-
- enum Type {
- GEOMETRY_INVALID,
- GEOMETRY_SURFACE,
- GEOMETRY_POLY,
- GEOMETRY_PARTICLES,
- GEOMETRY_MULTISURFACE,
- };
-
- Type type;
- RID material;
- bool has_alpha;
- bool material_owned;
-
- Geometry() { has_alpha=false; material_owned = false; }
- virtual ~Geometry() {};
- };
-
- struct GeometryOwner {
-
- virtual ~GeometryOwner() {}
- };
-
- class Mesh;
-
- struct Surface : public Geometry {
-
- Array data;
- Array morph_data;
-
- bool packed;
- bool alpha_sort;
- int morph_target_count;
- AABB aabb;
-
- VS::PrimitiveType primitive;
-
- uint32_t format;
- uint32_t morph_format;
-
- Surface() {
-
- packed=false;
- morph_target_count=0;
- material_owned=false;
- format=0;
- morph_format=0;
-
- primitive=VS::PRIMITIVE_POINTS;
- }
-
- ~Surface() {
-
- }
- };
-
-
- struct Mesh {
-
- bool active;
- Vector<Surface*> surfaces;
- int morph_target_count;
- VS::MorphTargetMode morph_target_mode;
- AABB custom_aabb;
-
- mutable uint64_t last_pass;
- Mesh() {
- morph_target_mode=VS::MORPH_MODE_NORMALIZED;
- morph_target_count=0;
- last_pass=0;
- active=false;
- }
- };
- mutable RID_Owner<Mesh> mesh_owner;
-
- struct MultiMesh;
-
- struct MultiMeshSurface : public Geometry {
-
- Surface *surface;
- MultiMeshSurface() { type=GEOMETRY_MULTISURFACE; }
- };
-
- struct MultiMesh : public GeometryOwner {
-
- struct Element {
-
- Transform xform;
- Color color;
- };
-
- AABB aabb;
- RID mesh;
- int visible;
-
- //IDirect3DVertexBuffer9* instance_buffer;
- Vector<Element> elements;
-
- MultiMesh() {
- visible=-1;
- }
-
-
- };
-
-
- mutable RID_Owner<MultiMesh> multimesh_owner;
-
- struct Immediate {
-
-
- RID material;
- int empty;
- };
-
- mutable RID_Owner<Immediate> immediate_owner;
-
- struct Particles : public Geometry {
-
- ParticleSystemSW data; // software particle system
-
- Particles() {
- type=GEOMETRY_PARTICLES;
-
- }
- };
-
- mutable RID_Owner<Particles> particles_owner;
-
- struct ParticlesInstance : public GeometryOwner {
-
- RID particles;
-
- ParticleSystemProcessSW particles_process;
- Transform transform;
-
- ParticlesInstance() { }
- };
-
- mutable RID_Owner<ParticlesInstance> particles_instance_owner;
- ParticleSystemDrawInfoSW particle_draw_info;
-
- struct Skeleton {
-
- Vector<Transform> bones;
-
- };
-
- mutable RID_Owner<Skeleton> skeleton_owner;
-
-
- struct Light {
-
- VS::LightType type;
- float vars[VS::LIGHT_PARAM_MAX];
- Color colors[3];
- bool shadow_enabled;
- RID projector;
- bool volumetric_enabled;
- Color volumetric_color;
-
-
- Light() {
-
- vars[VS::LIGHT_PARAM_SPOT_ATTENUATION]=1;
- vars[VS::LIGHT_PARAM_SPOT_ANGLE]=45;
- vars[VS::LIGHT_PARAM_ATTENUATION]=1.0;
- vars[VS::LIGHT_PARAM_ENERGY]=1.0;
- vars[VS::LIGHT_PARAM_RADIUS]=1.0;
- vars[VS::LIGHT_PARAM_SHADOW_Z_OFFSET]=0.05;
-
- colors[VS::LIGHT_COLOR_DIFFUSE]=Color(1,1,1);
- colors[VS::LIGHT_COLOR_SPECULAR]=Color(1,1,1);
- shadow_enabled=false;
- volumetric_enabled=false;
- }
- };
-
-
- struct Environment {
-
-
- VS::EnvironmentBG bg_mode;
- Variant bg_param[VS::ENV_BG_PARAM_MAX];
- bool fx_enabled[VS::ENV_FX_MAX];
- Variant fx_param[VS::ENV_FX_PARAM_MAX];
-
- Environment() {
-
- bg_mode=VS::ENV_BG_DEFAULT_COLOR;
- bg_param[VS::ENV_BG_PARAM_COLOR]=Color(0,0,0);
- bg_param[VS::ENV_BG_PARAM_TEXTURE]=RID();
- bg_param[VS::ENV_BG_PARAM_CUBEMAP]=RID();
- bg_param[VS::ENV_BG_PARAM_ENERGY]=1.0;
-
- for(int i=0;i<VS::ENV_FX_MAX;i++)
- fx_enabled[i]=false;
-
- fx_param[VS::ENV_FX_PARAM_GLOW_BLUR_PASSES]=1;
- fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM]=0.0;
- fx_param[VS::ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD]=0.5;
- fx_param[VS::ENV_FX_PARAM_DOF_BLUR_PASSES]=1;
- fx_param[VS::ENV_FX_PARAM_DOF_BLUR_BEGIN]=100.0;
- fx_param[VS::ENV_FX_PARAM_DOF_BLUR_RANGE]=10.0;
- fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE]=0.4;
- fx_param[VS::ENV_FX_PARAM_HDR_WHITE]=1.0;
- fx_param[VS::ENV_FX_PARAM_HDR_GLOW_TRESHOLD]=0.95;
- fx_param[VS::ENV_FX_PARAM_HDR_GLOW_SCALE]=0.2;
- fx_param[VS::ENV_FX_PARAM_HDR_MIN_LUMINANCE]=0.4;
- fx_param[VS::ENV_FX_PARAM_HDR_MAX_LUMINANCE]=8.0;
- fx_param[VS::ENV_FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED]=0.5;
- fx_param[VS::ENV_FX_PARAM_FOG_BEGIN]=100.0;
- fx_param[VS::ENV_FX_PARAM_FOG_ATTENUATION]=1.0;
- fx_param[VS::ENV_FX_PARAM_FOG_BEGIN_COLOR]=Color(0,0,0);
- fx_param[VS::ENV_FX_PARAM_FOG_END_COLOR]=Color(0,0,0);
- fx_param[VS::ENV_FX_PARAM_FOG_BG]=true;
- fx_param[VS::ENV_FX_PARAM_BCS_BRIGHTNESS]=1.0;
- fx_param[VS::ENV_FX_PARAM_BCS_CONTRAST]=1.0;
- fx_param[VS::ENV_FX_PARAM_BCS_SATURATION]=1.0;
-
-
- }
-
- };
-
- mutable RID_Owner<Environment> environment_owner;
-
- struct SampledLight {
-
- int w,h;
- };
-
- mutable RID_Owner<SampledLight> sampled_light_owner;
-
- struct ShadowBuffer;
-
- struct LightInstance {
-
- struct SplitInfo {
-
- CameraMatrix camera;
- Transform transform;
- float near;
- float far;
- };
-
- RID light;
- Light *base;
- Transform transform;
- CameraMatrix projection;
-
- Transform custom_transform;
- CameraMatrix custom_projection;
-
- Vector3 light_vector;
- Vector3 spot_vector;
- float linear_att;
-
-
- LightInstance() { linear_att=1.0; }
-
- };
-
- mutable RID_Owner<Light> light_owner;
- mutable RID_Owner<LightInstance> light_instance_owner;
-
-
- RID default_material;
-
-
-
-
-public:
-
- /* TEXTURE API */
-
- virtual RID texture_create();
- virtual void texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags=VS::TEXTURE_FLAGS_DEFAULT);
- virtual void texture_set_data(RID p_texture,const Image& p_image,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT);
- virtual Image texture_get_data(RID p_texture,VS::CubeMapSide p_cube_side=VS::CUBEMAP_LEFT) const;
- virtual void texture_set_flags(RID p_texture,uint32_t p_flags);
- virtual uint32_t texture_get_flags(RID p_texture) const;
- virtual Image::Format texture_get_format(RID p_texture) const;
- virtual uint32_t texture_get_width(RID p_texture) const;
- virtual uint32_t texture_get_height(RID p_texture) const;
- virtual bool texture_has_alpha(RID p_texture) const;
- virtual void texture_set_size_override(RID p_texture,int p_width, int p_height);
- virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const;
-
- virtual void texture_set_path(RID p_texture,const String& p_path) {}
- virtual String texture_get_path(RID p_texture) const { return String(); }
- virtual void texture_debug_usage(List<VS::TextureInfo> *r_info) {}
-
- virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable) {}
-
- /* SHADER API */
-
- virtual RID shader_create(VS::ShaderMode p_mode=VS::SHADER_MATERIAL);
-
- virtual void shader_set_mode(RID p_shader,VS::ShaderMode p_mode);
- virtual VS::ShaderMode shader_get_mode(RID p_shader) const;
-
- virtual void shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs=0,int p_fragment_ofs=0,int p_light_ofs=0);
- virtual String shader_get_fragment_code(RID p_shader) const;
- virtual String shader_get_vertex_code(RID p_shader) const;
- virtual String shader_get_light_code(RID p_shader) const;
-
- virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const;
-
-
- virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture);
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const;
-
- virtual Variant shader_get_default_param(RID p_shader, const StringName& p_name);
-
- /* COMMON MATERIAL API */
-
- virtual RID material_create();
-
- virtual void material_set_shader(RID p_shader_material, RID p_shader);
- virtual RID material_get_shader(RID p_shader_material) const;
-
- virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value);
- virtual Variant material_get_param(RID p_material, const StringName& p_param) const;
-
- virtual void material_set_flag(RID p_material, VS::MaterialFlag p_flag,bool p_enabled);
- virtual bool material_get_flag(RID p_material,VS::MaterialFlag p_flag) const;
-
- virtual void material_set_depth_draw_mode(RID p_material, VS::MaterialDepthDrawMode p_mode);
- virtual VS::MaterialDepthDrawMode material_get_depth_draw_mode(RID p_material) const;
-
- virtual void material_set_blend_mode(RID p_material,VS::MaterialBlendMode p_mode);
- virtual VS::MaterialBlendMode material_get_blend_mode(RID p_material) const;
-
- virtual void material_set_line_width(RID p_material,float p_line_width);
- virtual float material_get_line_width(RID p_material) const;
-
- /* MESH API */
-
-
- virtual RID mesh_create();
-
- virtual void mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),bool p_alpha_sort=false);
- virtual Array mesh_get_surface_arrays(RID p_mesh,int p_surface) const;
- virtual Array mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const;
- virtual void mesh_add_custom_surface(RID p_mesh,const Variant& p_dat);
-
- virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount);
- virtual int mesh_get_morph_target_count(RID p_mesh) const;
-
- virtual void mesh_set_morph_target_mode(RID p_mesh,VS::MorphTargetMode p_mode);
- virtual VS::MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const;
-
- virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned=false);
- virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const;
-
- virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const;
- virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const;
- virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const;
- virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const;
-
- virtual void mesh_remove_surface(RID p_mesh,int p_index);
- virtual int mesh_get_surface_count(RID p_mesh) const;
-
- virtual AABB mesh_get_aabb(RID p_mesh,RID p_skeleton=RID()) const;
-
- virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb);
- virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
-
-
- /* MULTIMESH API */
-
- virtual RID multimesh_create();
-
- virtual void multimesh_set_instance_count(RID p_multimesh,int p_count);
- virtual int multimesh_get_instance_count(RID p_multimesh) const;
-
- virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh);
- virtual void multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb);
- virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform);
- virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color);
-
- virtual RID multimesh_get_mesh(RID p_multimesh) const;
- virtual AABB multimesh_get_aabb(RID p_multimesh) const;;
-
- virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const;
- virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const;
-
- virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible);
- virtual int multimesh_get_visible_instances(RID p_multimesh) const;
-
- /* IMMEDIATE API */
-
- virtual RID immediate_create();
- virtual void immediate_begin(RID p_immediate,VS::PrimitiveType p_rimitive,RID p_texture=RID());
- virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex);
- virtual void immediate_normal(RID p_immediate,const Vector3& p_normal);
- virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent);
- virtual void immediate_color(RID p_immediate,const Color& p_color);
- virtual void immediate_uv(RID p_immediate,const Vector2& tex_uv);
- virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv);
- virtual void immediate_end(RID p_immediate);
- virtual void immediate_clear(RID p_immediate);
- virtual void immediate_set_material(RID p_immediate,RID p_material);
- virtual RID immediate_get_material(RID p_immediate) const;
-
- virtual AABB immediate_get_aabb(RID p_mesh) const;
-
- /* PARTICLES API */
-
- virtual RID particles_create();
-
- virtual void particles_set_amount(RID p_particles, int p_amount);
- virtual int particles_get_amount(RID p_particles) const;
-
- virtual void particles_set_emitting(RID p_particles, bool p_emitting);
- virtual bool particles_is_emitting(RID p_particles) const;
-
- virtual void particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility);
- virtual AABB particles_get_visibility_aabb(RID p_particles) const;
-
- virtual void particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents);
- virtual Vector3 particles_get_emission_half_extents(RID p_particles) const;
-
- virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity);
- virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const;
-
- virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points);
- virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const;
-
- virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal);
- virtual Vector3 particles_get_gravity_normal(RID p_particles) const;
-
- virtual void particles_set_variable(RID p_particles, VS::ParticleVariable p_variable,float p_value);
- virtual float particles_get_variable(RID p_particles, VS::ParticleVariable p_variable) const;
-
- virtual void particles_set_randomness(RID p_particles, VS::ParticleVariable p_variable,float p_randomness);
- virtual float particles_get_randomness(RID p_particles, VS::ParticleVariable p_variable) const;
-
- virtual void particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos);
- virtual float particles_get_color_phase_pos(RID p_particles, int p_phase) const;
-
- virtual void particles_set_color_phases(RID p_particles, int p_phases);
- virtual int particles_get_color_phases(RID p_particles) const;
-
- virtual void particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color);
- virtual Color particles_get_color_phase_color(RID p_particles, int p_phase) const;
-
- virtual void particles_set_attractors(RID p_particles, int p_attractors);
- virtual int particles_get_attractors(RID p_particles) const;
-
- virtual void particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos);
- virtual Vector3 particles_get_attractor_pos(RID p_particles,int p_attractor) const;
-
- virtual void particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force);
- virtual float particles_get_attractor_strength(RID p_particles,int p_attractor) const;
-
- virtual void particles_set_material(RID p_particles, RID p_material,bool p_owned=false);
- virtual RID particles_get_material(RID p_particles) const;
-
- virtual AABB particles_get_aabb(RID p_particles) const;
-
- virtual void particles_set_height_from_velocity(RID p_particles, bool p_enable);
- virtual bool particles_has_height_from_velocity(RID p_particles) const;
-
- virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable);
- virtual bool particles_is_using_local_coordinates(RID p_particles) const;
-
- /* SKELETON API */
-
- virtual RID skeleton_create();
- virtual void skeleton_resize(RID p_skeleton,int p_bones);
- virtual int skeleton_get_bone_count(RID p_skeleton) const;
- virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform);
- virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone);
-
-
- /* LIGHT API */
-
- virtual RID light_create(VS::LightType p_type);
- virtual VS::LightType light_get_type(RID p_light) const;
-
- virtual void light_set_color(RID p_light,VS::LightColor p_type, const Color& p_color);
- virtual Color light_get_color(RID p_light,VS::LightColor p_type) const;
-
- virtual void light_set_shadow(RID p_light,bool p_enabled);
- virtual bool light_has_shadow(RID p_light) const;
-
- virtual void light_set_volumetric(RID p_light,bool p_enabled);
- virtual bool light_is_volumetric(RID p_light) const;
-
- virtual void light_set_projector(RID p_light,RID p_texture);
- virtual RID light_get_projector(RID p_light) const;
-
- virtual void light_set_var(RID p_light, VS::LightParam p_var, float p_value);
- virtual float light_get_var(RID p_light, VS::LightParam p_var) const;
-
- virtual void light_set_operator(RID p_light,VS::LightOp p_op);
- virtual VS::LightOp light_get_operator(RID p_light) const;
-
- virtual void light_omni_set_shadow_mode(RID p_light,VS::LightOmniShadowMode p_mode);
- virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) const;
-
-
- virtual void light_directional_set_shadow_mode(RID p_light,VS::LightDirectionalShadowMode p_mode);
- virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) const;
- virtual void light_directional_set_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param, float p_value);
- virtual float light_directional_get_shadow_param(RID p_light,VS::LightDirectionalShadowParam p_param) const;
-
- virtual AABB light_get_aabb(RID p_poly) const;
-
-
- virtual RID light_instance_create(RID p_light);
- virtual void light_instance_set_transform(RID p_light_instance,const Transform& p_transform);
-
- virtual bool light_instance_has_shadow(RID p_light_instance) const;
- virtual bool light_instance_assign_shadow(RID p_light_instance);
- virtual ShadowType light_instance_get_shadow_type(RID p_light_instance) const;
- virtual int light_instance_get_shadow_passes(RID p_light_instance) const;
- virtual bool light_instance_get_pssm_shadow_overlap(RID p_light_instance) const;
- virtual void light_instance_set_custom_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0);
- virtual int light_instance_get_shadow_size(RID p_light_instance, int p_index=0) const { return 1; }
-
- virtual ShadowType light_instance_get_shadow_type(RID p_light_instance,bool p_far=false) const;
- virtual void light_instance_set_shadow_transform(RID p_light_instance, int p_index, const CameraMatrix& p_camera, const Transform& p_transform, float p_split_near=0,float p_split_far=0);
-
- virtual void shadow_clear_near();
- virtual bool shadow_allocate_near(RID p_light);
- virtual bool shadow_allocate_far(RID p_light);
-
-
- /* PARTICLES INSTANCE */
-
- virtual RID particles_instance_create(RID p_particles);
- virtual void particles_instance_set_transform(RID p_particles_instance,const Transform& p_transform);
-
- /* VIEWPORT */
-
- virtual RID viewport_data_create();
-
- virtual RID render_target_create();
- virtual void render_target_set_size(RID p_render_target, int p_width, int p_height);
- virtual RID render_target_get_texture(RID p_render_target) const;
- virtual bool render_target_renedered_in_frame(RID p_render_target);
-
- /* RENDER API */
- /* all calls (inside begin/end shadow) are always warranted to be in the following order: */
-
- virtual void begin_frame();
-
- virtual void set_viewport(const VS::ViewportRect& p_viewport);
- virtual void set_render_target(RID p_render_target,bool p_transparent_bg=false,bool p_vflip=false);
- virtual void clear_viewport(const Color& p_color);
- virtual void capture_viewport(Image* r_capture);
-
-
- virtual void begin_scene(RID p_viewport_data,RID p_env,VS::ScenarioDebugMode p_debug);
- virtual void begin_shadow_map( RID p_light_instance, int p_shadow_pass );
-
- virtual void set_camera(const Transform& p_world,const CameraMatrix& p_projection,bool p_ortho_hint);
-
- virtual void add_light( RID p_light_instance ); ///< all "add_light" calls happen before add_geometry calls
-
-
- virtual void add_mesh( const RID& p_mesh, const InstanceData *p_data);
- virtual void add_multimesh( const RID& p_multimesh, const InstanceData *p_data);
- virtual void add_immediate( const RID& p_immediate, const InstanceData *p_data) {}
- virtual void add_particles( const RID& p_particle_instance, const InstanceData *p_data);
-
- virtual void end_scene();
- virtual void end_shadow_map();
-
- virtual void end_frame();
-
- /* CANVAS API */
-
- virtual void begin_canvas_bg();
- virtual void canvas_begin();
- virtual void canvas_disable_blending();
- virtual void canvas_set_opacity(float p_opacity);
- virtual void canvas_set_blend_mode(VS::MaterialBlendMode p_mode);
- virtual void canvas_begin_rect(const Matrix32& p_transform);
- virtual void canvas_set_clip(bool p_clip, const Rect2& p_rect);
- virtual void canvas_end_rect();
- virtual void canvas_draw_line(const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width,bool p_antialiased);
- virtual void canvas_draw_rect(const Rect2& p_rect, int p_flags, const Rect2& p_source,RID p_texture,const Color& p_modulate);
- virtual void canvas_draw_style_box(const Rect2& p_rect, const Rect2& p_src_region, RID p_texture,const float *p_margins, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1));
- virtual void canvas_draw_primitive(const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width);
- virtual void canvas_draw_polygon(int p_vertex_count, const int* p_indices, const Vector2* p_vertices, const Vector2* p_uvs, const Color* p_colors,const RID& p_texture,bool p_singlecolor);
- virtual void canvas_set_transform(const Matrix32& p_transform);
-
- virtual void canvas_render_items(CanvasItem *p_item_list,int p_z,const Color& p_modulate,CanvasLight *p_light);
-
- virtual RID canvas_light_occluder_create();
- virtual void canvas_light_occluder_set_polylines(RID p_occluder, const DVector<Vector2>& p_lines);
-
- virtual RID canvas_light_shadow_buffer_create(int p_width);
- virtual void canvas_light_shadow_buffer_update(RID p_buffer, const Matrix32& p_light_xform, int p_light_mask,float p_near, float p_far, CanvasLightOccluderInstance* p_occluders, CameraMatrix *p_xform_cache);
-
- virtual void canvas_debug_viewport_shadows(CanvasLight* p_lights_with_shadow);
-
- /* ENVIRONMENT */
-
- virtual RID environment_create();
-
- virtual void environment_set_background(RID p_env,VS::EnvironmentBG p_bg);
- virtual VS::EnvironmentBG environment_get_background(RID p_env) const;
-
- virtual void environment_set_background_param(RID p_env,VS::EnvironmentBGParam p_param, const Variant& p_value);
- virtual Variant environment_get_background_param(RID p_env,VS::EnvironmentBGParam p_param) const;
-
- virtual void environment_set_enable_fx(RID p_env,VS::EnvironmentFx p_effect,bool p_enabled);
- virtual bool environment_is_fx_enabled(RID p_env,VS::EnvironmentFx p_effect) const;
-
- virtual void environment_fx_set_param(RID p_env,VS::EnvironmentFxParam p_param,const Variant& p_value);
- virtual Variant environment_fx_get_param(RID p_env,VS::EnvironmentFxParam p_param) const;
-
- /* SAMPLED LIGHT */
- virtual RID sampled_light_dp_create(int p_width,int p_height);
- virtual void sampled_light_dp_update(RID p_sampled_light,const Color *p_data,float p_multiplier);
-
-
- /*MISC*/
-
- virtual bool is_texture(const RID& p_rid) const;
- virtual bool is_material(const RID& p_rid) const;
- virtual bool is_mesh(const RID& p_rid) const;
- virtual bool is_immediate(const RID& p_rid) const;
- virtual bool is_multimesh(const RID& p_rid) const;
- virtual bool is_particles(const RID &p_beam) const;
-
- virtual bool is_light(const RID& p_rid) const;
- virtual bool is_light_instance(const RID& p_rid) const;
- virtual bool is_particles_instance(const RID& p_rid) const;
- virtual bool is_skeleton(const RID& p_rid) const;
- virtual bool is_environment(const RID& p_rid) const;
- virtual bool is_canvas_light_occluder(const RID& p_rid) const;
-
- virtual bool is_shader(const RID& p_rid) const;
-
- virtual void free(const RID& p_rid);
-
- virtual void custom_shade_model_set_shader(int p_model, RID p_shader);
- virtual RID custom_shade_model_get_shader(int p_model) const;
- virtual void custom_shade_model_set_name(int p_model, const String& p_name);
- virtual String custom_shade_model_get_name(int p_model) const;
- virtual void custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info);
- virtual void custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const;
-
-
- virtual void init();
- virtual void finish();
-
- virtual int get_render_info(VS::RenderInfo p_info);
-
- virtual bool needs_to_draw_next_frame() const;
-
- virtual bool has_feature(VS::Features p_feature) const;
-
- virtual void restore_framebuffer();
-
- RasterizerDummy();
- virtual ~RasterizerDummy();
-};
-
-
-#endif // RASTERIZER_DUMMY_H
diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp
index 09b3ada509..7dfd9822f7 100644
--- a/servers/visual/shader_language.cpp
+++ b/servers/visual/shader_language.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -44,14 +44,71 @@ static bool _is_hex(CharType c) {
return (c>='0' && c<='9') || (c>='a' && c<='f') || (c>='A' && c<='F');
}
+
+String ShaderLanguage::get_operator_text(Operator p_op) {
+
+ static const char* op_names[OP_MAX]={"==",
+ "!=",
+ "<",
+ "<=",
+ ">",
+ ">=",
+ "&&",
+ "||",
+ "!",
+ "-",
+ "+",
+ "-",
+ "*",
+ "/",
+ "%",
+ "<<",
+ ">>",
+ "=",
+ "+=",
+ "-=",
+ "*=",
+ "/=",
+ "%=",
+ "<<=",
+ ">>=",
+ "&=",
+ "|=",
+ "^=",
+ "&",
+ "|",
+ "^",
+ "~",
+ "++"
+ "--",
+ "()",
+ "construct"};
+
+ return op_names[p_op];
+
+}
+
+
const char * ShaderLanguage::token_names[TK_MAX]={
"EMPTY",
- "INDENTIFIER",
+ "IDENTIFIER",
"TRUE",
"FALSE",
"REAL_CONSTANT",
+ "INT_CONSTANT",
"TYPE_VOID",
"TYPE_BOOL",
+ "TYPE_BVEC2",
+ "TYPE_BVEC3",
+ "TYPE_BVEC4",
+ "TYPE_INT",
+ "TYPE_IVEC2",
+ "TYPE_IVEC3",
+ "TYPE_IVEC4",
+ "TYPE_UINT",
+ "TYPE_UVEC2",
+ "TYPE_UVEC3",
+ "TYPE_UVEC4",
"TYPE_FLOAT",
"TYPE_VEC2",
"TYPE_VEC3",
@@ -59,9 +116,13 @@ const char * ShaderLanguage::token_names[TK_MAX]={
"TYPE_MAT2",
"TYPE_MAT3",
"TYPE_MAT4",
- "TYPE_TEXTURE",
- "TYPE_CUBEMAP",
- "TYPE_COLOR",
+ "TYPE_SAMPLER2D",
+ "TYPE_ISAMPLER2D",
+ "TYPE_USAMPLER2D",
+ "TYPE_SAMPLERCUBE",
+ "PRECISION_LOW",
+ "PRECISION_MID",
+ "PRECISION_HIGH",
"OP_EQUAL",
"OP_NOT_EQUAL",
"OP_LESS",
@@ -75,14 +136,35 @@ const char * ShaderLanguage::token_names[TK_MAX]={
"OP_SUB",
"OP_MUL",
"OP_DIV",
- "OP_NEG",
+ "OP_MOD",
+ "OP_SHIFT_LEFT",
+ "OP_SHIFT_RIGHT",
"OP_ASSIGN",
"OP_ASSIGN_ADD",
"OP_ASSIGN_SUB",
"OP_ASSIGN_MUL",
"OP_ASSIGN_DIV",
+ "OP_ASSIGN_MOD",
+ "OP_ASSIGN_SHIFT_LEFT",
+ "OP_ASSIGN_SHIFT_RIGHT",
+ "OP_ASSIGN_BIT_AND",
+ "OP_ASSIGN_BIT_OR",
+ "OP_ASSIGN_BIT_XOR",
+ "OP_BIT_AND",
+ "OP_BIT_OR",
+ "OP_BIT_XOR",
+ "OP_BIT_INVERT",
+ "OP_INCREMENT",
+ "OP_DECREMENT",
"CF_IF",
"CF_ELSE",
+ "CF_FOR",
+ "CF_WHILE",
+ "CF_DO",
+ "CF_SWITCH",
+ "CF_CASE",
+ "CF_BREAK",
+ "CF_CONTINUE",
"CF_RETURN",
"BRACKET_OPEN",
"BRACKET_CLOSE",
@@ -90,460 +172,504 @@ const char * ShaderLanguage::token_names[TK_MAX]={
"CURLY_BRACKET_CLOSE",
"PARENTHESIS_OPEN",
"PARENTHESIS_CLOSE",
+ "QUESTION",
"COMMA",
+ "COLON",
"SEMICOLON",
"PERIOD",
"UNIFORM",
+ "VARYING",
+ "RENDER_MODE",
+ "HINT_WHITE_TEXTURE",
+ "HINT_BLACK_TEXTURE",
+ "HINT_NORMAL_TEXTURE",
+ "HINT_ANISO_TEXTURE",
+ "HINT_ALBEDO_TEXTURE",
+ "HINT_BLACK_ALBEDO_TEXTURE",
+ "HINT_COLOR",
+ "HINT_RANGE",
+ "CURSOR",
"ERROR",
+ "EOF",
};
-ShaderLanguage::Token ShaderLanguage::read_token(const CharType* p_text,int p_len,int &r_line,int &r_chars) {
+String ShaderLanguage::get_token_text(Token p_token) {
-#define GETCHAR(m_idx) ((m_idx<p_len)?p_text[m_idx]:CharType(0))
+ String name=token_names[p_token.type];
+ if (p_token.type==TK_INT_CONSTANT || p_token.type==TK_REAL_CONSTANT) {
+ name+="("+rtos(p_token.constant)+")";
+ } else if (p_token.type==TK_IDENTIFIER) {
+ name+="("+String(p_token.text)+")";
+ } else if (p_token.type==TK_ERROR) {
+ name+="("+String(p_token.text)+")";
+ }
- r_chars=1; //by default everything eats one char
- switch(GETCHAR(0)) {
+ return name;
+}
- case '\t':
- case '\r':
- case ' ':
- return Token();
- case '\n':
- r_line++;
- return Token();
- case '/': {
+ShaderLanguage::Token ShaderLanguage::_make_token(TokenType p_type,const StringName& p_text) {
- switch(GETCHAR(1)) {
- case '*': { // block comment
+ Token tk;
+ tk.type=p_type;
+ tk.text=p_text;
+ tk.line=tk_line;
+ if (tk.type==TK_ERROR) {
+ _set_error(p_text);
+ }
+ return tk;
+}
+const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[]={
+ {TK_TRUE,"true"},
+ {TK_FALSE,"false"},
+ {TK_TYPE_VOID,"void"},
+ {TK_TYPE_BOOL,"bool"},
+ {TK_TYPE_BVEC2,"bvec2"},
+ {TK_TYPE_BVEC3,"bvec3"},
+ {TK_TYPE_BVEC4,"bvec4"},
+ {TK_TYPE_INT,"int"},
+ {TK_TYPE_IVEC2,"ivec2"},
+ {TK_TYPE_IVEC3,"ivec3"},
+ {TK_TYPE_IVEC4,"ivec4"},
+ {TK_TYPE_UINT,"uint"},
+ {TK_TYPE_UVEC2,"uvec2"},
+ {TK_TYPE_UVEC3,"uvec3"},
+ {TK_TYPE_UVEC4,"uvec4"},
+ {TK_TYPE_FLOAT,"float"},
+ {TK_TYPE_VEC2,"vec2"},
+ {TK_TYPE_VEC3,"vec3"},
+ {TK_TYPE_VEC4,"vec4"},
+ {TK_TYPE_MAT2,"mat2"},
+ {TK_TYPE_MAT3,"mat3"},
+ {TK_TYPE_MAT4,"mat4"},
+ {TK_TYPE_SAMPLER2D,"sampler2D"},
+ {TK_TYPE_ISAMPLER2D,"isampler2D"},
+ {TK_TYPE_USAMPLER2D,"usampler2D"},
+ {TK_TYPE_SAMPLERCUBE,"samplerCube"},
+ {TK_PRECISION_LOW,"lowp"},
+ {TK_PRECISION_MID,"mediump"},
+ {TK_PRECISION_HIGH,"highp"},
+ {TK_CF_IF,"if"},
+ {TK_CF_ELSE,"else"},
+ {TK_CF_FOR,"for"},
+ {TK_CF_WHILE,"while"},
+ {TK_CF_DO,"do"},
+ {TK_CF_SWITCH,"switch"},
+ {TK_CF_CASE,"case"},
+ {TK_CF_BREAK,"break"},
+ {TK_CF_CONTINUE,"continue"},
+ {TK_CF_RETURN,"return"},
+ {TK_UNIFORM,"uniform"},
+ {TK_VARYING,"varying"},
+ {TK_RENDER_MODE,"render_mode"},
+ {TK_HINT_WHITE_TEXTURE,"hint_white"},
+ {TK_HINT_BLACK_TEXTURE,"hint_black"},
+ {TK_HINT_NORMAL_TEXTURE,"hint_normal"},
+ {TK_HINT_ANISO_TEXTURE,"hint_aniso"},
+ {TK_HINT_ALBEDO_TEXTURE,"hint_albedo"},
+ {TK_HINT_BLACK_ALBEDO_TEXTURE,"hint_black_albedo"},
+ {TK_HINT_COLOR,"hint_color"},
+ {TK_HINT_RANGE,"hint_range"},
+
+ {TK_ERROR,NULL}
+};
- while(true) {
- if (GETCHAR(r_chars+1)==0) {
- r_chars+=1;
- break;
- } if (GETCHAR(r_chars+1)=='*' && GETCHAR(r_chars+2)=='/') {
- r_chars+=3;
- break;
- } if (GETCHAR(r_chars+1)=='\n') {
- r_line++;
- }
- r_chars++;
- }
- return Token();
+ShaderLanguage::Token ShaderLanguage::_get_token() {
- } break;
- case '/': { // line comment skip
+#define GETCHAR(m_idx) (((char_idx+m_idx)<code.length())?code[char_idx+m_idx]:CharType(0))
- while(GETCHAR(r_chars+1)!='\n' && GETCHAR(r_chars+1)!=0) {
- r_chars++;
- }
- r_chars++;
- //r_line++;
-
- return Token();
+ while(true) {
+ char_idx++;
+ switch(GETCHAR(-1)) {
+
+ case 0:
+ return _make_token(TK_EOF);
+ case 0xFFFF:
+ return _make_token(TK_CURSOR); //for completion
+ case '\t':
+ case '\r':
+ case ' ':
+ continue;
+ case '\n':
+ tk_line++;
+ continue;
+ case '/': {
- } break;
- case '=': { // diveq
+ switch(GETCHAR(0)) {
+ case '*': { // block comment
- r_chars=2;
- return Token(TK_OP_ASSIGN_DIV);
+ char_idx++;
+ while(true) {
+ if (GETCHAR(0)==0) {
+ return _make_token(TK_EOF);
+ } if (GETCHAR(0)=='*' && GETCHAR(1)=='/') {
+ char_idx+=2;
+ break;
+ } if (GETCHAR(0)=='\n') {
+ tk_line++;
+ }
- } break;
- default:
- return Token(TK_OP_DIV);
+ char_idx++;
+ }
- }
- } break;
- case '=': {
- if (GETCHAR(1)=='=') {
- r_chars++;
- return Token(TK_OP_EQUAL);
- }
+ } break;
+ case '/': { // line comment skip
- return Token(TK_OP_ASSIGN);
- } break;
- case '<': {
- if (GETCHAR(1)=='=') {
- r_chars++;
- return Token(TK_OP_LESS_EQUAL);
- } /*else if (GETCHAR(1)=='<') {
- r_chars++;
- if (GETCHAR(2)=='=') {
- r_chars++;
- return Token(TK_OP_ASSIGN_SHIFT_LEFT);
- }
+ while(true) {
+ if (GETCHAR(0)=='\n') {
+ char_idx++;
+ break;
+ }
+ if (GETCHAR(0)==0) {
+ return _make_token(TK_EOF);
+ }
+ char_idx++;
+ }
- return Token(TK_OP_SHIFT_LEFT);
- }*/
+ } break;
+ case '=': { // diveq
- return Token(TK_OP_LESS);
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_DIV);
- } break;
- case '>': {
- if (GETCHAR(1)=='=') {
- r_chars++;
- return Token(TK_OP_GREATER_EQUAL);
- }/* else if (GETCHAR(1)=='<') {
- r_chars++;
- if (GETCHAR(2)=='=') {
- r_chars++;
- return Token(TK_OP_ASSIGN_SHIFT_RIGHT);
+ } break;
+ default:
+ return _make_token(TK_OP_DIV);
}
- return Token(TK_OP_SHIFT_RIGHT);
- }*/
-
- return Token(TK_OP_GREATER);
-
- } break;
- case '!': {
- if (GETCHAR(1)=='=') {
- r_chars++;
- return Token(TK_OP_NOT_EQUAL);
- }
+ continue; //a comment, continue to next token
+ } break;
+ case '=': {
- return Token(TK_OP_NOT);
-
- } break;
- //case '"' //string - no strings in shader
- //case '\'' //string - no strings in shader
- case '{':
- return Token(TK_CURLY_BRACKET_OPEN);
- case '}':
- return Token(TK_CURLY_BRACKET_CLOSE);
- //case '[':
- // return Token(TK_BRACKET_OPEN);
- //case ']':
- // return Token(TK_BRACKET_CLOSE);
- case '(':
- return Token(TK_PARENTHESIS_OPEN);
- case ')':
- return Token(TK_PARENTHESIS_CLOSE);
- case ',':
- return Token(TK_COMMA);
- case ';':
- return Token(TK_SEMICOLON);
- //case '?':
- // return Token(TK_QUESTION_MARK);
- //case ':':
- // return Token(TK_COLON); //for methods maybe but now useless.
- //case '^':
- // return Token(TK_OP_BIT_XOR);
- //case '~':
- // return Token(TK_OP_BIT_INVERT);
- case '&': {
-
- if (GETCHAR(1)=='&') {
-
- r_chars++;
- return Token(TK_OP_AND);
- }
-
- return Token(TK_ERROR,"Unknown character");
-
-/*
- if (GETCHAR(1)=='=') {
- r_chars++;
- return Token(TK_OP_ASSIGN_BIT_AND);
- } else if (GETCHAR(1)=='&') {
- r_chars++;
- return Token(TK_OP_AND);
- }
- return TK_OP_BIT_AND;*/
- } break;
- case '|': {
+ if (GETCHAR(0)=='=') {
+ char_idx++;
+ return _make_token(TK_OP_EQUAL);
+ }
- if (GETCHAR(1)=='|') {
+ return _make_token(TK_OP_ASSIGN);
+
+ } break;
+ case '<': {
+ if (GETCHAR(0)=='=') {
+ char_idx++;
+ return _make_token(TK_OP_LESS_EQUAL);
+ } else if (GETCHAR(0)=='<') {
+ char_idx++;
+ if (GETCHAR(0)=='=') {
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_SHIFT_LEFT);
+ }
- r_chars++;
- return Token(TK_OP_OR);
- }
+ return _make_token(TK_OP_SHIFT_LEFT);
+ }
- return Token(TK_ERROR,"Unknown character");
+ return _make_token(TK_OP_LESS);
+
+ } break;
+ case '>': {
+ if (GETCHAR(0)=='=') {
+ char_idx++;
+ return _make_token(TK_OP_GREATER_EQUAL);
+ } else if (GETCHAR(0)=='<') {
+ char_idx++;
+ if (GETCHAR(0)=='=') {
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_SHIFT_RIGHT);
+ }
- /*
- if (GETCHAR(1)=='=') {
- r_chars++;
- return Token(TK_OP_ASSIGN_BIT_OR);
- } else if (GETCHAR(1)=='|') {
- r_chars++;
- return Token(TK_OP_OR);
- }
- return TK_OP_BIT_OR;
- */
- } break;
- case '*': {
+ return _make_token(TK_OP_SHIFT_RIGHT);
+ }
- if (GETCHAR(1)=='=') {
- r_chars++;
- return Token(TK_OP_ASSIGN_MUL);
- }
- return TK_OP_MUL;
- } break;
- case '+': {
+ return _make_token(TK_OP_GREATER);
- if (GETCHAR(1)=='=') {
- r_chars++;
- return Token(TK_OP_ASSIGN_ADD);
- } /*else if (GETCHAR(1)=='+') {
+ } break;
+ case '!': {
+ if (GETCHAR(0)=='=') {
+ char_idx++;
+ return _make_token(TK_OP_NOT_EQUAL);
+ }
- r_chars++;
- return Token(TK_OP_PLUS_PLUS);
- }*/
+ return _make_token(TK_OP_NOT);
+
+ } break;
+ //case '"' //string - no strings in shader
+ //case '\'' //string - no strings in shader
+ case '{':
+ return _make_token(TK_CURLY_BRACKET_OPEN);
+ case '}':
+ return _make_token(TK_CURLY_BRACKET_CLOSE);
+ case '[':
+ return _make_token(TK_BRACKET_OPEN);
+ case ']':
+ return _make_token(TK_BRACKET_CLOSE);
+ case '(':
+ return _make_token(TK_PARENTHESIS_OPEN);
+ case ')':
+ return _make_token(TK_PARENTHESIS_CLOSE);
+ case ',':
+ return _make_token(TK_COMMA);
+ case ';':
+ return _make_token(TK_SEMICOLON);
+ case '?':
+ return _make_token(TK_QUESTION);
+ case ':':
+ return _make_token(TK_COLON);
+ case '^':
+ return _make_token(TK_OP_BIT_XOR);
+ case '~':
+ return _make_token(TK_OP_BIT_INVERT);
+ case '&': {
+ if (GETCHAR(0)=='=') {
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_BIT_AND);
+ } else if (GETCHAR(0)=='&') {
+ char_idx++;
+ return _make_token(TK_OP_AND);
+ }
+ return _make_token(TK_OP_BIT_AND);
+ } break;
+ case '|': {
+
+ if (GETCHAR(0)=='=') {
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_BIT_OR);
+ } else if (GETCHAR(0)=='|') {
+ char_idx++;
+ return _make_token(TK_OP_OR);
+ }
+ return _make_token(TK_OP_BIT_OR);
- return TK_OP_ADD;
- } break;
- case '-': {
+ } break;
+ case '*': {
- if (GETCHAR(1)=='=') {
- r_chars++;
- return Token(TK_OP_ASSIGN_SUB);
- }/* else if (GETCHAR(1)=='-') {
+ if (GETCHAR(0)=='=') {
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_MUL);
+ }
+ return _make_token(TK_OP_MUL);
+ } break;
+ case '+': {
- r_chars++;
- return Token(TK_OP_MINUS_MINUS);
- }*/
+ if (GETCHAR(0)=='=') {
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_ADD);
+ } else if (GETCHAR(0)=='+') {
- return TK_OP_SUB;
- } break;
- /*case '%': {
+ char_idx++;
+ return _make_token(TK_OP_INCREMENT);
+ }
- if (GETCHAR(1)=='=') {
- r_chars++;
- return Token(TK_OP_ASSIGN_MOD);
- }
+ return _make_token(TK_OP_ADD);
+ } break;
+ case '-': {
- return TK_OP_MOD;
- } break;*/
- default: {
+ if (GETCHAR(0)=='=') {
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_SUB);
+ }else if (GETCHAR(0)=='-') {
- if (_is_number(GETCHAR(0)) || (GETCHAR(0)=='.' && _is_number(GETCHAR(1)))) {
- // parse number
- bool period_found=false;
- bool exponent_found=false;
- bool hexa_found=false;
- bool sign_found=false;
+ char_idx++;
+ return _make_token(TK_OP_DECREMENT);
+ }
- String str;
- int i=0;
+ return _make_token(TK_OP_SUB);
+ } break;
+ case '%': {
- while(true) {
- if (GETCHAR(i)=='.') {
- if (period_found || exponent_found)
- return Token(TK_ERROR,"Invalid numeric constant");
- period_found=true;
- } else if (GETCHAR(i)=='x') {
- if (hexa_found || str.length()!=1 || str[0]!='0')
- return Token(TK_ERROR,"Invalid numeric constant");
- hexa_found=true;
- } else if (GETCHAR(i)=='e') {
- if (hexa_found || exponent_found)
- return Token(TK_ERROR,"Invalid numeric constant");
- exponent_found=true;
- } else if (_is_number(GETCHAR(i))) {
- //all ok
- } else if (hexa_found && _is_hex(GETCHAR(i))) {
-
- } else if ((GETCHAR(i)=='-' || GETCHAR(i)=='+') && exponent_found) {
- if (sign_found)
- return Token(TK_ERROR,"Invalid numeric constant");
- sign_found=true;
- } else
- break;
-
- str+=CharType(GETCHAR(i));
- i++;
+ if (GETCHAR(0)=='=') {
+ char_idx++;
+ return _make_token(TK_OP_ASSIGN_MOD);
}
- if (!_is_number(str[str.length()-1]))
- return Token(TK_ERROR,"Invalid numeric constant");
+ return _make_token(TK_OP_MOD);
+ } break;
+ default: {
- r_chars+=str.length()-1;
- return Token(TK_REAL_CONSTANT,str);
- /*
- if (period_found)
- return Token(TK_NUMBER_REAL,str);
- else
- return Token(TK_NUMBER_INTEGER,str);*/
+ char_idx--; //go back one, since we have no idea what this is
- }
+ if (_is_number(GETCHAR(0)) || (GETCHAR(0)=='.' && _is_number(GETCHAR(1)))) {
+ // parse number
+ bool period_found=false;
+ bool exponent_found=false;
+ bool hexa_found=false;
+ bool sign_found=false;
+ bool minus_exponent_found=false;
- if (GETCHAR(0)=='.') {
- //parse period
- return Token(TK_PERIOD);
- }
+ String str;
+ int i=0;
- if (_is_text_char(GETCHAR(0))) {
- // parse identifier
- String str;
- str+=CharType(GETCHAR(0));
+ while(true) {
+ if (GETCHAR(i)=='.') {
+ if (period_found || exponent_found)
+ return _make_token(TK_ERROR,"Invalid numeric constant");
+ period_found=true;
+ } else if (GETCHAR(i)=='x') {
+ if (hexa_found || str.length()!=1 || str[0]!='0')
+ return _make_token(TK_ERROR,"Invalid numeric constant");
+ hexa_found=true;
+ } else if (GETCHAR(i)=='e') {
+ if (hexa_found || exponent_found)
+ return _make_token(TK_ERROR,"Invalid numeric constant");
+ exponent_found=true;
+ } else if (_is_number(GETCHAR(i))) {
+ //all ok
+ } else if (hexa_found && _is_hex(GETCHAR(i))) {
+
+ } else if ((GETCHAR(i)=='-' || GETCHAR(i)=='+') && exponent_found) {
+ if (sign_found)
+ return _make_token(TK_ERROR,"Invalid numeric constant");
+ sign_found=true;
+ if (GETCHAR(i)=='-')
+ minus_exponent_found=true;
+ } else
+ break;
- while(_is_text_char(GETCHAR(r_chars))) {
+ str+=CharType(GETCHAR(i));
+ i++;
+ }
- str+=CharType(GETCHAR(r_chars));
- r_chars++;
- }
+ if (!_is_number(str[str.length()-1]))
+ return _make_token(TK_ERROR,"Invalid numeric constant");
- //see if keyword
- struct _kws { TokenType token; const char *text;};
- static const _kws keyword_list[]={
- {TK_TRUE,"true"},
- {TK_FALSE,"false"},
- {TK_TYPE_VOID,"void"},
- {TK_TYPE_BOOL,"bool"},
- /*{TK_TYPE_INT,"int"},
- {TK_TYPE_INT2,"int2"},
- {TK_TYPE_INT3,"int3"},
- {TK_TYPE_INT4,"int4"},*/
- {TK_TYPE_FLOAT,"float"},
- /*{TK_TYPE_FLOAT2,"float2"},
- {TK_TYPE_FLOAT3,"float3"},
- {TK_TYPE_FLOAT4,"float4"},*/
- {TK_TYPE_VEC2,"vec2"},
- {TK_TYPE_VEC3,"vec3"},
- {TK_TYPE_VEC4,"vec4"},
- {TK_TYPE_TEXTURE,"texture"},
- {TK_TYPE_CUBEMAP,"cubemap"},
- {TK_TYPE_COLOR,"color"},
+ char_idx+=str.length();
+ Token tk;
+ if (period_found || minus_exponent_found)
+ tk.type=TK_REAL_CONSTANT;
+ else
+ tk.type=TK_INT_CONSTANT;
- {TK_TYPE_MAT2,"mat2"},
- /*{TK_TYPE_MAT3,"mat3"},
- {TK_TYPE_MAT4,"mat3"},*/
- {TK_TYPE_MAT3,"mat3"},
- {TK_TYPE_MAT4,"mat4"},
- {TK_CF_IF,"if"},
- {TK_CF_ELSE,"else"},
- /*
- {TK_CF_FOR,"for"},
- {TK_CF_WHILE,"while"},
- {TK_CF_DO,"do"},
- {TK_CF_SWITCH,"switch"},
- {TK_CF_BREAK,"break"},
- {TK_CF_CONTINUE,"continue"},*/
- {TK_CF_RETURN,"return"},
- {TK_UNIFORM,"uniform"},
- {TK_ERROR,NULL}
- };
+ if (!str.is_valid_float()) {
+ return _make_token(TK_ERROR,"Invalid numeric constant");
+ }
- int idx=0;
+ tk.constant=str.to_double();
+ tk.line=tk_line;
- while(keyword_list[idx].text) {
+ return tk;
- if (str==keyword_list[idx].text)
- return Token(keyword_list[idx].token);
- idx++;
}
+ if (GETCHAR(0)=='.') {
+ //parse period
+ char_idx++;
+ return _make_token(TK_PERIOD);
+ }
- return Token(TK_INDENTIFIER,str);
- }
-
- if (GETCHAR(0)>32)
- return Token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))+": '"+String::chr(GETCHAR(0))+"'");
- else
- return Token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0)));
+ if (_is_text_char(GETCHAR(0))) {
+ // parse identifier
+ String str;
- } break;
- }
+ while(_is_text_char(GETCHAR(0))) {
- ERR_PRINT("BUG");
- return Token();
-}
+ str+=CharType(GETCHAR(0));
+ char_idx++;
+ }
-Error ShaderLanguage::tokenize(const String& p_text,Vector<Token> *p_tokens,String *r_error,int *r_err_line,int *r_err_column) {
+ //see if keyword
+ //should be converted to a static map
+ int idx=0;
+ while(keyword_list[idx].text) {
- int len =p_text.length();
- int pos=0;
+ if (str==keyword_list[idx].text) {
- int line=0;
+ return _make_token(keyword_list[idx].token);
+ }
+ idx++;
+ }
- while(pos<len) {
- int advance=0;
- int prev_line=line;
- Token t = read_token(&p_text[pos],len-pos,line,advance);
- t.line=prev_line;
+ return _make_token(TK_IDENTIFIER,str);
+ }
- if (t.type==TK_ERROR) {
+ if (GETCHAR(0)>32)
+ return _make_token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0))+": '"+String::chr(GETCHAR(0))+"'");
+ else
+ return _make_token(TK_ERROR,"Tokenizer: Unknown character #"+itos(GETCHAR(0)));
- if (r_error) {
- *r_error=t.text;
- *r_err_line=line;
- return ERR_COMPILATION_FAILED;
- }
+ } break;
}
+ }
+ ERR_PRINT("BUG");
+ return Token();
+}
- if (t.type!=TK_EMPTY)
- p_tokens->push_back(t);
- //if (prev_line!=line)
- // p_tokens->push_back(Token(TK_LINE,itos(line)));
- pos+=advance;
+String ShaderLanguage::token_debug(const String& p_code) {
- }
+ clear();
- return OK;
+ code=p_code;
-}
+ String output;
-String ShaderLanguage::lex_debug(const String& p_code) {
+ Token tk = _get_token();
+ while(tk.type!=TK_EOF && tk.type!=TK_ERROR) {
- Vector<Token> tokens;
- String error;
- int errline,errcol;
- if (tokenize(p_code,&tokens,&error,&errline,&errcol)!=OK)
- return error;
- String ret;
- for(int i=0;i<tokens.size();i++) {
- ret+=String(token_names[tokens[i].type])+":"+itos(tokens[i].line)+":"+itos(tokens[i].col)+":"+tokens[i].text+"\n";
+ output+=itos(tk_line)+": "+get_token_text(tk)+"\n";
+ tk = _get_token();
}
- return ret;
+ return output;
}
bool ShaderLanguage::is_token_datatype(TokenType p_type) {
- return
- (p_type==TK_TYPE_VOID) ||
- (p_type==TK_TYPE_BOOL) ||
- (p_type==TK_TYPE_FLOAT) ||
- (p_type==TK_TYPE_VEC2) ||
- (p_type==TK_TYPE_VEC3) ||
- (p_type==TK_TYPE_VEC4) ||
- (p_type==TK_TYPE_COLOR) ||
- (p_type==TK_TYPE_MAT2) ||
- (p_type==TK_TYPE_MAT3) ||
- (p_type==TK_TYPE_MAT4) ||
- (p_type==TK_TYPE_CUBEMAP) ||
- (p_type==TK_TYPE_TEXTURE);
+ return (
+ p_type==TK_TYPE_VOID ||
+ p_type==TK_TYPE_BOOL ||
+ p_type==TK_TYPE_BVEC2 ||
+ p_type==TK_TYPE_BVEC3 ||
+ p_type==TK_TYPE_BVEC4 ||
+ p_type==TK_TYPE_INT ||
+ p_type==TK_TYPE_IVEC2 ||
+ p_type==TK_TYPE_IVEC3 ||
+ p_type==TK_TYPE_IVEC4 ||
+ p_type==TK_TYPE_UINT ||
+ p_type==TK_TYPE_UVEC2 ||
+ p_type==TK_TYPE_UVEC3 ||
+ p_type==TK_TYPE_UVEC4 ||
+ p_type==TK_TYPE_FLOAT ||
+ p_type==TK_TYPE_VEC2 ||
+ p_type==TK_TYPE_VEC3 ||
+ p_type==TK_TYPE_VEC4 ||
+ p_type==TK_TYPE_MAT2 ||
+ p_type==TK_TYPE_MAT3 ||
+ p_type==TK_TYPE_MAT4 ||
+ p_type==TK_TYPE_SAMPLER2D ||
+ p_type==TK_TYPE_ISAMPLER2D ||
+ p_type==TK_TYPE_USAMPLER2D ||
+ p_type==TK_TYPE_SAMPLERCUBE );
}
ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) {
- switch(p_type) {
+ return DataType(p_type-TK_TYPE_VOID);
+}
- case TK_TYPE_VOID: return TYPE_VOID;
- case TK_TYPE_BOOL: return TYPE_BOOL;
- case TK_TYPE_FLOAT: return TYPE_FLOAT;
- case TK_TYPE_VEC2: return TYPE_VEC2;
- case TK_TYPE_VEC3: return TYPE_VEC3;
- case TK_TYPE_VEC4: return TYPE_VEC4;
- case TK_TYPE_COLOR: return TYPE_VEC4;
- case TK_TYPE_MAT2: return TYPE_MAT2;
- case TK_TYPE_MAT3: return TYPE_MAT3;
- case TK_TYPE_MAT4: return TYPE_MAT4;
- case TK_TYPE_TEXTURE: return TYPE_TEXTURE;
- case TK_TYPE_CUBEMAP: return TYPE_CUBEMAP;
- default: return TYPE_VOID;
- }
- return TYPE_VOID;
+bool ShaderLanguage::is_token_precision(TokenType p_type) {
+
+ return (
+ p_type==TK_PRECISION_LOW ||
+ p_type==TK_PRECISION_MID ||
+ p_type==TK_PRECISION_HIGH );
+
+}
+
+ShaderLanguage::DataPrecision ShaderLanguage::get_token_precision(TokenType p_type) {
+
+ if (p_type==TK_PRECISION_LOW)
+ return PRECISION_LOWP;
+ else if (p_type==TK_PRECISION_HIGH)
+ return PRECISION_HIGHP;
+ else
+ return PRECISION_MEDIUMP;
}
@@ -553,6 +679,17 @@ String ShaderLanguage::get_datatype_name(DataType p_type) {
case TYPE_VOID: return "void";
case TYPE_BOOL: return "bool";
+ case TYPE_BVEC2: return "bvec2";
+ case TYPE_BVEC3: return "bvec3";
+ case TYPE_BVEC4: return "bvec4";
+ case TYPE_INT: return "int";
+ case TYPE_IVEC2: return "ivec2";
+ case TYPE_IVEC3: return "ivec3";
+ case TYPE_IVEC4: return "ivec4";
+ case TYPE_UINT: return "uint";
+ case TYPE_UVEC2: return "uvec2";
+ case TYPE_UVEC3: return "uvec3";
+ case TYPE_UVEC4: return "uvec4";
case TYPE_FLOAT: return "float";
case TYPE_VEC2: return "vec2";
case TYPE_VEC3: return "vec3";
@@ -560,9 +697,10 @@ String ShaderLanguage::get_datatype_name(DataType p_type) {
case TYPE_MAT2: return "mat2";
case TYPE_MAT3: return "mat3";
case TYPE_MAT4: return "mat4";
- case TYPE_TEXTURE: return "texture";
- case TYPE_CUBEMAP: return "cubemap";
- default: return "";
+ case TYPE_SAMPLER2D: return "sampler2D";
+ case TYPE_ISAMPLER2D: return "isampler2D";
+ case TYPE_USAMPLER2D: return "usampler2D";
+ case TYPE_SAMPLERCUBE: return "samplerCube";
}
return "";
@@ -571,211 +709,495 @@ String ShaderLanguage::get_datatype_name(DataType p_type) {
bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) {
- return
- (p_type==TK_TYPE_BOOL) ||
- (p_type==TK_TYPE_FLOAT) ||
- (p_type==TK_TYPE_VEC2) ||
- (p_type==TK_TYPE_VEC3) ||
- (p_type==TK_TYPE_VEC4) ||
- (p_type==TK_TYPE_COLOR) ||
- (p_type==TK_TYPE_MAT2) ||
- (p_type==TK_TYPE_MAT3) ||
- (p_type==TK_TYPE_MAT4) ||
- (p_type==TK_TYPE_TEXTURE) ||
- (p_type==TK_TYPE_CUBEMAP);
+ return is_token_datatype(p_type) && p_type!=TK_TYPE_VOID;
}
-bool ShaderLanguage::parser_is_at_function(Parser& parser) {
-
- return (is_token_datatype(parser.get_token_type(0)) && parser.get_token_type(1)==TK_INDENTIFIER && parser.get_token_type(2)==TK_PARENTHESIS_OPEN);
-}
-
-
-
-bool ShaderLanguage::test_existing_identifier(Node *p_node,const StringName p_identifier,bool p_func,bool p_var,bool p_builtin) {
+void ShaderLanguage::clear() {
- Node *node = p_node;
+ current_function=StringName();
- while(node) {
+ completion_type=COMPLETION_NONE;
+ completion_block=NULL;
+ completion_function=StringName();
- if (node->type==Node::TYPE_BLOCK) {
+ error_line=0;
+ tk_line=1;
+ char_idx=0;
+ error_set=false;
+ error_str="";
+ while(nodes) {
+ Node *n = nodes;
+ nodes=nodes->next;
+ memdelete(n);
+ }
- BlockNode *block = (BlockNode*)node;
- if (block->variables.has(p_identifier))
- return true;
- } else if (node->type==Node::TYPE_PROGRAM) {
+}
- ProgramNode *program = (ProgramNode*)node;
- for(int i=0;i<program->functions.size();i++) {
- if (program->functions[i].name==p_identifier) {
- return true;
- }
- }
+bool ShaderLanguage::_find_identifier(const BlockNode* p_block,const Map<StringName, DataType> &p_builtin_types,const StringName& p_identifier, DataType *r_data_type, IdentifierType *r_type) {
- if(program->builtin_variables.has(p_identifier)) {
- return true;
- }
- if(program->uniforms.has(p_identifier)) {
- return true;
- }
- } else if (node->type==Node::TYPE_FUNCTION) {
+ if (p_builtin_types.has(p_identifier)) {
- FunctionNode *func=(FunctionNode*)node;
- for(int i=0;i<func->arguments.size();i++)
- if (func->arguments[i].name==p_identifier)
- return true;
+ if (r_data_type) {
+ *r_data_type=p_builtin_types[p_identifier];
+ }
+ if (r_type) {
+ *r_type=IDENTIFIER_BUILTIN_VAR;
}
- node=node->parent;
+ return true;
}
- // try keywords
+ FunctionNode *function=NULL;
- int idx=0;
+ while(p_block) {
- //todo optimize
- while(intrinsic_func_defs[idx].name) {
+ if (p_block->variables.has(p_identifier)) {
+ if (r_data_type) {
+ *r_data_type=p_block->variables[p_identifier].type;
+ }
+ if (r_type) {
+ *r_type=IDENTIFIER_LOCAL_VAR;
+ }
- if (p_identifier.operator String()==intrinsic_func_defs[idx].name)
return true;
- idx++;
- }
-
+ }
- return false;
+ if (p_block->parent_function) {
+ function=p_block->parent_function;
+ break;
+ } else {
+ ERR_FAIL_COND_V(!p_block->parent_block,false);
+ p_block=p_block->parent_block;
+ }
+ }
-}
+ if (function) {
+ for(int i=0;i<function->arguments.size();i++) {
+ if (function->arguments[i].name==p_identifier) {
+ if (r_data_type) {
+ *r_data_type=function->arguments[i].type;
+ }
+ if (r_type) {
+ *r_type=IDENTIFIER_FUNCTION_ARGUMENT;
+ }
+ return true;
+ }
+ }
+ }
-Error ShaderLanguage::parse_function(Parser& parser,BlockNode *p_block) {
- if (!p_block->parent || p_block->parent->type!=Node::TYPE_PROGRAM) {
- parser.set_error("Misplaced function");
- return ERR_PARSE_ERROR;
+ if (shader->varyings.has(p_identifier)) {
+ if (r_data_type) {
+ *r_data_type=shader->varyings[p_identifier].type;
+ }
+ if (r_type) {
+ *r_type=IDENTIFIER_VARYING;
+ }
+ return true;
+ }
+ if (shader->uniforms.has(p_identifier)) {
+ if (r_data_type) {
+ *r_data_type=shader->uniforms[p_identifier].type;
+ }
+ if (r_type) {
+ *r_type=IDENTIFIER_UNIFORM;
+ }
+ return true;
}
+ for(int i=0;i<shader->functions.size();i++) {
- ProgramNode *program = (ProgramNode*)p_block->parent;
+ if (!shader->functions[i].callable)
+ continue;
- StringName name = parser.get_token(1).text;
+ if (shader->functions[i].name==p_identifier) {
+ if (r_data_type) {
+ *r_data_type=shader->functions[i].function->return_type;
+ }
+ if (r_type) {
+ *r_type=IDENTIFIER_FUNCTION;
+ }
+ }
+ }
- if (test_existing_identifier(p_block,name)) {
+ return false;
- parser.set_error("Duplicate Identifier (existing variable/builtin/function): "+name);
- return ERR_PARSE_ERROR;
+}
- }
+bool ShaderLanguage::_validate_operator(OperatorNode *p_op,DataType *r_ret_type) {
- FunctionNode *function = parser.create_node<FunctionNode>(program);
- function->body = parser.create_node<BlockNode>(function);
+ bool valid=false;
+ DataType ret_type;
+
+ switch(p_op->op) {
+ case OP_EQUAL:
+ case OP_NOT_EQUAL: {
+ DataType na = p_op->arguments[0]->get_datatype();
+ DataType nb = p_op->arguments[1]->get_datatype();
+ valid=na==nb;
+ ret_type=TYPE_BOOL;
+ } break;
+ case OP_LESS:
+ case OP_LESS_EQUAL:
+ case OP_GREATER:
+ case OP_GREATER_EQUAL: {
+ DataType na = p_op->arguments[0]->get_datatype();
+ DataType nb = p_op->arguments[1]->get_datatype();
- function->name=name;
+ valid = na==nb && (na==TYPE_UINT || na==TYPE_INT || na==TYPE_FLOAT);
+ ret_type=TYPE_BOOL;
- function->return_type=get_token_datatype(parser.get_token_type(0));
+ } break;
+ case OP_AND:
+ case OP_OR: {
+ DataType na = p_op->arguments[0]->get_datatype();
+ DataType nb = p_op->arguments[1]->get_datatype();
- { //add to programnode
- ProgramNode::Function f;
- f.name=name;
- f.function=function;
- program->functions.push_back(f);
- }
+ valid = na==nb && na==TYPE_BOOL;
+ ret_type=TYPE_BOOL;
- int ofs=3;
+ } break;
+ case OP_NOT: {
- while(true) {
+ DataType na = p_op->arguments[0]->get_datatype();
+ valid = na==TYPE_BOOL;
+ ret_type=TYPE_BOOL;
- //end of arguments
- if (parser.get_token_type(ofs)==TK_PARENTHESIS_CLOSE) {
- ofs++;
- break;
- }
- //next argument awaits
- if (parser.get_token_type(ofs)==TK_COMMA) {
- if (!is_token_nonvoid_datatype(parser.get_token_type(ofs+1))) {
- parser.set_error("Expected Identifier or ')' following ','");
- return ERR_PARSE_ERROR;
+ } break;
+ case OP_INCREMENT:
+ case OP_DECREMENT:
+ case OP_POST_INCREMENT:
+ case OP_POST_DECREMENT:
+ case OP_NEGATE: {
+ DataType na = p_op->arguments[0]->get_datatype();
+ valid = na>TYPE_BOOL && na<TYPE_MAT2;
+ ret_type=na;
+ } break;
+ case OP_ADD:
+ case OP_SUB:
+ case OP_MUL:
+ case OP_DIV: {
+ DataType na = p_op->arguments[0]->get_datatype();
+ DataType nb = p_op->arguments[1]->get_datatype();
+
+ if (na>nb) {
+ //make things easier;
+ SWAP(na,nb);
+ }
+
+ if (na==nb) {
+ valid = (na>TYPE_BOOL && na<TYPE_MAT2) || (p_op->op==OP_MUL && na>=TYPE_MAT2 && na<=TYPE_MAT4);
+ ret_type=na;
+ } else if (na==TYPE_INT && nb==TYPE_IVEC2) {
+ valid=true;
+ ret_type=TYPE_IVEC2;
+ } else if (na==TYPE_INT && nb==TYPE_IVEC3) {
+ valid=true;
+ ret_type=TYPE_IVEC3;
+ } else if (na==TYPE_INT && nb==TYPE_IVEC4) {
+ valid=true;
+ ret_type=TYPE_IVEC4;
+ } else if (na==TYPE_UINT && nb==TYPE_UVEC2) {
+ valid=true;
+ ret_type=TYPE_UVEC2;
+ } else if (na==TYPE_UINT && nb==TYPE_UVEC3) {
+ valid=true;
+ ret_type=TYPE_UVEC3;
+ } else if (na==TYPE_UINT && nb==TYPE_UVEC4) {
+ valid=true;
+ ret_type=TYPE_UVEC4;
+ } else if (na==TYPE_FLOAT && nb==TYPE_VEC2) {
+ valid=true;
+ ret_type=TYPE_VEC2;
+ } else if (na==TYPE_FLOAT && nb==TYPE_VEC3) {
+ valid=true;
+ ret_type=TYPE_VEC3;
+ } else if (na==TYPE_FLOAT && nb==TYPE_VEC4) {
+ valid=true;
+ ret_type=TYPE_VEC4;
+ } else if (p_op->op==OP_MUL && na==TYPE_VEC2 && nb==TYPE_MAT2) {
+ valid=true;
+ ret_type=TYPE_MAT2;
+ } else if (p_op->op==OP_MUL && na==TYPE_VEC3 && nb==TYPE_MAT3) {
+ valid=true;
+ ret_type=TYPE_MAT3;
+ } else if (p_op->op==OP_MUL && na==TYPE_VEC4 && nb==TYPE_MAT4) {
+ valid=true;
+ ret_type=TYPE_MAT4;
}
- ofs++;
- continue;
- }
+ } break;
+ case OP_ASSIGN_MOD:
+ case OP_MOD: {
+ /*
+ * The operator modulus (%) operates on signed or unsigned integers or integer vectors. The operand
+ * types must both be signed or both be unsigned. The operands cannot be vectors of differing size. If
+ * one operand is a scalar and the other vector, then the scalar is applied component-wise to the vector,
+ * resulting in the same type as the vector. If both are vectors of the same size, the result is computed
+ * component-wise.
+ */
+ DataType na = p_op->arguments[0]->get_datatype();
+ DataType nb = p_op->arguments[1]->get_datatype();
- if (!is_token_nonvoid_datatype(parser.get_token_type(ofs+0))) {
- parser.set_error("Invalid Argument Type");
- return ERR_PARSE_ERROR;
- }
+ if (na==TYPE_INT && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_INT;
+ } else if (na==TYPE_IVEC2 && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_IVEC2;
+ } else if (na==TYPE_IVEC3 && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_IVEC3;
+ } else if (na==TYPE_IVEC4 && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_IVEC4;
+ } else if (na==TYPE_IVEC2 && nb==TYPE_IVEC2) {
+ valid=true;
+ ret_type=TYPE_IVEC2;
+ } else if (na==TYPE_IVEC3 && nb==TYPE_IVEC3) {
+ valid=true;
+ ret_type=TYPE_IVEC3;
+ } else if (na==TYPE_IVEC4 && nb==TYPE_IVEC4) {
+ valid=true;
+ ret_type=TYPE_IVEC4;
+ /////
+ } else if (na==TYPE_UINT && nb==TYPE_UINT) {
+ valid=true;
+ ret_type=TYPE_UINT;
+ } else if (na==TYPE_UVEC2 && nb==TYPE_UINT) {
+ valid=true;
+ ret_type=TYPE_UVEC2;
+ } else if (na==TYPE_UVEC3 && nb==TYPE_UINT) {
+ valid=true;
+ ret_type=TYPE_UVEC3;
+ } else if (na==TYPE_UVEC4 && nb==TYPE_UINT) {
+ valid=true;
+ ret_type=TYPE_UVEC4;
+ } else if (na==TYPE_UVEC2 && nb==TYPE_UVEC2) {
+ valid=true;
+ ret_type=TYPE_UVEC2;
+ } else if (na==TYPE_UVEC3 && nb==TYPE_UVEC3) {
+ valid=true;
+ ret_type=TYPE_UVEC3;
+ } else if (na==TYPE_UVEC4 && nb==TYPE_UVEC4) {
+ valid=true;
+ ret_type=TYPE_UVEC4;
+ }
+ } break;
+ case OP_ASSIGN_SHIFT_LEFT:
+ case OP_ASSIGN_SHIFT_RIGHT:
+ case OP_SHIFT_LEFT:
+ case OP_SHIFT_RIGHT: {
- DataType identtype=get_token_datatype(parser.get_token_type(ofs+0));
+ DataType na = p_op->arguments[0]->get_datatype();
+ DataType nb = p_op->arguments[1]->get_datatype();
- if (parser.get_token_type(ofs+1)!=TK_INDENTIFIER) {
- parser.set_error("Expected Argument Identifier");
- return ERR_PARSE_ERROR;
- }
+ if (na>=TYPE_UINT && na<=TYPE_UVEC4) {
+ na=DataType(na-4);
+ }
- StringName identname=parser.get_token(ofs+1).text;
+ if (nb>=TYPE_UINT && nb<=TYPE_UVEC4) {
+ nb=DataType(nb-4);
+ }
- if (test_existing_identifier(function,identname)) {
- parser.set_error("Duplicate Argument Identifier: "+identname);
- return ERR_DUPLICATE_SYMBOL;
- }
+ if (na==TYPE_INT && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_INT;
+ } else if (na==TYPE_IVEC2 && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_IVEC2;
+ } else if (na==TYPE_IVEC3 && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_IVEC3;
+ } else if (na==TYPE_IVEC4 && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_IVEC4;
+ } else if (na==TYPE_IVEC2 && nb==TYPE_IVEC2) {
+ valid=true;
+ ret_type=TYPE_IVEC2;
+ } else if (na==TYPE_IVEC3 && nb==TYPE_IVEC3) {
+ valid=true;
+ ret_type=TYPE_IVEC3;
+ } else if (na==TYPE_IVEC4 && nb==TYPE_IVEC4) {
+ valid=true;
+ ret_type=TYPE_IVEC4;
+ }
+ } break;
+ case OP_ASSIGN: {
+ DataType na = p_op->arguments[0]->get_datatype();
+ DataType nb = p_op->arguments[1]->get_datatype();
+ valid=na==nb;
+ ret_type=na;
+ } break;
+ case OP_ASSIGN_ADD:
+ case OP_ASSIGN_SUB:
+ case OP_ASSIGN_MUL:
+ case OP_ASSIGN_DIV: {
- FunctionNode::Argument arg;
- arg.name=identname;
- arg.type=identtype;
- //function->body->variables[arg.name]=arg.type;
- function->arguments.push_back(arg);
+ DataType na = p_op->arguments[0]->get_datatype();
+ DataType nb = p_op->arguments[1]->get_datatype();
- ofs+=2;
- }
- parser.advance(ofs);
- // match {
- if (parser.get_token_type()!=TK_CURLY_BRACKET_OPEN) {
- parser.set_error("Expected '{'");
- return ERR_PARSE_ERROR;
- }
+ if (na==nb) {
+ valid = (na>TYPE_BOOL && na<TYPE_MAT2) || (p_op->op==OP_ASSIGN_MUL && na>=TYPE_MAT2 && na<=TYPE_MAT4);
+ ret_type=na;
+ } else if (na==TYPE_IVEC2 && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_IVEC2;
+ } else if (na==TYPE_IVEC3 && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_IVEC3;
+ } else if (na==TYPE_IVEC4 && nb==TYPE_INT ) {
+ valid=true;
+ ret_type=TYPE_IVEC4;
+ } else if (na==TYPE_UVEC2 && nb==TYPE_UINT) {
+ valid=true;
+ ret_type=TYPE_UVEC2;
+ } else if (na==TYPE_UVEC3 && nb==TYPE_UINT) {
+ valid=true;
+ ret_type=TYPE_UVEC3;
+ } else if (na==TYPE_UVEC4 && nb==TYPE_UINT) {
+ valid=true;
+ ret_type=TYPE_UVEC4;
+ } else if (na==TYPE_VEC2 && nb==TYPE_FLOAT ) {
+ valid=true;
+ ret_type=TYPE_VEC2;
+ } else if (na==TYPE_VEC3 && nb==TYPE_FLOAT) {
+ valid=true;
+ ret_type=TYPE_VEC3;
+ } else if (na==TYPE_VEC4 && nb==TYPE_FLOAT) {
+ valid=true;
+ ret_type=TYPE_VEC4;
+ } else if (p_op->op==OP_ASSIGN_MUL && na==TYPE_MAT2 && nb==TYPE_VEC2) {
+ valid=true;
+ ret_type=TYPE_MAT2;
+ } else if (p_op->op==OP_ASSIGN_MUL && na==TYPE_MAT3 && nb==TYPE_VEC3) {
+ valid=true;
+ ret_type=TYPE_MAT3;
+ } else if (p_op->op==OP_ASSIGN_MUL && na==TYPE_MAT4 && nb==TYPE_VEC4) {
+ valid=true;
+ ret_type=TYPE_MAT4;
+ }
+ } break;
+ case OP_ASSIGN_BIT_AND:
+ case OP_ASSIGN_BIT_OR:
+ case OP_ASSIGN_BIT_XOR:
+ case OP_BIT_AND:
+ case OP_BIT_OR:
+ case OP_BIT_XOR: {
- parser.advance();
- Error err = parse_block(parser,function->body);
+ /*
+ * The bitwise operators and (&), exclusive-or (^), and inclusive-or (|). The operands must be of type
+ * signed or unsigned integers or integer vectors. The operands cannot be vectors of differing size. If
+ * one operand is a scalar and the other a vector, the scalar is applied component-wise to the vector,
+ * resulting in the same type as the vector. The fundamental types of the operands (signed or unsigned)
+ * must match.
+ */
- if (err)
- return err;
+ DataType na = p_op->arguments[0]->get_datatype();
+ DataType nb = p_op->arguments[1]->get_datatype();
- // make sure that if the function has a return type, it does return something..
- if (function->return_type!=TYPE_VOID) {
- bool found=false;
- for(int i=0;i<function->body->statements.size();i++) {
- if (function->body->statements[i]->type==Node::TYPE_CONTROL_FLOW) {
+ if (na>nb && p_op->op>=OP_BIT_AND) {
+ //can swap for non assign
+ SWAP(na,nb);
+ }
- ControlFlowNode *cf = (ControlFlowNode*)function->body->statements[i];
- if (cf->flow_op==FLOW_OP_RETURN) {
- // type of return was already checked when inserted
- // no need to check here
- found=true;
- }
+ if (na==TYPE_INT && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_INT;
+ } else if (na==TYPE_IVEC2 && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_IVEC2;
+ } else if (na==TYPE_IVEC3 && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_IVEC3;
+ } else if (na==TYPE_IVEC4 && nb==TYPE_INT) {
+ valid=true;
+ ret_type=TYPE_IVEC4;
+ } else if (na==TYPE_IVEC2 && nb==TYPE_IVEC2) {
+ valid=true;
+ ret_type=TYPE_IVEC2;
+ } else if (na==TYPE_IVEC3 && nb==TYPE_IVEC3) {
+ valid=true;
+ ret_type=TYPE_IVEC3;
+ } else if (na==TYPE_IVEC4 && nb==TYPE_IVEC4) {
+ valid=true;
+ ret_type=TYPE_IVEC4;
+ /////
+ } else if (na==TYPE_UINT && nb==TYPE_UINT) {
+ valid=true;
+ ret_type=TYPE_UINT;
+ } else if (na==TYPE_UVEC2 && nb==TYPE_UINT) {
+ valid=true;
+ ret_type=TYPE_UVEC2;
+ } else if (na==TYPE_UVEC3 && nb==TYPE_UINT) {
+ valid=true;
+ ret_type=TYPE_UVEC3;
+ } else if (na==TYPE_UVEC4 && nb==TYPE_UINT) {
+ valid=true;
+ ret_type=TYPE_UVEC4;
+ } else if (na==TYPE_UVEC2 && nb==TYPE_UVEC2) {
+ valid=true;
+ ret_type=TYPE_UVEC2;
+ } else if (na==TYPE_UVEC3 && nb==TYPE_UVEC3) {
+ valid=true;
+ ret_type=TYPE_UVEC3;
+ } else if (na==TYPE_UVEC4 && nb==TYPE_UVEC4) {
+ valid=true;
+ ret_type=TYPE_UVEC4;
}
- }
+ } break;
+ case OP_BIT_INVERT: { //unaries
+ DataType na = p_op->arguments[0]->get_datatype();
+ valid = na>=TYPE_INT && na<TYPE_FLOAT;
+ ret_type=na;
+ } break;
+ case OP_SELECT_IF: {
+ DataType na = p_op->arguments[0]->get_datatype();
+ DataType nb = p_op->arguments[1]->get_datatype();
+ DataType nc = p_op->arguments[2]->get_datatype();
- if (!found) {
- parser.set_error("Function must return a value (use the main block)");
- return ERR_PARSE_ERROR;
+ valid = na==TYPE_BOOL && (nb==nc);
+ ret_type=nb;
+ } break;
+ default: {
+ ERR_FAIL_V(false);
}
}
- return OK;
-}
+ if (r_ret_type)
+ *r_ret_type=ret_type;
+ return valid;
+}
-const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={
+const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[]={
//constructors
{"bool",TYPE_BOOL,{TYPE_BOOL,TYPE_VOID}},
+ {"bvec2",TYPE_BVEC2,{TYPE_BOOL,TYPE_VOID}},
+ {"bvec2",TYPE_BVEC2,{TYPE_BOOL,TYPE_BOOL,TYPE_VOID}},
+ {"bvec3",TYPE_BVEC3,{TYPE_BOOL,TYPE_VOID}},
+ {"bvec3",TYPE_BVEC3,{TYPE_BOOL,TYPE_BOOL,TYPE_BOOL,TYPE_VOID}},
+ {"bvec3",TYPE_BVEC3,{TYPE_BVEC2,TYPE_BOOL,TYPE_VOID}},
+ {"bvec3",TYPE_BVEC3,{TYPE_BOOL,TYPE_BVEC2,TYPE_VOID}},
+ {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_VOID}},
+ {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_BOOL,TYPE_BOOL,TYPE_BOOL,TYPE_VOID}},
+ {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_BVEC2,TYPE_BOOL,TYPE_VOID}},
+ {"bvec4",TYPE_BVEC4,{TYPE_BVEC2,TYPE_BOOL,TYPE_BOOL,TYPE_VOID}},
+ {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_BOOL,TYPE_BVEC2,TYPE_VOID}},
+ {"bvec4",TYPE_BVEC4,{TYPE_BOOL,TYPE_BVEC3,TYPE_VOID}},
+ {"bvec4",TYPE_BVEC4,{TYPE_BVEC3,TYPE_BOOL,TYPE_VOID}},
+ {"bvec4",TYPE_BVEC4,{TYPE_BVEC2,TYPE_BVEC2,TYPE_VOID}},
+
+
{"float",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
{"vec2",TYPE_VEC2,{TYPE_FLOAT,TYPE_VOID}},
{"vec2",TYPE_VEC2,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}},
@@ -791,10 +1213,132 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={
{"vec4",TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC3,TYPE_VOID}},
{"vec4",TYPE_VEC4,{TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
{"vec4",TYPE_VEC4,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+
+ {"int",TYPE_INT,{TYPE_INT,TYPE_VOID}},
+ {"ivec2",TYPE_IVEC2,{TYPE_INT,TYPE_VOID}},
+ {"ivec2",TYPE_IVEC2,{TYPE_INT,TYPE_INT,TYPE_VOID}},
+ {"ivec3",TYPE_IVEC3,{TYPE_INT,TYPE_VOID}},
+ {"ivec3",TYPE_IVEC3,{TYPE_INT,TYPE_INT,TYPE_INT,TYPE_VOID}},
+ {"ivec3",TYPE_IVEC3,{TYPE_IVEC2,TYPE_INT,TYPE_VOID}},
+ {"ivec3",TYPE_IVEC3,{TYPE_INT,TYPE_IVEC2,TYPE_VOID}},
+ {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_VOID}},
+ {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_INT,TYPE_INT,TYPE_INT,TYPE_VOID}},
+ {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_IVEC2,TYPE_INT,TYPE_VOID}},
+ {"ivec4",TYPE_IVEC4,{TYPE_IVEC2,TYPE_INT,TYPE_INT,TYPE_VOID}},
+ {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_INT,TYPE_IVEC2,TYPE_VOID}},
+ {"ivec4",TYPE_IVEC4,{TYPE_INT,TYPE_IVEC3,TYPE_VOID}},
+ {"ivec4",TYPE_IVEC4,{TYPE_IVEC3,TYPE_INT,TYPE_VOID}},
+ {"ivec4",TYPE_IVEC4,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}},
+
+ {"uint",TYPE_UINT,{TYPE_UINT,TYPE_VOID}},
+ {"uvec2",TYPE_UVEC2,{TYPE_UINT,TYPE_VOID}},
+ {"uvec2",TYPE_UVEC2,{TYPE_UINT,TYPE_UINT,TYPE_VOID}},
+ {"uvec3",TYPE_UVEC3,{TYPE_UINT,TYPE_VOID}},
+ {"uvec3",TYPE_UVEC3,{TYPE_UINT,TYPE_UINT,TYPE_UINT,TYPE_VOID}},
+ {"uvec3",TYPE_UVEC3,{TYPE_UVEC2,TYPE_UINT,TYPE_VOID}},
+ {"uvec3",TYPE_UVEC3,{TYPE_UINT,TYPE_UVEC2,TYPE_VOID}},
+ {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_VOID}},
+ {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_UINT,TYPE_UINT,TYPE_UINT,TYPE_VOID}},
+ {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_UVEC2,TYPE_UINT,TYPE_VOID}},
+ {"uvec4",TYPE_UVEC4,{TYPE_UVEC2,TYPE_UINT,TYPE_UINT,TYPE_VOID}},
+ {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_UINT,TYPE_UVEC2,TYPE_VOID}},
+ {"uvec4",TYPE_UVEC4,{TYPE_UINT,TYPE_UVEC3,TYPE_VOID}},
+ {"uvec4",TYPE_UVEC4,{TYPE_UVEC3,TYPE_UINT,TYPE_VOID}},
+ {"uvec4",TYPE_UVEC4,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}},
+
{"mat2",TYPE_MAT2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
{"mat3",TYPE_MAT3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
{"mat4",TYPE_MAT4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
- //intrinsics - trigonometry
+
+ {"mat2",TYPE_MAT2,{TYPE_FLOAT,TYPE_VOID}},
+ {"mat3",TYPE_MAT3,{TYPE_FLOAT,TYPE_VOID}},
+ {"mat4",TYPE_MAT4,{TYPE_FLOAT,TYPE_VOID}},
+
+ //conversion scalars
+
+ {"int",TYPE_INT,{TYPE_BOOL,TYPE_VOID}},
+ {"int",TYPE_INT,{TYPE_INT,TYPE_VOID}},
+ {"int",TYPE_INT,{TYPE_UINT,TYPE_VOID}},
+ {"int",TYPE_INT,{TYPE_FLOAT,TYPE_VOID}},
+
+ {"float",TYPE_FLOAT,{TYPE_BOOL,TYPE_VOID}},
+ {"float",TYPE_FLOAT,{TYPE_INT,TYPE_VOID}},
+ {"float",TYPE_FLOAT,{TYPE_UINT,TYPE_VOID}},
+ {"float",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
+
+ {"uint",TYPE_UINT,{TYPE_BOOL,TYPE_VOID}},
+ {"uint",TYPE_UINT,{TYPE_INT,TYPE_VOID}},
+ {"uint",TYPE_UINT,{TYPE_UINT,TYPE_VOID}},
+ {"uint",TYPE_UINT,{TYPE_FLOAT,TYPE_VOID}},
+
+ {"bool",TYPE_BOOL,{TYPE_BOOL,TYPE_VOID}},
+ {"bool",TYPE_BOOL,{TYPE_INT,TYPE_VOID}},
+ {"bool",TYPE_BOOL,{TYPE_UINT,TYPE_VOID}},
+ {"bool",TYPE_BOOL,{TYPE_FLOAT,TYPE_VOID}},
+
+ //conversion vectors
+
+ {"ivec2",TYPE_IVEC2,{TYPE_BVEC2,TYPE_VOID}},
+ {"ivec2",TYPE_IVEC2,{TYPE_IVEC2,TYPE_VOID}},
+ {"ivec2",TYPE_IVEC2,{TYPE_UVEC2,TYPE_VOID}},
+ {"ivec2",TYPE_IVEC2,{TYPE_VEC2,TYPE_VOID}},
+
+ {"vec2",TYPE_VEC2,{TYPE_BVEC2,TYPE_VOID}},
+ {"vec2",TYPE_VEC2,{TYPE_IVEC2,TYPE_VOID}},
+ {"vec2",TYPE_VEC2,{TYPE_UVEC2,TYPE_VOID}},
+ {"vec2",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}},
+
+ {"uvec2",TYPE_UVEC2,{TYPE_BVEC2,TYPE_VOID}},
+ {"uvec2",TYPE_UVEC2,{TYPE_IVEC2,TYPE_VOID}},
+ {"uvec2",TYPE_UVEC2,{TYPE_UVEC2,TYPE_VOID}},
+ {"uvec2",TYPE_UVEC2,{TYPE_VEC2,TYPE_VOID}},
+
+ {"bvec2",TYPE_BVEC2,{TYPE_BVEC2,TYPE_VOID}},
+ {"bvec2",TYPE_BVEC2,{TYPE_IVEC2,TYPE_VOID}},
+ {"bvec2",TYPE_BVEC2,{TYPE_UVEC2,TYPE_VOID}},
+ {"bvec2",TYPE_BVEC2,{TYPE_VEC2,TYPE_VOID}},
+
+ {"ivec3",TYPE_IVEC3,{TYPE_BVEC3,TYPE_VOID}},
+ {"ivec3",TYPE_IVEC3,{TYPE_IVEC3,TYPE_VOID}},
+ {"ivec3",TYPE_IVEC3,{TYPE_UVEC3,TYPE_VOID}},
+ {"ivec3",TYPE_IVEC3,{TYPE_VEC3,TYPE_VOID}},
+
+ {"vec3",TYPE_VEC3,{TYPE_BVEC3,TYPE_VOID}},
+ {"vec3",TYPE_VEC3,{TYPE_IVEC3,TYPE_VOID}},
+ {"vec3",TYPE_VEC3,{TYPE_UVEC3,TYPE_VOID}},
+ {"vec3",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}},
+
+ {"uvec3",TYPE_UVEC3,{TYPE_BVEC3,TYPE_VOID}},
+ {"uvec3",TYPE_UVEC3,{TYPE_IVEC3,TYPE_VOID}},
+ {"uvec3",TYPE_UVEC3,{TYPE_UVEC3,TYPE_VOID}},
+ {"uvec3",TYPE_UVEC3,{TYPE_VEC3,TYPE_VOID}},
+
+ {"bvec3",TYPE_BVEC3,{TYPE_BVEC3,TYPE_VOID}},
+ {"bvec3",TYPE_BVEC3,{TYPE_IVEC3,TYPE_VOID}},
+ {"bvec3",TYPE_BVEC3,{TYPE_UVEC3,TYPE_VOID}},
+ {"bvec3",TYPE_BVEC3,{TYPE_VEC3,TYPE_VOID}},
+
+ {"ivec4",TYPE_IVEC4,{TYPE_BVEC4,TYPE_VOID}},
+ {"ivec4",TYPE_IVEC4,{TYPE_IVEC4,TYPE_VOID}},
+ {"ivec4",TYPE_IVEC4,{TYPE_UVEC4,TYPE_VOID}},
+ {"ivec4",TYPE_IVEC4,{TYPE_VEC4,TYPE_VOID}},
+
+ {"vec4",TYPE_VEC4,{TYPE_BVEC4,TYPE_VOID}},
+ {"vec4",TYPE_VEC4,{TYPE_IVEC4,TYPE_VOID}},
+ {"vec4",TYPE_VEC4,{TYPE_UVEC4,TYPE_VOID}},
+ {"vec4",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}},
+
+ {"uvec4",TYPE_UVEC4,{TYPE_BVEC4,TYPE_VOID}},
+ {"uvec4",TYPE_UVEC4,{TYPE_IVEC4,TYPE_VOID}},
+ {"uvec4",TYPE_UVEC4,{TYPE_UVEC4,TYPE_VOID}},
+ {"uvec4",TYPE_UVEC4,{TYPE_VEC4,TYPE_VOID}},
+
+ {"bvec4",TYPE_BVEC4,{TYPE_BVEC4,TYPE_VOID}},
+ {"bvec4",TYPE_BVEC4,{TYPE_IVEC4,TYPE_VOID}},
+ {"bvec4",TYPE_BVEC4,{TYPE_UVEC4,TYPE_VOID}},
+ {"bvec4",TYPE_BVEC4,{TYPE_VEC4,TYPE_VOID}},
+
+ //builtins - trigonometry
{"sin",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
{"cos",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
{"tan",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
@@ -805,7 +1349,7 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={
{"sinh",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
{"cosh",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
{"tanh",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
- //intrinsics - exponential
+ //builtins - exponential
{"pow",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}},
{"pow",TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}},
{"pow",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
@@ -825,15 +1369,34 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={
{"sqrt",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}},
{"sqrt",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}},
{"sqrt",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}},
- //intrinsics - common
+ //builtins - common
{"abs",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
{"abs",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}},
{"abs",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}},
{"abs",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}},
+
+ {"abs",TYPE_INT,{TYPE_INT,TYPE_VOID}},
+ {"abs",TYPE_IVEC2,{TYPE_IVEC2,TYPE_VOID}},
+ {"abs",TYPE_IVEC3,{TYPE_IVEC3,TYPE_VOID}},
+ {"abs",TYPE_IVEC4,{TYPE_IVEC4,TYPE_VOID}},
+
+ {"abs",TYPE_UINT,{TYPE_UINT,TYPE_VOID}},
+ {"abs",TYPE_UVEC2,{TYPE_UVEC2,TYPE_VOID}},
+ {"abs",TYPE_UVEC3,{TYPE_UVEC3,TYPE_VOID}},
+ {"abs",TYPE_UVEC4,{TYPE_UVEC4,TYPE_VOID}},
+
+
{"sign",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
{"sign",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}},
{"sign",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}},
{"sign",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}},
+
+ {"sign",TYPE_INT,{TYPE_INT,TYPE_VOID}},
+ {"sign",TYPE_IVEC2,{TYPE_IVEC2,TYPE_VOID}},
+ {"sign",TYPE_IVEC3,{TYPE_IVEC3,TYPE_VOID}},
+ {"sign",TYPE_IVEC4,{TYPE_IVEC4,TYPE_VOID}},
+
+
{"floor",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
{"floor",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}},
{"floor",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}},
@@ -854,18 +1417,51 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={
{"fract",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}},
{"fract",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}},
{"fract",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}},
+
{"mod",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}},
{"mod",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"mod",TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}},
{"mod",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
+ {"mod",TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
{"mod",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
+ {"mod",TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}},
+
+ {"modf",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}},
+ {"modf",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"modf",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
+ {"modf",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
+
{"min",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}},
{"min",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
{"min",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
{"min",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
+
+ {"min",TYPE_INT,{TYPE_INT,TYPE_INT,TYPE_VOID}},
+ {"min",TYPE_IVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}},
+ {"min",TYPE_IVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}},
+ {"min",TYPE_IVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}},
+
+ {"min",TYPE_UINT,{TYPE_UINT,TYPE_UINT,TYPE_VOID}},
+ {"min",TYPE_UVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}},
+ {"min",TYPE_UVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}},
+ {"min",TYPE_UVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}},
+
{"max",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}},
{"max",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
{"max",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
{"max",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
+
+ {"max",TYPE_INT,{TYPE_INT,TYPE_INT,TYPE_VOID}},
+ {"max",TYPE_IVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}},
+ {"max",TYPE_IVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}},
+ {"max",TYPE_IVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}},
+
+ {"max",TYPE_UINT,{TYPE_UINT,TYPE_UINT,TYPE_VOID}},
+ {"max",TYPE_UVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}},
+ {"max",TYPE_UVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}},
+ {"max",TYPE_UVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}},
+
+
{"clamp",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}},
{"clamp",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
{"clamp",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
@@ -873,13 +1469,39 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={
{"clamp",TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}},
{"clamp",TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}},
{"clamp",TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}},
+
+
+ {"clamp",TYPE_INT,{TYPE_INT,TYPE_INT,TYPE_INT,TYPE_VOID}},
+ {"clamp",TYPE_IVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}},
+ {"clamp",TYPE_IVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}},
+ {"clamp",TYPE_IVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}},
+ {"clamp",TYPE_IVEC2,{TYPE_IVEC2,TYPE_INT,TYPE_INT,TYPE_VOID}},
+ {"clamp",TYPE_IVEC3,{TYPE_IVEC3,TYPE_INT,TYPE_INT,TYPE_VOID}},
+ {"clamp",TYPE_IVEC4,{TYPE_IVEC4,TYPE_INT,TYPE_INT,TYPE_VOID}},
+
+ {"clamp",TYPE_UINT,{TYPE_UINT,TYPE_UINT,TYPE_UINT,TYPE_VOID}},
+ {"clamp",TYPE_UVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}},
+ {"clamp",TYPE_UVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}},
+ {"clamp",TYPE_UVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}},
+ {"clamp",TYPE_UVEC2,{TYPE_UVEC2,TYPE_UINT,TYPE_UINT,TYPE_VOID}},
+ {"clamp",TYPE_UVEC3,{TYPE_UVEC3,TYPE_UINT,TYPE_UINT,TYPE_VOID}},
+ {"clamp",TYPE_UVEC4,{TYPE_UVEC4,TYPE_UINT,TYPE_UINT,TYPE_VOID}},
+
{"mix",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}},
+ {"mix",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_BOOL,TYPE_VOID}},
{"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}},
+ {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_BOOL,TYPE_VOID}},
+ {"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_BVEC2,TYPE_VOID}},
{"mix",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
{"mix",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+ {"mix",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_BOOL,TYPE_VOID}},
+ {"mix",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_BVEC3,TYPE_VOID}},
{"mix",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
{"mix",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}},
+ {"mix",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_BOOL,TYPE_VOID}},
+ {"mix",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_BVEC3,TYPE_VOID}},
{"mix",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
+
{"step",TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VOID}},
{"step",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
{"step",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
@@ -895,7 +1517,37 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={
{"smoothstep",TYPE_VEC3,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VEC3,TYPE_VOID}},
{"smoothstep",TYPE_VEC4,{TYPE_FLOAT,TYPE_FLOAT,TYPE_VEC4,TYPE_VOID}},
- //intrinsics - geometric
+ {"isnan",TYPE_BOOL,{TYPE_FLOAT,TYPE_VOID}},
+ {"isnan",TYPE_BOOL,{TYPE_VEC2,TYPE_VOID}},
+ {"isnan",TYPE_BOOL,{TYPE_VEC3,TYPE_VOID}},
+ {"isnan",TYPE_BOOL,{TYPE_VEC4,TYPE_VOID}},
+
+ {"isinf",TYPE_BOOL,{TYPE_FLOAT,TYPE_VOID}},
+ {"isinf",TYPE_BOOL,{TYPE_VEC2,TYPE_VOID}},
+ {"isinf",TYPE_BOOL,{TYPE_VEC3,TYPE_VOID}},
+ {"isinf",TYPE_BOOL,{TYPE_VEC4,TYPE_VOID}},
+
+ {"floatBitsToInt",TYPE_INT,{TYPE_FLOAT,TYPE_VOID}},
+ {"floatBitsToInt",TYPE_IVEC2,{TYPE_VEC2,TYPE_VOID}},
+ {"floatBitsToInt",TYPE_IVEC3,{TYPE_VEC3,TYPE_VOID}},
+ {"floatBitsToInt",TYPE_IVEC4,{TYPE_VEC4,TYPE_VOID}},
+
+ {"floatBitsToUInt",TYPE_UINT,{TYPE_FLOAT,TYPE_VOID}},
+ {"floatBitsToUInt",TYPE_UVEC2,{TYPE_VEC2,TYPE_VOID}},
+ {"floatBitsToUInt",TYPE_UVEC3,{TYPE_VEC3,TYPE_VOID}},
+ {"floatBitsToUInt",TYPE_UVEC4,{TYPE_VEC4,TYPE_VOID}},
+
+ {"intBitsToFloat",TYPE_FLOAT,{TYPE_INT,TYPE_VOID}},
+ {"intBitsToFloat",TYPE_VEC2,{TYPE_IVEC2,TYPE_VOID}},
+ {"intBitsToFloat",TYPE_VEC3,{TYPE_IVEC3,TYPE_VOID}},
+ {"intBitsToFloat",TYPE_VEC4,{TYPE_IVEC4,TYPE_VOID}},
+
+ {"uintBitsToFloat",TYPE_FLOAT,{TYPE_UINT,TYPE_VOID}},
+ {"uintBitsToFloat",TYPE_VEC2,{TYPE_UVEC2,TYPE_VOID}},
+ {"uintBitsToFloat",TYPE_VEC3,{TYPE_UVEC3,TYPE_VOID}},
+ {"uintBitsToFloat",TYPE_VEC4,{TYPE_UVEC4,TYPE_VOID}},
+
+ //builtins - geometric
{"length",TYPE_FLOAT,{TYPE_VEC2,TYPE_VOID}},
{"length",TYPE_FLOAT,{TYPE_VEC3,TYPE_VOID}},
{"length",TYPE_FLOAT,{TYPE_VEC4,TYPE_VOID}},
@@ -911,317 +1563,211 @@ const ShaderLanguage::IntrinsicFuncDef ShaderLanguage::intrinsic_func_defs[]={
{"normalize",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}},
{"reflect",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
{"refract",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
- //intrinsics - texture
- {"tex",TYPE_VEC4,{TYPE_TEXTURE,TYPE_VEC2,TYPE_VOID}},
- {"texcube",TYPE_VEC4,{TYPE_CUBEMAP,TYPE_VEC3,TYPE_VOID}},
- {"texscreen",TYPE_VEC3,{TYPE_VEC2,TYPE_VOID}},
- {"texpos",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}},
- {NULL,TYPE_VOID,{TYPE_VOID}}
+ {"facefordward",TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"facefordward",TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
+ {"facefordward",TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
-};
+ {"matrixCompMult",TYPE_MAT2,{TYPE_MAT2,TYPE_MAT2,TYPE_VOID}},
+ {"matrixCompMult",TYPE_MAT3,{TYPE_MAT3,TYPE_MAT3,TYPE_VOID}},
+ {"matrixCompMult",TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4,TYPE_VOID}},
-const ShaderLanguage::OperatorDef ShaderLanguage::operator_defs[]={
-
- {OP_ASSIGN,TYPE_VOID,{TYPE_BOOL,TYPE_BOOL}},
- {OP_ASSIGN,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_ASSIGN,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}},
- {OP_ASSIGN,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}},
- {OP_ASSIGN,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}},
- {OP_ASSIGN,TYPE_VOID,{TYPE_MAT2,TYPE_MAT2}},
- {OP_ASSIGN,TYPE_VOID,{TYPE_MAT3,TYPE_MAT3}},
- {OP_ASSIGN,TYPE_VOID,{TYPE_MAT4,TYPE_MAT4}},
- {OP_ADD,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_ADD,TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2}},
- {OP_ADD,TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3}},
- {OP_ADD,TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4}},
- {OP_SUB,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_SUB,TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2}},
- {OP_SUB,TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3}},
- {OP_SUB,TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4}},
- {OP_MUL,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2}},
- {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT}},
- {OP_MUL,TYPE_VEC2,{TYPE_FLOAT,TYPE_VEC2}},
- {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT3}},
- {OP_MUL,TYPE_VEC2,{TYPE_MAT2,TYPE_VEC2}},
- {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT2}},
- {OP_MUL,TYPE_VEC2,{TYPE_MAT3,TYPE_VEC2}},
- {OP_MUL,TYPE_VEC2,{TYPE_VEC2,TYPE_MAT4}},
- {OP_MUL,TYPE_VEC2,{TYPE_MAT4,TYPE_VEC2}},
- {OP_MUL,TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3}},
- {OP_MUL,TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT}},
- {OP_MUL,TYPE_VEC3,{TYPE_FLOAT,TYPE_VEC3}},
- {OP_MUL,TYPE_VEC3,{TYPE_MAT3,TYPE_VEC3}},
- {OP_MUL,TYPE_VEC3,{TYPE_MAT4,TYPE_VEC3}},
- {OP_MUL,TYPE_VEC3,{TYPE_VEC3,TYPE_MAT3}},
- {OP_MUL,TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4}},
- {OP_MUL,TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT}},
- {OP_MUL,TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC4}},
- {OP_MUL,TYPE_VEC4,{TYPE_MAT4,TYPE_VEC4}},
- {OP_MUL,TYPE_VEC4,{TYPE_VEC4,TYPE_MAT4}},
- {OP_MUL,TYPE_MAT2,{TYPE_MAT2,TYPE_MAT2}},
- {OP_MUL,TYPE_MAT3,{TYPE_MAT3,TYPE_MAT3}},
- {OP_MUL,TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4}},
- {OP_DIV,TYPE_FLOAT,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_DIV,TYPE_VEC2,{TYPE_VEC2,TYPE_VEC2}},
- {OP_DIV,TYPE_VEC2,{TYPE_VEC2,TYPE_FLOAT}},
- {OP_DIV,TYPE_VEC2,{TYPE_FLOAT,TYPE_VEC2}},
- {OP_DIV,TYPE_VEC3,{TYPE_VEC3,TYPE_VEC3}},
- {OP_DIV,TYPE_VEC3,{TYPE_VEC3,TYPE_FLOAT}},
- {OP_DIV,TYPE_VEC3,{TYPE_FLOAT,TYPE_VEC3}},
- {OP_DIV,TYPE_VEC4,{TYPE_VEC4,TYPE_VEC4}},
- {OP_DIV,TYPE_VEC4,{TYPE_VEC4,TYPE_FLOAT}},
- {OP_DIV,TYPE_VEC4,{TYPE_FLOAT,TYPE_VEC4}},
- {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}},
- {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}},
- {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}},
- {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}},
- {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}},
- {OP_ASSIGN_ADD,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}},
- {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}},
- {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}},
- {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}},
- {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}},
- {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}},
- {OP_ASSIGN_SUB,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC2,TYPE_MAT2}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT2,TYPE_MAT2}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_MAT3}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC3,TYPE_MAT4}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_VEC4,TYPE_MAT4}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT3,TYPE_MAT3}},
- {OP_ASSIGN_MUL,TYPE_VOID,{TYPE_MAT4,TYPE_MAT4}},
- {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC2,TYPE_VEC2}},
- {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC2,TYPE_FLOAT}},
- {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC3,TYPE_VEC3}},
- {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC3,TYPE_FLOAT}},
- {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC4,TYPE_VEC4}},
- {OP_ASSIGN_DIV,TYPE_VOID,{TYPE_VEC4,TYPE_FLOAT}},
- {OP_NEG,TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
- {OP_NEG,TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}},
- {OP_NEG,TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}},
- {OP_NEG,TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}},
- {OP_NOT,TYPE_BOOL,{TYPE_BOOL,TYPE_VOID}},
- {OP_CMP_EQ,TYPE_BOOL,{TYPE_BOOL,TYPE_BOOL}},
- {OP_CMP_EQ,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_CMP_EQ,TYPE_BOOL,{TYPE_VEC3,TYPE_VEC2}},
- {OP_CMP_EQ,TYPE_BOOL,{TYPE_VEC3,TYPE_VEC3}},
- {OP_CMP_EQ,TYPE_BOOL,{TYPE_VEC3,TYPE_VEC4}},
- //{OP_CMP_EQ,TYPE_MAT3,{TYPE_MAT4,TYPE_MAT3}}, ??
- //{OP_CMP_EQ,TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4}}, ??
- {OP_CMP_NEQ,TYPE_BOOL,{TYPE_BOOL,TYPE_BOOL}},
- {OP_CMP_NEQ,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_CMP_NEQ,TYPE_BOOL,{TYPE_VEC2,TYPE_VEC2}},
- {OP_CMP_NEQ,TYPE_BOOL,{TYPE_VEC3,TYPE_VEC3}},
- {OP_CMP_NEQ,TYPE_BOOL,{TYPE_VEC4,TYPE_VEC4}},
- //{OP_CMP_NEQ,TYPE_MAT4,{TYPE_MAT4,TYPE_MAT4}}, //?
- {OP_CMP_LEQ,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_CMP_GEQ,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_CMP_LESS,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_CMP_GREATER,TYPE_BOOL,{TYPE_FLOAT,TYPE_FLOAT}},
- {OP_CMP_OR,TYPE_BOOL,{TYPE_BOOL,TYPE_BOOL}},
- {OP_CMP_AND,TYPE_BOOL,{TYPE_BOOL,TYPE_BOOL}},
- {OP_MAX,TYPE_VOID,{TYPE_VOID,TYPE_VOID}}
-};
+ {"outerProduct",TYPE_MAT2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"outerProduct",TYPE_MAT3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
+ {"outerProduct",TYPE_MAT4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
+ {"transpose",TYPE_MAT2,{TYPE_MAT2,TYPE_VOID}},
+ {"transpose",TYPE_MAT3,{TYPE_MAT3,TYPE_VOID}},
+ {"transpose",TYPE_MAT4,{TYPE_MAT4,TYPE_VOID}},
-const ShaderLanguage::BuiltinsDef ShaderLanguage::vertex_builtins_defs[]={
-
- { "SRC_VERTEX", TYPE_VEC3},
- { "SRC_NORMAL", TYPE_VEC3},
- { "SRC_TANGENT", TYPE_VEC3},
- { "SRC_BINORMALF", TYPE_FLOAT},
-
- { "POSITION", TYPE_VEC4 },
- { "VERTEX", TYPE_VEC3},
- { "NORMAL", TYPE_VEC3},
- { "TANGENT", TYPE_VEC3},
- { "BINORMAL", TYPE_VEC3},
- { "UV", TYPE_VEC2},
- { "UV2", TYPE_VEC2},
- { "COLOR", TYPE_VEC4},
- { "BONES", TYPE_VEC4},
- { "WEIGHTS", TYPE_VEC4},
- { "VAR1", TYPE_VEC4},
- { "VAR2", TYPE_VEC4},
- { "SPEC_EXP", TYPE_FLOAT},
- { "POINT_SIZE", TYPE_FLOAT},
-
- //builtins
- { "WORLD_MATRIX", TYPE_MAT4},
- { "INV_CAMERA_MATRIX", TYPE_MAT4},
- { "PROJECTION_MATRIX", TYPE_MAT4},
- { "MODELVIEW_MATRIX", TYPE_MAT4},
- { "INSTANCE_ID", TYPE_FLOAT},
- { "TIME", TYPE_FLOAT},
- { NULL, TYPE_VOID},
-};
-const ShaderLanguage::BuiltinsDef ShaderLanguage::fragment_builtins_defs[]={
-
- { "VERTEX", TYPE_VEC3},
- { "POSITION", TYPE_VEC4},
- { "NORMAL", TYPE_VEC3},
- { "TANGENT", TYPE_VEC3},
- { "BINORMAL", TYPE_VEC3},
- { "NORMALMAP", TYPE_VEC3},
- { "NORMALMAP_DEPTH", TYPE_FLOAT},
- { "UV", TYPE_VEC2},
- { "UV2", TYPE_VEC2},
- { "COLOR", TYPE_VEC4},
- { "NORMAL", TYPE_VEC3},
- { "VAR1", TYPE_VEC4},
- { "VAR2", TYPE_VEC4},
- { "DIFFUSE", TYPE_VEC3},
- { "DIFFUSE_ALPHA", TYPE_VEC4},
- { "SPECULAR", TYPE_VEC3},
- { "EMISSION", TYPE_VEC3},
- { "SPEC_EXP", TYPE_FLOAT},
- { "GLOW", TYPE_FLOAT},
- { "SHADE_PARAM", TYPE_FLOAT},
- { "DISCARD", TYPE_BOOL},
- { "SCREEN_UV", TYPE_VEC2},
- { "POINT_COORD", TYPE_VEC2},
- { "INV_CAMERA_MATRIX", TYPE_MAT4},
-
-// { "SCREEN_POS", TYPE_VEC2},
-// { "SCREEN_TEXEL_SIZE", TYPE_VEC2},
- { "TIME", TYPE_FLOAT},
- { NULL, TYPE_VOID}
+ {"determinant",TYPE_FLOAT,{TYPE_MAT2,TYPE_VOID}},
+ {"determinant",TYPE_FLOAT,{TYPE_MAT3,TYPE_VOID}},
+ {"determinant",TYPE_FLOAT,{TYPE_MAT4,TYPE_VOID}},
-};
+ {"inverse",TYPE_MAT2,{TYPE_MAT2,TYPE_VOID}},
+ {"inverse",TYPE_MAT3,{TYPE_MAT3,TYPE_VOID}},
+ {"inverse",TYPE_MAT4,{TYPE_MAT4,TYPE_VOID}},
-const ShaderLanguage::BuiltinsDef ShaderLanguage::light_builtins_defs[]={
-
- { "NORMAL", TYPE_VEC3},
- { "LIGHT_DIR", TYPE_VEC3},
- { "LIGHT_DIFFUSE", TYPE_VEC3},
- { "LIGHT_SPECULAR", TYPE_VEC3},
- { "EYE_VEC", TYPE_VEC3},
- { "DIFFUSE", TYPE_VEC3},
- { "SPECULAR", TYPE_VEC3},
- { "SPECULAR_EXP", TYPE_FLOAT},
- { "SHADE_PARAM", TYPE_FLOAT},
- { "LIGHT", TYPE_VEC3},
- { "SHADOW", TYPE_VEC3 },
- { "POINT_COORD", TYPE_VEC2 },
-// { "SCREEN_POS", TYPE_VEC2},
-// { "SCREEN_TEXEL_SIZE", TYPE_VEC2},
- { "TIME", TYPE_FLOAT},
- { NULL, TYPE_VOID}
-};
+ {"lessThan",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"lessThan",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
+ {"lessThan",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
+ {"lessThan",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}},
+ {"lessThan",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}},
+ {"lessThan",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}},
+ {"lessThan",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}},
+ {"lessThan",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}},
+ {"lessThan",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}},
-const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_vertex_builtins_defs[]={
+ {"greaterThan",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"greaterThan",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
+ {"greaterThan",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
- { "SRC_VERTEX", TYPE_VEC2},
- { "VERTEX", TYPE_VEC2},
- { "WORLD_VERTEX", TYPE_VEC2},
- { "UV", TYPE_VEC2},
- { "COLOR", TYPE_VEC4},
- { "VAR1", TYPE_VEC4},
- { "VAR2", TYPE_VEC4},
- { "POINT_SIZE", TYPE_FLOAT},
+ {"greaterThan",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}},
+ {"greaterThan",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}},
+ {"greaterThan",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}},
- //builtins
- { "WORLD_MATRIX", TYPE_MAT4},
- { "PROJECTION_MATRIX", TYPE_MAT4},
- { "EXTRA_MATRIX", TYPE_MAT4},
- { "TIME", TYPE_FLOAT},
- { NULL, TYPE_VOID},
-};
-const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_fragment_builtins_defs[]={
-
- { "SRC_COLOR", TYPE_VEC4},
- { "POSITION", TYPE_VEC4},
- { "NORMAL", TYPE_VEC3},
- { "NORMALMAP", TYPE_VEC3},
- { "NORMALMAP_DEPTH", TYPE_FLOAT},
- { "UV", TYPE_VEC2},
- { "COLOR", TYPE_VEC4},
- { "TEXTURE", TYPE_TEXTURE},
- { "TEXTURE_PIXEL_SIZE", TYPE_VEC2},
- { "VAR1", TYPE_VEC4},
- { "VAR2", TYPE_VEC4},
- { "SCREEN_UV", TYPE_VEC2},
- { "POINT_COORD", TYPE_VEC2},
-
-// { "SCREEN_POS", TYPE_VEC2},
-// { "SCREEN_TEXEL_SIZE", TYPE_VEC2},
- { "TIME", TYPE_FLOAT},
- { NULL, TYPE_VOID}
+ {"greaterThan",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}},
+ {"greaterThan",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}},
+ {"greaterThan",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}},
-};
+ {"lessThanEqual",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"lessThanEqual",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
+ {"lessThanEqual",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
-const ShaderLanguage::BuiltinsDef ShaderLanguage::ci_light_builtins_defs[]={
-
- { "POSITION", TYPE_VEC4},
- { "NORMAL", TYPE_VEC3},
- { "UV", TYPE_VEC2},
- { "COLOR", TYPE_VEC4},
- { "TEXTURE", TYPE_TEXTURE},
- { "TEXTURE_PIXEL_SIZE", TYPE_VEC2},
- { "VAR1", TYPE_VEC4},
- { "VAR2", TYPE_VEC4},
- { "SCREEN_UV", TYPE_VEC2},
- { "LIGHT_VEC", TYPE_VEC2},
- { "LIGHT_HEIGHT", TYPE_FLOAT},
- { "LIGHT_COLOR", TYPE_VEC4},
- { "LIGHT_UV", TYPE_VEC2},
- { "LIGHT", TYPE_VEC4},
- { "SHADOW", TYPE_VEC4},
- { "POINT_COORD", TYPE_VEC2},
-// { "SCREEN_POS", TYPE_VEC2},
-// { "SCREEN_TEXEL_SIZE", TYPE_VEC2},
- { "TIME", TYPE_FLOAT},
- { NULL, TYPE_VOID}
+ {"lessThanEqual",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}},
+ {"lessThanEqual",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}},
+ {"lessThanEqual",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}},
-};
+ {"lessThanEqual",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}},
+ {"lessThanEqual",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}},
+ {"lessThanEqual",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}},
-const ShaderLanguage::BuiltinsDef ShaderLanguage::postprocess_fragment_builtins_defs[]={
+ {"greaterThanEqual",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"greaterThanEqual",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
+ {"greaterThanEqual",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
- { "IN_COLOR", TYPE_VEC3},
- { "IN_POSITION", TYPE_VEC3},
- { "OUT_COLOR", TYPE_VEC3},
- { "SCREEN_POS", TYPE_VEC2},
- { "SCREEN_TEXEL_SIZE", TYPE_VEC2},
- { "TIME", TYPE_FLOAT},
- { NULL, TYPE_VOID}
-};
+ {"greaterThanEqual",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}},
+ {"greaterThanEqual",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}},
+ {"greaterThanEqual",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}},
+ {"greaterThanEqual",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}},
+ {"greaterThanEqual",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}},
+ {"greaterThanEqual",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}},
+ {"equal",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"equal",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
+ {"equal",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
-ShaderLanguage::DataType ShaderLanguage::compute_node_type(Node *p_node) {
+ {"equal",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}},
+ {"equal",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}},
+ {"equal",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}},
- switch(p_node->type) {
+ {"equal",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}},
+ {"equal",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}},
+ {"equal",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}},
- case Node::TYPE_PROGRAM: ERR_FAIL_V(TYPE_VOID);
- case Node::TYPE_FUNCTION: return static_cast<FunctionNode*>(p_node)->return_type;
- case Node::TYPE_BLOCK: ERR_FAIL_V(TYPE_VOID);
- case Node::TYPE_VARIABLE: return static_cast<VariableNode*>(p_node)->datatype_cache;
- case Node::TYPE_CONSTANT: return static_cast<ConstantNode*>(p_node)->datatype;
- case Node::TYPE_OPERATOR: return static_cast<OperatorNode*>(p_node)->return_cache;
- case Node::TYPE_CONTROL_FLOW: ERR_FAIL_V(TYPE_VOID);
- case Node::TYPE_MEMBER: return static_cast<MemberNode*>(p_node)->datatype;
- }
+ {"equal",TYPE_BVEC2,{TYPE_BVEC2,TYPE_BVEC2,TYPE_VOID}},
+ {"equal",TYPE_BVEC3,{TYPE_BVEC3,TYPE_BVEC3,TYPE_VOID}},
+ {"equal",TYPE_BVEC4,{TYPE_BVEC4,TYPE_BVEC4,TYPE_VOID}},
- return TYPE_VOID;
-}
+ {"notEqual",TYPE_BVEC2,{TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"notEqual",TYPE_BVEC3,{TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
+ {"notEqual",TYPE_BVEC4,{TYPE_VEC4,TYPE_VEC4,TYPE_VOID}},
+
+ {"notEqual",TYPE_BVEC2,{TYPE_IVEC2,TYPE_IVEC2,TYPE_VOID}},
+ {"notEqual",TYPE_BVEC3,{TYPE_IVEC3,TYPE_IVEC3,TYPE_VOID}},
+ {"notEqual",TYPE_BVEC4,{TYPE_IVEC4,TYPE_IVEC4,TYPE_VOID}},
+ {"notEqual",TYPE_BVEC2,{TYPE_UVEC2,TYPE_UVEC2,TYPE_VOID}},
+ {"notEqual",TYPE_BVEC3,{TYPE_UVEC3,TYPE_UVEC3,TYPE_VOID}},
+ {"notEqual",TYPE_BVEC4,{TYPE_UVEC4,TYPE_UVEC4,TYPE_VOID}},
-ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, OperatorNode *p_func) {
+ {"notEqual",TYPE_BVEC2,{TYPE_BVEC2,TYPE_BVEC2,TYPE_VOID}},
+ {"notEqual",TYPE_BVEC3,{TYPE_BVEC3,TYPE_BVEC3,TYPE_VOID}},
+ {"notEqual",TYPE_BVEC4,{TYPE_BVEC4,TYPE_BVEC4,TYPE_VOID}},
+
+ {"any",TYPE_BOOL,{TYPE_BVEC2,TYPE_VOID}},
+ {"any",TYPE_BOOL,{TYPE_BVEC3,TYPE_VOID}},
+ {"any",TYPE_BOOL,{TYPE_BVEC4,TYPE_VOID}},
+
+ {"all",TYPE_BOOL,{TYPE_BVEC2,TYPE_VOID}},
+ {"all",TYPE_BOOL,{TYPE_BVEC3,TYPE_VOID}},
+ {"all",TYPE_BOOL,{TYPE_BVEC4,TYPE_VOID}},
+
+ {"not",TYPE_BOOL,{TYPE_BVEC2,TYPE_VOID}},
+ {"not",TYPE_BOOL,{TYPE_BVEC3,TYPE_VOID}},
+ {"not",TYPE_BOOL,{TYPE_BVEC4,TYPE_VOID}},
+
+ //builtins - texture
+ {"textureSize",TYPE_VEC2,{TYPE_SAMPLER2D,TYPE_INT,TYPE_VOID}},
+ {"textureSize",TYPE_VEC2,{TYPE_ISAMPLER2D,TYPE_INT,TYPE_VOID}},
+ {"textureSize",TYPE_VEC2,{TYPE_USAMPLER2D,TYPE_INT,TYPE_VOID}},
+ {"textureSize",TYPE_VEC2,{TYPE_SAMPLERCUBE,TYPE_INT,TYPE_VOID}},
+
+ {"texture",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC2,TYPE_VOID}},
+ {"texture",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_VOID}},
+ {"texture",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}},
+ {"texture",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+
+ {"texture",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC2,TYPE_VOID}},
+ {"texture",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_VOID}},
+ {"texture",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}},
+ {"texture",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+
+ {"texture",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC2,TYPE_VOID}},
+ {"texture",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_VOID}},
+ {"texture",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC2,TYPE_FLOAT,TYPE_VOID}},
+ {"texture",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+
+ {"texture",TYPE_VEC4,{TYPE_SAMPLERCUBE,TYPE_VEC3,TYPE_VOID}},
+ {"texture",TYPE_VEC4,{TYPE_SAMPLERCUBE,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+
+ {"textureProj",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_VOID}},
+ {"textureProj",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC4,TYPE_VOID}},
+ {"textureProj",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+ {"textureProj",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}},
+
+ {"textureProj",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_VOID}},
+ {"textureProj",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC4,TYPE_VOID}},
+ {"textureProj",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+ {"textureProj",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}},
+
+ {"textureProj",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_VOID}},
+ {"textureProj",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC4,TYPE_VOID}},
+ {"textureProj",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+ {"textureProj",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}},
+
+ {"textureLod",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+ {"textureLod",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+ {"textureLod",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+ {"textureLod",TYPE_VEC4,{TYPE_SAMPLERCUBE,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+
+ {"texelFetch",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_IVEC2,TYPE_INT,TYPE_VOID}},
+ {"texelFetch",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_IVEC2,TYPE_INT,TYPE_VOID}},
+ {"texelFetch",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_IVEC2,TYPE_INT,TYPE_VOID}},
+
+ {"textureProjLod",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+ {"textureProjLod",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}},
+
+ {"textureProjLod",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+ {"textureProjLod",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}},
+
+ {"textureProjLod",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC3,TYPE_FLOAT,TYPE_VOID}},
+ {"textureProjLod",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC4,TYPE_FLOAT,TYPE_VOID}},
+
+ {"textureGrad",TYPE_VEC4,{TYPE_SAMPLER2D,TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"textureGrad",TYPE_IVEC4,{TYPE_ISAMPLER2D,TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"textureGrad",TYPE_UVEC4,{TYPE_USAMPLER2D,TYPE_VEC2,TYPE_VEC2,TYPE_VEC2,TYPE_VOID}},
+ {"textureGrad",TYPE_VEC4,{TYPE_SAMPLERCUBE,TYPE_VEC3,TYPE_VEC3,TYPE_VEC3,TYPE_VOID}},
+
+ {"textureScreen",TYPE_VEC4,{TYPE_VEC2,TYPE_VOID}},
+
+ {"dFdx",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
+ {"dFdx",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}},
+ {"dFdx",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}},
+ {"dFdx",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}},
+
+ {"dFdy",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
+ {"dFdy",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}},
+ {"dFdy",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}},
+ {"dFdy",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}},
+
+ {"fwidth",TYPE_FLOAT,{TYPE_FLOAT,TYPE_VOID}},
+ {"fwidth",TYPE_VEC2,{TYPE_VEC2,TYPE_VOID}},
+ {"fwidth",TYPE_VEC3,{TYPE_VEC3,TYPE_VOID}},
+ {"fwidth",TYPE_VEC4,{TYPE_VEC4,TYPE_VOID}},
+
+
+ {NULL,TYPE_VOID,{TYPE_VOID}}
+
+};
+
+
+
+bool ShaderLanguage::_validate_function_call(BlockNode* p_block, OperatorNode *p_func,DataType *r_ret_type) {
ERR_FAIL_COND_V(p_func->op!=OP_CALL && p_func->op!=OP_CONSTRUCT,NULL);
@@ -1230,44 +1776,49 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper
ERR_FAIL_COND_V( p_func->arguments[0]->type!=Node::TYPE_VARIABLE, NULL );
- String name = static_cast<VariableNode*>(p_func->arguments[0])->name.operator String();
+ StringName name = static_cast<VariableNode*>(p_func->arguments[0])->name.operator String();
bool all_const=true;
for(int i=1;i<p_func->arguments.size();i++) {
if (p_func->arguments[i]->type!=Node::TYPE_CONSTANT)
all_const=false;
- args.push_back(compute_node_type(p_func->arguments[i]));
+ args.push_back(p_func->arguments[i]->get_datatype());
}
int argcount=args.size();
- bool found_intrinsic=false;
+ bool failed_builtin=false;
+
if (argcount<=4) {
- // test intrinsics
+ // test builtins
int idx=0;
- while (intrinsic_func_defs[idx].name) {
+ while (builtin_func_defs[idx].name) {
- if (name==intrinsic_func_defs[idx].name) {
+ if (name==builtin_func_defs[idx].name) {
+ failed_builtin=true;
bool fail=false;
for(int i=0;i<argcount;i++) {
- if (args[i]!=intrinsic_func_defs[idx].args[i]) {
+ if (get_scalar_type(args[i])==args[i] && p_func->arguments[i+1]->type==Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode*>(p_func->arguments[i+1]),builtin_func_defs[idx].args[i])) {
+ //all good
+ } else if (args[i]!=builtin_func_defs[idx].args[i]) {
fail=true;
break;
}
}
- if (!fail && argcount<4 && intrinsic_func_defs[idx].args[argcount]!=TYPE_VOID)
+ if (!fail && argcount<4 && builtin_func_defs[idx].args[argcount]!=TYPE_VOID)
fail=true; //make sure the number of arguments matches
if (!fail) {
- p_func->return_cache=intrinsic_func_defs[idx].rettype;
- found_intrinsic=true;
- break;
+ if (r_ret_type)
+ *r_ret_type=builtin_func_defs[idx].rettype;
+
+ return true;
}
}
@@ -1276,8 +1827,24 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper
}
}
+ if (failed_builtin) {
+ String err ="Invalid arguments for built-in function: "+String(name)+"(";
+ for(int i=0;i<argcount;i++) {
+ if (i>0)
+ err+=",";
+
+ if (p_func->arguments[i+1]->type==Node::TYPE_CONSTANT && p_func->arguments[i+1]->get_datatype()==TYPE_INT && static_cast<ConstantNode*>(p_func->arguments[i+1])->values[0].sint<0) {
+ err+="-";
+ }
+ err+=get_datatype_name(args[i]);
+ }
+ err+=")";
+ _set_error(err);
+ return false;
+ }
- if (found_intrinsic) {
+#if 0
+ if (found_builtin) {
if (p_func->op==OP_CONSTRUCT && all_const) {
@@ -1289,6 +1856,7 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper
switch(v.get_type()) {
case Variant::REAL: cdata.push_back(v); break;
+ case Variant::INT: cdata.push_back(v); break;
case Variant::VECTOR2: { Vector2 v2=v; cdata.push_back(v2.x); cdata.push_back(v2.y); } break;
case Variant::VECTOR3: { Vector3 v3=v; cdata.push_back(v3.x); cdata.push_back(v3.y); cdata.push_back(v3.z);} break;
case Variant::PLANE: { Plane v4=v; cdata.push_back(v4.normal.x); cdata.push_back(v4.normal.y); cdata.push_back(v4.normal.z); cdata.push_back(v4.d); } break;
@@ -1330,193 +1898,335 @@ ShaderLanguage::Node* ShaderLanguage::validate_function_call(Parser&parser, Oper
}
return p_func;
}
-
+#endif
// try existing functions..
- FunctionNode *exclude_function=NULL; //exclude current function (in case inside one)
-
-
- Node *node = p_func;
+ StringName exclude_function;
+ BlockNode *block = p_block;
- while(node->parent) {
+ while(block) {
- if (node->type==Node::TYPE_FUNCTION) {
-
- exclude_function = (FunctionNode*)node;
+ if (block->parent_function) {
+ exclude_function=block->parent_function->name;
}
+ block=block->parent_block;
+ }
- node=node->parent;
+ if (name==exclude_function) {
+ _set_error("Recursion is not allowed");
+ return false;
}
- ERR_FAIL_COND_V(node->type!=Node::TYPE_PROGRAM,NULL);
- ProgramNode *program = (ProgramNode*)node;
+ for(int i=0;i<shader->functions.size();i++) {
- for(int i=0;i<program->functions.size();i++) {
- if (program->functions[i].function==exclude_function)
+ if (name != shader->functions[i].name)
continue;
- FunctionNode *pfunc = program->functions[i].function;
+ if (!shader->functions[i].callable) {
+ _set_error("Function '"+String(name)+" can't be called from source code.");
+ return false;
+ }
+
+ FunctionNode *pfunc = shader->functions[i].function;
+
if (pfunc->arguments.size()!=args.size())
continue;
bool fail=false;
+
for(int i=0;i<args.size();i++) {
- if (args[i]!=pfunc->arguments[i].type) {
+
+ if (get_scalar_type(args[i])==args[i] && p_func->arguments[i+1]->type==Node::TYPE_CONSTANT && convert_constant(static_cast<ConstantNode*>(p_func->arguments[i+1]),pfunc->arguments[i].type)) {
+ //all good
+ } else if (args[i]!=pfunc->arguments[i].type) {
fail=true;
break;
}
}
- if (!fail && name == program->functions[i].name) {
+ if (!fail) {
p_func->return_cache=pfunc->return_type;
- return p_func;
+ return true;
}
}
- return NULL;
+ return false;
}
-ShaderLanguage::Node * ShaderLanguage::validate_operator(Parser& parser,OperatorNode *p_func) {
+bool ShaderLanguage::_parse_function_arguments(BlockNode* p_block,const Map<StringName,DataType> &p_builtin_types,OperatorNode* p_func,int *r_complete_arg) {
- int argcount = p_func->arguments.size();
- ERR_FAIL_COND_V(argcount>2,NULL);
+ TkPos pos = _get_tkpos();
+ Token tk = _get_token();
- DataType argtype[2]={TYPE_VOID,TYPE_VOID};
- bool all_const=true;
+ if (tk.type==TK_PARENTHESIS_CLOSE) {
+ return true;
+ }
- for(int i=0;i<argcount;i++) {
+ _set_tkpos(pos);
+
+
+ while(true) {
+
+
+ if (r_complete_arg) {
+ pos = _get_tkpos();
+ tk = _get_token();
+
+ if (tk.type==TK_CURSOR) {
+
+ *r_complete_arg=p_func->arguments.size()-1;
+ } else {
+
+ _set_tkpos(pos);
+ }
+ }
+
+ Node *arg= _parse_and_reduce_expression(p_block,p_builtin_types);
+
+ if (!arg) {
+
+ return false;
+ }
+
+
+ p_func->arguments.push_back(arg);
+
+ tk = _get_token();
+
+
+ if (tk.type==TK_PARENTHESIS_CLOSE) {
+
+ return true;
+ } else if (tk.type!=TK_COMMA) {
+ // something is broken
+ _set_error("Expected ',' or ')' after argument");
+ return false;
+ }
- argtype[i]=compute_node_type(p_func->arguments[i]);
- if (p_func->arguments[i]->type!=Node::TYPE_CONSTANT)
- all_const=false;
}
- int idx=0;
- bool valid=false;
- while(operator_defs[idx].op!=OP_MAX) {
+ return true;
+}
+
+bool ShaderLanguage::is_token_operator(TokenType p_type) {
- if (p_func->op==operator_defs[idx].op) {
+ return (p_type==TK_OP_EQUAL ||
+ p_type==TK_OP_NOT_EQUAL ||
+ p_type==TK_OP_LESS ||
+ p_type==TK_OP_LESS_EQUAL ||
+ p_type==TK_OP_GREATER ||
+ p_type==TK_OP_GREATER_EQUAL ||
+ p_type==TK_OP_AND ||
+ p_type==TK_OP_OR ||
+ p_type==TK_OP_NOT ||
+ p_type==TK_OP_ADD ||
+ p_type==TK_OP_SUB ||
+ p_type==TK_OP_MUL ||
+ p_type==TK_OP_DIV ||
+ p_type==TK_OP_MOD ||
+ p_type==TK_OP_SHIFT_LEFT ||
+ p_type==TK_OP_SHIFT_RIGHT ||
+ p_type==TK_OP_ASSIGN ||
+ p_type==TK_OP_ASSIGN_ADD ||
+ p_type==TK_OP_ASSIGN_SUB ||
+ p_type==TK_OP_ASSIGN_MUL ||
+ p_type==TK_OP_ASSIGN_DIV ||
+ p_type==TK_OP_ASSIGN_MOD ||
+ p_type==TK_OP_ASSIGN_SHIFT_LEFT ||
+ p_type==TK_OP_ASSIGN_SHIFT_RIGHT ||
+ p_type==TK_OP_ASSIGN_BIT_AND ||
+ p_type==TK_OP_ASSIGN_BIT_OR ||
+ p_type==TK_OP_ASSIGN_BIT_XOR ||
+ p_type==TK_OP_BIT_AND ||
+ p_type==TK_OP_BIT_OR ||
+ p_type==TK_OP_BIT_XOR ||
+ p_type==TK_OP_BIT_INVERT ||
+ p_type==TK_OP_INCREMENT ||
+ p_type==TK_OP_DECREMENT ||
+ p_type==TK_QUESTION ||
+ p_type==TK_COLON );
+}
- if (operator_defs[idx].args[0]==argtype[0] && operator_defs[idx].args[1]==argtype[1]) {
+bool ShaderLanguage::convert_constant(ConstantNode* p_constant, DataType p_to_type,ConstantNode::Value *p_value) {
- p_func->return_cache=operator_defs[idx].rettype;
- valid=true;
- break;
+ if (p_constant->datatype==p_to_type) {
+ if (p_value) {
+ for(int i=0;i<p_constant->values.size();i++) {
+ p_value[i]=p_constant->values[i];
}
}
+ return true;
+ } else if (p_constant->datatype==TYPE_INT && p_to_type==TYPE_FLOAT) {
+
+ if (p_value) {
+ p_value->real=p_constant->values[0].sint;
+ }
+ return true;
+ } else if (p_constant->datatype==TYPE_UINT && p_to_type==TYPE_FLOAT) {
+
+ if (p_value) {
+ p_value->real=p_constant->values[0].uint;
+ }
+ return true;
+ } else if (p_constant->datatype==TYPE_INT && p_to_type==TYPE_UINT) {
+ if (p_constant->values[0].sint<0) {
+ return false;
+ }
+ if (p_value) {
+ p_value->uint=p_constant->values[0].sint;
+ }
+ return true;
+ } else if (p_constant->datatype==TYPE_UINT && p_to_type==TYPE_INT) {
+
+ if (p_constant->values[0].uint>0x7FFFFFFF) {
+ return false;
+ }
+ if (p_value) {
+ p_value->sint=p_constant->values[0].uint;
+ }
+ return true;
+ } else
+ return false;
+
+}
+
+bool ShaderLanguage::is_scalar_type(DataType p_type) {
+
+ return p_type==TYPE_BOOL || p_type==TYPE_INT || p_type==TYPE_UINT || p_type==TYPE_FLOAT;
+}
+
+bool ShaderLanguage::is_sampler_type(DataType p_type) {
+
+ return p_type==TYPE_SAMPLER2D || p_type==TYPE_ISAMPLER2D || p_type==TYPE_USAMPLER2D || p_type==TYPE_SAMPLERCUBE;
+
+}
+
+void ShaderLanguage::get_keyword_list(List<String> *r_keywords) {
+
+ Set<String> kws;
+
+ int idx=0;
+
+ while(keyword_list[idx].text) {
+ kws.insert(keyword_list[idx].text);
idx++;
}
- if (!valid)
- return NULL;
+ idx=0;
-#define _RCO2(m_op,m_vop)\
-case m_op: {\
- ConstantNode *cn = parser.create_node<ConstantNode>(p_func->parent);\
- cn->datatype=p_func->return_cache; \
- Variant::evaluate(m_vop,static_cast<ConstantNode*>(p_func->arguments[0])->value,static_cast<ConstantNode*>(p_func->arguments[1])->value,cn->value,valid);\
- if (!valid)\
- return NULL;\
- return cn;\
-} break;
-
-#define _RCO1(m_op,m_vop)\
-case m_op: {\
- ConstantNode *cn = parser.create_node<ConstantNode>(p_func->parent);\
- cn->datatype=p_func->return_cache; \
- Variant::evaluate(m_vop,static_cast<ConstantNode*>(p_func->arguments[0])->value,Variant(),cn->value,valid);\
- if (!valid)\
- return NULL;\
- return cn;\
-} break;
-
- if (all_const) {
- //reduce constant operator
- switch(p_func->op) {
- _RCO2(OP_ADD,Variant::OP_ADD);
- _RCO2(OP_SUB,Variant::OP_SUBSTRACT);
- _RCO2(OP_MUL,Variant::OP_MULTIPLY);
- _RCO2(OP_DIV,Variant::OP_DIVIDE);
- _RCO1(OP_NEG,Variant::OP_NEGATE);
- _RCO1(OP_NOT,Variant::OP_NOT);
- _RCO2(OP_CMP_EQ,Variant::OP_EQUAL);
- _RCO2(OP_CMP_NEQ,Variant::OP_NOT_EQUAL);
- _RCO2(OP_CMP_LEQ,Variant::OP_LESS_EQUAL);
- _RCO2(OP_CMP_GEQ,Variant::OP_GREATER_EQUAL);
- _RCO2(OP_CMP_LESS,Variant::OP_LESS);
- _RCO2(OP_CMP_GREATER,Variant::OP_GREATER);
- _RCO2(OP_CMP_OR,Variant::OP_OR);
- _RCO2(OP_CMP_AND,Variant::OP_AND);
- default: {}
- }
+ while (builtin_func_defs[idx].name) {
+
+ kws.insert(builtin_func_defs[idx].name);
+
+ idx++;
+ }
+
+ for(Set<String>::Element *E=kws.front();E;E=E->next()) {
+ r_keywords->push_back(E->get());
}
+}
+void ShaderLanguage::get_builtin_funcs(List<String> *r_keywords) {
- return p_func;
+ Set<String> kws;
+
+ int idx=0;
+
+ while (builtin_func_defs[idx].name) {
+
+ kws.insert(builtin_func_defs[idx].name);
+
+ idx++;
+ }
+
+ for(Set<String>::Element *E=kws.front();E;E=E->next()) {
+ r_keywords->push_back(E->get());
+ }
}
-bool ShaderLanguage::is_token_operator(TokenType p_type) {
- return (p_type==TK_OP_EQUAL) ||
- (p_type==TK_OP_NOT_EQUAL) ||
- (p_type==TK_OP_LESS) ||
- (p_type==TK_OP_LESS_EQUAL) ||
- (p_type==TK_OP_GREATER) ||
- (p_type==TK_OP_GREATER_EQUAL) ||
- (p_type==TK_OP_AND) ||
- (p_type==TK_OP_OR) ||
- (p_type==TK_OP_NOT) ||
- (p_type==TK_OP_ADD) ||
- (p_type==TK_OP_SUB) ||
- (p_type==TK_OP_MUL) ||
- (p_type==TK_OP_DIV) ||
- (p_type==TK_OP_NEG) ||
- (p_type==TK_OP_ASSIGN) ||
- (p_type==TK_OP_ASSIGN_ADD) ||
- (p_type==TK_OP_ASSIGN_SUB) ||
- (p_type==TK_OP_ASSIGN_MUL) ||
- (p_type==TK_OP_ASSIGN_DIV);
+ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) {
+
+ static const DataType scalar_types[]={
+ TYPE_VOID,
+ TYPE_BOOL,
+ TYPE_BOOL,
+ TYPE_BOOL,
+ TYPE_BOOL,
+ TYPE_INT,
+ TYPE_INT,
+ TYPE_INT,
+ TYPE_INT,
+ TYPE_UINT,
+ TYPE_UINT,
+ TYPE_UINT,
+ TYPE_UINT,
+ TYPE_FLOAT,
+ TYPE_FLOAT,
+ TYPE_FLOAT,
+ TYPE_FLOAT,
+ TYPE_FLOAT,
+ TYPE_FLOAT,
+ TYPE_FLOAT,
+ TYPE_FLOAT,
+ TYPE_INT,
+ TYPE_UINT,
+ TYPE_FLOAT,
+ };
+
+ return scalar_types[p_type];
}
-ShaderLanguage::Operator ShaderLanguage::get_token_operator(TokenType p_type) {
- switch(p_type) {
- case TK_OP_EQUAL: return OP_CMP_EQ ;
- case TK_OP_NOT_EQUAL: return OP_CMP_NEQ;
- case TK_OP_LESS: return OP_CMP_LESS ;
- case TK_OP_LESS_EQUAL: return OP_CMP_LEQ ;
- case TK_OP_GREATER: return OP_CMP_GREATER ;
- case TK_OP_GREATER_EQUAL: return OP_CMP_GEQ ;
- case TK_OP_AND: return OP_CMP_AND ;
- case TK_OP_OR: return OP_CMP_OR ;
- case TK_OP_NOT: return OP_NOT ;
- case TK_OP_ADD: return OP_ADD ;
- case TK_OP_SUB: return OP_SUB ;
- case TK_OP_MUL: return OP_MUL ;
- case TK_OP_DIV: return OP_DIV ;
- case TK_OP_NEG: return OP_NEG ;
- case TK_OP_ASSIGN: return OP_ASSIGN ;
- case TK_OP_ASSIGN_ADD: return OP_ASSIGN_ADD ;
- case TK_OP_ASSIGN_SUB: return OP_ASSIGN_SUB ;
- case TK_OP_ASSIGN_MUL: return OP_ASSIGN_MUL ;
- case TK_OP_ASSIGN_DIV: return OP_ASSIGN_DIV ;
- default: ERR_FAIL_V(OP_MAX);
+
+bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block,CompletionType p_type,StringName& identifier) {
+
+ identifier=StringName();
+
+ TkPos pos;
+
+ Token tk = _get_token();
+
+ if (tk.type==TK_IDENTIFIER) {
+ identifier=tk.text;
+ pos = _get_tkpos();
+ tk = _get_token();
+ }
+
+ if (tk.type==TK_CURSOR) {
+
+ completion_type=p_type;
+ completion_line=tk_line;
+ completion_block=p_block;
+
+ pos = _get_tkpos();
+ tk = _get_token();
+
+ if (tk.type==TK_IDENTIFIER) {
+ identifier=identifier.operator String() + tk.text.operator String();
+ } else {
+ _set_tkpos(pos);
+ }
+ return true;
+ } else if (identifier!=StringName()){
+ _set_tkpos(pos);
}
- return OP_MAX;
+ return false;
}
-Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_expr) {
+
+ShaderLanguage::Node* ShaderLanguage::_parse_expression(BlockNode* p_block,const Map<StringName,DataType> &p_builtin_types) {
Vector<Expression> expression;
//Vector<TokenType> operators;
@@ -1524,416 +2234,462 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex
while(true) {
Node *expr=NULL;
+ TkPos prepos = _get_tkpos();
+ Token tk = _get_token();
+ TkPos pos = _get_tkpos();
- if (parser.get_token_type()==TK_PARENTHESIS_OPEN) {
+ if (tk.type==TK_PARENTHESIS_OPEN) {
//handle subexpression
- parser.advance();
- Error err = parse_expression(parser,p_parent,&expr);
- if (err)
- return err;
- if (parser.get_token_type()!=TK_PARENTHESIS_CLOSE) {
+ expr = _parse_and_reduce_expression(p_block,p_builtin_types);
+ if (!expr)
+ return NULL;
- parser.set_error("Expected ')' in expression");
- return ERR_PARSE_ERROR;
- }
+ tk = _get_token();
+
+ if (tk.type!=TK_PARENTHESIS_CLOSE) {
- parser.advance();
+ _set_error("Expected ')' in expression");
+ return NULL;
+ }
- } else if (parser.get_token_type()==TK_REAL_CONSTANT) {
+ } else if (tk.type==TK_REAL_CONSTANT) {
- ConstantNode *constant = parser.create_node<ConstantNode>(p_parent);
- constant->value=parser.get_token().text.operator String().to_double();
+ ConstantNode *constant = alloc_node<ConstantNode>();
+ ConstantNode::Value v;
+ v.real=tk.constant;
+ constant->values.push_back(v);
constant->datatype=TYPE_FLOAT;
expr=constant;
- parser.advance();
- } else if (parser.get_token_type()==TK_TRUE) {
+
+ } else if (tk.type==TK_INT_CONSTANT) {
+
+
+ ConstantNode *constant = alloc_node<ConstantNode>();
+ ConstantNode::Value v;
+ v.sint=tk.constant;
+ constant->values.push_back(v);
+ constant->datatype=TYPE_INT;
+ expr=constant;
+
+ } else if (tk.type==TK_TRUE) {
//print_line("found true");
//handle true constant
- ConstantNode *constant = parser.create_node<ConstantNode>(p_parent);
- constant->value=true;
+ ConstantNode *constant = alloc_node<ConstantNode>();
+ ConstantNode::Value v;
+ v.boolean=true;
+ constant->values.push_back(v);
constant->datatype=TYPE_BOOL;
expr=constant;
- parser.advance();
- } else if (parser.get_token_type()==TK_FALSE) {
+
+ } else if (tk.type==TK_FALSE) {
//handle false constant
- ConstantNode *constant = parser.create_node<ConstantNode>(p_parent);
- constant->value=false;
+ ConstantNode *constant = alloc_node<ConstantNode>();
+ ConstantNode::Value v;
+ v.boolean=false;
+ constant->values.push_back(v);
constant->datatype=TYPE_BOOL;
expr=constant;
- parser.advance();
- } else if (parser.get_token_type()==TK_TYPE_VOID) {
-
- //make sure void is not used in expression
- parser.set_error("Void value not allowed in Expression");
- return ERR_PARSE_ERROR;
- } else if (parser.get_token_type(1)==TK_PARENTHESIS_OPEN && (is_token_nonvoid_datatype(parser.get_token_type()) || parser.get_token_type()==TK_INDENTIFIER)) {
-
-
- //function or constructor
- StringName name;
- DataType constructor=TYPE_VOID;
- if (is_token_nonvoid_datatype(parser.get_token_type())) {
-
- constructor=get_token_datatype(parser.get_token_type());
- switch(get_token_datatype(parser.get_token_type())) {
- case TYPE_BOOL: name="bool"; break;
- case TYPE_FLOAT: name="float"; break;
- case TYPE_VEC2: name="vec2"; break;
- case TYPE_VEC3: name="vec3"; break;
- case TYPE_VEC4: name="vec4"; break;
- case TYPE_MAT2: name="mat2"; break;
- case TYPE_MAT3: name="mat3"; break;
- case TYPE_MAT4: name="mat4"; break;
- default: ERR_FAIL_V(ERR_BUG);
- }
- } else {
- name=parser.get_token().text;
- }
+ } else if (tk.type==TK_TYPE_VOID) {
- if (!test_existing_identifier(p_parent,name)) {
+ //make sure void is not used in expression
+ _set_error("Void value not allowed in Expression");
+ return NULL;
+ } else if (is_token_nonvoid_datatype(tk.type)) {
+ //basic type constructor
- parser.set_error("Unknown identifier in expression: "+name);
- return ERR_PARSE_ERROR;
- }
+ OperatorNode *func = alloc_node<OperatorNode>();
+ func->op=OP_CONSTRUCT;
- parser.advance(2);
- OperatorNode *func = parser.create_node<OperatorNode>(p_parent);
+ if (is_token_precision(tk.type)) {
- func->op=constructor!=TYPE_VOID?OP_CONSTRUCT:OP_CALL;
+ func->return_precision_cache=get_token_precision(tk.type);
+ tk=_get_token();
+ }
- VariableNode *funcname = parser.create_node<VariableNode>(func);
- funcname->name=name;
+ VariableNode *funcname = alloc_node<VariableNode>();
+ funcname->name=get_datatype_name(get_token_datatype(tk.type));
func->arguments.push_back(funcname);
- //parse parameters
+ tk=_get_token();
+ if (tk.type!=TK_PARENTHESIS_OPEN) {
+ _set_error("Expected '(' after type name");
+ return NULL;
+ }
- if (parser.get_token_type()==TK_PARENTHESIS_CLOSE) {
- parser.advance();
- } else {
+ int carg=-1;
- while(true) {
+ bool ok = _parse_function_arguments(p_block,p_builtin_types,func,&carg);
+ if (carg>=0) {
+ completion_type=COMPLETION_CALL_ARGUMENTS;
+ completion_line=tk_line;
+ completion_block=p_block;
+ completion_function=funcname->name;
+ completion_argument=carg;
+ }
- Node *arg=NULL;
- Error err = parse_expression(parser,func,&arg);
- if (err)
- return err;
- func->arguments.push_back(arg);
+ if (!ok)
+ return NULL;
- if (parser.get_token_type()==TK_PARENTHESIS_CLOSE) {
- parser.advance();
- break;
+ if (!_validate_function_call(p_block,func,&func->return_cache)) {
+ _set_error("No matching constructor found for: '"+String(funcname->name)+"'");
+ return NULL;
+ }
+ //validate_Function_call()
- } else if (parser.get_token_type()==TK_COMMA) {
+ expr=_reduce_expression(p_block,func);
- if (parser.get_token_type(1)==TK_PARENTHESIS_CLOSE) {
- parser.set_error("Expression expected");
- return ERR_PARSE_ERROR;
- }
+ } else if (tk.type==TK_IDENTIFIER) {
- parser.advance();
- } else {
- // something is broken
- parser.set_error("Expected ',' or ')'");
- return ERR_PARSE_ERROR;
- }
+ _set_tkpos(prepos);
- }
- }
+ StringName identifier;
- expr=validate_function_call(parser,func);
- if (!expr) {
+ _get_completable_identifier(p_block,COMPLETION_IDENTIFIER,identifier);
- parser.set_error("Invalid arguments to function/constructor: "+StringName(name));
- return ERR_PARSE_ERROR;
- }
+ tk=_get_token();
+ if (tk.type==TK_PARENTHESIS_OPEN) {
+ //a function
+ StringName name = identifier;
- } else if (parser.get_token_type()==TK_INDENTIFIER) {
- //probably variable
+ OperatorNode *func = alloc_node<OperatorNode>();
+ func->op=OP_CALL;
+ VariableNode *funcname = alloc_node<VariableNode>();
+ funcname->name=name;
+ func->arguments.push_back(funcname);
+ int carg=-1;
- Node *node =p_parent;
- bool existing=false;
- DataType datatype;
- StringName identifier=parser.get_token().text;
+ bool ok =_parse_function_arguments(p_block,p_builtin_types,func,&carg);
- while(node) {
+ for(int i=0;i<shader->functions.size();i++) {
+ if (shader->functions[i].name==name) {
+ shader->functions[i].uses_function.insert(name);
+ }
+ }
- if (node->type==Node::TYPE_BLOCK) {
- BlockNode *block = (BlockNode*)node;
- if (block->variables.has(identifier)) {
- existing=true;
- datatype=block->variables[identifier];
- break;
- }
+ if (carg>=0) {
+ completion_type=COMPLETION_CALL_ARGUMENTS;
+ completion_line=tk_line;
+ completion_block=p_block;
+ completion_function=funcname->name;
+ completion_argument=carg;
}
- if (node->type==Node::TYPE_FUNCTION) {
+ if (!ok)
+ return NULL;
- FunctionNode *function=(FunctionNode*)node;
- for(int i=0;i<function->arguments.size();i++) {
- if (function->arguments[i].name==identifier) {
- existing=true;
- datatype=function->arguments[i].type;
- break;
- }
- }
+ if (!_validate_function_call(p_block,func,&func->return_cache)) {
+ _set_error("No matching function found for: '"+String(funcname->name)+"'");
+ return NULL;
+ }
- if (existing)
- break;
+ expr=func;
- }
+ } else {
+ //an identifier
- if (node->type==Node::TYPE_PROGRAM) {
+ _set_tkpos(pos);
- ProgramNode *program = (ProgramNode*)node;
- if (program->builtin_variables.has(identifier)) {
- datatype = program->builtin_variables[identifier];
- existing=true;
- break;
- }
- if (program->uniforms.has(identifier)) {
- datatype = program->uniforms[identifier].type;
- existing=true;
- break;
- }
+ DataType data_type;
+ IdentifierType ident_type;
+ if (!_find_identifier(p_block,p_builtin_types,identifier,&data_type,&ident_type)) {
+ _set_error("Unknown identifier in expression: "+String(identifier));
+ return NULL;
}
- node=node->parent;
- }
+ if (ident_type==IDENTIFIER_FUNCTION) {
+ _set_error("Can't use function as identifier: "+String(identifier));
+ return NULL;
+ }
- if (!existing) {
- parser.set_error("Nonexistent identifier in expression: "+identifier);
- return ERR_PARSE_ERROR;
+ VariableNode *varname = alloc_node<VariableNode>();
+ varname->name=identifier;
+ varname->datatype_cache=data_type;
+ expr=varname;
}
- VariableNode *varname = parser.create_node<VariableNode>(p_parent);
- varname->name=identifier;
- varname->datatype_cache=datatype;
- parser.advance();
- expr=varname;
-
- } else if (parser.get_token_type()==TK_OP_SUB || parser.get_token_type()==TK_OP_NOT) {
- //single prefix operators
- TokenType token_type=parser.get_token_type();
- parser.advance();
- //Node *subexpr=NULL;
- //Error err = parse_expression(parser,p_parent,&subexpr);
- //if (err)
- // return err;
+ } else if (tk.type==TK_OP_ADD) {
+ continue; //this one does nothing
+ } else if (tk.type==TK_OP_SUB || tk.type==TK_OP_NOT || tk.type==TK_OP_BIT_INVERT || tk.type==TK_OP_INCREMENT || tk.type==TK_OP_DECREMENT) {
- //OperatorNode *op = parser.create_node<OperatorNode>(p_parent);
Expression e;
e.is_op=true;
- switch(token_type) {
- case TK_OP_SUB: e.op=TK_OP_NEG; break;
- case TK_OP_NOT: e.op=TK_OP_NOT; break;
- //case TK_OP_PLUS_PLUS: op->op=OP_PLUS_PLUS; break;
- //case TK_OP_MINUS_MINUS: op->op=OP_MINUS_MINUS; break;
- default: ERR_FAIL_V(ERR_BUG);
+ switch(tk.type) {
+ case TK_OP_SUB: e.op=OP_NEGATE; break;
+ case TK_OP_NOT: e.op=OP_NOT; break;
+ case TK_OP_BIT_INVERT: e.op=OP_BIT_INVERT; break;
+ case TK_OP_INCREMENT: e.op=OP_INCREMENT; break;
+ case TK_OP_DECREMENT: e.op=OP_DECREMENT; break;
+ default: ERR_FAIL_V(NULL);
}
expression.push_back(e);
-
continue;
} else {
- print_line("found bug?");
- print_line("misplaced token: "+String(token_names[parser.get_token_type()]));
-
- parser.set_error("Error parsing expression, misplaced: "+String(token_names[parser.get_token_type()]));
- return ERR_PARSE_ERROR;
+ _set_error("Expected expression, found: "+get_token_text(tk));
+ return NULL;
//nothing
}
- ERR_FAIL_COND_V(!expr,ERR_BUG);
+ ERR_FAIL_COND_V(!expr,NULL);
/* OK now see what's NEXT to the operator.. */
/* OK now see what's NEXT to the operator.. */
/* OK now see what's NEXT to the operator.. */
+ while(true) {
+ TkPos pos = _get_tkpos();
+ tk=_get_token();
- if (parser.get_token_type()==TK_PERIOD) {
+ if (tk.type==TK_PERIOD) {
- if (parser.get_token_type(1)!=TK_INDENTIFIER) {
- parser.set_error("Expected identifier as member");
- return ERR_PARSE_ERROR;
- }
-
- DataType dt = compute_node_type(expr);
- String ident = parser.get_token(1).text;
-
- bool ok=true;
- DataType member_type;
- switch(dt) {
- case TYPE_VEC2: {
-
- int l = ident.length();
- if (l==1) {
- member_type=TYPE_FLOAT;
- } else if (l==2) {
- member_type=TYPE_VEC2;
- } else {
- ok=false;
- break;
- }
+ StringName identifier;
+ if (_get_completable_identifier(p_block,COMPLETION_INDEX,identifier)) {
+ completion_base=expr->get_datatype();
+ }
- const CharType *c=ident.ptr();
- for(int i=0;i<l;i++) {
+ if (identifier==StringName()) {
+ _set_error("Expected identifier as member");
+ return NULL;
+ }
- switch(c[i]) {
- case 'r':
- case 'g':
- case 'x':
- case 'y':
- break;
- default:
- ok=false;
- break;
+ DataType dt = expr->get_datatype();
+ String ident = identifier;
+
+ bool ok=true;
+ DataType member_type;
+ switch(dt) {
+ case TYPE_BVEC2:
+ case TYPE_IVEC2:
+ case TYPE_UVEC2:
+ case TYPE_VEC2: {
+
+ int l = ident.length();
+ if (l==1) {
+ member_type=DataType(dt-1);
+ } else if (l==2) {
+ member_type=dt;
+ } else {
+ ok=false;
+ break;
}
- }
- } break;
- case TYPE_VEC3: {
+ const CharType *c=ident.ptr();
+ for(int i=0;i<l;i++) {
+
+ switch(c[i]) {
+ case 'r':
+ case 'g':
+ case 'x':
+ case 'y':
+ break;
+ default:
+ ok=false;
+ break;
+ }
+ }
- int l = ident.length();
- if (l==1) {
- member_type=TYPE_FLOAT;
- } else if (l==2) {
- member_type=TYPE_VEC2;
- } else if (l==3) {
- member_type=TYPE_VEC3;
- } else {
- ok=false;
- break;
- }
+ } break;
+ case TYPE_BVEC3:
+ case TYPE_IVEC3:
+ case TYPE_UVEC3:
+ case TYPE_VEC3: {
+
+ int l = ident.length();
+ if (l==1) {
+ member_type=DataType(dt-2);
+ } else if (l==2) {
+ member_type=DataType(dt-1);
+ } else if (l==3) {
+ member_type=dt;
+ } else {
+ ok=false;
+ break;
+ }
- const CharType *c=ident.ptr();
- for(int i=0;i<l;i++) {
+ const CharType *c=ident.ptr();
+ for(int i=0;i<l;i++) {
+
+ switch(c[i]) {
+ case 'r':
+ case 'g':
+ case 'b':
+ case 'x':
+ case 'y':
+ case 'z':
+ break;
+ default:
+ ok=false;
+ break;
+ }
+ }
- switch(c[i]) {
- case 'r':
- case 'g':
- case 'b':
- case 'x':
- case 'y':
- case 'z':
- break;
- default:
- ok=false;
- break;
+ } break;
+ case TYPE_BVEC4:
+ case TYPE_IVEC4:
+ case TYPE_UVEC4:
+ case TYPE_VEC4: {
+
+ int l = ident.length();
+ if (l==1) {
+ member_type=DataType(dt-3);
+ } else if (l==2) {
+ member_type=DataType(dt-2);
+ } else if (l==3) {
+ member_type=DataType(dt-1);
+ } else if (l==4) {
+ member_type=dt;
+ } else {
+ ok=false;
+ break;
}
- }
- } break;
- case TYPE_VEC4: {
+ const CharType *c=ident.ptr();
+ for(int i=0;i<l;i++) {
+
+ switch(c[i]) {
+ case 'r':
+ case 'g':
+ case 'b':
+ case 'a':
+ case 'x':
+ case 'y':
+ case 'z':
+ case 'w':
+ break;
+ default:
+ ok=false;
+ break;
+ }
+ }
- int l = ident.length();
- if (l==1) {
- member_type=TYPE_FLOAT;
- } else if (l==2) {
- member_type=TYPE_VEC2;
- } else if (l==3) {
- member_type=TYPE_VEC3;
- } else if (l==4) {
- member_type=TYPE_VEC4;
- } else {
- ok=false;
- break;
- }
+ } break;
+ case TYPE_MAT2: ok=(ident=="x" || ident=="y"); member_type=TYPE_VEC2; break;
+ case TYPE_MAT3: ok=(ident=="x" || ident=="y" || ident=="z" ); member_type=TYPE_VEC3; break;
+ case TYPE_MAT4: ok=(ident=="x" || ident=="y" || ident=="z" || ident=="w"); member_type=TYPE_VEC4; break;
+ default: {}
+ }
- const CharType *c=ident.ptr();
- for(int i=0;i<l;i++) {
-
- switch(c[i]) {
- case 'r':
- case 'g':
- case 'b':
- case 'a':
- case 'x':
- case 'y':
- case 'z':
- case 'w':
- break;
- default:
- ok=false;
- break;
- }
- }
+ if (!ok) {
- } break;
- case TYPE_MAT2: ok=(ident=="x" || ident=="y"); member_type=TYPE_VEC2; break;
- case TYPE_MAT3: ok=(ident=="x" || ident=="y" || ident=="z" ); member_type=TYPE_VEC3; break;
- case TYPE_MAT4: ok=(ident=="x" || ident=="y" || ident=="z" || ident=="w"); member_type=TYPE_VEC4; break;
- default: {}
- }
+ _set_error("Invalid member for expression: ."+ident);
+ return NULL;
+ }
- if (!ok) {
+ MemberNode *mn = alloc_node<MemberNode>();
+ mn->basetype=dt;
+ mn->datatype=member_type;
+ mn->name=ident;
+ mn->owner=expr;
+ expr=mn;
- parser.set_error("Invalid member for expression: ."+ident);
- return ERR_PARSE_ERROR;
- }
- MemberNode *mn = parser.create_node<MemberNode>(p_parent);
- mn->basetype=dt;
- mn->datatype=member_type;
- mn->name=ident;
- mn->owner=expr;
- expr=mn;
+ //todo
+ //member (period) has priority over any operator
+ //creates a subindexing expression in place
- parser.advance(2);
- //todo
- //member (period) has priority over any operator
- //creates a subindexing expression in place
+ /*} else if (tk.type==TK_BRACKET_OPEN) {
+ //todo
+ //subindexing has priority over any operator
+ //creates a subindexing expression in place
- } else if (parser.get_token_type()==TK_BRACKET_OPEN) {
- //todo
- //subindexing has priority over any operator
- //creates a subindexing expression in place
+ */
+ } else if (tk.type==TK_OP_INCREMENT || tk.type==TK_OP_DECREMENT) {
+ OperatorNode *op = alloc_node<OperatorNode>();
+ op->op=tk.type==TK_OP_DECREMENT ? OP_POST_DECREMENT : OP_POST_INCREMENT;
+ op->arguments.push_back(expr);
- } /*else if (parser.get_token_type()==TK_OP_PLUS_PLUS || parser.get_token_type()==TK_OP_MINUS_MINUS) {
- //todo
- //inc/dec operators have priority over any operator
- //creates a subindexing expression in place
- //return OK; //wtfs
+ if (!_validate_operator(op,&op->return_cache)) {
+ _set_error("Invalid base type for increment/decrement operator");
+ return NULL;
+ }
+ expr=op;
+ } else {
- } */
+ _set_tkpos(pos);
+ break;
+ }
+ }
Expression e;
e.is_op=false;
e.node=expr;
expression.push_back(e);
+ pos = _get_tkpos();
+ tk = _get_token();
- if (is_token_operator(parser.get_token_type())) {
+ if (is_token_operator(tk.type)) {
Expression o;
o.is_op=true;
- o.op=parser.get_token_type();
+
+ switch(tk.type) {
+
+ case TK_OP_EQUAL: o.op = OP_EQUAL; break;
+ case TK_OP_NOT_EQUAL: o.op = OP_NOT_EQUAL; break;
+ case TK_OP_LESS: o.op = OP_LESS; break;
+ case TK_OP_LESS_EQUAL: o.op = OP_LESS_EQUAL; break;
+ case TK_OP_GREATER: o.op = OP_GREATER; break;
+ case TK_OP_GREATER_EQUAL: o.op = OP_GREATER_EQUAL; break;
+ case TK_OP_AND: o.op = OP_AND; break;
+ case TK_OP_OR: o.op = OP_OR; break;
+ case TK_OP_ADD: o.op = OP_ADD; break;
+ case TK_OP_SUB: o.op = OP_SUB; break;
+ case TK_OP_MUL: o.op = OP_MUL; break;
+ case TK_OP_DIV: o.op = OP_DIV; break;
+ case TK_OP_MOD: o.op = OP_MOD; break;
+ case TK_OP_SHIFT_LEFT: o.op = OP_SHIFT_LEFT; break;
+ case TK_OP_SHIFT_RIGHT: o.op = OP_SHIFT_RIGHT; break;
+ case TK_OP_ASSIGN: o.op = OP_ASSIGN; break;
+ case TK_OP_ASSIGN_ADD: o.op = OP_ASSIGN_ADD; break;
+ case TK_OP_ASSIGN_SUB: o.op = OP_ASSIGN_SUB; break;
+ case TK_OP_ASSIGN_MUL: o.op = OP_ASSIGN_MUL; break;
+ case TK_OP_ASSIGN_DIV: o.op = OP_ASSIGN_DIV; break;
+ case TK_OP_ASSIGN_MOD: o.op = OP_ASSIGN_MOD; break;
+ case TK_OP_ASSIGN_SHIFT_LEFT: o.op = OP_ASSIGN_SHIFT_LEFT; break;
+ case TK_OP_ASSIGN_SHIFT_RIGHT: o.op = OP_ASSIGN_SHIFT_RIGHT; break;
+ case TK_OP_ASSIGN_BIT_AND: o.op = OP_ASSIGN_BIT_AND; break;
+ case TK_OP_ASSIGN_BIT_OR: o.op = OP_ASSIGN_BIT_OR; break;
+ case TK_OP_ASSIGN_BIT_XOR: o.op = OP_ASSIGN_BIT_XOR; break;
+ case TK_OP_BIT_AND: o.op = OP_BIT_AND; break;
+ case TK_OP_BIT_OR: o.op = OP_BIT_OR ; break;
+ case TK_OP_BIT_XOR: o.op = OP_BIT_XOR; break;
+ case TK_QUESTION: o.op = OP_SELECT_IF; break;
+ case TK_COLON: o.op = OP_SELECT_ELSE; break;
+ default: {
+ _set_error("Invalid token for operator: "+get_token_text(tk));
+ return NULL;
+ }
+ }
+
expression.push_back(o);
- parser.advance();
+
} else {
+ _set_tkpos(pos); //something else, so rollback and end
break;
}
}
@@ -1947,6 +2703,7 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex
int next_op=-1;
int min_priority=0xFFFFF;
bool is_unary=false;
+ bool is_ternary=false;
for(int i=0;i<expression.size();i++) {
@@ -1956,45 +2713,48 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex
}
bool unary=false;
+ bool ternary=false;
int priority;
switch(expression[i].op) {
-
- case TK_OP_NOT: priority=0; unary=true; break;
- case TK_OP_NEG: priority=0; unary=true; break;
-
- case TK_OP_MUL: priority=1; break;
- case TK_OP_DIV: priority=1; break;
-
- case TK_OP_ADD: priority=2; break;
- case TK_OP_SUB: priority=2; break;
-
- // shift left/right =2
-
- case TK_OP_LESS: priority=4; break;
- case TK_OP_LESS_EQUAL: priority=4; break;
- case TK_OP_GREATER: priority=4; break;
- case TK_OP_GREATER_EQUAL: priority=4; break;
-
- case TK_OP_EQUAL: priority=5; break;
- case TK_OP_NOT_EQUAL: priority=5; break;
-
- //bit and =5
- //bit xor =6
- //bit or=7
-
- case TK_OP_AND: priority=8; break;
- case TK_OP_OR: priority=9; break;
-
- // ?: = 10
-
- case TK_OP_ASSIGN_ADD: priority=11; break;
- case TK_OP_ASSIGN_SUB: priority=11; break;
- case TK_OP_ASSIGN_MUL: priority=11; break;
- case TK_OP_ASSIGN_DIV: priority=11; break;
- case TK_OP_ASSIGN: priority=11; break;
-
- default: ERR_FAIL_V(ERR_BUG); //unexpected operator
+ case OP_EQUAL: priority=8; break;
+ case OP_NOT_EQUAL: priority=8; break;
+ case OP_LESS: priority=7; break;
+ case OP_LESS_EQUAL: priority=7; break;
+ case OP_GREATER: priority=7; break;
+ case OP_GREATER_EQUAL: priority=7; break;
+ case OP_AND: priority=12; break;
+ case OP_OR: priority=14; break;
+ case OP_NOT: priority=3; unary=true; break;
+ case OP_NEGATE: priority=3; unary=true; break;
+ case OP_ADD: priority=5; break;
+ case OP_SUB: priority=5; break;
+ case OP_MUL: priority=4; break;
+ case OP_DIV: priority=4; break;
+ case OP_MOD: priority=4; break;
+ case OP_SHIFT_LEFT: priority=6; break;
+ case OP_SHIFT_RIGHT: priority=6; break;
+ case OP_ASSIGN: priority=16; break;
+ case OP_ASSIGN_ADD: priority=16; break;
+ case OP_ASSIGN_SUB: priority=16; break;
+ case OP_ASSIGN_MUL: priority=16; break;
+ case OP_ASSIGN_DIV: priority=16; break;
+ case OP_ASSIGN_MOD: priority=16; break;
+ case OP_ASSIGN_SHIFT_LEFT: priority=16; break;
+ case OP_ASSIGN_SHIFT_RIGHT: priority=16; break;
+ case OP_ASSIGN_BIT_AND: priority=16; break;
+ case OP_ASSIGN_BIT_OR: priority=16; break;
+ case OP_ASSIGN_BIT_XOR: priority=16; break;
+ case OP_BIT_AND: priority=9; break;
+ case OP_BIT_OR: priority=11; break;
+ case OP_BIT_XOR: priority=10; break;
+ case OP_BIT_INVERT: priority=3; unary=true; break;
+ case OP_INCREMENT: priority=3; unary=true; break;
+ case OP_DECREMENT: priority=3; unary=true; break;
+ case OP_SELECT_IF: priority=15; ternary=true; break;
+ case OP_SELECT_ELSE: priority=15; ternary=true; break;
+
+ default: ERR_FAIL_V(NULL); //unexpected operator
}
@@ -2004,11 +2764,12 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex
next_op=i;
min_priority=priority;
is_unary=unary;
+ is_ternary=ternary;
}
}
- ERR_FAIL_COND_V(next_op==-1,ERR_BUG);
+ ERR_FAIL_COND_V(next_op==-1,NULL);
// OK! create operator..
// OK! create operator..
@@ -2020,48 +2781,90 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex
expr_pos++;
if (expr_pos==expression.size()) {
//can happen..
- parser.set_error("Unexpected end of expression..");
- return ERR_BUG;
+ _set_error("Unexpected end of expression..");
+ return NULL;
}
}
//consecutively do unary opeators
for(int i=expr_pos-1;i>=next_op;i--) {
- OperatorNode *op = parser.create_node<OperatorNode>(p_parent);
- op->op=get_token_operator(expression[i].op);
+ OperatorNode *op = alloc_node<OperatorNode>();
+ op->op=expression[i].op;
op->arguments.push_back(expression[i+1].node);
expression[i].is_op=false;
- expression[i].node=validate_operator(parser,op);
- if (!expression[i].node) {
+ expression[i].node=op;
+
+
+ if (!_validate_operator(op,&op->return_cache)) {
String at;
for(int i=0;i<op->arguments.size();i++) {
if (i>0)
at+=" and ";
- at+=get_datatype_name(compute_node_type(op->arguments[i]));
+ at+=get_datatype_name(op->arguments[i]->get_datatype());
}
- parser.set_error("Invalid argument to unary operator "+String(token_names[op->op])+": "+at);
- return ERR_PARSE_ERROR;
+ _set_error("Invalid arguments to unary operator '"+get_operator_text(op->op)+"' :" +at);
+ return NULL;
}
expression.remove(i+1);
}
+
+ } else if (is_ternary) {
+
+ if (next_op <1 || next_op>=(expression.size()-1)) {
+ _set_error("Parser bug..");
+ ERR_FAIL_V(NULL);
+ }
+
+ if (next_op+2 >= expression.size() || !expression[next_op+2].is_op || expression[next_op+2].op!=OP_SELECT_ELSE) {
+ _set_error("Mising matching ':' for select operator");
+ return NULL;
+ }
+
+
+
+ OperatorNode *op = alloc_node<OperatorNode>();
+ op->op=expression[next_op].op;
+ op->arguments.push_back(expression[next_op-1].node);
+ op->arguments.push_back(expression[next_op+1].node);
+ op->arguments.push_back(expression[next_op+3].node);
+
+ expression[next_op-1].is_op=false;
+ expression[next_op-1].node=op;
+ if (!_validate_operator(op,&op->return_cache)) {
+
+ String at;
+ for(int i=0;i<op->arguments.size();i++) {
+ if (i>0)
+ at+=" and ";
+ at+=get_datatype_name(op->arguments[i]->get_datatype());
+
+ }
+ _set_error("Invalid argument to ternary ?: operator: "+at);
+ return NULL;
+ }
+
+ for(int i=0;i<4;i++) {
+ expression.remove(next_op);
+ }
+
} else {
if (next_op <1 || next_op>=(expression.size()-1)) {
- parser.set_error("Parser bug..");
- ERR_FAIL_V(ERR_BUG);
+ _set_error("Parser bug..");
+ ERR_FAIL_V(NULL);
}
- OperatorNode *op = parser.create_node<OperatorNode>(p_parent);
- op->op=get_token_operator(expression[next_op].op);
+ OperatorNode *op = alloc_node<OperatorNode>();
+ op->op=expression[next_op].op;
if (expression[next_op-1].is_op) {
- parser.set_error("Parser bug..");
- ERR_FAIL_V(ERR_BUG);
+ _set_error("Parser bug..");
+ ERR_FAIL_V(NULL);
}
if (expression[next_op+1].is_op) {
@@ -2070,645 +2873,1032 @@ Error ShaderLanguage::parse_expression(Parser& parser,Node *p_parent,Node **r_ex
// can be followed by an unary op in a valid combination,
// due to how precedence works, unaries will always dissapear first
- parser.set_error("Parser bug..");
+ _set_error("Parser bug..");
}
op->arguments.push_back(expression[next_op-1].node); //expression goes as left
op->arguments.push_back(expression[next_op+1].node); //next expression goes as right
+ expression[next_op-1].node=op;
//replace all 3 nodes by this operator and make it an expression
- expression[next_op-1].node=validate_operator(parser,op);
- if (!expression[next_op-1].node) {
+
+ if (!_validate_operator(op,&op->return_cache)) {
String at;
for(int i=0;i<op->arguments.size();i++) {
if (i>0)
at+=" and ";
- at+=get_datatype_name(compute_node_type(op->arguments[i]));
+ at+=get_datatype_name(op->arguments[i]->get_datatype());
}
- static const char *op_names[OP_MAX]={"=","+","-","*","/","+=","-=","*=","/=","-","!","==","!=","<=",">=","<",">","||","&&","call","()"};
-
- parser.set_error("Invalid arguments to operator "+String(op_names[op->op])+": "+at);
- return ERR_PARSE_ERROR;
+ _set_error("Invalid arguments to operator '"+get_operator_text(op->op)+"' :" +at);
+ return NULL;
}
+
expression.remove(next_op);
expression.remove(next_op);
}
-#if 0
- OperatorNode *op = parser.create_node<OperatorNode>(p_parent);
- op->op=get_token_operator(operators[next_op]);
+ }
+
+ return expression[0].node;
+}
+
+
+ShaderLanguage::Node* ShaderLanguage::_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node) {
+
+ if (p_node->type!=Node::TYPE_OPERATOR)
+ return p_node;
+
+ //for now only reduce simple constructors
+ OperatorNode *op=static_cast<OperatorNode*>(p_node);
+
+ if (op->op==OP_CONSTRUCT) {
+
+
+ ERR_FAIL_COND_V(op->arguments[0]->type!=Node::TYPE_VARIABLE,p_node);
+ VariableNode *vn = static_cast<VariableNode*>(op->arguments[0]);
+ //StringName name=vn->name;
+
+ DataType base=get_scalar_type(op->get_datatype());
- op->arguments.push_back(expressions[next_op]); //expression goes as left
- op->arguments.push_back(expressions[next_op+1]); //next expression goes as right
+ Vector<ConstantNode::Value> values;
- expressions[next_op]=validate_operator(parser,op);
- if (!expressions[next_op]) {
- String at;
- for(int i=0;i<op->arguments.size();i++) {
- if (i>0)
- at+=" and ";
- at+=get_datatype_name(compute_node_type(op->arguments[i]));
+ for(int i=1;i<op->arguments.size();i++) {
+
+ op->arguments[i]=_reduce_expression(p_block,op->arguments[i]);
+ if (op->arguments[i]->type==Node::TYPE_CONSTANT) {
+ ConstantNode *cn = static_cast<ConstantNode*>(op->arguments[i]);
+
+ if (get_scalar_type(cn->datatype)==base) {
+
+ for(int j=0;j<cn->values.size();j++) {
+ values.push_back(cn->values[j]);
+ }
+ } else if (get_scalar_type(cn->datatype)==cn->datatype) {
+
+ ConstantNode::Value v;
+ if (!convert_constant(cn,base,&v)) {
+ return p_node;
+ }
+ values.push_back(v);
+ } else {
+ return p_node;
+ }
+
+ } else {
+ return p_node;
}
- parser.set_error("Invalid arguments to operator "+String(token_names[operators[next_op]])+": "+at);
- return ERR_PARSE_ERROR;
}
- expressions.remove(next_op+1);
- operators.remove(next_op);
-#endif
+ ConstantNode *cn=alloc_node<ConstantNode>();
+ cn->datatype=op->get_datatype();
+ cn->values=values;
+ return cn;
+ } else if (op->op==OP_NEGATE) {
- }
+ op->arguments[0]=_reduce_expression(p_block,op->arguments[0]);
+ if (op->arguments[0]->type==Node::TYPE_CONSTANT) {
- *r_expr=expression[0].node;
+ ConstantNode *cn = static_cast<ConstantNode*>(op->arguments[0]);
- return OK;
+ DataType base=get_scalar_type(cn->datatype);
-/*
- TokenType token_type=parser.get_token_type();
- OperatorNode *op = parser.create_node<OperatorNode>(p_parent);
- op->op=get_token_operator(parser.get_token_type());
+ Vector<ConstantNode::Value> values;
- op->arguments.push_back(*r_expr); //expression goes as left
- parser.advance();
- Node *right_expr=NULL;
- Error err = parse_expression(parser,p_parent,&right_expr);
- if (err)
- return err;
- op->arguments.push_back(right_expr);
+ for(int i=0;i<cn->values.size();i++) {
- if (!validate_operator(op)) {
+ ConstantNode::Value nv;
+ switch(base) {
+ case TYPE_BOOL: {
+ nv.boolean=!cn->values[i].boolean;
+ } break;
+ case TYPE_INT: {
+ nv.sint=-cn->values[i].sint;
+ } break;
+ case TYPE_UINT: {
+ nv.uint=-cn->values[i].uint;
+ } break;
+ case TYPE_FLOAT: {
+ nv.real=-cn->values[i].real;
+ } break;
+ default: {}
+ }
- parser.set_error("Invalid arguments to operator "+String(token_names[token_type]));
- return ERR_PARSE_ERROR;
+ values.push_back(nv);
}
-*/
+
+ cn->values=values;
+ return cn;
+ }
+ }
+
+ return p_node;
+
}
-Error ShaderLanguage::parse_variable_declaration(Parser& parser,BlockNode *p_block) {
- bool uniform = parser.get_token(-1).type==TK_UNIFORM;
+ShaderLanguage::Node* ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map<StringName,DataType> &p_builtin_types) {
- DataType type=get_token_datatype(parser.get_token_type(0));
- bool iscolor = parser.get_token_type(0)==TK_TYPE_COLOR;
- if (type==TYPE_VOID) {
+ ShaderLanguage::Node* expr = _parse_expression(p_block,p_builtin_types);
+ if (!expr) //errored
+ return NULL;
- parser.set_error("Cannot Declare a 'void' Variable");
- return ERR_PARSE_ERROR;
- }
+ expr = _reduce_expression(p_block,expr);
- if (type==TYPE_TEXTURE && !uniform) {
+ return expr;
+}
- parser.set_error("Cannot Declare a Non-Uniform Texture");
- return ERR_PARSE_ERROR;
- }
- if (type==TYPE_CUBEMAP && !uniform) {
- parser.set_error("Cannot Declare a Non-Uniform Cubemap");
- return ERR_PARSE_ERROR;
- }
- parser.advance();
- int found=0;
+Error ShaderLanguage::_parse_block(BlockNode* p_block,const Map<StringName,DataType> &p_builtin_types,bool p_just_one,bool p_can_break,bool p_can_continue) {
while(true) {
+ TkPos pos = _get_tkpos();
- if (found && parser.get_token_type()!=TK_COMMA) {
- break;
- }
+ Token tk = _get_token();
+ if (tk.type==TK_CURLY_BRACKET_CLOSE) { //end of block
+ if (p_just_one) {
+ _set_error("Unexpected '}'");
+ return ERR_PARSE_ERROR;
+ }
- if (parser.get_token_type()!=TK_INDENTIFIER) {
+ return OK;
- parser.set_error("Identifier Expected");
- return ERR_PARSE_ERROR;
+ } else if (is_token_precision(tk.type) || is_token_nonvoid_datatype(tk.type)) {
+ DataPrecision precision=PRECISION_DEFAULT;
+ if (is_token_precision(tk.type)) {
+ precision=get_token_precision(tk.type);
+ tk = _get_token();
+ if (!is_token_nonvoid_datatype(tk.type)) {
+ _set_error("Expected datatype after precission");
+ return ERR_PARSE_ERROR;
+ }
+ }
- }
+ DataType type = get_token_datatype(tk.type);
- StringName name = parser.get_token().text;
+ tk = _get_token();
- if (test_existing_identifier(p_block,name)) {
- parser.set_error("Duplicate Identifier (existing variable/function): "+name);
- return ERR_PARSE_ERROR;
- }
+ while(true) {
- found=true;
+ if (tk.type!=TK_IDENTIFIER) {
+ _set_error("Expected identifier after type");
+ return ERR_PARSE_ERROR;
+ }
- parser.advance();
- //see if declaration has an initializer
- if (parser.get_token_type()==TK_OP_ASSIGN) {
- parser.advance();
- OperatorNode * op = parser.create_node<OperatorNode>(p_block);
- VariableNode * var = parser.create_node<VariableNode>(op);
- var->name=name;
- var->datatype_cache=type;
- var->uniform=uniform;
- Node *expr;
- Error err = parse_expression(parser,p_block,&expr);
+ StringName name = tk.text;
+ if (_find_identifier(p_block,p_builtin_types,name)) {
+ _set_error("Redefinition of '"+String(name)+"'");
+ return ERR_PARSE_ERROR;
+ }
- if (err)
- return err;
+ BlockNode::Variable var;
+ var.type=type;
+ var.precision=precision;
+ var.line=tk_line;
+ p_block->variables[name]=var;
- if (var->uniform) {
+ tk = _get_token();
- if (expr->type!=Node::TYPE_CONSTANT) {
+ if (tk.type==TK_OP_ASSIGN) {
+ //variable creted with assignment! must parse an expression
+ Node* n = _parse_and_reduce_expression(p_block,p_builtin_types);
+ if (!n)
+ return ERR_PARSE_ERROR;
- parser.set_error("Uniform can only be initialized to a constant.");
- return ERR_PARSE_ERROR;
+ OperatorNode *assign = alloc_node<OperatorNode>();
+ VariableNode *vnode = alloc_node<VariableNode>();
+ vnode->name=name;
+ vnode->datatype_cache=type;
+ assign->arguments.push_back(vnode);
+ assign->arguments.push_back(n);
+ assign->op=OP_ASSIGN;
+ p_block->statements.push_back(assign);
+ tk = _get_token();
}
- Uniform u;
- u.order=parser.program->uniforms.size();
- u.type=type;
- u.default_value=static_cast<ConstantNode*>(expr)->value;
- if (iscolor && u.default_value.get_type()==Variant::PLANE) {
- Color c;
- Plane p = u.default_value;
- c=Color(p.normal.x,p.normal.y,p.normal.z,p.d);
- u.default_value=c;
- }
- parser.program->uniforms[var->name]=u;
- } else {
- op->op=OP_ASSIGN;
- op->arguments.push_back(var);
- op->arguments.push_back(expr);
- Node *n=validate_operator(parser,op);
- if (!n) {
- parser.set_error("Invalid initializer for variable: "+name);
+ if (tk.type==TK_COMMA) {
+ tk = _get_token();
+ //another variable
+ } else if (tk.type==TK_SEMICOLON) {
+ break;
+ } else {
+ _set_error("Expected ',' or ';' after variable");
return ERR_PARSE_ERROR;
}
- p_block->statements.push_back(n);
+ }
+ } else if (tk.type==TK_CURLY_BRACKET_OPEN) {
+ //a sub block, just because..
+ BlockNode* block = alloc_node<BlockNode>();
+ block->parent_block=p_block;
+ _parse_block(block,p_builtin_types,false,p_can_break,p_can_continue);
+ p_block->statements.push_back(block);
+ } else if (tk.type==TK_CF_IF) {
+ //if () {}
+ tk = _get_token();
+ if (tk.type!=TK_PARENTHESIS_OPEN) {
+ _set_error("Expected '(' after if");
+ return ERR_PARSE_ERROR;
}
- } else {
- //initialize it EMPTY
-
- OperatorNode * op = parser.create_node<OperatorNode>(p_block);
- VariableNode * var = parser.create_node<VariableNode>(op);
- ConstantNode * con = parser.create_node<ConstantNode>(op);
-
- var->name=name;
- var->datatype_cache=type;
- var->uniform=uniform;
- con->datatype=type;
-
- switch(type) {
- case TYPE_BOOL: con->value=false; break;
- case TYPE_FLOAT: con->value=0.0; break;
- case TYPE_VEC2: con->value=Vector2(); break;
- case TYPE_VEC3: con->value=Vector3(); break;
- case TYPE_VEC4: con->value=iscolor?Variant(Color()):Variant(Plane()); break;
- case TYPE_MAT2: con->value=Matrix32(); break;
- case TYPE_MAT3: con->value=Matrix3(); break;
- case TYPE_MAT4: con->value=Transform(); break;
- case TYPE_TEXTURE:
- case TYPE_CUBEMAP: con->value=RID(); break;
- default: {}
+ ControlFlowNode *cf = alloc_node<ControlFlowNode>();
+ cf->flow_op=FLOW_OP_IF;
+ Node* n = _parse_and_reduce_expression(p_block,p_builtin_types);
+ if (!n)
+ return ERR_PARSE_ERROR;
+
+ tk = _get_token();
+ if (tk.type!=TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected '(' after expression");
+ return ERR_PARSE_ERROR;
}
- if (uniform) {
- Uniform u;
- u.type=type;
- u.default_value=con->value;
- u.order=parser.program->uniforms.size();
- parser.program->uniforms[var->name]=u;
+ BlockNode* block = alloc_node<BlockNode>();
+ block->parent_block=p_block;
+ cf->expressions.push_back(n);
+ cf->blocks.push_back(block);
+ p_block->statements.push_back(cf);
+
+
+ Error err=_parse_block(block,p_builtin_types,true,p_can_break,p_can_continue);
+
+ pos=_get_tkpos();
+ tk = _get_token();
+ if (tk.type==TK_CF_ELSE) {
+
+ block = alloc_node<BlockNode>();
+ block->parent_block=p_block;
+ cf->blocks.push_back(block);
+ err=_parse_block(block,p_builtin_types,true,p_can_break,p_can_continue);
} else {
- op->op=OP_ASSIGN;
- op->arguments.push_back(var);
- op->arguments.push_back(con);
- p_block->statements.push_back(op);
+ _set_tkpos(pos); //rollback
}
- }
+ } else {
- if (!uniform)
- p_block->variables[name]=type;
+ //nothng else, so expression
+ _set_tkpos(pos); //rollback
+ Node*expr = _parse_and_reduce_expression(p_block,p_builtin_types);
+ if (!expr)
+ return ERR_PARSE_ERROR;
+ p_block->statements.push_back(expr);
+ tk = _get_token();
- }
+ if (tk.type!=TK_SEMICOLON) {
+ _set_error("Expected ';' after statement");
+ return ERR_PARSE_ERROR;
+ }
+ }
- if (parser.get_token_type()!=TK_SEMICOLON) {
- parser.set_error("Expected ';'");
- return ERR_PARSE_ERROR;
+ if (p_just_one)
+ break;
}
-
return OK;
-
}
-Error ShaderLanguage::parse_flow_if(Parser& parser,Node *p_parent,Node **r_statement) {
- ControlFlowNode *cf = parser.create_node<ControlFlowNode>(p_parent);
+Error ShaderLanguage::_parse_shader(const Map< StringName, Map<StringName,DataType> > &p_functions, const Set<String> &p_render_modes) {
- cf->flow_op=FLOW_OP_IF;
- parser.advance();
+ Token tk = _get_token();
- if (parser.get_token_type()!=TK_PARENTHESIS_OPEN) {
- parser.set_error("Expected '(' after 'if'");
- return ERR_PARSE_ERROR;
- }
- parser.advance();
+ int texture_uniforms = 0;
+ int uniforms =0;
- Node *expression=NULL;
- Error err = parse_expression(parser,cf,&expression);
- if (err)
- return err;
+ while(tk.type!=TK_EOF) {
- if (compute_node_type(expression)!=TYPE_BOOL) {
+ switch(tk.type) {
+ case TK_RENDER_MODE: {
- parser.set_error("Expression for 'if' is not boolean");
- return ERR_PARSE_ERROR;
- }
+ while(true) {
- cf->statements.push_back(expression);
+ StringName mode;
+ _get_completable_identifier(NULL,COMPLETION_RENDER_MODE,mode);
- if (parser.get_token_type()!=TK_PARENTHESIS_CLOSE) {
- parser.set_error("Expected ')' after expression");
- return ERR_PARSE_ERROR;
- }
+ if (mode==StringName()) {
+ _set_error("Expected identifier for render mode");
+ return ERR_PARSE_ERROR;
+ }
- parser.advance();
+ if (!p_render_modes.has(mode)) {
+ _set_error("Invalid render mode: '"+String(mode)+"'");
+ return ERR_PARSE_ERROR;
+ }
- if (parser.get_token_type()!=TK_CURLY_BRACKET_OPEN) {
- parser.set_error("Expected statement block after 'if()'");
- return ERR_PARSE_ERROR;
- }
+ if (shader->render_modes.find(mode)!=-1) {
+ _set_error("Duplicate render mode: '"+String(mode)+"'");
+ return ERR_PARSE_ERROR;
+ }
- Node *substatement=NULL;
- err = parse_statement(parser,cf,&substatement);
- if (err)
- return err;
+ shader->render_modes.push_back(mode);
- cf->statements.push_back(substatement);
+ tk = _get_token();
+ if (tk.type==TK_COMMA) {
+ //all good, do nothing
+ } else if (tk.type==TK_SEMICOLON) {
+ break; //done
+ } else {
+ _set_error("Unexpected token: "+get_token_text(tk));
+ return ERR_PARSE_ERROR;
+ }
+ }
+ } break;
+ case TK_UNIFORM:
+ case TK_VARYING: {
+
+ bool uniform = tk.type==TK_UNIFORM;
+ DataPrecision precision = PRECISION_DEFAULT;
+ DataType type;
+ StringName name;
+
+ tk = _get_token();
+ if (is_token_precision(tk.type)) {
+ precision=get_token_precision(tk.type);
+ tk = _get_token();
+ }
- if (parser.get_token_type()==TK_CF_ELSE) {
+ if (!is_token_datatype(tk.type)) {
+ _set_error("Expected datatype. ");
+ return ERR_PARSE_ERROR;
+ }
- parser.advance();
+ type = get_token_datatype(tk.type);
- if (parser.get_token_type()!=TK_CURLY_BRACKET_OPEN) {
- parser.set_error("Expected statement block after 'else'");
- return ERR_PARSE_ERROR;
- }
+ if (type==TYPE_VOID) {
+ _set_error("void datatype not allowed here");
+ return ERR_PARSE_ERROR;
+ }
+ if (!uniform && type<TYPE_FLOAT && type>TYPE_VEC4) {
+ _set_error("Invalid type for varying, only float,vec2,vec3,vec4 allowed.");
+ return ERR_PARSE_ERROR;
+ }
- substatement=NULL;
- err = parse_statement(parser,cf,&substatement);
- if (err)
- return err;
+ tk = _get_token();
+ if (tk.type!=TK_IDENTIFIER) {
+ _set_error("Expected identifier!");
+ return ERR_PARSE_ERROR;
+ }
- cf->statements.push_back(substatement);
- }
+ name=tk.text;
+ if (_find_identifier(NULL,Map<StringName,DataType>(),name)) {
+ _set_error("Redefinition of '"+String(name)+"'");
+ return ERR_PARSE_ERROR;
+ }
+ if (uniform) {
- *r_statement=cf;
+ ShaderNode::Uniform uniform;
- return OK;
-}
+ if (is_sampler_type(type)) {
+ uniform.texture_order=texture_uniforms++;
+ uniform.order=-1;
+ } else {
+ uniform.texture_order=-1;
+ uniform.order=uniforms++;
+ }
+ uniform.type=type;
+ uniform.precission=precision;
-Error ShaderLanguage::parse_flow_return(Parser& parser,Node *p_parent,Node **r_statement) {
+ //todo parse default value
+ tk = _get_token();
+ if (tk.type==TK_OP_ASSIGN) {
- FunctionNode *function=NULL;
+ Node* expr = _parse_and_reduce_expression(NULL,Map<StringName,DataType>());
+ if (!expr)
+ return ERR_PARSE_ERROR;
+ if (expr->type!=Node::TYPE_CONSTANT) {
+ _set_error("Expected constant expression after '='");
+ return ERR_PARSE_ERROR;
+ }
- Node *parent=p_parent;
+ ConstantNode* cn = static_cast<ConstantNode*>(expr);
- while(parent) {
+ uniform.default_value.resize(cn->values.size());
- if (parent->type==Node::TYPE_FUNCTION) {
+ if (!convert_constant(cn,uniform.type,uniform.default_value.ptr())) {
+ _set_error("Can't convert constant to "+get_datatype_name(uniform.type));
+ return ERR_PARSE_ERROR;
+ }
+ tk = _get_token();
+ }
- function=(FunctionNode*)parent;
- break;
- }
+ if (tk.type==TK_COLON) {
+ //hint
+
+ tk = _get_token();
+ if (tk.type==TK_HINT_WHITE_TEXTURE) {
+ uniform.hint=ShaderNode::Uniform::HINT_WHITE;
+ } else if (tk.type==TK_HINT_BLACK_TEXTURE) {
+ uniform.hint=ShaderNode::Uniform::HINT_BLACK;
+ } else if (tk.type==TK_HINT_NORMAL_TEXTURE) {
+ uniform.hint=ShaderNode::Uniform::HINT_NORMAL;
+ } else if (tk.type==TK_HINT_ANISO_TEXTURE) {
+ uniform.hint=ShaderNode::Uniform::HINT_ANISO;
+ } else if (tk.type==TK_HINT_ALBEDO_TEXTURE) {
+ uniform.hint=ShaderNode::Uniform::HINT_ALBEDO;
+ } else if (tk.type==TK_HINT_BLACK_ALBEDO_TEXTURE) {
+ uniform.hint=ShaderNode::Uniform::HINT_BLACK_ALBEDO;
+ } else if (tk.type==TK_HINT_COLOR) {
+ if (type!=TYPE_VEC4) {
+ _set_error("Color hint is for vec4 only");
+ return ERR_PARSE_ERROR;
+ }
+ uniform.hint=ShaderNode::Uniform::HINT_COLOR;
+ } else if (tk.type==TK_HINT_RANGE) {
+
+ uniform.hint=ShaderNode::Uniform::HINT_RANGE;
+ if (type!=TYPE_FLOAT && type!=TYPE_INT) {
+ _set_error("Range hint is for float and int only");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+ if (tk.type!=TK_PARENTHESIS_OPEN) {
+ _set_error("Expected '(' after hint_range");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+
+ float sign=1.0;
+
+ if (tk.type==TK_OP_SUB) {
+ sign=-1.0;
+ tk = _get_token();
+ }
+
+ if (tk.type!=TK_REAL_CONSTANT && tk.type!=TK_INT_CONSTANT) {
+ _set_error("Expected integer constant");
+ return ERR_PARSE_ERROR;
+ }
+
+ uniform.hint_range[0]=tk.constant;
+ uniform.hint_range[0]*=sign;
+
+ tk = _get_token();
+
+ if (tk.type!=TK_COMMA) {
+ _set_error("Expected ',' after integer constant");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+
+ sign=1.0;
+
+ if (tk.type==TK_OP_SUB) {
+ sign=-1.0;
+ tk = _get_token();
+ }
+
+
+ if (tk.type!=TK_REAL_CONSTANT && tk.type!=TK_INT_CONSTANT) {
+ _set_error("Expected integer constant after ','");
+ return ERR_PARSE_ERROR;
+ }
+
+ uniform.hint_range[1]=tk.constant;
+ uniform.hint_range[1]*=sign;
+
+ tk = _get_token();
+
+ if (tk.type==TK_COMMA) {
+ tk = _get_token();
+
+ if (tk.type!=TK_REAL_CONSTANT && tk.type!=TK_INT_CONSTANT) {
+ _set_error("Expected integer constant after ','");
+ return ERR_PARSE_ERROR;
+ }
+
+ uniform.hint_range[2]=tk.constant;
+ tk = _get_token();
+ } else {
+ if (type==TYPE_INT) {
+ uniform.hint_range[2]=1;
+ } else {
+ uniform.hint_range[2]=0.001;
+ }
+ }
+
+ if (tk.type!=TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ','");
+ return ERR_PARSE_ERROR;
+ }
+
+
+ } else {
+ _set_error("Expected valid type hint after ':'.");
+ }
- parent=parent->parent;
- }
+ if (uniform.hint!=ShaderNode::Uniform::HINT_RANGE && uniform.hint!=ShaderNode::Uniform::HINT_NONE && uniform.hint!=ShaderNode::Uniform::HINT_COLOR && type <=TYPE_MAT4) {
+ _set_error("This hint is only for sampler types");
+ return ERR_PARSE_ERROR;
- if (!function) {
+ }
- parser.set_error("'return' must be inside a function");
- return ERR_PARSE_ERROR;
- }
+ tk = _get_token();
+ }
- ControlFlowNode *cf = parser.create_node<ControlFlowNode>(p_parent);
+ shader->uniforms[name]=uniform;
- cf->flow_op=FLOW_OP_RETURN;
+ if (tk.type!=TK_SEMICOLON) {
+ _set_error("Expected ';'");
+ return ERR_PARSE_ERROR;
+ }
+ } else {
- parser.advance();
+ ShaderNode::Varying varying;
+ varying.type=type;
+ varying.precission=precision;
+ shader->varyings[name]=varying;
- if (function->return_type!=TYPE_VOID) {
- // should expect a return expression.
+ tk = _get_token();
+ if (tk.type!=TK_SEMICOLON) {
+ _set_error("Expected ';'");
+ return ERR_PARSE_ERROR;
+ }
- Node *expr=NULL;
- Error err = parse_expression(parser,cf,&expr);
- if (err)
- return err;
+ }
- if (compute_node_type(expr)!=function->return_type) {
- parser.set_error("Invalid type for 'return' expression");
- return ERR_PARSE_ERROR;
- }
- cf->statements.push_back(expr);
- }
- *r_statement=cf;
+ } break;
+ default: {
+ //function
- if (parser.get_token_type()!=TK_SEMICOLON) {
- parser.set_error("Expected ';'");
- return ERR_PARSE_ERROR;
- }
+ DataPrecision precision = PRECISION_DEFAULT;
+ DataType type;
+ StringName name;
- return OK;
-}
+ if (is_token_precision(tk.type)) {
+ precision=get_token_precision(tk.type);
+ tk = _get_token();
+ }
-Error ShaderLanguage::parse_statement(Parser& parser,Node *p_parent,Node **r_statement) {
+ if (!is_token_datatype(tk.type)) {
+ _set_error("Expected funtion, uniform or varying ");
+ return ERR_PARSE_ERROR;
+ }
- *r_statement=NULL;
+ type = get_token_datatype(tk.type);
- TokenType token_type = parser.get_token_type();
+ _get_completable_identifier(NULL,COMPLETION_MAIN_FUNCTION,name);
- if (token_type==TK_CURLY_BRACKET_OPEN) {
- //sub-block
- parser.advance();
- BlockNode *block = parser.create_node<BlockNode>(p_parent);
+ if (name==StringName()) {
+ _set_error("Expected function name after datatype");
+ return ERR_PARSE_ERROR;
- *r_statement=block;
- return parse_block(parser,block);
- } else if (token_type==TK_SEMICOLON) {
- // empty ;
- parser.advance();
- return OK;
- } else if (token_type==TK_CF_IF) {
- return parse_flow_if(parser,p_parent,r_statement);
+ }
- } else if (token_type==TK_CF_RETURN) {
- return parse_flow_return(parser,p_parent,r_statement);
- } else {
- Error err=parse_expression(parser,p_parent,r_statement);
- if (err)
- return err;
+ if (_find_identifier(NULL,Map<StringName,DataType>(),name)) {
+ _set_error("Redefinition of '"+String(name)+"'");
+ return ERR_PARSE_ERROR;
+ }
- if (parser.get_token_type()!=TK_SEMICOLON) {
- parser.set_error("Expected ';'");
- return ERR_PARSE_ERROR;
- }
+ tk = _get_token();
+ if (tk.type!=TK_PARENTHESIS_OPEN) {
+ _set_error("Expected '(' after identifier");
+ return ERR_PARSE_ERROR;
- }
+ }
- return OK;
-}
-Error ShaderLanguage::parse_block(Parser& parser,BlockNode *p_block) {
+ Map<StringName,DataType> builtin_types;
+ if (p_functions.has(name)) {
+ builtin_types=p_functions[name];
+ }
- while(true) {
+ ShaderNode::Function function;
- if (parser.is_at_end()) {
- if (p_block->parent->type!=Node::TYPE_PROGRAM) {
- parser.set_error("Unexpected End of File");
- return ERR_PARSE_ERROR;
- }
- return OK; //bye
- }
+ function.callable=!p_functions.has(name);
+ function.name=name;
- TokenType token_type = parser.get_token_type();
+ FunctionNode* func_node=alloc_node<FunctionNode>();
- if (token_type==TK_CURLY_BRACKET_CLOSE) {
- if (p_block->parent->type==Node::TYPE_PROGRAM) {
- parser.set_error("Unexpected '}'");
- return ERR_PARSE_ERROR;
- }
- parser.advance();
- return OK; // exit block
+ function.function=func_node;
- } else if (token_type==TK_UNIFORM) {
+ shader->functions.push_back(function);
- if (p_block!=parser.program->body) {
+ func_node->name=name;
+ func_node->return_type=type;
+ func_node->return_precision=precision;
- parser.set_error("Uniform only allowed in main program body.");
- return ERR_PARSE_ERROR;
- }
- parser.advance();
- Error err=parse_variable_declaration(parser,p_block);
- if (err)
- return err;
+ func_node->body = alloc_node<BlockNode>();
+ func_node->body->parent_function=func_node;
- } else if (is_token_datatype(token_type)) {
- Error err=OK;
- if (parser_is_at_function(parser))
- err = parse_function(parser,p_block);
- else {
- err = parse_variable_declaration(parser,p_block);
- }
+ tk = _get_token();
- if (err)
- return err;
+ while(true) {
+ if (tk.type==TK_PARENTHESIS_CLOSE) {
+ break;
+ }
- } else {
- // must be a statement
- Node *statement=NULL;
+ DataType ptype;
+ StringName pname;
+ DataPrecision pprecision = PRECISION_DEFAULT;
- Error err = parse_statement(parser,p_block,&statement);
- if (err)
- return err;
- if (statement) {
- p_block->statements.push_back(statement);
- }
+ if (is_token_precision(tk.type)) {
+ pprecision=get_token_precision(tk.type);
+ tk = _get_token();
+ }
+
+ if (!is_token_datatype(tk.type)) {
+ _set_error("Expected a valid datatype for argument");
+ return ERR_PARSE_ERROR;
+ }
+
+ ptype=get_token_datatype(tk.type);
+
+ if (ptype==TYPE_VOID) {
+ _set_error("void not allowed in argument");
+ return ERR_PARSE_ERROR;
+ }
+
+ tk = _get_token();
+
+ if (tk.type!=TK_IDENTIFIER) {
+ _set_error("Expected identifier for argument name");
+ return ERR_PARSE_ERROR;
+ }
+
+ pname = tk.text;
+
+ if (_find_identifier(func_node->body,builtin_types,pname)) {
+ _set_error("Redefinition of '"+String(pname)+"'");
+ return ERR_PARSE_ERROR;
+ }
+ FunctionNode::Argument arg;
+ arg.type=ptype;
+ arg.name=pname;
+ arg.precision=pprecision;
+
+ func_node->arguments.push_back(arg);
+
+ tk = _get_token();
+
+
+ if (tk.type==TK_COMMA) {
+ tk = _get_token();
+ //do none and go on
+ } else if (tk.type!=TK_PARENTHESIS_CLOSE) {
+ _set_error("Expected ',' or ')' after identifier");
+ return ERR_PARSE_ERROR;
+ }
+
+ }
+
+ if (p_functions.has(name)) {
+ //if one of the core functions, make sure they are of the correct form
+ if (func_node->arguments.size() > 0) {
+ _set_error("Function '"+String(name)+"' expects no arguments.");
+ return ERR_PARSE_ERROR;
+ }
+ if (func_node->return_type!=TYPE_VOID) {
+ _set_error("Function '"+String(name)+"' must be of void return type.");
+ return ERR_PARSE_ERROR;
+ }
+ }
+
+
+ //all good let's parse inside the fucntion!
+ tk = _get_token();
+ if (tk.type!=TK_CURLY_BRACKET_OPEN) {
+ _set_error("Expected '{' to begin function");
+ return ERR_PARSE_ERROR;
+ }
+
+ current_function = name;
+
+ Error err = _parse_block(func_node->body,builtin_types);
+ if (err)
+ return err;
+ current_function=StringName();
+ }
}
+
+ tk = _get_token();
}
return OK;
}
+Error ShaderLanguage::compile(const String& p_code, const Map< StringName, Map<StringName,DataType> > &p_functions, const Set<String> &p_render_modes) {
+ clear();
-Error ShaderLanguage::parse(const Vector<Token>& p_tokens,ShaderType p_type,CompileFunc p_compile_func,void *p_userdata,String *r_error,int *r_err_line,int *r_err_column) {
+ code=p_code;
+ nodes=NULL;
- Parser parser(p_tokens);
- parser.program = parser.create_node<ProgramNode>(NULL);
- parser.program->body = parser.create_node<BlockNode>(parser.program);
+ shader = alloc_node<ShaderNode>();
+ Error err = _parse_shader(p_functions,p_render_modes);
+ if (err!=OK) {
+ return err;
+ }
+ return OK;
+}
- //add builtins
- switch(p_type) {
- case SHADER_MATERIAL_VERTEX: {
- int idx=0;
- while (vertex_builtins_defs[idx].name) {
- parser.program->builtin_variables[vertex_builtins_defs[idx].name]=vertex_builtins_defs[idx].type;
- idx++;
- }
+Error ShaderLanguage::complete(const String& p_code,const Map< StringName, Map<StringName,DataType> > &p_functions,const Set<String>& p_render_modes,List<String>* r_options,String& r_call_hint) {
+
+ clear();
+
+ code=p_code;
+
+ nodes=NULL;
+
+ shader = alloc_node<ShaderNode>();
+ Error err = _parse_shader(p_functions,p_render_modes);
+
+ switch(completion_type) {
+
+ case COMPLETION_NONE: {
+ //do none
+ return ERR_PARSE_ERROR;
} break;
- case SHADER_MATERIAL_FRAGMENT: {
- int idx=0;
- while (fragment_builtins_defs[idx].name) {
- parser.program->builtin_variables[fragment_builtins_defs[idx].name]=fragment_builtins_defs[idx].type;
- idx++;
+ case COMPLETION_RENDER_MODE: {
+ for(const Set<String>::Element *E=p_render_modes.front();E;E=E->next()) {
+
+ r_options->push_back(E->get());
}
+
+ return OK;
} break;
- case SHADER_MATERIAL_LIGHT: {
- int idx=0;
- while (light_builtins_defs[idx].name) {
- parser.program->builtin_variables[light_builtins_defs[idx].name]=light_builtins_defs[idx].type;
- idx++;
+ case COMPLETION_MAIN_FUNCTION: {
+
+ for(const Map< StringName, Map<StringName,DataType> >::Element *E=p_functions.front();E;E=E->next()) {
+
+ r_options->push_back(E->key());
}
+
+ return OK;
} break;
- case SHADER_CANVAS_ITEM_VERTEX: {
- int idx=0;
- while (ci_vertex_builtins_defs[idx].name) {
- parser.program->builtin_variables[ci_vertex_builtins_defs[idx].name]=ci_vertex_builtins_defs[idx].type;
- idx++;
+ case COMPLETION_IDENTIFIER:
+ case COMPLETION_FUNCTION_CALL: {
+
+ bool comp_ident=completion_type==COMPLETION_IDENTIFIER;
+ Set<String> matches;
+
+ StringName skip_function;
+
+ BlockNode *block=completion_block;
+
+
+ while(block) {
+
+ if (comp_ident) {
+ for (const Map<StringName,BlockNode::Variable>::Element *E=block->variables.front();E;E=E->next()) {
+
+ if (E->get().line<completion_line) {
+ matches.insert(E->key());
+ }
+ }
+ }
+
+
+ if (block->parent_function) {
+ if (comp_ident) {
+ for(int i=0;i<block->parent_function->arguments.size();i++) {
+ matches.insert(block->parent_function->arguments[i].name);
+ }
+ }
+ skip_function=block->parent_function->name;
+ }
+ block=block->parent_block;
}
- } break;
- case SHADER_CANVAS_ITEM_FRAGMENT: {
- int idx=0;
- while (ci_fragment_builtins_defs[idx].name) {
- parser.program->builtin_variables[ci_fragment_builtins_defs[idx].name]=ci_fragment_builtins_defs[idx].type;
- idx++;
+
+ if (comp_ident && skip_function!=StringName() && p_functions.has(skip_function)) {
+
+ for (Map<StringName,DataType>::Element *E=p_functions[skip_function].front();E;E=E->next()) {
+ matches.insert(E->key());
+ }
}
- } break;
- case SHADER_CANVAS_ITEM_LIGHT: {
- int idx=0;
- while (ci_light_builtins_defs[idx].name) {
- parser.program->builtin_variables[ci_light_builtins_defs[idx].name]=ci_light_builtins_defs[idx].type;
- idx++;
+
+ if (comp_ident) {
+ for (const Map<StringName,ShaderNode::Varying>::Element *E=shader->varyings.front();E;E=E->next()) {
+ matches.insert(E->key());
+
+ }
+ for (const Map<StringName,ShaderNode::Uniform>::Element *E=shader->uniforms.front();E;E=E->next()) {
+ matches.insert(E->key());
+ }
+
+
}
- } break;
- case SHADER_POST_PROCESS: {
+
+ for(int i=0;i<shader->functions.size();i++) {
+ if (!shader->functions[i].callable || shader->functions[i].name==skip_function)
+ continue;
+ matches.insert(String(shader->functions[i].name)+"(");
+ }
+
int idx=0;
- while (postprocess_fragment_builtins_defs[idx].name) {
- parser.program->builtin_variables[postprocess_fragment_builtins_defs[idx].name]=postprocess_fragment_builtins_defs[idx].type;
+
+ while (builtin_func_defs[idx].name) {
+
+ matches.insert(String(builtin_func_defs[idx].name)+"(");
idx++;
}
+
+ for(Set<String>::Element *E=matches.front();E;E=E->next()) {
+ r_options->push_back(E->get());
+ }
+
+ return OK;
+
} break;
- }
+ case COMPLETION_CALL_ARGUMENTS: {
- Error err = parse_block(parser,parser.program->body);
- if (err) {
- parser.get_error(r_error,r_err_line,r_err_column);
- return err;
- }
+ for(int i=0;i<shader->functions.size();i++) {
+ if (!shader->functions[i].callable)
+ continue;
+ if (shader->functions[i].name==completion_function) {
- if (p_compile_func) {
- err = p_compile_func(p_userdata,parser.program);
- }
+ String calltip;
- //clean up nodes created
- while(parser.nodegc.size()) {
+ calltip+=get_datatype_name( shader->functions[i].function->return_type );
+ calltip+=" ";
+ calltip+=shader->functions[i].name;
+ calltip+="(";
- memdelete( parser.nodegc.front()->get() );
- parser.nodegc.pop_front();
- }
- return err;
-}
+ for(int j=0;j<shader->functions[i].function->arguments.size();j++) {
-Error ShaderLanguage::compile(const String& p_code,ShaderType p_type,CompileFunc p_compile_func,void *p_userdata,String *r_error,int *r_err_line,int *r_err_column) {
+ if (j>0)
+ calltip+=", ";
+ else
+ calltip+=" ";
- *r_error="";
- *r_err_line=0;
- *r_err_column=0;
- Vector<Token> tokens;
+ if (j==completion_argument) {
+ calltip+=CharType(0xFFFF);
+ }
- Error err = tokenize(p_code,&tokens,r_error,r_err_line,r_err_column);
- if (err!=OK) {
- print_line("tokenizer error!");
- }
+ calltip+=get_datatype_name(shader->functions[i].function->arguments[j].type);
+ calltip+=" ";
+ calltip+=shader->functions[i].function->arguments[j].name;
- if (err!=OK) {
- return err;
- }
- err = parse(tokens,p_type,p_compile_func,p_userdata,r_error,r_err_line,r_err_column);
- if (err!=OK) {
- return err;
- }
- return OK;
-}
+ if (j==completion_argument) {
+ calltip+=CharType(0xFFFF);
+ }
+ }
-void ShaderLanguage::get_keyword_list(ShaderType p_type, List<String> *p_keywords) {
+ if (shader->functions[i].function->arguments.size())
+ calltip+=" ";
+ calltip+=")";
- int idx=0;
+ r_call_hint=calltip;
+ return OK;
+ }
- p_keywords->push_back("uniform");
- p_keywords->push_back("texture");
- p_keywords->push_back("cubemap");
- p_keywords->push_back("color");
- p_keywords->push_back("if");
- p_keywords->push_back("else");
+ }
- while(intrinsic_func_defs[idx].name) {
+ int idx=0;
- p_keywords->push_back(intrinsic_func_defs[idx].name);
- idx++;
- }
+ String calltip;
+ while (builtin_func_defs[idx].name) {
- switch(p_type) {
- case SHADER_MATERIAL_VERTEX: {
- idx=0;
- while (vertex_builtins_defs[idx].name) {
- p_keywords->push_back(vertex_builtins_defs[idx].name);
- idx++;
- }
- } break;
- case SHADER_MATERIAL_FRAGMENT: {
- idx=0;
- while (fragment_builtins_defs[idx].name) {
- p_keywords->push_back(fragment_builtins_defs[idx].name);
- idx++;
- }
- } break;
- case SHADER_MATERIAL_LIGHT: {
- idx=0;
- while (light_builtins_defs[idx].name) {
- p_keywords->push_back(light_builtins_defs[idx].name);
- idx++;
- }
- } break;
- case SHADER_CANVAS_ITEM_VERTEX: {
- idx=0;
- while (ci_vertex_builtins_defs[idx].name) {
- p_keywords->push_back(ci_vertex_builtins_defs[idx].name);
- idx++;
- }
- } break;
- case SHADER_CANVAS_ITEM_FRAGMENT: {
- idx=0;
- while (ci_fragment_builtins_defs[idx].name) {
- p_keywords->push_back(ci_fragment_builtins_defs[idx].name);
+ if (completion_function==builtin_func_defs[idx].name) {
+
+ if (calltip.length())
+ calltip+="\n";
+
+ calltip+=get_datatype_name( builtin_func_defs[idx].rettype );
+ calltip+=" ";
+ calltip+=builtin_func_defs[idx].name;
+ calltip+="(";
+
+ bool found_arg=false;
+ for(int i=0;i<4;i++) {
+
+ if (builtin_func_defs[idx].args[i]==TYPE_VOID)
+ break;
+
+ if (i>0)
+ calltip+=", ";
+ else
+ calltip+=" ";
+
+ if (i==completion_argument) {
+ calltip+=CharType(0xFFFF);
+ }
+
+ calltip+=get_datatype_name(builtin_func_defs[idx].args[i]);
+
+ if (i==completion_argument) {
+ calltip+=CharType(0xFFFF);
+ }
+
+ found_arg=true;
+
+ }
+
+ if (found_arg)
+ calltip+=" ";
+ calltip+=")";
+
+
+ }
idx++;
}
+
+ r_call_hint=calltip;
+
+ return OK;
+
} break;
- case SHADER_CANVAS_ITEM_LIGHT: {
- idx=0;
- while (ci_light_builtins_defs[idx].name) {
- p_keywords->push_back(ci_light_builtins_defs[idx].name);
- idx++;
+ case COMPLETION_INDEX: {
+
+ const char colv[4]={'r','g','b','a'};
+ const char coordv[4]={'x','y','z','w'};
+
+
+ int limit=0;
+
+ switch(completion_base) {
+ case TYPE_BVEC2:
+ case TYPE_IVEC2:
+ case TYPE_UVEC2:
+ case TYPE_VEC2: {
+ limit=2;
+
+ } break;
+ case TYPE_BVEC3:
+ case TYPE_IVEC3:
+ case TYPE_UVEC3:
+ case TYPE_VEC3: {
+
+ limit=3;
+
+ } break;
+ case TYPE_BVEC4:
+ case TYPE_IVEC4:
+ case TYPE_UVEC4:
+ case TYPE_VEC4: {
+
+ limit=4;
+
+ } break;
+ case TYPE_MAT2: limit=2; break;
+ case TYPE_MAT3: limit=3; break;
+ case TYPE_MAT4: limit=4; break;
+ default: {}
}
- } break;
- case SHADER_POST_PROCESS: {
- idx=0;
- while (postprocess_fragment_builtins_defs[idx].name) {
- p_keywords->push_back(postprocess_fragment_builtins_defs[idx].name);
- idx++;
+ for(int i=0;i<limit;i++) {
+ r_options->push_back(String::chr(colv[i]));
+ r_options->push_back(String::chr(coordv[i]));
}
+
} break;
+
}
+ return ERR_PARSE_ERROR;
+}
+
+String ShaderLanguage::get_error_text() {
+
+ return error_str;
+}
+
+int ShaderLanguage::get_error_line() {
+
+ return error_line;
}
+
+ShaderLanguage::ShaderNode *ShaderLanguage::get_shader() {
+
+ return shader;
+}
+
+ShaderLanguage::ShaderLanguage() {
+
+ nodes=NULL;
+}
+
+ShaderLanguage::~ShaderLanguage() {
+
+ clear();
+}
+
+
diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h
index 31e9fcda5b..4f8717088e 100644
--- a/servers/visual/shader_language.h
+++ b/servers/visual/shader_language.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -46,12 +46,24 @@ public:
enum TokenType {
TK_EMPTY,
- TK_INDENTIFIER,
+ TK_IDENTIFIER,
TK_TRUE,
TK_FALSE,
TK_REAL_CONSTANT,
+ TK_INT_CONSTANT,
TK_TYPE_VOID,
TK_TYPE_BOOL,
+ TK_TYPE_BVEC2,
+ TK_TYPE_BVEC3,
+ TK_TYPE_BVEC4,
+ TK_TYPE_INT,
+ TK_TYPE_IVEC2,
+ TK_TYPE_IVEC3,
+ TK_TYPE_IVEC4,
+ TK_TYPE_UINT,
+ TK_TYPE_UVEC2,
+ TK_TYPE_UVEC3,
+ TK_TYPE_UVEC4,
TK_TYPE_FLOAT,
TK_TYPE_VEC2,
TK_TYPE_VEC3,
@@ -59,9 +71,13 @@ public:
TK_TYPE_MAT2,
TK_TYPE_MAT3,
TK_TYPE_MAT4,
- TK_TYPE_TEXTURE,
- TK_TYPE_CUBEMAP,
- TK_TYPE_COLOR,
+ TK_TYPE_SAMPLER2D,
+ TK_TYPE_ISAMPLER2D,
+ TK_TYPE_USAMPLER2D,
+ TK_TYPE_SAMPLERCUBE,
+ TK_PRECISION_LOW,
+ TK_PRECISION_MID,
+ TK_PRECISION_HIGH,
TK_OP_EQUAL,
TK_OP_NOT_EQUAL,
TK_OP_LESS,
@@ -75,14 +91,35 @@ public:
TK_OP_SUB,
TK_OP_MUL,
TK_OP_DIV,
- TK_OP_NEG,
+ TK_OP_MOD,
+ TK_OP_SHIFT_LEFT,
+ TK_OP_SHIFT_RIGHT,
TK_OP_ASSIGN,
TK_OP_ASSIGN_ADD,
TK_OP_ASSIGN_SUB,
TK_OP_ASSIGN_MUL,
TK_OP_ASSIGN_DIV,
+ TK_OP_ASSIGN_MOD,
+ TK_OP_ASSIGN_SHIFT_LEFT,
+ TK_OP_ASSIGN_SHIFT_RIGHT,
+ TK_OP_ASSIGN_BIT_AND,
+ TK_OP_ASSIGN_BIT_OR,
+ TK_OP_ASSIGN_BIT_XOR,
+ TK_OP_BIT_AND,
+ TK_OP_BIT_OR,
+ TK_OP_BIT_XOR,
+ TK_OP_BIT_INVERT,
+ TK_OP_INCREMENT,
+ TK_OP_DECREMENT,
TK_CF_IF,
TK_CF_ELSE,
+ TK_CF_FOR,
+ TK_CF_WHILE,
+ TK_CF_DO,
+ TK_CF_SWITCH,
+ TK_CF_CASE,
+ TK_CF_BREAK,
+ TK_CF_CONTINUE,
TK_CF_RETURN,
TK_BRACKET_OPEN,
TK_BRACKET_CLOSE,
@@ -90,31 +127,49 @@ public:
TK_CURLY_BRACKET_CLOSE,
TK_PARENTHESIS_OPEN,
TK_PARENTHESIS_CLOSE,
+ TK_QUESTION,
TK_COMMA,
+ TK_COLON,
TK_SEMICOLON,
TK_PERIOD,
TK_UNIFORM,
+ TK_VARYING,
+ TK_RENDER_MODE,
+ TK_HINT_WHITE_TEXTURE,
+ TK_HINT_BLACK_TEXTURE,
+ TK_HINT_NORMAL_TEXTURE,
+ TK_HINT_ANISO_TEXTURE,
+ TK_HINT_ALBEDO_TEXTURE,
+ TK_HINT_BLACK_ALBEDO_TEXTURE,
+ TK_HINT_COLOR,
+ TK_HINT_RANGE,
+ TK_CURSOR,
TK_ERROR,
+ TK_EOF,
TK_MAX
};
-
-
/* COMPILER */
- enum ShaderType {
- SHADER_MATERIAL_VERTEX,
- SHADER_MATERIAL_FRAGMENT,
- SHADER_MATERIAL_LIGHT,
- SHADER_CANVAS_ITEM_VERTEX,
- SHADER_CANVAS_ITEM_FRAGMENT,
- SHADER_CANVAS_ITEM_LIGHT,
- SHADER_POST_PROCESS,
- };
+ // lame work around to Apple defining this as a macro in 10.12 SDK
+ #ifdef TYPE_BOOL
+ #undef TYPE_BOOL
+ #endif
enum DataType {
TYPE_VOID,
TYPE_BOOL,
+ TYPE_BVEC2,
+ TYPE_BVEC3,
+ TYPE_BVEC4,
+ TYPE_INT,
+ TYPE_IVEC2,
+ TYPE_IVEC3,
+ TYPE_IVEC4,
+ TYPE_UINT,
+ TYPE_UVEC2,
+ TYPE_UVEC3,
+ TYPE_UVEC4,
TYPE_FLOAT,
TYPE_VEC2,
TYPE_VEC3,
@@ -122,30 +177,58 @@ public:
TYPE_MAT2,
TYPE_MAT3,
TYPE_MAT4,
- TYPE_TEXTURE,
- TYPE_CUBEMAP,
+ TYPE_SAMPLER2D,
+ TYPE_ISAMPLER2D,
+ TYPE_USAMPLER2D,
+ TYPE_SAMPLERCUBE,
+ };
+
+ enum DataPrecision {
+ PRECISION_LOWP,
+ PRECISION_MEDIUMP,
+ PRECISION_HIGHP,
+ PRECISION_DEFAULT,
};
enum Operator {
- OP_ASSIGN,
+ OP_EQUAL,
+ OP_NOT_EQUAL,
+ OP_LESS,
+ OP_LESS_EQUAL,
+ OP_GREATER,
+ OP_GREATER_EQUAL,
+ OP_AND,
+ OP_OR,
+ OP_NOT,
+ OP_NEGATE,
OP_ADD,
OP_SUB,
OP_MUL,
OP_DIV,
+ OP_MOD,
+ OP_SHIFT_LEFT,
+ OP_SHIFT_RIGHT,
+ OP_ASSIGN,
OP_ASSIGN_ADD,
OP_ASSIGN_SUB,
OP_ASSIGN_MUL,
OP_ASSIGN_DIV,
- OP_NEG,
- OP_NOT,
- OP_CMP_EQ,
- OP_CMP_NEQ,
- OP_CMP_LEQ,
- OP_CMP_GEQ,
- OP_CMP_LESS,
- OP_CMP_GREATER,
- OP_CMP_OR,
- OP_CMP_AND,
+ OP_ASSIGN_MOD,
+ OP_ASSIGN_SHIFT_LEFT,
+ OP_ASSIGN_SHIFT_RIGHT,
+ OP_ASSIGN_BIT_AND,
+ OP_ASSIGN_BIT_OR,
+ OP_ASSIGN_BIT_XOR,
+ OP_BIT_AND,
+ OP_BIT_OR,
+ OP_BIT_XOR,
+ OP_BIT_INVERT,
+ OP_INCREMENT,
+ OP_DECREMENT,
+ OP_SELECT_IF,
+ OP_SELECT_ELSE, //used only internally, then only IF appears with 3 arguments
+ OP_POST_INCREMENT,
+ OP_POST_DECREMENT,
OP_CALL,
OP_CONSTRUCT,
OP_MAX
@@ -154,18 +237,21 @@ public:
enum FlowOperation {
FLOW_OP_IF,
FLOW_OP_RETURN,
- //FLOW_OP_FOR,
- //FLOW_OP_WHILE,
- //FLOW_OP_DO,
- //FLOW_OP_BREAK,
- //FLOW_OP_CONTINUE,
+ FLOW_OP_FOR,
+ FLOW_OP_WHILE,
+ FLOW_OP_DO,
+ FLOW_OP_BREAK,
+ FLOW_OP_SWITCH,
+ FLOW_OP_CONTINUE
};
struct Node {
+ Node *next;
+
enum Type {
- TYPE_PROGRAM,
+ TYPE_SHADER,
TYPE_FUNCTION,
TYPE_BLOCK,
TYPE_VARIABLE,
@@ -175,7 +261,6 @@ public:
TYPE_MEMBER
};
- Node * parent;
Type type;
virtual DataType get_datatype() const { return TYPE_VOID; }
@@ -183,46 +268,75 @@ public:
virtual ~Node() {}
};
+ template<class T>
+ T* alloc_node() {
+ T* node = memnew(T);
+ node->next=nodes;
+ nodes=node;
+ return node;
+ }
+
+ Node *nodes;
+
struct OperatorNode : public Node {
DataType return_cache;
+ DataPrecision return_precision_cache;
Operator op;
Vector<Node*> arguments;
virtual DataType get_datatype() const { return return_cache; }
- OperatorNode() { type=TYPE_OPERATOR; return_cache=TYPE_VOID; }
+ OperatorNode() { type=TYPE_OPERATOR; return_cache=TYPE_VOID; return_precision_cache=PRECISION_DEFAULT; }
};
struct VariableNode : public Node {
- bool uniform;
DataType datatype_cache;
StringName name;
virtual DataType get_datatype() const { return datatype_cache; }
- VariableNode() { type=TYPE_VARIABLE; datatype_cache=TYPE_VOID; uniform=false; }
+ VariableNode() { type=TYPE_VARIABLE; datatype_cache=TYPE_VOID; }
};
struct ConstantNode : public Node {
DataType datatype;
- Variant value;
+
+ union Value {
+ bool boolean;
+ float real;
+ int32_t sint;
+ uint32_t uint;
+ };
+
+ Vector<Value> values;
virtual DataType get_datatype() const { return datatype; }
ConstantNode() { type=TYPE_CONSTANT; }
};
+ struct FunctionNode;
+
struct BlockNode : public Node {
+ FunctionNode *parent_function;
+ BlockNode *parent_block;
+
+ struct Variable {
+ DataType type;
+ DataPrecision precision;
+ int line; //for completion
+ };
- Map<StringName,DataType> variables;
+ Map<StringName,Variable> variables;
List<Node*> statements;
- BlockNode() { type=TYPE_BLOCK; }
+ BlockNode() { type=TYPE_BLOCK; parent_block=NULL; parent_function=NULL; }
};
struct ControlFlowNode : public Node {
FlowOperation flow_op;
- Vector<Node*> statements;
+ Vector<Node*> expressions;
+ Vector<BlockNode*> blocks;
ControlFlowNode() { type=TYPE_CONTROL_FLOW; flow_op=FLOW_OP_IF;}
};
@@ -244,39 +358,67 @@ public:
StringName name;
DataType type;
+ DataPrecision precision;
};
StringName name;
DataType return_type;
+ DataPrecision return_precision;
Vector<Argument> arguments;
BlockNode *body;
- FunctionNode() { type=TYPE_FUNCTION; }
+ FunctionNode() { type=TYPE_FUNCTION; return_precision=PRECISION_DEFAULT; }
};
- struct Uniform {
- int order;
- DataType type;
- Variant default_value;
- };
-
- struct ProgramNode : public Node {
+ struct ShaderNode : public Node {
struct Function {
StringName name;
FunctionNode*function;
+ Set<StringName> uses_function;
+ bool callable;
+ };
+
+ struct Varying {
+ DataType type;
+ DataPrecision precission;
+ };
+
+ struct Uniform {
+ enum Hint {
+ HINT_NONE,
+ HINT_COLOR,
+ HINT_RANGE,
+ HINT_ALBEDO,
+ HINT_BLACK_ALBEDO,
+ HINT_NORMAL,
+ HINT_BLACK,
+ HINT_WHITE,
+ HINT_ANISO,
+ HINT_MAX
+ };
+
+ int order;
+ int texture_order;
+ DataType type;
+ DataPrecision precission;
+ Vector<ConstantNode::Value> default_value;
+ Hint hint;
+ float hint_range[3];
+
+ Uniform() { hint=HINT_NONE; hint_range[0]=0; hint_range[1]=1; hint_range[2]=0.001;}
};
- Map<StringName,DataType> builtin_variables;
+ Map<StringName,Varying> varyings;
Map<StringName,Uniform> uniforms;
+ Vector<StringName> render_modes;
Vector<Function> functions;
- BlockNode *body;
- ProgramNode() { type=TYPE_PROGRAM; }
+ ShaderNode() { type=TYPE_SHADER; }
};
@@ -284,12 +426,12 @@ public:
bool is_op;
union {
- TokenType op;
+ Operator op;
Node *node;
};
};
- typedef Error (*CompileFunc)(void*,ProgramNode*);
+
struct VarInfo {
@@ -297,133 +439,163 @@ public:
DataType type;
};
-private:
-
-
-
- static const char * token_names[TK_MAX];
+ enum CompletionType {
+ COMPLETION_NONE,
+ COMPLETION_RENDER_MODE,
+ COMPLETION_MAIN_FUNCTION,
+ COMPLETION_IDENTIFIER,
+ COMPLETION_FUNCTION_CALL,
+ COMPLETION_CALL_ARGUMENTS,
+ COMPLETION_INDEX,
+ };
struct Token {
TokenType type;
StringName text;
- uint16_t line,col;
-
- Token(TokenType p_type=TK_EMPTY,const String& p_text=String()) { type=p_type; text=p_text; line=0; col=0; }
+ double constant;
+ uint16_t line;
};
+ static String get_operator_text(Operator p_op);
+ static String get_token_text(Token p_token);
+
+ static bool is_token_datatype(TokenType p_type);
+ static DataType get_token_datatype(TokenType p_type);
+ static bool is_token_precision(TokenType p_type);
+ static DataPrecision get_token_precision(TokenType p_type);
+ static String get_datatype_name(DataType p_type);
+ static bool is_token_nonvoid_datatype(TokenType p_type);
+ static bool is_token_operator(TokenType p_type);
+
+ static bool convert_constant(ConstantNode* p_constant, DataType p_to_type,ConstantNode::Value *p_value=NULL);
+ static DataType get_scalar_type(DataType p_type);
+ static bool is_scalar_type(DataType p_type);
+ static bool is_sampler_type(DataType p_type);
+
+ static void get_keyword_list(List<String> *r_keywords);
+ static void get_builtin_funcs(List<String> *r_keywords);
+private:
- static Token read_token(const CharType* p_text,int p_len,int &r_line,int &r_chars);
- static Error tokenize(const String& p_text,Vector<Token> *p_tokens,String *r_error,int *r_err_line,int *r_err_column);
+ struct KeyWord { TokenType token; const char *text;};
+ static const KeyWord keyword_list[];
+ bool error_set;
+ String error_str;
+ int error_line;
+ String code;
+ int char_idx;
+ int tk_line;
+ StringName current_function;
- class Parser {
+ struct TkPos {
+ int char_idx;
+ int tk_line;
+ };
- Vector<Token> tokens;
- int pos;
- String error;
- public:
+ TkPos _get_tkpos() {
+ TkPos tkp;
+ tkp.char_idx=char_idx;
+ tkp.tk_line=tk_line;
+ return tkp;
+ }
- void set_error(const String& p_error) { error=p_error; }
- void get_error(String *r_error, int *r_line, int *r_column) {
+ void _set_tkpos(TkPos p_pos) {
+ char_idx=p_pos.char_idx;
+ tk_line=p_pos.tk_line;
+ }
- *r_error=error;
- *r_line=get_token(pos).line;
- *r_column=get_token(pos).col;
- }
+ void _set_error(const String& p_str) {
+ if (error_set)
+ return;
+ error_line=tk_line;
+ error_set=true;
+ error_str=p_str;
+ }
- Token get_token(int ofs=0) const { int idx=pos+ofs; if (idx<0 || idx>=tokens.size()) return Token(TK_ERROR); return tokens[idx]; }
- TokenType get_token_type(int ofs=0) const { int idx=pos+ofs; if (idx<0 || idx>=tokens.size()) return TK_ERROR; return tokens[idx].type; }
- void advance(int p_amount=1) { pos+=p_amount; }
- bool is_at_end() const { return pos>=tokens.size(); }
+ static const char * token_names[TK_MAX];
- ProgramNode *program;
- template<class T>
- T* create_node(Node *p_parent) { T*n=memnew( T ); nodegc.push_back(n); n->parent=p_parent; return n; }
- List<Node*> nodegc;
- Parser(const Vector<Token>& p_tokens) { tokens=p_tokens; pos=0;}
- };
- struct IntrinsicFuncDef {
- enum { MAX_ARGS=5 };
- const char* name;
- DataType rettype;
- const DataType args[MAX_ARGS];
+ Token _make_token(TokenType p_type, const StringName& p_text=StringName());
+ Token _get_token();
+ ShaderNode *shader;
+
+ enum IdentifierType {
+ IDENTIFIER_FUNCTION,
+ IDENTIFIER_UNIFORM,
+ IDENTIFIER_VARYING,
+ IDENTIFIER_FUNCTION_ARGUMENT,
+ IDENTIFIER_LOCAL_VAR,
+ IDENTIFIER_BUILTIN_VAR,
};
- static const IntrinsicFuncDef intrinsic_func_defs[];
+ bool _find_identifier(const BlockNode* p_block,const Map<StringName, DataType> &p_builtin_types,const StringName& p_identifier, DataType *r_data_type=NULL, IdentifierType *r_type=NULL);
- struct OperatorDef {
+ bool _validate_operator(OperatorNode *p_op,DataType *r_ret_type=NULL);
- enum { MAX_ARGS=2 };
- Operator op;
+
+ struct BuiltinFuncDef {
+
+ enum { MAX_ARGS=5 };
+ const char* name;
DataType rettype;
const DataType args[MAX_ARGS];
+
};
- static const OperatorDef operator_defs[];
+ CompletionType completion_type;
+ int completion_line;
+ BlockNode *completion_block;
+ DataType completion_base;
+ StringName completion_function;
+ int completion_argument;
- struct BuiltinsDef {
- const char* name;
- DataType type;
- };
+ bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName& identifier);
- static const BuiltinsDef vertex_builtins_defs[];
- static const BuiltinsDef fragment_builtins_defs[];
- static const BuiltinsDef light_builtins_defs[];
+ static const BuiltinFuncDef builtin_func_defs[];
+ bool _validate_function_call(BlockNode* p_block, OperatorNode *p_func,DataType *r_ret_type);
- static const BuiltinsDef ci_vertex_builtins_defs[];
- static const BuiltinsDef ci_fragment_builtins_defs[];
- static const BuiltinsDef ci_light_builtins_defs[];
+ bool _parse_function_arguments(BlockNode *p_block, const Map<StringName,DataType> &p_builtin_types, OperatorNode* p_func, int *r_complete_arg=NULL);
+ Node* _parse_expression(BlockNode *p_block, const Map<StringName,DataType> &p_builtin_types);
- static const BuiltinsDef postprocess_fragment_builtins_defs[];
+ ShaderLanguage::Node* _reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node);
+ Node* _parse_and_reduce_expression(BlockNode *p_block,const Map<StringName,DataType> &p_builtin_types);
- static DataType get_token_datatype(TokenType p_type);
- static String get_datatype_name(DataType p_type);
- static bool is_token_datatype(TokenType p_type);
- static bool is_token_nonvoid_datatype(TokenType p_type);
+ Error _parse_block(BlockNode *p_block, const Map<StringName, DataType> &p_builtin_types, bool p_just_one=false, bool p_can_break=false, bool p_can_continue=false);
- static bool test_existing_identifier(Node *p_node,const StringName p_identifier,bool p_func=true,bool p_var=true,bool p_builtin=true);
+ Error _parse_shader(const Map< StringName, Map<StringName,DataType> > &p_functions, const Set<String> &p_render_modes);
- static bool parser_is_at_function(Parser& parser);
- static DataType compute_node_type(Node *p_node);
- static Node* validate_function_call(Parser&parser, OperatorNode *p_func);
- static Node* validate_operator(Parser& parser,OperatorNode *p_func);
- static bool is_token_operator(TokenType p_type);
- static Operator get_token_operator(TokenType p_type);
+public:
- static Error parse_expression(Parser& parser,Node *p_parent,Node **r_expr);
+ //static void get_keyword_list(ShaderType p_type,List<String> *p_keywords);
- static Error parse_variable_declaration(Parser& parser,BlockNode *p_block);
- static Error parse_function(Parser& parser,BlockNode *p_block);
- static Error parse_flow_if(Parser& parser,Node *p_parent,Node **r_statement);
- static Error parse_flow_return(Parser& parser,Node *p_parent,Node **r_statement);
- static Error parse_statement(Parser& parser,Node *p_parent,Node **r_statement);
- static Error parse_block(Parser& parser,BlockNode *p_block);
+ void clear();
+ Error compile(const String& p_code,const Map< StringName, Map<StringName,DataType> > &p_functions,const Set<String>& p_render_modes);
+ Error complete(const String& p_code,const Map< StringName, Map<StringName,DataType> > &p_functions,const Set<String>& p_render_modes,List<String>* r_options,String& r_call_hint);
- static Error parse(const Vector<Token> &p_tokens,ShaderType p_type,CompileFunc p_compile_func,void *p_userdata,String *r_error,int *r_err_line,int *r_err_column);
-;
-public:
+ String get_error_text();
+ int get_error_line();
- static void get_keyword_list(ShaderType p_type,List<String> *p_keywords);
+ ShaderNode *get_shader();
- static Error compile(const String& p_code,ShaderType p_type, CompileFunc p_compile_func,void *p_userdata,String *r_error,int *r_err_line,int *r_err_column);
- static String lex_debug(const String& p_code);
+ String token_debug(const String& p_code);
+ ShaderLanguage();
+ ~ShaderLanguage();
};
diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp
new file mode 100644
index 0000000000..0eb3e0fc5a
--- /dev/null
+++ b/servers/visual/shader_types.cpp
@@ -0,0 +1,182 @@
+#include "shader_types.h"
+
+
+const Map< StringName, Map<StringName,ShaderLanguage::DataType> >& ShaderTypes::get_functions(VS::ShaderMode p_mode) {
+
+ return shader_modes[p_mode].functions;
+}
+
+const Set<String>& ShaderTypes::get_modes(VS::ShaderMode p_mode) {
+
+ return shader_modes[p_mode].modes;
+}
+
+
+ShaderTypes *ShaderTypes::singleton=NULL;
+
+ShaderTypes::ShaderTypes()
+{
+ singleton=this;
+
+ /*************** SPATIAL ***********************/
+
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_VERTEX"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_NORMAL"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_TANGENT"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_BONES"]=ShaderLanguage::TYPE_IVEC4;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["SRC_WEIGHTS"]=ShaderLanguage::TYPE_VEC4;
+
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["POSITION"]=ShaderLanguage::TYPE_VEC4 ;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["VERTEX"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["NORMAL"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["TANGENT"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["BINORMAL"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["UV"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["UV2"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["COLOR"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["POINT_SIZE"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["INSTANCE_ID"]=ShaderLanguage::TYPE_INT;
+
+ //builtins
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["WORLD_MATRIX"]=ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["INV_CAMERA_MATRIX"]=ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["PROJECTION_MATRIX"]=ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["TIME"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["vertex"]["VIEWPORT_SIZE"]=ShaderLanguage::TYPE_VEC2;
+
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["VERTEX"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["FRAGCOORD"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["FRONT_FACING"]=ShaderLanguage::TYPE_BOOL;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["NORMAL"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["TANGENT"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["BINORMAL"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["NORMALMAP"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["NORMALMAP_DEPTH"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["UV"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["UV2"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["COLOR"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["NORMAL"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ALBEDO"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ALPHA"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SPECULAR"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ROUGHNESS"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["RIM"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["RIM_TINT"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["CLEARCOAT"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["CLEARCOAT_GLOSS"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ANISOTROPY"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["ANISOTROPY_FLOW"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SSS_STRENGTH"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["AO"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["EMISSION"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SPECIAL"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["DISCARD"]=ShaderLanguage::TYPE_BOOL;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2;
+
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["WORLD_MATRIX"]=ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["INV_CAMERA_MATRIX"]=ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["PROJECTION_MATRIX"]=ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["TIME"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_SPATIAL].functions["fragment"]["VIEWPORT_SIZE"]=ShaderLanguage::TYPE_VEC2;
+
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mix");
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_add");
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_sub");
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("blend_mul");
+
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_opaque");
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_always");
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_never");
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("depth_draw_alpha_prepass");
+
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_front");
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_back");
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("cull_disabled");
+
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("unshaded");
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("ontop");
+
+ shader_modes[VS::SHADER_SPATIAL].modes.insert("skip_transform");
+
+ /************ CANVAS ITEM **************************/
+
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["SRC_VERTEX"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["VERTEX"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["UV"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["VERTEX_COLOR"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["POINT_SIZE"]=ShaderLanguage::TYPE_FLOAT;
+
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["WORLD_MATRIX"]=ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["PROJECTION_MATRIX"]=ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["EXTRA_MATRIX"]=ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"]["TIME"]=ShaderLanguage::TYPE_FLOAT;
+
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SRC_COLOR"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POSITION"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMAL"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["NORMALMAP_DEPTH"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["UV"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["COLOR"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TEXTURE"]=ShaderLanguage::TYPE_SAMPLER2D;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TEXTURE_PIXEL_SIZE"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"]["TIME"]=ShaderLanguage::TYPE_FLOAT;
+
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POSITION"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["NORMAL"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["UV"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["COLOR"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TEXTURE"]=ShaderLanguage::TYPE_SAMPLER2D;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TEXTURE_PIXEL_SIZE"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["VAR1"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["VAR2"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["SCREEN_UV"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_VEC"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_HEIGHT"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_COLOR"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_UV"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT_SHADOW"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["LIGHT"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["SHADOW"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["POINT_COORD"]=ShaderLanguage::TYPE_VEC2;
+ shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"]["TIME"]=ShaderLanguage::TYPE_FLOAT;
+
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("skip_transform");
+
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_mix");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_add");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_sub");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_mul");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("blend_premul_alpha");
+
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("unshaded");
+ shader_modes[VS::SHADER_CANVAS_ITEM].modes.insert("light_only");
+
+
+ /************ PARTICLES **************************/
+
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["COLOR"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["VELOCITY"]=ShaderLanguage::TYPE_VEC3;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["MASS"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["ACTIVE"]=ShaderLanguage::TYPE_BOOL;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["RESTART"]=ShaderLanguage::TYPE_BOOL;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["CUSTOM"]=ShaderLanguage::TYPE_VEC4;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["TRANSFORM"]=ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["TIME"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["LIFETIME"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["DELTA"]=ShaderLanguage::TYPE_FLOAT;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["SEED"]=ShaderLanguage::TYPE_BOOL;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["ORIGIN"]=ShaderLanguage::TYPE_MAT4;
+ shader_modes[VS::SHADER_PARTICLES].functions["vertex"]["INDEX"]=ShaderLanguage::TYPE_INT;
+
+ shader_modes[VS::SHADER_PARTICLES].modes.insert("billboard");
+ shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_force");
+ shader_modes[VS::SHADER_PARTICLES].modes.insert("disable_velocity");
+
+
+
+
+}
diff --git a/servers/visual/shader_types.h b/servers/visual/shader_types.h
new file mode 100644
index 0000000000..411d5790a9
--- /dev/null
+++ b/servers/visual/shader_types.h
@@ -0,0 +1,27 @@
+#ifndef SHADERTYPES_H
+#define SHADERTYPES_H
+
+#include "shader_language.h"
+#include "servers/visual_server.h"
+class ShaderTypes {
+
+
+ struct Type {
+
+ Map< StringName, Map<StringName,ShaderLanguage::DataType> > functions;
+ Set<String> modes;
+ };
+
+ Map<VS::ShaderMode,Type> shader_modes;
+
+ static ShaderTypes *singleton;
+public:
+ static ShaderTypes *get_singleton() { return singleton; }
+
+ const Map< StringName, Map<StringName,ShaderLanguage::DataType> >& get_functions(VS::ShaderMode p_mode);
+ const Set<String>& get_modes(VS::ShaderMode p_mode);
+
+ ShaderTypes();
+};
+
+#endif // SHADERTYPES_H
diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp
new file mode 100644
index 0000000000..f4031b711d
--- /dev/null
+++ b/servers/visual/visual_server_canvas.cpp
@@ -0,0 +1,1270 @@
+#include "visual_server_canvas.h"
+#include "visual_server_global.h"
+#include "visual_server_viewport.h"
+
+void VisualServerCanvas::_render_canvas_item_tree(Item *p_canvas_item, const Transform2D& p_transform, const Rect2& p_clip_rect, const Color& p_modulate, RasterizerCanvas::Light *p_lights) {
+
+
+ static const int z_range = VS::CANVAS_ITEM_Z_MAX-VS::CANVAS_ITEM_Z_MIN+1;
+ RasterizerCanvas::Item *z_list[z_range];
+ RasterizerCanvas::Item *z_last_list[z_range];
+
+ for(int i=0;i<z_range;i++) {
+ z_list[i]=NULL;
+ z_last_list[i]=NULL;
+ }
+
+
+ _render_canvas_item(p_canvas_item,p_transform,p_clip_rect,Color(1,1,1,1),0,z_list,z_last_list,NULL,NULL);
+
+ for(int i=0;i<z_range;i++) {
+ if (!z_list[i])
+ continue;
+ VSG::canvas_render->canvas_render_items(z_list[i],VS::CANVAS_ITEM_Z_MIN+i,p_modulate,p_lights);
+ }
+
+}
+
+void VisualServerCanvas::_render_canvas_item(Item *p_canvas_item,const Transform2D& p_transform,const Rect2& p_clip_rect, const Color &p_modulate,int p_z,RasterizerCanvas::Item **z_list,RasterizerCanvas::Item **z_last_list,Item *p_canvas_clip,Item *p_material_owner) {
+
+ Item *ci = p_canvas_item;
+
+ if (!ci->visible)
+ return;
+
+ Rect2 rect = ci->get_rect();
+ Transform2D xform = p_transform * ci->xform;
+ Rect2 global_rect = xform.xform(rect);
+ global_rect.pos+=p_clip_rect.pos;
+
+
+ if (ci->use_parent_material && p_material_owner)
+ ci->material_owner=p_material_owner;
+ else {
+ p_material_owner=ci;
+ ci->material_owner=NULL;
+ }
+
+
+ Color modulate( ci->modulate.r * p_modulate.r, ci->modulate.g * p_modulate.g,ci->modulate.b * p_modulate.b,ci->modulate.a * p_modulate.a);
+
+ if (modulate.a<0.007)
+ return;
+
+
+ int child_item_count=ci->child_items.size();
+ Item **child_items=(Item**)alloca(child_item_count*sizeof(Item*));
+ copymem(child_items,ci->child_items.ptr(),child_item_count*sizeof(Item*));
+
+ if (ci->clip) {
+ if (p_canvas_clip != NULL) {
+ ci->final_clip_rect=p_canvas_clip->final_clip_rect.clip(global_rect);
+ } else {
+ ci->final_clip_rect=global_rect;
+ }
+ ci->final_clip_owner=ci;
+
+ } else {
+ ci->final_clip_owner=p_canvas_clip;
+ }
+
+ if (ci->sort_y) {
+
+ SortArray<Item*,ItemPtrSort> sorter;
+ sorter.sort(child_items,child_item_count);
+ }
+
+ if (ci->z_relative)
+ p_z=CLAMP(p_z+ci->z,VS::CANVAS_ITEM_Z_MIN,VS::CANVAS_ITEM_Z_MAX);
+ else
+ p_z=ci->z;
+
+ for(int i=0;i<child_item_count;i++) {
+
+ if (!child_items[i]->behind)
+ continue;
+ _render_canvas_item(child_items[i],xform,p_clip_rect,modulate,p_z,z_list,z_last_list,(Item*)ci->final_clip_owner,p_material_owner);
+ }
+
+ if (ci->copy_back_buffer) {
+
+ ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect);
+ }
+
+ if ((!ci->commands.empty() && p_clip_rect.intersects(global_rect)) || ci->vp_render || ci->copy_back_buffer) {
+ //something to draw?
+ ci->final_transform=xform;
+ ci->final_modulate=Color(modulate.r*ci->self_modulate.r, modulate.g*ci->self_modulate.g, modulate.b*ci->self_modulate.b, modulate.a*ci->self_modulate.a );
+ ci->global_rect_cache=global_rect;
+ ci->global_rect_cache.pos-=p_clip_rect.pos;
+ ci->light_masked=false;
+
+ int zidx = p_z-VS::CANVAS_ITEM_Z_MIN;
+
+ if (z_last_list[zidx]) {
+ z_last_list[zidx]->next=ci;
+ z_last_list[zidx]=ci;
+
+ } else {
+ z_list[zidx]=ci;
+ z_last_list[zidx]=ci;
+ }
+
+ ci->next=NULL;
+
+ }
+
+ for(int i=0;i<child_item_count;i++) {
+
+ if (child_items[i]->behind)
+ continue;
+ _render_canvas_item(child_items[i],xform,p_clip_rect,modulate,p_z,z_list,z_last_list,(Item*)ci->final_clip_owner,p_material_owner);
+ }
+
+}
+
+void VisualServerCanvas::_light_mask_canvas_items(int p_z,RasterizerCanvas::Item *p_canvas_item,RasterizerCanvas::Light *p_masked_lights) {
+
+ if (!p_masked_lights)
+ return;
+
+ RasterizerCanvas::Item *ci=p_canvas_item;
+
+ while(ci) {
+
+ RasterizerCanvas::Light *light=p_masked_lights;
+ while(light) {
+
+ if (ci->light_mask&light->item_mask && p_z>=light->z_min && p_z<=light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache,light->rect_cache)) {
+ ci->light_masked=true;
+ }
+
+ light=light->mask_next_ptr;
+ }
+
+ ci=ci->next;
+ }
+
+
+
+
+}
+
+void VisualServerCanvas::render_canvas(Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect) {
+
+ VSG::canvas_render->canvas_begin();
+
+ int l = p_canvas->child_items.size();
+ Canvas::ChildItem *ci=p_canvas->child_items.ptr();
+
+ bool has_mirror=false;
+ for(int i=0;i<l;i++) {
+ if (ci[i].mirror.x || ci[i].mirror.y) {
+ has_mirror=true;
+ break;
+ }
+ }
+
+
+ if (!has_mirror) {
+
+ static const int z_range = VS::CANVAS_ITEM_Z_MAX-VS::CANVAS_ITEM_Z_MIN+1;
+ RasterizerCanvas::Item *z_list[z_range];
+ RasterizerCanvas::Item *z_last_list[z_range];
+
+ for(int i=0;i<z_range;i++) {
+ z_list[i]=NULL;
+ z_last_list[i]=NULL;
+ }
+ for(int i=0;i<l;i++) {
+ _render_canvas_item(ci[i].item,p_transform,p_clip_rect,Color(1,1,1,1),0,z_list,z_last_list,NULL,NULL);
+ }
+
+ for(int i=0;i<z_range;i++) {
+ if (!z_list[i])
+ continue;
+
+ if (p_masked_lights) {
+ _light_mask_canvas_items(VS::CANVAS_ITEM_Z_MIN+i,z_list[i],p_masked_lights);
+ }
+
+ VSG::canvas_render->canvas_render_items(z_list[i],VS::CANVAS_ITEM_Z_MIN+i,p_canvas->modulate,p_lights);
+ }
+ } else {
+
+ for(int i=0;i<l;i++) {
+
+ Canvas::ChildItem& ci=p_canvas->child_items[i];
+ _render_canvas_item_tree(ci.item,p_transform,p_clip_rect,p_canvas->modulate,p_lights);
+
+ //mirroring (useful for scrolling backgrounds)
+ if (ci.mirror.x!=0) {
+
+ Transform2D xform2 = p_transform * Transform2D(0,Vector2(ci.mirror.x,0));
+ _render_canvas_item_tree(ci.item,xform2,p_clip_rect,p_canvas->modulate,p_lights);
+ }
+ if (ci.mirror.y!=0) {
+
+ Transform2D xform2 = p_transform * Transform2D(0,Vector2(0,ci.mirror.y));
+ _render_canvas_item_tree(ci.item,xform2,p_clip_rect,p_canvas->modulate,p_lights);
+ }
+ if (ci.mirror.y!=0 && ci.mirror.x!=0) {
+
+ Transform2D xform2 = p_transform * Transform2D(0,ci.mirror);
+ _render_canvas_item_tree(ci.item,xform2,p_clip_rect,p_canvas->modulate,p_lights);
+ }
+
+ }
+ }
+
+}
+
+
+RID VisualServerCanvas::canvas_create() {
+
+ Canvas * canvas = memnew( Canvas );
+ ERR_FAIL_COND_V(!canvas,RID());
+ RID rid = canvas_owner.make_rid( canvas );
+
+ return rid;
+}
+
+void VisualServerCanvas::canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring) {
+
+ Canvas * canvas = canvas_owner.getornull(p_canvas);
+ ERR_FAIL_COND(!canvas);
+ Item *canvas_item = canvas_item_owner.getornull(p_item);
+ ERR_FAIL_COND(!canvas_item);
+
+ int idx = canvas->find_item(canvas_item);
+ ERR_FAIL_COND(idx==-1);
+ canvas->child_items[idx].mirror=p_mirroring;
+
+}
+void VisualServerCanvas::canvas_set_modulate(RID p_canvas,const Color& p_color) {
+
+ Canvas * canvas = canvas_owner.get(p_canvas);
+ ERR_FAIL_COND(!canvas);
+ canvas->modulate=p_color;
+}
+
+
+RID VisualServerCanvas::canvas_item_create() {
+
+ Item *canvas_item = memnew( Item );
+ ERR_FAIL_COND_V(!canvas_item,RID());
+
+ return canvas_item_owner.make_rid( canvas_item );
+}
+
+void VisualServerCanvas::canvas_item_set_parent(RID p_item,RID p_parent) {
+
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ if (canvas_item->parent.is_valid()) {
+
+ if (canvas_owner.owns(canvas_item->parent)) {
+
+ Canvas *canvas = canvas_owner.get(canvas_item->parent);
+ canvas->erase_item(canvas_item);
+ } else if (canvas_item_owner.owns(canvas_item->parent)) {
+
+ Item *item_owner = canvas_item_owner.get(canvas_item->parent);
+ item_owner->child_items.erase(canvas_item);
+ }
+
+ canvas_item->parent=RID();
+ }
+
+
+ if (p_parent.is_valid()) {
+ if (canvas_owner.owns(p_parent)) {
+
+ Canvas *canvas = canvas_owner.get(p_parent);
+ Canvas::ChildItem ci;
+ ci.item=canvas_item;
+ canvas->child_items.push_back(ci);
+ canvas->children_order_dirty=true;
+ } else if (canvas_item_owner.owns(p_parent)) {
+
+ Item *item_owner = canvas_item_owner.get(p_parent);
+ item_owner->child_items.push_back(canvas_item);
+ item_owner->children_order_dirty=true;
+
+ } else {
+
+ ERR_EXPLAIN("Invalid parent");
+ ERR_FAIL();
+ }
+
+
+ }
+
+ canvas_item->parent=p_parent;
+
+
+}
+void VisualServerCanvas::canvas_item_set_visible(RID p_item,bool p_visible){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->visible=p_visible;
+
+}
+void VisualServerCanvas::canvas_item_set_light_mask(RID p_item,int p_mask){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->light_mask=p_mask;
+
+}
+
+void VisualServerCanvas::canvas_item_set_transform(RID p_item, const Transform2D& p_transform){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->xform=p_transform;
+
+}
+void VisualServerCanvas::canvas_item_set_clip(RID p_item, bool p_clip){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->clip=p_clip;
+
+}
+void VisualServerCanvas::canvas_item_set_distance_field_mode(RID p_item, bool p_enable){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->distance_field=p_enable;
+
+
+}
+void VisualServerCanvas::canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->custom_rect=p_custom_rect;
+ canvas_item->rect=p_rect;
+
+}
+void VisualServerCanvas::canvas_item_set_modulate(RID p_item, const Color& p_color) {
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->modulate=p_color;
+
+}
+void VisualServerCanvas::canvas_item_set_self_modulate(RID p_item, const Color& p_color){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->self_modulate=p_color;
+
+}
+
+void VisualServerCanvas::canvas_item_set_draw_behind_parent(RID p_item, bool p_enable){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->behind=p_enable;
+
+}
+
+
+void VisualServerCanvas::canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width,bool p_antialiased) {
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandLine * line = memnew( Item::CommandLine );
+ ERR_FAIL_COND(!line);
+ line->color=p_color;
+ line->from=p_from;
+ line->to=p_to;
+ line->width=p_width;
+ line->antialiased=p_antialiased;
+ canvas_item->rect_dirty=true;
+
+
+ canvas_item->commands.push_back(line);
+}
+
+void VisualServerCanvas::canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color) {
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandRect * rect = memnew( Item::CommandRect );
+ ERR_FAIL_COND(!rect);
+ rect->modulate=p_color;
+ rect->rect=p_rect;
+ canvas_item->rect_dirty=true;
+
+ canvas_item->commands.push_back(rect);
+}
+
+void VisualServerCanvas::canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color) {
+
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandCircle * circle = memnew( Item::CommandCircle );
+ ERR_FAIL_COND(!circle);
+ circle->color=p_color;
+ circle->pos=p_pos;
+ circle->radius=p_radius;
+
+ canvas_item->commands.push_back(circle);
+
+}
+
+void VisualServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile,const Color& p_modulate,bool p_transpose) {
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandRect * rect = memnew( Item::CommandRect );
+ ERR_FAIL_COND(!rect);
+ rect->modulate=p_modulate;
+ rect->rect=p_rect;
+ rect->flags=0;
+ if (p_tile) {
+ rect->flags|=RasterizerCanvas::CANVAS_RECT_TILE;
+ rect->flags|=RasterizerCanvas::CANVAS_RECT_REGION;
+ rect->source=Rect2(0,0,p_rect.size.width,p_rect.size.height);
+ }
+
+ if (p_rect.size.x<0) {
+
+ rect->flags|=RasterizerCanvas::CANVAS_RECT_FLIP_H;
+ rect->rect.size.x = -rect->rect.size.x;
+ }
+ if (p_rect.size.y<0) {
+
+ rect->flags|=RasterizerCanvas::CANVAS_RECT_FLIP_V;
+ rect->rect.size.y = -rect->rect.size.y;
+ }
+ if (p_transpose) {
+ rect->flags|=RasterizerCanvas::CANVAS_RECT_TRANSPOSE;
+ SWAP(rect->rect.size.x, rect->rect.size.y);
+ }
+ rect->texture=p_texture;
+ canvas_item->rect_dirty=true;
+ canvas_item->commands.push_back(rect);
+}
+
+void VisualServerCanvas::canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate,bool p_transpose) {
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandRect * rect = memnew( Item::CommandRect );
+ ERR_FAIL_COND(!rect);
+ rect->modulate=p_modulate;
+ rect->rect=p_rect;
+ rect->texture=p_texture;
+ rect->source=p_src_rect;
+ rect->flags=RasterizerCanvas::CANVAS_RECT_REGION;
+
+ if (p_rect.size.x<0) {
+
+ rect->flags|=RasterizerCanvas::CANVAS_RECT_FLIP_H;
+ rect->rect.size.x = -rect->rect.size.x;
+ }
+ if (p_rect.size.y<0) {
+
+ rect->flags|=RasterizerCanvas::CANVAS_RECT_FLIP_V;
+ rect->rect.size.y = -rect->rect.size.y;
+ }
+ if (p_transpose) {
+ rect->flags|=RasterizerCanvas::CANVAS_RECT_TRANSPOSE;
+ SWAP(rect->rect.size.x, rect->rect.size.y);
+ }
+
+ canvas_item->rect_dirty=true;
+
+ canvas_item->commands.push_back(rect);
+
+}
+
+void VisualServerCanvas::canvas_item_add_nine_patch(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright,VS::NinePatchAxisMode p_x_axis_mode, VS::NinePatchAxisMode p_y_axis_mode,bool p_draw_center,const Color& p_modulate) {
+
+
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandNinePatch * style = memnew( Item::CommandNinePatch );
+ ERR_FAIL_COND(!style);
+ style->texture=p_texture;
+ style->rect=p_rect;
+ style->source=p_source;
+ style->draw_center=p_draw_center;
+ style->color=p_modulate;
+ style->margin[MARGIN_LEFT]=p_topleft.x;
+ style->margin[MARGIN_TOP]=p_topleft.y;
+ style->margin[MARGIN_RIGHT]=p_bottomright.x;
+ style->margin[MARGIN_BOTTOM]=p_bottomright.y;
+ style->axis_x=p_x_axis_mode;
+ style->axis_y=p_y_axis_mode;
+ canvas_item->rect_dirty=true;
+
+ canvas_item->commands.push_back(style);
+}
+void VisualServerCanvas::canvas_item_add_primitive(RID p_item,const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width) {
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandPrimitive * prim = memnew( Item::CommandPrimitive );
+ ERR_FAIL_COND(!prim);
+ prim->texture=p_texture;
+ prim->points=p_points;
+ prim->uvs=p_uvs;
+ prim->colors=p_colors;
+ prim->width=p_width;
+ canvas_item->rect_dirty=true;
+
+ canvas_item->commands.push_back(prim);
+}
+
+void VisualServerCanvas::canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture) {
+
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+#ifdef DEBUG_ENABLED
+ int pointcount = p_points.size();
+ ERR_FAIL_COND(pointcount<3);
+ int color_size=p_colors.size();
+ int uv_size=p_uvs.size();
+ ERR_FAIL_COND(color_size!=0 && color_size!=1 && color_size!=pointcount);
+ ERR_FAIL_COND(uv_size!=0 && (uv_size!=pointcount || !p_texture.is_valid()));
+#endif
+ Vector<int> indices = Geometry::triangulate_polygon(p_points);
+
+ if (indices.empty()) {
+
+ ERR_EXPLAIN("Bad Polygon!");
+ ERR_FAIL_V();
+ }
+
+ Item::CommandPolygon * polygon = memnew( Item::CommandPolygon );
+ ERR_FAIL_COND(!polygon);
+ polygon->texture=p_texture;
+ polygon->points=p_points;
+ polygon->uvs=p_uvs;
+ polygon->colors=p_colors;
+ polygon->indices=indices;
+ polygon->count=indices.size();
+ canvas_item->rect_dirty=true;
+
+ canvas_item->commands.push_back(polygon);
+
+}
+
+
+void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector<int>& p_indices, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture, int p_count) {
+
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ int ps = p_points.size();
+ ERR_FAIL_COND(!p_colors.empty() && p_colors.size()!=ps && p_colors.size()!=1);
+ ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size()!=ps);
+
+ Vector<int> indices = p_indices;
+
+ int count = p_count * 3;
+
+ if (indices.empty()) {
+
+ ERR_FAIL_COND( ps % 3 != 0 );
+ if (p_count == -1)
+ count = ps;
+ } else {
+
+ ERR_FAIL_COND( indices.size() % 3 != 0 );
+ if (p_count == -1)
+ count = indices.size();
+ }
+
+ Item::CommandPolygon * polygon = memnew( Item::CommandPolygon );
+ ERR_FAIL_COND(!polygon);
+ polygon->texture=p_texture;
+ polygon->points=p_points;
+ polygon->uvs=p_uvs;
+ polygon->colors=p_colors;
+ polygon->indices=indices;
+ polygon->count = count;
+ canvas_item->rect_dirty=true;
+
+ canvas_item->commands.push_back(polygon);
+}
+
+
+void VisualServerCanvas::canvas_item_add_set_transform(RID p_item,const Transform2D& p_transform) {
+
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandTransform * tr = memnew( Item::CommandTransform );
+ ERR_FAIL_COND(!tr);
+ tr->xform=p_transform;
+
+ canvas_item->commands.push_back(tr);
+
+}
+
+void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID& p_mesh,RID p_skeleton){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandMesh * m = memnew( Item::CommandMesh );
+ ERR_FAIL_COND(!m);
+ m->mesh=p_mesh;
+ m->skeleton=p_skeleton;
+
+ canvas_item->commands.push_back(m);
+}
+void VisualServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh,RID p_skeleton){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandMultiMesh * mm = memnew( Item::CommandMultiMesh );
+ ERR_FAIL_COND(!mm);
+ mm->multimesh=p_mesh;
+ mm->skeleton=p_skeleton;
+
+ canvas_item->commands.push_back(mm);
+
+}
+
+void VisualServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignore){
+
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ Item::CommandClipIgnore * ci = memnew( Item::CommandClipIgnore);
+ ERR_FAIL_COND(!ci);
+ ci->ignore=p_ignore;
+
+ canvas_item->commands.push_back(ci);
+}
+void VisualServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable){
+
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->sort_y=p_enable;
+}
+void VisualServerCanvas::canvas_item_set_z(RID p_item, int p_z){
+
+ ERR_FAIL_COND(p_z<VS::CANVAS_ITEM_Z_MIN || p_z>VS::CANVAS_ITEM_Z_MAX);
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->z=p_z;
+}
+void VisualServerCanvas::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->z_relative=p_enable;
+
+}
+void VisualServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect){
+
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+ if (bool(canvas_item->copy_back_buffer!=NULL) !=p_enable) {
+ if (p_enable) {
+ canvas_item->copy_back_buffer = memnew( RasterizerCanvas::Item::CopyBackBuffer );
+ } else {
+ memdelete(canvas_item->copy_back_buffer);
+ canvas_item->copy_back_buffer=NULL;
+ }
+ }
+
+ if (p_enable) {
+ canvas_item->copy_back_buffer->rect=p_rect;
+ canvas_item->copy_back_buffer->full=p_rect==Rect2();
+ }
+
+}
+
+void VisualServerCanvas::canvas_item_clear(RID p_item){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->clear();
+}
+void VisualServerCanvas::canvas_item_set_draw_index(RID p_item,int p_index){
+
+ Item *canvas_item = canvas_item_owner.getornull( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->index=p_index;
+
+ if (canvas_item_owner.owns( canvas_item->parent)) {
+ Item *canvas_item_parent = canvas_item_owner.getornull( canvas_item->parent );
+ canvas_item_parent->children_order_dirty=true;
+ return;
+ }
+
+ Canvas* canvas = canvas_owner.getornull( canvas_item->parent );
+ if (canvas) {
+ canvas->children_order_dirty=true;
+ return;
+ }
+
+}
+
+void VisualServerCanvas::canvas_item_set_material(RID p_item, RID p_material){
+
+ Item *canvas_item = canvas_item_owner.get( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->material=p_material;
+}
+
+void VisualServerCanvas::canvas_item_set_use_parent_material(RID p_item, bool p_enable){
+
+ Item *canvas_item = canvas_item_owner.get( p_item );
+ ERR_FAIL_COND(!canvas_item);
+
+ canvas_item->use_parent_material=p_enable;
+
+}
+
+RID VisualServerCanvas::canvas_light_create(){
+
+ RasterizerCanvas::Light *clight = memnew( RasterizerCanvas::Light );
+ clight->light_internal = VSG::canvas_render->light_internal_create();
+ return canvas_light_owner.make_rid(clight);
+
+}
+void VisualServerCanvas::canvas_light_attach_to_canvas(RID p_light,RID p_canvas){
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ if (clight->canvas.is_valid()) {
+
+ Canvas *canvas = canvas_owner.getornull(clight->canvas);
+ canvas->lights.erase(clight);
+ }
+
+ if (!canvas_owner.owns(p_canvas))
+ p_canvas=RID();
+
+ clight->canvas=p_canvas;
+
+ if (clight->canvas.is_valid()) {
+
+ Canvas *canvas = canvas_owner.get(clight->canvas);
+ canvas->lights.insert(clight);
+ }
+}
+
+
+void VisualServerCanvas::canvas_light_set_enabled(RID p_light, bool p_enabled){
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->enabled=p_enabled;
+
+}
+void VisualServerCanvas::canvas_light_set_scale(RID p_light, float p_scale){
+
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->scale=p_scale;
+
+}
+void VisualServerCanvas::canvas_light_set_transform(RID p_light, const Transform2D& p_transform){
+
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->xform=p_transform;
+
+}
+void VisualServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture){
+
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->texture=p_texture;
+
+}
+void VisualServerCanvas::canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset){
+
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->texture_offset=p_offset;
+
+}
+void VisualServerCanvas::canvas_light_set_color(RID p_light, const Color& p_color){
+
+
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->color=p_color;
+}
+void VisualServerCanvas::canvas_light_set_height(RID p_light, float p_height){
+
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->height=p_height;
+
+}
+void VisualServerCanvas::canvas_light_set_energy(RID p_light, float p_energy){
+
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->energy=p_energy;
+
+}
+void VisualServerCanvas::canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z){
+
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->z_min=p_min_z;
+ clight->z_max=p_max_z;
+
+}
+void VisualServerCanvas::canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer){
+
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+
+ clight->layer_max=p_max_layer;
+ clight->layer_min=p_min_layer;
+
+
+}
+void VisualServerCanvas::canvas_light_set_item_cull_mask(RID p_light, int p_mask){
+
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->item_mask=p_mask;
+
+}
+void VisualServerCanvas::canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask){
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->item_shadow_mask=p_mask;
+
+}
+void VisualServerCanvas::canvas_light_set_mode(RID p_light, VS::CanvasLightMode p_mode){
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->mode=p_mode;
+
+}
+
+
+void VisualServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled){
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ if (clight->shadow_buffer.is_valid()==p_enabled)
+ return;
+ if (p_enabled) {
+ clight->shadow_buffer=VSG::storage->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
+ } else {
+ VSG::storage->free(clight->shadow_buffer);
+ clight->shadow_buffer=RID();
+ }
+
+}
+void VisualServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_size){
+
+ ERR_FAIL_COND(p_size<32 || p_size>16384);
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ int new_size = nearest_power_of_2(p_size);
+ if (new_size==clight->shadow_buffer_size)
+ return;
+
+ clight->shadow_buffer_size=nearest_power_of_2(p_size);
+
+ if (clight->shadow_buffer.is_valid()) {
+ VSG::storage->free(clight->shadow_buffer);
+ clight->shadow_buffer=VSG::storage->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
+ }
+}
+
+void VisualServerCanvas::canvas_light_set_shadow_gradient_length(RID p_light, float p_length) {
+
+ ERR_FAIL_COND(p_length<0);
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->shadow_gradient_length=p_length;
+
+}
+void VisualServerCanvas::canvas_light_set_shadow_filter(RID p_light, VS::CanvasLightShadowFilter p_filter) {
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->shadow_filter=p_filter;
+
+}
+void VisualServerCanvas::canvas_light_set_shadow_color(RID p_light, const Color& p_color) {
+
+ RasterizerCanvas::Light *clight = canvas_light_owner.get(p_light);
+ ERR_FAIL_COND(!clight);
+
+ clight->shadow_color=p_color;
+}
+
+
+
+RID VisualServerCanvas::canvas_light_occluder_create() {
+
+ RasterizerCanvas::LightOccluderInstance *occluder = memnew( RasterizerCanvas::LightOccluderInstance );
+
+ return canvas_light_occluder_owner.make_rid(occluder);
+}
+void VisualServerCanvas::canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas){
+
+ RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ if (occluder->canvas.is_valid()) {
+
+ Canvas *canvas = canvas_owner.get(occluder->canvas);
+ canvas->occluders.erase(occluder);
+ }
+
+ if (!canvas_owner.owns(p_canvas))
+ p_canvas=RID();
+
+ occluder->canvas=p_canvas;
+
+ if (occluder->canvas.is_valid()) {
+
+ Canvas *canvas = canvas_owner.get(occluder->canvas);
+ canvas->occluders.insert(occluder);
+ }
+}
+void VisualServerCanvas::canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled) {
+
+ RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ occluder->enabled=p_enabled;
+}
+void VisualServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon) {
+
+ RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ if (occluder->polygon.is_valid()) {
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
+ if (occluder_poly) {
+ occluder_poly->owners.erase(occluder);
+ }
+ }
+
+ occluder->polygon=p_polygon;
+ occluder->polygon_buffer=RID();
+
+ if (occluder->polygon.is_valid()) {
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
+ if (!occluder_poly)
+ occluder->polygon=RID();
+ ERR_FAIL_COND(!occluder_poly);
+ occluder_poly->owners.insert(occluder);
+ occluder->polygon_buffer=occluder_poly->occluder;
+ occluder->aabb_cache=occluder_poly->aabb;
+ occluder->cull_cache=occluder_poly->cull_mode;
+ }
+
+}
+void VisualServerCanvas::canvas_light_occluder_set_transform(RID p_occluder,const Transform2D& p_xform) {
+
+ RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ occluder->xform=p_xform;
+}
+void VisualServerCanvas::canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask) {
+
+ RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_occluder);
+ ERR_FAIL_COND(!occluder);
+
+ occluder->light_mask=p_mask;
+}
+
+RID VisualServerCanvas::canvas_occluder_polygon_create() {
+
+ LightOccluderPolygon * occluder_poly = memnew( LightOccluderPolygon );
+ occluder_poly->occluder=VSG::storage->canvas_light_occluder_create();
+ return canvas_light_occluder_polygon_owner.make_rid(occluder_poly);
+
+}
+void VisualServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape,bool p_closed) {
+
+ if (p_shape.size()<3) {
+ canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,p_shape);
+ return;
+ }
+
+ PoolVector<Vector2> lines;
+ int lc = p_shape.size()*2;
+
+ lines.resize(lc-(p_closed?0:2));
+ {
+ PoolVector<Vector2>::Write w = lines.write();
+ PoolVector<Vector2>::Read r = p_shape.read();
+
+ int max=lc/2;
+ if (!p_closed) {
+ max--;
+ }
+ for(int i=0;i<max;i++) {
+
+ Vector2 a = r[i];
+ Vector2 b = r[(i+1)%(lc/2)];
+ w[i*2+0]=a;
+ w[i*2+1]=b;
+ }
+
+ }
+
+ canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,lines);
+}
+void VisualServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape) {
+
+ LightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
+ ERR_FAIL_COND(!occluder_poly);
+ ERR_FAIL_COND(p_shape.size()&1);
+
+ int lc = p_shape.size();
+ occluder_poly->aabb=Rect2();
+ {
+ PoolVector<Vector2>::Read r = p_shape.read();
+ for(int i=0;i<lc;i++) {
+ if (i==0)
+ occluder_poly->aabb.pos=r[i];
+ else
+ occluder_poly->aabb.expand_to(r[i]);
+ }
+ }
+
+ VSG::storage->canvas_light_occluder_set_polylines(occluder_poly->occluder,p_shape);
+ for( Set<RasterizerCanvas::LightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) {
+ E->get()->aabb_cache=occluder_poly->aabb;
+ }
+}
+
+
+void VisualServerCanvas::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,VS::CanvasOccluderPolygonCullMode p_mode) {
+
+ LightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
+ ERR_FAIL_COND(!occluder_poly);
+ occluder_poly->cull_mode=p_mode;
+ for( Set<RasterizerCanvas::LightOccluderInstance*>::Element *E=occluder_poly->owners.front();E;E=E->next()) {
+ E->get()->cull_cache=p_mode;
+ }
+}
+
+
+
+bool VisualServerCanvas::free(RID p_rid) {
+
+ if (canvas_owner.owns(p_rid)) {
+
+ Canvas *canvas = canvas_owner.get(p_rid);
+ ERR_FAIL_COND_V(!canvas,false);
+
+ while(canvas->viewports.size()) {
+
+ VisualServerViewport::Viewport *vp = VSG::viewport->viewport_owner.get(canvas->viewports.front()->get());
+ ERR_FAIL_COND_V(!vp,true);
+
+ Map<RID,VisualServerViewport::Viewport::CanvasData>::Element *E=vp->canvas_map.find(p_rid);
+ ERR_FAIL_COND_V(!E,true);
+ vp->canvas_map.erase(p_rid);
+
+ canvas->viewports.erase( canvas->viewports.front() );
+ }
+
+ for (int i=0;i<canvas->child_items.size();i++) {
+
+ canvas->child_items[i].item->parent=RID();
+ }
+
+ for (Set<RasterizerCanvas::Light*>::Element *E=canvas->lights.front();E;E=E->next()) {
+
+ E->get()->canvas=RID();
+ }
+
+ for (Set<RasterizerCanvas::LightOccluderInstance*>::Element *E=canvas->occluders.front();E;E=E->next()) {
+
+ E->get()->canvas=RID();
+ }
+
+ canvas_owner.free( p_rid );
+
+ memdelete( canvas );
+
+ } else if (canvas_item_owner.owns(p_rid)) {
+
+ Item *canvas_item = canvas_item_owner.get(p_rid);
+ ERR_FAIL_COND_V(!canvas_item,true);
+
+ if (canvas_item->parent.is_valid()) {
+
+ if (canvas_owner.owns(canvas_item->parent)) {
+
+ Canvas *canvas = canvas_owner.get(canvas_item->parent);
+ canvas->erase_item(canvas_item);
+ } else if (canvas_item_owner.owns(canvas_item->parent)) {
+
+ Item *item_owner = canvas_item_owner.get(canvas_item->parent);
+ item_owner->child_items.erase(canvas_item);
+
+ }
+ }
+
+ for (int i=0;i<canvas_item->child_items.size();i++) {
+
+ canvas_item->child_items[i]->parent=RID();
+ }
+
+ /*
+ if (canvas_item->material) {
+ canvas_item->material->owners.erase(canvas_item);
+ }
+ */
+
+ canvas_item_owner.free( p_rid );
+
+ memdelete( canvas_item );
+
+ } else if (canvas_light_owner.owns(p_rid)) {
+
+ RasterizerCanvas::Light *canvas_light = canvas_light_owner.get(p_rid);
+ ERR_FAIL_COND_V(!canvas_light,true);
+
+ if (canvas_light->canvas.is_valid()) {
+ Canvas* canvas = canvas_owner.get(canvas_light->canvas);
+ if (canvas)
+ canvas->lights.erase(canvas_light);
+ }
+
+ if (canvas_light->shadow_buffer.is_valid())
+ VSG::storage->free(canvas_light->shadow_buffer);
+
+ VSG::canvas_render->light_internal_free(canvas_light->light_internal);
+
+ canvas_light_owner.free( p_rid );
+ memdelete( canvas_light );
+
+ } else if (canvas_light_occluder_owner.owns(p_rid)) {
+
+ RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.get(p_rid);
+ ERR_FAIL_COND_V(!occluder,true);
+
+ if (occluder->polygon.is_valid()) {
+
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(occluder->polygon);
+ if (occluder_poly) {
+ occluder_poly->owners.erase(occluder);
+ }
+
+ }
+
+ if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) {
+
+ Canvas *canvas = canvas_owner.get(occluder->canvas);
+ canvas->occluders.erase(occluder);
+
+ }
+
+ canvas_light_occluder_owner.free( p_rid );
+ memdelete(occluder);
+
+ } else if (canvas_light_occluder_polygon_owner.owns(p_rid)) {
+
+ LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_rid);
+ ERR_FAIL_COND_V(!occluder_poly,true);
+ VSG::storage->free(occluder_poly->occluder);
+
+ while(occluder_poly->owners.size()) {
+
+ occluder_poly->owners.front()->get()->polygon=RID();
+ occluder_poly->owners.erase( occluder_poly->owners.front() );
+ }
+
+ canvas_light_occluder_polygon_owner.free( p_rid );
+ memdelete(occluder_poly);
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+
+
+VisualServerCanvas::VisualServerCanvas()
+{
+
+}
diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h
new file mode 100644
index 0000000000..035c48d9ef
--- /dev/null
+++ b/servers/visual/visual_server_canvas.h
@@ -0,0 +1,217 @@
+#ifndef VISUALSERVERCANVAS_H
+#define VISUALSERVERCANVAS_H
+
+#include "rasterizer.h"
+#include "visual_server_viewport.h"
+
+class VisualServerCanvas {
+public:
+
+
+ struct Item : public RasterizerCanvas::Item {
+
+
+ RID parent; // canvas it belongs to
+ List<Item*>::Element *E;
+ int z;
+ bool z_relative;
+ bool sort_y;
+ Color modulate;
+ Color self_modulate;
+ bool use_parent_material;
+ int index;
+ bool children_order_dirty;
+
+
+ Vector<Item*> child_items;
+
+
+ Item() {
+ children_order_dirty=true;
+ E=NULL;
+ z=0;
+ modulate=Color(1,1,1,1);
+ self_modulate=Color(1,1,1,1);
+ sort_y=false;
+ use_parent_material=false;
+ z_relative=true;
+ index=0;
+ }
+ };
+
+
+ struct ItemPtrSort {
+
+ _FORCE_INLINE_ bool operator()(const Item* p_left,const Item* p_right) const {
+
+ if(Math::abs(p_left->xform.elements[2].y - p_right->xform.elements[2].y) < CMP_EPSILON )
+ return p_left->xform.elements[2].x < p_right->xform.elements[2].x;
+ else
+ return p_left->xform.elements[2].y < p_right->xform.elements[2].y;
+ }
+ };
+
+ struct LightOccluderPolygon : RID_Data {
+
+ bool active;
+ Rect2 aabb;
+ VS::CanvasOccluderPolygonCullMode cull_mode;
+ RID occluder;
+ Set<RasterizerCanvas::LightOccluderInstance*> owners;
+
+ LightOccluderPolygon() { active=false; cull_mode=VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
+ };
+
+
+ RID_Owner<LightOccluderPolygon> canvas_light_occluder_polygon_owner;
+
+ RID_Owner<RasterizerCanvas::LightOccluderInstance> canvas_light_occluder_owner;
+
+ struct Canvas : public VisualServerViewport::CanvasBase {
+
+ Set<RID> viewports;
+ struct ChildItem {
+
+ Point2 mirror;
+ Item *item;
+ bool operator<(const ChildItem& p_item) const {
+ return item->index < p_item.item->index;
+ }
+ };
+
+
+
+ Set<RasterizerCanvas::Light*> lights;
+
+ Set<RasterizerCanvas::LightOccluderInstance*> occluders;
+
+ bool children_order_dirty;
+ Vector<ChildItem> child_items;
+ Color modulate;
+
+ int find_item(Item *p_item) {
+ for(int i=0;i<child_items.size();i++) {
+ if (child_items[i].item==p_item)
+ return i;
+ }
+ return -1;
+ }
+ void erase_item(Item *p_item) {
+ int idx=find_item(p_item);
+ if (idx>=0)
+ child_items.remove(idx);
+ }
+
+
+ Canvas() { modulate=Color(1,1,1,1); children_order_dirty=true; }
+
+ };
+
+
+ RID_Owner<Canvas> canvas_owner;
+ RID_Owner<Item> canvas_item_owner;
+ RID_Owner<RasterizerCanvas::Light> canvas_light_owner;
+
+private:
+
+ void _render_canvas_item_tree(Item *p_canvas_item, const Transform2D& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights);
+ void _render_canvas_item(Item *p_canvas_item, const Transform2D& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner);
+ void _light_mask_canvas_items(int p_z,RasterizerCanvas::Item *p_canvas_item,RasterizerCanvas::Light *p_masked_lights);
+public:
+
+ void render_canvas(Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights,const Rect2& p_clip_rect);
+
+ RID canvas_create();
+ void canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring);
+ void canvas_set_modulate(RID p_canvas,const Color& p_color);
+
+
+ RID canvas_item_create();
+ void canvas_item_set_parent(RID p_item,RID p_parent);
+
+ void canvas_item_set_visible(RID p_item,bool p_visible);
+ void canvas_item_set_light_mask(RID p_item,int p_mask);
+
+ void canvas_item_set_transform(RID p_item, const Transform2D& p_transform);
+ void canvas_item_set_clip(RID p_item, bool p_clip);
+ void canvas_item_set_distance_field_mode(RID p_item, bool p_enable);
+ void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2());
+ void canvas_item_set_modulate(RID p_item, const Color& p_color);
+ void canvas_item_set_self_modulate(RID p_item, const Color& p_color);
+
+ void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable);
+
+
+ void canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width=1.0,bool p_antialiased=false);
+ void canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color);
+ void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color);
+ void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false);
+ void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false);
+ void canvas_item_add_nine_patch(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright,VS::NinePatchAxisMode p_x_axis_mode=VS::NINE_PATCH_STRETCH, VS::NinePatchAxisMode p_y_axis_mode=VS::NINE_PATCH_STRETCH,bool p_draw_center=true,const Color& p_modulate=Color(1,1,1));
+ void canvas_item_add_primitive(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width=1.0);
+ void canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID());
+ void canvas_item_add_triangle_array(RID p_item, const Vector<int>& p_indices, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID(), int p_count=-1);
+ void canvas_item_add_mesh(RID p_item, const RID& p_mesh,RID p_skeleton=RID());
+ void canvas_item_add_multimesh(RID p_item, RID p_mesh,RID p_skeleton=RID());
+ void canvas_item_add_set_transform(RID p_item,const Transform2D& p_transform);
+ void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
+ void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
+ void canvas_item_set_z(RID p_item, int p_z);
+ void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
+ void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect);
+
+ void canvas_item_clear(RID p_item);
+ void canvas_item_set_draw_index(RID p_item, int p_index);
+
+ void canvas_item_set_material(RID p_item, RID p_material);
+
+ void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
+
+ RID canvas_light_create();
+ void canvas_light_attach_to_canvas(RID p_light,RID p_canvas);
+ void canvas_light_set_enabled(RID p_light, bool p_enabled);
+ void canvas_light_set_scale(RID p_light, float p_scale);
+ void canvas_light_set_transform(RID p_light, const Transform2D& p_transform);
+ void canvas_light_set_texture(RID p_light, RID p_texture);
+ void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset);
+ void canvas_light_set_color(RID p_light, const Color& p_color);
+ void canvas_light_set_height(RID p_light, float p_height);
+ void canvas_light_set_energy(RID p_light, float p_energy);
+ void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z);
+ void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer);
+ void canvas_light_set_item_cull_mask(RID p_light, int p_mask);
+ void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask);
+
+ void canvas_light_set_mode(RID p_light, VS::CanvasLightMode p_mode);
+
+
+ void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled);
+ void canvas_light_set_shadow_buffer_size(RID p_light, int p_size);
+ void canvas_light_set_shadow_gradient_length(RID p_light, float p_length);
+ void canvas_light_set_shadow_filter(RID p_light, VS::CanvasLightShadowFilter p_filter);
+ void canvas_light_set_shadow_color(RID p_light, const Color& p_color);
+
+
+
+ RID canvas_light_occluder_create();
+ void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas);
+ void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled);
+ void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon);
+ void canvas_light_occluder_set_transform(RID p_occluder,const Transform2D& p_xform);
+ void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask);
+
+ RID canvas_occluder_polygon_create();
+ void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape,bool p_closed);
+ void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape);
+
+
+ void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,VS::CanvasOccluderPolygonCullMode p_mode);
+
+
+ bool free(RID p_rid);
+ VisualServerCanvas();
+
+
+};
+
+#endif // VISUALSERVERCANVAS_H
diff --git a/servers/visual/visual_server_global.cpp b/servers/visual/visual_server_global.cpp
new file mode 100644
index 0000000000..32b9710f42
--- /dev/null
+++ b/servers/visual/visual_server_global.cpp
@@ -0,0 +1,10 @@
+#include "visual_server_global.h"
+
+RasterizerStorage *VisualServerGlobals::storage=NULL;
+RasterizerCanvas *VisualServerGlobals::canvas_render=NULL;
+RasterizerScene *VisualServerGlobals::scene_render=NULL;
+Rasterizer *VisualServerGlobals::rasterizer=NULL;
+
+VisualServerCanvas *VisualServerGlobals::canvas=NULL;
+VisualServerViewport *VisualServerGlobals::viewport=NULL;
+VisualServerScene *VisualServerGlobals::scene=NULL;
diff --git a/servers/visual/visual_server_global.h b/servers/visual/visual_server_global.h
new file mode 100644
index 0000000000..d413334ac4
--- /dev/null
+++ b/servers/visual/visual_server_global.h
@@ -0,0 +1,26 @@
+#ifndef VISUALSERVERGLOBAL_H
+#define VISUALSERVERGLOBAL_H
+
+#include "rasterizer.h"
+
+class VisualServerCanvas;
+class VisualServerViewport;
+class VisualServerScene;
+
+class VisualServerGlobals
+{
+public:
+
+ static RasterizerStorage *storage;
+ static RasterizerCanvas *canvas_render;
+ static RasterizerScene *scene_render;
+ static Rasterizer *rasterizer;
+
+ static VisualServerCanvas *canvas;
+ static VisualServerViewport *viewport;
+ static VisualServerScene *scene;
+};
+
+#define VSG VisualServerGlobals
+
+#endif // VISUALSERVERGLOBAL_H
diff --git a/servers/visual/visual_server_light_baker.cpp b/servers/visual/visual_server_light_baker.cpp
new file mode 100644
index 0000000000..4956d78ab0
--- /dev/null
+++ b/servers/visual/visual_server_light_baker.cpp
@@ -0,0 +1,6 @@
+#include "visual_server_light_baker.h"
+
+VisualServerLightBaker::VisualServerLightBaker()
+{
+
+}
diff --git a/servers/visual/visual_server_light_baker.h b/servers/visual/visual_server_light_baker.h
new file mode 100644
index 0000000000..42f016f614
--- /dev/null
+++ b/servers/visual/visual_server_light_baker.h
@@ -0,0 +1,29 @@
+#ifndef VISUALSERVERLIGHTBAKER_H
+#define VISUALSERVERLIGHTBAKER_H
+
+#include "servers/visual_server.h"
+
+class VisualServerLightBaker {
+public:
+
+ struct BakeCell {
+
+ uint32_t cells[8];
+ uint32_t neighbours[7]; //one unused
+ uint32_t albedo; //albedo in RGBE
+ uint32_t emission; //emissive light in RGBE
+ uint32_t light[4]; //accumulated light in 16:16 fixed point (needs to be integer for moving lights fast)
+ float alpha; //used for upsampling
+ uint32_t directional_pass; //used for baking directional
+
+ };
+
+
+
+
+
+
+ VisualServerLightBaker();
+};
+
+#endif // VISUALSERVERLIGHTBAKER_H
diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp
index f7614ac080..3a5ffda8f5 100644
--- a/servers/visual/visual_server_raster.cpp
+++ b/servers/visual/visual_server_raster.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -28,18 +28,169 @@
/*************************************************************************/
#include "visual_server_raster.h"
#include "os/os.h"
-#include "globals.h"
+#include "global_config.h"
#include "default_mouse_cursor.xpm"
#include "sort.h"
#include "io/marshalls.h"
+#include "visual_server_canvas.h"
+#include "visual_server_global.h"
+#include "visual_server_scene.h"
+
// careful, these may run in different threads than the visual server
+
+
+
+/* CURSOR */
+void VisualServerRaster::cursor_set_rotation(float p_rotation, int p_cursor ){
+
+}
+void VisualServerRaster::cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor, const Rect2 &p_region){
+
+}
+void VisualServerRaster::cursor_set_visible(bool p_visible, int p_cursor ){
+
+}
+void VisualServerRaster::cursor_set_pos(const Point2& p_pos, int p_cursor ){
+
+}
+
+/* BLACK BARS */
+
+
+void VisualServerRaster::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom){
+
+}
+void VisualServerRaster::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom){
+
+}
+
+
+/* FREE */
+
+void VisualServerRaster::free( RID p_rid ){
+
+ if (VSG::storage->free(p_rid))
+ return;
+ if (VSG::canvas->free(p_rid))
+ return;
+ if (VSG::viewport->free(p_rid))
+ return;
+ if (VSG::scene->free(p_rid))
+ return;
+
+}
+
+/* EVENT QUEUING */
+
+void VisualServerRaster::draw(){
+
+ /*
+ if (changes)
+ print_line("changes: "+itos(changes));
+ */
+
+ changes=0;
+
+ VSG::rasterizer->begin_frame();
+
+ VSG::scene->update_dirty_instances(); //update scene stuff
+
+ VSG::viewport->draw_viewports();
+ VSG::scene->render_probes();
+ //_draw_cursors_and_margins();
+ VSG::rasterizer->end_frame();
+ //draw_extra_frame=VS:rasterizer->needs_to_draw_next_frame();
+}
+void VisualServerRaster::sync(){
+
+}
+bool VisualServerRaster::has_changed() const{
+
+ return changes>0;
+}
+void VisualServerRaster::init(){
+
+ VSG::rasterizer->initialize();
+
+}
+void VisualServerRaster::finish(){
+
+ if (test_cube.is_valid()) {
+ free(test_cube);
+ }
+
+ VSG::rasterizer->finalize();
+}
+
+
+/* STATUS INFORMATION */
+
+
+int VisualServerRaster::get_render_info(RenderInfo p_info){
+
+ return 0;
+}
+
+
+
+/* TESTING */
+
+
+
+void VisualServerRaster::set_boot_image(const Image& p_image, const Color& p_color,bool p_scale){
+
+}
+void VisualServerRaster::set_default_clear_color(const Color& p_color){
+
+}
+
+bool VisualServerRaster::has_feature(Features p_feature) const {
+
+ return false;
+}
+
+RID VisualServerRaster::get_test_cube() {
+ if (!test_cube.is_valid()) {
+ test_cube=_make_test_cube();
+ }
+ return test_cube;
+}
+
+
+bool VisualServerRaster::has_os_feature(const String& p_feature) const {
+
+ return VSG::storage->has_os_feature(p_feature);
+}
+
+VisualServerRaster::VisualServerRaster() {
+
+ VSG::canvas = memnew( VisualServerCanvas);
+ VSG::viewport = memnew( VisualServerViewport);
+ VSG::scene = memnew( VisualServerScene );
+ VSG::rasterizer = Rasterizer::create();
+ VSG::storage=VSG::rasterizer->get_storage();
+ VSG::canvas_render=VSG::rasterizer->get_canvas();
+ VSG::scene_render=VSG::rasterizer->get_scene();
+
+}
+
+VisualServerRaster::~VisualServerRaster() {
+
+ memdelete(VSG::canvas);
+ memdelete(VSG::viewport);
+ memdelete(VSG::rasterizer);
+}
+
+
+#if 0
+
BalloonAllocator<> *VisualServerRaster::OctreeAllocator::allocator=NULL;
#define VS_CHANGED\
changes++;\
-// print_line(__FUNCTION__);
+ //print_line(__FUNCTION__);
@@ -265,33 +416,33 @@ RID VisualServerRaster::fixed_material_create() {
return rasterizer->fixed_material_create();
}
-void VisualServerRaster::fixed_material_set_flag(RID p_material, FixedMaterialFlags p_flag, bool p_enabled) {
+void VisualServerRaster::fixed_material_set_flag(RID p_material, FixedSpatialMaterialFlags p_flag, bool p_enabled) {
rasterizer->fixed_material_set_flag(p_material,p_flag,p_enabled);
}
-bool VisualServerRaster::fixed_material_get_flag(RID p_material, FixedMaterialFlags p_flag) const {
+bool VisualServerRaster::fixed_material_get_flag(RID p_material, FixedSpatialMaterialFlags p_flag) const {
return rasterizer->fixed_material_get_flag(p_material,p_flag);
}
-void VisualServerRaster::fixed_material_set_param(RID p_material, FixedMaterialParam p_parameter, const Variant& p_value) {
+void VisualServerRaster::fixed_material_set_param(RID p_material, FixedSpatialMaterialParam p_parameter, const Variant& p_value) {
VS_CHANGED;
rasterizer->fixed_material_set_parameter(p_material,p_parameter,p_value);
}
-Variant VisualServerRaster::fixed_material_get_param(RID p_material,FixedMaterialParam p_parameter) const {
+Variant VisualServerRaster::fixed_material_get_param(RID p_material,FixedSpatialMaterialParam p_parameter) const {
return rasterizer->fixed_material_get_parameter(p_material,p_parameter);
}
-void VisualServerRaster::fixed_material_set_texture(RID p_material,FixedMaterialParam p_parameter, RID p_texture) {
+void VisualServerRaster::fixed_material_set_texture(RID p_material,FixedSpatialMaterialParam p_parameter, RID p_texture) {
VS_CHANGED;
rasterizer->fixed_material_set_texture(p_material,p_parameter,p_texture);
}
-RID VisualServerRaster::fixed_material_get_texture(RID p_material,FixedMaterialParam p_parameter) const {
+RID VisualServerRaster::fixed_material_get_texture(RID p_material,FixedSpatialMaterialParam p_parameter) const {
return rasterizer->fixed_material_get_texture(p_material,p_parameter);
}
@@ -299,12 +450,12 @@ RID VisualServerRaster::fixed_material_get_texture(RID p_material,FixedMaterialP
-void VisualServerRaster::fixed_material_set_texcoord_mode(RID p_material,FixedMaterialParam p_parameter, FixedMaterialTexCoordMode p_mode) {
+void VisualServerRaster::fixed_material_set_texcoord_mode(RID p_material,FixedSpatialMaterialParam p_parameter, FixedSpatialMaterialTexCoordMode p_mode) {
VS_CHANGED;
rasterizer->fixed_material_set_texcoord_mode(p_material,p_parameter,p_mode);
}
-VS::FixedMaterialTexCoordMode VisualServerRaster::fixed_material_get_texcoord_mode(RID p_material,FixedMaterialParam p_parameter) const {
+VS::FixedSpatialMaterialTexCoordMode VisualServerRaster::fixed_material_get_texcoord_mode(RID p_material,FixedSpatialMaterialParam p_parameter) const {
return rasterizer->fixed_material_get_texcoord_mode(p_material,p_parameter);
}
@@ -331,14 +482,14 @@ Transform VisualServerRaster::fixed_material_get_uv_transform(RID p_material) co
return rasterizer->fixed_material_get_uv_transform(p_material);
}
-void VisualServerRaster::fixed_material_set_light_shader(RID p_material,FixedMaterialLightShader p_shader) {
+void VisualServerRaster::fixed_material_set_light_shader(RID p_material,FixedSpatialMaterialLightShader p_shader) {
VS_CHANGED;
rasterizer->fixed_material_set_light_shader(p_material,p_shader);
}
-VisualServerRaster::FixedMaterialLightShader VisualServerRaster::fixed_material_get_light_shader(RID p_material) const{
+VisualServerRaster::FixedSpatialMaterialLightShader VisualServerRaster::fixed_material_get_light_shader(RID p_material) const{
return rasterizer->fixed_material_get_light_shader(p_material);
}
@@ -677,13 +828,13 @@ Vector3 VisualServerRaster::particles_get_emission_base_velocity(RID p_particles
return rasterizer->particles_get_emission_base_velocity(p_particles);
}
-void VisualServerRaster::particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points) {
+void VisualServerRaster::particles_set_emission_points(RID p_particles, const PoolVector<Vector3>& p_points) {
VS_CHANGED;
rasterizer->particles_set_emission_points(p_particles,p_points);
}
-DVector<Vector3> VisualServerRaster::particles_get_emission_points(RID p_particles) const {
+PoolVector<Vector3> VisualServerRaster::particles_get_emission_points(RID p_particles) const {
return rasterizer->particles_get_emission_points(p_particles);
}
@@ -1137,7 +1288,7 @@ float VisualServerRaster::baked_light_get_lightmap_multiplier(RID p_baked_light)
}
-void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree){
+void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const PoolVector<uint8_t> p_octree){
VS_CHANGED;
BakedLight *baked_light = baked_light_owner.get(p_baked_light);
@@ -1146,7 +1297,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
if (p_octree.size()==0) {
if (baked_light->data.octree_texture.is_valid())
rasterizer->free(baked_light->data.octree_texture);
- baked_light->data.octree_texture=RID();
+ baked_light->data.octree_texture;
baked_light->octree_aabb=AABB();
baked_light->octree_tex_size=Size2();
} else {
@@ -1159,7 +1310,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
bool has_light_tex=false;
{
- DVector<uint8_t>::Read r=p_octree.read();
+ PoolVector<uint8_t>::Read r=p_octree.read();
tex_w = decode_uint32(&r[0]);
tex_h = decode_uint32(&r[4]);
print_line("TEX W: "+itos(tex_w)+" TEX H:"+itos(tex_h)+" LEN: "+itos(p_octree.size()));
@@ -1203,7 +1354,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
if (tex_w!=baked_light->octree_tex_size.x || tex_h!=baked_light->octree_tex_size.y) {
rasterizer->free(baked_light->data.octree_texture);
- baked_light->data.octree_texture=RID();
+ baked_light->data.octree_texture;
baked_light->octree_tex_size.x=0;
baked_light->octree_tex_size.y=0;
}
@@ -1212,7 +1363,7 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
if (baked_light->data.light_texture.is_valid()) {
if (!has_light_tex || light_tex_w!=baked_light->light_tex_size.x || light_tex_h!=baked_light->light_tex_size.y) {
rasterizer->free(baked_light->data.light_texture);
- baked_light->data.light_texture=RID();
+ baked_light->data.light_texture;
baked_light->light_tex_size.x=0;
baked_light->light_tex_size.y=0;
}
@@ -1220,20 +1371,20 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
if (!baked_light->data.octree_texture.is_valid()) {
baked_light->data.octree_texture=rasterizer->texture_create();
- rasterizer->texture_allocate(baked_light->data.octree_texture,tex_w,tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER);
+ rasterizer->texture_allocate(baked_light->data.octree_texture,tex_w,tex_h,Image::FORMAT_RGBA8,TEXTURE_FLAG_FILTER);
baked_light->octree_tex_size.x=tex_w;
baked_light->octree_tex_size.y=tex_h;
}
if (!baked_light->data.light_texture.is_valid() && has_light_tex) {
baked_light->data.light_texture=rasterizer->texture_create();
- rasterizer->texture_allocate(baked_light->data.light_texture,light_tex_w,light_tex_h,Image::FORMAT_RGBA,TEXTURE_FLAG_FILTER);
+ rasterizer->texture_allocate(baked_light->data.light_texture,light_tex_w,light_tex_h,Image::FORMAT_RGBA8,TEXTURE_FLAG_FILTER);
baked_light->light_tex_size.x=light_tex_w;
baked_light->light_tex_size.y=light_tex_h;
}
- Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_octree);
+ Image img(tex_w,tex_h,0,Image::FORMAT_RGBA8,p_octree);
rasterizer->texture_set_data(baked_light->data.octree_texture,img);
}
@@ -1244,22 +1395,22 @@ void VisualServerRaster::baked_light_set_octree(RID p_baked_light,const DVector<
}
-DVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) const{
+PoolVector<uint8_t> VisualServerRaster::baked_light_get_octree(RID p_baked_light) const{
BakedLight *baked_light = baked_light_owner.get(p_baked_light);
- ERR_FAIL_COND_V(!baked_light,DVector<uint8_t>());
+ ERR_FAIL_COND_V(!baked_light,PoolVector<uint8_t>());
if (rasterizer->is_texture(baked_light->data.octree_texture)) {
Image img = rasterizer->texture_get_data(baked_light->data.octree_texture);
return img.get_data();
} else {
- return DVector<uint8_t>();
+ return PoolVector<uint8_t>();
}
}
-void VisualServerRaster::baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light) {
+void VisualServerRaster::baked_light_set_light(RID p_baked_light,const PoolVector<uint8_t> p_light) {
VS_CHANGED;
BakedLight *baked_light = baked_light_owner.get(p_baked_light);
@@ -1276,30 +1427,30 @@ void VisualServerRaster::baked_light_set_light(RID p_baked_light,const DVector<u
print_line("w: "+itos(tex_w)+" h: "+itos(tex_h)+" lightsize: "+itos(p_light.size()));
- Image img(tex_w,tex_h,0,Image::FORMAT_RGBA,p_light);
+ Image img(tex_w,tex_h,0,Image::FORMAT_RGBA8,p_light);
rasterizer->texture_set_data(baked_light->data.light_texture,img);
}
-DVector<uint8_t> VisualServerRaster::baked_light_get_light(RID p_baked_light) const{
+PoolVector<uint8_t> VisualServerRaster::baked_light_get_light(RID p_baked_light) const{
BakedLight *baked_light = baked_light_owner.get(p_baked_light);
- ERR_FAIL_COND_V(!baked_light,DVector<uint8_t>());
+ ERR_FAIL_COND_V(!baked_light,PoolVector<uint8_t>());
if (rasterizer->is_texture(baked_light->data.light_texture)) {
Image img = rasterizer->texture_get_data(baked_light->data.light_texture);
return img.get_data();
} else {
- return DVector<uint8_t>();
+ return PoolVector<uint8_t>();
}
}
-void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const DVector<int> &p_sampler) {
+void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const PoolVector<int> &p_sampler) {
BakedLight *baked_light = baked_light_owner.get(p_baked_light);
ERR_FAIL_COND(!baked_light);
@@ -1310,10 +1461,10 @@ void VisualServerRaster::baked_light_set_sampler_octree(RID p_baked_light, const
}
-DVector<int> VisualServerRaster::baked_light_get_sampler_octree(RID p_baked_light) const {
+PoolVector<int> VisualServerRaster::baked_light_get_sampler_octree(RID p_baked_light) const {
BakedLight *baked_light = baked_light_owner.get(p_baked_light);
- ERR_FAIL_COND_V(!baked_light,DVector<int>());
+ ERR_FAIL_COND_V(!baked_light,PoolVector<int>());
return baked_light->sampler;
@@ -1611,8 +1762,8 @@ void VisualServerRaster::viewport_set_as_render_target(RID p_viewport,bool p_ena
if (!p_enable) {
rasterizer->free(viewport->render_target);
- viewport->render_target=RID();
- viewport->render_target_texture=RID();
+ viewport->render_target;
+ viewport->render_target_texture;
if (viewport->update_list.in_list())
viewport_update_list.remove(&viewport->update_list);
@@ -1811,7 +1962,7 @@ void VisualServerRaster::viewport_attach_camera(RID p_viewport,RID p_camera) {
// a camera
viewport->camera=p_camera;
} else {
- viewport->camera=RID();
+ viewport->camera;
}
}
@@ -1830,7 +1981,7 @@ void VisualServerRaster::viewport_set_scenario(RID p_viewport,RID p_scenario) {
// a camera
viewport->scenario=p_scenario;
} else {
- viewport->scenario=RID();
+ viewport->scenario;
}
}
@@ -2284,7 +2435,7 @@ void VisualServerRaster::instance_set_base(RID p_instance, RID p_base) {
instance->base_type=INSTANCE_NONE;
- instance->base_rid=RID();
+ instance->base_rid;
if (p_base.is_valid()) {
@@ -2786,7 +2937,7 @@ void VisualServerRaster::instance_geometry_set_flag(RID p_instance,InstanceFlags
Instance *instance = instance_owner.get( p_instance );
ERR_FAIL_COND( !instance );
-// ERR_FAIL_COND( ! ( (1<<instance->base_type) & INSTANCE_GEOMETRY_MASK) );
+ //ERR_FAIL_COND( ! ( (1<<instance->base_type) & INSTANCE_GEOMETRY_MASK) );
switch(p_flags) {
@@ -2838,7 +2989,7 @@ bool VisualServerRaster::instance_geometry_get_flag(RID p_instance,InstanceFlags
const Instance *instance = instance_owner.get( p_instance );
ERR_FAIL_COND_V( !instance, false );
-// ERR_FAIL_COND_V( ! ( (1<<instance->base_type) & INSTANCE_GEOMETRY_MASK), false );
+ //ERR_FAIL_COND_V( ! ( (1<<instance->base_type) & INSTANCE_GEOMETRY_MASK), false );
switch(p_flags) {
@@ -3003,7 +3154,7 @@ void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instanc
if (instance->sampled_light) {
instance->sampled_light->baked_light_sampler_info->owned_instances.erase(instance);
- instance->data.sampled_light=RID();
+ instance->data.sampled_light;
}
if(p_baked_light_sampler.is_valid()) {
@@ -3016,7 +3167,7 @@ void VisualServerRaster::instance_geometry_set_baked_light_sampler(RID p_instanc
instance->sampled_light=NULL;
}
- instance->data.sampled_light=RID();
+ instance->data.sampled_light;
}
@@ -3193,8 +3344,10 @@ void VisualServerRaster::_update_instance(Instance *p_instance) {
} else {
- // if (new_aabb==p_instance->data.transformed_aabb)
- // return;
+ /*
+ if (new_aabb==p_instance->data.transformed_aabb)
+ return;
+ */
p_instance->scenario->octree.move(p_instance->octree_id,new_aabb);
}
@@ -3432,7 +3585,7 @@ void VisualServerRaster::canvas_item_set_parent(RID p_item,RID p_parent) {
item_owner->child_items.erase(canvas_item);
}
- canvas_item->parent=RID();
+ canvas_item->parent;
}
@@ -4057,7 +4210,7 @@ void VisualServerRaster::canvas_light_attach_to_canvas(RID p_light,RID p_canvas)
}
if (!canvas_owner.owns(p_canvas))
- p_canvas=RID();
+ p_canvas;
clight->canvas=p_canvas;
if (clight->canvas.is_valid()) {
@@ -4184,7 +4337,7 @@ void VisualServerRaster::canvas_light_set_shadow_enabled(RID p_light, bool p_ena
clight->shadow_buffer=rasterizer->canvas_light_shadow_buffer_create(clight->shadow_buffer_size);
} else {
rasterizer->free(clight->shadow_buffer);
- clight->shadow_buffer=RID();
+ clight->shadow_buffer;
}
@@ -4246,7 +4399,7 @@ void VisualServerRaster::canvas_light_occluder_attach_to_canvas(RID p_occluder,R
}
if (!canvas_owner.owns(p_canvas))
- p_canvas=RID();
+ p_canvas;
occluder->canvas=p_canvas;
@@ -4279,12 +4432,12 @@ void VisualServerRaster::canvas_light_occluder_set_polygon(RID p_occluder,RID p_
}
occluder->polygon=p_polygon;
- occluder->polygon_buffer=RID();
+ occluder->polygon_buffer;
if (occluder->polygon.is_valid()) {
CanvasLightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.get(p_polygon);
if (!occluder_poly)
- occluder->polygon=RID();
+ occluder->polygon;
ERR_FAIL_COND(!occluder_poly);
occluder_poly->owners.insert(occluder);
occluder->polygon_buffer=occluder_poly->occluder;
@@ -4324,20 +4477,20 @@ RID VisualServerRaster::canvas_occluder_polygon_create() {
}
-void VisualServerRaster::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const DVector<Vector2>& p_shape, bool p_close){
+void VisualServerRaster::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const PoolVector<Vector2>& p_shape, bool p_close){
if (p_shape.size()<3) {
canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,p_shape);
return;
}
- DVector<Vector2> lines;
+ PoolVector<Vector2> lines;
int lc = p_shape.size()*2;
lines.resize(lc-(p_close?0:2));
{
- DVector<Vector2>::Write w = lines.write();
- DVector<Vector2>::Read r = p_shape.read();
+ PoolVector<Vector2>::Write w = lines.write();
+ PoolVector<Vector2>::Read r = p_shape.read();
int max=lc/2;
if (!p_close) {
@@ -4356,7 +4509,7 @@ void VisualServerRaster::canvas_occluder_polygon_set_shape(RID p_occluder_polygo
canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon,lines);
}
-void VisualServerRaster::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape) {
+void VisualServerRaster::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape) {
CanvasLightOccluderPolygon * occluder_poly = canvas_light_occluder_polygon_owner.get(p_occluder_polygon);
ERR_FAIL_COND(!occluder_poly);
@@ -4365,7 +4518,7 @@ void VisualServerRaster::canvas_occluder_polygon_set_shape_as_lines(RID p_occlud
int lc = p_shape.size();
occluder_poly->aabb=Rect2();
{
- DVector<Vector2>::Read r = p_shape.read();
+ PoolVector<Vector2>::Read r = p_shape.read();
for(int i=0;i<lc;i++) {
if (i==0)
occluder_poly->aabb.pos=r[i];
@@ -4514,7 +4667,7 @@ void VisualServerRaster::_free_attached_instances(RID p_rid,bool p_free_scenario
void VisualServerRaster::custom_shade_model_set_shader(int p_model, RID p_shader) {
VS_CHANGED;
-// rasterizer->custom_shade_model_set_shader(p_model,p_shader);
+ //rasterizer->custom_shade_model_set_shader(p_model,p_shader);
}
RID VisualServerRaster::custom_shade_model_get_shader(int p_model) const {
@@ -4558,7 +4711,7 @@ void VisualServerRaster::free( RID p_rid ) {
//detach skeletons
for (Set<Instance*>::Element *F=E->get().front();F;F=F->next()) {
- F->get()->data.skeleton=RID();
+ F->get()->data.skeleton;
}
skeleton_dependency_map.erase(E);
}
@@ -4604,8 +4757,10 @@ void VisualServerRaster::free( RID p_rid ) {
BakedLightSampler *baked_light_sampler = baked_light_sampler_owner.get(p_rid);
ERR_FAIL_COND(!baked_light_sampler);
- //if (baked_light->data.octree_texture.is_valid())
- // rasterizer->free(baked_light->data.octree_texture);
+ /*
+ if (baked_light->data.octree_texture.is_valid())
+ rasterizer->free(baked_light->data.octree_texture);
+ */
baked_light_sampler_owner.free(p_rid);
memdelete(baked_light_sampler);
@@ -4624,7 +4779,7 @@ void VisualServerRaster::free( RID p_rid ) {
Viewport *viewport = viewport_owner.get( p_rid );
ERR_FAIL_COND(!viewport);
-// Viewport *parent=NULL;
+ //Viewport *parent=NULL;
rasterizer->free(viewport->viewport_data);
if (viewport->render_target.is_valid()) {
@@ -4688,17 +4843,17 @@ void VisualServerRaster::free( RID p_rid ) {
for (int i=0;i<canvas->child_items.size();i++) {
- canvas->child_items[i].item->parent=RID();
+ canvas->child_items[i].item->parent;
}
for (Set<Rasterizer::CanvasLight*>::Element *E=canvas->lights.front();E;E=E->next()) {
- E->get()->canvas=RID();
+ E->get()->canvas;
}
for (Set<Rasterizer::CanvasLightOccluderInstance*>::Element *E=canvas->occluders.front();E;E=E->next()) {
- E->get()->canvas=RID();
+ E->get()->canvas;
}
canvas_owner.free( p_rid );
@@ -4726,7 +4881,7 @@ void VisualServerRaster::free( RID p_rid ) {
for (int i=0;i<canvas_item->child_items.size();i++) {
- canvas_item->child_items[i]->parent=RID();
+ canvas_item->child_items[i]->parent;
}
if (canvas_item->material) {
@@ -4798,7 +4953,7 @@ void VisualServerRaster::free( RID p_rid ) {
while(occluder_poly->owners.size()) {
- occluder_poly->owners.front()->get()->polygon=RID();
+ occluder_poly->owners.front()->get()->polygon;
occluder_poly->owners.erase( occluder_poly->owners.front() );
}
@@ -4963,7 +5118,7 @@ void VisualServerRaster::_light_instance_update_pssm_shadow(Instance *p_light,Sc
float distances[5];
float texsize=rasterizer->light_instance_get_shadow_size( p_light->light_info->instance );
-// float cull_min=p_cull_range.min;
+ //float cull_min=p_cull_range.min;
//float cull_max=p_cull_range.max;
@@ -6196,7 +6351,7 @@ void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instan
AABB sample_aabb= bl->data.transform.affine_inverse().xform(AABB(Vector3(-r,-r,-r)+p_sampled_light->data.transform.origin,Vector3(r*2,r*2,r*2)));
//ok got octree local AABB
- DVector<int>::Read rp = bl->baked_light_info->baked_light->sampler.read();
+ PoolVector<int>::Read rp = bl->baked_light_info->baked_light->sampler.read();
const int *rptr = rp.ptr();
int first = rptr[1];
@@ -6417,7 +6572,7 @@ void VisualServerRaster::_process_sampled_light(const Transform& p_camera,Instan
for(Set<Instance*>::Element *F=p_sampled_light->baked_light_sampler_info->owned_instances.front();F;F=F->next()) {
- F->get()->data.sampled_light=RID(); //do not use because nothing close
+ F->get()->data.sampled_light; //do not use because nothing close
}
}
@@ -6515,7 +6670,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
/* print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0));
print_line("OTO: "+itos(p_scenario->octree.get_octant_count()));
-// print_line("OTE: "+itos(p_scenario->octree.get_elem_count()));
+ //print_line("OTE: "+itos(p_scenario->octree.get_elem_count()));
print_line("OTP: "+itos(p_scenario->octree.get_pair_count()));
*/
@@ -6619,7 +6774,7 @@ void VisualServerRaster::_render_camera(Viewport *p_viewport,Camera *p_camera, S
if (light_cull_count<MAX_LIGHTS_CULLED) {
light_cull_result[light_cull_count++]=ins;
-// rasterizer->light_instance_set_active_hint(ins->light_info->instance);
+ //rasterizer->light_instance_set_active_hint(ins->light_info->instance);
{
//compute distance to camera using aabb support
Vector3 n = ins->data.transform.basis.xform_inv(cull_range.nearp.normal).normalized();
@@ -7142,7 +7297,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
ViewportRect desired_rect=p_viewport->rect;
ViewportRect old_rect = viewport_rect;
-// bool vpchanged=false;
+ //bool vpchanged=false;
// convert default expanding viewports to actual size
//if (desired_rect.x==0 && desired_rect.y==0 && desired_rect.width==0 && desired_rect.height==0) {
if (p_parent_w != 0 && p_parent_h != 0) {
@@ -7334,7 +7489,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
for (Map<Viewport::CanvasKey,Viewport::CanvasData*>::Element *E=canvas_map.front();E;E=E->next()) {
- // print_line("canvas "+itos(i)+" size: "+itos(I->get()->canvas->child_items.size()));
+ //print_line("canvas "+itos(i)+" size: "+itos(I->get()->canvas->child_items.size()));
//print_line("GT "+p_viewport->global_transform+". CT: "+E->get()->transform);
Matrix32 xform = p_viewport->global_transform * E->get()->transform;
@@ -7366,7 +7521,7 @@ void VisualServerRaster::_draw_viewport(Viewport *p_viewport,int p_ofs_x, int p_
}
-// rasterizer->canvas_debug_viewport_shadows(lights_with_shadow);
+ //rasterizer->canvas_debug_viewport_shadows(lights_with_shadow);
}
//capture
@@ -7534,10 +7689,10 @@ void VisualServerRaster::_draw_cursors_and_margins() {
ERR_CONTINUE( !tex );
if (cursors[i].region.has_no_area()) {
Point2 size(texture_get_width(tex), texture_get_height(tex));
- rasterizer->canvas_draw_rect(Rect2(cursors[i].pos, size), 0, Rect2(), tex, Color(1, 1, 1, 1));
+ rasterizer->canvas_draw_rect(Rect2(cursors[i].pos-cursors[i].center, size), 0, Rect2(), tex, Color(1, 1, 1, 1));
} else {
Point2 size = cursors[i].region.size;
- rasterizer->canvas_draw_rect(Rect2(cursors[i].pos, size), Rasterizer::CANVAS_RECT_REGION, cursors[i].region, tex, Color(1, 1, 1, 1));
+ rasterizer->canvas_draw_rect(Rect2(cursors[i].pos-cursors[i].center, size), Rasterizer::CANVAS_RECT_REGION, cursors[i].region, tex, Color(1, 1, 1, 1));
}
};
@@ -7579,8 +7734,10 @@ void VisualServerRaster::sync() {
}
void VisualServerRaster::draw() {
- //if (changes)
- // print_line("changes: "+itos(changes));
+ /*
+ if (changes)
+ print_line("changes: "+itos(changes));
+ */
changes=0;
shadows_enabled=GLOBAL_DEF("render/shadows_enabled",true);
room_cull_enabled = GLOBAL_DEF("render/room_cull_enabled",true);
@@ -7679,7 +7836,7 @@ void VisualServerRaster::init() {
Image img;
img.create(default_mouse_cursor_xpm);
- //img.convert(Image::FORMAT_RGB);
+ //img.convert(Image::FORMAT_RGB8);
default_cursor_texture = texture_create_from_image(img, 0);
aabb_random_points.resize( GLOBAL_DEF("render/aabb_random_points",16) );
@@ -7766,3 +7923,4 @@ VisualServerRaster::VisualServerRaster(Rasterizer *p_rasterizer) {
VisualServerRaster::~VisualServerRaster()
{
}
+#endif
diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h
index 496820f4a8..7d547e1862 100644
--- a/servers/visual/visual_server_raster.h
+++ b/servers/visual/visual_server_raster.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -34,12 +34,17 @@
#include "servers/visual/rasterizer.h"
#include "allocators.h"
#include "octree.h"
-
+#include "visual_server_global.h"
+#include "visual_server_viewport.h"
+#include "visual_server_canvas.h"
+#include "visual_server_scene.h"
/**
@author Juan Linietsky <reduzio@gmail.com>
*/
+
+
class VisualServerRaster : public VisualServer {
@@ -57,6 +62,12 @@ class VisualServerRaster : public VisualServer {
};
+ int changes;
+ bool draw_extra_frame;
+ RID test_cube;
+
+
+ #if 0
struct Room {
bool occlude_exterior;
@@ -92,8 +103,8 @@ class VisualServerRaster : public VisualServer {
struct BakedLight {
Rasterizer::BakedLightData data;
- DVector<int> sampler;
- AABB octree_aabb;
+ PoolVector<int> sampler;
+ Rect3 octree_aabb;
Size2i octree_tex_size;
Size2i light_tex_size;
@@ -131,7 +142,7 @@ class VisualServerRaster : public VisualServer {
Transform transform;
- Camera() {
+ Camera() {
visible_layers=0xFFFFFFFF;
fov=60;
@@ -140,8 +151,8 @@ class VisualServerRaster : public VisualServer {
size=1.0;
vaspect=false;
- }
- };
+ }
+ };
struct Instance;
@@ -166,8 +177,8 @@ class VisualServerRaster : public VisualServer {
RID base_rid;
- AABB aabb;
- AABB transformed_aabb;
+ Rect3 aabb;
+ Rect3 transformed_aabb;
uint32_t object_ID;
bool visible;
bool visible_in_all_rooms;
@@ -374,97 +385,6 @@ class VisualServerRaster : public VisualServer {
mutable RID_Owner<Rasterizer::CanvasItemMaterial> canvas_item_material_owner;
- struct CanvasItem : public Rasterizer::CanvasItem {
-
-
- RID parent; // canvas it belongs to
- List<CanvasItem*>::Element *E;
- RID viewport;
- int z;
- bool z_relative;
- bool sort_y;
- float opacity;
- float self_opacity;
- bool use_parent_material;
-
-
- Vector<CanvasItem*> child_items;
-
-
- CanvasItem() {
- E=NULL;
- z=0;
- opacity=1;
- self_opacity=1;
- sort_y=false;
- use_parent_material=false;
- z_relative=true;
- }
- };
-
-
- struct CanvasItemPtrSort {
-
- _FORCE_INLINE_ bool operator()(const CanvasItem* p_left,const CanvasItem* p_right) const {
-
- return p_left->xform.elements[2].y < p_right->xform.elements[2].y;
- }
- };
-
- struct CanvasLightOccluder;
-
- struct CanvasLightOccluderPolygon {
-
- bool active;
- Rect2 aabb;
- CanvasOccluderPolygonCullMode cull_mode;
- RID occluder;
- Set<Rasterizer::CanvasLightOccluderInstance*> owners;
-
- CanvasLightOccluderPolygon() { active=false; cull_mode=CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; }
- };
-
-
- RID_Owner<CanvasLightOccluderPolygon> canvas_light_occluder_polygon_owner;
-
- RID_Owner<Rasterizer::CanvasLightOccluderInstance> canvas_light_occluder_owner;
-
- struct CanvasLight;
-
- struct Canvas {
-
- Set<RID> viewports;
- struct ChildItem {
-
- Point2 mirror;
- CanvasItem *item;
- };
-
- Set<Rasterizer::CanvasLight*> lights;
- Set<Rasterizer::CanvasLightOccluderInstance*> occluders;
-
- Vector<ChildItem> child_items;
- Color modulate;
-
- int find_item(CanvasItem *p_item) {
- for(int i=0;i<child_items.size();i++) {
- if (child_items[i].item==p_item)
- return i;
- }
- return -1;
- }
- void erase_item(CanvasItem *p_item) {
- int idx=find_item(p_item);
- if (idx>=0)
- child_items.remove(idx);
- }
-
- Canvas() { modulate=Color(1,1,1,1); }
-
- };
-
-
- RID_Owner<Rasterizer::CanvasLight> canvas_light_owner;
struct Viewport {
@@ -508,11 +428,11 @@ class VisualServerRaster : public VisualServer {
struct CanvasData {
Canvas *canvas;
- Matrix32 transform;
+ Transform2D transform;
int layer;
};
- Matrix32 global_transform;
+ Transform2D global_transform;
Map<RID,CanvasData> canvas_map;
@@ -531,7 +451,7 @@ class VisualServerRaster : public VisualServer {
float min,max;
float z_near,z_far;
- void add_aabb(const AABB& p_aabb) {
+ void add_aabb(const Rect3& p_aabb) {
}
@@ -634,9 +554,9 @@ class VisualServerRaster : public VisualServer {
void _render_no_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario);
void _render_camera(Viewport *p_viewport,Camera *p_camera, Scenario *p_scenario);
static void _render_canvas_item_viewport(VisualServer* p_self,void *p_vp,const Rect2& p_rect);
- void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights);
- void _render_canvas_item(CanvasItem *p_canvas_item, const Matrix32& p_transform, const Rect2& p_clip_rect, float p_opacity, int p_z, Rasterizer::CanvasItem **z_list, Rasterizer::CanvasItem **z_last_list, CanvasItem *p_canvas_clip, CanvasItem *p_material_owner);
- void _render_canvas(Canvas *p_canvas, const Matrix32 &p_transform, Rasterizer::CanvasLight *p_lights, Rasterizer::CanvasLight *p_masked_lights);
+ void _render_canvas_item_tree(CanvasItem *p_canvas_item, const Transform2D& p_transform, const Rect2& p_clip_rect, const Color &p_modulate, Rasterizer::CanvasLight *p_lights);
+ void _render_canvas_item(CanvasItem *p_canvas_item, const Transform2D& p_transform, const Rect2& p_clip_rect, float p_opacity, int p_z, Rasterizer::CanvasItem **z_list, Rasterizer::CanvasItem **z_last_list, CanvasItem *p_canvas_clip, CanvasItem *p_material_owner);
+ void _render_canvas(Canvas *p_canvas, const Transform2D &p_transform, Rasterizer::CanvasLight *p_lights, Rasterizer::CanvasLight *p_masked_lights);
void _light_mask_canvas_items(int p_z,Rasterizer::CanvasItem *p_canvas_item,Rasterizer::CanvasLight *p_masked_lights);
Vector<Vector3> _camera_generate_endpoints(Instance *p_light,Camera *p_camera,float p_range_min, float p_range_max);
@@ -658,635 +578,595 @@ class VisualServerRaster : public VisualServer {
Rasterizer *rasterizer;
-public:
- virtual RID texture_create();
- virtual void texture_allocate(RID p_texture,int p_width, int p_height,Image::Format p_format,uint32_t p_flags=TEXTURE_FLAGS_DEFAULT);
- virtual void texture_set_data(RID p_texture,const Image& p_image,CubeMapSide p_cube_side=CUBEMAP_LEFT);
- virtual Image texture_get_data(RID p_texture,CubeMapSide p_cube_side=CUBEMAP_LEFT) const;
- virtual void texture_set_flags(RID p_texture,uint32_t p_flags) ;
- virtual uint32_t texture_get_flags(RID p_texture) const;
- virtual Image::Format texture_get_format(RID p_texture) const;
- virtual uint32_t texture_get_width(RID p_texture) const;
- virtual uint32_t texture_get_height(RID p_texture) const;
- virtual void texture_set_size_override(RID p_texture,int p_width, int p_height);
- virtual bool texture_can_stream(RID p_texture) const;
- virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const;
-
- virtual void texture_set_path(RID p_texture,const String& p_path);
- virtual String texture_get_path(RID p_texture) const;
-
- virtual void texture_debug_usage(List<TextureInfo> *r_info);
-
- virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable);
-
-
- /* SHADER API */
-
- virtual RID shader_create(ShaderMode p_mode=SHADER_MATERIAL);
-
- virtual void shader_set_mode(RID p_shader,ShaderMode p_mode);
- virtual ShaderMode shader_get_mode(RID p_shader) const;
-
- virtual void shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light,int p_vertex_ofs=0,int p_fragment_ofs=0,int p_light_ofs=0);
- virtual String shader_get_vertex_code(RID p_shader) const;
- virtual String shader_get_fragment_code(RID p_shader) const;
- virtual String shader_get_light_code(RID p_shader) const;
-
- virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const;
-
- virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture);
- virtual RID shader_get_default_texture_param(RID p_shader, const StringName& p_name) const;
-
-
- /* COMMON MATERIAL API */
+#endif
- virtual RID material_create();
+public:
- virtual void material_set_shader(RID p_shader_material, RID p_shader);
- virtual RID material_get_shader(RID p_shader_material) const;
+#define DISPLAY_CHANGED changes++;
- virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value);
- virtual Variant material_get_param(RID p_material, const StringName& p_param) const;
+#define BIND0R(m_r,m_name) m_r m_name() { return BINDBASE->m_name(); }
+#define BIND1R(m_r,m_name,m_type1) m_r m_name(m_type1 arg1) { return BINDBASE->m_name(arg1); }
+#define BIND1RC(m_r,m_name,m_type1) m_r m_name(m_type1 arg1) const { return BINDBASE->m_name(arg1); }
+#define BIND2RC(m_r,m_name,m_type1,m_type2) m_r m_name(m_type1 arg1,m_type2 arg2) const { return BINDBASE->m_name(arg1,arg2); }
+#define BIND3RC(m_r,m_name,m_type1,m_type2,m_type3) m_r m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3) const { return BINDBASE->m_name(arg1,arg2,arg3); }
+#define BIND4RC(m_r,m_name,m_type1,m_type2,m_type3,m_type4) m_r m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4) const { return BINDBASE->m_name(arg1,arg2,arg3,arg4); }
- virtual void material_set_flag(RID p_material, MaterialFlag p_flag,bool p_enabled);
- virtual bool material_get_flag(RID p_material,MaterialFlag p_flag) const;
+#define BIND1(m_name,m_type1) void m_name(m_type1 arg1) { DISPLAY_CHANGED BINDBASE->m_name(arg1); }
+#define BIND2(m_name,m_type1,m_type2) void m_name(m_type1 arg1,m_type2 arg2) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2); }
+#define BIND2C(m_name,m_type1,m_type2) void m_name(m_type1 arg1,m_type2 arg2) const { BINDBASE->m_name(arg1,arg2); }
+#define BIND3(m_name,m_type1,m_type2,m_type3) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3); }
+#define BIND4(m_name,m_type1,m_type2,m_type3,m_type4) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4); }
+#define BIND5(m_name,m_type1,m_type2,m_type3,m_type4,m_type5) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5); }
+#define BIND6(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6); }
+#define BIND7(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6,m_type7) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6,m_type7 arg7) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7); }
+#define BIND8(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6,m_type7,m_type8) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6,m_type7 arg7,m_type8 arg8) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8); }
+#define BIND9(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6,m_type7,m_type8,m_type9) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6,m_type7 arg7,m_type8 arg8,m_type9 arg9) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9); }
+#define BIND10(m_name,m_type1,m_type2,m_type3,m_type4,m_type5,m_type6,m_type7,m_type8,m_type9,m_type10) void m_name(m_type1 arg1,m_type2 arg2,m_type3 arg3,m_type4 arg4,m_type5 arg5,m_type6 arg6,m_type7 arg7,m_type8 arg8,m_type9 arg9,m_type10 arg10) { DISPLAY_CHANGED BINDBASE->m_name(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10); }
- virtual void material_set_depth_draw_mode(RID p_material, MaterialDepthDrawMode p_mode);
- virtual MaterialDepthDrawMode material_get_depth_draw_mode(RID p_material) const;
+//from now on, calls forwarded to this singleton
+#define BINDBASE VSG::storage
- virtual void material_set_blend_mode(RID p_material,MaterialBlendMode p_mode);
- virtual MaterialBlendMode material_get_blend_mode(RID p_material) const;
+ /* TEXTURE API */
- virtual void material_set_line_width(RID p_material,float p_line_width);
- virtual float material_get_line_width(RID p_material) const;
- /* FIXED MATERIAL */
+ BIND0R(RID,texture_create)
+ BIND5(texture_allocate,RID,int,int,Image::Format,uint32_t)
+ BIND3(texture_set_data,RID,const Image&,CubeMapSide)
+ BIND2RC(Image,texture_get_data,RID,CubeMapSide)
+ BIND2(texture_set_flags,RID,uint32_t)
+ BIND1RC(uint32_t,texture_get_flags,RID)
+ BIND1RC(Image::Format,texture_get_format,RID)
+ BIND1RC(uint32_t,texture_get_width,RID)
+ BIND1RC(uint32_t,texture_get_height,RID)
+ BIND3(texture_set_size_override,RID,int,int)
+ BIND2RC(RID,texture_create_radiance_cubemap,RID,int)
+ BIND3(texture_set_detect_3d_callback,RID,TextureDetectCallback,void*)
+ BIND3(texture_set_detect_srgb_callback,RID,TextureDetectCallback,void*)
- virtual RID fixed_material_create();
+ BIND2(texture_set_path,RID,const String&)
+ BIND1RC(String,texture_get_path,RID)
+ BIND1(texture_set_shrink_all_x2_on_set_data,bool)
+ BIND1(texture_debug_usage,List<TextureInfo>*)
- virtual void fixed_material_set_flag(RID p_material, FixedMaterialFlags p_flag, bool p_enabled);
- virtual bool fixed_material_get_flag(RID p_material, FixedMaterialFlags p_flag) const;
+ BIND1(textures_keep_original,bool)
- virtual void fixed_material_set_param(RID p_material, FixedMaterialParam p_parameter, const Variant& p_value);
- virtual Variant fixed_material_get_param(RID p_material,FixedMaterialParam p_parameter) const;
+ /* SKYBOX API */
- virtual void fixed_material_set_texture(RID p_material,FixedMaterialParam p_parameter, RID p_texture);
- virtual RID fixed_material_get_texture(RID p_material,FixedMaterialParam p_parameter) const;
+ BIND0R(RID,skybox_create)
+ BIND3(skybox_set_texture,RID,RID,int)
- virtual void fixed_material_set_texcoord_mode(RID p_material,FixedMaterialParam p_parameter, FixedMaterialTexCoordMode p_mode);
- virtual FixedMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,FixedMaterialParam p_parameter) const;
+ /* SHADER API */
+ BIND1R(RID,shader_create,ShaderMode)
- virtual void fixed_material_set_uv_transform(RID p_material,const Transform& p_transform);
- virtual Transform fixed_material_get_uv_transform(RID p_material) const;
- virtual void fixed_material_set_light_shader(RID p_material,FixedMaterialLightShader p_shader);
- virtual FixedMaterialLightShader fixed_material_get_light_shader(RID p_material) const;
+ BIND2(shader_set_mode,RID,ShaderMode)
+ BIND1RC(ShaderMode,shader_get_mode,RID)
- virtual void fixed_material_set_point_size(RID p_material,float p_size);
- virtual float fixed_material_get_point_size(RID p_material) const;
+ BIND2(shader_set_code,RID,const String&)
+ BIND1RC(String,shader_get_code,RID)
- /* SURFACE API */
- virtual RID mesh_create();
+ BIND2C(shader_get_param_list,RID, List<PropertyInfo> *)
- virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount);
- virtual int mesh_get_morph_target_count(RID p_mesh) const;
+ BIND3(shader_set_default_texture_param,RID,const StringName&,RID)
+ BIND2RC(RID,shader_get_default_texture_param,RID,const StringName&)
- virtual void mesh_set_morph_target_mode(RID p_mesh,MorphTargetMode p_mode);
- virtual MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const;
- virtual void mesh_add_custom_surface(RID p_mesh,const Variant& p_dat); //this is used by each platform in a different way
+ /* COMMON MATERIAL API */
- virtual void mesh_add_surface(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),bool p_alpha_sort=false);
- virtual Array mesh_get_surface_arrays(RID p_mesh,int p_surface) const;
- virtual Array mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const;
+ BIND0R(RID,material_create)
- virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned=false);
- virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const;
+ BIND2(material_set_shader,RID,RID)
+ BIND1RC(RID,material_get_shader,RID)
- virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const;
- virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const;
- virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const;
- virtual PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const;
+ BIND3(material_set_param,RID, const StringName&, const Variant& )
+ BIND2RC(Variant,material_get_param,RID, const StringName& )
- virtual void mesh_remove_surface(RID p_mesh,int p_index);
- virtual int mesh_get_surface_count(RID p_mesh) const;
+ BIND2(material_set_line_width,RID, float )
- virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb);
- virtual AABB mesh_get_custom_aabb(RID p_mesh) const;
- virtual void mesh_clear(RID p_mesh);
- /* MULTIMESH API */
+ /* MESH API */
- virtual RID multimesh_create();
- virtual void multimesh_set_instance_count(RID p_multimesh,int p_count);
- virtual int multimesh_get_instance_count(RID p_multimesh) const;
+ BIND0R(RID,mesh_create)
- virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh);
- virtual void multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb);
- virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform);
- virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color);
+ BIND10(mesh_add_surface,RID,uint32_t,PrimitiveType,const PoolVector<uint8_t>&,int ,const PoolVector<uint8_t>& ,int ,const Rect3&,const Vector<PoolVector<uint8_t> >&,const Vector<Rect3>& )
- virtual RID multimesh_get_mesh(RID p_multimesh) const;
- virtual AABB multimesh_get_aabb(RID p_multimesh,const AABB& p_aabb) const;
- virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const;
- virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const;
+ BIND2(mesh_set_blend_shape_count,RID,int)
+ BIND1RC(int,mesh_get_blend_shape_count,RID)
- virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible);
- virtual int multimesh_get_visible_instances(RID p_multimesh) const;
- /* IMMEDIATE API */
+ BIND2(mesh_set_blend_shape_mode,RID,BlendShapeMode)
+ BIND1RC(BlendShapeMode, mesh_get_blend_shape_mode,RID )
- virtual RID immediate_create();
- virtual void immediate_begin(RID p_immediate,PrimitiveType p_rimitive,RID p_texture=RID());
- virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex);
- virtual void immediate_normal(RID p_immediate,const Vector3& p_normal);
- virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent);
- virtual void immediate_color(RID p_immediate,const Color& p_color);
- virtual void immediate_uv(RID p_immediate, const Vector2& p_uv);
- virtual void immediate_uv2(RID p_immediate,const Vector2& tex_uv);
- virtual void immediate_end(RID p_immediate);
- virtual void immediate_clear(RID p_immediate);
- virtual void immediate_set_material(RID p_immediate,RID p_material);
- virtual RID immediate_get_material(RID p_immediate) const;
+ BIND3(mesh_surface_set_material,RID, int , RID )
+ BIND2RC(RID,mesh_surface_get_material,RID, int )
+ BIND2RC(int,mesh_surface_get_array_len,RID,int)
+ BIND2RC(int,mesh_surface_get_array_index_len,RID,int)
- /* PARTICLES API */
+ BIND2RC(PoolVector<uint8_t>,mesh_surface_get_array,RID,int)
+ BIND2RC(PoolVector<uint8_t>,mesh_surface_get_index_array,RID, int)
- virtual RID particles_create();
+ BIND2RC(uint32_t,mesh_surface_get_format,RID,int)
+ BIND2RC(PrimitiveType,mesh_surface_get_primitive_type,RID,int)
- virtual void particles_set_amount(RID p_particles, int p_amount);
- virtual int particles_get_amount(RID p_particles) const;
+ BIND2RC(Rect3,mesh_surface_get_aabb,RID,int)
+ BIND2RC(Vector<PoolVector<uint8_t> >,mesh_surface_get_blend_shapes,RID,int)
+ BIND2RC(Vector<Rect3>,mesh_surface_get_skeleton_aabb,RID,int)
- virtual void particles_set_emitting(RID p_particles, bool p_emitting);
- virtual bool particles_is_emitting(RID p_particles) const;
+ BIND2(mesh_remove_surface,RID,int)
+ BIND1RC(int,mesh_get_surface_count,RID)
- virtual void particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility);
- virtual AABB particles_get_visibility_aabb(RID p_particles) const;
+ BIND2(mesh_set_custom_aabb,RID,const Rect3&)
+ BIND1RC(Rect3,mesh_get_custom_aabb,RID)
- virtual void particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents);
- virtual Vector3 particles_get_emission_half_extents(RID p_particles) const;
+ BIND1(mesh_clear,RID)
- virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity);
- virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const;
-
- virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points);
- virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const;
-
- virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal);
- virtual Vector3 particles_get_gravity_normal(RID p_particles) const;
+ /* MULTIMESH API */
- virtual void particles_set_variable(RID p_particles, ParticleVariable p_variable,float p_value);
- virtual float particles_get_variable(RID p_particles, ParticleVariable p_variable) const;
- virtual void particles_set_randomness(RID p_particles, ParticleVariable p_variable,float p_randomness);
- virtual float particles_get_randomness(RID p_particles, ParticleVariable p_variable) const;
+ BIND0R(RID,multimesh_create)
- virtual void particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos);
- virtual float particles_get_color_phase_pos(RID p_particles, int p_phase) const;
+ BIND4(multimesh_allocate,RID,int,MultimeshTransformFormat,MultimeshColorFormat)
+ BIND1RC(int,multimesh_get_instance_count,RID)
- virtual void particles_set_color_phases(RID p_particles, int p_phases);
- virtual int particles_get_color_phases(RID p_particles) const;
+ BIND2(multimesh_set_mesh,RID,RID)
+ BIND3(multimesh_instance_set_transform,RID,int,const Transform&)
+ BIND3(multimesh_instance_set_transform_2d,RID,int,const Transform2D& )
+ BIND3(multimesh_instance_set_color,RID,int,const Color&)
- virtual void particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color);
- virtual Color particles_get_color_phase_color(RID p_particles, int p_phase) const;
+ BIND1RC(RID,multimesh_get_mesh,RID)
+ BIND1RC(Rect3,multimesh_get_aabb,RID)
- virtual void particles_set_attractors(RID p_particles, int p_attractors);
- virtual int particles_get_attractors(RID p_particles) const;
+ BIND2RC(Transform,multimesh_instance_get_transform,RID,int )
+ BIND2RC(Transform2D,multimesh_instance_get_transform_2d,RID,int)
+ BIND2RC(Color,multimesh_instance_get_color,RID,int)
- virtual void particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos);
- virtual Vector3 particles_get_attractor_pos(RID p_particles,int p_attractor) const;
+ BIND2(multimesh_set_visible_instances,RID,int)
+ BIND1RC(int,multimesh_get_visible_instances,RID)
- virtual void particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force);
- virtual float particles_get_attractor_strength(RID p_particles,int p_attractor) const;
- virtual void particles_set_material(RID p_particles, RID p_material,bool p_owned=false);
- virtual RID particles_get_material(RID p_particles) const;
+ /* IMMEDIATE API */
- virtual void particles_set_height_from_velocity(RID p_particles, bool p_enable);
- virtual bool particles_has_height_from_velocity(RID p_particles) const;
+ BIND0R(RID,immediate_create)
+ BIND3(immediate_begin,RID,PrimitiveType,RID)
+ BIND2(immediate_vertex,RID,const Vector3&)
+ BIND2(immediate_normal,RID,const Vector3&)
+ BIND2(immediate_tangent,RID,const Plane&)
+ BIND2(immediate_color,RID,const Color&)
+ BIND2(immediate_uv,RID,const Vector2& )
+ BIND2(immediate_uv2,RID,const Vector2&)
+ BIND1(immediate_end,RID)
+ BIND1(immediate_clear,RID)
+ BIND2(immediate_set_material,RID ,RID )
+ BIND1RC(RID,immediate_get_material,RID)
- virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable);
- virtual bool particles_is_using_local_coordinates(RID p_particles) const;
+ /* SKELETON API */
+ BIND0R(RID,skeleton_create)
+ BIND3(skeleton_allocate,RID,int,bool)
+ BIND1RC(int,skeleton_get_bone_count,RID)
+ BIND3(skeleton_bone_set_transform,RID,int,const Transform&)
+ BIND2RC(Transform,skeleton_bone_get_transform,RID,int)
+ BIND3(skeleton_bone_set_transform_2d,RID,int, const Transform2D& )
+ BIND2RC(Transform2D,skeleton_bone_get_transform_2d,RID,int)
/* Light API */
- virtual RID light_create(LightType p_type);
- virtual LightType light_get_type(RID p_light) const;
-
- virtual void light_set_color(RID p_light,LightColor p_type, const Color& p_color);
- virtual Color light_get_color(RID p_light,LightColor p_type) const;
-
+ BIND1R(RID,light_create,LightType)
- virtual void light_set_shadow(RID p_light,bool p_enabled);
- virtual bool light_has_shadow(RID p_light) const;
+ BIND2(light_set_color,RID,const Color&)
+ BIND3(light_set_param,RID ,LightParam ,float )
+ BIND2(light_set_shadow,RID ,bool )
+ BIND2(light_set_shadow_color,RID ,const Color& )
+ BIND2(light_set_projector,RID,RID )
+ BIND2(light_set_negative,RID,bool )
+ BIND2(light_set_cull_mask,RID ,uint32_t )
- virtual void light_set_volumetric(RID p_light,bool p_enabled);
- virtual bool light_is_volumetric(RID p_light) const;
+ BIND2(light_omni_set_shadow_mode,RID,LightOmniShadowMode)
+ BIND2(light_omni_set_shadow_detail,RID,LightOmniShadowDetail)
- virtual void light_set_projector(RID p_light,RID p_texture);
- virtual RID light_get_projector(RID p_light) const;
+ BIND2(light_directional_set_shadow_mode,RID,LightDirectionalShadowMode)
+ BIND2(light_directional_set_blend_splits,RID,bool)
- virtual void light_set_param(RID p_light, LightParam p_var, float p_value);
- virtual float light_get_param(RID p_light, LightParam p_var) const;
+ /* PROBE API */
- virtual void light_set_operator(RID p_light,LightOp p_op);
- virtual LightOp light_get_operator(RID p_light) const;
+ BIND0R(RID,reflection_probe_create)
- virtual void light_omni_set_shadow_mode(RID p_light,LightOmniShadowMode p_mode);
- virtual LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) const;
-
- virtual void light_directional_set_shadow_mode(RID p_light,LightDirectionalShadowMode p_mode);
- virtual LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) const;
- virtual void light_directional_set_shadow_param(RID p_light,LightDirectionalShadowParam p_param, float p_value);
- virtual float light_directional_get_shadow_param(RID p_light,LightDirectionalShadowParam p_param) const;
-
-
- /* SKELETON API */
-
- virtual RID skeleton_create();
- virtual void skeleton_resize(RID p_skeleton,int p_bones);
- virtual int skeleton_get_bone_count(RID p_skeleton) const;
- virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform);
- virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone);
+ BIND2(reflection_probe_set_update_mode,RID, ReflectionProbeUpdateMode )
+ BIND2(reflection_probe_set_intensity,RID, float )
+ BIND2(reflection_probe_set_interior_ambient,RID, const Color& )
+ BIND2(reflection_probe_set_interior_ambient_energy,RID, float )
+ BIND2(reflection_probe_set_interior_ambient_probe_contribution,RID, float )
+ BIND2(reflection_probe_set_max_distance,RID, float )
+ BIND2(reflection_probe_set_extents,RID, const Vector3& )
+ BIND2(reflection_probe_set_origin_offset,RID, const Vector3& )
+ BIND2(reflection_probe_set_as_interior,RID, bool )
+ BIND2(reflection_probe_set_enable_box_projection,RID, bool )
+ BIND2(reflection_probe_set_enable_shadows,RID, bool )
+ BIND2(reflection_probe_set_cull_mask,RID, uint32_t )
/* ROOM API */
- virtual RID room_create();
- virtual void room_set_bounds(RID p_room, const BSP_Tree& p_bounds);
- virtual BSP_Tree room_get_bounds(RID p_room) const;
+ BIND0R(RID,room_create)
+ BIND4(room_add_bounds,RID, const PoolVector<Vector2>& ,float ,const Transform& )
+ BIND1(room_clear_bounds,RID)
/* PORTAL API */
- virtual RID portal_create();
- virtual void portal_set_shape(RID p_portal, const Vector<Point2>& p_shape);
- virtual Vector<Point2> portal_get_shape(RID p_portal) const;
- virtual void portal_set_enabled(RID p_portal, bool p_enabled);
- virtual bool portal_is_enabled(RID p_portal) const;
- virtual void portal_set_disable_distance(RID p_portal, float p_distance);
- virtual float portal_get_disable_distance(RID p_portal) const;
- virtual void portal_set_disabled_color(RID p_portal, const Color& p_color);
- virtual Color portal_get_disabled_color(RID p_portal) const;
- virtual void portal_set_connect_range(RID p_portal, float p_range);
- virtual float portal_get_connect_range(RID p_portal) const;
-
- /* BAKED LIGHT */
+ // portals are only (x/y) points, forming a convex shape, which its clockwise
+ // order points outside. (z is 0);
- virtual RID baked_light_create();
+ BIND0R(RID,portal_create)
+ BIND2(portal_set_shape,RID , const Vector<Point2>& )
+ BIND2(portal_set_enabled,RID , bool )
+ BIND2(portal_set_disable_distance,RID , float )
+ BIND2(portal_set_disabled_color,RID , const Color& )
- virtual void baked_light_set_mode(RID p_baked_light,BakedLightMode p_mode);
- virtual BakedLightMode baked_light_get_mode(RID p_baked_light) const;
+ /* BAKED LIGHT API */
- virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree);
- virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const;
+ BIND0R(RID, gi_probe_create)
- virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light);
- virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const;
+ BIND2(gi_probe_set_bounds,RID,const Rect3&)
+ BIND1RC(Rect3,gi_probe_get_bounds,RID)
- virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler);
- virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const;
+ BIND2(gi_probe_set_cell_size,RID,float)
+ BIND1RC(float,gi_probe_get_cell_size,RID)
- virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier);
- virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const;
+ BIND2(gi_probe_set_to_cell_xform,RID,const Transform&)
+ BIND1RC(Transform,gi_probe_get_to_cell_xform,RID)
- virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id);
- virtual void baked_light_clear_lightmaps(RID p_baked_light);
+ BIND2(gi_probe_set_dynamic_range,RID,int)
+ BIND1RC(int,gi_probe_get_dynamic_range,RID)
- virtual void baked_light_set_realtime_color_enabled(RID p_baked_light, const bool p_enabled);
- virtual bool baked_light_get_realtime_color_enabled(RID p_baked_light) const;
+ BIND2(gi_probe_set_energy,RID,float)
+ BIND1RC(float,gi_probe_get_energy,RID)
- virtual void baked_light_set_realtime_color(RID p_baked_light, const Color& p_color);
- virtual Color baked_light_get_realtime_color(RID p_baked_light) const;
+ BIND2(gi_probe_set_bias,RID,float)
+ BIND1RC(float,gi_probe_get_bias,RID)
- virtual void baked_light_set_realtime_energy(RID p_baked_light, const float p_energy);
- virtual float baked_light_get_realtime_energy(RID p_baked_light) const;
+ BIND2(gi_probe_set_propagation,RID,float)
+ BIND1RC(float,gi_probe_get_propagation,RID)
- /* BAKED LIGHT SAMPLER */
+ BIND2(gi_probe_set_interior,RID,bool)
+ BIND1RC(bool,gi_probe_is_interior,RID)
- virtual RID baked_light_sampler_create();
+ BIND2(gi_probe_set_compress,RID,bool)
+ BIND1RC(bool,gi_probe_is_compressed,RID)
- virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value);
- virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const;
+ BIND2(gi_probe_set_dynamic_data,RID,const PoolVector<int>& )
+ BIND1RC( PoolVector<int>,gi_probe_get_dynamic_data,RID)
- virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution);
- virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const;
+ /* PARTICLES */
- /* CAMERA API */
+ BIND0R(RID, particles_create)
- virtual RID camera_create();
- virtual void camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far);
- virtual void camera_set_orthogonal(RID p_camera,float p_size, float p_z_near, float p_z_far);
- virtual void camera_set_transform(RID p_camera,const Transform& p_transform);
+ BIND2(particles_set_emitting,RID,bool)
+ BIND2(particles_set_amount,RID,int )
+ BIND2(particles_set_lifetime,RID,float )
+ BIND2(particles_set_pre_process_time,RID,float )
+ BIND2(particles_set_explosiveness_ratio,RID,float )
+ BIND2(particles_set_randomness_ratio,RID,float )
+ BIND2(particles_set_custom_aabb,RID,const Rect3& )
+ BIND2(particles_set_gravity,RID,const Vector3& )
+ BIND2(particles_set_use_local_coordinates,RID,bool )
+ BIND2(particles_set_process_material,RID,RID )
- virtual void camera_set_visible_layers(RID p_camera,uint32_t p_layers);
- virtual uint32_t camera_get_visible_layers(RID p_camera) const;
+ BIND2(particles_set_emission_shape,RID,VS::ParticlesEmissionShape )
+ BIND2(particles_set_emission_sphere_radius,RID,float )
+ BIND2(particles_set_emission_box_extents,RID,const Vector3& )
+ BIND2(particles_set_emission_points,RID,const PoolVector<Vector3>& )
- virtual void camera_set_environment(RID p_camera,RID p_env);
- virtual RID camera_get_environment(RID p_camera) const;
- virtual void camera_set_use_vertical_aspect(RID p_camera,bool p_enable);
- virtual bool camera_is_using_vertical_aspect(RID p_camera,bool p_enable) const;
+ BIND2(particles_set_draw_order,RID,VS::ParticlesDrawOrder )
- /* VIEWPORT API */
+ BIND2(particles_set_draw_passes,RID,int )
+ BIND3(particles_set_draw_pass_material,RID,int , RID )
+ BIND3(particles_set_draw_pass_mesh,RID,int , RID )
- virtual RID viewport_create();
+ BIND1R(Rect3,particles_get_current_aabb,RID);
- virtual void viewport_attach_to_screen(RID p_viewport,int p_screen=0);
- virtual void viewport_detach(RID p_viewport);
- virtual void viewport_set_as_render_target(RID p_viewport,bool p_enable);
- virtual void viewport_set_render_target_update_mode(RID p_viewport,RenderTargetUpdateMode p_mode);
- virtual RenderTargetUpdateMode viewport_get_render_target_update_mode(RID p_viewport) const;
- virtual RID viewport_get_render_target_texture(RID p_viewport) const;
- virtual void viewport_set_render_target_vflip(RID p_viewport,bool p_enable);
- virtual bool viewport_get_render_target_vflip(RID p_viewport) const;
- virtual void viewport_set_render_target_clear_on_new_frame(RID p_viewport,bool p_enable);
- virtual bool viewport_get_render_target_clear_on_new_frame(RID p_viewport) const;
- virtual void viewport_render_target_clear(RID p_viewport);
- virtual void viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect);
+#undef BINDBASE
+//from now on, calls forwarded to this singleton
+#define BINDBASE VSG::scene
+ /* CAMERA API */
- virtual void viewport_queue_screen_capture(RID p_viewport);
- virtual Image viewport_get_screen_capture(RID p_viewport) const;
- virtual void viewport_set_rect(RID p_viewport,const ViewportRect& p_rect);
- virtual ViewportRect viewport_get_rect(RID p_viewport) const;
+ BIND0R(RID, camera_create)
+ BIND4(camera_set_perspective,RID,float, float , float )
+ BIND4(camera_set_orthogonal,RID,float , float , float )
+ BIND2(camera_set_transform,RID,const Transform&)
+ BIND2(camera_set_cull_mask,RID,uint32_t )
+ BIND2(camera_set_environment,RID ,RID )
+ BIND2(camera_set_use_vertical_aspect,RID,bool)
- virtual void viewport_set_hide_scenario(RID p_viewport,bool p_hide);
- virtual void viewport_set_hide_canvas(RID p_viewport,bool p_hide);
- virtual void viewport_set_disable_environment(RID p_viewport,bool p_disable);
- virtual void viewport_attach_camera(RID p_viewport,RID p_camera);
- virtual void viewport_set_scenario(RID p_viewport,RID p_scenario);
+#undef BINDBASE
+//from now on, calls forwarded to this singleton
+#define BINDBASE VSG::viewport
- virtual RID viewport_get_attached_camera(RID p_viewport) const;
- virtual RID viewport_get_scenario(RID p_viewport) const;
- virtual void viewport_attach_canvas(RID p_viewport,RID p_canvas);
- virtual void viewport_remove_canvas(RID p_viewport,RID p_canvas);
- virtual void viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Matrix32& p_offset);
- virtual Matrix32 viewport_get_canvas_transform(RID p_viewport,RID p_canvas) const;
- virtual void viewport_set_global_canvas_transform(RID p_viewport,const Matrix32& p_transform);
- virtual Matrix32 viewport_get_global_canvas_transform(RID p_viewport) const;
- virtual void viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer);
- virtual void viewport_set_transparent_background(RID p_viewport,bool p_enabled);
- virtual bool viewport_has_transparent_background(RID p_viewport) const;
+ /* VIEWPORT TARGET API */
+ BIND0R(RID,viewport_create)
- /* ENVIRONMENT API */
+ BIND3(viewport_set_size,RID,int ,int )
- virtual RID environment_create();
+ BIND2(viewport_set_active,RID ,bool )
+ BIND2(viewport_set_parent_viewport,RID,RID)
- virtual void environment_set_background(RID p_env,EnvironmentBG p_bg);
- virtual EnvironmentBG environment_get_background(RID p_env) const;
+ BIND2(viewport_set_clear_mode,RID,ViewportClearMode )
- virtual void environment_set_background_param(RID p_env,EnvironmentBGParam p_param, const Variant& p_value);
- virtual Variant environment_get_background_param(RID p_env,EnvironmentBGParam p_param) const;
+ BIND3(viewport_attach_to_screen,RID ,const Rect2& ,int )
+ BIND1(viewport_detach,RID)
- virtual void environment_set_enable_fx(RID p_env,EnvironmentFx p_effect,bool p_enabled);
- virtual bool environment_is_fx_enabled(RID p_env,EnvironmentFx p_effect) const;
+ BIND2(viewport_set_update_mode,RID,ViewportUpdateMode )
+ BIND2(viewport_set_vflip,RID,bool)
- virtual void environment_fx_set_param(RID p_env,EnvironmentFxParam p_effect,const Variant& p_param);
- virtual Variant environment_fx_get_param(RID p_env,EnvironmentFxParam p_effect) const;
+ BIND1RC(RID,viewport_get_texture,RID )
+ BIND2(viewport_set_hide_scenario,RID,bool )
+ BIND2(viewport_set_hide_canvas,RID,bool )
+ BIND2(viewport_set_disable_environment,RID,bool )
+ BIND2(viewport_set_disable_3d,RID,bool )
- /* SCENARIO API */
+ BIND2(viewport_attach_camera,RID,RID )
+ BIND2(viewport_set_scenario,RID,RID )
+ BIND2(viewport_attach_canvas,RID,RID )
- virtual RID scenario_create();
+ BIND2(viewport_remove_canvas,RID,RID )
+ BIND3(viewport_set_canvas_transform,RID ,RID ,const Transform2D& )
+ BIND2(viewport_set_transparent_background,RID ,bool )
- virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode);
- virtual void scenario_set_environment(RID p_scenario, RID p_environment);
- virtual RID scenario_get_environment(RID p_scenario, RID p_environment) const;
- virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
+ BIND2(viewport_set_global_canvas_transform,RID,const Transform2D& )
+ BIND3(viewport_set_canvas_layer,RID ,RID ,int )
+ BIND2(viewport_set_shadow_atlas_size,RID ,int )
+ BIND3(viewport_set_shadow_atlas_quadrant_subdivision,RID ,int, int )
+ BIND2(viewport_set_msaa,RID ,ViewportMSAA )
+ BIND2(viewport_set_hdr,RID ,bool )
+ /* ENVIRONMENT API */
- /* INSTANCING API */
-
- virtual RID instance_create();
-
- virtual void instance_set_base(RID p_instance, RID p_base);
- virtual RID instance_get_base(RID p_instance) const;
+#undef BINDBASE
+//from now on, calls forwarded to this singleton
+#define BINDBASE VSG::scene_render
- virtual void instance_set_scenario(RID p_instance, RID p_scenario);
- virtual RID instance_get_scenario(RID p_instance) const;
+ BIND0R(RID,environment_create)
- virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask);
- virtual uint32_t instance_get_layer_mask(RID p_instance) const;
+ BIND2(environment_set_background,RID ,EnvironmentBG )
+ BIND2(environment_set_skybox,RID,RID )
+ BIND2(environment_set_skybox_scale,RID,float)
+ BIND2(environment_set_bg_color,RID,const Color& )
+ BIND2(environment_set_bg_energy,RID,float )
+ BIND2(environment_set_canvas_max_layer,RID,int )
+ BIND4(environment_set_ambient_light,RID,const Color& ,float,float )
+ BIND8(environment_set_ssr,RID,bool,int,float,float,float,bool,bool )
+ BIND10(environment_set_ssao,RID ,bool , float , float , float,float,float , float ,const Color &,bool )
- virtual AABB instance_get_base_aabb(RID p_instance) const;
- virtual void instance_attach_object_instance_ID(RID p_instance,uint32_t p_ID);
- virtual uint32_t instance_get_object_instance_ID(RID p_instance) const;
- virtual void instance_attach_skeleton(RID p_instance,RID p_skeleton);
- virtual RID instance_get_skeleton(RID p_instance) const;
+ BIND6(environment_set_dof_blur_near,RID,bool ,float,float,float,EnvironmentDOFBlurQuality)
+ BIND6(environment_set_dof_blur_far,RID,bool ,float,float,float,EnvironmentDOFBlurQuality)
+ BIND10(environment_set_glow,RID,bool ,int ,float ,float ,float ,EnvironmentGlowBlendMode,float,float,bool )
+ BIND5(environment_set_fog,RID,bool ,float ,float ,RID )
- virtual void instance_set_morph_target_weight(RID p_instance,int p_shape, float p_weight);
- virtual float instance_get_morph_target_weight(RID p_instance,int p_shape) const;
+ BIND9(environment_set_tonemap,RID,EnvironmentToneMapper, float ,float ,bool, float ,float ,float,float )
- virtual void instance_set_surface_material(RID p_instance,int p_surface, RID p_material);
+ BIND6(environment_set_adjustment,RID,bool ,float ,float ,float ,RID )
- virtual void instance_set_transform(RID p_instance, const Transform& p_transform);
- virtual Transform instance_get_transform(RID p_instance) const;
+ /* SCENARIO API */
- virtual void instance_set_exterior( RID p_instance, bool p_enabled );
- virtual bool instance_is_exterior( RID p_instance) const;
- virtual void instance_set_room( RID p_instance, RID p_room );
- virtual RID instance_get_room( RID p_instance ) const ;
+#undef BINDBASE
+#define BINDBASE VSG::scene
- virtual void instance_set_extra_visibility_margin( RID p_instance, real_t p_margin );
- virtual real_t instance_get_extra_visibility_margin( RID p_instance ) const;
+ BIND0R(RID,scenario_create)
- virtual Vector<RID> instances_cull_aabb(const AABB& p_aabb, RID p_scenario=RID()) const;
- virtual Vector<RID> instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario=RID()) const;
- virtual Vector<RID> instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario=RID()) const;
+ BIND2(scenario_set_debug,RID,ScenarioDebugMode )
+ BIND2(scenario_set_environment,RID, RID )
+ BIND3(scenario_set_reflection_atlas_size,RID, int,int )
+ BIND2(scenario_set_fallback_environment,RID, RID )
- virtual void instance_geometry_set_flag(RID p_instance,InstanceFlags p_flags,bool p_enabled);
- virtual bool instance_geometry_get_flag(RID p_instance,InstanceFlags p_flags) const;
- virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting);
- virtual VS::ShadowCastingSetting instance_geometry_get_cast_shadows_setting(RID p_instance) const;
+ /* INSTANCING API */
+ // from can be mesh, light, area and portal so far.
+ BIND0R(RID,instance_create)
- virtual void instance_geometry_set_material_override(RID p_instance, RID p_material);
- virtual RID instance_geometry_get_material_override(RID p_instance) const;
+ BIND2(instance_set_base,RID, RID ) // from can be mesh, light, poly, area and portal so far.
+ BIND2(instance_set_scenario,RID, RID ) // from can be mesh, light, poly, area and portal so far.
+ BIND2(instance_set_layer_mask,RID, uint32_t )
+ BIND2(instance_set_transform,RID, const Transform& )
+ BIND2(instance_attach_object_instance_ID,RID,ObjectID )
+ BIND3(instance_set_blend_shape_weight,RID,int , float )
+ BIND3(instance_set_surface_material,RID,int , RID )
+ BIND2(instance_set_visible,RID ,bool)
- virtual void instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max);
- virtual float instance_geometry_get_draw_range_max(RID p_instance) const;
- virtual float instance_geometry_get_draw_range_min(RID p_instance) const;
- virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light);
- virtual RID instance_geometry_get_baked_light(RID p_instance) const;
+ BIND2(instance_attach_skeleton,RID,RID )
+ BIND2(instance_set_exterior, RID, bool )
+ BIND2(instance_set_room, RID, RID )
- virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler);
- virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const;
+ BIND2(instance_set_extra_visibility_margin, RID, real_t )
- virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id);
- virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const;
+ // don't use these in a game!
+ BIND2RC(Vector<ObjectID>,instances_cull_aabb,const Rect3& , RID)
+ BIND3RC(Vector<ObjectID>,instances_cull_ray,const Vector3& , const Vector3& , RID )
+ BIND2RC(Vector<ObjectID>,instances_cull_convex,const Vector<Plane>& , RID)
- virtual void instance_light_set_enabled(RID p_instance,bool p_enabled);
- virtual bool instance_light_is_enabled(RID p_instance) const;
- /* CANVAS (2D) */
+ BIND3(instance_geometry_set_flag,RID,InstanceFlags ,bool )
+ BIND2(instance_geometry_set_cast_shadows_setting,RID, ShadowCastingSetting )
+ BIND2(instance_geometry_set_material_override,RID, RID )
- virtual RID canvas_create();
- virtual void canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring);
- virtual Point2 canvas_get_item_mirroring(RID p_canvas,RID p_item) const;
- virtual void canvas_set_modulate(RID p_canvas,const Color& p_color);
+ BIND5(instance_geometry_set_draw_range,RID,float ,float ,float ,float )
+ BIND2(instance_geometry_set_as_instance_lod,RID,RID )
- virtual RID canvas_item_create();
+#undef BINDBASE
+//from now on, calls forwarded to this singleton
+#define BINDBASE VSG::canvas
- virtual void canvas_item_set_parent(RID p_item,RID p_parent_item);
- virtual RID canvas_item_get_parent(RID p_canvas_item) const;
+ /* CANVAS (2D) */
- virtual void canvas_item_set_visible(RID p_item,bool p_visible);
- virtual bool canvas_item_is_visible(RID p_item) const;
+ BIND0R(RID,canvas_create)
+ BIND3(canvas_set_item_mirroring,RID ,RID ,const Point2& )
+ BIND2(canvas_set_modulate,RID,const Color&)
- virtual void canvas_item_set_blend_mode(RID p_canvas_item,MaterialBlendMode p_blend);
- virtual void canvas_item_set_light_mask(RID p_canvas_item,int p_mask);
+ BIND0R(RID,canvas_item_create)
+ BIND2(canvas_item_set_parent,RID ,RID)
+ BIND2(canvas_item_set_visible,RID,bool )
+ BIND2(canvas_item_set_light_mask,RID,int )
- //virtual void canvas_item_set_rect(RID p_item, const Rect2& p_rect);
- virtual void canvas_item_set_transform(RID p_item, const Matrix32& p_transform);
- virtual void canvas_item_set_clip(RID p_item, bool p_clip);
- virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable);
- virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2());
- virtual void canvas_item_set_opacity(RID p_item, float p_opacity);
- virtual float canvas_item_get_opacity(RID p_item, float p_opacity) const;
- virtual void canvas_item_set_on_top(RID p_item, bool p_on_top);
- virtual bool canvas_item_is_on_top(RID p_item) const;
+ BIND2(canvas_item_set_transform,RID, const Transform2D& )
+ BIND2(canvas_item_set_clip,RID, bool )
+ BIND2(canvas_item_set_distance_field_mode,RID, bool )
+ BIND3(canvas_item_set_custom_rect,RID, bool ,const Rect2& )
+ BIND2(canvas_item_set_modulate,RID, const Color& )
+ BIND2(canvas_item_set_self_modulate,RID, const Color& )
- virtual void canvas_item_set_self_opacity(RID p_item, float p_self_opacity);
- virtual float canvas_item_get_self_opacity(RID p_item, float p_self_opacity) const;
+ BIND2(canvas_item_set_draw_behind_parent,RID, bool )
- virtual void canvas_item_attach_viewport(RID p_item, RID p_viewport);
- virtual void canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to, const Color& p_color, float p_width=1.0, bool p_antialiased=false);
- virtual void canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color);
- virtual void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color);
- virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false);
- virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false);
- virtual void canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1));
- virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width=1.0);
- virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID());
- virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int>& p_indices, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID(), int p_count=-1);
- virtual void canvas_item_add_triangle_array_ptr(RID p_item, int p_count, const int* p_indices, const Point2* p_points, const Color* p_colors,const Point2* p_uvs=NULL, RID p_texture=RID());
- virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform);
- virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend);
- virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore);
- virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable);
- virtual void canvas_item_set_z(RID p_item, int p_z);
- virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable);
- virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect);
+ BIND6(canvas_item_add_line,RID, const Point2& , const Point2& ,const Color& ,float ,bool )
+ BIND3(canvas_item_add_rect,RID, const Rect2& , const Color& )
+ BIND4(canvas_item_add_circle,RID, const Point2& , float ,const Color& )
+ BIND6(canvas_item_add_texture_rect,RID, const Rect2& , RID ,bool ,const Color& ,bool )
+ BIND6(canvas_item_add_texture_rect_region,RID, const Rect2& , RID ,const Rect2& ,const Color& ,bool )
+ BIND10(canvas_item_add_nine_patch,RID, const Rect2& , const Rect2& , RID ,const Vector2& , const Vector2& ,NinePatchAxisMode , NinePatchAxisMode,bool ,const Color& )
+ BIND6(canvas_item_add_primitive,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ,float )
+ BIND5(canvas_item_add_polygon,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID )
+ BIND7(canvas_item_add_triangle_array,RID, const Vector<int>& , const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID , int)
+ BIND3(canvas_item_add_mesh,RID, const RID& ,RID )
+ BIND3(canvas_item_add_multimesh,RID, RID ,RID )
+ BIND2(canvas_item_add_set_transform,RID,const Transform2D& )
+ BIND2(canvas_item_add_clip_ignore,RID, bool )
+ BIND2(canvas_item_set_sort_children_by_y,RID, bool )
+ BIND2(canvas_item_set_z,RID, int )
+ BIND2(canvas_item_set_z_as_relative_to_parent,RID, bool )
+ BIND3(canvas_item_set_copy_to_backbuffer,RID, bool ,const Rect2& )
- virtual void canvas_item_set_material(RID p_item, RID p_material);
- virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable);
+ BIND1(canvas_item_clear,RID )
+ BIND2(canvas_item_set_draw_index,RID,int)
- virtual RID canvas_light_create();
- virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas);
- virtual void canvas_light_set_enabled(RID p_light, bool p_enabled);
- virtual void canvas_light_set_transform(RID p_light, const Matrix32& p_transform);
- virtual void canvas_light_set_scale(RID p_light, float p_scale);
- virtual void canvas_light_set_texture(RID p_light, RID p_texture);
- virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset);
- virtual void canvas_light_set_color(RID p_light, const Color& p_color);
- virtual void canvas_light_set_height(RID p_light, float p_height);
- virtual void canvas_light_set_energy(RID p_light, float p_energy);
- virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z);
- virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer);
- virtual void canvas_light_set_item_mask(RID p_light, int p_mask);
- virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask);
+ BIND2(canvas_item_set_material,RID, RID )
- virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode);
- virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled);
- virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size);
- virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier);
- virtual void canvas_light_set_shadow_color(RID p_light, const Color& p_color);
+ BIND2(canvas_item_set_use_parent_material,RID, bool )
+ BIND0R(RID,canvas_light_create)
+ BIND2(canvas_light_attach_to_canvas,RID,RID )
+ BIND2(canvas_light_set_enabled,RID, bool )
+ BIND2(canvas_light_set_scale,RID, float )
+ BIND2(canvas_light_set_transform,RID, const Transform2D& )
+ BIND2(canvas_light_set_texture,RID, RID )
+ BIND2(canvas_light_set_texture_offset,RID, const Vector2& )
+ BIND2(canvas_light_set_color,RID, const Color& )
+ BIND2(canvas_light_set_height,RID, float )
+ BIND2(canvas_light_set_energy,RID, float )
+ BIND3(canvas_light_set_z_range,RID, int ,int )
+ BIND3(canvas_light_set_layer_range,RID, int ,int )
+ BIND2(canvas_light_set_item_cull_mask,RID, int )
+ BIND2(canvas_light_set_item_shadow_cull_mask,RID, int )
- virtual RID canvas_light_occluder_create();
- virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas);
- virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled);
- virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon);
- virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform);
- virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask);
+ BIND2(canvas_light_set_mode,RID, CanvasLightMode )
+ BIND2(canvas_light_set_shadow_enabled,RID, bool )
+ BIND2(canvas_light_set_shadow_buffer_size,RID, int )
+ BIND2(canvas_light_set_shadow_gradient_length,RID, float )
+ BIND2(canvas_light_set_shadow_filter,RID, CanvasLightShadowFilter )
+ BIND2(canvas_light_set_shadow_color,RID, const Color& )
- virtual RID canvas_occluder_polygon_create();
- virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_close);
- virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape);
- virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode);
+ BIND0R(RID,canvas_light_occluder_create)
+ BIND2(canvas_light_occluder_attach_to_canvas,RID,RID )
+ BIND2(canvas_light_occluder_set_enabled,RID,bool )
+ BIND2(canvas_light_occluder_set_polygon,RID,RID )
+ BIND2(canvas_light_occluder_set_transform,RID,const Transform2D& )
+ BIND2(canvas_light_occluder_set_light_mask,RID,int )
- virtual void canvas_item_clear(RID p_item);
- virtual void canvas_item_raise(RID p_item);
- /* CANVAS ITEM MATERIAL */
+ BIND0R(RID,canvas_occluder_polygon_create)
+ BIND3(canvas_occluder_polygon_set_shape,RID,const PoolVector<Vector2>& ,bool)
+ BIND2(canvas_occluder_polygon_set_shape_as_lines,RID ,const PoolVector<Vector2>&)
- virtual RID canvas_item_material_create();
- virtual void canvas_item_material_set_shader(RID p_material, RID p_shader);
- virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value);
- virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const;
- virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode);
+ BIND2(canvas_occluder_polygon_set_cull_mode,RID,CanvasOccluderPolygonCullMode)
/* CURSOR */
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0); // radians
- virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset, int p_cursor=0, const Rect2 &p_region=Rect2());
+ virtual void cursor_set_texture(RID p_texture, const Point2 &p_center_offset = Point2(0, 0), int p_cursor=0, const Rect2 &p_region=Rect2());
virtual void cursor_set_visible(bool p_visible, int p_cursor = 0);
virtual void cursor_set_pos(const Point2& p_pos, int p_cursor = 0);
/* BLACK BARS */
+
virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom);
virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom);
- /* FREE */
- virtual void free( RID p_rid );
-
- /* CUSTOM SHADE MODEL */
+ /* FREE */
- virtual void custom_shade_model_set_shader(int p_model, RID p_shader);
- virtual RID custom_shade_model_get_shader(int p_model) const;
- virtual void custom_shade_model_set_name(int p_model, const String& p_name);
- virtual String custom_shade_model_get_name(int p_model) const;
- virtual void custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info);
- virtual void custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const;
+ virtual void free( RID p_rid ); ///< free RIDs associated with the visual server
/* EVENT QUEUING */
virtual void draw();
virtual void sync();
-
+ virtual bool has_changed() const;
virtual void init();
virtual void finish();
- virtual bool has_changed() const;
+ /* STATUS INFORMATION */
- /* RENDER INFO */
virtual int get_render_info(RenderInfo p_info);
- virtual bool has_feature(Features p_feature) const;
- RID get_test_cube();
+ virtual RID get_test_cube();
+
- virtual void set_boot_image(const Image& p_image, const Color& p_color, bool p_scale);
+ /* TESTING */
+
+ virtual void set_boot_image(const Image& p_image, const Color& p_color,bool p_scale);
virtual void set_default_clear_color(const Color& p_color);
- VisualServerRaster(Rasterizer *p_rasterizer);
+ virtual bool has_feature(Features p_feature) const;
+
+ virtual bool has_os_feature(const String& p_feature) const;
+
+
+ VisualServerRaster();
~VisualServerRaster();
+#undef DISPLAY_CHANGED
+
+#undef BIND0R
+#undef BIND1RC
+#undef BIND2RC
+#undef BIND3RC
+#undef BIND4RC
+
+#undef BIND1
+#undef BIND2
+#undef BIND3
+#undef BIND4
+#undef BIND5
+#undef BIND6
+#undef BIND7
+#undef BIND8
+#undef BIND9
+#undef BIND10
+
};
#endif
diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp
new file mode 100644
index 0000000000..6f7b2e3aed
--- /dev/null
+++ b/servers/visual/visual_server_scene.cpp
@@ -0,0 +1,3629 @@
+#include "visual_server_scene.h"
+#include "visual_server_global.h"
+#include "os/os.h"
+/* CAMERA API */
+
+
+
+
+
+RID VisualServerScene::camera_create() {
+
+ Camera * camera = memnew( Camera );
+ return camera_owner.make_rid( camera );
+
+}
+
+void VisualServerScene::camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far) {
+
+ Camera *camera = camera_owner.get( p_camera );
+ ERR_FAIL_COND(!camera);
+ camera->type=Camera::PERSPECTIVE;
+ camera->fov=p_fovy_degrees;
+ camera->znear=p_z_near;
+ camera->zfar=p_z_far;
+
+}
+
+void VisualServerScene::camera_set_orthogonal(RID p_camera,float p_size, float p_z_near, float p_z_far) {
+
+ Camera *camera = camera_owner.get( p_camera );
+ ERR_FAIL_COND(!camera);
+ camera->type=Camera::ORTHOGONAL;
+ camera->size=p_size;
+ camera->znear=p_z_near;
+ camera->zfar=p_z_far;
+}
+
+void VisualServerScene::camera_set_transform(RID p_camera,const Transform& p_transform) {
+
+ Camera *camera = camera_owner.get( p_camera );
+ ERR_FAIL_COND(!camera);
+ camera->transform=p_transform.orthonormalized();
+
+
+}
+
+void VisualServerScene::camera_set_cull_mask(RID p_camera,uint32_t p_layers) {
+
+
+ Camera *camera = camera_owner.get( p_camera );
+ ERR_FAIL_COND(!camera);
+
+ camera->visible_layers=p_layers;
+
+}
+
+void VisualServerScene::camera_set_environment(RID p_camera,RID p_env) {
+
+ Camera *camera = camera_owner.get( p_camera );
+ ERR_FAIL_COND(!camera);
+ camera->env=p_env;
+
+}
+
+
+void VisualServerScene::camera_set_use_vertical_aspect(RID p_camera,bool p_enable) {
+
+ Camera *camera = camera_owner.get( p_camera );
+ ERR_FAIL_COND(!camera);
+ camera->vaspect=p_enable;
+
+}
+
+
+/* SCENARIO API */
+
+
+
+void* VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance *p_A,int, OctreeElementID, Instance *p_B,int) {
+
+ //VisualServerScene *self = (VisualServerScene*)p_self;
+ Instance *A = p_A;
+ Instance *B = p_B;
+
+ //instance indices are designed so greater always contains lesser
+ if (A->base_type > B->base_type) {
+ SWAP(A,B); //lesser always first
+ }
+
+ if (B->base_type==VS::INSTANCE_LIGHT && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
+
+ InstanceLightData * light = static_cast<InstanceLightData*>(B->base_data);
+ InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data);
+
+
+ InstanceLightData::PairInfo pinfo;
+ pinfo.geometry=A;
+ pinfo.L = geom->lighting.push_back(B);
+
+ List<InstanceLightData::PairInfo>::Element *E = light->geometries.push_back(pinfo);
+
+ if (geom->can_cast_shadows) {
+
+ light->shadow_dirty=true;
+ }
+ geom->lighting_dirty=true;
+
+ return E; //this element should make freeing faster
+ } else if (B->base_type==VS::INSTANCE_REFLECTION_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
+
+ InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(B->base_data);
+ InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data);
+
+
+ InstanceReflectionProbeData::PairInfo pinfo;
+ pinfo.geometry=A;
+ pinfo.L = geom->reflection_probes.push_back(B);
+
+ List<InstanceReflectionProbeData::PairInfo>::Element *E = reflection_probe->geometries.push_back(pinfo);
+
+ geom->reflection_dirty=true;
+
+ return E; //this element should make freeing faster
+ } else if (B->base_type==VS::INSTANCE_GI_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
+
+ InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(B->base_data);
+ InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data);
+
+
+ InstanceGIProbeData::PairInfo pinfo;
+ pinfo.geometry=A;
+ pinfo.L = geom->gi_probes.push_back(B);
+
+ List<InstanceGIProbeData::PairInfo>::Element *E = gi_probe->geometries.push_back(pinfo);
+
+ geom->gi_probes_dirty=true;
+
+ return E; //this element should make freeing faster
+
+ } else if (B->base_type==VS::INSTANCE_GI_PROBE && A->base_type==VS::INSTANCE_LIGHT) {
+
+ InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(B->base_data);
+ InstanceLightData * light = static_cast<InstanceLightData*>(A->base_data);
+
+ return gi_probe->lights.insert(A);
+ }
+
+
+
+#if 0
+ if (A->base_type==INSTANCE_PORTAL) {
+
+ ERR_FAIL_COND_V( B->base_type!=INSTANCE_PORTAL,NULL );
+
+ A->portal_info->candidate_set.insert(B);
+ B->portal_info->candidate_set.insert(A);
+
+ self->_portal_attempt_connect(A);
+ //attempt to conncet portal A (will go through B anyway)
+ //this is a little hackish, but works fine in practice
+
+ } else if (A->base_type==INSTANCE_GI_PROBE || B->base_type==INSTANCE_GI_PROBE) {
+
+ if (B->base_type==INSTANCE_GI_PROBE) {
+ SWAP(A,B);
+ }
+
+ ERR_FAIL_COND_V(B->base_type!=INSTANCE_GI_PROBE_SAMPLER,NULL);
+ B->gi_probe_sampler_info->gi_probes.insert(A);
+
+ } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) {
+
+ if (B->base_type==INSTANCE_ROOM)
+ SWAP(A,B);
+
+ ERR_FAIL_COND_V(! ((1<<B->base_type)&INSTANCE_GEOMETRY_MASK ),NULL);
+
+ B->auto_rooms.insert(A);
+ A->room_info->owned_autoroom_geometry.insert(B);
+
+ self->_instance_validate_autorooms(B);
+
+
+ } else {
+
+ if (B->base_type==INSTANCE_LIGHT) {
+
+ SWAP(A,B);
+ } else if (A->base_type!=INSTANCE_LIGHT) {
+ return NULL;
+ }
+
+
+ A->light_info->affected.insert(B);
+ B->lights.insert(A);
+ B->light_cache_dirty=true;
+
+
+ }
+#endif
+
+ return NULL;
+
+}
+void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance *p_A,int, OctreeElementID, Instance *p_B,int,void* udata) {
+
+ //VisualServerScene *self = (VisualServerScene*)p_self;
+ Instance *A = p_A;
+ Instance *B = p_B;
+
+ //instance indices are designed so greater always contains lesser
+ if (A->base_type > B->base_type) {
+ SWAP(A,B); //lesser always first
+ }
+
+
+
+ if (B->base_type==VS::INSTANCE_LIGHT && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
+
+ InstanceLightData * light = static_cast<InstanceLightData*>(B->base_data);
+ InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data);
+
+ List<InstanceLightData::PairInfo>::Element *E = reinterpret_cast<List<InstanceLightData::PairInfo>::Element*>(udata);
+
+ geom->lighting.erase(E->get().L);
+ light->geometries.erase(E);
+
+ if (geom->can_cast_shadows) {
+ light->shadow_dirty=true;
+ }
+ geom->lighting_dirty=true;
+
+
+ } else if (B->base_type==VS::INSTANCE_REFLECTION_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
+
+ InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(B->base_data);
+ InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data);
+
+ List<InstanceReflectionProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceReflectionProbeData::PairInfo>::Element*>(udata);
+
+ geom->reflection_probes.erase(E->get().L);
+ reflection_probe->geometries.erase(E);
+
+ geom->reflection_dirty=true;
+
+ } else if (B->base_type==VS::INSTANCE_GI_PROBE && (1<<A->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
+
+ InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(B->base_data);
+ InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(A->base_data);
+
+ List<InstanceGIProbeData::PairInfo>::Element *E = reinterpret_cast<List<InstanceGIProbeData::PairInfo>::Element*>(udata);
+
+ geom->gi_probes.erase(E->get().L);
+ gi_probe->geometries.erase(E);
+
+ geom->gi_probes_dirty=true;
+
+
+ } else if (B->base_type==VS::INSTANCE_GI_PROBE && A->base_type==VS::INSTANCE_LIGHT) {
+
+ InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(B->base_data);
+ InstanceLightData * light = static_cast<InstanceLightData*>(A->base_data);
+
+
+ Set<Instance*>::Element *E = reinterpret_cast<Set<Instance*>::Element*>(udata);
+
+ gi_probe->lights.erase(E);
+ }
+#if 0
+ if (A->base_type==INSTANCE_PORTAL) {
+
+ ERR_FAIL_COND( B->base_type!=INSTANCE_PORTAL );
+
+
+ A->portal_info->candidate_set.erase(B);
+ B->portal_info->candidate_set.erase(A);
+
+ //after disconnecting them, see if they can connect again
+ self->_portal_attempt_connect(A);
+ self->_portal_attempt_connect(B);
+
+ } else if (A->base_type==INSTANCE_GI_PROBE || B->base_type==INSTANCE_GI_PROBE) {
+
+ if (B->base_type==INSTANCE_GI_PROBE) {
+ SWAP(A,B);
+ }
+
+ ERR_FAIL_COND(B->base_type!=INSTANCE_GI_PROBE_SAMPLER);
+ B->gi_probe_sampler_info->gi_probes.erase(A);
+
+ } else if (A->base_type==INSTANCE_ROOM || B->base_type==INSTANCE_ROOM) {
+
+ if (B->base_type==INSTANCE_ROOM)
+ SWAP(A,B);
+
+ ERR_FAIL_COND(! ((1<<B->base_type)&INSTANCE_GEOMETRY_MASK ));
+
+ B->auto_rooms.erase(A);
+ B->valid_auto_rooms.erase(A);
+ A->room_info->owned_autoroom_geometry.erase(B);
+
+ }else {
+
+
+
+ if (B->base_type==INSTANCE_LIGHT) {
+
+ SWAP(A,B);
+ } else if (A->base_type!=INSTANCE_LIGHT) {
+ return;
+ }
+
+
+ A->light_info->affected.erase(B);
+ B->lights.erase(A);
+ B->light_cache_dirty=true;
+
+ }
+#endif
+}
+
+RID VisualServerScene::scenario_create() {
+
+ Scenario *scenario = memnew( Scenario );
+ ERR_FAIL_COND_V(!scenario,RID());
+ RID scenario_rid = scenario_owner.make_rid( scenario );
+ scenario->self=scenario_rid;
+
+ scenario->octree.set_pair_callback(_instance_pair,this);
+ scenario->octree.set_unpair_callback(_instance_unpair,this);
+ scenario->reflection_probe_shadow_atlas=VSG::scene_render->shadow_atlas_create();
+ VSG::scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas,1024); //make enough shadows for close distance, don't bother with rest
+ VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,0,4);
+ VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,1,4);
+ VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,2,4);
+ VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas,3,8);
+ scenario->reflection_atlas=VSG::scene_render->reflection_atlas_create();
+
+ return scenario_rid;
+}
+
+void VisualServerScene::scenario_set_debug(RID p_scenario,VS::ScenarioDebugMode p_debug_mode) {
+
+ Scenario *scenario = scenario_owner.get(p_scenario);
+ ERR_FAIL_COND(!scenario);
+ scenario->debug=p_debug_mode;
+}
+
+void VisualServerScene::scenario_set_environment(RID p_scenario, RID p_environment) {
+
+ Scenario *scenario = scenario_owner.get(p_scenario);
+ ERR_FAIL_COND(!scenario);
+ scenario->environment=p_environment;
+
+}
+
+void VisualServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_environment) {
+
+
+ Scenario *scenario = scenario_owner.get(p_scenario);
+ ERR_FAIL_COND(!scenario);
+ scenario->fallback_environment=p_environment;
+
+
+}
+
+void VisualServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_size,int p_subdiv) {
+
+ Scenario *scenario = scenario_owner.get(p_scenario);
+ ERR_FAIL_COND(!scenario);
+ VSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas,p_size);
+ VSG::scene_render->reflection_atlas_set_subdivision(scenario->reflection_atlas,p_subdiv);
+
+
+}
+
+
+
+/* INSTANCING API */
+
+void VisualServerScene::_instance_queue_update(Instance *p_instance,bool p_update_aabb,bool p_update_materials) {
+
+ if (p_update_aabb)
+ p_instance->update_aabb=true;
+ if (p_update_materials)
+ p_instance->update_materials=true;
+
+ if (p_instance->update_item.in_list())
+ return;
+
+ _instance_update_list.add(&p_instance->update_item);
+
+
+}
+
+// from can be mesh, light, area and portal so far.
+RID VisualServerScene::instance_create(){
+
+ Instance *instance = memnew( Instance );
+ ERR_FAIL_COND_V(!instance,RID());
+
+ RID instance_rid = instance_owner.make_rid(instance);
+ instance->self=instance_rid;
+
+
+ return instance_rid;
+
+
+}
+
+void VisualServerScene::instance_set_base(RID p_instance, RID p_base){
+
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND( !instance );
+
+ Scenario *scenario = instance->scenario;
+
+ if (instance->base_type!=VS::INSTANCE_NONE) {
+ //free anything related to that base
+
+ VSG::storage->instance_remove_dependency(instance->base,instance);
+
+ if (scenario && instance->octree_id) {
+ scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away
+ instance->octree_id=0;
+ }
+
+ switch(instance->base_type) {
+ case VS::INSTANCE_LIGHT: {
+
+ InstanceLightData *light = static_cast<InstanceLightData*>(instance->base_data);
+
+ if (instance->scenario && light->D) {
+ instance->scenario->directional_lights.erase( light->D );
+ light->D=NULL;
+ }
+ VSG::scene_render->free(light->instance);
+ } break;
+ case VS::INSTANCE_REFLECTION_PROBE: {
+
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(instance->base_data);
+ VSG::scene_render->free(reflection_probe->instance);
+ if (reflection_probe->update_list.in_list()) {
+ reflection_probe_render_list.remove(&reflection_probe->update_list);
+ }
+ } break;
+ case VS::INSTANCE_GI_PROBE: {
+
+ InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData*>(instance->base_data);
+
+ while(gi_probe->dynamic.updating_stage==GI_UPDATE_STAGE_LIGHTING) {
+ //wait until bake is done if it's baking
+ OS::get_singleton()->delay_usec(1);
+ }
+ if (gi_probe->update_element.in_list()) {
+ gi_probe_update_list.remove(&gi_probe->update_element);
+ }
+ if (gi_probe->dynamic.probe_data.is_valid()) {
+ VSG::storage->free(gi_probe->dynamic.probe_data);
+ }
+
+ VSG::scene_render->free(gi_probe->probe_instance);
+
+ } break;
+
+ }
+
+ if (instance->base_data) {
+ memdelete( instance->base_data );
+ instance->base_data=NULL;
+ }
+
+ instance->blend_values.clear();
+
+ for(int i=0;i<instance->materials.size();i++) {
+ if (instance->materials[i].is_valid()) {
+ VSG::storage->material_remove_instance_owner(instance->materials[i],instance);
+ }
+ }
+ instance->materials.clear();
+
+#if 0
+ if (instance->light_info) {
+
+ if (instance->scenario && instance->light_info->D)
+ instance->scenario->directional_lights.erase( instance->light_info->D );
+ rasterizer->free(instance->light_info->instance);
+ memdelete(instance->light_info);
+ instance->light_info=NULL;
+ }
+
+
+
+ if ( instance->room ) {
+
+ instance_set_room(p_instance,RID());
+ /*
+ if((1<<instance->base_type)&INSTANCE_GEOMETRY_MASK)
+ instance->room->room_info->owned_geometry_instances.erase(instance->RE);
+ else if (instance->base_type==INSTANCE_PORTAL) {
+ print_line("freeing portal, is it there? "+itos(instance->room->room_info->owned_portal_instances.(instance->RE)));
+ instance->room->room_info->owned_portal_instances.erase(instance->RE);
+ } else if (instance->base_type==INSTANCE_ROOM)
+ instance->room->room_info->owned_room_instances.erase(instance->RE);
+ else if (instance->base_type==INSTANCE_LIGHT)
+ instance->room->room_info->owned_light_instances.erase(instance->RE);
+
+ instance->RE=NULL;*/
+ }
+
+
+
+
+
+
+ if (instance->portal_info) {
+
+ _portal_disconnect(instance,true);
+ memdelete(instance->portal_info);
+ instance->portal_info=NULL;
+
+ }
+
+ if (instance->gi_probe_info) {
+
+ while(instance->gi_probe_info->owned_instances.size()) {
+
+ Instance *owned=instance->gi_probe_info->owned_instances.front()->get();
+ owned->gi_probe=NULL;
+ owned->data.gi_probe=NULL;
+ owned->data.gi_probe_octree_xform=NULL;
+ owned->BLE=NULL;
+ instance->gi_probe_info->owned_instances.pop_front();
+ }
+
+ memdelete(instance->gi_probe_info);
+ instance->gi_probe_info=NULL;
+
+ }
+
+ if (instance->scenario && instance->octree_id) {
+ instance->scenario->octree.erase( instance->octree_id );
+ instance->octree_id=0;
+ }
+
+
+ if (instance->room_info) {
+
+ for(List<Instance*>::Element *E=instance->room_info->owned_geometry_instances.front();E;E=E->next()) {
+
+ Instance *owned = E->get();
+ owned->room=NULL;
+ owned->RE=NULL;
+ }
+ for(List<Instance*>::Element *E=instance->room_info->owned_portal_instances.front();E;E=E->next()) {
+
+ _portal_disconnect(E->get(),true);
+ Instance *owned = E->get();
+ owned->room=NULL;
+ owned->RE=NULL;
+ }
+
+ for(List<Instance*>::Element *E=instance->room_info->owned_room_instances.front();E;E=E->next()) {
+
+ Instance *owned = E->get();
+ owned->room=NULL;
+ owned->RE=NULL;
+ }
+
+ if (instance->room_info->disconnected_child_portals.size()) {
+ ERR_PRINT("BUG: Disconnected portals remain!");
+ }
+ memdelete(instance->room_info);
+ instance->room_info=NULL;
+
+ }
+
+ if (instance->particles_info) {
+
+ rasterizer->free( instance->particles_info->instance );
+ memdelete(instance->particles_info);
+ instance->particles_info=NULL;
+
+ }
+
+ if (instance->gi_probe_sampler_info) {
+
+ while (instance->gi_probe_sampler_info->owned_instances.size()) {
+
+ instance_geometry_set_gi_probe_sampler(instance->gi_probe_sampler_info->owned_instances.front()->get()->self,RID());
+ }
+
+ if (instance->gi_probe_sampler_info->sampled_light.is_valid()) {
+ rasterizer->free(instance->gi_probe_sampler_info->sampled_light);
+ }
+ memdelete( instance->gi_probe_sampler_info );
+ instance->gi_probe_sampler_info=NULL;
+ }
+#endif
+
+ }
+
+
+ instance->base_type=VS::INSTANCE_NONE;
+ instance->base=RID();
+
+
+ if (p_base.is_valid()) {
+
+ instance->base_type=VSG::storage->get_base_type(p_base);
+ ERR_FAIL_COND(instance->base_type==VS::INSTANCE_NONE);
+
+ switch(instance->base_type) {
+ case VS::INSTANCE_LIGHT: {
+
+ InstanceLightData *light = memnew( InstanceLightData );
+
+ if (scenario && VSG::storage->light_get_type(p_base)==VS::LIGHT_DIRECTIONAL) {
+ light->D = scenario->directional_lights.push_back(instance);
+ }
+
+ light->instance = VSG::scene_render->light_instance_create(p_base);
+
+ instance->base_data=light;
+ } break;
+ case VS::INSTANCE_MESH:
+ case VS::INSTANCE_MULTIMESH:
+ case VS::INSTANCE_IMMEDIATE: {
+
+ InstanceGeometryData *geom = memnew( InstanceGeometryData );
+ instance->base_data=geom;
+ } break;
+ case VS::INSTANCE_REFLECTION_PROBE: {
+
+ InstanceReflectionProbeData *reflection_probe = memnew( InstanceReflectionProbeData );
+ reflection_probe->owner=instance;
+ instance->base_data=reflection_probe;
+
+ reflection_probe->instance=VSG::scene_render->reflection_probe_instance_create(p_base);
+ } break;
+ case VS::INSTANCE_GI_PROBE: {
+
+ InstanceGIProbeData *gi_probe = memnew( InstanceGIProbeData );
+ instance->base_data=gi_probe;
+ gi_probe->owner=instance;
+
+ if (scenario && !gi_probe->update_element.in_list()) {
+ gi_probe_update_list.add(&gi_probe->update_element);
+ }
+
+ gi_probe->probe_instance=VSG::scene_render->gi_probe_instance_create();
+
+ } break;
+
+ }
+
+ VSG::storage->instance_add_dependency(p_base,instance);
+
+ instance->base=p_base;
+
+ if (scenario)
+ _instance_queue_update(instance,true,true);
+
+
+#if 0
+ if (rasterizer->is_mesh(p_base)) {
+ instance->base_type=INSTANCE_MESH;
+ instance->data.morph_values.resize( rasterizer->mesh_get_morph_target_count(p_base));
+ instance->data.materials.resize( rasterizer->mesh_get_surface_count(p_base));
+ } else if (rasterizer->is_multimesh(p_base)) {
+ instance->base_type=INSTANCE_MULTIMESH;
+ } else if (rasterizer->is_immediate(p_base)) {
+ instance->base_type=INSTANCE_IMMEDIATE;
+ } else if (rasterizer->is_particles(p_base)) {
+ instance->base_type=INSTANCE_PARTICLES;
+ instance->particles_info=memnew( Instance::ParticlesInfo );
+ instance->particles_info->instance = rasterizer->particles_instance_create( p_base );
+ } else if (rasterizer->is_light(p_base)) {
+
+ instance->base_type=INSTANCE_LIGHT;
+ instance->light_info = memnew( Instance::LightInfo );
+ instance->light_info->instance = rasterizer->light_instance_create(p_base);
+ if (instance->scenario && rasterizer->light_get_type(p_base)==LIGHT_DIRECTIONAL) {
+
+ instance->light_info->D = instance->scenario->directional_lights.push_back(instance->self);
+ }
+
+ } else if (room_owner.owns(p_base)) {
+ instance->base_type=INSTANCE_ROOM;
+ instance->room_info = memnew( Instance::RoomInfo );
+ instance->room_info->room=room_owner.get(p_base);
+ } else if (portal_owner.owns(p_base)) {
+
+ instance->base_type=INSTANCE_PORTAL;
+ instance->portal_info = memnew(Instance::PortalInfo);
+ instance->portal_info->portal=portal_owner.get(p_base);
+ } else if (gi_probe_owner.owns(p_base)) {
+
+ instance->base_type=INSTANCE_GI_PROBE;
+ instance->gi_probe_info=memnew(Instance::BakedLightInfo);
+ instance->gi_probe_info->gi_probe=gi_probe_owner.get(p_base);
+
+ //instance->portal_info = memnew(Instance::PortalInfo);
+ //instance->portal_info->portal=portal_owner.get(p_base);
+ } else if (gi_probe_sampler_owner.owns(p_base)) {
+
+
+ instance->base_type=INSTANCE_GI_PROBE_SAMPLER;
+ instance->gi_probe_sampler_info=memnew( Instance::BakedLightSamplerInfo);
+ instance->gi_probe_sampler_info->sampler=gi_probe_sampler_owner.get(p_base);
+
+ //instance->portal_info = memnew(Instance::PortalInfo);
+ //instance->portal_info->portal=portal_owner.get(p_base);
+
+ } else {
+ ERR_EXPLAIN("Invalid base RID for instance!")
+ ERR_FAIL();
+ }
+
+ instance_dependency_map[ p_base ].insert( instance->self );
+#endif
+
+
+ }
+}
+void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario){
+
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND( !instance );
+
+ if (instance->scenario) {
+
+ instance->scenario->instances.remove( &instance->scenario_item );
+
+ if (instance->octree_id) {
+ instance->scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away
+ instance->octree_id=0;
+ }
+
+
+ switch(instance->base_type) {
+
+ case VS::INSTANCE_LIGHT: {
+
+
+ InstanceLightData *light = static_cast<InstanceLightData*>(instance->base_data);
+
+ if (light->D) {
+ instance->scenario->directional_lights.erase( light->D );
+ light->D=NULL;
+ }
+ } break;
+ case VS::INSTANCE_REFLECTION_PROBE: {
+
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(instance->base_data);
+ VSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance);
+ } break;
+ case VS::INSTANCE_GI_PROBE: {
+
+ InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData*>(instance->base_data);
+ if (gi_probe->update_element.in_list()) {
+ gi_probe_update_list.remove(&gi_probe->update_element);
+ }
+ } break;
+
+ }
+
+ instance->scenario=NULL;
+ }
+
+
+ if (p_scenario.is_valid()) {
+
+ Scenario *scenario = scenario_owner.get( p_scenario );
+ ERR_FAIL_COND(!scenario);
+
+ instance->scenario=scenario;
+
+ scenario->instances.add( &instance->scenario_item );
+
+
+ switch(instance->base_type) {
+
+ case VS::INSTANCE_LIGHT: {
+
+
+ InstanceLightData *light = static_cast<InstanceLightData*>(instance->base_data);
+
+ if (VSG::storage->light_get_type(instance->base)==VS::LIGHT_DIRECTIONAL) {
+ light->D = scenario->directional_lights.push_back(instance);
+ }
+ } break;
+ case VS::INSTANCE_GI_PROBE: {
+
+ InstanceGIProbeData *gi_probe = static_cast<InstanceGIProbeData*>(instance->base_data);
+ if (!gi_probe->update_element.in_list()) {
+ gi_probe_update_list.add(&gi_probe->update_element);
+ }
+ } break;
+ }
+
+ _instance_queue_update(instance,true,true);
+ }
+}
+void VisualServerScene::instance_set_layer_mask(RID p_instance, uint32_t p_mask){
+
+
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND( !instance );
+
+ instance->layer_mask=p_mask;
+}
+void VisualServerScene::instance_set_transform(RID p_instance, const Transform& p_transform){
+
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND( !instance );
+
+ if (instance->transform==p_transform)
+ return; //must be checked to avoid worst evil
+
+ instance->transform=p_transform;
+ _instance_queue_update(instance,true);
+}
+void VisualServerScene::instance_attach_object_instance_ID(RID p_instance,ObjectID p_ID){
+
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND( !instance );
+
+ instance->object_ID=p_ID;
+
+}
+void VisualServerScene::instance_set_blend_shape_weight(RID p_instance,int p_shape, float p_weight){
+
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND( !instance );
+
+ if (instance->update_item.in_list()) {
+ _update_dirty_instance(instance);
+ }
+
+ ERR_FAIL_INDEX(p_shape,instance->blend_values.size());
+ instance->blend_values[p_shape]=p_weight;
+}
+
+void VisualServerScene::instance_set_surface_material(RID p_instance,int p_surface, RID p_material){
+
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND( !instance );
+
+ if (instance->update_item.in_list()) {
+ _update_dirty_instance(instance);
+ }
+
+ ERR_FAIL_INDEX(p_surface,instance->materials.size());
+
+ if (instance->materials[p_surface].is_valid()) {
+ VSG::storage->material_remove_instance_owner(instance->materials[p_surface],instance);
+ }
+ instance->materials[p_surface]=p_material;
+ instance->base_material_changed();
+
+ if (instance->materials[p_surface].is_valid()) {
+ VSG::storage->material_add_instance_owner(instance->materials[p_surface],instance);
+ }
+
+
+}
+
+void VisualServerScene::instance_set_visible(RID p_instance,bool p_visible) {
+
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND( !instance );
+
+ if (instance->visible==p_visible)
+ return;
+
+ instance->visible=p_visible;
+
+
+ switch(instance->base_type) {
+ case VS::INSTANCE_LIGHT: {
+ if (VSG::storage->light_get_type(instance->base)!=VS::LIGHT_DIRECTIONAL && instance->octree_id && instance->scenario) {
+ instance->scenario->octree.set_pairable(instance->octree_id,p_visible,1<<VS::INSTANCE_LIGHT,p_visible?VS::INSTANCE_GEOMETRY_MASK:0);
+ }
+
+ } break;
+ case VS::INSTANCE_REFLECTION_PROBE: {
+ if (instance->octree_id && instance->scenario) {
+ instance->scenario->octree.set_pairable(instance->octree_id,p_visible,1<<VS::INSTANCE_REFLECTION_PROBE,p_visible?VS::INSTANCE_GEOMETRY_MASK:0);
+ }
+
+ } break;
+ case VS::INSTANCE_GI_PROBE: {
+ if (instance->octree_id && instance->scenario) {
+ instance->scenario->octree.set_pairable(instance->octree_id,p_visible,1<<VS::INSTANCE_GI_PROBE,p_visible?(VS::INSTANCE_GEOMETRY_MASK|(1<<VS::INSTANCE_LIGHT)):0);
+ }
+
+ } break;
+
+ }
+
+}
+
+void VisualServerScene::instance_attach_skeleton(RID p_instance,RID p_skeleton){
+
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND( !instance );
+
+ if (instance->skeleton==p_skeleton)
+ return;
+
+ if (instance->skeleton.is_valid()) {
+ VSG::storage->instance_remove_skeleton(p_skeleton,instance);
+ }
+
+ instance->skeleton=p_skeleton;
+
+ if (instance->skeleton.is_valid()) {
+ VSG::storage->instance_add_skeleton(p_skeleton,instance);
+ }
+
+ _instance_queue_update(instance,true);
+}
+
+void VisualServerScene::instance_set_exterior( RID p_instance, bool p_enabled ){
+
+}
+void VisualServerScene::instance_set_room( RID p_instance, RID p_room ){
+
+}
+
+void VisualServerScene::instance_set_extra_visibility_margin( RID p_instance, real_t p_margin ){
+
+}
+
+Vector<ObjectID> VisualServerScene::instances_cull_aabb(const Rect3& p_aabb, RID p_scenario) const {
+
+
+ Vector<ObjectID> instances;
+ Scenario *scenario=scenario_owner.get(p_scenario);
+ ERR_FAIL_COND_V(!scenario,instances);
+
+ const_cast<VisualServerScene*>(this)->update_dirty_instances(); // check dirty instances before culling
+
+ int culled=0;
+ Instance *cull[1024];
+ culled=scenario->octree.cull_AABB(p_aabb,cull,1024);
+
+ for (int i=0;i<culled;i++) {
+
+ Instance *instance=cull[i];
+ ERR_CONTINUE(!instance);
+ if (instance->object_ID==0)
+ continue;
+
+ instances.push_back(instance->object_ID);
+ }
+
+ return instances;
+}
+Vector<ObjectID> VisualServerScene::instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario) const{
+
+ Vector<ObjectID> instances;
+ Scenario *scenario=scenario_owner.get(p_scenario);
+ ERR_FAIL_COND_V(!scenario,instances);
+ const_cast<VisualServerScene*>(this)->update_dirty_instances(); // check dirty instances before culling
+
+ int culled=0;
+ Instance *cull[1024];
+ culled=scenario->octree.cull_segment(p_from,p_to*10000,cull,1024);
+
+
+ for (int i=0;i<culled;i++) {
+ Instance *instance=cull[i];
+ ERR_CONTINUE(!instance);
+ if (instance->object_ID==0)
+ continue;
+
+ instances.push_back(instance->object_ID);
+ }
+
+ return instances;
+
+}
+Vector<ObjectID> VisualServerScene::instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario) const{
+
+ Vector<ObjectID> instances;
+ Scenario *scenario=scenario_owner.get(p_scenario);
+ ERR_FAIL_COND_V(!scenario,instances);
+ const_cast<VisualServerScene*>(this)->update_dirty_instances(); // check dirty instances before culling
+
+ int culled=0;
+ Instance *cull[1024];
+
+
+ culled=scenario->octree.cull_convex(p_convex,cull,1024);
+
+ for (int i=0;i<culled;i++) {
+
+ Instance *instance=cull[i];
+ ERR_CONTINUE(!instance);
+ if (instance->object_ID==0)
+ continue;
+
+ instances.push_back(instance->object_ID);
+ }
+
+ return instances;
+
+}
+
+void VisualServerScene::instance_geometry_set_flag(RID p_instance,VS::InstanceFlags p_flags,bool p_enabled){
+
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND( !instance );
+
+ switch(p_flags) {
+
+ case VS::INSTANCE_FLAG_BILLBOARD: {
+
+ instance->billboard=p_enabled;
+
+ } break;
+ case VS::INSTANCE_FLAG_BILLBOARD_FIX_Y: {
+
+ instance->billboard_y=p_enabled;
+
+ } break;
+ case VS::INSTANCE_FLAG_CAST_SHADOW: {
+ if (p_enabled == true) {
+ instance->cast_shadows = VS::SHADOW_CASTING_SETTING_ON;
+ }
+ else {
+ instance->cast_shadows = VS::SHADOW_CASTING_SETTING_OFF;
+ }
+
+ instance->base_material_changed(); // to actually compute if shadows are visible or not
+
+ } break;
+ case VS::INSTANCE_FLAG_DEPH_SCALE: {
+
+ instance->depth_scale=p_enabled;
+
+ } break;
+ case VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS: {
+
+ instance->visible_in_all_rooms=p_enabled;
+
+ } break;
+
+ }
+}
+void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting) {
+
+}
+void VisualServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material){
+
+ Instance *instance = instance_owner.get( p_instance );
+ ERR_FAIL_COND( !instance );
+
+ if (instance->material_override.is_valid()) {
+ VSG::storage->material_remove_instance_owner(instance->material_override,instance);
+ }
+ instance->material_override=p_material;
+ instance->base_material_changed();
+
+ if (instance->material_override.is_valid()) {
+ VSG::storage->material_add_instance_owner(instance->material_override,instance);
+ }
+
+}
+
+
+void VisualServerScene::instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max,float p_min_margin,float p_max_margin){
+
+}
+void VisualServerScene::instance_geometry_set_as_instance_lod(RID p_instance,RID p_as_lod_of_instance){
+
+}
+
+
+void VisualServerScene::_update_instance(Instance *p_instance) {
+
+ p_instance->version++;
+
+ if (p_instance->base_type == VS::INSTANCE_LIGHT) {
+
+ InstanceLightData *light = static_cast<InstanceLightData*>(p_instance->base_data);
+
+ VSG::scene_render->light_instance_set_transform( light->instance, p_instance->transform );
+ light->shadow_dirty=true;
+
+ }
+
+ if (p_instance->base_type == VS::INSTANCE_REFLECTION_PROBE) {
+
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(p_instance->base_data);
+
+ VSG::scene_render->reflection_probe_instance_set_transform( reflection_probe->instance, p_instance->transform );
+ reflection_probe->reflection_dirty=true;
+
+ }
+
+
+ if (p_instance->aabb.has_no_surface())
+ return;
+
+#if 0
+ if (p_instance->base_type == VS::INSTANCE_PARTICLES) {
+
+ rasterizer->particles_instance_set_transform( p_instance->particles_info->instance, p_instance->data.transform );
+ }
+
+#endif
+ if ((1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
+
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData*>(p_instance->base_data);
+ //make sure lights are updated if it casts shadow
+
+ if (geom->can_cast_shadows) {
+ for (List<Instance*>::Element *E=geom->lighting.front();E;E=E->next()) {
+ InstanceLightData *light = static_cast<InstanceLightData*>(E->get()->base_data);
+ light->shadow_dirty=true;
+ }
+ }
+
+ }
+#if 0
+ else if (p_instance->base_type == INSTANCE_ROOM) {
+
+ p_instance->room_info->affine_inverse=p_instance->data.transform.affine_inverse();
+ } else if (p_instance->base_type == INSTANCE_GI_PROBE) {
+
+ Transform scale;
+ scale.basis.scale(p_instance->gi_probe_info->gi_probe->octree_aabb.size);
+ scale.origin=p_instance->gi_probe_info->gi_probe->octree_aabb.pos;
+ //print_line("scale: "+scale);
+ p_instance->gi_probe_info->affine_inverse=(p_instance->data.transform*scale).affine_inverse();
+ }
+
+
+#endif
+
+ p_instance->mirror = p_instance->transform.basis.determinant() < 0.0;
+
+ Rect3 new_aabb;
+#if 0
+ if (p_instance->base_type==INSTANCE_PORTAL) {
+
+ //portals need to be transformed in a special way, so they don't become too wide if they have scale..
+ Transform portal_xform = p_instance->data.transform;
+ portal_xform.basis.set_axis(2,portal_xform.basis.get_axis(2).normalized());
+
+ p_instance->portal_info->plane_cache=Plane( p_instance->data.transform.origin, portal_xform.basis.get_axis(2));
+ int point_count=p_instance->portal_info->portal->shape.size();
+ p_instance->portal_info->transformed_point_cache.resize(point_count);
+
+ AABB portal_aabb;
+
+ for(int i=0;i<point_count;i++) {
+
+ Point2 src = p_instance->portal_info->portal->shape[i];
+ Vector3 point = portal_xform.xform(Vector3(src.x,src.y,0));
+ p_instance->portal_info->transformed_point_cache[i]=point;
+ if (i==0)
+ portal_aabb.pos=point;
+ else
+ portal_aabb.expand_to(point);
+ }
+
+ portal_aabb.grow_by(p_instance->portal_info->portal->connect_range);
+
+ new_aabb = portal_aabb;
+
+ } else {
+#endif
+ new_aabb = p_instance->transform.xform(p_instance->aabb);
+#if 0
+ }
+#endif
+
+
+ p_instance->transformed_aabb=new_aabb;
+
+ if (!p_instance->scenario) {
+
+ return;
+ }
+
+
+
+ if (p_instance->octree_id==0) {
+
+ uint32_t base_type = 1<<p_instance->base_type;
+ uint32_t pairable_mask=0;
+ bool pairable=false;
+
+ if (p_instance->base_type == VS::INSTANCE_LIGHT || p_instance->base_type==VS::INSTANCE_REFLECTION_PROBE) {
+
+ pairable_mask=p_instance->visible?VS::INSTANCE_GEOMETRY_MASK:0;
+ pairable=true;
+ }
+
+ if (p_instance->base_type == VS::INSTANCE_GI_PROBE) {
+ //lights and geometries
+ pairable_mask=p_instance->visible?VS::INSTANCE_GEOMETRY_MASK|(1<<VS::INSTANCE_LIGHT):0;
+ pairable=true;
+ }
+
+#if 0
+
+ if (p_instance->base_type == VS::INSTANCE_PORTAL) {
+
+ pairable_mask=(1<<INSTANCE_PORTAL);
+ pairable=true;
+ }
+
+ if (p_instance->base_type == VS::INSTANCE_GI_PROBE_SAMPLER) {
+
+ pairable_mask=(1<<INSTANCE_GI_PROBE);
+ pairable=true;
+ }
+
+
+ if (!p_instance->room && (1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
+
+ base_type|=VS::INSTANCE_ROOMLESS_MASK;
+ }
+
+ if (p_instance->base_type == VS::INSTANCE_ROOM) {
+
+ pairable_mask=INSTANCE_ROOMLESS_MASK;
+ pairable=true;
+ }
+#endif
+
+ // not inside octree
+ p_instance->octree_id = p_instance->scenario->octree.create(p_instance,new_aabb,0,pairable,base_type,pairable_mask);
+
+ } else {
+
+ /*
+ if (new_aabb==p_instance->data.transformed_aabb)
+ return;
+ */
+
+ p_instance->scenario->octree.move(p_instance->octree_id,new_aabb);
+ }
+#if 0
+ if (p_instance->base_type==INSTANCE_PORTAL) {
+
+ _portal_attempt_connect(p_instance);
+ }
+
+ if (!p_instance->room && (1<<p_instance->base_type)&INSTANCE_GEOMETRY_MASK) {
+
+ _instance_validate_autorooms(p_instance);
+ }
+
+ if (p_instance->base_type == INSTANCE_ROOM) {
+
+ for(Set<Instance*>::Element *E=p_instance->room_info->owned_autoroom_geometry.front();E;E=E->next())
+ _instance_validate_autorooms(E->get());
+ }
+#endif
+
+}
+
+void VisualServerScene::_update_instance_aabb(Instance *p_instance) {
+
+ Rect3 new_aabb;
+
+ ERR_FAIL_COND(p_instance->base_type!=VS::INSTANCE_NONE && !p_instance->base.is_valid());
+
+ switch(p_instance->base_type) {
+ case VisualServer::INSTANCE_NONE: {
+
+ // do nothing
+ } break;
+ case VisualServer::INSTANCE_MESH: {
+
+ new_aabb = VSG::storage->mesh_get_aabb(p_instance->base,p_instance->skeleton);
+
+ } break;
+
+ case VisualServer::INSTANCE_MULTIMESH: {
+
+ new_aabb = VSG::storage->multimesh_get_aabb(p_instance->base);
+
+ } break;
+ case VisualServer::INSTANCE_IMMEDIATE: {
+
+ new_aabb = VSG::storage->immediate_get_aabb(p_instance->base);
+
+
+ } break;
+#if 0
+
+ case VisualServer::INSTANCE_PARTICLES: {
+
+ new_aabb = rasterizer->particles_get_aabb(p_instance->base);
+
+
+ } break;
+#endif
+ case VisualServer::INSTANCE_LIGHT: {
+
+ new_aabb = VSG::storage->light_get_aabb(p_instance->base);
+
+ } break;
+ case VisualServer::INSTANCE_REFLECTION_PROBE: {
+
+ new_aabb = VSG::storage->reflection_probe_get_aabb(p_instance->base);
+
+ } break;
+ case VisualServer::INSTANCE_GI_PROBE: {
+
+ new_aabb = VSG::storage->gi_probe_get_bounds(p_instance->base);
+
+ } break;
+
+#if 0
+ case VisualServer::INSTANCE_ROOM: {
+
+ Room *room = room_owner.get( p_instance->base );
+ ERR_FAIL_COND(!room);
+ new_aabb=room->bounds.get_aabb();
+
+ } break;
+ case VisualServer::INSTANCE_PORTAL: {
+
+ Portal *portal = portal_owner.get( p_instance->base );
+ ERR_FAIL_COND(!portal);
+ for (int i=0;i<portal->shape.size();i++) {
+
+ Vector3 point( portal->shape[i].x, portal->shape[i].y, 0 );
+ if (i==0) {
+
+ new_aabb.pos=point;
+ new_aabb.size.z=0.01; // make it not flat for octree
+ } else {
+
+ new_aabb.expand_to(point);
+ }
+ }
+
+ } break;
+ case VisualServer::INSTANCE_GI_PROBE: {
+
+ BakedLight *gi_probe = gi_probe_owner.get( p_instance->base );
+ ERR_FAIL_COND(!gi_probe);
+ new_aabb=gi_probe->octree_aabb;
+
+ } break;
+ case VisualServer::INSTANCE_GI_PROBE_SAMPLER: {
+
+ BakedLightSampler *gi_probe_sampler = gi_probe_sampler_owner.get( p_instance->base );
+ ERR_FAIL_COND(!gi_probe_sampler);
+ float radius = gi_probe_sampler->params[VS::BAKED_LIGHT_SAMPLER_RADIUS];
+
+ new_aabb=AABB(Vector3(-radius,-radius,-radius),Vector3(radius*2,radius*2,radius*2));
+
+ } break;
+#endif
+ default: {}
+ }
+
+ if (p_instance->extra_margin)
+ new_aabb.grow_by(p_instance->extra_margin);
+
+ p_instance->aabb=new_aabb;
+
+}
+
+
+
+
+
+void VisualServerScene::_light_instance_update_shadow(Instance *p_instance,const Transform p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_orthogonal,RID p_shadow_atlas,Scenario* p_scenario) {
+
+
+ InstanceLightData * light = static_cast<InstanceLightData*>(p_instance->base_data);
+
+ switch(VSG::storage->light_get_type(p_instance->base)) {
+
+ case VS::LIGHT_DIRECTIONAL: {
+
+ float max_distance =p_cam_projection.get_z_far();
+ float shadow_max = VSG::storage->light_get_param(p_instance->base,VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE);
+ if (shadow_max>0) {
+ max_distance=MIN(shadow_max,max_distance);
+ }
+ max_distance=MAX(max_distance,p_cam_projection.get_z_near()+0.001);
+
+ float range = max_distance-p_cam_projection.get_z_near();
+
+ int splits=0;
+ switch(VSG::storage->light_directional_get_shadow_mode(p_instance->base)) {
+ case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: splits=1; break;
+ case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: splits=2; break;
+ case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: splits=4; break;
+ }
+
+ float distances[5];
+
+ distances[0]=p_cam_projection.get_z_near();
+ for(int i=0;i<splits;i++) {
+ distances[i+1]=p_cam_projection.get_z_near()+VSG::storage->light_get_param(p_instance->base,VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET+i))*range;
+ };
+
+ distances[splits]=max_distance;
+
+ float texture_size=VSG::scene_render->get_directional_light_shadow_size(light->instance);
+
+ bool overlap = VSG::storage->light_directional_get_blend_splits(p_instance->base);
+
+ for (int i=0;i<splits;i++) {
+
+ // setup a camera matrix for that range!
+ CameraMatrix camera_matrix;
+
+ float aspect = p_cam_projection.get_aspect();
+
+
+ if (p_cam_orthogonal) {
+
+ float w,h;
+ p_cam_projection.get_viewport_size(w,h);
+ camera_matrix.set_orthogonal(w,aspect,distances[(i==0 || !overlap )?i:i-1],distances[i+1],false);
+ } else {
+
+ float fov = p_cam_projection.get_fov();
+ camera_matrix.set_perspective(fov,aspect,distances[(i==0 || !overlap )?i:i-1],distances[i+1],false);
+ }
+
+ //obtain the frustum endpoints
+
+ Vector3 endpoints[8]; // frustum plane endpoints
+ bool res = camera_matrix.get_endpoints(p_cam_transform,endpoints);
+ ERR_CONTINUE(!res);
+
+ // obtain the light frustm ranges (given endpoints)
+
+ Vector3 x_vec=p_instance->transform.basis.get_axis( Vector3::AXIS_X ).normalized();
+ Vector3 y_vec=p_instance->transform.basis.get_axis( Vector3::AXIS_Y ).normalized();
+ Vector3 z_vec=p_instance->transform.basis.get_axis( Vector3::AXIS_Z ).normalized();
+ //z_vec points agsint the camera, like in default opengl
+
+ float x_min,x_max;
+ float y_min,y_max;
+ float z_min,z_max;
+
+ float x_min_cam,x_max_cam;
+ float y_min_cam,y_max_cam;
+ float z_min_cam,z_max_cam;
+
+
+ //used for culling
+ for(int j=0;j<8;j++) {
+
+ float d_x=x_vec.dot(endpoints[j]);
+ float d_y=y_vec.dot(endpoints[j]);
+ float d_z=z_vec.dot(endpoints[j]);
+
+ if (j==0 || d_x<x_min)
+ x_min=d_x;
+ if (j==0 || d_x>x_max)
+ x_max=d_x;
+
+ if (j==0 || d_y<y_min)
+ y_min=d_y;
+ if (j==0 || d_y>y_max)
+ y_max=d_y;
+
+ if (j==0 || d_z<z_min)
+ z_min=d_z;
+ if (j==0 || d_z>z_max)
+ z_max=d_z;
+
+
+ }
+
+
+
+
+
+ {
+ //camera viewport stuff
+ //this trick here is what stabilizes the shadow (make potential jaggies to not move)
+ //at the cost of some wasted resolution. Still the quality increase is very well worth it
+
+
+ Vector3 center;
+
+ for(int j=0;j<8;j++) {
+
+ center+=endpoints[j];
+ }
+ center/=8.0;
+
+ //center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5;
+
+ float radius=0;
+
+ for(int j=0;j<8;j++) {
+
+ float d = center.distance_to(endpoints[j]);
+ if (d>radius)
+ radius=d;
+ }
+
+
+ radius *= texture_size/(texture_size-2.0); //add a texel by each side, so stepified texture will always fit
+
+ x_max_cam=x_vec.dot(center)+radius;
+ x_min_cam=x_vec.dot(center)-radius;
+ y_max_cam=y_vec.dot(center)+radius;
+ y_min_cam=y_vec.dot(center)-radius;
+ z_max_cam=z_vec.dot(center)+radius;
+ z_min_cam=z_vec.dot(center)-radius;
+
+ float unit = radius*2.0/texture_size;
+
+ x_max_cam=Math::stepify(x_max_cam,unit);
+ x_min_cam=Math::stepify(x_min_cam,unit);
+ y_max_cam=Math::stepify(y_max_cam,unit);
+ y_min_cam=Math::stepify(y_min_cam,unit);
+
+ }
+
+ //now that we now all ranges, we can proceed to make the light frustum planes, for culling octree
+
+ Vector<Plane> light_frustum_planes;
+ light_frustum_planes.resize(6);
+
+ //right/left
+ light_frustum_planes[0]=Plane( x_vec, x_max );
+ light_frustum_planes[1]=Plane( -x_vec, -x_min );
+ //top/bottom
+ light_frustum_planes[2]=Plane( y_vec, y_max );
+ light_frustum_planes[3]=Plane( -y_vec, -y_min );
+ //near/far
+ light_frustum_planes[4]=Plane( z_vec, z_max+1e6 );
+ light_frustum_planes[5]=Plane( -z_vec, -z_min ); // z_min is ok, since casters further than far-light plane are not needed
+
+ int cull_count = p_scenario->octree.cull_convex(light_frustum_planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK);
+
+ // a pre pass will need to be needed to determine the actual z-near to be used
+
+
+ for (int j=0;j<cull_count;j++) {
+
+ float min,max;
+ Instance *instance = instance_shadow_cull_result[j];
+ if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) {
+ cull_count--;
+ SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]);
+ j--;
+ continue;
+
+ }
+
+
+ instance->transformed_aabb.project_range_in_plane(Plane(z_vec,0),min,max);
+ if (max>z_max)
+ z_max=max;
+ }
+
+ {
+ CameraMatrix ortho_camera;
+ real_t half_x = (x_max_cam-x_min_cam) * 0.5;
+ real_t half_y = (y_max_cam-y_min_cam) * 0.5;
+
+
+ ortho_camera.set_orthogonal( -half_x, half_x,-half_y,half_y, 0, (z_max-z_min_cam) );
+
+ Transform ortho_transform;
+ ortho_transform.basis=p_instance->transform.basis;
+ ortho_transform.origin=x_vec*(x_min_cam+half_x)+y_vec*(y_min_cam+half_y)+z_vec*z_max;
+
+ VSG::scene_render->light_instance_set_shadow_transform(light->instance,ortho_camera,ortho_transform,0,distances[i+1],i);
+ }
+
+
+
+ VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count);
+
+ }
+
+ } break;
+ case VS::LIGHT_OMNI: {
+
+ VS::LightOmniShadowMode shadow_mode = VSG::storage->light_omni_get_shadow_mode(p_instance->base);
+
+ switch(shadow_mode) {
+ case VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID: {
+
+ for(int i=0;i<2;i++) {
+
+ //using this one ensures that raster deferred will have it
+
+ float radius = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_RANGE);
+
+ float z =i==0?-1:1;
+ Vector<Plane> planes;
+ planes.resize(5);
+ planes[0]=p_instance->transform.xform(Plane(Vector3(0,0,z),radius));
+ planes[1]=p_instance->transform.xform(Plane(Vector3(1,0,z).normalized(),radius));
+ planes[2]=p_instance->transform.xform(Plane(Vector3(-1,0,z).normalized(),radius));
+ planes[3]=p_instance->transform.xform(Plane(Vector3(0,1,z).normalized(),radius));
+ planes[4]=p_instance->transform.xform(Plane(Vector3(0,-1,z).normalized(),radius));
+
+
+ int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK);
+
+ for (int j=0;j<cull_count;j++) {
+
+ Instance *instance = instance_shadow_cull_result[j];
+ if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) {
+ cull_count--;
+ SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]);
+ j--;
+
+ }
+ }
+
+ VSG::scene_render->light_instance_set_shadow_transform(light->instance,CameraMatrix(),p_instance->transform,radius,0,i);
+ VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count);
+ }
+ } break;
+ case VS::LIGHT_OMNI_SHADOW_CUBE: {
+
+ float radius = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_RANGE);
+ CameraMatrix cm;
+ cm.set_perspective(90,1,0.01,radius);
+
+ for(int i=0;i<6;i++) {
+
+ //using this one ensures that raster deferred will have it
+
+
+
+ static const Vector3 view_normals[6]={
+ Vector3(-1, 0, 0),
+ Vector3(+1, 0, 0),
+ Vector3( 0,-1, 0),
+ Vector3( 0,+1, 0),
+ Vector3( 0, 0,-1),
+ Vector3( 0, 0,+1)
+ };
+ static const Vector3 view_up[6]={
+ Vector3( 0,-1, 0),
+ Vector3( 0,-1, 0),
+ Vector3( 0, 0,-1),
+ Vector3( 0, 0,+1),
+ Vector3( 0,-1, 0),
+ Vector3( 0,-1, 0)
+ };
+
+ Transform xform = p_instance->transform * Transform().looking_at(view_normals[i],view_up[i]);
+
+
+ Vector<Plane> planes = cm.get_projection_planes(xform);
+
+ int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK);
+
+ for (int j=0;j<cull_count;j++) {
+
+ Instance *instance = instance_shadow_cull_result[j];
+ if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) {
+ cull_count--;
+ SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]);
+ j--;
+
+ }
+ }
+
+
+ VSG::scene_render->light_instance_set_shadow_transform(light->instance,cm,xform,radius,0,i);
+ VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,i,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count);
+ }
+
+ //restore the regular DP matrix
+ VSG::scene_render->light_instance_set_shadow_transform(light->instance,CameraMatrix(),p_instance->transform,radius,0,0);
+
+ } break;
+ }
+
+
+ } break;
+ case VS::LIGHT_SPOT: {
+
+
+ float radius = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_RANGE);
+ float angle = VSG::storage->light_get_param( p_instance->base, VS::LIGHT_PARAM_SPOT_ANGLE);
+
+ CameraMatrix cm;
+ cm.set_perspective( angle*2.0, 1.0, 0.01, radius );
+
+
+ Vector<Plane> planes = cm.get_projection_planes(p_instance->transform);
+ int cull_count = p_scenario->octree.cull_convex(planes,instance_shadow_cull_result,MAX_INSTANCE_CULL,VS::INSTANCE_GEOMETRY_MASK);
+
+ for (int j=0;j<cull_count;j++) {
+
+ Instance *instance = instance_shadow_cull_result[j];
+ if (!instance->visible || !((1<<instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) || !static_cast<InstanceGeometryData*>(instance->base_data)->can_cast_shadows) {
+ cull_count--;
+ SWAP(instance_shadow_cull_result[j],instance_shadow_cull_result[cull_count]);
+ j--;
+
+ }
+ }
+
+
+ VSG::scene_render->light_instance_set_shadow_transform(light->instance,cm,p_instance->transform,radius,0,0);
+ VSG::scene_render->render_shadow(light->instance,p_shadow_atlas,0,(RasterizerScene::InstanceBase**)instance_shadow_cull_result,cull_count);
+
+ } break;
+ }
+
+}
+
+
+void VisualServerScene::render_camera(RID p_camera, RID p_scenario,Size2 p_viewport_size,RID p_shadow_atlas) {
+
+ Camera *camera = camera_owner.getornull(p_camera);
+ ERR_FAIL_COND(!camera);
+
+ /* STEP 1 - SETUP CAMERA */
+ CameraMatrix camera_matrix;
+ bool ortho=false;
+
+
+ switch(camera->type) {
+ case Camera::ORTHOGONAL: {
+
+ camera_matrix.set_orthogonal(
+ camera->size,
+ p_viewport_size.width / (float)p_viewport_size.height,
+ camera->znear,
+ camera->zfar,
+ camera->vaspect
+
+ );
+ ortho=true;
+ } break;
+ case Camera::PERSPECTIVE: {
+
+ camera_matrix.set_perspective(
+ camera->fov,
+ p_viewport_size.width / (float)p_viewport_size.height,
+ camera->znear,
+ camera->zfar,
+ camera->vaspect
+
+ );
+ ortho=false;
+
+ } break;
+ }
+
+ _render_scene(camera->transform,camera_matrix,ortho,camera->env,camera->visible_layers,p_scenario,p_shadow_atlas,RID(),-1);
+
+}
+
+
+void VisualServerScene::_render_scene(const Transform p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_orthogonal,RID p_force_environment,uint32_t p_visible_layers, RID p_scenario,RID p_shadow_atlas,RID p_reflection_probe,int p_reflection_probe_pass) {
+
+
+
+ Scenario *scenario = scenario_owner.getornull(p_scenario);
+
+ render_pass++;
+ uint32_t camera_layer_mask=p_visible_layers;
+
+ VSG::scene_render->set_scene_pass(render_pass);
+
+
+ //rasterizer->set_camera(camera->transform, camera_matrix,ortho);
+
+ Vector<Plane> planes = p_cam_projection.get_projection_planes(p_cam_transform);
+
+ Plane near_plane(p_cam_transform.origin,-p_cam_transform.basis.get_axis(2).normalized());
+ float z_far = p_cam_projection.get_z_far();
+
+ /* STEP 2 - CULL */
+ int cull_count = scenario->octree.cull_convex(planes,instance_cull_result,MAX_INSTANCE_CULL);
+ light_cull_count=0;
+
+ reflection_probe_cull_count=0;
+
+ //light_samplers_culled=0;
+
+/* print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0));
+ print_line("OTO: "+itos(p_scenario->octree.get_octant_count()));
+ //print_line("OTE: "+itos(p_scenario->octree.get_elem_count()));
+ print_line("OTP: "+itos(p_scenario->octree.get_pair_count()));
+*/
+
+ /* STEP 3 - PROCESS PORTALS, VALIDATE ROOMS */
+
+
+ // compute portals
+#if 0
+ exterior_visited=false;
+ exterior_portal_cull_count=0;
+
+ if (room_cull_enabled) {
+ for(int i=0;i<cull_count;i++) {
+
+ Instance *ins = instance_cull_result[i];
+ ins->last_render_pass=render_pass;
+
+ if (ins->base_type!=INSTANCE_PORTAL)
+ continue;
+
+ if (ins->room)
+ continue;
+
+ ERR_CONTINUE(exterior_portal_cull_count>=MAX_EXTERIOR_PORTALS);
+ exterior_portal_cull_result[exterior_portal_cull_count++]=ins;
+
+ }
+
+ room_cull_count = p_scenario->octree.cull_point(camera->transform.origin,room_cull_result,MAX_ROOM_CULL,NULL,(1<<INSTANCE_ROOM)|(1<<INSTANCE_PORTAL));
+
+
+ Set<Instance*> current_rooms;
+ Set<Instance*> portal_rooms;
+ //add to set
+ for(int i=0;i<room_cull_count;i++) {
+
+ if (room_cull_result[i]->base_type==INSTANCE_ROOM) {
+ current_rooms.insert(room_cull_result[i]);
+ }
+ if (room_cull_result[i]->base_type==INSTANCE_PORTAL) {
+ //assume inside that room if also inside the portal..
+ if (room_cull_result[i]->room) {
+ portal_rooms.insert(room_cull_result[i]->room);
+ }
+
+ SWAP(room_cull_result[i],room_cull_result[room_cull_count-1]);
+ room_cull_count--;
+ i--;
+ }
+ }
+
+ //remove from set if it has a parent room or BSP doesn't contain
+ for(int i=0;i<room_cull_count;i++) {
+ Instance *r = room_cull_result[i];
+
+ //check inside BSP
+ Vector3 room_local_point = r->room_info->affine_inverse.xform( camera->transform.origin );
+
+ if (!portal_rooms.has(r) && !r->room_info->room->bounds.point_is_inside(room_local_point)) {
+
+ current_rooms.erase(r);
+ continue;
+ }
+
+ //check parent
+ while (r->room) {// has parent room
+
+ current_rooms.erase(r);
+ r=r->room;
+ }
+
+ }
+
+ if (current_rooms.size()) {
+ //camera is inside a room
+ // go through rooms
+ for(Set<Instance*>::Element *E=current_rooms.front();E;E=E->next()) {
+ _cull_room(camera,E->get());
+ }
+
+ } else {
+ //start from exterior
+ _cull_room(camera,NULL);
+
+ }
+ }
+
+#endif
+ /* STEP 4 - REMOVE FURTHER CULLED OBJECTS, ADD LIGHTS */
+
+ for(int i=0;i<cull_count;i++) {
+
+ Instance *ins = instance_cull_result[i];
+
+ bool keep=false;
+
+ if ((camera_layer_mask&ins->layer_mask)==0) {
+
+ //failure
+ } else if (ins->base_type==VS::INSTANCE_LIGHT && ins->visible) {
+
+
+ if (ins->visible && light_cull_count<MAX_LIGHTS_CULLED) {
+
+ InstanceLightData * light = static_cast<InstanceLightData*>(ins->base_data);
+
+ if (!light->geometries.empty()) {
+ //do not add this light if no geometry is affected by it..
+ light_cull_result[light_cull_count]=ins;
+ light_instance_cull_result[light_cull_count]=light->instance;
+ if (p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(ins->base)) {
+ VSG::scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later
+ }
+
+ light_cull_count++;
+ }
+
+
+ }
+ } else if (ins->base_type==VS::INSTANCE_REFLECTION_PROBE && ins->visible) {
+
+
+ if (ins->visible && reflection_probe_cull_count<MAX_REFLECTION_PROBES_CULLED) {
+
+ InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(ins->base_data);
+
+ if (p_reflection_probe!=reflection_probe->instance) {
+ //avoid entering The Matrix
+
+ if (!reflection_probe->geometries.empty()) {
+ //do not add this light if no geometry is affected by it..
+
+ if (reflection_probe->reflection_dirty || VSG::scene_render->reflection_probe_instance_needs_redraw(reflection_probe->instance)) {
+ if (!reflection_probe->update_list.in_list()) {
+ reflection_probe->render_step=0;
+ reflection_probe_render_list.add(&reflection_probe->update_list);
+ }
+
+ reflection_probe->reflection_dirty=false;
+ }
+
+ if (VSG::scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) {
+ reflection_probe_instance_cull_result[reflection_probe_cull_count]=reflection_probe->instance;
+ reflection_probe_cull_count++;
+ }
+
+ }
+ }
+ }
+
+ } else if (ins->base_type==VS::INSTANCE_GI_PROBE && ins->visible) {
+
+ InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(ins->base_data);
+ if (!gi_probe->update_element.in_list()) {
+ gi_probe_update_list.add(&gi_probe->update_element);
+ }
+
+ } else if ((1<<ins->base_type)&VS::INSTANCE_GEOMETRY_MASK && ins->visible && ins->cast_shadows!=VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) {
+
+ keep=true;
+#if 0
+ bool discarded=false;
+
+ if (ins->draw_range_end>0) {
+
+ float d = cull_range.nearp.distance_to(ins->data.transform.origin);
+ if (d<0)
+ d=0;
+ discarded=(d<ins->draw_range_begin || d>=ins->draw_range_end);
+
+
+ }
+
+ if (!discarded) {
+
+ // test if this geometry should be visible
+
+ if (room_cull_enabled) {
+
+
+ if (ins->visible_in_all_rooms) {
+ keep=true;
+ } else if (ins->room) {
+
+ if (ins->room->room_info->last_visited_pass==render_pass)
+ keep=true;
+ } else if (ins->auto_rooms.size()) {
+
+
+ for(Set<Instance*>::Element *E=ins->auto_rooms.front();E;E=E->next()) {
+
+ if (E->get()->room_info->last_visited_pass==render_pass) {
+ keep=true;
+ break;
+ }
+ }
+ } else if(exterior_visited)
+ keep=true;
+ } else {
+
+ keep=true;
+ }
+
+
+ }
+
+
+ if (keep) {
+ // update cull range
+ float min,max;
+ ins->transformed_aabb.project_range_in_plane(cull_range.nearp,min,max);
+
+ if (min<cull_range.min)
+ cull_range.min=min;
+ if (max>cull_range.max)
+ cull_range.max=max;
+
+ if (ins->sampled_light && ins->sampled_light->gi_probe_sampler_info->last_pass!=render_pass) {
+ if (light_samplers_culled<MAX_LIGHT_SAMPLERS) {
+ light_sampler_cull_result[light_samplers_culled++]=ins->sampled_light;
+ ins->sampled_light->gi_probe_sampler_info->last_pass=render_pass;
+ }
+ }
+ }
+#endif
+
+
+ InstanceGeometryData * geom = static_cast<InstanceGeometryData*>(ins->base_data);
+
+
+ if (geom->lighting_dirty) {
+ int l=0;
+ //only called when lights AABB enter/exit this geometry
+ ins->light_instances.resize(geom->lighting.size());
+
+ for (List<Instance*>::Element *E=geom->lighting.front();E;E=E->next()) {
+
+ InstanceLightData * light = static_cast<InstanceLightData*>(E->get()->base_data);
+
+ ins->light_instances[l++]=light->instance;
+ }
+
+ geom->lighting_dirty=false;
+ }
+
+ if (geom->reflection_dirty) {
+ int l=0;
+ //only called when reflection probe AABB enter/exit this geometry
+ ins->reflection_probe_instances.resize(geom->reflection_probes.size());
+
+ for (List<Instance*>::Element *E=geom->reflection_probes.front();E;E=E->next()) {
+
+ InstanceReflectionProbeData * reflection_probe = static_cast<InstanceReflectionProbeData*>(E->get()->base_data);
+
+ ins->reflection_probe_instances[l++]=reflection_probe->instance;
+ }
+
+ geom->reflection_dirty=false;
+ }
+
+ if (geom->gi_probes_dirty) {
+ int l=0;
+ //only called when reflection probe AABB enter/exit this geometry
+ ins->gi_probe_instances.resize(geom->gi_probes.size());
+
+ for (List<Instance*>::Element *E=geom->gi_probes.front();E;E=E->next()) {
+
+ InstanceGIProbeData * gi_probe = static_cast<InstanceGIProbeData*>(E->get()->base_data);
+
+ ins->gi_probe_instances[l++]=gi_probe->probe_instance;
+ }
+
+ geom->gi_probes_dirty=false;
+ }
+
+ ins->depth = near_plane.distance_to(ins->transform.origin);
+ ins->depth_layer=CLAMP(int(ins->depth*8/z_far),0,7);
+
+ }
+
+ if (!keep) {
+ // remove, no reason to keep
+ cull_count--;
+ SWAP( instance_cull_result[i], instance_cull_result[ cull_count ] );
+ i--;
+ ins->last_render_pass=0; // make invalid
+ } else {
+
+ ins->last_render_pass=render_pass;
+ }
+ }
+
+ /* STEP 5 - PROCESS LIGHTS */
+
+ RID *directional_light_ptr=&light_instance_cull_result[light_cull_count];
+ int directional_light_count=0;
+
+ // directional lights
+ {
+
+ Instance** lights_with_shadow = (Instance**)alloca(sizeof(Instance*)*scenario->directional_lights.size());
+ int directional_shadow_count=0;
+
+ for (List<Instance*>::Element *E=scenario->directional_lights.front();E;E=E->next()) {
+
+ if (light_cull_count+directional_light_count>=MAX_LIGHTS_CULLED) {
+ break;
+ }
+
+ if (!E->get()->visible)
+ continue;
+
+ InstanceLightData * light = static_cast<InstanceLightData*>(E->get()->base_data);
+
+
+ //check shadow..
+
+
+ if (light && p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(E->get()->base)) {
+ lights_with_shadow[directional_shadow_count++]=E->get();
+
+ }
+
+ //add to list
+
+ directional_light_ptr[directional_light_count++]=light->instance;
+ }
+
+ VSG::scene_render->set_directional_shadow_count(directional_shadow_count);
+
+ for(int i=0;i<directional_shadow_count;i++) {
+
+ _light_instance_update_shadow(lights_with_shadow[i],p_cam_transform,p_cam_projection,p_cam_orthogonal,p_shadow_atlas,scenario);
+
+ }
+ }
+
+
+ { //setup shadow maps
+
+ //SortArray<Instance*,_InstanceLightsort> sorter;
+ //sorter.sort(light_cull_result,light_cull_count);
+ for (int i=0;i<light_cull_count;i++) {
+
+ Instance *ins = light_cull_result[i];
+
+ if (!p_shadow_atlas.is_valid() || !VSG::storage->light_has_shadow(ins->base))
+ continue;
+
+ InstanceLightData * light = static_cast<InstanceLightData*>(ins->base_data);
+
+ float coverage;
+
+ { //compute coverage
+
+
+ Transform cam_xf = p_cam_transform;
+ float zn = p_cam_projection.get_z_near();
+ Plane p (cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2) ); //camera near plane
+
+ float vp_w,vp_h; //near plane size in screen coordinates
+ p_cam_projection.get_viewport_size(vp_w,vp_h);
+
+
+ switch(VSG::storage->light_get_type(ins->base)) {
+
+ case VS::LIGHT_OMNI: {
+
+ float radius = VSG::storage->light_get_param(ins->base,VS::LIGHT_PARAM_RANGE);
+
+ //get two points parallel to near plane
+ Vector3 points[2]={
+ ins->transform.origin,
+ ins->transform.origin+cam_xf.basis.get_axis(0)*radius
+ };
+
+ if (!p_cam_orthogonal) {
+ //if using perspetive, map them to near plane
+ for(int j=0;j<2;j++) {
+ if (p.distance_to(points[j]) < 0 ) {
+ points[j].z=-zn; //small hack to keep size constant when hitting the screen
+
+ }
+
+ p.intersects_segment(cam_xf.origin,points[j],&points[j]); //map to plane
+ }
+
+
+ }
+
+ float screen_diameter = points[0].distance_to(points[1])*2;
+ coverage = screen_diameter / (vp_w+vp_h);
+ } break;
+ case VS::LIGHT_SPOT: {
+
+ float radius = VSG::storage->light_get_param(ins->base,VS::LIGHT_PARAM_RANGE);
+ float angle = VSG::storage->light_get_param(ins->base,VS::LIGHT_PARAM_SPOT_ANGLE);
+
+
+ float w = radius*Math::sin(Math::deg2rad(angle));
+ float d = radius*Math::cos(Math::deg2rad(angle));
+
+
+ Vector3 base = ins->transform.origin-ins->transform.basis.get_axis(2).normalized()*d;
+
+ Vector3 points[2]={
+ base,
+ base+cam_xf.basis.get_axis(0)*w
+ };
+
+ if (!p_cam_orthogonal) {
+ //if using perspetive, map them to near plane
+ for(int j=0;j<2;j++) {
+ if (p.distance_to(points[j]) < 0 ) {
+ points[j].z=-zn; //small hack to keep size constant when hitting the screen
+
+ }
+
+ p.intersects_segment(cam_xf.origin,points[j],&points[j]); //map to plane
+ }
+
+
+ }
+
+ float screen_diameter = points[0].distance_to(points[1])*2;
+ coverage = screen_diameter / (vp_w+vp_h);
+
+
+ } break;
+ default: {
+ ERR_PRINT("Invalid Light Type");
+ }
+ }
+
+ }
+
+
+ if (light->shadow_dirty) {
+ light->last_version++;
+ light->shadow_dirty=false;
+ }
+
+
+ bool redraw = VSG::scene_render->shadow_atlas_update_light(p_shadow_atlas,light->instance,coverage,light->last_version);
+
+ if (redraw) {
+ //must redraw!
+ _light_instance_update_shadow(ins,p_cam_transform,p_cam_projection,p_cam_orthogonal,p_shadow_atlas,scenario);
+ }
+
+ }
+ }
+
+ /* ENVIRONMENT */
+
+ RID environment;
+ if (p_force_environment.is_valid()) //camera has more environment priority
+ environment=p_force_environment;
+ else if (scenario->environment.is_valid())
+ environment=scenario->environment;
+ else
+ environment=scenario->fallback_environment;
+
+#if 0
+ /* STEP 6 - SAMPLE BAKED LIGHT */
+
+ bool islinear =false;
+ if (environment.is_valid()) {
+ islinear = rasterizer->environment_is_fx_enabled(environment,VS::ENV_FX_SRGB);
+ }
+
+ for(int i=0;i<light_samplers_culled;i++) {
+
+ _process_sampled_light(camera->transform,light_sampler_cull_result[i],islinear);
+ }
+#endif
+ /* STEP 7 - PROCESS GEOMETRY AND DRAW SCENE*/
+
+ VSG::scene_render->render_scene(p_cam_transform, p_cam_projection,p_cam_orthogonal,(RasterizerScene::InstanceBase**)instance_cull_result,cull_count,light_instance_cull_result,light_cull_count+directional_light_count,reflection_probe_instance_cull_result,reflection_probe_cull_count,environment,p_shadow_atlas,scenario->reflection_atlas,p_reflection_probe,p_reflection_probe_pass);
+
+
+}
+
+bool VisualServerScene::_render_reflection_probe_step(Instance* p_instance,int p_step) {
+
+ InstanceReflectionProbeData *reflection_probe = static_cast<InstanceReflectionProbeData*>(p_instance->base_data);
+ Scenario *scenario = p_instance->scenario;
+ ERR_FAIL_COND_V(!scenario,true);
+
+ if (p_step==0) {
+
+ if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance,scenario->reflection_atlas)) {
+ return true; //sorry, all full :(
+ }
+ }
+
+ if (p_step>=0 && p_step<6) {
+
+ static const Vector3 view_normals[6]={
+ Vector3(-1, 0, 0),
+ Vector3(+1, 0, 0),
+ Vector3( 0,-1, 0),
+ Vector3( 0,+1, 0),
+ Vector3( 0, 0,-1),
+ Vector3( 0, 0,+1)
+ };
+
+ Vector3 extents = VSG::storage->reflection_probe_get_extents(p_instance->base);
+ Vector3 origin_offset = VSG::storage->reflection_probe_get_origin_offset(p_instance->base);
+ float max_distance = VSG::storage->reflection_probe_get_origin_max_distance(p_instance->base);
+
+
+ Vector3 edge = view_normals[p_step]*extents;
+ float distance = ABS(view_normals[p_step].dot(edge)-view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit
+
+ max_distance = MAX(max_distance,distance);
+
+
+ //render cubemap side
+ CameraMatrix cm;
+ cm.set_perspective(90,1,0.01,max_distance);
+
+
+ static const Vector3 view_up[6]={
+ Vector3( 0,-1, 0),
+ Vector3( 0,-1, 0),
+ Vector3( 0, 0,-1),
+ Vector3( 0, 0,+1),
+ Vector3( 0,-1, 0),
+ Vector3( 0,-1, 0)
+ };
+
+ Transform local_view;
+ local_view.set_look_at(origin_offset,origin_offset+view_normals[p_step],view_up[p_step]);
+
+ Transform xform = p_instance->transform * local_view;
+
+ RID shadow_atlas;
+
+ if (VSG::storage->reflection_probe_renders_shadows(p_instance->base)) {
+
+ shadow_atlas=scenario->reflection_probe_shadow_atlas;
+ }
+
+ _render_scene(xform,cm,false,RID(),VSG::storage->reflection_probe_get_cull_mask(p_instance->base),p_instance->scenario->self,shadow_atlas,reflection_probe->instance,p_step);
+
+ } else {
+ //do roughness postprocess step until it belives it's done
+ return VSG::scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance);
+ }
+
+ return false;
+}
+
+void VisualServerScene::_gi_probe_fill_local_data(int p_idx, int p_level, int p_x, int p_y, int p_z, const GIProbeDataCell* p_cell, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, Vector<uint32_t> *prev_cell) {
+
+ if (p_level==p_header->cell_subdiv-1) {
+
+ Vector3 emission;
+ emission.x=(p_cell[p_idx].emission>>24)/255.0;
+ emission.y=((p_cell[p_idx].emission>>16)&0xFF)/255.0;
+ emission.z=((p_cell[p_idx].emission>>8)&0xFF)/255.0;
+ float l = (p_cell[p_idx].emission&0xFF)/255.0;
+ l*=8.0;
+
+ emission*=l;
+
+ p_local_data[p_idx].energy[0]=uint16_t(emission.x*1024); //go from 0 to 1024 for light
+ p_local_data[p_idx].energy[1]=uint16_t(emission.y*1024); //go from 0 to 1024 for light
+ p_local_data[p_idx].energy[2]=uint16_t(emission.z*1024); //go from 0 to 1024 for light
+ } else {
+
+ p_local_data[p_idx].energy[0]=0;
+ p_local_data[p_idx].energy[1]=0;
+ p_local_data[p_idx].energy[2]=0;
+
+ int half=(1<<(p_header->cell_subdiv-1))>>(p_level+1);
+
+ for(int i=0;i<8;i++) {
+
+ uint32_t child = p_cell[p_idx].children[i];
+
+ if (child==0xFFFFFFFF)
+ continue;
+
+ int x = p_x;
+ int y = p_y;
+ int z = p_z;
+
+ if (i&1)
+ x+=half;
+ if (i&2)
+ y+=half;
+ if (i&4)
+ z+=half;
+
+ _gi_probe_fill_local_data(child,p_level+1,x,y,z,p_cell,p_header,p_local_data,prev_cell);
+ }
+ }
+
+ //position for each part of the mipmaped texture
+ p_local_data[p_idx].pos[0]=p_x>>(p_header->cell_subdiv-p_level-1);
+ p_local_data[p_idx].pos[1]=p_y>>(p_header->cell_subdiv-p_level-1);
+ p_local_data[p_idx].pos[2]=p_z>>(p_header->cell_subdiv-p_level-1);
+
+ prev_cell[p_level].push_back(p_idx);
+
+}
+
+
+void VisualServerScene::_gi_probe_bake_threads(void* self) {
+
+ VisualServerScene* vss = (VisualServerScene*)self;
+ vss->_gi_probe_bake_thread();
+}
+
+void VisualServerScene::_setup_gi_probe(Instance *p_instance) {
+
+
+ InstanceGIProbeData *probe = static_cast<InstanceGIProbeData*>(p_instance->base_data);
+
+ if (probe->dynamic.probe_data.is_valid()) {
+ VSG::storage->free(probe->dynamic.probe_data);
+ probe->dynamic.probe_data=RID();
+ }
+
+ probe->dynamic.light_data=VSG::storage->gi_probe_get_dynamic_data(p_instance->base);
+
+ if (probe->dynamic.light_data.size()==0)
+ return;
+ //using dynamic data
+ PoolVector<int>::Read r=probe->dynamic.light_data.read();
+
+ const GIProbeDataHeader *header = (GIProbeDataHeader *)r.ptr();
+
+ probe->dynamic.local_data.resize(header->cell_count);
+
+ int cell_count = probe->dynamic.local_data.size();
+ PoolVector<InstanceGIProbeData::LocalData>::Write ldw = probe->dynamic.local_data.write();
+ const GIProbeDataCell *cells = (GIProbeDataCell*)&r[16];
+
+ probe->dynamic.level_cell_lists.resize(header->cell_subdiv);
+
+ _gi_probe_fill_local_data(0,0,0,0,0,cells,header,ldw.ptr(),probe->dynamic.level_cell_lists.ptr());
+
+ bool compress = VSG::storage->gi_probe_is_compressed(p_instance->base);
+
+ probe->dynamic.compression = compress ? VSG::storage->gi_probe_get_dynamic_data_get_preferred_compression() : RasterizerStorage::GI_PROBE_UNCOMPRESSED;
+
+ probe->dynamic.probe_data=VSG::storage->gi_probe_dynamic_data_create(header->width,header->height,header->depth,probe->dynamic.compression);
+
+ probe->dynamic.bake_dynamic_range=VSG::storage->gi_probe_get_dynamic_range(p_instance->base);
+
+ probe->dynamic.mipmaps_3d.clear();
+ probe->dynamic.propagate=VSG::storage->gi_probe_get_propagation(p_instance->base);
+
+ probe->dynamic.grid_size[0]=header->width;
+ probe->dynamic.grid_size[1]=header->height;
+ probe->dynamic.grid_size[2]=header->depth;
+
+ int size_limit = 1;
+ int size_divisor = 1;
+
+ if (probe->dynamic.compression==RasterizerStorage::GI_PROBE_S3TC) {
+ print_line("S3TC");
+ size_limit=4;
+ size_divisor=4;
+ }
+ for(int i=0;i<(int)header->cell_subdiv;i++) {
+
+ uint32_t x = header->width >> i;
+ uint32_t y = header->height >> i;
+ uint32_t z = header->depth >> i;
+
+ //create and clear mipmap
+ PoolVector<uint8_t> mipmap;
+ int size = x*y*z*4;
+ size/=size_divisor;
+ mipmap.resize(size);
+ PoolVector<uint8_t>::Write w = mipmap.write();
+ zeromem(w.ptr(),size);
+ w = PoolVector<uint8_t>::Write();
+
+ probe->dynamic.mipmaps_3d.push_back(mipmap);
+
+ if (x<=size_limit || y<=size_limit || z<=size_limit)
+ break;
+ }
+
+ probe->dynamic.updating_stage=GI_UPDATE_STAGE_CHECK;
+ probe->invalid=false;
+ probe->dynamic.enabled=true;
+
+ Transform cell_to_xform = VSG::storage->gi_probe_get_to_cell_xform(p_instance->base);
+ Rect3 bounds = VSG::storage->gi_probe_get_bounds(p_instance->base);
+ float cell_size = VSG::storage->gi_probe_get_cell_size(p_instance->base);
+
+ probe->dynamic.light_to_cell_xform=cell_to_xform * p_instance->transform.affine_inverse();
+
+ VSG::scene_render->gi_probe_instance_set_light_data(probe->probe_instance,p_instance->base,probe->dynamic.probe_data);
+ VSG::scene_render->gi_probe_instance_set_transform_to_data(probe->probe_instance,probe->dynamic.light_to_cell_xform);
+
+ VSG::scene_render->gi_probe_instance_set_bounds(probe->probe_instance,bounds.size/cell_size);
+
+ probe->base_version=VSG::storage->gi_probe_get_version(p_instance->base);
+
+ //if compression is S3TC, fill it up
+ if (probe->dynamic.compression==RasterizerStorage::GI_PROBE_S3TC) {
+
+ //create all blocks
+ Vector<Map<uint32_t,InstanceGIProbeData::CompBlockS3TC> > comp_blocks;
+ int mipmap_count = probe->dynamic.mipmaps_3d.size();
+ comp_blocks.resize(mipmap_count);
+
+ for(int i=0;i<cell_count;i++) {
+
+ const GIProbeDataCell &c = cells[i];
+ const InstanceGIProbeData::LocalData &ld = ldw[i];
+ int level = c.level_alpha>>16;
+ int mipmap = header->cell_subdiv - level -1;
+ if (mipmap >= mipmap_count)
+ continue;//uninteresting
+
+
+ int blockx = (ld.pos[0]>>2);
+ int blocky = (ld.pos[1]>>2);
+ int blockz = (ld.pos[2]); //compression is x/y only
+
+ int blockw = (header->width >> mipmap) >> 2;
+ int blockh = (header->height >> mipmap) >> 2;
+
+ //print_line("cell "+itos(i)+" level "+itos(level)+"mipmap: "+itos(mipmap)+" pos: "+Vector3(blockx,blocky,blockz)+" size "+Vector2(blockw,blockh));
+
+ uint32_t key = blockz * blockw*blockh + blocky * blockw + blockx;
+
+ Map<uint32_t,InstanceGIProbeData::CompBlockS3TC> & cmap = comp_blocks[mipmap];
+
+ if (!cmap.has(key)) {
+
+ InstanceGIProbeData::CompBlockS3TC k;
+ k.offset=key; //use offset as counter first
+ k.source_count=0;
+ cmap[key]=k;
+ }
+
+ InstanceGIProbeData::CompBlockS3TC &k=cmap[key];
+ ERR_CONTINUE(k.source_count==16);
+ k.sources[k.source_count++]=i;
+ }
+
+ //fix the blocks, precomputing what is needed
+ probe->dynamic.mipmaps_s3tc.resize(mipmap_count);
+
+ for(int i=0;i<mipmap_count;i++) {
+ print_line("S3TC level: "+itos(i)+" blocks: "+itos(comp_blocks[i].size()));
+ probe->dynamic.mipmaps_s3tc[i].resize(comp_blocks[i].size());
+ PoolVector<InstanceGIProbeData::CompBlockS3TC>::Write w = probe->dynamic.mipmaps_s3tc[i].write();
+ int block_idx=0;
+
+ for (Map<uint32_t,InstanceGIProbeData::CompBlockS3TC>::Element *E=comp_blocks[i].front();E;E=E->next()) {
+
+ InstanceGIProbeData::CompBlockS3TC k = E->get();
+
+ //PRECOMPUTE ALPHA
+ int max_alpha=-100000;
+ int min_alpha=k.source_count==16 ?100000 :0; //if the block is not completely full, minimum is always 0, (and those blocks will map to 1, which will be zero)
+
+ uint8_t alpha_block[4][4]={ {0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0} };
+
+ for(int j=0;j<k.source_count;j++) {
+
+ int alpha = (cells[k.sources[j]].level_alpha>>8)&0xFF;
+ if (alpha<min_alpha)
+ min_alpha=alpha;
+ if (alpha>max_alpha)
+ max_alpha=alpha;
+ //fill up alpha block
+ alpha_block[ldw[k.sources[j]].pos[0]%4][ldw[k.sources[j]].pos[1]%4]=alpha;
+
+ }
+
+ //use the first mode (8 adjustable levels)
+ k.alpha[0]=max_alpha;
+ k.alpha[1]=min_alpha;
+
+ uint64_t alpha_bits=0;
+
+ if (max_alpha!=min_alpha) {
+
+ int idx=0;
+
+ for(int y=0;y<4;y++) {
+ for(int x=0;x<4;x++) {
+
+ //substract minimum
+ uint32_t a = uint32_t(alpha_block[x][y])-min_alpha;
+ //convert range to 3 bits
+ a =int((a * 7.0 / (max_alpha-min_alpha))+0.5);
+ a = CLAMP(a,0,7); //just to be sure
+ a = 7-a; //because range is inverted in this mode
+ if (a==0) {
+ //do none, remain
+ } else if (a==7) {
+ a=1;
+ } else {
+ a=a+1;
+ }
+
+ alpha_bits|=uint64_t(a)<<(idx*3);
+ idx++;
+ }
+ }
+ }
+
+ k.alpha[2]=(alpha_bits >> 0)&0xFF;
+ k.alpha[3]=(alpha_bits >> 8)&0xFF;
+ k.alpha[4]=(alpha_bits >> 16)&0xFF;
+ k.alpha[5]=(alpha_bits >> 24)&0xFF;
+ k.alpha[6]=(alpha_bits >> 32)&0xFF;
+ k.alpha[7]=(alpha_bits >> 40)&0xFF;
+
+ w[block_idx++]=k;
+
+ }
+
+ }
+ }
+
+}
+
+void VisualServerScene::_gi_probe_bake_thread() {
+
+ while(true) {
+
+ probe_bake_sem->wait();
+ if (probe_bake_thread_exit) {
+ break;
+ }
+
+ Instance* to_bake=NULL;
+
+ probe_bake_mutex->lock();
+
+ if (!probe_bake_list.empty()) {
+ to_bake=probe_bake_list.front()->get();
+ probe_bake_list.pop_front();
+
+ }
+ probe_bake_mutex->unlock();
+
+ if (!to_bake)
+ continue;
+
+ _bake_gi_probe(to_bake);
+ }
+}
+
+
+
+uint32_t VisualServerScene::_gi_bake_find_cell(const GIProbeDataCell *cells,int x,int y, int z,int p_cell_subdiv) {
+
+
+ uint32_t cell=0;
+
+ int ofs_x=0;
+ int ofs_y=0;
+ int ofs_z=0;
+ int size = 1<<(p_cell_subdiv-1);
+ int half=size/2;
+
+ if (x<0 || x>=size)
+ return -1;
+ if (y<0 || y>=size)
+ return -1;
+ if (z<0 || z>=size)
+ return -1;
+
+ for(int i=0;i<p_cell_subdiv-1;i++) {
+
+ const GIProbeDataCell *bc = &cells[cell];
+
+ int child = 0;
+ if (x >= ofs_x + half) {
+ child|=1;
+ ofs_x+=half;
+ }
+ if (y >= ofs_y + half) {
+ child|=2;
+ ofs_y+=half;
+ }
+ if (z >= ofs_z + half) {
+ child|=4;
+ ofs_z+=half;
+ }
+
+ cell = bc->children[child];
+ if (cell==0xFFFFFFFF)
+ return 0xFFFFFFFF;
+
+ half>>=1;
+ }
+
+ return cell;
+
+}
+
+static float _get_normal_advance(const Vector3& p_normal ) {
+
+ Vector3 normal = p_normal;
+ Vector3 unorm = normal.abs();
+
+ if ( (unorm.x >= unorm.y) && (unorm.x >= unorm.z) ) {
+ // x code
+ unorm = normal.x > 0.0 ? Vector3( 1.0, 0.0, 0.0 ) : Vector3( -1.0, 0.0, 0.0 ) ;
+ } else if ( (unorm.y > unorm.x) && (unorm.y >= unorm.z) ) {
+ // y code
+ unorm = normal.y > 0.0 ? Vector3( 0.0, 1.0, 0.0 ) : Vector3( 0.0, -1.0, 0.0 ) ;
+ } else if ( (unorm.z > unorm.x) && (unorm.z > unorm.y) ) {
+ // z code
+ unorm = normal.z > 0.0 ? Vector3( 0.0, 0.0, 1.0 ) : Vector3( 0.0, 0.0, -1.0 ) ;
+ } else {
+ // oh-no we messed up code
+ // has to be
+ unorm = Vector3( 1.0, 0.0, 0.0 );
+ }
+
+ return 1.0/normal.dot(unorm);
+
+}
+
+void VisualServerScene::_bake_gi_probe_light(const GIProbeDataHeader *header,const GIProbeDataCell *cells,InstanceGIProbeData::LocalData *local_data,const uint32_t *leaves,int leaf_count, const InstanceGIProbeData::LightCache& light_cache,int sign) {
+
+
+ int light_r = int(light_cache.color.r * light_cache.energy * 1024.0)*sign;
+ int light_g = int(light_cache.color.g * light_cache.energy * 1024.0)*sign;
+ int light_b = int(light_cache.color.b * light_cache.energy * 1024.0)*sign;
+
+ float limits[3]={float(header->width),float(header->height),float(header->depth)};
+ Plane clip[3];
+ int clip_planes=0;
+
+
+
+ switch(light_cache.type) {
+
+ case VS::LIGHT_DIRECTIONAL: {
+
+ float max_len = Vector3(limits[0],limits[1],limits[2]).length()*1.1;
+
+ Vector3 light_axis = -light_cache.transform.basis.get_axis(2).normalized();
+
+ for(int i=0;i<3;i++) {
+
+ if (ABS(light_axis[i])<CMP_EPSILON)
+ continue;
+ clip[clip_planes].normal[i]=1.0;
+
+ if (light_axis[i]<0) {
+
+ clip[clip_planes].d=limits[i]+1;
+ } else {
+ clip[clip_planes].d-=1.0;
+ }
+
+ clip_planes++;
+ }
+
+ float distance_adv = _get_normal_advance(light_axis);
+
+ int success_count=0;
+
+ uint64_t us = OS::get_singleton()->get_ticks_usec();
+
+ for(int i=0;i<leaf_count;i++) {
+
+ uint32_t idx = leaves[i];
+
+ const GIProbeDataCell *cell = &cells[idx];
+ InstanceGIProbeData::LocalData *light = &local_data[idx];
+
+ Vector3 to(light->pos[0]+0.5,light->pos[1]+0.5,light->pos[2]+0.5);
+ Vector3 norm (
+ (((cells[idx].normal>>16)&0xFF)/255.0)*2.0-1.0,
+ (((cells[idx].normal>>8)&0xFF)/255.0)*2.0-1.0,
+ (((cells[idx].normal>>0)&0xFF)/255.0)*2.0-1.0
+ );
+
+
+ float att = norm.dot(-light_axis);
+ if (att<0.001) {
+ //not lighting towards this
+ continue;
+ }
+
+ Vector3 from = to - max_len * light_axis;
+
+ for(int j=0;j<clip_planes;j++) {
+
+ clip[j].intersects_segment(from,to,&from);
+ }
+
+ float distance = (to - from).length();
+ distance+=distance_adv-Math::fmod(distance,distance_adv); //make it reach the center of the box always
+ from = to - light_axis * distance;
+
+ uint32_t result=0xFFFFFFFF;
+
+ while(distance>-distance_adv) { //use this to avoid precision errors
+
+ result = _gi_bake_find_cell(cells,int(floor(from.x)),int(floor(from.y)),int(floor(from.z)),header->cell_subdiv);
+ if (result!=0xFFFFFFFF) {
+ break;
+ }
+
+ from+=light_axis*distance_adv;
+ distance-=distance_adv;
+ }
+
+ if (result==idx) {
+ //cell hit itself! hooray!
+ light->energy[0]+=int32_t(light_r*att*((cell->albedo>>16)&0xFF)/255.0);
+ light->energy[1]+=int32_t(light_g*att*((cell->albedo>>8)&0xFF)/255.0);
+ light->energy[2]+=int32_t(light_b*att*((cell->albedo)&0xFF)/255.0);
+ success_count++;
+ }
+ }
+ print_line("BAKE TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0));
+ print_line("valid cells: "+itos(success_count));
+
+
+ } break;
+ case VS::LIGHT_OMNI:
+ case VS::LIGHT_SPOT: {
+
+
+ uint64_t us = OS::get_singleton()->get_ticks_usec();
+
+ Vector3 light_pos = light_cache.transform.origin;
+ Vector3 spot_axis = -light_cache.transform.basis.get_axis(2).normalized();
+
+
+ float local_radius = light_cache.radius * light_cache.transform.basis.get_axis(2).length();
+
+ for(int i=0;i<leaf_count;i++) {
+
+ uint32_t idx = leaves[i];
+
+ const GIProbeDataCell *cell = &cells[idx];
+ InstanceGIProbeData::LocalData *light = &local_data[idx];
+
+ Vector3 to(light->pos[0]+0.5,light->pos[1]+0.5,light->pos[2]+0.5);
+ Vector3 norm (
+ (((cells[idx].normal>>16)&0xFF)/255.0)*2.0-1.0,
+ (((cells[idx].normal>>8)&0xFF)/255.0)*2.0-1.0,
+ (((cells[idx].normal>>0)&0xFF)/255.0)*2.0-1.0
+ );
+
+ Vector3 light_axis = (to - light_pos).normalized();
+ float distance_adv = _get_normal_advance(light_axis);
+
+ float att = norm.dot(-light_axis);
+ if (att<0.001) {
+ //not lighting towards this
+ continue;
+ }
+
+ {
+ float d = light_pos.distance_to(to);
+ if (d+distance_adv > local_radius)
+ continue; // too far away
+
+ float dt = CLAMP((d+distance_adv)/local_radius,0,1);
+ att*= powf(1.0-dt,light_cache.attenuation);
+ }
+
+
+ if (light_cache.type==VS::LIGHT_SPOT) {
+
+ float angle = Math::rad2deg(acos(light_axis.dot(spot_axis)));
+ if (angle > light_cache.spot_angle)
+ continue;
+
+ float d = CLAMP(angle/light_cache.spot_angle,1,0);
+ att*= powf(1.0-d,light_cache.spot_attenuation);
+
+ }
+
+ clip_planes=0;
+
+ for(int c=0;c<3;c++) {
+
+ if (ABS(light_axis[c])<CMP_EPSILON)
+ continue;
+ clip[clip_planes].normal[c]=1.0;
+
+ if (light_axis[c]<0) {
+
+ clip[clip_planes].d=limits[c]+1;
+ } else {
+ clip[clip_planes].d-=1.0;
+ }
+
+ clip_planes++;
+ }
+
+ Vector3 from = light_pos;
+
+ for(int j=0;j<clip_planes;j++) {
+
+ clip[j].intersects_segment(from,to,&from);
+ }
+
+ float distance = (to - from).length();
+
+
+
+ distance-=Math::fmod(distance,distance_adv); //make it reach the center of the box always, but this tame make it closer
+ from = to - light_axis * distance;
+
+ uint32_t result=0xFFFFFFFF;
+
+ while(distance>-distance_adv) { //use this to avoid precision errors
+
+ result = _gi_bake_find_cell(cells,int(floor(from.x)),int(floor(from.y)),int(floor(from.z)),header->cell_subdiv);
+ if (result!=0xFFFFFFFF) {
+ break;
+ }
+
+ from+=light_axis*distance_adv;
+ distance-=distance_adv;
+ }
+
+ if (result==idx) {
+ //cell hit itself! hooray!
+
+ light->energy[0]+=int32_t(light_r*att*((cell->albedo>>16)&0xFF)/255.0);
+ light->energy[1]+=int32_t(light_g*att*((cell->albedo>>8)&0xFF)/255.0);
+ light->energy[2]+=int32_t(light_b*att*((cell->albedo)&0xFF)/255.0);
+
+ }
+ }
+ print_line("BAKE TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0));
+
+
+ } break;
+ }
+}
+
+
+void VisualServerScene::_bake_gi_downscale_light(int p_idx, int p_level, const GIProbeDataCell* p_cells, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data,float p_propagate) {
+
+ //average light to upper level
+
+ float divisor=0;
+ float sum[3]={0.0,0.0,0.0};
+
+ for(int i=0;i<8;i++) {
+
+ uint32_t child = p_cells[p_idx].children[i];
+
+ if (child==0xFFFFFFFF)
+ continue;
+
+ if (p_level+1 < (int)p_header->cell_subdiv-1) {
+ _bake_gi_downscale_light(child,p_level+1,p_cells,p_header,p_local_data,p_propagate);
+ }
+
+ sum[0]+=p_local_data[child].energy[0];
+ sum[1]+=p_local_data[child].energy[1];
+ sum[2]+=p_local_data[child].energy[2];
+ divisor+=1.0;
+
+ }
+
+ divisor=Math::lerp((float)8.0,divisor,p_propagate);
+ sum[0]/=divisor;
+ sum[1]/=divisor;
+ sum[2]/=divisor;
+
+ //divide by eight for average
+ p_local_data[p_idx].energy[0]=Math::fast_ftoi(sum[0]);
+ p_local_data[p_idx].energy[1]=Math::fast_ftoi(sum[1]);
+ p_local_data[p_idx].energy[2]=Math::fast_ftoi(sum[2]);
+
+}
+
+
+void VisualServerScene::_bake_gi_probe(Instance *p_gi_probe) {
+
+ InstanceGIProbeData * probe_data = static_cast<InstanceGIProbeData*>(p_gi_probe->base_data);
+
+ PoolVector<int>::Read r=probe_data->dynamic.light_data.read();
+
+ const GIProbeDataHeader *header = (const GIProbeDataHeader *)r.ptr();
+ const GIProbeDataCell *cells = (const GIProbeDataCell*)&r[16];
+
+ int leaf_count = probe_data->dynamic.level_cell_lists[ header->cell_subdiv -1 ].size();
+ const uint32_t *leaves = probe_data->dynamic.level_cell_lists[ header->cell_subdiv -1 ].ptr();
+
+ PoolVector<InstanceGIProbeData::LocalData>::Write ldw = probe_data->dynamic.local_data.write();
+
+ InstanceGIProbeData::LocalData *local_data = ldw.ptr();
+
+
+ //remove what must be removed
+ for (Map<RID,InstanceGIProbeData::LightCache>::Element *E=probe_data->dynamic.light_cache.front();E;E=E->next()) {
+
+ RID rid = E->key();
+ const InstanceGIProbeData::LightCache& lc = E->get();
+
+ if (!probe_data->dynamic.light_cache_changes.has(rid) || !(probe_data->dynamic.light_cache_changes[rid]==lc)) {
+ //erase light data
+
+ _bake_gi_probe_light(header,cells,local_data,leaves,leaf_count,lc,-1);
+ }
+
+ }
+
+ //add what must be added
+ for (Map<RID,InstanceGIProbeData::LightCache>::Element *E=probe_data->dynamic.light_cache_changes.front();E;E=E->next()) {
+
+ RID rid = E->key();
+ const InstanceGIProbeData::LightCache& lc = E->get();
+
+ if (!probe_data->dynamic.light_cache.has(rid) || !(probe_data->dynamic.light_cache[rid]==lc)) {
+ //add light data
+
+ _bake_gi_probe_light(header,cells,local_data,leaves,leaf_count,lc,1);
+ }
+ }
+
+ SWAP(probe_data->dynamic.light_cache_changes,probe_data->dynamic.light_cache);
+
+ //downscale to lower res levels
+ _bake_gi_downscale_light(0,0,cells,header,local_data,probe_data->dynamic.propagate);
+
+ //plot result to 3D texture!
+
+ if (probe_data->dynamic.compression==RasterizerStorage::GI_PROBE_UNCOMPRESSED) {
+
+ for(int i=0;i<(int)header->cell_subdiv;i++) {
+
+ int stage = header->cell_subdiv - i -1;
+
+ if (stage >= probe_data->dynamic.mipmaps_3d.size())
+ continue; //no mipmap for this one
+
+ print_line("generating mipmap stage: "+itos(stage));
+ int level_cell_count = probe_data->dynamic.level_cell_lists[ i ].size();
+ const uint32_t *level_cells = probe_data->dynamic.level_cell_lists[ i ].ptr();
+
+ PoolVector<uint8_t>::Write lw = probe_data->dynamic.mipmaps_3d[stage].write();
+ uint8_t *mipmapw = lw.ptr();
+
+ uint32_t sizes[3]={header->width>>stage,header->height>>stage,header->depth>>stage};
+
+ for(int j=0;j<level_cell_count;j++) {
+
+ uint32_t idx = level_cells[j];
+
+ uint32_t r = (uint32_t(local_data[idx].energy[0])/probe_data->dynamic.bake_dynamic_range)>>2;
+ uint32_t g = (uint32_t(local_data[idx].energy[1])/probe_data->dynamic.bake_dynamic_range)>>2;
+ uint32_t b = (uint32_t(local_data[idx].energy[2])/probe_data->dynamic.bake_dynamic_range)>>2;
+ uint32_t a = (cells[idx].level_alpha>>8)&0xFF;
+
+ uint32_t mm_ofs = sizes[0]*sizes[1]*(local_data[idx].pos[2]) + sizes[0]*(local_data[idx].pos[1]) + (local_data[idx].pos[0]);
+ mm_ofs*=4; //for RGBA (4 bytes)
+
+ mipmapw[mm_ofs+0]=uint8_t(CLAMP(r,0,255));
+ mipmapw[mm_ofs+1]=uint8_t(CLAMP(g,0,255));
+ mipmapw[mm_ofs+2]=uint8_t(CLAMP(b,0,255));
+ mipmapw[mm_ofs+3]=uint8_t(CLAMP(a,0,255));
+
+
+ }
+ }
+ } else if (probe_data->dynamic.compression==RasterizerStorage::GI_PROBE_S3TC) {
+
+
+ int mipmap_count = probe_data->dynamic.mipmaps_3d.size();
+
+ for(int mmi=0;mmi<mipmap_count;mmi++) {
+
+ PoolVector<uint8_t>::Write mmw = probe_data->dynamic.mipmaps_3d[mmi].write();
+ int block_count = probe_data->dynamic.mipmaps_s3tc[mmi].size();
+ PoolVector<InstanceGIProbeData::CompBlockS3TC>::Read mmr = probe_data->dynamic.mipmaps_s3tc[mmi].read();
+
+ for(int i=0;i<block_count;i++) {
+
+ const InstanceGIProbeData::CompBlockS3TC& b = mmr[i];
+
+ uint8_t *blockptr = &mmw[b.offset*16];
+ copymem(blockptr,b.alpha,8); //copy alpha part, which is precomputed
+
+ Vector3 colors[16];
+
+ for(int j=0;j<b.source_count;j++) {
+
+ colors[j].x=(local_data[b.sources[j]].energy[0]/float(probe_data->dynamic.bake_dynamic_range))/1024.0;
+ colors[j].y=(local_data[b.sources[j]].energy[1]/float(probe_data->dynamic.bake_dynamic_range))/1024.0;
+ colors[j].z=(local_data[b.sources[j]].energy[2]/float(probe_data->dynamic.bake_dynamic_range))/1024.0;
+ }
+ //super quick and dirty compression
+ //find 2 most futher apart
+ float distance=0;
+ Vector3 from,to;
+
+ if (b.source_count==16) {
+ //all cells are used so, find minmax between them
+ int further_apart[2]={0,0};
+ for(int j=0;j<b.source_count;j++) {
+ for(int k=j+1;k<b.source_count;k++) {
+ float d = colors[j].distance_squared_to(colors[k]);
+ if (d>distance) {
+ distance=d;
+ further_apart[0]=j;
+ further_apart[1]=k;
+ }
+ }
+ }
+
+ from = colors[further_apart[0]];
+ to = colors[further_apart[1]];
+
+ } else {
+ //if a block is missing, the priority is that this block remains black,
+ //otherwise the geometry will appear deformed
+ //correct shape wins over correct color in this case
+ //average all colors first
+ Vector3 average;
+
+ for(int j=0;j<b.source_count;j++) {
+ average+=colors[j];
+ }
+ average.normalize();
+ //find max distance in normal from average
+ for(int j=0;j<b.source_count;j++) {
+ float d = average.dot(colors[j]);
+ distance=MAX(d,distance);
+ }
+
+ from = Vector3(); //from black
+ to = average * distance;
+ //find max distance
+
+ }
+
+
+ int indices[16];
+ uint16_t color_0=0;
+ color_0 = CLAMP(int(from.x*31),0,31)<<11;
+ color_0 |= CLAMP(int(from.y*63),0,63)<<5;
+ color_0 |= CLAMP(int(from.z*31),0,31);
+
+ uint16_t color_1=0;
+ color_1 = CLAMP(int(to.x*31),0,31)<<11;
+ color_1 |= CLAMP(int(to.y*63),0,63)<<5;
+ color_1 |= CLAMP(int(to.z*31),0,31);
+
+ if (color_1 > color_0) {
+ SWAP(color_1,color_0);
+ SWAP(from,to);
+ }
+
+
+ if (distance>0) {
+
+ Vector3 dir = (to-from).normalized();
+
+
+ for(int j=0;j<b.source_count;j++) {
+
+ float d = (colors[j]-from).dot(dir) / distance;
+ indices[j]=int(d*3+0.5);
+
+ static const int index_swap[4]={0,3,1,2};
+
+ indices[j]=index_swap[CLAMP(indices[j],0,3)];
+
+
+ }
+ } else {
+ for(int j=0;j<b.source_count;j++) {
+ indices[j]=0;
+ }
+ }
+
+ //by default, 1 is black, otherwise it will be overriden by source
+
+ uint32_t index_block[16]={1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1 };
+
+ for(int j=0;j<b.source_count;j++) {
+
+ int x=local_data[b.sources[j]].pos[0]%4;
+ int y=local_data[b.sources[j]].pos[1]%4;
+
+ index_block[y*4+x]=indices[j];
+ }
+
+ uint32_t encode=0;
+
+ for(int j=0;j<16;j++) {
+ encode|=index_block[j]<<(j*2);
+ }
+
+ blockptr[8]=color_0&0xFF;
+ blockptr[9]=(color_0>>8)&0xFF;
+ blockptr[10]=color_1&0xFF;
+ blockptr[11]=(color_1>>8)&0xFF;
+ blockptr[12]=encode&0xFF;
+ blockptr[13]=(encode>>8)&0xFF;
+ blockptr[14]=(encode>>16)&0xFF;
+ blockptr[15]=(encode>>24)&0xFF;
+
+ }
+
+
+ }
+
+ }
+
+
+ //send back to main thread to update un little chunks
+ probe_data->dynamic.updating_stage=GI_UPDATE_STAGE_UPLOADING;
+
+}
+
+bool VisualServerScene::_check_gi_probe(Instance *p_gi_probe) {
+
+ InstanceGIProbeData * probe_data = static_cast<InstanceGIProbeData*>(p_gi_probe->base_data);
+
+ probe_data->dynamic.light_cache_changes.clear();
+
+ bool all_equal=true;
+
+
+ for (List<Instance*>::Element *E=p_gi_probe->scenario->directional_lights.front();E;E=E->next()) {
+
+ InstanceGIProbeData::LightCache lc;
+ lc.type=VSG::storage->light_get_type(E->get()->base);
+ lc.color=VSG::storage->light_get_color(E->get()->base);
+ lc.energy=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_ENERGY);
+ lc.radius=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_RANGE);
+ lc.attenuation=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_ATTENUATION);
+ lc.spot_angle=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_SPOT_ANGLE);
+ lc.spot_attenuation=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_SPOT_ATTENUATION);
+ lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform;
+
+ if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self]==lc)) {
+ all_equal=false;
+ }
+
+ probe_data->dynamic.light_cache_changes[E->get()->self]=lc;
+
+ }
+
+
+ for (Set<Instance*>::Element *E=probe_data->lights.front();E;E=E->next()) {
+
+ InstanceGIProbeData::LightCache lc;
+ lc.type=VSG::storage->light_get_type(E->get()->base);
+ lc.color=VSG::storage->light_get_color(E->get()->base);
+ lc.energy=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_ENERGY);
+ lc.radius=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_RANGE);
+ lc.attenuation=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_ATTENUATION);
+ lc.spot_angle=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_SPOT_ANGLE);
+ lc.spot_attenuation=VSG::storage->light_get_param(E->get()->base,VS::LIGHT_PARAM_SPOT_ATTENUATION);
+ lc.transform = probe_data->dynamic.light_to_cell_xform * E->get()->transform;
+
+ if (!probe_data->dynamic.light_cache.has(E->get()->self) || !(probe_data->dynamic.light_cache[E->get()->self]==lc)) {
+ all_equal=false;
+ }
+
+ probe_data->dynamic.light_cache_changes[E->get()->self]=lc;
+ }
+
+ //lighting changed from after to before, must do some updating
+ return !all_equal || probe_data->dynamic.light_cache_changes.size()!=probe_data->dynamic.light_cache.size();
+
+}
+
+void VisualServerScene::render_probes() {
+
+ /* REFLECTION PROBES */
+
+ SelfList<InstanceReflectionProbeData> *ref_probe = reflection_probe_render_list.first();
+
+ bool busy=false;
+
+ while(ref_probe) {
+
+ SelfList<InstanceReflectionProbeData> *next=ref_probe->next();
+ RID base = ref_probe->self()->owner->base;
+
+ switch(VSG::storage->reflection_probe_get_update_mode(base)) {
+
+ case VS::REFLECTION_PROBE_UPDATE_ONCE: {
+ if (busy) //already rendering something
+ break;
+
+ bool done = _render_reflection_probe_step(ref_probe->self()->owner,ref_probe->self()->render_step);
+ if (done) {
+ reflection_probe_render_list.remove(ref_probe);
+ } else {
+ ref_probe->self()->render_step++;
+ }
+
+ busy=true; //do not render another one of this kind
+ } break;
+ case VS::REFLECTION_PROBE_UPDATE_ALWAYS: {
+
+ int step=0;
+ bool done=false;
+ while(!done) {
+ done = _render_reflection_probe_step(ref_probe->self()->owner,step);
+ step++;
+ }
+
+ reflection_probe_render_list.remove(ref_probe);
+ } break;
+
+ }
+
+ ref_probe=next;
+ }
+
+ /* GI PROBES */
+
+ SelfList<InstanceGIProbeData> *gi_probe = gi_probe_update_list.first();
+
+ while(gi_probe) {
+
+ SelfList<InstanceGIProbeData> *next=gi_probe->next();
+
+ InstanceGIProbeData *probe = gi_probe->self();
+ Instance *instance_probe = probe->owner;
+
+ //check if probe must be setup, but don't do if on the lighting thread
+
+ bool force_lighting=false;
+
+ if (probe->invalid || (probe->dynamic.updating_stage==GI_UPDATE_STAGE_CHECK && probe->base_version!=VSG::storage->gi_probe_get_version(instance_probe->base))) {
+
+ _setup_gi_probe(instance_probe);
+ force_lighting=true;
+ }
+
+ float propagate = VSG::storage->gi_probe_get_propagation(instance_probe->base);
+
+ if (probe->dynamic.propagate!=propagate) {
+ probe->dynamic.propagate=propagate;
+ force_lighting=true;
+ }
+
+
+ if (probe->invalid==false && probe->dynamic.enabled) {
+
+ switch(probe->dynamic.updating_stage) {
+ case GI_UPDATE_STAGE_CHECK: {
+
+ if (_check_gi_probe(instance_probe) || force_lighting) {
+ //send to lighting thread
+ probe->dynamic.updating_stage=GI_UPDATE_STAGE_LIGHTING;
+
+#ifndef NO_THREADS
+ probe_bake_mutex->lock();
+ probe_bake_list.push_back(instance_probe);
+ probe_bake_mutex->unlock();
+ probe_bake_sem->post();
+
+#else
+
+ _bake_gi_probe(instance_probe);
+#endif
+
+ }
+ } break;
+ case GI_UPDATE_STAGE_LIGHTING: {
+ //do none, wait til done!
+
+ } break;
+ case GI_UPDATE_STAGE_UPLOADING: {
+
+ uint64_t us = OS::get_singleton()->get_ticks_usec();
+
+ for(int i=0;i<(int)probe->dynamic.mipmaps_3d.size();i++) {
+
+ int mmsize = probe->dynamic.mipmaps_3d[i].size();
+ PoolVector<uint8_t>::Read r = probe->dynamic.mipmaps_3d[i].read();
+ VSG::storage->gi_probe_dynamic_data_update(probe->dynamic.probe_data,0,probe->dynamic.grid_size[2]>>i,i,r.ptr());
+ }
+
+
+ probe->dynamic.updating_stage=GI_UPDATE_STAGE_CHECK;
+
+ //print_line("UPLOAD TIME: "+rtos((OS::get_singleton()->get_ticks_usec()-us)/1000000.0));
+ } break;
+
+ }
+ }
+ //_update_gi_probe(gi_probe->self()->owner);
+
+
+ gi_probe=next;
+ }
+
+
+
+}
+
+void VisualServerScene::_update_dirty_instance(Instance *p_instance) {
+
+ if (p_instance->update_aabb)
+ _update_instance_aabb(p_instance);
+
+
+ if (p_instance->update_materials) {
+
+ if (p_instance->base_type==VS::INSTANCE_MESH) {
+ //remove materials no longer used and un-own them
+
+ int new_mat_count = VSG::storage->mesh_get_surface_count(p_instance->base);
+ for(int i=p_instance->materials.size()-1;i>=new_mat_count;i--) {
+ if (p_instance->materials[i].is_valid()) {
+ VSG::storage->material_remove_instance_owner(p_instance->materials[i],p_instance);
+ }
+ }
+ p_instance->materials.resize(new_mat_count);
+
+ int new_blend_shape_count = VSG::storage->mesh_get_blend_shape_count(p_instance->base);
+ if (new_blend_shape_count!=p_instance->blend_values.size()) {
+ p_instance->blend_values.resize(new_blend_shape_count);
+ for(int i=0;i<new_blend_shape_count;i++) {
+ p_instance->blend_values[i]=0;
+ }
+ }
+ }
+
+ if ((1<<p_instance->base_type)&VS::INSTANCE_GEOMETRY_MASK) {
+
+ InstanceGeometryData *geom = static_cast<InstanceGeometryData*>(p_instance->base_data);
+
+ bool can_cast_shadows=true;
+
+ if (p_instance->cast_shadows==VS::SHADOW_CASTING_SETTING_OFF) {
+ can_cast_shadows=false;
+ } else if (p_instance->material_override.is_valid()) {
+ can_cast_shadows=VSG::storage->material_casts_shadows(p_instance->material_override);
+ } else {
+
+
+
+ if (p_instance->base_type==VS::INSTANCE_MESH) {
+ RID mesh=p_instance->base;
+
+ if (mesh.is_valid()) {
+ bool cast_shadows=false;
+
+ for(int i=0;i<p_instance->materials.size();i++) {
+
+
+ RID mat = p_instance->materials[i].is_valid()?p_instance->materials[i]:VSG::storage->mesh_surface_get_material(mesh,i);
+
+ if (!mat.is_valid()) {
+ cast_shadows=true;
+ break;
+ }
+
+ if (VSG::storage->material_casts_shadows(mat)) {
+ cast_shadows=true;
+ break;
+ }
+ }
+
+ if (!cast_shadows) {
+ can_cast_shadows=false;
+ }
+ }
+
+ } else if (p_instance->base_type==VS::INSTANCE_MULTIMESH) {
+ RID mesh = VSG::storage->multimesh_get_mesh(p_instance->base);
+ if (mesh.is_valid()) {
+
+ bool cast_shadows=false;
+
+ int sc = VSG::storage->mesh_get_surface_count(mesh);
+ for(int i=0;i<sc;i++) {
+
+ RID mat =VSG::storage->mesh_surface_get_material(mesh,i);
+
+ if (!mat.is_valid()) {
+ cast_shadows=true;
+ break;
+ }
+
+ if (VSG::storage->material_casts_shadows(mat)) {
+ cast_shadows=true;
+ break;
+ }
+
+ }
+
+ if (!cast_shadows) {
+ can_cast_shadows=false;
+ }
+ }
+ } else if (p_instance->base_type==VS::INSTANCE_IMMEDIATE) {
+
+ RID mat = VSG::storage->immediate_get_material(p_instance->base);
+
+ if (!mat.is_valid() || VSG::storage->material_casts_shadows(mat)) {
+ can_cast_shadows=true;
+ } else {
+ can_cast_shadows=false;
+ }
+
+
+ }
+
+
+
+ }
+
+ if (can_cast_shadows!=geom->can_cast_shadows) {
+ //ability to cast shadows change, let lights now
+ for (List<Instance*>::Element *E=geom->lighting.front();E;E=E->next()) {
+ InstanceLightData *light = static_cast<InstanceLightData*>(E->get()->base_data);
+ light->shadow_dirty=true;
+ }
+
+ geom->can_cast_shadows=can_cast_shadows;
+ }
+ }
+
+ }
+
+ _update_instance(p_instance);
+
+ p_instance->update_aabb=false;
+ p_instance->update_materials=false;
+
+ _instance_update_list.remove( &p_instance->update_item );
+}
+
+
+void VisualServerScene::update_dirty_instances() {
+
+ VSG::storage->update_dirty_resources();
+
+ while(_instance_update_list.first()) {
+
+ _update_dirty_instance( _instance_update_list.first()->self() );
+ }
+}
+
+bool VisualServerScene::free(RID p_rid) {
+
+ if (camera_owner.owns(p_rid)) {
+
+ Camera *camera = camera_owner.get( p_rid );
+
+ camera_owner.free(p_rid);
+ memdelete(camera);
+
+ } else if (scenario_owner.owns(p_rid)) {
+
+ Scenario *scenario = scenario_owner.get( p_rid );
+
+ while(scenario->instances.first()) {
+ instance_set_scenario(scenario->instances.first()->self()->self,RID());
+ }
+ VSG::scene_render->free(scenario->reflection_probe_shadow_atlas);
+ VSG::scene_render->free(scenario->reflection_atlas);
+ scenario_owner.free(p_rid);
+ memdelete(scenario);
+
+ } else if (instance_owner.owns(p_rid)) {
+ // delete the instance
+
+ update_dirty_instances();
+
+ Instance *instance = instance_owner.get(p_rid);
+
+ instance_set_room(p_rid,RID());
+ instance_set_scenario(p_rid,RID());
+ instance_set_base(p_rid,RID());
+ instance_geometry_set_material_override(p_rid,RID());
+ instance_attach_skeleton(p_rid,RID());
+
+ update_dirty_instances(); //in case something changed this
+
+ instance_owner.free(p_rid);
+ memdelete(instance);
+ } else {
+ return false;
+ }
+
+
+ return true;
+}
+
+VisualServerScene *VisualServerScene::singleton=NULL;
+
+
+VisualServerScene::VisualServerScene() {
+
+#ifndef NO_THREADS
+ probe_bake_sem = Semaphore::create();
+ probe_bake_mutex = Mutex::create();
+ probe_bake_thread = Thread::create(_gi_probe_bake_threads,this);
+ probe_bake_thread_exit=false;
+#endif
+
+
+ render_pass=1;
+ singleton=this;
+
+}
+
+VisualServerScene::~VisualServerScene() {
+
+#ifndef NO_THREADS
+ probe_bake_thread_exit=true;
+ Thread::wait_to_finish(probe_bake_thread);
+ memdelete(probe_bake_thread);
+ memdelete(probe_bake_sem);
+ memdelete(probe_bake_mutex);
+
+#endif
+
+
+}
diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h
new file mode 100644
index 0000000000..f9a5dde1ac
--- /dev/null
+++ b/servers/visual/visual_server_scene.h
@@ -0,0 +1,589 @@
+#ifndef VISUALSERVERSCENE_H
+#define VISUALSERVERSCENE_H
+
+#include "servers/visual/rasterizer.h"
+
+#include "geometry.h"
+#include "allocators.h"
+#include "octree.h"
+#include "self_list.h"
+#include "os/thread.h"
+#include "os/semaphore.h"
+#include "os/semaphore.h"
+
+class VisualServerScene {
+public:
+
+
+ enum {
+
+ MAX_INSTANCE_CULL=65536,
+ MAX_LIGHTS_CULLED=4096,
+ MAX_REFLECTION_PROBES_CULLED=4096,
+ MAX_ROOM_CULL=32,
+ MAX_EXTERIOR_PORTALS=128,
+ };
+
+ uint64_t render_pass;
+
+
+ static VisualServerScene *singleton;
+#if 0
+ struct Portal {
+
+ bool enabled;
+ float disable_distance;
+ Color disable_color;
+ float connect_range;
+ Vector<Point2> shape;
+ Rect2 bounds;
+
+
+ Portal() { enabled=true; disable_distance=50; disable_color=Color(); connect_range=0.8; }
+ };
+
+ struct BakedLight {
+
+ Rasterizer::BakedLightData data;
+ PoolVector<int> sampler;
+ AABB octree_aabb;
+ Size2i octree_tex_size;
+ Size2i light_tex_size;
+
+ };
+
+ struct BakedLightSampler {
+
+ float params[BAKED_LIGHT_SAMPLER_MAX];
+ int resolution;
+ Vector<Vector3> dp_cache;
+
+ BakedLightSampler() {
+ params[BAKED_LIGHT_SAMPLER_STRENGTH]=1.0;
+ params[BAKED_LIGHT_SAMPLER_ATTENUATION]=1.0;
+ params[BAKED_LIGHT_SAMPLER_RADIUS]=1.0;
+ params[BAKED_LIGHT_SAMPLER_DETAIL_RATIO]=0.1;
+ resolution=16;
+ }
+ };
+
+ void _update_baked_light_sampler_dp_cache(BakedLightSampler * blsamp);
+
+#endif
+
+
+ /* CAMERA API */
+
+ struct Camera : public RID_Data {
+
+ enum Type {
+ PERSPECTIVE,
+ ORTHOGONAL
+ };
+ Type type;
+ float fov;
+ float znear,zfar;
+ float size;
+ uint32_t visible_layers;
+ bool vaspect;
+ RID env;
+
+ Transform transform;
+
+ Camera() {
+
+ visible_layers=0xFFFFFFFF;
+ fov=60;
+ type=PERSPECTIVE;
+ znear=0.1; zfar=100;
+ size=1.0;
+ vaspect=false;
+
+ }
+ };
+
+ mutable RID_Owner<Camera> camera_owner;
+
+ virtual RID camera_create();
+ virtual void camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far);
+ virtual void camera_set_orthogonal(RID p_camera,float p_size, float p_z_near, float p_z_far);
+ virtual void camera_set_transform(RID p_camera,const Transform& p_transform);
+ virtual void camera_set_cull_mask(RID p_camera,uint32_t p_layers);
+ virtual void camera_set_environment(RID p_camera,RID p_env);
+ virtual void camera_set_use_vertical_aspect(RID p_camera,bool p_enable);
+
+
+ /*
+
+ struct RoomInfo {
+
+ Transform affine_inverse;
+ Room *room;
+ List<Instance*> owned_geometry_instances;
+ List<Instance*> owned_portal_instances;
+ List<Instance*> owned_room_instances;
+ List<Instance*> owned_light_instances; //not used, but just for the sake of it
+ Set<Instance*> disconnected_child_portals;
+ Set<Instance*> owned_autoroom_geometry;
+ uint64_t last_visited_pass;
+ RoomInfo() { last_visited_pass=0; }
+
+ };
+
+ struct InstancePortal {
+
+ Portal *portal;
+ Set<Instance*> candidate_set;
+ Instance *connected;
+ uint64_t last_visited_pass;
+
+ Plane plane_cache;
+ Vector<Vector3> transformed_point_cache;
+
+
+ PortalInfo() { connected=NULL; last_visited_pass=0;}
+ };
+*/
+
+
+
+ /* SCENARIO API */
+
+ struct Instance;
+
+ struct Scenario : RID_Data {
+
+
+ VS::ScenarioDebugMode debug;
+ RID self;
+ // well wtf, balloon allocator is slower?
+
+ Octree<Instance,true> octree;
+
+ List<Instance*> directional_lights;
+ RID environment;
+ RID fallback_environment;
+ RID reflection_probe_shadow_atlas;
+ RID reflection_atlas;
+
+
+ SelfList<Instance>::List instances;
+
+ Scenario() { debug=VS::SCENARIO_DEBUG_DISABLED; }
+ };
+
+ mutable RID_Owner<Scenario> scenario_owner;
+
+ static void* _instance_pair(void *p_self, OctreeElementID, Instance *p_A,int, OctreeElementID, Instance *p_B,int);
+ static void _instance_unpair(void *p_self, OctreeElementID, Instance *p_A,int, OctreeElementID, Instance *p_B,int,void*);
+
+ virtual RID scenario_create();
+
+ virtual void scenario_set_debug(RID p_scenario,VS::ScenarioDebugMode p_debug_mode);
+ virtual void scenario_set_environment(RID p_scenario, RID p_environment);
+ virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment);
+ virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size,int p_subdiv);
+
+
+ /* INSTANCING API */
+
+ struct InstanceBaseData {
+
+
+ virtual ~InstanceBaseData() {}
+ };
+
+
+
+ struct Instance : RasterizerScene::InstanceBase {
+
+ RID self;
+ //scenario stuff
+ OctreeElementID octree_id;
+ Scenario *scenario;
+ SelfList<Instance> scenario_item;
+
+ //aabb stuff
+ bool update_aabb;
+ bool update_materials;
+
+ SelfList<Instance> update_item;
+
+
+ Rect3 aabb;
+ Rect3 transformed_aabb;
+ float extra_margin;
+ uint32_t object_ID;
+
+ float lod_begin;
+ float lod_end;
+ float lod_begin_hysteresis;
+ float lod_end_hysteresis;
+ RID lod_instance;
+
+ Instance *room;
+ SelfList<Instance> room_item;
+ bool visible_in_all_rooms;
+
+ uint64_t last_render_pass;
+ uint64_t last_frame_pass;
+
+ uint64_t version; // changes to this, and changes to base increase version
+
+ InstanceBaseData *base_data;
+
+ virtual void base_removed() {
+
+ singleton->instance_set_base(self,RID());
+ }
+
+ virtual void base_changed() {
+
+ singleton->_instance_queue_update(this,true,true);
+ }
+
+ virtual void base_material_changed() {
+
+ singleton->_instance_queue_update(this,false,true);
+ }
+
+
+ Instance() : scenario_item(this), update_item(this), room_item(this) {
+
+ octree_id=0;
+ scenario=NULL;
+
+
+ update_aabb=false;
+ update_materials=false;
+
+ extra_margin=0;
+
+
+ object_ID=0;
+ visible=true;
+
+ lod_begin=0;
+ lod_end=0;
+ lod_begin_hysteresis=0;
+ lod_end_hysteresis=0;
+
+ room=NULL;
+ visible_in_all_rooms=false;
+
+
+
+ last_render_pass=0;
+ last_frame_pass=0;
+ version=1;
+ base_data=NULL;
+
+ }
+
+ ~Instance() {
+
+ if (base_data)
+ memdelete(base_data);
+
+ }
+ };
+
+ SelfList<Instance>::List _instance_update_list;
+ void _instance_queue_update(Instance *p_instance,bool p_update_aabb,bool p_update_materials=false);
+
+
+ struct InstanceGeometryData : public InstanceBaseData {
+
+ List<Instance*> lighting;
+ bool lighting_dirty;
+ bool can_cast_shadows;
+
+ List<Instance*> reflection_probes;
+ bool reflection_dirty;
+
+ List<Instance*> gi_probes;
+ bool gi_probes_dirty;
+
+ InstanceGeometryData() {
+
+ lighting_dirty=false;
+ reflection_dirty=true;
+ can_cast_shadows=true;
+ gi_probes_dirty=true;
+ }
+ };
+
+ struct InstanceReflectionProbeData : public InstanceBaseData {
+
+
+ Instance *owner;
+
+ struct PairInfo {
+ List<Instance*>::Element *L; //reflection iterator in geometry
+ Instance *geometry;
+ };
+ List<PairInfo> geometries;
+
+
+ RID instance;
+ bool reflection_dirty;
+ SelfList<InstanceReflectionProbeData> update_list;
+
+ int render_step;
+
+ InstanceReflectionProbeData() : update_list(this) {
+
+ reflection_dirty=true;
+ render_step=-1;
+ }
+ };
+
+ SelfList<InstanceReflectionProbeData>::List reflection_probe_render_list;
+
+ struct InstanceLightData : public InstanceBaseData {
+
+ struct PairInfo {
+ List<Instance*>::Element *L; //light iterator in geometry
+ Instance *geometry;
+ };
+
+ RID instance;
+ uint64_t last_version;
+ List<Instance*>::Element *D; // directional light in scenario
+
+ bool shadow_dirty;
+
+ List<PairInfo> geometries;
+
+ Instance *baked_light;
+
+ InstanceLightData() {
+
+ shadow_dirty=true;
+ D=NULL;
+ last_version=0;
+ baked_light=NULL;
+ }
+ };
+
+ struct InstanceGIProbeData : public InstanceBaseData {
+
+
+ Instance *owner;
+
+ struct PairInfo {
+ List<Instance*>::Element *L; //gi probe iterator in geometry
+ Instance *geometry;
+ };
+
+ List<PairInfo> geometries;
+
+ Set<Instance*> lights;
+
+ struct LightCache {
+
+ VS::LightType type;
+ Transform transform;
+ Color color;
+ float energy;
+ float radius;
+ float attenuation;
+ float spot_angle;
+ float spot_attenuation;
+
+ bool operator==(const LightCache& p_cache) {
+
+ return (type==p_cache.type &&
+ transform==p_cache.transform &&
+ color==p_cache.color &&
+ energy==p_cache.energy &&
+ radius==p_cache.radius &&
+ attenuation==p_cache.attenuation &&
+ spot_angle==p_cache.spot_angle &&
+ spot_attenuation==p_cache.spot_attenuation);
+ }
+
+ LightCache() {
+
+ type=VS::LIGHT_DIRECTIONAL;
+ energy=1.0;
+ radius=1.0;
+ attenuation=1.0;
+ spot_angle=1.0;
+ spot_attenuation=1.0;
+
+ }
+
+ };
+
+ struct LocalData {
+ uint16_t pos[3];
+ uint16_t energy[3]; //using 0..1024 for float range 0..1. integer is needed for deterministic add/remove of lights
+ };
+
+ struct CompBlockS3TC {
+ uint32_t offset; //offset in mipmap
+ uint32_t source_count; //sources
+ uint32_t sources[16]; //id for each source
+ uint8_t alpha[8]; //alpha block is pre-computed
+ };
+
+
+ struct Dynamic {
+
+ Map<RID,LightCache> light_cache;
+ Map<RID,LightCache> light_cache_changes;
+ PoolVector<int> light_data;
+ PoolVector<LocalData> local_data;
+ Vector<Vector<uint32_t> > level_cell_lists;
+ RID probe_data;
+ bool enabled;
+ int bake_dynamic_range;
+ RasterizerStorage::GIProbeCompression compression;
+
+ Vector< PoolVector<uint8_t> > mipmaps_3d;
+ Vector< PoolVector<CompBlockS3TC> > mipmaps_s3tc; //for s3tc
+
+ int updating_stage;
+ float propagate;
+
+ int grid_size[3];
+
+ Transform light_to_cell_xform;
+
+ } dynamic;
+
+
+ RID probe_instance;
+
+
+ bool invalid;
+ uint32_t base_version;
+
+ SelfList<InstanceGIProbeData> update_element;
+
+ InstanceGIProbeData() : update_element(this) {
+ invalid=true;
+ base_version=0;
+ }
+
+ };
+
+
+ SelfList<InstanceGIProbeData>::List gi_probe_update_list;
+
+
+ Instance *instance_cull_result[MAX_INSTANCE_CULL];
+ Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps
+ Instance *light_cull_result[MAX_LIGHTS_CULLED];
+ RID light_instance_cull_result[MAX_LIGHTS_CULLED];
+ int light_cull_count;
+ RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED];
+ int reflection_probe_cull_count;
+
+
+ RID_Owner<Instance> instance_owner;
+
+ // from can be mesh, light, area and portal so far.
+ virtual RID instance_create(); // from can be mesh, light, poly, area and portal so far.
+
+ virtual void instance_set_base(RID p_instance, RID p_base); // from can be mesh, light, poly, area and portal so far.
+ virtual void instance_set_scenario(RID p_instance, RID p_scenario); // from can be mesh, light, poly, area and portal so far.
+ virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask);
+ virtual void instance_set_transform(RID p_instance, const Transform& p_transform);
+ virtual void instance_attach_object_instance_ID(RID p_instance,ObjectID p_ID);
+ virtual void instance_set_blend_shape_weight(RID p_instance,int p_shape, float p_weight);
+ virtual void instance_set_surface_material(RID p_instance,int p_surface, RID p_material);
+ virtual void instance_set_visible(RID p_instance,bool p_visible);
+
+
+ virtual void instance_attach_skeleton(RID p_instance,RID p_skeleton);
+ virtual void instance_set_exterior( RID p_instance, bool p_enabled );
+ virtual void instance_set_room( RID p_instance, RID p_room );
+
+ virtual void instance_set_extra_visibility_margin( RID p_instance, real_t p_margin );
+
+
+ // don't use these in a game!
+ virtual Vector<ObjectID> instances_cull_aabb(const Rect3& p_aabb, RID p_scenario=RID()) const;
+ virtual Vector<ObjectID> instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario=RID()) const;
+ virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario=RID()) const;
+
+
+ virtual void instance_geometry_set_flag(RID p_instance,VS::InstanceFlags p_flags,bool p_enabled);
+ virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting);
+ virtual void instance_geometry_set_material_override(RID p_instance, RID p_material);
+
+
+ virtual void instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max,float p_min_margin,float p_max_margin);
+ virtual void instance_geometry_set_as_instance_lod(RID p_instance,RID p_as_lod_of_instance);
+
+
+ _FORCE_INLINE_ void _update_instance(Instance *p_instance);
+ _FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance);
+ _FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance);
+
+ _FORCE_INLINE_ void _light_instance_update_shadow(Instance *p_instance,const Transform p_cam_transform,const CameraMatrix& p_cam_projection,bool p_cam_orthogonal,RID p_shadow_atlas,Scenario* p_scenario);
+
+ void _render_scene(const Transform p_cam_transform, const CameraMatrix& p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass);
+
+ void render_camera(RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas);
+ void update_dirty_instances();
+
+ //probes
+ struct GIProbeDataHeader {
+
+ uint32_t version;
+ uint32_t cell_subdiv;
+ uint32_t width;
+ uint32_t height;
+ uint32_t depth;
+ uint32_t cell_count;
+ uint32_t leaf_cell_count;
+ };
+
+
+ struct GIProbeDataCell {
+
+ uint32_t children[8];
+ uint32_t albedo;
+ uint32_t emission;
+ uint32_t normal;
+ uint32_t level_alpha;
+ };
+
+ enum {
+ GI_UPDATE_STAGE_CHECK,
+ GI_UPDATE_STAGE_LIGHTING,
+ GI_UPDATE_STAGE_UPLOADING,
+ };
+
+ void _gi_probe_bake_thread();
+ static void _gi_probe_bake_threads(void*);
+
+ volatile bool probe_bake_thread_exit;
+ Thread *probe_bake_thread;
+ Semaphore *probe_bake_sem;
+ Mutex *probe_bake_mutex;
+ List<Instance*> probe_bake_list;
+
+ bool _render_reflection_probe_step(Instance* p_instance,int p_step);
+ void _gi_probe_fill_local_data(int p_idx,int p_level,int p_x,int p_y,int p_z,const GIProbeDataCell* p_cell,const GIProbeDataHeader *p_header,InstanceGIProbeData::LocalData *p_local_data,Vector<uint32_t> *prev_cell);
+
+ _FORCE_INLINE_ uint32_t _gi_bake_find_cell(const GIProbeDataCell *cells,int x,int y, int z,int p_cell_subdiv);
+ void _bake_gi_downscale_light(int p_idx, int p_level, const GIProbeDataCell* p_cells, const GIProbeDataHeader *p_header, InstanceGIProbeData::LocalData *p_local_data, float p_propagate);
+ void _bake_gi_probe_light(const GIProbeDataHeader *header,const GIProbeDataCell *cells,InstanceGIProbeData::LocalData *local_data,const uint32_t *leaves,int p_leaf_count, const InstanceGIProbeData::LightCache& light_cache,int p_sign);
+ void _bake_gi_probe(Instance *p_probe);
+ bool _check_gi_probe(Instance *p_gi_probe);
+ void _setup_gi_probe(Instance *p_instance);
+
+ void render_probes();
+
+
+ bool free(RID p_rid);
+
+ VisualServerScene();
+ ~VisualServerScene();
+};
+
+#endif // VISUALSERVERSCENE_H
diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp
new file mode 100644
index 0000000000..d32c4dd6bf
--- /dev/null
+++ b/servers/visual/visual_server_viewport.cpp
@@ -0,0 +1,568 @@
+#include "visual_server_viewport.h"
+#include "visual_server_global.h"
+#include "visual_server_canvas.h"
+#include "visual_server_scene.h"
+#include "global_config.h"
+
+
+
+void VisualServerViewport::_draw_viewport(Viewport *p_viewport) {
+
+ /* Camera should always be BEFORE any other 3D */
+#if 0
+ bool scenario_draw_canvas_bg=false;
+ int scenario_canvas_max_layer=0;
+
+ if (!p_viewport->hide_canvas && !p_viewport->disable_environment && scenario_owner.owns(p_viewport->scenario)) {
+
+ Scenario *scenario=scenario_owner.get(p_viewport->scenario);
+ if (scenario->environment.is_valid()) {
+ if (rasterizer->is_environment(scenario->environment)) {
+ scenario_draw_canvas_bg=rasterizer->environment_get_background(scenario->environment)==VS::ENV_BG_CANVAS;
+ scenario_canvas_max_layer=rasterizer->environment_get_background_param(scenario->environment,VS::ENV_BG_PARAM_CANVAS_MAX_LAYER);
+ }
+ }
+ }
+
+ bool can_draw_3d=!p_viewport->hide_scenario && camera_owner.owns(p_viewport->camera) && scenario_owner.owns(p_viewport->scenario);
+
+
+ if (scenario_draw_canvas_bg) {
+
+ rasterizer->begin_canvas_bg();
+ }
+
+ if (!scenario_draw_canvas_bg && can_draw_3d) {
+
+ _draw_viewport_camera(p_viewport,false);
+
+ } else if (true /*|| !p_viewport->canvas_list.empty()*/){
+
+ //clear the viewport black because of no camera? i seriously should..
+ if (p_viewport->render_target_clear_on_new_frame || p_viewport->render_target_clear) {
+ if (p_viewport->transparent_bg) {
+ rasterizer->clear_viewport(Color(0,0,0,0));
+ }
+ else {
+ Color cc=clear_color;
+ if (scenario_draw_canvas_bg)
+ cc.a=0;
+ rasterizer->clear_viewport(cc);
+ }
+ p_viewport->render_target_clear=false;
+ }
+ }
+#endif
+
+ if (p_viewport->clear_mode!=VS::VIEWPORT_CLEAR_NEVER) {
+ VSG::rasterizer->clear_render_target(clear_color);
+ if (p_viewport->clear_mode==VS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) {
+ p_viewport->clear_mode=VS::VIEWPORT_CLEAR_NEVER;
+ }
+ }
+
+
+ if (!p_viewport->disable_3d && p_viewport->camera.is_valid()) {
+
+ VSG::scene->render_camera(p_viewport->camera,p_viewport->scenario,p_viewport->size,p_viewport->shadow_atlas);
+ }
+
+ if (!p_viewport->hide_canvas) {
+ int i=0;
+
+ Map<Viewport::CanvasKey,Viewport::CanvasData*> canvas_map;
+
+ Rect2 clip_rect(0,0,p_viewport->size.x,p_viewport->size.y);
+ RasterizerCanvas::Light *lights=NULL;
+ RasterizerCanvas::Light *lights_with_shadow=NULL;
+ RasterizerCanvas::Light *lights_with_mask=NULL;
+ Rect2 shadow_rect;
+
+ int light_count=0;
+
+ for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) {
+
+ Transform2D xf = p_viewport->global_transform * E->get().transform;
+
+ VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas*>(E->get().canvas);
+
+ //find lights in canvas
+
+
+ for(Set<RasterizerCanvas::Light*>::Element *F=canvas->lights.front();F;F=F->next()) {
+
+
+ RasterizerCanvas::Light* cl=F->get();
+ if (cl->enabled && cl->texture.is_valid()) {
+ //not super efficient..
+ Size2 tsize(VSG::storage->texture_get_width(cl->texture),VSG::storage->texture_get_height(cl->texture));
+ tsize*=cl->scale;
+
+ Vector2 offset=tsize/2.0;
+ cl->rect_cache=Rect2(-offset+cl->texture_offset,tsize);
+ cl->xform_cache=xf * cl->xform;
+
+
+ if (clip_rect.intersects_transformed(cl->xform_cache,cl->rect_cache)) {
+
+ cl->filter_next_ptr=lights;
+ lights=cl;
+ cl->texture_cache=NULL;
+ Transform2D scale;
+ scale.scale(cl->rect_cache.size);
+ scale.elements[2]=cl->rect_cache.pos;
+ cl->light_shader_xform = (cl->xform_cache * scale).affine_inverse();
+ cl->light_shader_pos=cl->xform_cache[2];
+ if (cl->shadow_buffer.is_valid()) {
+
+ cl->shadows_next_ptr=lights_with_shadow;
+ if (lights_with_shadow==NULL) {
+ shadow_rect = cl->xform_cache.xform(cl->rect_cache);
+ } else {
+ shadow_rect=shadow_rect.merge( cl->xform_cache.xform(cl->rect_cache) );
+ }
+ lights_with_shadow=cl;
+ cl->radius_cache=cl->rect_cache.size.length();
+
+ }
+ if (cl->mode==VS::CANVAS_LIGHT_MODE_MASK) {
+ cl->mask_next_ptr=lights_with_mask;
+ lights_with_mask=cl;
+ }
+
+ light_count++;
+ }
+
+ VSG::canvas_render->light_internal_update(cl->light_internal,cl);
+
+ }
+ }
+
+ //print_line("lights: "+itos(light_count));
+ canvas_map[ Viewport::CanvasKey( E->key(), E->get().layer) ]=&E->get();
+
+ }
+
+ if (lights_with_shadow) {
+ //update shadows if any
+
+ RasterizerCanvas::LightOccluderInstance * occluders=NULL;
+
+ //make list of occluders
+ for (Map<RID,Viewport::CanvasData>::Element *E=p_viewport->canvas_map.front();E;E=E->next()) {
+
+ VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas*>(E->get().canvas);
+ Transform2D xf = p_viewport->global_transform * E->get().transform;
+
+
+ for(Set<RasterizerCanvas::LightOccluderInstance*>::Element *F=canvas->occluders.front();F;F=F->next()) {
+
+ if (!F->get()->enabled)
+ continue;
+ F->get()->xform_cache = xf * F->get()->xform;
+ if (shadow_rect.intersects_transformed(F->get()->xform_cache,F->get()->aabb_cache)) {
+
+ F->get()->next=occluders;
+ occluders=F->get();
+
+ }
+ }
+ }
+ //update the light shadowmaps with them
+ RasterizerCanvas::Light *light=lights_with_shadow;
+ while(light) {
+
+ VSG::canvas_render->canvas_light_shadow_buffer_update(light->shadow_buffer,light->xform_cache.affine_inverse(),light->item_mask,light->radius_cache/1000.0,light->radius_cache*1.1,occluders,&light->shadow_matrix_cache);
+ light=light->shadows_next_ptr;
+ }
+
+ //VSG::canvas_render->reset_canvas();
+ }
+
+ VSG::rasterizer->restore_render_target();
+
+
+#if 0
+ if (scenario_draw_canvas_bg && canvas_map.front() && canvas_map.front()->key().layer>scenario_canvas_max_layer) {
+
+ _draw_viewport_camera(p_viewport,!can_draw_3d);
+ scenario_draw_canvas_bg=false;
+
+ }
+#endif
+
+
+ for (Map<Viewport::CanvasKey,Viewport::CanvasData*>::Element *E=canvas_map.front();E;E=E->next()) {
+
+ VisualServerCanvas::Canvas *canvas = static_cast<VisualServerCanvas::Canvas*>(E->get()->canvas);
+
+ //print_line("canvas "+itos(i)+" size: "+itos(I->get()->canvas->child_items.size()));
+ //print_line("GT "+p_viewport->global_transform+". CT: "+E->get()->transform);
+ Transform2D xform = p_viewport->global_transform * E->get()->transform;
+
+ RasterizerCanvas::Light *canvas_lights=NULL;
+
+ RasterizerCanvas::Light *ptr=lights;
+ while(ptr) {
+ if (E->get()->layer>=ptr->layer_min && E->get()->layer<=ptr->layer_max) {
+ ptr->next_ptr=canvas_lights;
+ canvas_lights=ptr;
+ }
+ ptr=ptr->filter_next_ptr;
+ }
+
+ VSG::canvas->render_canvas( canvas,xform,canvas_lights,lights_with_mask,clip_rect );
+ i++;
+#if 0
+ if (scenario_draw_canvas_bg && E->key().layer>=scenario_canvas_max_layer) {
+ _draw_viewport_camera(p_viewport,!can_draw_3d);
+ scenario_draw_canvas_bg=false;
+ }
+#endif
+
+
+ }
+#if 0
+ if (scenario_draw_canvas_bg) {
+ _draw_viewport_camera(p_viewport,!can_draw_3d);
+ scenario_draw_canvas_bg=false;
+ }
+#endif
+
+ //VSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow);
+ }
+
+
+
+}
+
+void VisualServerViewport::draw_viewports() {
+
+ //sort viewports
+
+
+ //draw viewports
+
+ clear_color=GLOBAL_GET("rendering/viewport/default_clear_color");
+
+
+ active_viewports.sort_custom<ViewportSort>();
+
+ for(int i=0;i<active_viewports.size();i++) {
+
+ Viewport *vp = active_viewports[i];
+
+ if (vp->update_mode==VS::VIEWPORT_UPDATE_DISABLED)
+ continue;
+
+ ERR_CONTINUE( !vp->render_target.is_valid() );
+
+ bool visible = vp->viewport_to_screen_rect!=Rect2() || vp->update_mode==VS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode==VS::VIEWPORT_UPDATE_ONCE;
+
+ if (!visible)
+ continue;
+
+ VSG::rasterizer->set_current_render_target(vp->render_target);
+ _draw_viewport(vp);
+
+ if (vp->viewport_to_screen_rect!=Rect2()) {
+ //copy to screen if set as such
+ VSG::rasterizer->set_current_render_target(RID());
+ VSG::rasterizer->blit_render_target_to_screen(vp->render_target,vp->viewport_to_screen_rect,vp->viewport_to_screen);
+ }
+
+ if (vp->update_mode==VS::VIEWPORT_UPDATE_ONCE) {
+ vp->update_mode=VS::VIEWPORT_UPDATE_DISABLED;
+ }
+ }
+}
+
+
+RID VisualServerViewport::viewport_create() {
+
+ Viewport * viewport = memnew( Viewport );
+
+ RID rid = viewport_owner.make_rid(viewport);
+
+ viewport->self=rid;
+ viewport->hide_scenario=false;
+ viewport->hide_canvas=false;
+ viewport->render_target=VSG::storage->render_target_create();
+ viewport->shadow_atlas=VSG::scene_render->shadow_atlas_create();
+
+ return rid;
+
+}
+
+void VisualServerViewport::viewport_set_size(RID p_viewport,int p_width,int p_height){
+
+ ERR_FAIL_COND(p_width<0 && p_height<0);
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+
+
+ viewport->size=Size2(p_width,p_height);
+ VSG::storage->render_target_set_size(viewport->render_target,p_width,p_height);
+
+
+}
+
+void VisualServerViewport::viewport_set_active(RID p_viewport,bool p_active) {
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ if (p_active) {
+ ERR_FAIL_COND(active_viewports.find(viewport)!=-1);//already active
+ active_viewports.push_back(viewport);
+ } else {
+ active_viewports.erase(viewport);
+ }
+
+
+}
+
+void VisualServerViewport::viewport_set_parent_viewport(RID p_viewport,RID p_parent_viewport) {
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->parent=p_parent_viewport;
+}
+
+void VisualServerViewport::viewport_set_clear_mode(RID p_viewport,VS::ViewportClearMode p_clear_mode) {
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->clear_mode=p_clear_mode;
+
+}
+
+
+void VisualServerViewport::viewport_attach_to_screen(RID p_viewport,const Rect2& p_rect,int p_screen){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->viewport_to_screen_rect=p_rect;
+ viewport->viewport_to_screen=p_screen;
+}
+void VisualServerViewport::viewport_detach(RID p_viewport){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->viewport_to_screen_rect=Rect2();
+ viewport->viewport_to_screen=0;
+
+}
+
+void VisualServerViewport::viewport_set_update_mode(RID p_viewport,VS::ViewportUpdateMode p_mode){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->update_mode=p_mode;
+
+}
+void VisualServerViewport::viewport_set_vflip(RID p_viewport,bool p_enable){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_VFLIP,p_enable);
+
+}
+
+RID VisualServerViewport::viewport_get_texture(RID p_viewport) const{
+
+ const Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND_V(!viewport,RID());
+
+ return VSG::storage->render_target_get_texture(viewport->render_target);
+
+}
+
+void VisualServerViewport::viewport_set_hide_scenario(RID p_viewport,bool p_hide){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->hide_scenario=p_hide;
+}
+void VisualServerViewport::viewport_set_hide_canvas(RID p_viewport,bool p_hide){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->hide_canvas=p_hide;
+}
+void VisualServerViewport::viewport_set_disable_environment(RID p_viewport,bool p_disable){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+
+ viewport->disable_environment=p_disable;
+}
+
+void VisualServerViewport::viewport_set_disable_3d(RID p_viewport,bool p_disable){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+
+ viewport->disable_3d=p_disable;
+ VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_NO_3D,p_disable);
+}
+
+void VisualServerViewport::viewport_attach_camera(RID p_viewport,RID p_camera){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->camera=p_camera;
+}
+void VisualServerViewport::viewport_set_scenario(RID p_viewport,RID p_scenario){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->scenario=p_scenario;
+}
+void VisualServerViewport::viewport_attach_canvas(RID p_viewport,RID p_canvas){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ ERR_FAIL_COND(viewport->canvas_map.has(p_canvas));
+ VisualServerCanvas::Canvas *canvas = VSG::canvas->canvas_owner.getornull(p_canvas);
+ ERR_FAIL_COND(!canvas);
+
+ canvas->viewports.insert(p_viewport);
+ viewport->canvas_map[p_canvas]=Viewport::CanvasData();
+ viewport->canvas_map[p_canvas].layer=0;
+ viewport->canvas_map[p_canvas].canvas=canvas;
+
+}
+
+void VisualServerViewport::viewport_remove_canvas(RID p_viewport,RID p_canvas){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ VisualServerCanvas::Canvas *canvas = VSG::canvas->canvas_owner.getornull(p_canvas);
+ ERR_FAIL_COND(!canvas);
+
+ viewport->canvas_map.erase(p_canvas);
+ canvas->viewports.erase(p_viewport);
+
+}
+void VisualServerViewport::viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Transform2D& p_offset){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas));
+ viewport->canvas_map[p_canvas].transform=p_offset;
+
+}
+void VisualServerViewport::viewport_set_transparent_background(RID p_viewport,bool p_enabled){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_TRANSPARENT,p_enabled);
+
+}
+
+void VisualServerViewport::viewport_set_global_canvas_transform(RID p_viewport,const Transform2D& p_transform){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->global_transform=p_transform;
+
+}
+void VisualServerViewport::viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer){
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas));
+ viewport->canvas_map[p_canvas].layer=p_layer;
+
+}
+
+void VisualServerViewport::viewport_set_shadow_atlas_size(RID p_viewport,int p_size) {
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ viewport->shadow_atlas_size=p_size;
+
+ VSG::scene_render->shadow_atlas_set_size( viewport->shadow_atlas, viewport->shadow_atlas_size);
+
+}
+
+void VisualServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport,int p_quadrant,int p_subdiv) {
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ VSG::scene_render->shadow_atlas_set_quadrant_subdivision( viewport->shadow_atlas, p_quadrant, p_subdiv);
+
+}
+
+void VisualServerViewport::viewport_set_msaa(RID p_viewport,VS::ViewportMSAA p_msaa) {
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ VSG::storage->render_target_set_msaa(viewport->render_target,p_msaa);
+}
+
+void VisualServerViewport::viewport_set_hdr(RID p_viewport,bool p_enabled) {
+
+ Viewport * viewport = viewport_owner.getornull(p_viewport);
+ ERR_FAIL_COND(!viewport);
+
+ VSG::storage->render_target_set_flag(viewport->render_target,RasterizerStorage::RENDER_TARGET_HDR,p_enabled);
+
+}
+
+bool VisualServerViewport::free(RID p_rid) {
+
+ if (viewport_owner.owns(p_rid)) {
+
+ Viewport * viewport = viewport_owner.getornull(p_rid);
+
+
+ VSG::storage->free( viewport->render_target );
+ VSG::scene_render->free( viewport->shadow_atlas );
+
+ while(viewport->canvas_map.front()) {
+ viewport_remove_canvas(p_rid,viewport->canvas_map.front()->key());
+ }
+
+ viewport_set_scenario(p_rid,RID());
+ active_viewports.erase(viewport);
+
+ viewport_owner.free(p_rid);
+ memdelete(viewport);
+
+
+ return true;
+ }
+
+ return false;
+
+}
+
+VisualServerViewport::VisualServerViewport()
+{
+
+}
diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h
new file mode 100644
index 0000000000..ff4bc2601d
--- /dev/null
+++ b/servers/visual/visual_server_viewport.h
@@ -0,0 +1,150 @@
+#ifndef VISUALSERVERVIEWPORT_H
+#define VISUALSERVERVIEWPORT_H
+
+#include "servers/visual_server.h"
+#include "rasterizer.h"
+#include "self_list.h"
+
+class VisualServerViewport {
+public:
+
+ struct CanvasBase : public RID_Data {
+
+
+ };
+
+
+
+ struct Viewport : public RID_Data {
+
+ RID self;
+ RID parent;
+
+ Size2i size;
+ RID camera;
+ RID scenario;
+
+ VS::ViewportUpdateMode update_mode;
+ RID render_target;
+ RID render_target_texture;
+
+ int viewport_to_screen;
+ Rect2 viewport_to_screen_rect;
+
+ bool hide_scenario;
+ bool hide_canvas;
+ bool disable_environment;
+ bool disable_3d;
+
+ RID shadow_atlas;
+ int shadow_atlas_size;
+
+
+ VS::ViewportClearMode clear_mode;
+
+ bool rendered_in_prev_frame;
+
+ struct CanvasKey {
+
+ int layer;
+ RID canvas;
+ bool operator<(const CanvasKey& p_canvas) const { if (layer==p_canvas.layer) return canvas < p_canvas.canvas; return layer<p_canvas.layer; }
+ CanvasKey() { layer=0; }
+ CanvasKey(const RID& p_canvas, int p_layer) { canvas=p_canvas; layer=p_layer; }
+ };
+
+ struct CanvasData {
+
+ CanvasBase *canvas;
+ Transform2D transform;
+ int layer;
+ };
+
+ Transform2D global_transform;
+
+ Map<RID,CanvasData> canvas_map;
+
+ Viewport() {
+ update_mode=VS::VIEWPORT_UPDATE_WHEN_VISIBLE;
+ clear_mode=VS::VIEWPORT_CLEAR_ALWAYS;
+ rendered_in_prev_frame=false;
+ disable_environment=false;
+ viewport_to_screen=0;
+ shadow_atlas_size=0;
+ disable_3d=false;
+
+ }
+ };
+
+ mutable RID_Owner<Viewport> viewport_owner;
+
+
+ struct ViewportSort {
+ _FORCE_INLINE_ bool operator()(const Viewport*p_left,const Viewport* p_right) const {
+
+ bool left_to_screen = p_left->viewport_to_screen_rect.size!=Size2();
+ bool right_to_screen = p_right->viewport_to_screen_rect.size!=Size2();
+
+ if (left_to_screen==right_to_screen) {
+
+ return p_left->parent==p_right->self;
+ } else {
+ return right_to_screen;
+ }
+ }
+ };
+
+
+ Vector<Viewport*> active_viewports;
+private:
+ Color clear_color;
+ void _draw_viewport(Viewport *p_viewport);
+public:
+
+
+ RID viewport_create();
+
+ void viewport_set_size(RID p_viewport,int p_width,int p_height);
+
+ void viewport_attach_to_screen(RID p_viewport,const Rect2& p_rect=Rect2(),int p_screen=0);
+ void viewport_detach(RID p_viewport);
+
+ void viewport_set_active(RID p_viewport,bool p_active);
+ void viewport_set_parent_viewport(RID p_viewport,RID p_parent_viewport);
+ void viewport_set_update_mode(RID p_viewport,VS::ViewportUpdateMode p_mode);
+ void viewport_set_vflip(RID p_viewport,bool p_enable);
+
+
+ void viewport_set_clear_mode(RID p_viewport,VS::ViewportClearMode p_clear_mode);
+
+ RID viewport_get_texture(RID p_viewport) const;
+
+ void viewport_set_hide_scenario(RID p_viewport,bool p_hide);
+ void viewport_set_hide_canvas(RID p_viewport,bool p_hide);
+ void viewport_set_disable_environment(RID p_viewport,bool p_disable);
+ void viewport_set_disable_3d(RID p_viewport,bool p_disable);
+
+ void viewport_attach_camera(RID p_viewport,RID p_camera);
+ void viewport_set_scenario(RID p_viewport,RID p_scenario);
+ void viewport_attach_canvas(RID p_viewport,RID p_canvas);
+ void viewport_remove_canvas(RID p_viewport,RID p_canvas);
+ void viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Transform2D& p_offset);
+ void viewport_set_transparent_background(RID p_viewport,bool p_enabled);
+
+ void viewport_set_global_canvas_transform(RID p_viewport,const Transform2D& p_transform);
+ void viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer);
+
+ void viewport_set_shadow_atlas_size(RID p_viewport,int p_size);
+ void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport,int p_quadrant,int p_subdiv);
+
+ void viewport_set_msaa(RID p_viewport,VS::ViewportMSAA p_msaa);
+ void viewport_set_hdr(RID p_viewport,bool p_enabled);
+
+ void draw_viewports();
+
+ bool free(RID p_rid);
+
+ VisualServerViewport();
+};
+
+#endif // VISUALSERVERVIEWPORT_H
diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp
deleted file mode 100644
index 5ea4145342..0000000000
--- a/servers/visual/visual_server_wrap_mt.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/*************************************************************************/
-/* visual_server_wrap_mt.cpp */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 "visual_server_wrap_mt.h"
-#include "os/os.h"
-#include "globals.h"
-void VisualServerWrapMT::thread_exit() {
-
- exit=true;
-}
-
-void VisualServerWrapMT::thread_draw() {
-
-
- draw_mutex->lock();
-
- draw_pending--;
- bool draw=(draw_pending==0);// only draw when no more flushes are pending
-
- draw_mutex->unlock();
-
- if (draw) {
-
- visual_server->draw();
- }
-
-}
-
-void VisualServerWrapMT::thread_flush() {
-
-
- draw_mutex->lock();
-
- draw_pending--;
-
- draw_mutex->unlock();
-
-}
-
-
-
-void VisualServerWrapMT::_thread_callback(void *_instance) {
-
- VisualServerWrapMT *vsmt = reinterpret_cast<VisualServerWrapMT*>(_instance);
-
-
- vsmt->thread_loop();
-}
-
-void VisualServerWrapMT::thread_loop() {
-
- server_thread=Thread::get_caller_ID();
-
- OS::get_singleton()->make_rendering_thread();
-
- visual_server->init();
-
- exit=false;
- draw_thread_up=true;
- while(!exit) {
- // flush commands one by one, until exit is requested
- command_queue.wait_and_flush_one();
- }
-
- command_queue.flush_all(); // flush all
-
- visual_server->finish();
-
-}
-
-
-/* EVENT QUEUING */
-
-void VisualServerWrapMT::sync() {
-
- if (create_thread) {
-
- /* TODO: sync with the thread */
-
- /*
- ERR_FAIL_COND(!draw_mutex);
- draw_mutex->lock();
- draw_pending++; //cambiar por un saferefcount
- draw_mutex->unlock();
- */
- //command_queue.push( this, &VisualServerWrapMT::thread_flush);
- } else {
-
- command_queue.flush_all(); //flush all pending from other threads
- }
-
-}
-
-void VisualServerWrapMT::draw() {
-
-
- if (create_thread) {
-
- /* TODO: Make it draw
- ERR_FAIL_COND(!draw_mutex);
- draw_mutex->lock();
- draw_pending++; //cambiar por un saferefcount
- draw_mutex->unlock();
-
- command_queue.push( this, &VisualServerWrapMT::thread_draw);
- */
- } else {
-
- visual_server->draw();
- }
-}
-
-
-void VisualServerWrapMT::init() {
-
- if (create_thread) {
-
- draw_mutex = Mutex::create();
- print_line("CREATING RENDER THREAD");
- OS::get_singleton()->release_rendering_thread();
- if (create_thread) {
- thread = Thread::create( _thread_callback, this );
- print_line("STARTING RENDER THREAD");
- }
- while(!draw_thread_up) {
- OS::get_singleton()->delay_usec(1000);
- }
- print_line("DONE RENDER THREAD");
- } else {
-
- visual_server->init();
- }
-
-}
-
-void VisualServerWrapMT::finish() {
-
-
- if (thread) {
-
- command_queue.push( this, &VisualServerWrapMT::thread_exit);
- Thread::wait_to_finish( thread );
- memdelete(thread);
-
-
- texture_free_cached_ids();
- mesh_free_cached_ids();
-
- thread=NULL;
- } else {
- visual_server->finish();
- }
-
- if (draw_mutex)
- memdelete(draw_mutex);
-
-}
-
-
-VisualServerWrapMT::VisualServerWrapMT(VisualServer* p_contained,bool p_create_thread) : command_queue(p_create_thread) {
-
- visual_server=p_contained;
- create_thread=p_create_thread;
- thread=NULL;
- draw_mutex=NULL;
- draw_pending=0;
- draw_thread_up=false;
- alloc_mutex=Mutex::create();
- texture_pool_max_size=GLOBAL_DEF("render/thread_textures_prealloc",5);
- mesh_pool_max_size=GLOBAL_DEF("core/rid_pool_prealloc",20);
- if (!p_create_thread) {
- server_thread=Thread::get_caller_ID();
- } else {
- server_thread=0;
- }
-}
-
-
-VisualServerWrapMT::~VisualServerWrapMT() {
-
- memdelete(visual_server);
- memdelete(alloc_mutex);
- //finish();
-
-}
-
-
diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h
deleted file mode 100644
index b4e374dd6f..0000000000
--- a/servers/visual/visual_server_wrap_mt.h
+++ /dev/null
@@ -1,739 +0,0 @@
-/*************************************************************************/
-/* visual_server_wrap_mt.h */
-/*************************************************************************/
-/* This file is part of: */
-/* GODOT ENGINE */
-/* http://www.godotengine.org */
-/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
-/* */
-/* 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 VISUAL_SERVER_WRAP_MT_H
-#define VISUAL_SERVER_WRAP_MT_H
-
-
-#include "servers/visual_server.h"
-#include "command_queue_mt.h"
-#include "os/thread.h"
-
-/**
- @author Juan Linietsky <reduzio@gmail.com>
-*/
-class VisualServerWrapMT : public VisualServer {
-
- // the real visual server
- mutable VisualServer *visual_server;
-
- mutable CommandQueueMT command_queue;
-
- static void _thread_callback(void *_instance);
- void thread_loop();
-
- Thread::ID server_thread;
- volatile bool exit;
- Thread *thread;
- volatile bool draw_thread_up;
- bool create_thread;
-
- Mutex *draw_mutex;
- int draw_pending;
- void thread_draw();
- void thread_flush();
-
- void thread_exit();
-
- Mutex*alloc_mutex;
-
-
- int texture_pool_max_size;
- List<RID> texture_id_pool;
-
- int mesh_pool_max_size;
- List<RID> mesh_id_pool;
-
-//#define DEBUG_SYNC
-
-#ifdef DEBUG_SYNC
-#define SYNC_DEBUG print_line("sync on: "+String(__FUNCTION__));
-#else
-#define SYNC_DEBUG
-#endif
-
-public:
-
-#define ServerName VisualServer
-#define ServerNameWrapMT VisualServerWrapMT
-#define server_name visual_server
-#include "servers/server_wrap_mt_common.h"
-
- //FUNC0R(RID,texture_create);
- FUNCRID(texture);
- FUNC5(texture_allocate,RID,int,int,Image::Format,uint32_t);
- FUNC3(texture_set_data,RID,const Image&,CubeMapSide);
- FUNC2RC(Image,texture_get_data,RID,CubeMapSide);
- FUNC2(texture_set_flags,RID,uint32_t);
- FUNC1RC(Image::Format,texture_get_format,RID);
- FUNC1RC(uint32_t,texture_get_flags,RID);
- FUNC1RC(uint32_t,texture_get_width,RID);
- FUNC1RC(uint32_t,texture_get_height,RID);
- FUNC3(texture_set_size_override,RID,int,int);
- FUNC1RC(bool,texture_can_stream,RID);
- FUNC3C(texture_set_reload_hook,RID,ObjectID,const StringName&);
-
- FUNC2(texture_set_path,RID,const String&);
- FUNC1RC(String,texture_get_path,RID);
-
- FUNC1(texture_set_shrink_all_x2_on_set_data,bool);
-
- virtual void texture_debug_usage(List<TextureInfo> *r_info) {
- //pass directly, should lock the server anyway
- visual_server->texture_debug_usage(r_info);
- }
-
-
- /* SHADER API */
-
- FUNC1R(RID,shader_create,ShaderMode);
- FUNC2(shader_set_mode,RID,ShaderMode);
- FUNC1RC(ShaderMode,shader_get_mode,RID);
- FUNC7(shader_set_code,RID,const String&,const String&,const String&,int,int,int);
- FUNC1RC(String,shader_get_vertex_code,RID);
- FUNC1RC(String,shader_get_fragment_code,RID);
- FUNC1RC(String,shader_get_light_code,RID);
- FUNC2SC(shader_get_param_list,RID,List<PropertyInfo>*);
-
- FUNC3(shader_set_default_texture_param,RID,const StringName&,RID);
- FUNC2RC(RID,shader_get_default_texture_param,RID,const StringName&);
-
-
- /*virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) {
- if (Thread::get_caller_ID()!=server_thread) {
- command_queue.push_and_sync( visual_server, &VisualServer::shader_get_param_list,p_shader,p_param_list);
- } else {
- visual_server->m_type(p1, p2, p3, p4, p5);
- }
- }*/
-
-// virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list);
-
-
- /* COMMON MATERIAL API */
-
- FUNC0R(RID,material_create);
- FUNC2(material_set_shader,RID,RID);
- FUNC1RC(RID,material_get_shader,RID);
-
- FUNC3(material_set_param,RID,const StringName&,const Variant&);
- FUNC2RC(Variant,material_get_param,RID,const StringName&);
-
- FUNC3(material_set_flag,RID,MaterialFlag,bool);
- FUNC2RC(bool,material_get_flag,RID,MaterialFlag);
-
- FUNC2(material_set_depth_draw_mode,RID,MaterialDepthDrawMode);
- FUNC1RC(MaterialDepthDrawMode,material_get_depth_draw_mode,RID);
-
- FUNC2(material_set_blend_mode,RID,MaterialBlendMode);
- FUNC1RC(MaterialBlendMode,material_get_blend_mode,RID);
-
- FUNC2(material_set_line_width,RID,float);
- FUNC1RC(float,material_get_line_width,RID);
-
- /* FIXED MATERIAL */
-
-
- FUNC0R(RID,fixed_material_create);
-
- FUNC3(fixed_material_set_flag,RID, FixedMaterialFlags , bool );
- FUNC2RC(bool, fixed_material_get_flag,RID, FixedMaterialFlags);
-
- FUNC3(fixed_material_set_param,RID, FixedMaterialParam, const Variant& );
- FUNC2RC(Variant, fixed_material_get_param,RID ,FixedMaterialParam);
-
- FUNC3(fixed_material_set_texture,RID ,FixedMaterialParam, RID );
- FUNC2RC(RID, fixed_material_get_texture,RID,FixedMaterialParam);
-
-
-
- FUNC3(fixed_material_set_texcoord_mode,RID,FixedMaterialParam, FixedMaterialTexCoordMode );
- FUNC2RC(FixedMaterialTexCoordMode, fixed_material_get_texcoord_mode,RID,FixedMaterialParam);
-
- FUNC2(fixed_material_set_light_shader,RID,FixedMaterialLightShader);
- FUNC1RC(FixedMaterialLightShader, fixed_material_get_light_shader,RID);
-
- FUNC2(fixed_material_set_uv_transform,RID,const Transform&);
- FUNC1RC(Transform, fixed_material_get_uv_transform,RID);
-
- FUNC2(fixed_material_set_point_size,RID ,float);
- FUNC1RC(float,fixed_material_get_point_size,RID);
-
- /* SURFACE API */
- FUNCRID(mesh);
-
- FUNC2(mesh_set_morph_target_count,RID,int);
- FUNC1RC(int,mesh_get_morph_target_count,RID);
-
-
- FUNC2(mesh_set_morph_target_mode,RID,MorphTargetMode);
- FUNC1RC(MorphTargetMode,mesh_get_morph_target_mode,RID);
-
- FUNC2(mesh_add_custom_surface,RID,const Variant&); //this is used by each platform in a different way
-
- FUNC5(mesh_add_surface,RID,PrimitiveType,const Array&,const Array&,bool);
- FUNC2RC(Array,mesh_get_surface_arrays,RID,int);
- FUNC2RC(Array,mesh_get_surface_morph_arrays,RID,int);
-
- FUNC4(mesh_surface_set_material,RID, int, RID,bool);
- FUNC2RC(RID,mesh_surface_get_material,RID, int);
-
- FUNC2RC(int,mesh_surface_get_array_len,RID, int);
- FUNC2RC(int,mesh_surface_get_array_index_len,RID, int);
- FUNC2RC(uint32_t,mesh_surface_get_format,RID, int);
- FUNC2RC(PrimitiveType,mesh_surface_get_primitive_type,RID, int);
-
- FUNC2(mesh_remove_surface,RID,int);
- FUNC1RC(int,mesh_get_surface_count,RID);
- FUNC1(mesh_clear,RID);
-
-
- FUNC2(mesh_set_custom_aabb,RID,const AABB&);
- FUNC1RC(AABB,mesh_get_custom_aabb,RID);
-
-
- /* MULTIMESH API */
-
- FUNC0R(RID,multimesh_create);
- FUNC2(multimesh_set_instance_count,RID,int);
- FUNC1RC(int,multimesh_get_instance_count,RID);
-
- FUNC2(multimesh_set_mesh,RID,RID);
- FUNC2(multimesh_set_aabb,RID,const AABB&);
- FUNC3(multimesh_instance_set_transform,RID,int,const Transform&);
- FUNC3(multimesh_instance_set_color,RID,int,const Color&);
-
- FUNC1RC(RID,multimesh_get_mesh,RID);
- FUNC2RC(AABB,multimesh_get_aabb,RID,const AABB&);
- FUNC2RC(Transform,multimesh_instance_get_transform,RID,int);
- FUNC2RC(Color,multimesh_instance_get_color,RID,int);
-
- FUNC2(multimesh_set_visible_instances,RID,int);
- FUNC1RC(int,multimesh_get_visible_instances,RID);
-
- /* IMMEDIATE API */
-
-
- FUNC0R(RID,immediate_create);
- FUNC3(immediate_begin,RID,PrimitiveType,RID);
- FUNC2(immediate_vertex,RID,const Vector3&);
- FUNC2(immediate_normal,RID,const Vector3&);
- FUNC2(immediate_tangent,RID,const Plane&);
- FUNC2(immediate_color,RID,const Color&);
- FUNC2(immediate_uv,RID,const Vector2&);
- FUNC2(immediate_uv2,RID,const Vector2&);
- FUNC1(immediate_end,RID);
- FUNC1(immediate_clear,RID);
- FUNC2(immediate_set_material,RID,RID);
- FUNC1RC(RID,immediate_get_material,RID);
-
-
- /* PARTICLES API */
-
- FUNC0R(RID,particles_create);
-
- FUNC2(particles_set_amount,RID, int );
- FUNC1RC(int,particles_get_amount,RID);
-
- FUNC2(particles_set_emitting,RID, bool );
- FUNC1RC(bool,particles_is_emitting,RID);
-
- FUNC2(particles_set_visibility_aabb,RID, const AABB&);
- FUNC1RC(AABB,particles_get_visibility_aabb,RID);
-
- FUNC2(particles_set_emission_half_extents,RID, const Vector3&);
- FUNC1RC(Vector3,particles_get_emission_half_extents,RID);
-
- FUNC2(particles_set_emission_base_velocity,RID, const Vector3&);
- FUNC1RC(Vector3,particles_get_emission_base_velocity,RID);
-
- FUNC2(particles_set_emission_points,RID, const DVector<Vector3>& );
- FUNC1RC(DVector<Vector3>,particles_get_emission_points,RID);
-
- FUNC2(particles_set_gravity_normal,RID, const Vector3& );
- FUNC1RC(Vector3,particles_get_gravity_normal,RID);
-
- FUNC3(particles_set_variable,RID, ParticleVariable ,float);
- FUNC2RC(float,particles_get_variable,RID, ParticleVariable );
-
- FUNC3(particles_set_randomness,RID, ParticleVariable ,float);
- FUNC2RC(float,particles_get_randomness,RID, ParticleVariable );
-
- FUNC3(particles_set_color_phase_pos,RID, int , float);
- FUNC2RC(float,particles_get_color_phase_pos,RID, int );
-
- FUNC2(particles_set_color_phases,RID, int );
- FUNC1RC(int,particles_get_color_phases,RID);
-
- FUNC3(particles_set_color_phase_color,RID, int , const Color& );
- FUNC2RC(Color,particles_get_color_phase_color,RID, int );
-
- FUNC2(particles_set_attractors,RID, int);
- FUNC1RC(int,particles_get_attractors,RID);
-
- FUNC3(particles_set_attractor_pos,RID, int, const Vector3&);
- FUNC2RC(Vector3,particles_get_attractor_pos,RID,int);
-
- FUNC3(particles_set_attractor_strength,RID, int, float);
- FUNC2RC(float,particles_get_attractor_strength,RID,int);
-
- FUNC3(particles_set_material,RID, RID,bool);
- FUNC1RC(RID,particles_get_material,RID);
-
- FUNC2(particles_set_height_from_velocity,RID, bool);
- FUNC1RC(bool,particles_has_height_from_velocity,RID);
-
- FUNC2(particles_set_use_local_coordinates,RID, bool);
- FUNC1RC(bool,particles_is_using_local_coordinates,RID);
-
-
- /* Light API */
-
- FUNC1R(RID,light_create,LightType);
- FUNC1RC(LightType,light_get_type,RID);
-
- FUNC3(light_set_color,RID,LightColor , const Color& );
- FUNC2RC(Color,light_get_color,RID,LightColor );
-
-
- FUNC2(light_set_shadow,RID,bool );
- FUNC1RC(bool,light_has_shadow,RID);
-
- FUNC2(light_set_volumetric,RID,bool );
- FUNC1RC(bool,light_is_volumetric,RID);
-
- FUNC2(light_set_projector,RID,RID );
- FUNC1RC(RID,light_get_projector,RID);
-
- FUNC3(light_set_param,RID, LightParam , float );
- FUNC2RC(float,light_get_param,RID, LightParam );
-
- FUNC2(light_set_operator,RID,LightOp);
- FUNC1RC(LightOp,light_get_operator,RID);
-
- FUNC2(light_omni_set_shadow_mode,RID,LightOmniShadowMode);
- FUNC1RC(LightOmniShadowMode,light_omni_get_shadow_mode,RID);
-
- FUNC2(light_directional_set_shadow_mode,RID,LightDirectionalShadowMode);
- FUNC1RC(LightDirectionalShadowMode,light_directional_get_shadow_mode,RID);
- FUNC3(light_directional_set_shadow_param,RID,LightDirectionalShadowParam, float );
- FUNC2RC(float,light_directional_get_shadow_param,RID,LightDirectionalShadowParam );
-
-
- /* SKELETON API */
-
- FUNC0R(RID,skeleton_create);
- FUNC2(skeleton_resize,RID,int );
- FUNC1RC(int,skeleton_get_bone_count,RID) ;
- FUNC3(skeleton_bone_set_transform,RID,int, const Transform&);
- FUNC2R(Transform,skeleton_bone_get_transform,RID,int );
-
- /* ROOM API */
-
- FUNC0R(RID,room_create);
- FUNC2(room_set_bounds,RID, const BSP_Tree&);
- FUNC1RC(BSP_Tree,room_get_bounds,RID);
-
- /* PORTAL API */
-
- FUNC0R(RID,portal_create);
- FUNC2(portal_set_shape,RID,const Vector<Point2>&);
- FUNC1RC(Vector<Point2>,portal_get_shape,RID);
- FUNC2(portal_set_enabled,RID, bool);
- FUNC1RC(bool,portal_is_enabled,RID);
- FUNC2(portal_set_disable_distance,RID, float);
- FUNC1RC(float,portal_get_disable_distance,RID);
- FUNC2(portal_set_disabled_color,RID, const Color&);
- FUNC1RC(Color,portal_get_disabled_color,RID);
- FUNC2(portal_set_connect_range,RID, float);
- FUNC1RC(float,portal_get_connect_range,RID);
-
-
- FUNC0R(RID,baked_light_create);
- FUNC2(baked_light_set_mode,RID,BakedLightMode);
- FUNC1RC(BakedLightMode,baked_light_get_mode,RID);
-
- FUNC2(baked_light_set_octree,RID,DVector<uint8_t>);
- FUNC1RC(DVector<uint8_t>,baked_light_get_octree,RID);
-
- FUNC2(baked_light_set_light,RID,DVector<uint8_t>);
- FUNC1RC(DVector<uint8_t>,baked_light_get_light,RID);
-
- FUNC2(baked_light_set_sampler_octree,RID,const DVector<int>&);
- FUNC1RC(DVector<int>,baked_light_get_sampler_octree,RID);
-
- FUNC2(baked_light_set_lightmap_multiplier,RID,float);
- FUNC1RC(float,baked_light_get_lightmap_multiplier,RID);
-
- FUNC3(baked_light_add_lightmap,RID,RID,int);
- FUNC1(baked_light_clear_lightmaps,RID);
-
- FUNC2(baked_light_set_realtime_color_enabled, RID, const bool);
- FUNC1RC(bool, baked_light_get_realtime_color_enabled, RID);
-
- FUNC2(baked_light_set_realtime_color, RID, const Color&);
- FUNC1RC(Color, baked_light_get_realtime_color, RID);
-
- FUNC2(baked_light_set_realtime_energy, RID, const float);
- FUNC1RC(float, baked_light_get_realtime_energy, RID);
-
- FUNC0R(RID,baked_light_sampler_create);
-
- FUNC3(baked_light_sampler_set_param,RID, BakedLightSamplerParam , float );
- FUNC2RC(float,baked_light_sampler_get_param,RID, BakedLightSamplerParam );
-
- FUNC2(baked_light_sampler_set_resolution,RID,int);
- FUNC1RC(int,baked_light_sampler_get_resolution,RID);
-
- /* CAMERA API */
-
- FUNC0R(RID,camera_create);
- FUNC4(camera_set_perspective,RID,float , float , float );
- FUNC4(camera_set_orthogonal,RID,float, float , float );
- FUNC2(camera_set_transform,RID,const Transform& );
-
- FUNC2(camera_set_visible_layers,RID,uint32_t);
- FUNC1RC(uint32_t,camera_get_visible_layers,RID);
-
- FUNC2(camera_set_environment,RID,RID);
- FUNC1RC(RID,camera_get_environment,RID);
-
-
- FUNC2(camera_set_use_vertical_aspect,RID,bool);
- FUNC2RC(bool,camera_is_using_vertical_aspect,RID,bool);
-
-
- /* VIEWPORT API */
-
- FUNC0R(RID,viewport_create);
-
- FUNC2(viewport_attach_to_screen,RID,int );
- FUNC1(viewport_detach,RID);
-
- FUNC2(viewport_set_as_render_target,RID,bool);
- FUNC2(viewport_set_render_target_update_mode,RID,RenderTargetUpdateMode);
- FUNC1RC(RenderTargetUpdateMode,viewport_get_render_target_update_mode,RID);
- FUNC1RC(RID,viewport_get_render_target_texture,RID);
-
- FUNC2(viewport_set_render_target_vflip,RID,bool);
- FUNC1RC(bool,viewport_get_render_target_vflip,RID);
- FUNC2(viewport_set_render_target_to_screen_rect,RID,const Rect2&);
-
- FUNC2(viewport_set_render_target_clear_on_new_frame,RID,bool);
- FUNC1RC(bool,viewport_get_render_target_clear_on_new_frame,RID);
- FUNC1(viewport_render_target_clear,RID);
-
- FUNC1(viewport_queue_screen_capture,RID);
- FUNC1RC(Image,viewport_get_screen_capture,RID);
-
- FUNC2(viewport_set_rect,RID,const ViewportRect&);
- FUNC1RC(ViewportRect,viewport_get_rect,RID);
-
- FUNC2(viewport_set_hide_scenario,RID,bool );
- FUNC2(viewport_set_hide_canvas,RID,bool );
- FUNC2(viewport_attach_camera,RID,RID );
- FUNC2(viewport_set_scenario,RID,RID );
- FUNC2(viewport_set_disable_environment,RID,bool );
-
- FUNC1RC(RID,viewport_get_attached_camera,RID);
- FUNC1RC(RID,viewport_get_scenario,RID );
- FUNC2(viewport_attach_canvas,RID,RID);
- FUNC2(viewport_remove_canvas,RID,RID);
- FUNC3(viewport_set_canvas_transform,RID,RID,const Matrix32&);
- FUNC2RC(Matrix32,viewport_get_canvas_transform,RID,RID);
- FUNC2(viewport_set_global_canvas_transform,RID,const Matrix32&);
- FUNC1RC(Matrix32,viewport_get_global_canvas_transform,RID);
- FUNC3(viewport_set_canvas_layer,RID,RID ,int);
- FUNC2(viewport_set_transparent_background,RID,bool);
- FUNC1RC(bool,viewport_has_transparent_background,RID);
-
-
- /* ENVIRONMENT API */
-
- FUNC0R(RID,environment_create);
-
- FUNC2(environment_set_background,RID,EnvironmentBG);
- FUNC1RC(EnvironmentBG,environment_get_background,RID);
-
- FUNC3(environment_set_background_param,RID,EnvironmentBGParam, const Variant&);
- FUNC2RC(Variant,environment_get_background_param,RID,EnvironmentBGParam );
-
- FUNC3(environment_set_enable_fx,RID,EnvironmentFx,bool);
- FUNC2RC(bool,environment_is_fx_enabled,RID,EnvironmentFx);
-
-
- FUNC3(environment_fx_set_param,RID,EnvironmentFxParam,const Variant&);
- FUNC2RC(Variant,environment_fx_get_param,RID,EnvironmentFxParam);
-
-
- /* SCENARIO API */
-
- FUNC0R(RID,scenario_create);
-
- FUNC2(scenario_set_debug,RID,ScenarioDebugMode);
- FUNC2(scenario_set_environment,RID, RID);
- FUNC2RC(RID,scenario_get_environment,RID, RID);
- FUNC2(scenario_set_fallback_environment,RID, RID);
-
-
- /* INSTANCING API */
-
- FUNC0R(RID,instance_create);
-
- FUNC2(instance_set_base,RID, RID);
- FUNC1RC(RID,instance_get_base,RID);
-
- FUNC2(instance_set_scenario,RID, RID);
- FUNC1RC(RID,instance_get_scenario,RID);
-
- FUNC2(instance_set_layer_mask,RID, uint32_t);
- FUNC1RC(uint32_t,instance_get_layer_mask,RID);
-
- FUNC1RC(AABB,instance_get_base_aabb,RID);
-
- FUNC2(instance_attach_object_instance_ID,RID,uint32_t);
- FUNC1RC(uint32_t,instance_get_object_instance_ID,RID);
-
- FUNC2(instance_attach_skeleton,RID,RID);
- FUNC1RC(RID,instance_get_skeleton,RID);
-
- FUNC3(instance_set_morph_target_weight,RID,int, float);
- FUNC2RC(float,instance_get_morph_target_weight,RID,int);
-
- FUNC3(instance_set_surface_material,RID,int, RID);
-
- FUNC2(instance_set_transform,RID, const Transform&);
- FUNC1RC(Transform,instance_get_transform,RID);
-
- FUNC2(instance_set_exterior,RID, bool );
- FUNC1RC(bool,instance_is_exterior,RID);
-
- FUNC2(instance_set_room,RID, RID );
- FUNC1RC(RID,instance_get_room,RID ) ;
-
- FUNC2(instance_set_extra_visibility_margin,RID, real_t );
- FUNC1RC(real_t,instance_get_extra_visibility_margin,RID );
-
- FUNC2RC(Vector<RID>,instances_cull_aabb,const AABB& , RID );
- FUNC3RC(Vector<RID>,instances_cull_ray,const Vector3& ,const Vector3&, RID );
- FUNC2RC(Vector<RID>,instances_cull_convex,const Vector<Plane>& , RID );
-
- FUNC3(instance_geometry_set_flag,RID,InstanceFlags ,bool );
- FUNC2RC(bool,instance_geometry_get_flag,RID,InstanceFlags );
-
- FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting);
- FUNC1RC(ShadowCastingSetting, instance_geometry_get_cast_shadows_setting, RID);
-
- FUNC2(instance_geometry_set_material_override,RID, RID );
- FUNC1RC(RID,instance_geometry_get_material_override,RID);
-
- FUNC3(instance_geometry_set_draw_range,RID,float ,float);
- FUNC1RC(float,instance_geometry_get_draw_range_max,RID);
- FUNC1RC(float,instance_geometry_get_draw_range_min,RID);
-
- FUNC2(instance_geometry_set_baked_light,RID, RID );
- FUNC1RC(RID,instance_geometry_get_baked_light,RID);
-
- FUNC2(instance_geometry_set_baked_light_sampler,RID, RID );
- FUNC1RC(RID,instance_geometry_get_baked_light_sampler,RID);
-
- FUNC2(instance_geometry_set_baked_light_texture_index,RID, int);
- FUNC1RC(int,instance_geometry_get_baked_light_texture_index,RID);
-
- FUNC2(instance_light_set_enabled,RID,bool);
- FUNC1RC(bool,instance_light_is_enabled,RID);
-
- /* CANVAS (2D) */
-
- FUNC0R(RID,canvas_create);
- FUNC3(canvas_set_item_mirroring,RID,RID,const Point2&);
- FUNC2RC(Point2,canvas_get_item_mirroring,RID,RID);
- FUNC2(canvas_set_modulate,RID,const Color&);
-
-
- FUNC0R(RID,canvas_item_create);
-
- FUNC2(canvas_item_set_parent,RID,RID );
- FUNC1RC(RID,canvas_item_get_parent,RID);
-
- FUNC2(canvas_item_set_visible,RID,bool );
- FUNC1RC(bool,canvas_item_is_visible,RID);
-
- FUNC2(canvas_item_set_blend_mode,RID,MaterialBlendMode );
- FUNC2(canvas_item_set_light_mask,RID,int );
-
- //FUNC(canvas_item_set_rect,RID, const Rect2& p_rect);
- FUNC2(canvas_item_set_transform,RID, const Matrix32& );
- FUNC2(canvas_item_set_clip,RID, bool );
- FUNC2(canvas_item_set_distance_field_mode,RID, bool );
- FUNC3(canvas_item_set_custom_rect,RID, bool ,const Rect2&);
- FUNC2(canvas_item_set_opacity,RID, float );
- FUNC2RC(float,canvas_item_get_opacity,RID, float );
- FUNC2(canvas_item_set_on_top,RID, bool );
- FUNC1RC(bool,canvas_item_is_on_top,RID);
-
- FUNC2(canvas_item_set_self_opacity,RID, float );
- FUNC2RC(float,canvas_item_get_self_opacity,RID, float );
-
- FUNC2(canvas_item_attach_viewport,RID, RID );
-
- FUNC6(canvas_item_add_line,RID, const Point2& , const Point2& ,const Color& ,float,bool);
- FUNC3(canvas_item_add_rect,RID, const Rect2& , const Color& );
- FUNC4(canvas_item_add_circle,RID, const Point2& , float ,const Color& );
- FUNC6(canvas_item_add_texture_rect,RID, const Rect2& , RID ,bool ,const Color&,bool );
- FUNC6(canvas_item_add_texture_rect_region,RID, const Rect2& , RID ,const Rect2& ,const Color&,bool );
- FUNC8(canvas_item_add_style_box,RID, const Rect2& , const Rect2&, RID ,const Vector2& ,const Vector2&, bool ,const Color& );
- FUNC6(canvas_item_add_primitive,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID ,float );
- FUNC5(canvas_item_add_polygon,RID, const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID );
- FUNC7(canvas_item_add_triangle_array,RID, const Vector<int>& , const Vector<Point2>& , const Vector<Color>& ,const Vector<Point2>& , RID , int );
- FUNC7(canvas_item_add_triangle_array_ptr,RID, int , const int* , const Point2* , const Color* ,const Point2* , RID );
-
-
- FUNC2(canvas_item_add_set_transform,RID,const Matrix32& );
- FUNC2(canvas_item_add_set_blend_mode,RID, MaterialBlendMode );
- FUNC2(canvas_item_add_clip_ignore,RID, bool );
-
- FUNC2(canvas_item_set_sort_children_by_y,RID,bool);
- FUNC2(canvas_item_set_z,RID,int);
- FUNC2(canvas_item_set_z_as_relative_to_parent,RID,bool);
- FUNC3(canvas_item_set_copy_to_backbuffer,RID,bool,const Rect2&);
-
-
- FUNC2(canvas_item_set_material,RID, RID );
-
- FUNC2(canvas_item_set_use_parent_material,RID, bool );
-
- FUNC1(canvas_item_clear,RID);
- FUNC1(canvas_item_raise,RID);
-
- /* CANVAS LIGHT */
- FUNC0R(RID,canvas_light_create);
- FUNC2(canvas_light_attach_to_canvas,RID,RID);
- FUNC2(canvas_light_set_enabled,RID,bool);
- FUNC2(canvas_light_set_transform,RID,const Matrix32&);
- FUNC2(canvas_light_set_scale,RID,float);
- FUNC2(canvas_light_set_texture,RID,RID);
- FUNC2(canvas_light_set_texture_offset,RID,const Vector2&);
- FUNC2(canvas_light_set_color,RID,const Color&);
- FUNC2(canvas_light_set_height,RID,float);
- FUNC2(canvas_light_set_energy,RID,float);
- FUNC3(canvas_light_set_layer_range,RID,int,int);
- FUNC3(canvas_light_set_z_range,RID,int,int);
- FUNC2(canvas_light_set_item_mask,RID,int);
- FUNC2(canvas_light_set_item_shadow_mask,RID,int);
-
- FUNC2(canvas_light_set_mode,RID,CanvasLightMode);
- FUNC2(canvas_light_set_shadow_enabled,RID,bool);
- FUNC2(canvas_light_set_shadow_buffer_size,RID,int);
- FUNC2(canvas_light_set_shadow_esm_multiplier,RID,float);
- FUNC2(canvas_light_set_shadow_color,RID,const Color&);
-
-
-
- /* CANVAS OCCLUDER */
-
- FUNC0R(RID,canvas_light_occluder_create);
- FUNC2(canvas_light_occluder_attach_to_canvas,RID,RID);
- FUNC2(canvas_light_occluder_set_enabled,RID,bool);
- FUNC2(canvas_light_occluder_set_polygon,RID,RID);
- FUNC2(canvas_light_occluder_set_transform,RID,const Matrix32&);
- FUNC2(canvas_light_occluder_set_light_mask,RID,int);
-
-
- FUNC0R(RID,canvas_occluder_polygon_create);
- FUNC3(canvas_occluder_polygon_set_shape,RID,const DVector<Vector2>&,bool);
- FUNC2(canvas_occluder_polygon_set_shape_as_lines,RID,const DVector<Vector2>&);
- FUNC2(canvas_occluder_polygon_set_cull_mode,RID,CanvasOccluderPolygonCullMode);
-
- /* CANVAS MATERIAL */
-
- FUNC0R(RID,canvas_item_material_create);
- FUNC2(canvas_item_material_set_shader,RID,RID);
- FUNC3(canvas_item_material_set_shader_param,RID,const StringName&,const Variant&);
- FUNC2RC(Variant,canvas_item_material_get_shader_param,RID,const StringName&);
- FUNC2(canvas_item_material_set_shading_mode,RID,CanvasItemShadingMode);
-
- /* CURSOR */
- FUNC2(cursor_set_rotation,float , int ); // radians
- FUNC4(cursor_set_texture,RID , const Point2 &, int, const Rect2 &);
- FUNC2(cursor_set_visible,bool , int );
- FUNC2(cursor_set_pos,const Point2& , int );
-
- /* BLACK BARS */
-
- FUNC4(black_bars_set_margins,int , int , int , int );
- FUNC4(black_bars_set_images,RID , RID , RID , RID );
-
- /* FREE */
-
- FUNC1(free,RID);
-
- /* CUSTOM SHADE MODEL */
-
- FUNC2(custom_shade_model_set_shader,int , RID );
- FUNC1RC(RID,custom_shade_model_get_shader,int );
- FUNC2(custom_shade_model_set_name,int , const String& );
- FUNC1RC(String,custom_shade_model_get_name,int );
- FUNC2(custom_shade_model_set_param_info,int , const List<PropertyInfo>& );
- FUNC2SC(custom_shade_model_get_param_info,int , List<PropertyInfo>* );
-
- /* EVENT QUEUING */
-
-
- virtual void init();
- virtual void finish();
- virtual void draw();
- virtual void sync();
- FUNC0RC(bool,has_changed);
-
- /* RENDER INFO */
-
- FUNC1R(int,get_render_info,RenderInfo );
- virtual bool has_feature(Features p_feature) const { return visual_server->has_feature(p_feature); }
-
- FUNC3(set_boot_image,const Image& , const Color&,bool );
- FUNC1(set_default_clear_color,const Color& );
-
- FUNC0R(RID,get_test_cube );
-
-
- VisualServerWrapMT(VisualServer* p_contained,bool p_create_thread);
- ~VisualServerWrapMT();
-
-#undef ServerName
-#undef ServerNameWrapMT
-#undef server_name
-
-};
-
-#ifdef DEBUG_SYNC
-#undef DEBUG_SYNC
-#endif
-#undef SYNC_DEBUG
-
-#endif
diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp
index f69580254c..5d231d208e 100644
--- a/servers/visual_server.cpp
+++ b/servers/visual_server.cpp
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -27,7 +27,7 @@
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/*************************************************************************/
#include "visual_server.h"
-#include "globals.h"
+#include "global_config.h"
#include "method_bind_ext.inc"
VisualServer *VisualServer::singleton=NULL;
@@ -39,22 +39,12 @@ VisualServer *VisualServer::get_singleton() {
}
-void VisualServer::set_mipmap_policy(MipMapPolicy p_policy) {
- mm_policy=p_policy;
-}
-
-VisualServer::MipMapPolicy VisualServer::get_mipmap_policy() const {
-
- return (VisualServer::MipMapPolicy)mm_policy;
-}
-
-
-DVector<String> VisualServer::_shader_get_param_list(RID p_shader) const {
+PoolVector<String> VisualServer::_shader_get_param_list(RID p_shader) const {
//remove at some point
- DVector<String> pl;
+ PoolVector<String> pl;
#if 0
@@ -93,38 +83,48 @@ RID VisualServer::texture_create_from_image(const Image& p_image,uint32_t p_flag
RID VisualServer::get_test_texture() {
- if (test_texture) {
+ if (test_texture.is_valid()) {
return test_texture;
};
#define TEST_TEXTURE_SIZE 256
- Image data(TEST_TEXTURE_SIZE,TEST_TEXTURE_SIZE,0,Image::FORMAT_RGB);
- for (int x=0;x<TEST_TEXTURE_SIZE;x++) {
+ PoolVector<uint8_t> test_data;
+ test_data.resize(TEST_TEXTURE_SIZE*TEST_TEXTURE_SIZE*3);
- for (int y=0;y<TEST_TEXTURE_SIZE;y++) {
+ {
+ PoolVector<uint8_t>::Write w=test_data.write();
- Color c;
- int r=255-(x+y)/2;
+ for (int x=0;x<TEST_TEXTURE_SIZE;x++) {
- if ((x%(TEST_TEXTURE_SIZE/8))<2 ||(y%(TEST_TEXTURE_SIZE/8))<2) {
+ for (int y=0;y<TEST_TEXTURE_SIZE;y++) {
- c.r=y;
- c.g=r;
- c.b=x;
+ Color c;
+ int r=255-(x+y)/2;
- } else {
+ if ((x%(TEST_TEXTURE_SIZE/8))<2 ||(y%(TEST_TEXTURE_SIZE/8))<2) {
- c.r=r;
- c.g=x;
- c.b=y;
- }
+ c.r=y;
+ c.g=r;
+ c.b=x;
- data.put_pixel(x, y, c);
+ } else {
+
+ c.r=r;
+ c.g=x;
+ c.b=y;
+ }
+
+ w[(y*TEST_TEXTURE_SIZE+x)*3+0]=uint8_t(CLAMP(c.r*255,0,255));
+ w[(y*TEST_TEXTURE_SIZE+x)*3+1]=uint8_t(CLAMP(c.g*255,0,255));
+ w[(y*TEST_TEXTURE_SIZE+x)*3+2]=uint8_t(CLAMP(c.b*255,0,255));
+ }
}
}
+ Image data(TEST_TEXTURE_SIZE,TEST_TEXTURE_SIZE,false,Image::FORMAT_RGB8,test_data);
+
test_texture = texture_create_from_image(data);
return test_texture;
@@ -150,13 +150,13 @@ void VisualServer::_free_internal_rids() {
RID VisualServer::_make_test_cube() {
- DVector<Vector3> vertices;
- DVector<Vector3> normals;
- DVector<float> tangents;
- DVector<Vector3> uvs;
+ PoolVector<Vector3> vertices;
+ PoolVector<Vector3> normals;
+ PoolVector<float> tangents;
+ PoolVector<Vector3> uvs;
int vtx_idx=0;
-#define ADD_VTX(m_idx);\
+#define ADD_VTX(m_idx) \
vertices.push_back( face_points[m_idx] );\
normals.push_back( normal_points[m_idx] );\
tangents.push_back( normal_points[m_idx][1] );\
@@ -211,16 +211,16 @@ RID VisualServer::_make_test_cube() {
d[VisualServer::ARRAY_TEX_UV]= uvs ;
d[VisualServer::ARRAY_VERTEX]= vertices ;
- DVector<int> indices;
+ PoolVector<int> indices;
indices.resize(vertices.size());
for(int i=0;i<vertices.size();i++)
indices.set(i,i);
d[VisualServer::ARRAY_INDEX]=indices;
- mesh_add_surface( test_cube, PRIMITIVE_TRIANGLES,d );
-
+ mesh_add_surface_from_arrays( test_cube, PRIMITIVE_TRIANGLES,d );
+/*
test_material = fixed_material_create();
//material_set_flag(material, MATERIAL_FLAG_BILLBOARD_TOGGLE,true);
fixed_material_set_texture( test_material, FIXED_MATERIAL_PARAM_DIFFUSE, get_test_texture() );
@@ -229,7 +229,7 @@ RID VisualServer::_make_test_cube() {
fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_DIFFUSE, Color(1, 1, 1) );
fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_SPECULAR, Color(1,1,1) );
-
+*/
mesh_surface_set_material(test_cube, 0, test_material );
return test_cube;
@@ -238,8 +238,8 @@ RID VisualServer::_make_test_cube() {
RID VisualServer::make_sphere_mesh(int p_lats,int p_lons,float p_radius) {
- DVector<Vector3> vertices;
- DVector<Vector3> normals;
+ PoolVector<Vector3> vertices;
+ PoolVector<Vector3> normals;
for(int i = 1; i <= p_lats; i++) {
double lat0 = Math_PI * (-0.5 + (double) (i - 1) / p_lats);
@@ -289,7 +289,7 @@ RID VisualServer::make_sphere_mesh(int p_lats,int p_lons,float p_radius) {
d[ARRAY_VERTEX]=vertices;
d[ARRAY_NORMAL]=normals;
- mesh_add_surface(mesh,PRIMITIVE_TRIANGLES,d);
+ mesh_add_surface_from_arrays(mesh,PRIMITIVE_TRIANGLES,d);
return mesh;
}
@@ -311,7 +311,7 @@ RID VisualServer::material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_
//not valid, make
- material_2d[version]=fixed_material_create();
+/* material_2d[version]=fixed_material_create();
fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_USE_ALPHA,p_transparent);
fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,true);
fixed_material_set_flag(material_2d[version],FIXED_MATERIAL_FLAG_DISCARD_ALPHA,p_cut_alpha);
@@ -319,7 +319,8 @@ RID VisualServer::material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_
material_set_flag(material_2d[version],MATERIAL_FLAG_DOUBLE_SIDED,true);
material_set_depth_draw_mode(material_2d[version],p_opaque_prepass?MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA:MATERIAL_DEPTH_DRAW_OPAQUE_ONLY);
fixed_material_set_texture(material_2d[version],FIXED_MATERIAL_PARAM_DIFFUSE,get_white_texture());
- //material cut alpha?
+ //material cut alpha?*/
+
return material_2d[version];
}
@@ -328,407 +329,1269 @@ RID VisualServer::get_white_texture() {
if (white_texture.is_valid())
return white_texture;
- DVector<uint8_t> wt;
+ PoolVector<uint8_t> wt;
wt.resize(16*3);
{
- DVector<uint8_t>::Write w =wt.write();
+ PoolVector<uint8_t>::Write w =wt.write();
for(int i=0;i<16*3;i++)
w[i]=255;
}
- Image white(4,4,0,Image::FORMAT_RGB,wt);
+ Image white(4,4,0,Image::FORMAT_RGB8,wt);
white_texture=texture_create();
- texture_allocate(white_texture,4,4,Image::FORMAT_RGB);
+ texture_allocate(white_texture,4,4,Image::FORMAT_RGB8);
texture_set_data(white_texture,white);
return white_texture;
}
-void VisualServer::_bind_methods() {
+Error VisualServer::_surface_set_data(Array p_arrays,uint32_t p_format,uint32_t *p_offsets,uint32_t p_stride,PoolVector<uint8_t> &r_vertex_array,int p_vertex_array_len,PoolVector<uint8_t> &r_index_array,int p_index_array_len,Rect3 &r_aabb,Vector<Rect3> r_bone_aabb) {
- ObjectTypeDB::bind_method(_MD("texture_create"),&VisualServer::texture_create);
- ObjectTypeDB::bind_method(_MD("texture_create_from_image"),&VisualServer::texture_create_from_image,DEFVAL( TEXTURE_FLAGS_DEFAULT ) );
- //ObjectTypeDB::bind_method(_MD("texture_allocate"),&VisualServer::texture_allocate,DEFVAL( TEXTURE_FLAGS_DEFAULT ) );
- //ObjectTypeDB::bind_method(_MD("texture_set_data"),&VisualServer::texture_blit_rect,DEFVAL( CUBEMAP_LEFT ) );
- //ObjectTypeDB::bind_method(_MD("texture_get_rect"),&VisualServer::texture_get_rect );
- ObjectTypeDB::bind_method(_MD("texture_set_flags"),&VisualServer::texture_set_flags );
- ObjectTypeDB::bind_method(_MD("texture_get_flags"),&VisualServer::texture_get_flags );
- ObjectTypeDB::bind_method(_MD("texture_get_width"),&VisualServer::texture_get_width );
- ObjectTypeDB::bind_method(_MD("texture_get_height"),&VisualServer::texture_get_height );
-
- ObjectTypeDB::bind_method(_MD("texture_set_shrink_all_x2_on_set_data","shrink"),&VisualServer::texture_set_shrink_all_x2_on_set_data );
-
-#ifndef _3D_DISABLED
-
-
- ObjectTypeDB::bind_method(_MD("shader_create","mode"),&VisualServer::shader_create,DEFVAL(SHADER_MATERIAL));
- ObjectTypeDB::bind_method(_MD("shader_set_mode","shader","mode"),&VisualServer::shader_set_mode);
-
-
-
- ObjectTypeDB::bind_method(_MD("material_create"),&VisualServer::material_create);
-
- ObjectTypeDB::bind_method(_MD("material_set_shader","shader"),&VisualServer::material_set_shader);
- ObjectTypeDB::bind_method(_MD("material_get_shader"),&VisualServer::material_get_shader);
-
- ObjectTypeDB::bind_method(_MD("material_set_param"),&VisualServer::material_set_param);
- ObjectTypeDB::bind_method(_MD("material_get_param"),&VisualServer::material_get_param);
- ObjectTypeDB::bind_method(_MD("material_set_flag"),&VisualServer::material_set_flag);
- ObjectTypeDB::bind_method(_MD("material_get_flag"),&VisualServer::material_get_flag);
- ObjectTypeDB::bind_method(_MD("material_set_blend_mode"),&VisualServer::material_set_blend_mode);
- ObjectTypeDB::bind_method(_MD("material_get_blend_mode"),&VisualServer::material_get_blend_mode);
- ObjectTypeDB::bind_method(_MD("material_set_line_width"),&VisualServer::material_set_line_width);
- ObjectTypeDB::bind_method(_MD("material_get_line_width"),&VisualServer::material_get_line_width);
-
-
- ObjectTypeDB::bind_method(_MD("mesh_create"),&VisualServer::mesh_create);
- ObjectTypeDB::bind_method(_MD("mesh_add_surface"),&VisualServer::mesh_add_surface, DEFVAL(NO_INDEX_ARRAY));
- ObjectTypeDB::bind_method(_MD("mesh_surface_set_material"),&VisualServer::mesh_surface_set_material,DEFVAL(false));
- ObjectTypeDB::bind_method(_MD("mesh_surface_get_material"),&VisualServer::mesh_surface_get_material);
-
- ObjectTypeDB::bind_method(_MD("mesh_surface_get_array_len"),&VisualServer::mesh_surface_get_array_len);
- ObjectTypeDB::bind_method(_MD("mesh_surface_get_array_index_len"),&VisualServer::mesh_surface_get_array_index_len);
- ObjectTypeDB::bind_method(_MD("mesh_surface_get_format"),&VisualServer::mesh_surface_get_format);
- ObjectTypeDB::bind_method(_MD("mesh_surface_get_primitive_type"),&VisualServer::mesh_surface_get_primitive_type);
-
- ObjectTypeDB::bind_method(_MD("mesh_remove_surface"),&VisualServer::mesh_remove_surface);
- ObjectTypeDB::bind_method(_MD("mesh_get_surface_count"),&VisualServer::mesh_get_surface_count);
-
-
- ObjectTypeDB::bind_method(_MD("multimesh_create"),&VisualServer::multimesh_create);
- ObjectTypeDB::bind_method(_MD("multimesh_set_mesh"),&VisualServer::multimesh_set_mesh);
- ObjectTypeDB::bind_method(_MD("multimesh_set_aabb"),&VisualServer::multimesh_set_aabb);
- ObjectTypeDB::bind_method(_MD("multimesh_instance_set_transform"),&VisualServer::multimesh_instance_set_transform);
- ObjectTypeDB::bind_method(_MD("multimesh_instance_set_color"),&VisualServer::multimesh_instance_set_color);
- ObjectTypeDB::bind_method(_MD("multimesh_get_mesh"),&VisualServer::multimesh_get_mesh);
- ObjectTypeDB::bind_method(_MD("multimesh_get_aabb"),&VisualServer::multimesh_get_aabb);
- ObjectTypeDB::bind_method(_MD("multimesh_instance_get_transform"),&VisualServer::multimesh_instance_get_transform);
- ObjectTypeDB::bind_method(_MD("multimesh_instance_get_color"),&VisualServer::multimesh_instance_get_color);
-
-
-
- ObjectTypeDB::bind_method(_MD("particles_create"),&VisualServer::particles_create);
- ObjectTypeDB::bind_method(_MD("particles_set_amount"),&VisualServer::particles_set_amount);
- ObjectTypeDB::bind_method(_MD("particles_get_amount"),&VisualServer::particles_get_amount);
- ObjectTypeDB::bind_method(_MD("particles_set_emitting"),&VisualServer::particles_set_emitting);
- ObjectTypeDB::bind_method(_MD("particles_is_emitting"),&VisualServer::particles_is_emitting);
- ObjectTypeDB::bind_method(_MD("particles_set_visibility_aabb"),&VisualServer::particles_set_visibility_aabb);
- ObjectTypeDB::bind_method(_MD("particles_get_visibility_aabb"),&VisualServer::particles_get_visibility_aabb);
- ObjectTypeDB::bind_method(_MD("particles_set_variable"),&VisualServer::particles_set_variable);
- ObjectTypeDB::bind_method(_MD("particles_get_variable"),&VisualServer::particles_get_variable);
- ObjectTypeDB::bind_method(_MD("particles_set_randomness"),&VisualServer::particles_set_randomness);
- ObjectTypeDB::bind_method(_MD("particles_get_randomness"),&VisualServer::particles_get_randomness);
- ObjectTypeDB::bind_method(_MD("particles_set_color_phases"),&VisualServer::particles_set_color_phases);
- ObjectTypeDB::bind_method(_MD("particles_get_color_phases"),&VisualServer::particles_get_color_phases);
- ObjectTypeDB::bind_method(_MD("particles_set_color_phase_pos"),&VisualServer::particles_set_color_phase_pos);
- ObjectTypeDB::bind_method(_MD("particles_get_color_phase_pos"),&VisualServer::particles_get_color_phase_pos);
- ObjectTypeDB::bind_method(_MD("particles_set_color_phase_color"),&VisualServer::particles_set_color_phase_color);
- ObjectTypeDB::bind_method(_MD("particles_get_color_phase_color"),&VisualServer::particles_get_color_phase_color);
- ObjectTypeDB::bind_method(_MD("particles_set_attractors"),&VisualServer::particles_set_attractors);
- ObjectTypeDB::bind_method(_MD("particles_get_attractors"),&VisualServer::particles_get_attractors);
- ObjectTypeDB::bind_method(_MD("particles_set_attractor_pos"),&VisualServer::particles_set_attractor_pos);
- ObjectTypeDB::bind_method(_MD("particles_get_attractor_pos"),&VisualServer::particles_get_attractor_pos);
- ObjectTypeDB::bind_method(_MD("particles_set_attractor_strength"),&VisualServer::particles_set_attractor_strength);
- ObjectTypeDB::bind_method(_MD("particles_get_attractor_strength"),&VisualServer::particles_get_attractor_strength);
- ObjectTypeDB::bind_method(_MD("particles_set_material"),&VisualServer::particles_set_material,DEFVAL(false));
- ObjectTypeDB::bind_method(_MD("particles_set_height_from_velocity"),&VisualServer::particles_set_height_from_velocity);
- ObjectTypeDB::bind_method(_MD("particles_has_height_from_velocity"),&VisualServer::particles_has_height_from_velocity);
-
-
-
- ObjectTypeDB::bind_method(_MD("light_create"),&VisualServer::light_create);
- ObjectTypeDB::bind_method(_MD("light_get_type"),&VisualServer::light_get_type);
- ObjectTypeDB::bind_method(_MD("light_set_color"),&VisualServer::light_set_color);
- ObjectTypeDB::bind_method(_MD("light_get_color"),&VisualServer::light_get_color);
- ObjectTypeDB::bind_method(_MD("light_set_shadow"),&VisualServer::light_set_shadow);
- ObjectTypeDB::bind_method(_MD("light_has_shadow"),&VisualServer::light_has_shadow);
- ObjectTypeDB::bind_method(_MD("light_set_volumetric"),&VisualServer::light_set_volumetric);
- ObjectTypeDB::bind_method(_MD("light_is_volumetric"),&VisualServer::light_is_volumetric);
- ObjectTypeDB::bind_method(_MD("light_set_projector"),&VisualServer::light_set_projector);
- ObjectTypeDB::bind_method(_MD("light_get_projector"),&VisualServer::light_get_projector);
- ObjectTypeDB::bind_method(_MD("light_set_var"),&VisualServer::light_set_param);
- ObjectTypeDB::bind_method(_MD("light_get_var"),&VisualServer::light_get_param);
-
- ObjectTypeDB::bind_method(_MD("skeleton_create"),&VisualServer::skeleton_create);
- ObjectTypeDB::bind_method(_MD("skeleton_resize"),&VisualServer::skeleton_resize);
- ObjectTypeDB::bind_method(_MD("skeleton_get_bone_count"),&VisualServer::skeleton_get_bone_count);
- ObjectTypeDB::bind_method(_MD("skeleton_bone_set_transform"),&VisualServer::skeleton_bone_set_transform);
- ObjectTypeDB::bind_method(_MD("skeleton_bone_get_transform"),&VisualServer::skeleton_bone_get_transform);
-
+ PoolVector<uint8_t>::Write vw = r_vertex_array.write();
+ PoolVector<uint8_t>::Write iw;
+ if (r_index_array.size()) {
+ print_line("elements: "+itos(r_index_array.size()));
- ObjectTypeDB::bind_method(_MD("room_create"),&VisualServer::room_create);
- ObjectTypeDB::bind_method(_MD("room_set_bounds"),&VisualServer::room_set_bounds);
- ObjectTypeDB::bind_method(_MD("room_get_bounds"),&VisualServer::room_get_bounds);
-
- ObjectTypeDB::bind_method(_MD("portal_create"),&VisualServer::portal_create);
- ObjectTypeDB::bind_method(_MD("portal_set_shape"),&VisualServer::portal_set_shape);
- ObjectTypeDB::bind_method(_MD("portal_get_shape"),&VisualServer::portal_get_shape);
- ObjectTypeDB::bind_method(_MD("portal_set_enabled"),&VisualServer::portal_set_enabled);
- ObjectTypeDB::bind_method(_MD("portal_is_enabled"),&VisualServer::portal_is_enabled);
- ObjectTypeDB::bind_method(_MD("portal_set_disable_distance"),&VisualServer::portal_set_disable_distance);
- ObjectTypeDB::bind_method(_MD("portal_get_disable_distance"),&VisualServer::portal_get_disable_distance);
- ObjectTypeDB::bind_method(_MD("portal_set_disabled_color"),&VisualServer::portal_set_disabled_color);
- ObjectTypeDB::bind_method(_MD("portal_get_disabled_color"),&VisualServer::portal_get_disabled_color);
-
-
- ObjectTypeDB::bind_method(_MD("camera_create"),&VisualServer::camera_create);
- ObjectTypeDB::bind_method(_MD("camera_set_perspective"),&VisualServer::camera_set_perspective);
- ObjectTypeDB::bind_method(_MD("camera_set_orthogonal"),&VisualServer::_camera_set_orthogonal);
- ObjectTypeDB::bind_method(_MD("camera_set_transform"),&VisualServer::camera_set_transform);
-
-
- ObjectTypeDB::bind_method(_MD("viewport_create"),&VisualServer::viewport_create);
- ObjectTypeDB::bind_method(_MD("viewport_set_rect"),&VisualServer::_viewport_set_rect);
- ObjectTypeDB::bind_method(_MD("viewport_get_rect"),&VisualServer::_viewport_get_rect);
- ObjectTypeDB::bind_method(_MD("viewport_attach_camera"),&VisualServer::viewport_attach_camera,DEFVAL(RID()));
- ObjectTypeDB::bind_method(_MD("viewport_get_attached_camera"),&VisualServer::viewport_get_attached_camera);
- ObjectTypeDB::bind_method(_MD("viewport_get_scenario"),&VisualServer::viewport_get_scenario);
- ObjectTypeDB::bind_method(_MD("viewport_attach_canvas"),&VisualServer::viewport_attach_canvas);
- ObjectTypeDB::bind_method(_MD("viewport_remove_canvas"),&VisualServer::viewport_remove_canvas);
- ObjectTypeDB::bind_method(_MD("viewport_set_global_canvas_transform"),&VisualServer::viewport_set_global_canvas_transform);
-
- ObjectTypeDB::bind_method(_MD("scenario_create"),&VisualServer::scenario_create);
- ObjectTypeDB::bind_method(_MD("scenario_set_debug"),&VisualServer::scenario_set_debug);
-
-
- ObjectTypeDB::bind_method(_MD("instance_create"),&VisualServer::instance_create,DEFVAL(RID()));
- ObjectTypeDB::bind_method(_MD("instance_get_base"),&VisualServer::instance_get_base);
- ObjectTypeDB::bind_method(_MD("instance_get_base_aabb"),&VisualServer::instance_get_base);
- ObjectTypeDB::bind_method(_MD("instance_set_transform"),&VisualServer::instance_set_transform);
- ObjectTypeDB::bind_method(_MD("instance_get_transform"),&VisualServer::instance_get_transform);
- ObjectTypeDB::bind_method(_MD("instance_attach_object_instance_ID"),&VisualServer::instance_attach_object_instance_ID);
- ObjectTypeDB::bind_method(_MD("instance_get_object_instance_ID"),&VisualServer::instance_get_object_instance_ID);
- ObjectTypeDB::bind_method(_MD("instance_attach_skeleton"),&VisualServer::instance_attach_skeleton);
- ObjectTypeDB::bind_method(_MD("instance_get_skeleton"),&VisualServer::instance_get_skeleton);
- ObjectTypeDB::bind_method(_MD("instance_set_room"),&VisualServer::instance_set_room);
- ObjectTypeDB::bind_method(_MD("instance_get_room"),&VisualServer::instance_get_room);
-
- ObjectTypeDB::bind_method(_MD("instance_set_exterior"),&VisualServer::instance_set_exterior);
- ObjectTypeDB::bind_method(_MD("instance_is_exterior"),&VisualServer::instance_is_exterior);
-
- ObjectTypeDB::bind_method(_MD("instances_cull_aabb"),&VisualServer::instances_cull_aabb);
- ObjectTypeDB::bind_method(_MD("instances_cull_ray"),&VisualServer::instances_cull_ray);
- ObjectTypeDB::bind_method(_MD("instances_cull_convex"),&VisualServer::instances_cull_convex);
-
-
-
- ObjectTypeDB::bind_method(_MD("instance_geometry_override_material_param"),&VisualServer::instance_get_room);
- ObjectTypeDB::bind_method(_MD("instance_geometry_get_material_param"),&VisualServer::instance_get_room);
-
- ObjectTypeDB::bind_method(_MD("get_test_cube"),&VisualServer::get_test_cube);
-
-#endif
- ObjectTypeDB::bind_method(_MD("canvas_create"),&VisualServer::canvas_create);
- ObjectTypeDB::bind_method(_MD("canvas_item_create"),&VisualServer::canvas_item_create);
- ObjectTypeDB::bind_method(_MD("canvas_item_set_parent"),&VisualServer::canvas_item_set_parent);
- ObjectTypeDB::bind_method(_MD("canvas_item_get_parent"),&VisualServer::canvas_item_get_parent);
- ObjectTypeDB::bind_method(_MD("canvas_item_set_transform"),&VisualServer::canvas_item_set_transform);
- ObjectTypeDB::bind_method(_MD("canvas_item_set_custom_rect"),&VisualServer::canvas_item_set_custom_rect);
- ObjectTypeDB::bind_method(_MD("canvas_item_set_clip"),&VisualServer::canvas_item_set_clip);
- ObjectTypeDB::bind_method(_MD("canvas_item_set_opacity"),&VisualServer::canvas_item_set_opacity);
- ObjectTypeDB::bind_method(_MD("canvas_item_get_opacity"),&VisualServer::canvas_item_get_opacity);
- ObjectTypeDB::bind_method(_MD("canvas_item_set_self_opacity"),&VisualServer::canvas_item_set_self_opacity);
- ObjectTypeDB::bind_method(_MD("canvas_item_get_self_opacity"),&VisualServer::canvas_item_get_self_opacity);
- ObjectTypeDB::bind_method(_MD("canvas_item_set_z"),&VisualServer::canvas_item_set_z);
-
- ObjectTypeDB::bind_method(_MD("canvas_item_add_line"),&VisualServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false));
- ObjectTypeDB::bind_method(_MD("canvas_item_add_rect"),&VisualServer::canvas_item_add_rect);
- ObjectTypeDB::bind_method(_MD("canvas_item_add_texture_rect"),&VisualServer::canvas_item_add_texture_rect, DEFVAL(Color(1,1,1)), DEFVAL(false));
- ObjectTypeDB::bind_method(_MD("canvas_item_add_texture_rect_region"),&VisualServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1,1,1)), DEFVAL(false));
-
- ObjectTypeDB::bind_method(_MD("canvas_item_add_style_box"),&VisualServer::_canvas_item_add_style_box, DEFVAL(Color(1,1,1)));
-// ObjectTypeDB::bind_method(_MD("canvas_item_add_primitive"),&VisualServer::canvas_item_add_primitive,DEFVAL(Vector<Vector2>()),DEFVAL(RID()));
- ObjectTypeDB::bind_method(_MD("canvas_item_add_circle"),&VisualServer::canvas_item_add_circle);
-
- ObjectTypeDB::bind_method(_MD("viewport_set_canvas_transform"),&VisualServer::viewport_set_canvas_transform);
-
- ObjectTypeDB::bind_method(_MD("canvas_item_clear"),&VisualServer::canvas_item_clear);
- ObjectTypeDB::bind_method(_MD("canvas_item_raise"),&VisualServer::canvas_item_raise);
-
-
- ObjectTypeDB::bind_method(_MD("cursor_set_rotation"),&VisualServer::cursor_set_rotation);
- ObjectTypeDB::bind_method(_MD("cursor_set_texture"),&VisualServer::cursor_set_texture);
- ObjectTypeDB::bind_method(_MD("cursor_set_visible"),&VisualServer::cursor_set_visible);
- ObjectTypeDB::bind_method(_MD("cursor_set_pos"),&VisualServer::cursor_set_pos);
-
- ObjectTypeDB::bind_method(_MD("black_bars_set_margins","left","top","right","bottom"),&VisualServer::black_bars_set_margins);
- ObjectTypeDB::bind_method(_MD("black_bars_set_images","left","top","right","bottom"),&VisualServer::black_bars_set_images);
-
- ObjectTypeDB::bind_method(_MD("make_sphere_mesh"),&VisualServer::make_sphere_mesh);
- ObjectTypeDB::bind_method(_MD("mesh_add_surface_from_planes"),&VisualServer::mesh_add_surface_from_planes);
-
- ObjectTypeDB::bind_method(_MD("draw"),&VisualServer::draw);
- ObjectTypeDB::bind_method(_MD("sync"),&VisualServer::sync);
- ObjectTypeDB::bind_method(_MD("free_rid"),&VisualServer::free);
-
- ObjectTypeDB::bind_method(_MD("set_default_clear_color"),&VisualServer::set_default_clear_color);
-
- ObjectTypeDB::bind_method(_MD("get_render_info"),&VisualServer::get_render_info);
-
- BIND_CONSTANT( NO_INDEX_ARRAY );
- BIND_CONSTANT( CUSTOM_ARRAY_SIZE );
- BIND_CONSTANT( ARRAY_WEIGHTS_SIZE );
- BIND_CONSTANT( MAX_PARTICLE_COLOR_PHASES );
- BIND_CONSTANT( MAX_PARTICLE_ATTRACTORS );
- BIND_CONSTANT( MAX_CURSORS );
-
- BIND_CONSTANT( TEXTURE_FLAG_MIPMAPS );
- BIND_CONSTANT( TEXTURE_FLAG_REPEAT );
- BIND_CONSTANT( TEXTURE_FLAG_FILTER );
- BIND_CONSTANT( TEXTURE_FLAG_CUBEMAP );
- BIND_CONSTANT( TEXTURE_FLAGS_DEFAULT );
-
- BIND_CONSTANT( CUBEMAP_LEFT );
- BIND_CONSTANT( CUBEMAP_RIGHT );
- BIND_CONSTANT( CUBEMAP_BOTTOM );
- BIND_CONSTANT( CUBEMAP_TOP );
- BIND_CONSTANT( CUBEMAP_FRONT );
- BIND_CONSTANT( CUBEMAP_BACK );
-
- BIND_CONSTANT( SHADER_MATERIAL ); ///< param 0: name
- BIND_CONSTANT( SHADER_POST_PROCESS ); ///< param 0: name
-
- BIND_CONSTANT( MATERIAL_FLAG_VISIBLE );
- BIND_CONSTANT( MATERIAL_FLAG_DOUBLE_SIDED );
- BIND_CONSTANT( MATERIAL_FLAG_INVERT_FACES );
- BIND_CONSTANT( MATERIAL_FLAG_UNSHADED );
- BIND_CONSTANT( MATERIAL_FLAG_ONTOP );
- BIND_CONSTANT( MATERIAL_FLAG_MAX );
-
- BIND_CONSTANT( MATERIAL_BLEND_MODE_MIX );
- BIND_CONSTANT( MATERIAL_BLEND_MODE_ADD );
- BIND_CONSTANT( MATERIAL_BLEND_MODE_SUB );
- BIND_CONSTANT( MATERIAL_BLEND_MODE_MUL );
-
- BIND_CONSTANT( FIXED_MATERIAL_PARAM_DIFFUSE );
- BIND_CONSTANT( FIXED_MATERIAL_PARAM_DETAIL );
- BIND_CONSTANT( FIXED_MATERIAL_PARAM_SPECULAR );
- BIND_CONSTANT( FIXED_MATERIAL_PARAM_EMISSION );
- BIND_CONSTANT( FIXED_MATERIAL_PARAM_SPECULAR_EXP );
- BIND_CONSTANT( FIXED_MATERIAL_PARAM_GLOW );
- BIND_CONSTANT( FIXED_MATERIAL_PARAM_NORMAL );
- BIND_CONSTANT( FIXED_MATERIAL_PARAM_SHADE_PARAM );
- BIND_CONSTANT( FIXED_MATERIAL_PARAM_MAX );
-
-
-
- BIND_CONSTANT( FIXED_MATERIAL_TEXCOORD_SPHERE );
- BIND_CONSTANT( FIXED_MATERIAL_TEXCOORD_UV );
- BIND_CONSTANT( FIXED_MATERIAL_TEXCOORD_UV_TRANSFORM );
- BIND_CONSTANT( FIXED_MATERIAL_TEXCOORD_UV2 );
-
-
- BIND_CONSTANT( ARRAY_VERTEX );
- BIND_CONSTANT( ARRAY_NORMAL );
- BIND_CONSTANT( ARRAY_TANGENT );
- BIND_CONSTANT( ARRAY_COLOR );
- BIND_CONSTANT( ARRAY_TEX_UV );
- BIND_CONSTANT( ARRAY_BONES );
- BIND_CONSTANT( ARRAY_WEIGHTS );
- BIND_CONSTANT( ARRAY_INDEX );
- BIND_CONSTANT( ARRAY_MAX );
-
- BIND_CONSTANT( ARRAY_FORMAT_VERTEX );
- BIND_CONSTANT( ARRAY_FORMAT_NORMAL );
- BIND_CONSTANT( ARRAY_FORMAT_TANGENT );
- BIND_CONSTANT( ARRAY_FORMAT_COLOR );
- BIND_CONSTANT( ARRAY_FORMAT_TEX_UV );
- BIND_CONSTANT( ARRAY_FORMAT_BONES );
- BIND_CONSTANT( ARRAY_FORMAT_WEIGHTS );
- BIND_CONSTANT( ARRAY_FORMAT_INDEX );
-
- BIND_CONSTANT( PRIMITIVE_POINTS );
- BIND_CONSTANT( PRIMITIVE_LINES );
- BIND_CONSTANT( PRIMITIVE_LINE_STRIP );
- BIND_CONSTANT( PRIMITIVE_LINE_LOOP );
- BIND_CONSTANT( PRIMITIVE_TRIANGLES );
- BIND_CONSTANT( PRIMITIVE_TRIANGLE_STRIP );
- BIND_CONSTANT( PRIMITIVE_TRIANGLE_FAN );
- BIND_CONSTANT( PRIMITIVE_MAX );
-
- BIND_CONSTANT( PARTICLE_LIFETIME );
- BIND_CONSTANT( PARTICLE_SPREAD );
- BIND_CONSTANT( PARTICLE_GRAVITY );
- BIND_CONSTANT( PARTICLE_LINEAR_VELOCITY );
- BIND_CONSTANT( PARTICLE_ANGULAR_VELOCITY );
- BIND_CONSTANT( PARTICLE_LINEAR_ACCELERATION );
- BIND_CONSTANT( PARTICLE_RADIAL_ACCELERATION );
- BIND_CONSTANT( PARTICLE_TANGENTIAL_ACCELERATION );
- BIND_CONSTANT( PARTICLE_INITIAL_SIZE );
- BIND_CONSTANT( PARTICLE_FINAL_SIZE );
- BIND_CONSTANT( PARTICLE_INITIAL_ANGLE );
- BIND_CONSTANT( PARTICLE_HEIGHT );
- BIND_CONSTANT( PARTICLE_HEIGHT_SPEED_SCALE );
- BIND_CONSTANT( PARTICLE_VAR_MAX );
-
- BIND_CONSTANT( LIGHT_DIRECTIONAL );
- BIND_CONSTANT( LIGHT_OMNI );
- BIND_CONSTANT( LIGHT_SPOT );
-
-
- BIND_CONSTANT( LIGHT_COLOR_DIFFUSE );
- BIND_CONSTANT( LIGHT_COLOR_SPECULAR );
-
- BIND_CONSTANT( LIGHT_PARAM_SPOT_ATTENUATION );
- BIND_CONSTANT( LIGHT_PARAM_SPOT_ANGLE );
- BIND_CONSTANT( LIGHT_PARAM_RADIUS );
- BIND_CONSTANT( LIGHT_PARAM_ENERGY );
- BIND_CONSTANT( LIGHT_PARAM_ATTENUATION );
- BIND_CONSTANT( LIGHT_PARAM_MAX );
-
- BIND_CONSTANT( SCENARIO_DEBUG_DISABLED );
- BIND_CONSTANT( SCENARIO_DEBUG_WIREFRAME );
- BIND_CONSTANT( SCENARIO_DEBUG_OVERDRAW );
-
- BIND_CONSTANT( INSTANCE_MESH );
- BIND_CONSTANT( INSTANCE_MULTIMESH );
-
- BIND_CONSTANT( INSTANCE_PARTICLES );
- BIND_CONSTANT( INSTANCE_LIGHT );
- BIND_CONSTANT( INSTANCE_ROOM );
- BIND_CONSTANT( INSTANCE_PORTAL );
- BIND_CONSTANT( INSTANCE_GEOMETRY_MASK );
-
-
- BIND_CONSTANT( INFO_OBJECTS_IN_FRAME );
- BIND_CONSTANT( INFO_VERTICES_IN_FRAME );
- BIND_CONSTANT( INFO_MATERIAL_CHANGES_IN_FRAME );
- BIND_CONSTANT( INFO_SHADER_CHANGES_IN_FRAME );
- BIND_CONSTANT( INFO_SURFACE_CHANGES_IN_FRAME );
- BIND_CONSTANT( INFO_DRAW_CALLS_IN_FRAME );
- BIND_CONSTANT( INFO_USAGE_VIDEO_MEM_TOTAL );
- BIND_CONSTANT( INFO_VIDEO_MEM_USED );
- BIND_CONSTANT( INFO_TEXTURE_MEM_USED );
- BIND_CONSTANT( INFO_VERTEX_MEM_USED );
+ iw=r_index_array.write();
+
+ }
+
+ int max_bone=0;
+
+
+ for(int ai=0;ai<VS::ARRAY_MAX;ai++) {
+
+ if (!(p_format&(1<<ai))) // no array
+ continue;
+
+
+ switch(ai) {
+
+ case VS::ARRAY_VERTEX: {
+
+ if (p_format& VS::ARRAY_FLAG_USE_2D_VERTICES) {
+
+ PoolVector<Vector2> array = p_arrays[ai];
+ ERR_FAIL_COND_V( array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER );
+
+
+ PoolVector<Vector2>::Read read = array.read();
+ const Vector2* src=read.ptr();
+
+ // setting vertices means regenerating the AABB
+ Rect2 aabb;
+
+
+ if (p_format&ARRAY_COMPRESS_VERTEX) {
+
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+
+ uint16_t vector[2]={ Math::make_half_float(src[i].x), Math::make_half_float(src[i].y) };
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], vector, sizeof(uint16_t)*2);
+
+ if (i==0) {
+
+ aabb=Rect2(src[i],Vector2());
+ } else {
+
+ aabb.expand_to( src[i] );
+ }
+ }
+
+
+ } else {
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+
+ float vector[2]={ src[i].x, src[i].y };
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], vector, sizeof(float)*2);
+
+ if (i==0) {
+
+ aabb=Rect2(src[i],Vector2());
+ } else {
+
+ aabb.expand_to( src[i] );
+ }
+ }
+ }
+
+ r_aabb=Rect3(Vector3(aabb.pos.x,aabb.pos.y,0),Vector3(aabb.size.x,aabb.size.y,0));
+
+
+ } else {
+ PoolVector<Vector3> array = p_arrays[ai];
+ ERR_FAIL_COND_V( array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER );
+
+
+ PoolVector<Vector3>::Read read = array.read();
+ const Vector3* src=read.ptr();
+
+ // setting vertices means regenerating the AABB
+ Rect3 aabb;
+
+
+ if (p_format&ARRAY_COMPRESS_VERTEX) {
+
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+
+ uint16_t vector[4]={ Math::make_half_float(src[i].x), Math::make_half_float(src[i].y), Math::make_half_float(src[i].z), Math::make_half_float(1.0) };
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], vector, sizeof(uint16_t)*4);
+
+ if (i==0) {
+
+ aabb=Rect3(src[i],Vector3());
+ } else {
+
+ aabb.expand_to( src[i] );
+ }
+ }
+
+
+ } else {
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+
+ float vector[3]={ src[i].x, src[i].y, src[i].z };
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], vector, sizeof(float)*3);
+
+ if (i==0) {
+
+ aabb=Rect3(src[i],Vector3());
+ } else {
+
+ aabb.expand_to( src[i] );
+ }
+ }
+ }
+
+ r_aabb=aabb;
+
+ }
+
+
+ } break;
+ case VS::ARRAY_NORMAL: {
+
+ ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_VECTOR3_ARRAY, ERR_INVALID_PARAMETER );
+
+ PoolVector<Vector3> array = p_arrays[ai];
+ ERR_FAIL_COND_V( array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER );
+
+
+ PoolVector<Vector3>::Read read = array.read();
+ const Vector3* src=read.ptr();
+
+ // setting vertices means regenerating the AABB
+
+ if (p_format&ARRAY_COMPRESS_NORMAL) {
+
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+ uint8_t vector[4]={
+ CLAMP(src[i].x*127,-128,127),
+ CLAMP(src[i].y*127,-128,127),
+ CLAMP(src[i].z*127,-128,127),
+ 0,
+ };
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], vector, 4);
+
+ }
+
+ } else {
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+
+ float vector[3]={ src[i].x, src[i].y, src[i].z };
+ copymem(&vw[p_offsets[ai]+i*p_stride], vector, 3*4);
+
+ }
+ }
+
+ } break;
+
+ case VS::ARRAY_TANGENT: {
+
+ ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_REAL_ARRAY, ERR_INVALID_PARAMETER );
+
+ PoolVector<real_t> array = p_arrays[ai];
+
+ ERR_FAIL_COND_V( array.size() != p_vertex_array_len*4, ERR_INVALID_PARAMETER );
+
+
+ PoolVector<real_t>::Read read = array.read();
+ const real_t* src = read.ptr();
+
+ if (p_format&ARRAY_COMPRESS_TANGENT) {
+
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+ uint8_t xyzw[4]={
+ CLAMP(src[i*4+0]*127,-128,127),
+ CLAMP(src[i*4+1]*127,-128,127),
+ CLAMP(src[i*4+2]*127,-128,127),
+ CLAMP(src[i*4+3]*127,-128,127)
+ };
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], xyzw, 4);
+
+ }
+
+
+ } else {
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+ float xyzw[4]={
+ src[i*4+0],
+ src[i*4+1],
+ src[i*4+2],
+ src[i*4+3]
+ };
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], xyzw, 4*4);
+
+ }
+ }
+
+ } break;
+ case VS::ARRAY_COLOR: {
+
+ ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_COLOR_ARRAY, ERR_INVALID_PARAMETER );
+
+
+ PoolVector<Color> array = p_arrays[ai];
+
+ ERR_FAIL_COND_V( array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER );
+
+
+ PoolVector<Color>::Read read = array.read();
+ const Color* src = read.ptr();
+ if (p_format&ARRAY_COMPRESS_COLOR) {
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+
+ uint8_t colors[4];
+
+ for(int j=0;j<4;j++) {
+
+ colors[j]=CLAMP( int((src[i][j])*255.0), 0,255 );
+ }
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], colors, 4);
+
+ }
+ } else {
+
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], &src[i], 4*4);
+ }
+
+ }
+
+
+ } break;
+ case VS::ARRAY_TEX_UV: {
+
+ ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::POOL_VECTOR2_ARRAY, ERR_INVALID_PARAMETER );
+
+ PoolVector<Vector2> array = p_arrays[ai];
+
+ ERR_FAIL_COND_V( array.size() != p_vertex_array_len , ERR_INVALID_PARAMETER);
+
+ PoolVector<Vector2>::Read read = array.read();
+
+ const Vector2 * src=read.ptr();
+
+
+
+ if (p_format&ARRAY_COMPRESS_TEX_UV) {
+
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+ uint16_t uv[2]={ Math::make_half_float(src[i].x) , Math::make_half_float(src[i].y) };
+ copymem(&vw[p_offsets[ai]+i*p_stride], uv, 2*2);
+ }
+
+ } else {
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+ float uv[2]={ src[i].x , src[i].y };
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], uv, 2*4);
+
+ }
+ }
+
+
+ } break;
+
+ case VS::ARRAY_TEX_UV2: {
+
+
+ ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::POOL_VECTOR2_ARRAY, ERR_INVALID_PARAMETER );
+
+ PoolVector<Vector2> array = p_arrays[ai];
+
+ ERR_FAIL_COND_V( array.size() != p_vertex_array_len , ERR_INVALID_PARAMETER);
+
+ PoolVector<Vector2>::Read read = array.read();
+
+ const Vector2 * src=read.ptr();
+
+
+
+ if (p_format&ARRAY_COMPRESS_TEX_UV2) {
+
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+ uint16_t uv[2]={ Math::make_half_float(src[i].x) , Math::make_half_float(src[i].y) };
+ copymem(&vw[p_offsets[ai]+i*p_stride], uv, 2*2);
+ }
+
+ } else {
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+ float uv[2]={ src[i].x , src[i].y };
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], uv, 2*4);
+
+ }
+ }
+ } break;
+ case VS::ARRAY_WEIGHTS: {
+
+ ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_REAL_ARRAY, ERR_INVALID_PARAMETER );
+
+ PoolVector<real_t> array = p_arrays[ai];
+
+ ERR_FAIL_COND_V( array.size() != p_vertex_array_len*VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER );
+
+
+ PoolVector<real_t>::Read read = array.read();
+
+ const real_t * src = read.ptr();
+
+ if (p_format&ARRAY_COMPRESS_WEIGHTS) {
+
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+ uint16_t data[VS::ARRAY_WEIGHTS_SIZE];
+ for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) {
+ data[j]=CLAMP(src[i*VS::ARRAY_WEIGHTS_SIZE+j]*65535,0,65535);
+ }
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], data, 2*4);
+ }
+ } else {
+
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+ float data[VS::ARRAY_WEIGHTS_SIZE];
+ for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) {
+ data[j]=src[i*VS::ARRAY_WEIGHTS_SIZE+j];
+ }
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], data, 4*4);
+
+
+ }
+ }
+
+ } break;
+ case VS::ARRAY_BONES: {
+
+ ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_INT_ARRAY && p_arrays[ai].get_type() != Variant::POOL_REAL_ARRAY, ERR_INVALID_PARAMETER );
+
+ PoolVector<int> array = p_arrays[ai];
+
+ ERR_FAIL_COND_V( array.size() != p_vertex_array_len*VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER );
+
+
+ PoolVector<int>::Read read = array.read();
+
+ const int * src = read.ptr();
+
+
+ if (!(p_format&ARRAY_FLAG_USE_16_BIT_BONES)) {
+
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+ uint8_t data[VS::ARRAY_WEIGHTS_SIZE];
+ for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) {
+ data[j]=CLAMP(src[i*VS::ARRAY_WEIGHTS_SIZE+j],0,255);
+ max_bone=MAX(data[j],max_bone);
+
+ }
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], data, 4);
+
+
+ }
+
+ } else {
+ for (int i=0;i<p_vertex_array_len;i++) {
+
+ uint16_t data[VS::ARRAY_WEIGHTS_SIZE];
+ for (int j=0;j<VS::ARRAY_WEIGHTS_SIZE;j++) {
+ data[j]=src[i*VS::ARRAY_WEIGHTS_SIZE+j];
+ max_bone=MAX(data[j],max_bone);
+
+ }
+
+ copymem(&vw[p_offsets[ai]+i*p_stride], data, 2*4);
+
+
+ }
+ }
+
+
+ } break;
+ case VS::ARRAY_INDEX: {
+
+
+ ERR_FAIL_COND_V( p_index_array_len<=0, ERR_INVALID_DATA );
+ ERR_FAIL_COND_V( p_arrays[ai].get_type() != Variant::POOL_INT_ARRAY, ERR_INVALID_PARAMETER );
+
+ PoolVector<int> indices = p_arrays[ai];
+ ERR_FAIL_COND_V( indices.size() == 0, ERR_INVALID_PARAMETER );
+ ERR_FAIL_COND_V( indices.size() != p_index_array_len, ERR_INVALID_PARAMETER );
+
+ /* determine wether using 16 or 32 bits indices */
+
+ PoolVector<int>::Read read = indices.read();
+ const int *src=read.ptr();
+
+ for (int i=0;i<p_index_array_len;i++) {
+
+
+ if (p_vertex_array_len<(1<<16)) {
+ uint16_t v=src[i];
+
+ copymem(&iw[i*2], &v, 2);
+ } else {
+ uint32_t v=src[i];
+
+ copymem(&iw[i*4], &v, 4);
+ }
+ }
+ } break;
+ default: {
+ ERR_FAIL_V( ERR_INVALID_DATA );
+ }
+ }
+ }
+
+
+ if (p_format&VS::ARRAY_FORMAT_BONES) {
+ //create AABBs for each detected bone
+ int total_bones = max_bone+1;
+
+ bool first = r_bone_aabb.size()==0;
+
+ r_bone_aabb.resize(total_bones);
+
+ if (first) {
+ for(int i=0;i<total_bones;i++) {
+ r_bone_aabb[i].size==Vector3(-1,-1,-1); //negative means unused
+ }
+ }
+
+ PoolVector<Vector3> vertices = p_arrays[VS::ARRAY_VERTEX];
+ PoolVector<int> bones = p_arrays[VS::ARRAY_BONES];
+ PoolVector<float> weights = p_arrays[VS::ARRAY_WEIGHTS];
+
+ bool any_valid=false;
+
+ if (vertices.size() && bones.size()==vertices.size()*4 && weights.size()==bones.size()) {
+
+ int vs = vertices.size();
+ PoolVector<Vector3>::Read rv =vertices.read();
+ PoolVector<int>::Read rb=bones.read();
+ PoolVector<float>::Read rw=weights.read();
+
+ Rect3 *bptr = r_bone_aabb.ptr();
+
+ for(int i=0;i<vs;i++) {
+
+ Vector3 v = rv[i];
+ for(int j=0;j<4;j++) {
+
+ int idx = rb[i*4+j];
+ float w = rw[i*4+j];
+ if (w==0)
+ continue;//break;
+ ERR_FAIL_INDEX_V(idx,total_bones,ERR_INVALID_DATA);
+
+ if (bptr->size.x<0) {
+ //first
+ bptr[idx]=Rect3();
+ bptr[idx].pos=v;
+ any_valid=true;
+ } else {
+ bptr[idx].expand_to(v);
+ }
+ }
+ }
+ }
+
+ if (!any_valid && first) {
+
+ r_bone_aabb.clear();
+ }
+ }
+ return OK;
}
-void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate) {
- ERR_FAIL_COND(p_margins.size()!=4);
- canvas_item_add_style_box(p_item,p_rect,p_source,p_texture,Vector2(p_margins[0],p_margins[1]),Vector2(p_margins[2],p_margins[3]),true,p_modulate);
+void VisualServer::mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,uint32_t p_compress_format) {
+
+ ERR_FAIL_INDEX( p_primitive, VS::PRIMITIVE_MAX );
+ ERR_FAIL_COND(p_arrays.size()!=VS::ARRAY_MAX);
+
+ uint32_t format=0;
+
+ // validation
+ int index_array_len=0;
+ int array_len=0;
+
+ for(int i=0;i<p_arrays.size();i++) {
+
+ if (p_arrays[i].get_type()==Variant::NIL)
+ continue;
+
+ format|=(1<<i);
+
+ if (i==VS::ARRAY_VERTEX) {
+
+ Variant var = p_arrays[i];
+ switch(var.get_type()) {
+ case Variant::POOL_VECTOR2_ARRAY: {
+ PoolVector<Vector2> v2 = var;
+ array_len=v2.size();
+ } break;
+ case Variant::POOL_VECTOR3_ARRAY: {
+ PoolVector<Vector3> v3 = var;
+ array_len=v3.size();
+ } break;
+ default: {
+ Array v = var;
+ array_len=v.size();
+ } break;
+ }
+
+ array_len=PoolVector3Array(p_arrays[i]).size();
+ ERR_FAIL_COND(array_len==0);
+ } else if (i==VS::ARRAY_INDEX) {
+
+ index_array_len=PoolIntArray(p_arrays[i]).size();
+ }
+ }
+
+ ERR_FAIL_COND((format&VS::ARRAY_FORMAT_VERTEX)==0); // mandatory
+
+
+ if (p_blend_shapes.size()) {
+ //validate format for morphs
+ for(int i=0;i<p_blend_shapes.size();i++) {
+
+ uint32_t bsformat=0;
+ Array arr = p_blend_shapes[i];
+ for(int j=0;j<arr.size();j++) {
+
+
+ if (arr[j].get_type()!=Variant::NIL)
+ bsformat|=(1<<j);
+ }
+
+ ERR_FAIL_COND( (bsformat)!=(format&(VS::ARRAY_FORMAT_INDEX-1)));
+ }
+ }
+
+ uint32_t offsets[VS::ARRAY_MAX];
+
+ int total_elem_size=0;
+
+ for (int i=0;i<VS::ARRAY_MAX;i++) {
+
+
+ offsets[i]=0; //reset
+
+ if (!(format&(1<<i))) // no array
+ continue;
+
+
+ int elem_size=0;
+
+ switch(i) {
+
+ case VS::ARRAY_VERTEX: {
+
+ Variant arr = p_arrays[0];
+ if (arr.get_type()==Variant::POOL_VECTOR2_ARRAY) {
+ elem_size=2;
+ p_compress_format|=ARRAY_FLAG_USE_2D_VERTICES;
+ } else if (arr.get_type()==Variant::POOL_VECTOR3_ARRAY) {
+ p_compress_format&=~ARRAY_FLAG_USE_2D_VERTICES;
+ elem_size=3;
+ } else {
+ elem_size=(p_compress_format&ARRAY_FLAG_USE_2D_VERTICES)?2:3;
+ }
+
+ if (p_compress_format&ARRAY_COMPRESS_VERTEX) {
+ elem_size*=sizeof(int16_t);
+ } else {
+ elem_size*=sizeof(float);
+ }
+
+ if (elem_size==6) {
+ //had to pad
+ elem_size=8;
+ }
+
+ } break;
+ case VS::ARRAY_NORMAL: {
+
+ if (p_compress_format&ARRAY_COMPRESS_NORMAL) {
+ elem_size=sizeof(uint32_t);
+ } else {
+ elem_size=sizeof(float)*3;
+ }
+
+ } break;
+
+ case VS::ARRAY_TANGENT: {
+ if (p_compress_format&ARRAY_COMPRESS_TANGENT) {
+ elem_size=sizeof(uint32_t);
+ } else {
+ elem_size=sizeof(float)*4;
+ }
+
+ } break;
+ case VS::ARRAY_COLOR: {
+
+ if (p_compress_format&ARRAY_COMPRESS_COLOR) {
+ elem_size=sizeof(uint32_t);
+ } else {
+ elem_size=sizeof(float)*4;
+ }
+ } break;
+ case VS::ARRAY_TEX_UV: {
+ if (p_compress_format&ARRAY_COMPRESS_TEX_UV) {
+ elem_size=sizeof(uint32_t);
+ } else {
+ elem_size=sizeof(float)*2;
+ }
+
+ } break;
+
+ case VS::ARRAY_TEX_UV2: {
+ if (p_compress_format&ARRAY_COMPRESS_TEX_UV2) {
+ elem_size=sizeof(uint32_t);
+ } else {
+ elem_size=sizeof(float)*2;
+ }
+
+ } break;
+ case VS::ARRAY_WEIGHTS: {
+
+ if (p_compress_format&ARRAY_COMPRESS_WEIGHTS) {
+ elem_size=sizeof(uint16_t)*4;
+ } else {
+ elem_size=sizeof(float)*4;
+ }
+
+ } break;
+ case VS::ARRAY_BONES: {
+
+ PoolVector<int> bones = p_arrays[VS::ARRAY_BONES];
+ int max_bone=0;
+
+ {
+ int bc = bones.size();
+ PoolVector<int>::Read r=bones.read();
+ for(int j=0;j<bc;j++) {
+ max_bone=MAX(r[j],max_bone);
+ }
+ }
+
+ if (max_bone > 255) {
+ p_compress_format|=ARRAY_FLAG_USE_16_BIT_BONES;
+ elem_size=sizeof(uint16_t)*4;
+ } else {
+ p_compress_format&=~ARRAY_FLAG_USE_16_BIT_BONES;
+ elem_size=sizeof(uint32_t);
+ }
+
+
+ } break;
+ case VS::ARRAY_INDEX: {
+
+ if (index_array_len<=0) {
+ ERR_PRINT("index_array_len==NO_INDEX_ARRAY");
+ break;
+ }
+ /* determine wether using 16 or 32 bits indices */
+ if (array_len>=(1<<16)) {
+
+ elem_size=4;
+
+ } else {
+ elem_size=2;
+ }
+ offsets[i]=elem_size;
+ continue;
+ } break;
+ default: {
+ ERR_FAIL( );
+ }
+ }
+
+ offsets[i]=total_elem_size;
+ total_elem_size+=elem_size;
+
+
+ }
+
+ uint32_t mask = (1<<ARRAY_MAX)-1;
+ format|=(~mask)&p_compress_format; //make the full format
+
+
+ int array_size = total_elem_size * array_len;
+
+ PoolVector<uint8_t> vertex_array;
+ vertex_array.resize(array_size);
+
+ int index_array_size = offsets[VS::ARRAY_INDEX]*index_array_len;
+
+ PoolVector<uint8_t> index_array;
+ index_array.resize(index_array_size);
+
+ Rect3 aabb;
+ Vector<Rect3> bone_aabb;
+
+ Error err = _surface_set_data(p_arrays,format,offsets,total_elem_size,vertex_array,array_len,index_array,index_array_len,aabb,bone_aabb);
+
+ if (err) {
+ ERR_EXPLAIN("Invalid array format for surface");
+ ERR_FAIL_COND(err!=OK);
+ }
+
+ Vector<PoolVector<uint8_t> > blend_shape_data;
+
+ for(int i=0;i<p_blend_shapes.size();i++) {
+
+ PoolVector<uint8_t> vertex_array_shape;
+ vertex_array_shape.resize(array_size);
+ PoolVector<uint8_t> noindex;
+
+ Rect3 laabb;
+ Error err = _surface_set_data(p_blend_shapes[i],format&~ARRAY_FORMAT_INDEX,offsets,total_elem_size,vertex_array_shape,array_len,noindex,0,laabb,bone_aabb);
+ aabb.merge_with(laabb);
+ if (err) {
+ ERR_EXPLAIN("Invalid blend shape array format for surface");
+ ERR_FAIL_COND(err!=OK);
+ }
+
+ blend_shape_data.push_back(vertex_array_shape);
+ }
+
+ mesh_add_surface(p_mesh,format,p_primitive,vertex_array,array_len,index_array,index_array_len,aabb,blend_shape_data,bone_aabb);
+
}
-void VisualServer::_camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far) {
+Array VisualServer::_get_array_from_surface(uint32_t p_format,PoolVector<uint8_t> p_vertex_data,int p_vertex_len,PoolVector<uint8_t> p_index_data,int p_index_len) const {
+
+
+ uint32_t offsets[ARRAY_MAX];
+
+ int total_elem_size=0;
+
+ for (int i=0;i<VS::ARRAY_MAX;i++) {
+
+
+ offsets[i]=0; //reset
+
+ if (!(p_format&(1<<i))) // no array
+ continue;
+
+
+ int elem_size=0;
+
+ switch(i) {
+
+ case VS::ARRAY_VERTEX: {
+
+
+ if (p_format&ARRAY_FLAG_USE_2D_VERTICES) {
+ elem_size=2;
+ } else {
+ elem_size=3;
+ }
+
+ if (p_format&ARRAY_COMPRESS_VERTEX) {
+ elem_size*=sizeof(int16_t);
+ } else {
+ elem_size*=sizeof(float);
+ }
+
+ if (elem_size==6) {
+ elem_size=8;
+ }
+
+ } break;
+ case VS::ARRAY_NORMAL: {
+
+ if (p_format&ARRAY_COMPRESS_NORMAL) {
+ elem_size=sizeof(uint32_t);
+ } else {
+ elem_size=sizeof(float)*3;
+ }
+
+ } break;
+
+ case VS::ARRAY_TANGENT: {
+ if (p_format&ARRAY_COMPRESS_TANGENT) {
+ elem_size=sizeof(uint32_t);
+ } else {
+ elem_size=sizeof(float)*4;
+ }
+
+ } break;
+ case VS::ARRAY_COLOR: {
+
+ if (p_format&ARRAY_COMPRESS_COLOR) {
+ elem_size=sizeof(uint32_t);
+ } else {
+ elem_size=sizeof(float)*4;
+ }
+ } break;
+ case VS::ARRAY_TEX_UV: {
+ if (p_format&ARRAY_COMPRESS_TEX_UV) {
+ elem_size=sizeof(uint32_t);
+ } else {
+ elem_size=sizeof(float)*2;
+ }
+
+ } break;
+
+ case VS::ARRAY_TEX_UV2: {
+ if (p_format&ARRAY_COMPRESS_TEX_UV2) {
+ elem_size=sizeof(uint32_t);
+ } else {
+ elem_size=sizeof(float)*2;
+ }
+
+ } break;
+ case VS::ARRAY_WEIGHTS: {
+
+ if (p_format&ARRAY_COMPRESS_WEIGHTS) {
+ elem_size=sizeof(uint16_t)*4;
+ } else {
+ elem_size=sizeof(float)*4;
+ }
+
+ } break;
+ case VS::ARRAY_BONES: {
+
+ if (p_format&ARRAY_FLAG_USE_16_BIT_BONES) {
+ elem_size=sizeof(uint16_t)*4;
+ } else {
+ elem_size=sizeof(uint32_t);
+ }
+
+ } break;
+ case VS::ARRAY_INDEX: {
+
+ if (p_index_len<=0) {
+ ERR_PRINT("index_array_len==NO_INDEX_ARRAY");
+ break;
+ }
+ /* determine wether using 16 or 32 bits indices */
+ if (p_vertex_len>=(1<<16)) {
+
+ elem_size=4;
+
+ } else {
+ elem_size=2;
+ }
+ offsets[i]=elem_size;
+ continue;
+ } break;
+ default: {
+ ERR_FAIL_V( Array() );
+ }
+ }
+
+ offsets[i]=total_elem_size;
+ total_elem_size+=elem_size;
+
+
+ }
+
+ Array ret;
+ ret.resize(VS::ARRAY_MAX);
+
+ PoolVector<uint8_t>::Read r = p_vertex_data.read();
+
+ for(int i=0;i<VS::ARRAY_MAX;i++) {
+
+ if (!(p_format&(1<<i)))
+ continue;
+
+
+ switch(i) {
+
+ case VS::ARRAY_VERTEX: {
+
+
+ if (p_format&ARRAY_FLAG_USE_2D_VERTICES) {
+
+ PoolVector<Vector2> arr_2d;
+ arr_2d.resize(p_vertex_len);
+
+ if (p_format&ARRAY_COMPRESS_VERTEX) {
+
+ PoolVector<Vector2>::Write w = arr_2d.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]];
+ w[j]=Vector2(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1]));
+ }
+ } else {
+
+ PoolVector<Vector2>::Write w = arr_2d.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
+ w[j]=Vector2(v[0],v[1]);
+ }
+ }
+
+ ret[i]=arr_2d;
+ } else {
+
+ PoolVector<Vector3> arr_3d;
+ arr_3d.resize(p_vertex_len);
+
+ if (p_format&ARRAY_COMPRESS_VERTEX) {
+
+ PoolVector<Vector3>::Write w = arr_3d.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]];
+ w[j]=Vector3(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1]),Math::halfptr_to_float(&v[2]));
+ }
+ } else {
+
+ PoolVector<Vector3>::Write w = arr_3d.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
+ w[j]=Vector3(v[0],v[1],v[2]);
+ }
+ }
+
+ ret[i]=arr_3d;
+ }
+
+
+ } break;
+ case VS::ARRAY_NORMAL: {
+ PoolVector<Vector3> arr;
+ arr.resize(p_vertex_len);
+
+ if (p_format&ARRAY_COMPRESS_NORMAL) {
+
+ PoolVector<Vector3>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]];
+ w[j]=Vector3( float(v[0]/255.0)*2.0-1.0, float(v[1]/255.0)*2.0-1.0, float(v[2]/255.0)*2.0-1.0 );
+ }
+ } else {
+ PoolVector<Vector3>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
+ w[j]=Vector3(v[0],v[1],v[2]);
+ }
+ }
+
+ ret[i]=arr;
+
+ } break;
+
+ case VS::ARRAY_TANGENT: {
+ PoolVector<float> arr;
+ arr.resize(p_vertex_len*4);
+ if (p_format&ARRAY_COMPRESS_TANGENT) {
+ PoolVector<float>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]];
+ for(int k=0;k<4;k++) {
+ w[j*4+k]=float(v[k]/255.0)*2.0-1.0;
+ }
+ }
+ } else {
+
+ PoolVector<float>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+ const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
+ for(int k=0;k<4;k++) {
+ w[j*4+k]=v[k];
+ }
+ }
+
+ }
+
+ ret[i]=arr;
+
+ } break;
+ case VS::ARRAY_COLOR: {
+
+ PoolVector<Color> arr;
+ arr.resize(p_vertex_len);
+
+ if (p_format&ARRAY_COMPRESS_COLOR) {
+
+ PoolVector<Color>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]];
+ w[j]=Color( float(v[0]/255.0)*2.0-1.0, float(v[1]/255.0)*2.0-1.0, float(v[2]/255.0)*2.0-1.0, float(v[3]/255.0)*2.0-1.0 );
+ }
+ } else {
+ PoolVector<Color>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
+ w[j]=Color(v[0],v[1],v[2],v[3]);
+ }
+ }
+
+ ret[i]=arr;
+ } break;
+ case VS::ARRAY_TEX_UV: {
+
+ PoolVector<Vector2> arr;
+ arr.resize(p_vertex_len);
+
+ if (p_format&ARRAY_COMPRESS_TEX_UV) {
+
+ PoolVector<Vector2>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]];
+ w[j]=Vector2(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1]));
+ }
+ } else {
+
+ PoolVector<Vector2>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
+ w[j]=Vector2(v[0],v[1]);
+ }
+ }
+
+ ret[i]=arr;
+ } break;
+
+ case VS::ARRAY_TEX_UV2: {
+ PoolVector<Vector2> arr;
+ arr.resize(p_vertex_len);
+
+ if (p_format&ARRAY_COMPRESS_TEX_UV2) {
+
+ PoolVector<Vector2>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]];
+ w[j]=Vector2(Math::halfptr_to_float(&v[0]),Math::halfptr_to_float(&v[1]));
+ }
+ } else {
+
+ PoolVector<Vector2>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
+ w[j]=Vector2(v[0],v[1]);
+ }
+ }
+
+ ret[i]=arr;
+
+ } break;
+ case VS::ARRAY_WEIGHTS: {
+
+ PoolVector<float> arr;
+ arr.resize(p_vertex_len*4);
+ if (p_format&ARRAY_COMPRESS_WEIGHTS) {
+ PoolVector<float>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]];
+ for(int k=0;k<4;k++) {
+ w[j*4+k]=float(v[k]/65535.0)*2.0-1.0;
+ }
+ }
+ } else {
+
+ PoolVector<float>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+ const float *v = (const float*)&r[j*total_elem_size+offsets[i]];
+ for(int k=0;k<4;k++) {
+ w[j*4+k]=v[k];
+ }
+ }
+
+ }
+
+ ret[i]=arr;
+
+ } break;
+ case VS::ARRAY_BONES: {
+
+ PoolVector<int> arr;
+ arr.resize(p_vertex_len*4);
+ if (p_format&ARRAY_FLAG_USE_16_BIT_BONES) {
+
+ PoolVector<int>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+
+ const uint16_t *v = (const uint16_t*)&r[j*total_elem_size+offsets[i]];
+ for(int k=0;k<4;k++) {
+ w[j*4+k]=v[k];
+ }
+ }
+ } else {
+
+ PoolVector<int>::Write w = arr.write();
+
+ for(int j=0;j<p_vertex_len;j++) {
+ const uint8_t *v = (const uint8_t*)&r[j*total_elem_size+offsets[i]];
+ for(int k=0;k<4;k++) {
+ w[j*4+k]=v[k];
+ }
+ }
+
+ }
+
+ ret[i]=arr;
+
+ } break;
+ case VS::ARRAY_INDEX: {
+ /* determine wether using 16 or 32 bits indices */
+
+ PoolVector<uint8_t>::Read ir = p_index_data.read();
+
+ PoolVector<int> arr;
+ arr.resize(p_index_len);
+ if (p_vertex_len<(1<<16)) {
+
+ PoolVector<int>::Write w = arr.write();
+
+ for(int j=0;j<p_index_len;j++) {
+
+ const uint16_t *v = (const uint16_t*)&ir[j*2];
+ w[j]=*v;
+ }
+ } else {
+
+ PoolVector<int>::Write w = arr.write();
+
+ for(int j=0;j<p_index_len;j++) {
+ const int *v = (const int*)&ir[j*4];
+ w[j]=*v;
+ }
+
+ }
+ ret[i]=arr;
+ } break;
+ default: {
+ ERR_FAIL_V( ret );
+ }
+ }
+ }
+
+ return ret;
+}
+
+Array VisualServer::mesh_surface_get_arrays(RID p_mesh,int p_surface) const {
+
+ PoolVector<uint8_t> vertex_data = mesh_surface_get_array(p_mesh,p_surface);
+ ERR_FAIL_COND_V(vertex_data.size()==0,Array());
+ int vertex_len = mesh_surface_get_array_len(p_mesh,p_surface);
+
+ PoolVector<uint8_t> index_data = mesh_surface_get_index_array(p_mesh,p_surface);
+ int index_len = mesh_surface_get_array_index_len(p_mesh,p_surface);
+
+ uint32_t format = mesh_surface_get_format(p_mesh,p_surface);
+
+
+ return _get_array_from_surface(format,vertex_data,vertex_len,index_data,index_len);
+
+}
+
+void VisualServer::_bind_methods() {
+
+
+ ClassDB::bind_method(D_METHOD("texture_create"),&VisualServer::texture_create);
+ ClassDB::bind_method(D_METHOD("texture_create_from_image"),&VisualServer::texture_create_from_image,DEFVAL( TEXTURE_FLAGS_DEFAULT ) );
+ //ClassDB::bind_method(D_METHOD("texture_allocate"),&VisualServer::texture_allocate,DEFVAL( TEXTURE_FLAGS_DEFAULT ) );
+ //ClassDB::bind_method(D_METHOD("texture_set_data"),&VisualServer::texture_blit_rect,DEFVAL( CUBEMAP_LEFT ) );
+ //ClassDB::bind_method(D_METHOD("texture_get_rect"),&VisualServer::texture_get_rect );
+ ClassDB::bind_method(D_METHOD("texture_set_flags"),&VisualServer::texture_set_flags );
+ ClassDB::bind_method(D_METHOD("texture_get_flags"),&VisualServer::texture_get_flags );
+ ClassDB::bind_method(D_METHOD("texture_get_width"),&VisualServer::texture_get_width );
+ ClassDB::bind_method(D_METHOD("texture_get_height"),&VisualServer::texture_get_height );
+
+ ClassDB::bind_method(D_METHOD("texture_set_shrink_all_x2_on_set_data","shrink"),&VisualServer::texture_set_shrink_all_x2_on_set_data );
+
+
+
- camera_set_orthogonal(p_camera,p_size,p_z_near,p_z_far);
}
-void VisualServer::_viewport_set_rect(RID p_viewport,const Rect2& p_rect) {
+void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate) {
- ViewportRect r;
- r.x=p_rect.pos.x;
- r.y=p_rect.pos.y;
- r.width=p_rect.size.x;
- r.height=p_rect.size.y;
- viewport_set_rect(p_viewport,r);
+ ERR_FAIL_COND(p_margins.size()!=4);
+ //canvas_item_add_style_box(p_item,p_rect,p_source,p_texture,Vector2(p_margins[0],p_margins[1]),Vector2(p_margins[2],p_margins[3]),true,p_modulate);
}
-Rect2 VisualServer::_viewport_get_rect(RID p_viewport) const {
- ViewportRect r=viewport_get_rect(p_viewport);
- return Rect2(r.x,r.y,r.width,r.height);
+void VisualServer::_camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far) {
+
+ camera_set_orthogonal(p_camera,p_size,p_z_near,p_z_far);
}
@@ -738,8 +1601,8 @@ Rect2 VisualServer::_viewport_get_rect(RID p_viewport) const {
void VisualServer::mesh_add_surface_from_mesh_data( RID p_mesh, const Geometry::MeshData& p_mesh_data) {
#if 1
- DVector<Vector3> vertices;
- DVector<Vector3> normals;
+ PoolVector<Vector3> vertices;
+ PoolVector<Vector3> normals;
for (int i=0;i<p_mesh_data.faces.size();i++) {
@@ -761,12 +1624,12 @@ void VisualServer::mesh_add_surface_from_mesh_data( RID p_mesh, const Geometry::
d.resize(VS::ARRAY_MAX);
d[ARRAY_VERTEX]=vertices;
d[ARRAY_NORMAL]=normals;
- mesh_add_surface(p_mesh,PRIMITIVE_TRIANGLES, d);
+ mesh_add_surface_from_arrays(p_mesh,PRIMITIVE_TRIANGLES, d);
#else
- DVector<Vector3> vertices;
+ PoolVector<Vector3> vertices;
@@ -789,7 +1652,7 @@ void VisualServer::mesh_add_surface_from_mesh_data( RID p_mesh, const Geometry::
}
-void VisualServer::mesh_add_surface_from_planes( RID p_mesh, const DVector<Plane>& p_planes) {
+void VisualServer::mesh_add_surface_from_planes( RID p_mesh, const PoolVector<Plane>& p_planes) {
Geometry::MeshData mdata = Geometry::build_convex_mesh(p_planes);
@@ -797,6 +1660,10 @@ void VisualServer::mesh_add_surface_from_planes( RID p_mesh, const DVector<Plane
}
+void VisualServer::immediate_vertex_2d(RID p_immediate,const Vector2& p_vertex) {
+ immediate_vertex(p_immediate,Vector3(p_vertex.x,p_vertex.y,0));
+}
+
RID VisualServer::instance_create2(RID p_base, RID p_scenario) {
RID instance = instance_create();
@@ -808,11 +1675,8 @@ RID VisualServer::instance_create2(RID p_base, RID p_scenario) {
VisualServer::VisualServer() {
-// ERR_FAIL_COND(singleton);
+ //ERR_FAIL_COND(singleton);
singleton=this;
- mm_policy=GLOBAL_DEF("render/mipmap_policy",0);
- if (mm_policy<0 || mm_policy>2)
- mm_policy=0;
}
diff --git a/servers/visual_server.h b/servers/visual_server.h
index 2f3d8371f6..08cf34a653 100644
--- a/servers/visual_server.h
+++ b/servers/visual_server.h
@@ -5,7 +5,7 @@
/* GODOT ENGINE */
/* http://www.godotengine.org */
/*************************************************************************/
-/* Copyright (c) 2007-2016 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2007-2017 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
@@ -42,17 +42,17 @@
*/
class VisualServer : public Object {
- OBJ_TYPE( VisualServer, Object );
+ GDCLASS( VisualServer, Object );
static VisualServer *singleton;
int mm_policy;
- DVector<String> _shader_get_param_list(RID p_shader) const;
+ PoolVector<String> _shader_get_param_list(RID p_shader) const;
void _camera_set_orthogonal(RID p_camera,float p_size,float p_z_near,float p_z_far);
- void _viewport_set_rect(RID p_viewport,const Rect2& p_rect);
- Rect2 _viewport_get_rect(RID p_viewport) const;
void _canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector<float>& p_margins, const Color& p_modulate=Color(1,1,1));
+ Array _get_array_from_surface(uint32_t p_format,PoolVector<uint8_t> p_vertex_data,int p_vertex_len,PoolVector<uint8_t> p_index_data,int p_index_len) const;
+
protected:
RID _make_test_cube();
void _free_internal_rids();
@@ -61,6 +61,9 @@ protected:
RID test_material;
RID material_2d[16];
+
+ Error _surface_set_data(Array p_arrays,uint32_t p_format,uint32_t *p_offsets,uint32_t p_stride,PoolVector<uint8_t> &r_vertex_array,int p_vertex_array_len,PoolVector<uint8_t> &r_index_array,int p_index_array_len,Rect3 &r_aabb,Vector<Rect3> r_bone_aabb);
+
static VisualServer* (*create_func)();
static void _bind_methods();
public:
@@ -68,28 +71,16 @@ public:
static VisualServer *get_singleton();
static VisualServer *create();
- enum MipMapPolicy {
-
- MIPMAPS_ENABLED,
- MIPMAPS_ENABLED_FOR_PO2,
- MIPMAPS_DISABLED
- };
-
-
- virtual void set_mipmap_policy(MipMapPolicy p_policy);
- virtual MipMapPolicy get_mipmap_policy() const;
-
enum {
NO_INDEX_ARRAY=-1,
- CUSTOM_ARRAY_SIZE=8,
ARRAY_WEIGHTS_SIZE=4,
- MAX_PARTICLE_COLOR_PHASES=4,
- MAX_PARTICLE_ATTRACTORS=4,
CANVAS_ITEM_Z_MIN=-4096,
CANVAS_ITEM_Z_MAX=4096,
+ MAX_GLOW_LEVELS=7,
+
@@ -106,7 +97,7 @@ public:
TEXTURE_FLAG_CONVERT_TO_LINEAR=16,
TEXTURE_FLAG_MIRRORED_REPEAT=32, /// Repeat texture, with alternate sections mirrored
TEXTURE_FLAG_CUBEMAP=2048,
- TEXTURE_FLAG_VIDEO_SURFACE=4096,
+ TEXTURE_FLAG_USED_FOR_STREAMING=4096,
TEXTURE_FLAGS_DEFAULT=TEXTURE_FLAG_REPEAT|TEXTURE_FLAG_MIPMAPS|TEXTURE_FLAG_FILTER
};
@@ -132,14 +123,17 @@ public:
virtual uint32_t texture_get_width(RID p_texture) const=0;
virtual uint32_t texture_get_height(RID p_texture) const=0;
virtual void texture_set_size_override(RID p_texture,int p_width, int p_height)=0;
- virtual bool texture_can_stream(RID p_texture) const=0;
- virtual void texture_set_reload_hook(RID p_texture,ObjectID p_owner,const StringName& p_function) const=0;
virtual void texture_set_path(RID p_texture,const String& p_path)=0;
virtual String texture_get_path(RID p_texture) const=0;
virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable)=0;
+ typedef void (*TextureDetectCallback)(void*);
+
+ virtual void texture_set_detect_3d_callback(RID p_texture,TextureDetectCallback p_callback,void* p_userdata)=0;
+ virtual void texture_set_detect_srgb_callback(RID p_texture,TextureDetectCallback p_callback,void* p_userdata)=0;
+
struct TextureInfo {
RID texture;
Size2 size;
@@ -150,26 +144,31 @@ public:
virtual void texture_debug_usage(List<TextureInfo> *r_info)=0;
+ virtual void textures_keep_original(bool p_enable)=0;
+
+ /* SKYBOX API */
+
+ virtual RID skybox_create()=0;
+ virtual void skybox_set_texture(RID p_skybox,RID p_cube_map,int p_radiance_size)=0;
/* SHADER API */
enum ShaderMode {
- SHADER_MATERIAL,
+ SHADER_SPATIAL,
SHADER_CANVAS_ITEM,
- SHADER_POST_PROCESS,
+ SHADER_PARTICLES,
+ SHADER_MAX
};
- virtual RID shader_create(ShaderMode p_mode=SHADER_MATERIAL)=0;
+ virtual RID shader_create(ShaderMode p_mode=SHADER_SPATIAL)=0;
virtual void shader_set_mode(RID p_shader,ShaderMode p_mode)=0;
virtual ShaderMode shader_get_mode(RID p_shader) const=0;
- virtual void shader_set_code(RID p_shader, const String& p_vertex, const String& p_fragment,const String& p_light, int p_vertex_ofs=0,int p_fragment_ofs=0,int p_light_ofs=0)=0;
- virtual String shader_get_fragment_code(RID p_shader) const=0;
- virtual String shader_get_vertex_code(RID p_shader) const=0;
- virtual String shader_get_light_code(RID p_shader) const=0;
+ virtual void shader_set_code(RID p_shader, const String& p_code)=0;
+ virtual String shader_get_code(RID p_shader) const=0;
virtual void shader_get_param_list(RID p_shader, List<PropertyInfo> *p_param_list) const=0;
virtual void shader_set_default_texture_param(RID p_shader, const StringName& p_name, RID p_texture)=0;
@@ -186,113 +185,7 @@ public:
virtual void material_set_param(RID p_material, const StringName& p_param, const Variant& p_value)=0;
virtual Variant material_get_param(RID p_material, const StringName& p_param) const=0;
- enum MaterialFlag {
- MATERIAL_FLAG_VISIBLE,
- MATERIAL_FLAG_DOUBLE_SIDED,
- MATERIAL_FLAG_INVERT_FACES, ///< Invert front/back of the object
- MATERIAL_FLAG_UNSHADED,
- MATERIAL_FLAG_ONTOP,
- MATERIAL_FLAG_LIGHTMAP_ON_UV2,
- MATERIAL_FLAG_COLOR_ARRAY_SRGB,
- MATERIAL_FLAG_MAX,
- };
-
- virtual void material_set_flag(RID p_material, MaterialFlag p_flag,bool p_enabled)=0;
- virtual bool material_get_flag(RID p_material,MaterialFlag p_flag) const=0;
-
- enum MaterialDepthDrawMode {
- MATERIAL_DEPTH_DRAW_ALWAYS,
- MATERIAL_DEPTH_DRAW_OPAQUE_ONLY,
- MATERIAL_DEPTH_DRAW_OPAQUE_PRE_PASS_ALPHA,
- MATERIAL_DEPTH_DRAW_NEVER
- };
-
- virtual void material_set_depth_draw_mode(RID p_material, MaterialDepthDrawMode p_mode)=0;
- virtual MaterialDepthDrawMode material_get_depth_draw_mode(RID p_material) const=0;
-
- enum MaterialBlendMode {
- MATERIAL_BLEND_MODE_MIX, //default
- MATERIAL_BLEND_MODE_ADD,
- MATERIAL_BLEND_MODE_SUB,
- MATERIAL_BLEND_MODE_MUL,
- MATERIAL_BLEND_MODE_PREMULT_ALPHA
- };
-
-
- virtual void material_set_blend_mode(RID p_material,MaterialBlendMode p_mode)=0;
- virtual MaterialBlendMode material_get_blend_mode(RID p_material) const=0;
-
- virtual void material_set_line_width(RID p_material,float p_line_width)=0;
- virtual float material_get_line_width(RID p_material) const=0;
-
-
- //fixed material api
-
- virtual RID fixed_material_create()=0;
-
- enum FixedMaterialParam {
-
- FIXED_MATERIAL_PARAM_DIFFUSE,
- FIXED_MATERIAL_PARAM_DETAIL,
- FIXED_MATERIAL_PARAM_SPECULAR,
- FIXED_MATERIAL_PARAM_EMISSION,
- FIXED_MATERIAL_PARAM_SPECULAR_EXP,
- FIXED_MATERIAL_PARAM_GLOW,
- FIXED_MATERIAL_PARAM_NORMAL,
- FIXED_MATERIAL_PARAM_SHADE_PARAM,
- FIXED_MATERIAL_PARAM_MAX
- };
-
- enum FixedMaterialTexCoordMode {
-
- FIXED_MATERIAL_TEXCOORD_UV,
- FIXED_MATERIAL_TEXCOORD_UV_TRANSFORM,
- FIXED_MATERIAL_TEXCOORD_UV2,
- FIXED_MATERIAL_TEXCOORD_SPHERE
- };
-
- enum FixedMaterialFlags {
-
- FIXED_MATERIAL_FLAG_USE_ALPHA,
- FIXED_MATERIAL_FLAG_USE_COLOR_ARRAY,
- FIXED_MATERIAL_FLAG_USE_POINT_SIZE,
- FIXED_MATERIAL_FLAG_DISCARD_ALPHA,
- FIXED_MATERIAL_FLAG_USE_XY_NORMALMAP,
- FIXED_MATERIAL_FLAG_MAX,
- };
-
-
- virtual void fixed_material_set_flag(RID p_material, FixedMaterialFlags p_flag, bool p_enabled)=0;
- virtual bool fixed_material_get_flag(RID p_material, FixedMaterialFlags p_flag) const=0;
-
- virtual void fixed_material_set_param(RID p_material, FixedMaterialParam p_parameter, const Variant& p_value)=0;
- virtual Variant fixed_material_get_param(RID p_material,FixedMaterialParam p_parameter) const=0;
-
- virtual void fixed_material_set_texture(RID p_material,FixedMaterialParam p_parameter, RID p_texture)=0;
- virtual RID fixed_material_get_texture(RID p_material,FixedMaterialParam p_parameter) const=0;
-
-
- enum FixedMaterialLightShader {
-
- FIXED_MATERIAL_LIGHT_SHADER_LAMBERT,
- FIXED_MATERIAL_LIGHT_SHADER_WRAP,
- FIXED_MATERIAL_LIGHT_SHADER_VELVET,
- FIXED_MATERIAL_LIGHT_SHADER_TOON,
-
- };
-
-
- virtual void fixed_material_set_light_shader(RID p_material,FixedMaterialLightShader p_shader)=0;
- virtual FixedMaterialLightShader fixed_material_get_light_shader(RID p_material) const=0;
-
- virtual void fixed_material_set_texcoord_mode(RID p_material,FixedMaterialParam p_parameter, FixedMaterialTexCoordMode p_mode)=0;
- virtual FixedMaterialTexCoordMode fixed_material_get_texcoord_mode(RID p_material,FixedMaterialParam p_parameter) const=0;
-
- virtual void fixed_material_set_uv_transform(RID p_material,const Transform& p_transform)=0;
- virtual Transform fixed_material_get_uv_transform(RID p_material) const=0;
-
- virtual void fixed_material_set_point_size(RID p_material,float p_size)=0;
- virtual float fixed_material_get_point_size(RID p_material) const=0;
+ virtual void material_set_line_width(RID p_material, float p_width)=0;
/* MESH API */
@@ -321,8 +214,26 @@ public:
ARRAY_FORMAT_BONES=1<<ARRAY_BONES,
ARRAY_FORMAT_WEIGHTS=1<<ARRAY_WEIGHTS,
ARRAY_FORMAT_INDEX=1<<ARRAY_INDEX,
+
+ ARRAY_COMPRESS_BASE=(ARRAY_INDEX+1),
+ ARRAY_COMPRESS_VERTEX=1<<(ARRAY_VERTEX+ARRAY_COMPRESS_BASE), // mandatory
+ ARRAY_COMPRESS_NORMAL=1<<(ARRAY_NORMAL+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_TANGENT=1<<(ARRAY_TANGENT+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_COLOR=1<<(ARRAY_COLOR+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_TEX_UV=1<<(ARRAY_TEX_UV+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_TEX_UV2=1<<(ARRAY_TEX_UV2+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_BONES=1<<(ARRAY_BONES+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_WEIGHTS=1<<(ARRAY_WEIGHTS+ARRAY_COMPRESS_BASE),
+ ARRAY_COMPRESS_INDEX=1<<(ARRAY_INDEX+ARRAY_COMPRESS_BASE),
+
+ ARRAY_FLAG_USE_2D_VERTICES=ARRAY_COMPRESS_INDEX<<1,
+ ARRAY_FLAG_USE_16_BIT_BONES=ARRAY_COMPRESS_INDEX<<2,
+
+ ARRAY_COMPRESS_DEFAULT=ARRAY_COMPRESS_VERTEX|ARRAY_COMPRESS_NORMAL|ARRAY_COMPRESS_TANGENT|ARRAY_COMPRESS_COLOR|ARRAY_COMPRESS_TEX_UV|ARRAY_COMPRESS_TEX_UV2|ARRAY_COMPRESS_WEIGHTS
+
};
+
enum PrimitiveType {
PRIMITIVE_POINTS=0,
PRIMITIVE_LINES=1,
@@ -336,65 +247,88 @@ public:
virtual RID mesh_create()=0;
- virtual void mesh_add_surface(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),bool p_alpha_sort=false)=0;
- virtual Array mesh_get_surface_arrays(RID p_mesh,int p_surface) const=0;
- virtual Array mesh_get_surface_morph_arrays(RID p_mesh,int p_surface) const=0;
+ virtual void mesh_add_surface_from_arrays(RID p_mesh,PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes=Array(),uint32_t p_compress_format=ARRAY_COMPRESS_DEFAULT);
+ virtual void mesh_add_surface(RID p_mesh,uint32_t p_format,PrimitiveType p_primitive,const PoolVector<uint8_t>& p_array,int p_vertex_count,const PoolVector<uint8_t>& p_index_array,int p_index_count,const Rect3& p_aabb,const Vector<PoolVector<uint8_t> >& p_blend_shapes=Vector<PoolVector<uint8_t> >(),const Vector<Rect3>& p_bone_aabbs=Vector<Rect3>())=0;
- virtual void mesh_add_custom_surface(RID p_mesh,const Variant& p_dat)=0; //this is used by each platform in a different way
- virtual void mesh_set_morph_target_count(RID p_mesh,int p_amount)=0;
- virtual int mesh_get_morph_target_count(RID p_mesh) const=0;
+ virtual void mesh_set_blend_shape_count(RID p_mesh,int p_amount)=0;
+ virtual int mesh_get_blend_shape_count(RID p_mesh) const=0;
- enum MorphTargetMode {
- MORPH_MODE_NORMALIZED,
- MORPH_MODE_RELATIVE,
+ enum BlendShapeMode {
+ BLEND_SHAPE_MODE_NORMALIZED,
+ BLEND_SHAPE_MODE_RELATIVE,
};
- virtual void mesh_set_morph_target_mode(RID p_mesh,MorphTargetMode p_mode)=0;
- virtual MorphTargetMode mesh_get_morph_target_mode(RID p_mesh) const=0;
+ virtual void mesh_set_blend_shape_mode(RID p_mesh,BlendShapeMode p_mode)=0;
+ virtual BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const=0;
- virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material,bool p_owned=false)=0;
+ virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material)=0;
virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const=0;
virtual int mesh_surface_get_array_len(RID p_mesh, int p_surface) const=0;
virtual int mesh_surface_get_array_index_len(RID p_mesh, int p_surface) const=0;
+
+ virtual PoolVector<uint8_t> mesh_surface_get_array(RID p_mesh, int p_surface) const=0;
+ virtual PoolVector<uint8_t> mesh_surface_get_index_array(RID p_mesh, int p_surface) const=0;
+
+ virtual Array mesh_surface_get_arrays(RID p_mesh,int p_surface) const;
+
virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const=0;
virtual PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const=0;
+ virtual Rect3 mesh_surface_get_aabb(RID p_mesh, int p_surface) const=0;
+ virtual Vector<PoolVector<uint8_t> > mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const=0;
+ virtual Vector<Rect3> mesh_surface_get_skeleton_aabb(RID p_mesh, int p_surface) const=0;
+
virtual void mesh_remove_surface(RID p_mesh,int p_index)=0;
virtual int mesh_get_surface_count(RID p_mesh) const=0;
- virtual void mesh_set_custom_aabb(RID p_mesh,const AABB& p_aabb)=0;
- virtual AABB mesh_get_custom_aabb(RID p_mesh) const=0;
+ virtual void mesh_set_custom_aabb(RID p_mesh,const Rect3& p_aabb)=0;
+ virtual Rect3 mesh_get_custom_aabb(RID p_mesh) const=0;
virtual void mesh_clear(RID p_mesh)=0;
/* MULTIMESH API */
+
virtual RID multimesh_create()=0;
- virtual void multimesh_set_instance_count(RID p_multimesh,int p_count)=0;
+ enum MultimeshTransformFormat {
+ MULTIMESH_TRANSFORM_2D,
+ MULTIMESH_TRANSFORM_3D,
+ };
+
+ enum MultimeshColorFormat {
+ MULTIMESH_COLOR_NONE,
+ MULTIMESH_COLOR_8BIT,
+ MULTIMESH_COLOR_FLOAT,
+ };
+
+ virtual void multimesh_allocate(RID p_multimesh,int p_instances,MultimeshTransformFormat p_transform_format,MultimeshColorFormat p_color_format)=0;
virtual int multimesh_get_instance_count(RID p_multimesh) const=0;
virtual void multimesh_set_mesh(RID p_multimesh,RID p_mesh)=0;
- virtual void multimesh_set_aabb(RID p_multimesh,const AABB& p_aabb)=0;
virtual void multimesh_instance_set_transform(RID p_multimesh,int p_index,const Transform& p_transform)=0;
+ virtual void multimesh_instance_set_transform_2d(RID p_multimesh,int p_index,const Transform2D& p_transform)=0;
virtual void multimesh_instance_set_color(RID p_multimesh,int p_index,const Color& p_color)=0;
virtual RID multimesh_get_mesh(RID p_multimesh) const=0;
- virtual AABB multimesh_get_aabb(RID p_multimesh,const AABB& p_aabb) const=0;;
+ virtual Rect3 multimesh_get_aabb(RID p_multimesh) const=0;
virtual Transform multimesh_instance_get_transform(RID p_multimesh,int p_index) const=0;
+ virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh,int p_index) const=0;
virtual Color multimesh_instance_get_color(RID p_multimesh,int p_index) const=0;
virtual void multimesh_set_visible_instances(RID p_multimesh,int p_visible)=0;
virtual int multimesh_get_visible_instances(RID p_multimesh) const=0;
+
/* IMMEDIATE API */
virtual RID immediate_create()=0;
virtual void immediate_begin(RID p_immediate,PrimitiveType p_rimitive,RID p_texture=RID())=0;
virtual void immediate_vertex(RID p_immediate,const Vector3& p_vertex)=0;
+ virtual void immediate_vertex_2d(RID p_immediate,const Vector2& p_vertex);
virtual void immediate_normal(RID p_immediate,const Vector3& p_normal)=0;
virtual void immediate_tangent(RID p_immediate,const Plane& p_tangent)=0;
virtual void immediate_color(RID p_immediate,const Color& p_color)=0;
@@ -405,82 +339,15 @@ public:
virtual void immediate_set_material(RID p_immediate,RID p_material)=0;
virtual RID immediate_get_material(RID p_immediate) const=0;
+ /* SKELETON API */
- /* PARTICLES API */
-
- virtual RID particles_create()=0;
-
- enum ParticleVariable {
- PARTICLE_LIFETIME,
- PARTICLE_SPREAD,
- PARTICLE_GRAVITY,
- PARTICLE_LINEAR_VELOCITY,
- PARTICLE_ANGULAR_VELOCITY,
- PARTICLE_LINEAR_ACCELERATION,
- PARTICLE_RADIAL_ACCELERATION,
- PARTICLE_TANGENTIAL_ACCELERATION,
- PARTICLE_DAMPING,
- PARTICLE_INITIAL_SIZE,
- PARTICLE_FINAL_SIZE,
- PARTICLE_INITIAL_ANGLE,
- PARTICLE_HEIGHT,
- PARTICLE_HEIGHT_SPEED_SCALE,
- PARTICLE_VAR_MAX
- };
-
- virtual void particles_set_amount(RID p_particles, int p_amount)=0;
- virtual int particles_get_amount(RID p_particles) const=0;
-
- virtual void particles_set_emitting(RID p_particles, bool p_emitting)=0;
- virtual bool particles_is_emitting(RID p_particles) const=0;
-
- virtual void particles_set_visibility_aabb(RID p_particles, const AABB& p_visibility)=0;
- virtual AABB particles_get_visibility_aabb(RID p_particles) const=0;
-
- virtual void particles_set_emission_half_extents(RID p_particles, const Vector3& p_half_extents)=0;
- virtual Vector3 particles_get_emission_half_extents(RID p_particles) const=0;
-
- virtual void particles_set_emission_base_velocity(RID p_particles, const Vector3& p_base_velocity)=0;
- virtual Vector3 particles_get_emission_base_velocity(RID p_particles) const=0;
-
- virtual void particles_set_emission_points(RID p_particles, const DVector<Vector3>& p_points)=0;
- virtual DVector<Vector3> particles_get_emission_points(RID p_particles) const=0;
-
- virtual void particles_set_gravity_normal(RID p_particles, const Vector3& p_normal)=0;
- virtual Vector3 particles_get_gravity_normal(RID p_particles) const=0;
-
- virtual void particles_set_variable(RID p_particles, ParticleVariable p_variable,float p_value)=0;
- virtual float particles_get_variable(RID p_particles, ParticleVariable p_variable) const=0;
-
- virtual void particles_set_randomness(RID p_particles, ParticleVariable p_variable,float p_randomness)=0;
- virtual float particles_get_randomness(RID p_particles, ParticleVariable p_variable) const=0;
-
- virtual void particles_set_color_phases(RID p_particles, int p_phases)=0;
- virtual int particles_get_color_phases(RID p_particles) const=0;
-
- virtual void particles_set_color_phase_pos(RID p_particles, int p_phase, float p_pos)=0;
- virtual float particles_get_color_phase_pos(RID p_particles, int p_phase) const=0;
-
- virtual void particles_set_color_phase_color(RID p_particles, int p_phase, const Color& p_color)=0;
- virtual Color particles_get_color_phase_color(RID p_particles, int p_phase) const=0;
-
- virtual void particles_set_attractors(RID p_particles, int p_attractors)=0;
- virtual int particles_get_attractors(RID p_particles) const=0;
-
- virtual void particles_set_attractor_pos(RID p_particles, int p_attractor, const Vector3& p_pos)=0;
- virtual Vector3 particles_get_attractor_pos(RID p_particles,int p_attractor) const=0;
-
- virtual void particles_set_attractor_strength(RID p_particles, int p_attractor, float p_force)=0;
- virtual float particles_get_attractor_strength(RID p_particles,int p_attractor) const=0;
-
- virtual void particles_set_material(RID p_particles, RID p_material,bool p_owned=false)=0;
- virtual RID particles_get_material(RID p_particles) const=0;
-
- virtual void particles_set_height_from_velocity(RID p_particles, bool p_enable)=0;
- virtual bool particles_has_height_from_velocity(RID p_particles) const=0;
-
- virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable)=0;
- virtual bool particles_is_using_local_coordinates(RID p_particles) const=0;
+ virtual RID skeleton_create()=0;
+ virtual void skeleton_allocate(RID p_skeleton,int p_bones,bool p_2d_skeleton=false)=0;
+ virtual int skeleton_get_bone_count(RID p_skeleton) const=0;
+ virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform)=0;
+ virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone) const=0;
+ virtual void skeleton_bone_set_transform_2d(RID p_skeleton,int p_bone, const Transform2D& p_transform)=0;
+ virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton,int p_bone)const =0;
/* Light API */
@@ -490,99 +357,90 @@ public:
LIGHT_SPOT
};
- enum LightColor {
- LIGHT_COLOR_DIFFUSE,
- LIGHT_COLOR_SPECULAR
- };
-
enum LightParam {
- LIGHT_PARAM_SPOT_ATTENUATION,
- LIGHT_PARAM_SPOT_ANGLE,
- LIGHT_PARAM_RADIUS,
LIGHT_PARAM_ENERGY,
+ LIGHT_PARAM_SPECULAR,
+ LIGHT_PARAM_RANGE,
LIGHT_PARAM_ATTENUATION,
- LIGHT_PARAM_SHADOW_DARKENING,
- LIGHT_PARAM_SHADOW_Z_OFFSET,
- LIGHT_PARAM_SHADOW_Z_SLOPE_SCALE,
- LIGHT_PARAM_SHADOW_ESM_MULTIPLIER,
- LIGHT_PARAM_SHADOW_BLUR_PASSES,
+ LIGHT_PARAM_SPOT_ANGLE,
+ LIGHT_PARAM_SPOT_ATTENUATION,
+ LIGHT_PARAM_CONTACT_SHADOW_SIZE,
+ LIGHT_PARAM_SHADOW_MAX_DISTANCE,
+ LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET,
+ LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET,
+ LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET,
+ LIGHT_PARAM_SHADOW_NORMAL_BIAS,
+ LIGHT_PARAM_SHADOW_BIAS,
+ LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE,
LIGHT_PARAM_MAX
};
virtual RID light_create(LightType p_type)=0;
- virtual LightType light_get_type(RID p_light) const=0;
-
- virtual void light_set_color(RID p_light,LightColor p_type, const Color& p_color)=0;
- virtual Color light_get_color(RID p_light,LightColor p_type) const=0;
+ virtual void light_set_color(RID p_light,const Color& p_color)=0;
+ virtual void light_set_param(RID p_light,LightParam p_param,float p_value)=0;
virtual void light_set_shadow(RID p_light,bool p_enabled)=0;
- virtual bool light_has_shadow(RID p_light) const=0;
-
- virtual void light_set_volumetric(RID p_light,bool p_enabled)=0;
- virtual bool light_is_volumetric(RID p_light) const=0;
-
+ virtual void light_set_shadow_color(RID p_light,const Color& p_color)=0;
virtual void light_set_projector(RID p_light,RID p_texture)=0;
- virtual RID light_get_projector(RID p_light) const=0;
-
- virtual void light_set_param(RID p_light, LightParam p_var, float p_value)=0;
- virtual float light_get_param(RID p_light, LightParam p_var) const=0;
-
- enum LightOp {
-
- LIGHT_OPERATOR_ADD,
- LIGHT_OPERATOR_SUB
- };
-
- virtual void light_set_operator(RID p_light,LightOp p_op)=0;
- virtual LightOp light_get_operator(RID p_light) const=0;
+ virtual void light_set_negative(RID p_light,bool p_enable)=0;
+ virtual void light_set_cull_mask(RID p_light,uint32_t p_mask)=0;
// omni light
enum LightOmniShadowMode {
- LIGHT_OMNI_SHADOW_DEFAULT,
LIGHT_OMNI_SHADOW_DUAL_PARABOLOID,
- LIGHT_OMNI_SHADOW_CUBEMAP
+ LIGHT_OMNI_SHADOW_CUBE,
};
virtual void light_omni_set_shadow_mode(RID p_light,LightOmniShadowMode p_mode)=0;
- virtual LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) const=0;
+
+ // omni light
+ enum LightOmniShadowDetail {
+ LIGHT_OMNI_SHADOW_DETAIL_VERTICAL,
+ LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL
+ };
+
+ virtual void light_omni_set_shadow_detail(RID p_light,LightOmniShadowDetail p_detail)=0;
// directional light
enum LightDirectionalShadowMode {
LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL,
- LIGHT_DIRECTIONAL_SHADOW_PERSPECTIVE,
LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS,
LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS
};
virtual void light_directional_set_shadow_mode(RID p_light,LightDirectionalShadowMode p_mode)=0;
- virtual LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) const=0;
+ virtual void light_directional_set_blend_splits(RID p_light,bool p_enable)=0;
- enum LightDirectionalShadowParam {
+ /* PROBE API */
- LIGHT_DIRECTIONAL_SHADOW_PARAM_MAX_DISTANCE,
- LIGHT_DIRECTIONAL_SHADOW_PARAM_PSSM_SPLIT_WEIGHT,
- LIGHT_DIRECTIONAL_SHADOW_PARAM_PSSM_ZOFFSET_SCALE,
- };
+ virtual RID reflection_probe_create()=0;
- virtual void light_directional_set_shadow_param(RID p_light,LightDirectionalShadowParam p_param, float p_value)=0;
- virtual float light_directional_get_shadow_param(RID p_light,LightDirectionalShadowParam p_param) const=0;
+ enum ReflectionProbeUpdateMode {
+ REFLECTION_PROBE_UPDATE_ONCE,
+ REFLECTION_PROBE_UPDATE_ALWAYS,
+ };
- //@TODO fallof model and all that stuff
- /* SKELETON API */
+ virtual void reflection_probe_set_update_mode(RID p_probe, ReflectionProbeUpdateMode p_mode)=0;
+ virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity)=0;
+ virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color& p_color)=0;
+ virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy)=0;
+ virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib)=0;
+ virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance)=0;
+ virtual void reflection_probe_set_extents(RID p_probe, const Vector3& p_extents)=0;
+ virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3& p_offset)=0;
+ virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable)=0;
+ virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable)=0;
+ virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable)=0;
+ virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers)=0;
- virtual RID skeleton_create()=0;
- virtual void skeleton_resize(RID p_skeleton,int p_bones)=0;
- virtual int skeleton_get_bone_count(RID p_skeleton) const=0;
- virtual void skeleton_bone_set_transform(RID p_skeleton,int p_bone, const Transform& p_transform)=0;
- virtual Transform skeleton_bone_get_transform(RID p_skeleton,int p_bone)=0;
/* ROOM API */
virtual RID room_create()=0;
- virtual void room_set_bounds(RID p_room, const BSP_Tree& p_bounds)=0;
- virtual BSP_Tree room_get_bounds(RID p_room) const=0;
+ virtual void room_add_bounds(RID p_room, const PoolVector<Vector2>& p_convex_polygon,float p_height,const Transform& p_transform)=0;
+ virtual void room_clear_bounds(RID p_room)=0;
/* PORTAL API */
@@ -591,69 +449,91 @@ public:
virtual RID portal_create()=0;
virtual void portal_set_shape(RID p_portal, const Vector<Point2>& p_shape)=0;
- virtual Vector<Point2> portal_get_shape(RID p_portal) const=0;
virtual void portal_set_enabled(RID p_portal, bool p_enabled)=0;
- virtual bool portal_is_enabled(RID p_portal) const=0;
virtual void portal_set_disable_distance(RID p_portal, float p_distance)=0;
- virtual float portal_get_disable_distance(RID p_portal) const=0;
virtual void portal_set_disabled_color(RID p_portal, const Color& p_color)=0;
- virtual Color portal_get_disabled_color(RID p_portal) const=0;
- virtual void portal_set_connect_range(RID p_portal, float p_range) =0;
- virtual float portal_get_connect_range(RID p_portal) const =0;
+ /* GI PROBE API */
- /* BAKED LIGHT API */
+ virtual RID gi_probe_create()=0;
- virtual RID baked_light_create()=0;
- enum BakedLightMode {
- BAKED_LIGHT_OCTREE,
- BAKED_LIGHT_LIGHTMAPS
- };
+ virtual void gi_probe_set_bounds(RID p_probe,const Rect3& p_bounds)=0;
+ virtual Rect3 gi_probe_get_bounds(RID p_probe) const=0;
- virtual void baked_light_set_mode(RID p_baked_light,BakedLightMode p_mode)=0;
- virtual BakedLightMode baked_light_get_mode(RID p_baked_light) const=0;
+ virtual void gi_probe_set_cell_size(RID p_probe,float p_range)=0;
+ virtual float gi_probe_get_cell_size(RID p_probe) const=0;
- virtual void baked_light_set_octree(RID p_baked_light,const DVector<uint8_t> p_octree)=0;
- virtual DVector<uint8_t> baked_light_get_octree(RID p_baked_light) const=0;
+ virtual void gi_probe_set_to_cell_xform(RID p_probe,const Transform& p_xform)=0;
+ virtual Transform gi_probe_get_to_cell_xform(RID p_probe) const=0;
- virtual void baked_light_set_light(RID p_baked_light,const DVector<uint8_t> p_light)=0;
- virtual DVector<uint8_t> baked_light_get_light(RID p_baked_light) const=0;
+ virtual void gi_probe_set_dynamic_data(RID p_probe,const PoolVector<int>& p_data)=0;
+ virtual PoolVector<int> gi_probe_get_dynamic_data(RID p_probe) const=0;
- virtual void baked_light_set_sampler_octree(RID p_baked_light,const DVector<int> &p_sampler)=0;
- virtual DVector<int> baked_light_get_sampler_octree(RID p_baked_light) const=0;
+ virtual void gi_probe_set_dynamic_range(RID p_probe,int p_range)=0;
+ virtual int gi_probe_get_dynamic_range(RID p_probe) const=0;
- virtual void baked_light_set_lightmap_multiplier(RID p_baked_light,float p_multiplier)=0;
- virtual float baked_light_get_lightmap_multiplier(RID p_baked_light) const=0;
+ virtual void gi_probe_set_energy(RID p_probe,float p_range)=0;
+ virtual float gi_probe_get_energy(RID p_probe) const=0;
- virtual void baked_light_add_lightmap(RID p_baked_light,const RID p_texture,int p_id)=0;
- virtual void baked_light_clear_lightmaps(RID p_baked_light)=0;
+ virtual void gi_probe_set_bias(RID p_probe,float p_range)=0;
+ virtual float gi_probe_get_bias(RID p_probe) const=0;
- virtual void baked_light_set_realtime_color_enabled(RID p_baked_light, const bool p_enabled)=0;
- virtual bool baked_light_get_realtime_color_enabled(RID p_baked_light) const=0;
+ virtual void gi_probe_set_propagation(RID p_probe,float p_range)=0;
+ virtual float gi_probe_get_propagation(RID p_probe) const=0;
- virtual void baked_light_set_realtime_color(RID p_baked_light, const Color& p_color)=0;
- virtual Color baked_light_get_realtime_color(RID p_baked_light) const=0;
+ virtual void gi_probe_set_interior(RID p_probe,bool p_enable)=0;
+ virtual bool gi_probe_is_interior(RID p_probe) const=0;
- virtual void baked_light_set_realtime_energy(RID p_baked_light, const float p_energy) = 0;
- virtual float baked_light_get_realtime_energy(RID p_baked_light) const = 0;
+ virtual void gi_probe_set_compress(RID p_probe,bool p_enable)=0;
+ virtual bool gi_probe_is_compressed(RID p_probe) const=0;
- /* BAKED LIGHT SAMPLER */
+ /* PARTICLES API */
- virtual RID baked_light_sampler_create()=0;
+ virtual RID particles_create()=0;
- enum BakedLightSamplerParam {
- BAKED_LIGHT_SAMPLER_RADIUS,
- BAKED_LIGHT_SAMPLER_STRENGTH,
- BAKED_LIGHT_SAMPLER_ATTENUATION,
- BAKED_LIGHT_SAMPLER_DETAIL_RATIO,
- BAKED_LIGHT_SAMPLER_MAX
+ virtual void particles_set_emitting(RID p_particles,bool p_emitting)=0;
+ virtual void particles_set_amount(RID p_particles,int p_amount)=0;
+ virtual void particles_set_lifetime(RID p_particles,float p_lifetime)=0;
+ virtual void particles_set_pre_process_time(RID p_particles,float p_time)=0;
+ virtual void particles_set_explosiveness_ratio(RID p_particles,float p_ratio)=0;
+ virtual void particles_set_randomness_ratio(RID p_particles,float p_ratio)=0;
+ virtual void particles_set_custom_aabb(RID p_particles,const Rect3& p_aabb)=0;
+ virtual void particles_set_gravity(RID p_particles,const Vector3& p_gravity)=0;
+ virtual void particles_set_use_local_coordinates(RID p_particles,bool p_enable)=0;
+ virtual void particles_set_process_material(RID p_particles,RID p_material)=0;
+
+ enum ParticlesEmissionShape {
+ PARTICLES_EMSSION_POINT,
+ PARTICLES_EMSSION_SPHERE,
+ PARTICLES_EMSSION_BOX,
+ PARTICLES_EMSSION_POINTS,
+ PARTICLES_EMSSION_SEGMENTS,
+ };
+
+ virtual void particles_set_emission_shape(RID p_particles,ParticlesEmissionShape)=0;
+ virtual void particles_set_emission_sphere_radius(RID p_particles,float p_radius)=0;
+ virtual void particles_set_emission_box_extents(RID p_particles,const Vector3& p_extents)=0;
+ virtual void particles_set_emission_points(RID p_particles,const PoolVector<Vector3>& p_points)=0;
+
+ enum ParticlesDrawOrder {
+ PARTICLES_DRAW_ORDER_INDEX,
+ PARTICLES_DRAW_ORDER_LIFETIME,
+ PARTICLES_DRAW_ORDER_VIEW_DEPTH,
+ };
+
+ virtual void particles_set_draw_order(RID p_particles,ParticlesDrawOrder p_order)=0;
+
+ enum ParticlesDrawPassMode {
+ PARTICLES_DRAW_PASS_MODE_QUAD,
+ PARTICLES_DRAW_PASS_MODE_MESH
};
- virtual void baked_light_sampler_set_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param,float p_value)=0;
- virtual float baked_light_sampler_get_param(RID p_baked_light_sampler,BakedLightSamplerParam p_param) const=0;
- virtual void baked_light_sampler_set_resolution(RID p_baked_light_sampler,int p_resolution)=0;
- virtual int baked_light_sampler_get_resolution(RID p_baked_light_sampler) const=0;
+ virtual void particles_set_draw_passes(RID p_particles,int p_count)=0;
+ virtual void particles_set_draw_pass_material(RID p_particles,int p_pass, RID p_material)=0;
+ virtual void particles_set_draw_pass_mesh(RID p_particles,int p_pass, RID p_mesh)=0;
+
+ virtual Rect3 particles_get_current_aabb(RID p_particles)=0;
/* CAMERA API */
@@ -661,96 +541,80 @@ public:
virtual void camera_set_perspective(RID p_camera,float p_fovy_degrees, float p_z_near, float p_z_far)=0;
virtual void camera_set_orthogonal(RID p_camera,float p_size, float p_z_near, float p_z_far)=0;
virtual void camera_set_transform(RID p_camera,const Transform& p_transform)=0;
-
- virtual void camera_set_visible_layers(RID p_camera,uint32_t p_layers)=0;
- virtual uint32_t camera_get_visible_layers(RID p_camera) const=0;
-
+ virtual void camera_set_cull_mask(RID p_camera,uint32_t p_layers)=0;
virtual void camera_set_environment(RID p_camera,RID p_env)=0;
- virtual RID camera_get_environment(RID p_camera) const=0;
-
virtual void camera_set_use_vertical_aspect(RID p_camera,bool p_enable)=0;
- virtual bool camera_is_using_vertical_aspect(RID p_camera,bool p_enable) const=0;
/*
- virtual void camera_add_layer(RID p_camera);
- virtual void camera_layer_move_up(RID p_camera,int p_layer);
- virtual void camera_layer_move_down(RID p_camera,int p_layer);
- virtual void camera_layer_set_mask(RID p_camera,int p_layer,int p_mask);
- virtual int camera_layer_get_mask(RID p_camera,int p_layer) const;
-
- enum CameraLayerFlag {
-
- FLAG_CLEAR_DEPTH,
- FLAG_CLEAR_COLOR,
- FLAG_IGNORE_FOG,
+ enum ParticlesCollisionMode {
+ PARTICLES_COLLISION_NONE,
+ PARTICLES_COLLISION_TEXTURE,
+ PARTICLES_COLLISION_CUBEMAP,
};
- virtual void camera_layer_set_flag(RID p_camera,int p_layer,bool p_enable);
- virtual bool camera_layer_get_flag(RID p_camera,int p_layer) const;
+ virtual void particles_set_collision(RID p_particles,ParticlesCollisionMode p_mode,const Transform&, p_xform,const RID p_depth_tex,const RID p_normal_tex)=0;
*/
-
-
- /* VIEWPORT API */
+ /* VIEWPORT TARGET API */
virtual RID viewport_create()=0;
- virtual void viewport_attach_to_screen(RID p_viewport,int p_screen=0)=0;
+ virtual void viewport_set_size(RID p_viewport,int p_width,int p_height)=0;
+ virtual void viewport_set_active(RID p_viewport,bool p_active)=0;
+ virtual void viewport_set_parent_viewport(RID p_viewport,RID p_parent_viewport)=0;
+
+ virtual void viewport_attach_to_screen(RID p_viewport,const Rect2& p_rect=Rect2(),int p_screen=0)=0;
virtual void viewport_detach(RID p_viewport)=0;
- virtual void viewport_set_render_target_to_screen_rect(RID p_viewport,const Rect2& p_rect)=0;
- enum RenderTargetUpdateMode {
- RENDER_TARGET_UPDATE_DISABLED,
- RENDER_TARGET_UPDATE_ONCE, //then goes to disabled
- RENDER_TARGET_UPDATE_WHEN_VISIBLE, // default
- RENDER_TARGET_UPDATE_ALWAYS
+ enum ViewportUpdateMode {
+ VIEWPORT_UPDATE_DISABLED,
+ VIEWPORT_UPDATE_ONCE, //then goes to disabled, must be manually updated
+ VIEWPORT_UPDATE_WHEN_VISIBLE, // default
+ VIEWPORT_UPDATE_ALWAYS
};
- virtual void viewport_set_as_render_target(RID p_viewport,bool p_enable)=0;
- virtual void viewport_set_render_target_update_mode(RID p_viewport,RenderTargetUpdateMode p_mode)=0;
- virtual RenderTargetUpdateMode viewport_get_render_target_update_mode(RID p_viewport) const=0;
- virtual RID viewport_get_render_target_texture(RID p_viewport) const=0;
- virtual void viewport_set_render_target_vflip(RID p_viewport,bool p_enable)=0;
- virtual bool viewport_get_render_target_vflip(RID p_viewport) const=0;
- virtual void viewport_set_render_target_clear_on_new_frame(RID p_viewport,bool p_enable)=0;
- virtual bool viewport_get_render_target_clear_on_new_frame(RID p_viewport) const=0;
- virtual void viewport_render_target_clear(RID p_viewport)=0;
-
- virtual void viewport_queue_screen_capture(RID p_viewport)=0;
- virtual Image viewport_get_screen_capture(RID p_viewport) const=0;
-
+ virtual void viewport_set_update_mode(RID p_viewport,ViewportUpdateMode p_mode)=0;
+ virtual void viewport_set_vflip(RID p_viewport,bool p_enable)=0;
+ enum ViewportClearMode {
- struct ViewportRect {
-
- int x,y,width,height;
- ViewportRect() { x=y=width=height=0; }
+ VIEWPORT_CLEAR_ALWAYS,
+ VIEWPORT_CLEAR_NEVER,
+ VIEWPORT_CLEAR_ONLY_NEXT_FRAME
};
- virtual void viewport_set_rect(RID p_viewport,const ViewportRect& p_rect)=0;
- virtual ViewportRect viewport_get_rect(RID p_viewport) const=0;
+ virtual void viewport_set_clear_mode(RID p_viewport,ViewportClearMode p_clear_mode)=0;
+
+ virtual RID viewport_get_texture(RID p_viewport) const=0;
virtual void viewport_set_hide_scenario(RID p_viewport,bool p_hide)=0;
virtual void viewport_set_hide_canvas(RID p_viewport,bool p_hide)=0;
virtual void viewport_set_disable_environment(RID p_viewport,bool p_disable)=0;
+ virtual void viewport_set_disable_3d(RID p_viewport,bool p_disable)=0;
virtual void viewport_attach_camera(RID p_viewport,RID p_camera)=0;
virtual void viewport_set_scenario(RID p_viewport,RID p_scenario)=0;
- virtual RID viewport_get_attached_camera(RID p_viewport) const=0;
- virtual RID viewport_get_scenario(RID p_viewport) const=0;
virtual void viewport_attach_canvas(RID p_viewport,RID p_canvas)=0;
virtual void viewport_remove_canvas(RID p_viewport,RID p_canvas)=0;
- virtual void viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Matrix32& p_offset)=0;
- virtual Matrix32 viewport_get_canvas_transform(RID p_viewport,RID p_canvas) const=0;
+ virtual void viewport_set_canvas_transform(RID p_viewport,RID p_canvas,const Transform2D& p_offset)=0;
virtual void viewport_set_transparent_background(RID p_viewport,bool p_enabled)=0;
- virtual bool viewport_has_transparent_background(RID p_viewport) const=0;
-
- virtual void viewport_set_global_canvas_transform(RID p_viewport,const Matrix32& p_transform)=0;
- virtual Matrix32 viewport_get_global_canvas_transform(RID p_viewport) const=0;
+ virtual void viewport_set_global_canvas_transform(RID p_viewport,const Transform2D& p_transform)=0;
virtual void viewport_set_canvas_layer(RID p_viewport,RID p_canvas,int p_layer)=0;
+ virtual void viewport_set_shadow_atlas_size(RID p_viewport,int p_size)=0;
+ virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport,int p_quadrant,int p_subdiv)=0;
+
+ enum ViewportMSAA {
+ VIEWPORT_MSAA_DISABLED,
+ VIEWPORT_MSAA_2X,
+ VIEWPORT_MSAA_4X,
+ VIEWPORT_MSAA_8X,
+ VIEWPORT_MSAA_16X,
+ };
+ virtual void viewport_set_msaa(RID p_viewport,ViewportMSAA p_msaa)=0;
+ virtual void viewport_set_hdr(RID p_viewport,bool p_enabled)=0;
/* ENVIRONMENT API */
@@ -758,104 +622,61 @@ public:
enum EnvironmentBG {
- ENV_BG_KEEP,
- ENV_BG_DEFAULT_COLOR,
+ ENV_BG_CLEAR_COLOR,
ENV_BG_COLOR,
- ENV_BG_TEXTURE,
- ENV_BG_CUBEMAP,
+ ENV_BG_SKYBOX,
ENV_BG_CANVAS,
+ ENV_BG_KEEP,
ENV_BG_MAX
};
virtual void environment_set_background(RID p_env,EnvironmentBG p_bg)=0;
- virtual EnvironmentBG environment_get_background(RID p_env) const=0;
-
- enum EnvironmentBGParam {
-
- ENV_BG_PARAM_CANVAS_MAX_LAYER,
- ENV_BG_PARAM_COLOR,
- ENV_BG_PARAM_TEXTURE,
- ENV_BG_PARAM_CUBEMAP,
- ENV_BG_PARAM_ENERGY,
- ENV_BG_PARAM_SCALE,
- ENV_BG_PARAM_GLOW,
- ENV_BG_PARAM_MAX
- };
+ virtual void environment_set_skybox(RID p_env,RID p_skybox)=0;
+ virtual void environment_set_skybox_scale(RID p_env,float p_scale)=0;
+ virtual void environment_set_bg_color(RID p_env,const Color& p_color)=0;
+ virtual void environment_set_bg_energy(RID p_env,float p_energy)=0;
+ virtual void environment_set_canvas_max_layer(RID p_env,int p_max_layer)=0;
+ virtual void environment_set_ambient_light(RID p_env,const Color& p_color,float p_energy=1.0,float p_skybox_contribution=0.0)=0;
+ //set default SSAO options
+ //set default SSR options
+ //set default SSSSS options
- virtual void environment_set_background_param(RID p_env,EnvironmentBGParam p_param, const Variant& p_value)=0;
- virtual Variant environment_get_background_param(RID p_env,EnvironmentBGParam p_param) const=0;
-
- enum EnvironmentFx {
- ENV_FX_AMBIENT_LIGHT,
- ENV_FX_FXAA,
- ENV_FX_GLOW,
- ENV_FX_DOF_BLUR,
- ENV_FX_HDR,
- ENV_FX_FOG,
- ENV_FX_BCS,
- ENV_FX_SRGB,
- ENV_FX_MAX
+ enum EnvironmentDOFBlurQuality {
+ ENV_DOF_BLUR_QUALITY_LOW,
+ ENV_DOF_BLUR_QUALITY_MEDIUM,
+ ENV_DOF_BLUR_QUALITY_HIGH,
};
+ virtual void environment_set_dof_blur_near(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,EnvironmentDOFBlurQuality p_quality)=0;
+ virtual void environment_set_dof_blur_far(RID p_env,bool p_enable,float p_distance,float p_transition,float p_far_amount,EnvironmentDOFBlurQuality p_quality)=0;
-
- virtual void environment_set_enable_fx(RID p_env,EnvironmentFx p_effect,bool p_enabled)=0;
- virtual bool environment_is_fx_enabled(RID p_env,EnvironmentFx p_mode) const=0;
-
- enum EnvironmentFxBlurBlendMode {
- ENV_FX_BLUR_BLEND_MODE_ADDITIVE,
- ENV_FX_BLUR_BLEND_MODE_SCREEN,
- ENV_FX_BLUR_BLEND_MODE_SOFTLIGHT,
+ enum EnvironmentGlowBlendMode {
+ GLOW_BLEND_MODE_ADDITIVE,
+ GLOW_BLEND_MODE_SCREEN,
+ GLOW_BLEND_MODE_SOFTLIGHT,
+ GLOW_BLEND_MODE_REPLACE,
};
+ virtual void environment_set_glow(RID p_env,bool p_enable,int p_level_flags,float p_intensity,float p_strength,float p_bloom_treshold,EnvironmentGlowBlendMode p_blend_mode,float p_hdr_bleed_treshold,float p_hdr_bleed_scale,bool p_bicubic_upscale)=0;
+ virtual void environment_set_fog(RID p_env,bool p_enable,float p_begin,float p_end,RID p_gradient_texture)=0;
- enum EnvironmentFxHDRToneMapper {
- ENV_FX_HDR_TONE_MAPPER_LINEAR,
- ENV_FX_HDR_TONE_MAPPER_LOG,
- ENV_FX_HDR_TONE_MAPPER_REINHARDT,
- ENV_FX_HDR_TONE_MAPPER_REINHARDT_AUTOWHITE,
- };
- enum EnvironmentFxParam {
- ENV_FX_PARAM_AMBIENT_LIGHT_COLOR,
- ENV_FX_PARAM_AMBIENT_LIGHT_ENERGY,
- ENV_FX_PARAM_GLOW_BLUR_PASSES,
- ENV_FX_PARAM_GLOW_BLUR_SCALE,
- ENV_FX_PARAM_GLOW_BLUR_STRENGTH,
- ENV_FX_PARAM_GLOW_BLUR_BLEND_MODE,
- ENV_FX_PARAM_GLOW_BLOOM,
- ENV_FX_PARAM_GLOW_BLOOM_TRESHOLD,
- ENV_FX_PARAM_DOF_BLUR_PASSES,
- ENV_FX_PARAM_DOF_BLUR_BEGIN,
- ENV_FX_PARAM_DOF_BLUR_RANGE,
- ENV_FX_PARAM_HDR_TONEMAPPER,
- ENV_FX_PARAM_HDR_EXPOSURE,
- ENV_FX_PARAM_HDR_WHITE,
- ENV_FX_PARAM_HDR_GLOW_TRESHOLD,
- ENV_FX_PARAM_HDR_GLOW_SCALE,
- ENV_FX_PARAM_HDR_MIN_LUMINANCE,
- ENV_FX_PARAM_HDR_MAX_LUMINANCE,
- ENV_FX_PARAM_HDR_EXPOSURE_ADJUST_SPEED,
- ENV_FX_PARAM_FOG_BEGIN,
- ENV_FX_PARAM_FOG_BEGIN_COLOR,
- ENV_FX_PARAM_FOG_END_COLOR,
- ENV_FX_PARAM_FOG_ATTENUATION,
- ENV_FX_PARAM_FOG_BG,
- ENV_FX_PARAM_BCS_BRIGHTNESS,
- ENV_FX_PARAM_BCS_CONTRAST,
- ENV_FX_PARAM_BCS_SATURATION,
- ENV_FX_PARAM_MAX
+ enum EnvironmentToneMapper {
+ ENV_TONE_MAPPER_LINEAR,
+ ENV_TONE_MAPPER_REINHARDT,
+ ENV_TONE_MAPPER_FILMIC,
+ ENV_TONE_MAPPER_ACES
};
- virtual void environment_fx_set_param(RID p_env,EnvironmentFxParam p_effect,const Variant& p_param)=0;
- virtual Variant environment_fx_get_param(RID p_env,EnvironmentFxParam p_effect) const=0;
+ virtual void environment_set_tonemap(RID p_env,EnvironmentToneMapper p_tone_mapper,float p_exposure,float p_white,bool p_auto_exposure,float p_min_luminance,float p_max_luminance,float p_auto_exp_speed,float p_auto_exp_grey)=0;
+ virtual void environment_set_adjustment(RID p_env,bool p_enable,float p_brightness,float p_contrast,float p_saturation,RID p_ramp)=0;
+ virtual void environment_set_ssr(RID p_env,bool p_enable, int p_max_steps,float p_accel,float p_fade,float p_depth_tolerance,bool p_smooth,bool p_roughness)=0;
+ virtual void environment_set_ssao(RID p_env,bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect,const Color &p_color,bool p_blur)=0;
/* SCENARIO API */
-
-
virtual RID scenario_create()=0;
enum ScenarioDebugMode {
@@ -869,7 +690,7 @@ public:
virtual void scenario_set_debug(RID p_scenario,ScenarioDebugMode p_debug_mode)=0;
virtual void scenario_set_environment(RID p_scenario, RID p_environment)=0;
- virtual RID scenario_get_environment(RID p_scenario, RID p_environment) const=0;
+ virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_size,int p_subdiv)=0;
virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment)=0;
@@ -883,67 +704,47 @@ public:
INSTANCE_IMMEDIATE,
INSTANCE_PARTICLES,
INSTANCE_LIGHT,
+ INSTANCE_REFLECTION_PROBE,
INSTANCE_ROOM,
INSTANCE_PORTAL,
- INSTANCE_BAKED_LIGHT,
- INSTANCE_BAKED_LIGHT_SAMPLER,
+ INSTANCE_GI_PROBE,
+ INSTANCE_MAX,
+ /*INSTANCE_BAKED_LIGHT_SAMPLER,*/
- INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE)|(1<<INSTANCE_PARTICLES)
+ INSTANCE_GEOMETRY_MASK=(1<<INSTANCE_MESH)|(1<<INSTANCE_MULTIMESH)|(1<<INSTANCE_IMMEDIATE)
};
virtual RID instance_create2(RID p_base, RID p_scenario);
-// virtual RID instance_create(RID p_base,RID p_scenario)=0; // from can be mesh, light, area and portal so far.
+ //virtual RID instance_create(RID p_base,RID p_scenario)=0; // from can be mesh, light, area and portal so far.
virtual RID instance_create()=0; // from can be mesh, light, poly, area and portal so far.
virtual void instance_set_base(RID p_instance, RID p_base)=0; // from can be mesh, light, poly, area and portal so far.
- virtual RID instance_get_base(RID p_instance) const=0;
-
virtual void instance_set_scenario(RID p_instance, RID p_scenario)=0; // from can be mesh, light, poly, area and portal so far.
- virtual RID instance_get_scenario(RID p_instance) const=0;
-
virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask)=0;
- virtual uint32_t instance_get_layer_mask(RID p_instance) const=0;
-
- virtual AABB instance_get_base_aabb(RID p_instance) const=0;
-
virtual void instance_set_transform(RID p_instance, const Transform& p_transform)=0;
- virtual Transform instance_get_transform(RID p_instance) const=0;
-
-
- virtual void instance_attach_object_instance_ID(RID p_instance,uint32_t p_ID)=0;
- virtual uint32_t instance_get_object_instance_ID(RID p_instance) const=0;
-
- virtual void instance_set_morph_target_weight(RID p_instance,int p_shape, float p_weight)=0;
- virtual float instance_get_morph_target_weight(RID p_instance,int p_shape) const=0;
-
+ virtual void instance_attach_object_instance_ID(RID p_instance,ObjectID p_ID)=0;
+ virtual void instance_set_blend_shape_weight(RID p_instance,int p_shape, float p_weight)=0;
virtual void instance_set_surface_material(RID p_instance,int p_surface, RID p_material)=0;
+ virtual void instance_set_visible(RID p_instance,bool p_visible)=0;
virtual void instance_attach_skeleton(RID p_instance,RID p_skeleton)=0;
- virtual RID instance_get_skeleton(RID p_instance) const=0;
-
virtual void instance_set_exterior( RID p_instance, bool p_enabled )=0;
- virtual bool instance_is_exterior( RID p_instance) const=0;
-
virtual void instance_set_room( RID p_instance, RID p_room )=0;
- virtual RID instance_get_room( RID p_instance ) const =0;
virtual void instance_set_extra_visibility_margin( RID p_instance, real_t p_margin )=0;
- virtual real_t instance_get_extra_visibility_margin( RID p_instance ) const =0;
// don't use these in a game!
- virtual Vector<RID> instances_cull_aabb(const AABB& p_aabb, RID p_scenario=RID()) const=0;
- virtual Vector<RID> instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario=RID()) const=0;
- virtual Vector<RID> instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario=RID()) const=0;
+ virtual Vector<ObjectID> instances_cull_aabb(const Rect3& p_aabb, RID p_scenario=RID()) const=0;
+ virtual Vector<ObjectID> instances_cull_ray(const Vector3& p_from, const Vector3& p_to, RID p_scenario=RID()) const=0;
+ virtual Vector<ObjectID> instances_cull_convex(const Vector<Plane>& p_convex, RID p_scenario=RID()) const=0;
enum InstanceFlags {
- INSTANCE_FLAG_VISIBLE,
INSTANCE_FLAG_BILLBOARD,
INSTANCE_FLAG_BILLBOARD_FIX_Y,
INSTANCE_FLAG_CAST_SHADOW,
- INSTANCE_FLAG_RECEIVE_SHADOWS,
INSTANCE_FLAG_DEPH_SCALE,
INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS,
INSTANCE_FLAG_USE_BAKED_LIGHT,
@@ -958,80 +759,53 @@ public:
};
virtual void instance_geometry_set_flag(RID p_instance,InstanceFlags p_flags,bool p_enabled)=0;
- virtual bool instance_geometry_get_flag(RID p_instance,InstanceFlags p_flags) const=0;
-
virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, ShadowCastingSetting p_shadow_casting_setting) = 0;
- virtual ShadowCastingSetting instance_geometry_get_cast_shadows_setting(RID p_instance) const = 0;
-
virtual void instance_geometry_set_material_override(RID p_instance, RID p_material)=0;
- virtual RID instance_geometry_get_material_override(RID p_instance) const=0;
-
- virtual void instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max)=0;
- virtual float instance_geometry_get_draw_range_max(RID p_instance) const=0;
- virtual float instance_geometry_get_draw_range_min(RID p_instance) const=0;
-
- virtual void instance_geometry_set_baked_light(RID p_instance,RID p_baked_light)=0;
- virtual RID instance_geometry_get_baked_light(RID p_instance) const=0;
- virtual void instance_geometry_set_baked_light_sampler(RID p_instance,RID p_baked_light_sampler)=0;
- virtual RID instance_geometry_get_baked_light_sampler(RID p_instance) const=0;
- virtual void instance_geometry_set_baked_light_texture_index(RID p_instance,int p_tex_id)=0;
- virtual int instance_geometry_get_baked_light_texture_index(RID p_instance) const=0;
-
-
- virtual void instance_light_set_enabled(RID p_instance,bool p_enabled)=0;
- virtual bool instance_light_is_enabled(RID p_instance) const=0;
+ virtual void instance_geometry_set_draw_range(RID p_instance,float p_min,float p_max,float p_min_margin,float p_max_margin)=0;
+ virtual void instance_geometry_set_as_instance_lod(RID p_instance,RID p_as_lod_of_instance)=0;
/* CANVAS (2D) */
virtual RID canvas_create()=0;
virtual void canvas_set_item_mirroring(RID p_canvas,RID p_item,const Point2& p_mirroring)=0;
- virtual Point2 canvas_get_item_mirroring(RID p_canvas,RID p_item) const=0;
virtual void canvas_set_modulate(RID p_canvas,const Color& p_color)=0;
-
virtual RID canvas_item_create()=0;
virtual void canvas_item_set_parent(RID p_item,RID p_parent)=0;
- virtual RID canvas_item_get_parent(RID p_canvas_item) const=0;
virtual void canvas_item_set_visible(RID p_item,bool p_visible)=0;
- virtual bool canvas_item_is_visible(RID p_item) const=0;
-
virtual void canvas_item_set_light_mask(RID p_item,int p_mask)=0;
- virtual void canvas_item_set_blend_mode(RID p_canvas_item,MaterialBlendMode p_blend)=0;
-
- virtual void canvas_item_attach_viewport(RID p_item, RID p_viewport)=0;
-
- //virtual void canvas_item_set_rect(RID p_item, const Rect2& p_rect)=0;
-
- virtual void canvas_item_set_transform(RID p_item, const Matrix32& p_transform)=0;
+ virtual void canvas_item_set_transform(RID p_item, const Transform2D& p_transform)=0;
virtual void canvas_item_set_clip(RID p_item, bool p_clip)=0;
virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable)=0;
virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect,const Rect2& p_rect=Rect2())=0;
- virtual void canvas_item_set_opacity(RID p_item, float p_opacity)=0;
- virtual float canvas_item_get_opacity(RID p_item, float p_opacity) const=0;
+ virtual void canvas_item_set_modulate(RID p_item, const Color& p_color)=0;
+ virtual void canvas_item_set_self_modulate(RID p_item, const Color& p_color)=0;
- virtual void canvas_item_set_self_opacity(RID p_item, float p_self_opacity)=0;
- virtual float canvas_item_get_self_opacity(RID p_item, float p_self_opacity) const=0;
+ virtual void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable)=0;
- virtual void canvas_item_set_on_top(RID p_item, bool p_on_top)=0;
- virtual bool canvas_item_is_on_top(RID p_item) const=0;
+ enum NinePatchAxisMode {
+ NINE_PATCH_STRETCH,
+ NINE_PATCH_TILE,
+ NINE_PATCH_TILE_FIT,
+ };
virtual void canvas_item_add_line(RID p_item, const Point2& p_from, const Point2& p_to,const Color& p_color,float p_width=1.0,bool p_antialiased=false)=0;
virtual void canvas_item_add_rect(RID p_item, const Rect2& p_rect, const Color& p_color)=0;
virtual void canvas_item_add_circle(RID p_item, const Point2& p_pos, float p_radius,const Color& p_color)=0;
virtual void canvas_item_add_texture_rect(RID p_item, const Rect2& p_rect, RID p_texture,bool p_tile=false,const Color& p_modulate=Color(1,1,1),bool p_transpose=false)=0;
virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2& p_rect, RID p_texture,const Rect2& p_src_rect,const Color& p_modulate=Color(1,1,1),bool p_transpose=false)=0;
- virtual void canvas_item_add_style_box(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright, bool p_draw_center=true,const Color& p_modulate=Color(1,1,1))=0;
+ virtual void canvas_item_add_nine_patch(RID p_item, const Rect2& p_rect, const Rect2& p_source, RID p_texture,const Vector2& p_topleft, const Vector2& p_bottomright,NinePatchAxisMode p_x_axis_mode=NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode=NINE_PATCH_STRETCH,bool p_draw_center=true,const Color& p_modulate=Color(1,1,1))=0;
virtual void canvas_item_add_primitive(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs, RID p_texture,float p_width=1.0)=0;
virtual void canvas_item_add_polygon(RID p_item, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID())=0;
virtual void canvas_item_add_triangle_array(RID p_item, const Vector<int>& p_indices, const Vector<Point2>& p_points, const Vector<Color>& p_colors,const Vector<Point2>& p_uvs=Vector<Point2>(), RID p_texture=RID(), int p_count=-1)=0;
- virtual void canvas_item_add_triangle_array_ptr(RID p_item, int p_count, const int* p_indices, const Point2* p_points, const Color* p_colors,const Point2* p_uvs=NULL, RID p_texture=RID())=0;
- virtual void canvas_item_add_set_transform(RID p_item,const Matrix32& p_transform)=0;
- virtual void canvas_item_add_set_blend_mode(RID p_item, MaterialBlendMode p_blend)=0;
+ virtual void canvas_item_add_mesh(RID p_item, const RID& p_mesh,RID p_skeleton=RID())=0;
+ virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh,RID p_skeleton=RID())=0;
+ virtual void canvas_item_add_set_transform(RID p_item,const Transform2D& p_transform)=0;
virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore)=0;
virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable)=0;
virtual void canvas_item_set_z(RID p_item, int p_z)=0;
@@ -1039,7 +813,7 @@ public:
virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable,const Rect2& p_rect)=0;
virtual void canvas_item_clear(RID p_item)=0;
- virtual void canvas_item_raise(RID p_item)=0;
+ virtual void canvas_item_set_draw_index(RID p_item,int p_index)=0;
virtual void canvas_item_set_material(RID p_item, RID p_material)=0;
@@ -1049,7 +823,7 @@ public:
virtual void canvas_light_attach_to_canvas(RID p_light,RID p_canvas)=0;
virtual void canvas_light_set_enabled(RID p_light, bool p_enabled)=0;
virtual void canvas_light_set_scale(RID p_light, float p_scale)=0;
- virtual void canvas_light_set_transform(RID p_light, const Matrix32& p_transform)=0;
+ virtual void canvas_light_set_transform(RID p_light, const Transform2D& p_transform)=0;
virtual void canvas_light_set_texture(RID p_light, RID p_texture)=0;
virtual void canvas_light_set_texture_offset(RID p_light, const Vector2& p_offset)=0;
virtual void canvas_light_set_color(RID p_light, const Color& p_color)=0;
@@ -1057,8 +831,8 @@ public:
virtual void canvas_light_set_energy(RID p_light, float p_energy)=0;
virtual void canvas_light_set_z_range(RID p_light, int p_min_z,int p_max_z)=0;
virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer,int p_max_layer)=0;
- virtual void canvas_light_set_item_mask(RID p_light, int p_mask)=0;
- virtual void canvas_light_set_item_shadow_mask(RID p_light, int p_mask)=0;
+ virtual void canvas_light_set_item_cull_mask(RID p_light, int p_mask)=0;
+ virtual void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask)=0;
enum CanvasLightMode {
CANVAS_LIGHT_MODE_ADD,
@@ -1068,9 +842,20 @@ public:
};
virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode)=0;
+
+
+ enum CanvasLightShadowFilter {
+ CANVAS_LIGHT_FILTER_NONE,
+ CANVAS_LIGHT_FILTER_PCF3,
+ CANVAS_LIGHT_FILTER_PCF5,
+ CANVAS_LIGHT_FILTER_PCF9,
+ CANVAS_LIGHT_FILTER_PCF13,
+ };
+
virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled)=0;
virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size)=0;
- virtual void canvas_light_set_shadow_esm_multiplier(RID p_light, float p_multiplier)=0;
+ virtual void canvas_light_set_shadow_gradient_length(RID p_light, float p_length)=0;
+ virtual void canvas_light_set_shadow_filter(RID p_light, CanvasLightShadowFilter p_filter)=0;
virtual void canvas_light_set_shadow_color(RID p_light, const Color& p_color)=0;
@@ -1079,12 +864,13 @@ public:
virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder,RID p_canvas)=0;
virtual void canvas_light_occluder_set_enabled(RID p_occluder,bool p_enabled)=0;
virtual void canvas_light_occluder_set_polygon(RID p_occluder,RID p_polygon)=0;
- virtual void canvas_light_occluder_set_transform(RID p_occluder,const Matrix32& p_xform)=0;
+ virtual void canvas_light_occluder_set_transform(RID p_occluder,const Transform2D& p_xform)=0;
virtual void canvas_light_occluder_set_light_mask(RID p_occluder,int p_mask)=0;
virtual RID canvas_occluder_polygon_create()=0;
- virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const DVector<Vector2>& p_shape,bool p_closed)=0;
- virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const DVector<Vector2>& p_shape)=0;
+ virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape,bool p_closed)=0;
+ virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon,const PoolVector<Vector2>& p_shape)=0;
+
enum CanvasOccluderPolygonCullMode {
CANVAS_OCCLUDER_POLYGON_CULL_DISABLED,
CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE,
@@ -1092,21 +878,6 @@ public:
};
virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon,CanvasOccluderPolygonCullMode p_mode)=0;
- /* CANVAS ITEM MATERIAL */
-
- virtual RID canvas_item_material_create()=0;
- virtual void canvas_item_material_set_shader(RID p_material, RID p_shader)=0;
- virtual void canvas_item_material_set_shader_param(RID p_material, const StringName& p_param, const Variant& p_value)=0;
- virtual Variant canvas_item_material_get_shader_param(RID p_material, const StringName& p_param) const=0;
-
-
- enum CanvasItemShadingMode {
- CANVAS_ITEM_SHADING_NORMAL,
- CANVAS_ITEM_SHADING_UNSHADED,
- CANVAS_ITEM_SHADING_ONLY_LIGHT,
- };
-
- virtual void canvas_item_material_set_shading_mode(RID p_material, CanvasItemShadingMode p_mode)=0;
/* CURSOR */
virtual void cursor_set_rotation(float p_rotation, int p_cursor = 0)=0; // radians
@@ -1125,15 +896,6 @@ public:
virtual void free( RID p_rid )=0; ///< free RIDs associated with the visual server
- /* CUSTOM SHADING */
-
- virtual void custom_shade_model_set_shader(int p_model, RID p_shader)=0;
- virtual RID custom_shade_model_get_shader(int p_model) const=0;
- virtual void custom_shade_model_set_name(int p_model, const String& p_name)=0;
- virtual String custom_shade_model_get_name(int p_model) const=0;
- virtual void custom_shade_model_set_param_info(int p_model, const List<PropertyInfo>& p_info)=0;
- virtual void custom_shade_model_get_param_info(int p_model, List<PropertyInfo>* p_info) const=0;
-
/* EVENT QUEUING */
virtual void draw()=0;
@@ -1166,7 +928,6 @@ public:
RID material_2d_get(bool p_shaded, bool p_transparent, bool p_cut_alpha,bool p_opaque_prepass);
-
/* TESTING */
virtual RID get_test_cube()=0;
@@ -1177,7 +938,7 @@ public:
virtual RID make_sphere_mesh(int p_lats,int p_lons,float p_radius);
virtual void mesh_add_surface_from_mesh_data( RID p_mesh, const Geometry::MeshData& p_mesh_data);
- virtual void mesh_add_surface_from_planes( RID p_mesh, const DVector<Plane>& p_planes);
+ virtual void mesh_add_surface_from_planes( RID p_mesh, const PoolVector<Plane>& p_planes);
virtual void set_boot_image(const Image& p_image, const Color& p_color,bool p_scale)=0;
virtual void set_default_clear_color(const Color& p_color)=0;
@@ -1185,11 +946,12 @@ public:
enum Features {
FEATURE_SHADERS,
FEATURE_MULTITHREADED,
- FEATURE_NEEDS_RELOAD_HOOK,
};
virtual bool has_feature(Features p_feature) const=0;
+ virtual bool has_os_feature(const String& p_feature) const=0;
+
VisualServer();
virtual ~VisualServer();
@@ -1200,19 +962,15 @@ public:
VARIANT_ENUM_CAST( VisualServer::CubeMapSide );
VARIANT_ENUM_CAST( VisualServer::TextureFlags );
VARIANT_ENUM_CAST( VisualServer::ShaderMode );
-VARIANT_ENUM_CAST( VisualServer::MaterialFlag );
-VARIANT_ENUM_CAST( VisualServer::MaterialBlendMode );
-VARIANT_ENUM_CAST( VisualServer::ParticleVariable );
VARIANT_ENUM_CAST( VisualServer::ArrayType );
VARIANT_ENUM_CAST( VisualServer::ArrayFormat );
VARIANT_ENUM_CAST( VisualServer::PrimitiveType );
VARIANT_ENUM_CAST( VisualServer::LightType );
-VARIANT_ENUM_CAST( VisualServer::LightColor );
VARIANT_ENUM_CAST( VisualServer::LightParam );
VARIANT_ENUM_CAST( VisualServer::ScenarioDebugMode );
VARIANT_ENUM_CAST( VisualServer::InstanceType );
VARIANT_ENUM_CAST( VisualServer::RenderInfo );
-VARIANT_ENUM_CAST( VisualServer::MipMapPolicy );
+
//typedef VisualServer VS; // makes it easier to use
#define VS VisualServer